private static void HandleRespond(GameSession session, PacketReader packet)
    {
        List <QuestStatus> npcQuests = new();
        int objectId = packet.ReadInt();

        // Find if npc object id exists in field manager
        if (!session.FieldManager.State.Npcs.TryGetValue(objectId, out IFieldActor <NpcMetadata> npc))
        {
            return;
        }

        // Get all quests for this npc
        foreach (QuestStatus item in session.Player.QuestData.Values.Where(x => x.State is not QuestState.Finished))
        {
            if (npc.Value.Id == item.StartNpcId)
            {
                npcQuests.Add(item);
            }

            if (item.State is QuestState.Started && npc.Value.Id == item.CompleteNpcId && !npcQuests.Contains(item))
            {
                npcQuests.Add(item);
            }
        }

        session.Player.NpcTalk = new(npc.Value, npcQuests);
        NpcTalk npcTalk = session.Player.NpcTalk;

        ScriptLoader scriptLoader = new($"Npcs/{npc.Value.Id}", session);

        // If NPC is a shop, load and open the shop
        if (npc.Value.IsShop())
        {
            ShopHandler.HandleOpen(session, npc);
            return;
        }

        if (npc.Value.IsBank())
        {
            session.Send(HomeBank.OpenBank());
            return;
        }

        if (npc.Value.IsBeauty())
        {
            NpcMetadata npcTarget = NpcMetadataStorage.GetNpcMetadata(npcTalk.Npc.Id);
            if (npcTarget.ShopId == 507) // mirror
            {
                session.Send(NpcTalkPacket.Respond(npc, NpcType.Default, DialogType.Beauty, 0));
                HandleBeauty(session);
                return;
            }

            session.Send(NpcTalkPacket.Respond(npc, NpcType.Default, DialogType.Beauty, 1));
            return;
        }

        // Check if npc has an exploration quest
        QuestHelper.UpdateExplorationQuest(session, npc.Value.Id.ToString(), "talk_in");

        // If npc has quests, send quests and talk option
        if (npcQuests.Count != 0)
        {
            // Check if npc has scripts available
            if (ScriptMetadataStorage.NpcHasScripts(npc.Value.Id))
            {
                npcTalk.ScriptId = 0;
                session.Send(QuestPacket.SendDialogQuest(objectId, npcQuests));
                session.Send(NpcTalkPacket.Respond(npc, NpcType.QuestOptions, DialogType.TalkOption, npcTalk.ScriptId));
                return;
            }

            // If npc has no scripts, send the quest script id
            npcTalk.IsQuest = true;
            npcTalk.QuestId = npcQuests.First().Id;

            ScriptMetadata questScript = ScriptMetadataStorage.GetQuestScriptMetadata(npcTalk.QuestId);
            npcTalk.ScriptId = GetNextScript(questScript, npcTalk, 0, scriptLoader, session.Player);

            session.Send(QuestPacket.SendDialogQuest(objectId, npcQuests));
            session.Send(NpcTalkPacket.Respond(npc, NpcType.Quest, DialogType.CloseNext, npcTalk.ScriptId));
            return;
        }

        ScriptMetadata scriptMetadata = ScriptMetadataStorage.GetNpcScriptMetadata(npc.Value.Id);

        if (!scriptMetadata.Options.Exists(x => x.Type == ScriptType.Script))
        {
            return;
        }

        int firstScriptId = GetFirstScriptId(scriptLoader, scriptMetadata);

        npcTalk.ScriptId = firstScriptId;

        Option option = scriptMetadata.Options.First(x => x.Id == firstScriptId);

        DialogType dialogType = option.Contents[0].Distractor is null ? DialogType.Close1 : DialogType.CloseNextWithDistractor;

        session.Send(NpcTalkPacket.Respond(npc, NpcType.NormalTalk, dialogType, firstScriptId));

        // If npc has buttonset roulette, send roulette id 13.
        // TODO: Send the correct roulette id
        if (scriptMetadata.Options.Any(x => x.ButtonSet == "roulette"))
        {
            session.Send(NpcTalkPacket.Action(ActionType.OpenWindow, "RouletteDialog", "13"));
        }
    }
Beispiel #2
0
    private static void HandleBegin(GameSession session, PacketReader packet)
    {
        int objectId = packet.ReadInt();
        List <QuestStatus> npcQuests = new();
        int contentIndex             = 0;

        // Find if npc object id exists in field manager
        if (!session.FieldManager.State.Npcs.TryGetValue(objectId, out Npc npc))
        {
            return;
        }

        // Get all quests for this npc
        foreach (QuestStatus item in session.Player.QuestData.Values.Where(x => x.State is not QuestState.Completed))
        {
            if (npc.Value.Id == item.StartNpcId)
            {
                npcQuests.Add(item);
            }

            if (item.State is QuestState.Started && npc.Value.Id == item.CompleteNpcId && !npcQuests.Contains(item))
            {
                npcQuests.Add(item);
            }
        }

        session.Player.NpcTalk = new(npc.Value, npcQuests);
        NpcTalk npcTalk = session.Player.NpcTalk;

        ScriptMetadata scriptMetadata = ScriptMetadataStorage.GetNpcScriptMetadata(npc.Value.Id);
        NpcKind        kind           = npc.Value.NpcMetadataBasic.Kind;

        // need to find script properly before continuing
        NpcScript npcScript = GetFirstScript(session, scriptMetadata, npcTalk, npcQuests);

        switch (kind)
        {
        // reputation NPCs only have UI Dialog Type even if they have quests to accept/accepted.
        case NpcKind.SkyLumiknightCommander:
        case NpcKind.SkyGreenHoodCommander:
        case NpcKind.SkyDarkWindCommander:
        case NpcKind.SkyMapleAllianceCommander:
        case NpcKind.SkyRoyalGuardCommander:
        case NpcKind.KritiasLumiknightCommander:
        case NpcKind.KritiasGreenHoodCommander:
        case NpcKind.KritiasMapleAllianceCommander:
        case NpcKind.Humanitas:
            npcTalk.DialogType = DialogType.UI;
            ShopHandler.HandleOpen(session, npc, npc.Value.Id);
            break;

        case NpcKind.BalmyShop:
        case NpcKind.FixedShop:
        case NpcKind.RotatingShop:
            ShopHandler.HandleOpen(session, npc, npc.Value.Id);
            break;

        case NpcKind.Storage:
        case NpcKind.BlackMarket:
        case NpcKind.Birthday:     // TODO: needs a special case? select if birthday. script if not
            npcTalk.DialogType = DialogType.UI;
            break;
        }

        npcTalk.ScriptId = npcScript?.Id ?? 0;
        ResponseSelection responseSelection = GetResponseSelection(kind, npcTalk.DialogType, contentIndex, npcScript);

        if (npcTalk.DialogType.HasFlag(DialogType.Quest))
        {
            session.Send(QuestPacket.SendDialogQuest(objectId, npcQuests));
        }

        QuestManager.OnTalkNpc(session.Player, npc.Value.Id, npcTalk.ScriptId);
        session.Send(NpcTalkPacket.Respond(npc, npcTalk.DialogType, contentIndex, responseSelection, npcTalk.ScriptId));

        if (npcScript != null)
        {
            npcTalk.TalkFunction(session, npcScript.Contents[npcTalk.ContentIndex].FunctionId, "preTalkActions");
        }
    }