示例#1
0
        public override void Handle(GameSession session, PacketReader packet)
        {
            byte function = packet.ReadByte();

            switch (function)
            {
            case 0:     // Cancel
                return;

            case 1:
                int objectId = packet.ReadInt();
                if (!session.FieldManager.State.Npcs.TryGetValue(objectId, out IFieldObject <Npc> npc))
                {
                    return;     // Invalid NPC
                }
                // Stellar Chest: 11004215
                session.Send(NpcTalkPacket.Respond(npc, 0));
                break;

            case 2:                           // Continue chat?
                int index = packet.ReadInt(); // selection index
                session.Send(NpcTalkPacket.Close());
                break;
            }
        }
示例#2
0
    private static void HandleBeauty(GameSession session)
    {
        MapPortal portal = MapEntityStorage.GetPortals(session.Player.MapId).FirstOrDefault(portal => portal.Id == 99); // unsure how the portalId is determined

        if (portal is null)
        {
            return;
        }

        session.Send(NpcTalkPacket.Action(ActionType.Portal, "", "", portal.Id));
        NpcMetadata npcTarget = NpcMetadataStorage.GetNpcMetadata(session.Player.NpcTalk.Npc.Id);

        session.Player.ShopId = npcTarget.ShopId;

        switch (npcTarget.ShopId)
        {
        case 500:                                                                                  // Dr Dixon
            session.Send(NpcTalkPacket.Action(ActionType.OpenWindow, "BeautyShopDialog", "face")); // unsure how these strings are determined
            break;

        case 501:     // Dr Zenko
            session.Send(NpcTalkPacket.Action(ActionType.OpenWindow, "BeautyShopDialog", "skin"));
            break;

        case 504:     // Rosetta
        case 509:     //Lolly
            session.Send(NpcTalkPacket.Action(ActionType.OpenWindow, "BeautyShopDialog", "hair,style"));
            break;

        case 505:     // Ren
            session.Send(NpcTalkPacket.Action(ActionType.OpenWindow, "BeautyShopDialog", "makeup"));
            break;

        case 506:     // Douglas
            session.Send(NpcTalkPacket.Action(ActionType.OpenWindow, "BeautyShopDialog", "itemcolor"));
            break;

        case 507:     // Mirror
            session.Send(NpcTalkPacket.Action(ActionType.OpenWindow, "BeautyShopDialog", "mirror"));
            break;

        case 508:     // Paulie
            session.Send(NpcTalkPacket.Action(ActionType.OpenWindow, "BeautyShopDialog", "hair,random"));
            break;

        case 510:     // Mino
            session.Send(NpcTalkPacket.Action(ActionType.OpenWindow, "BeautyShopDialog", "hair,styleSave"));
            break;
        }

        session.Send(UserMoveByPortalPacket.Move(session.Player.FieldPlayer, portal.Coord.ToFloat(), portal.Rotation.ToFloat()));
    }
示例#3
0
    public static void HandleNpcTalkEventType(GameSession session, NpcScript npcScript, int eventId)
    {
        ScriptEvent scriptEvent = npcScript.Contents.First().Events.FirstOrDefault(x => x.Id == eventId);

        if (scriptEvent is null)
        {
            return;
        }

        int          indexContent  = Random.Shared.Next(scriptEvent.Contents.Count);
        EventContent eventContents = scriptEvent.Contents[indexContent];

        session.Send(NpcTalkPacket.CustomText(eventContents.Text, eventContents.VoiceId, eventContents.Illustration));
    }
示例#4
0
        public static void HandleOpen(GameSession session, IFieldObject <Npc> npcFieldObject)
        {
            NpcMetadata metadata = NpcMetadataStorage.GetNpc(npcFieldObject.Value.Id);

            ShopMetadata shop = ShopMetadataStorage.GetShop(metadata.ShopId);

            if (shop == null)
            {
                Console.WriteLine($"Unknown shop ID: {metadata.ShopId}");
                return;
            }

            session.Send(ShopPacket.Open(shop));
            session.Send(ShopPacket.LoadProducts(shop.Items));
            session.Send(ShopPacket.Reload());
            session.Send(NpcTalkPacket.Respond(npcFieldObject, NpcType.Default, DialogType.None, 0));
        }
示例#5
0
    public static void HandleOpen(GameSession session, IFieldObject <NpcMetadata> npcFieldObject)
    {
        NpcMetadata metadata = npcFieldObject.Value;

        Shop shop = DatabaseManager.Shops.FindById(metadata.ShopId);

        if (shop == null)
        {
            Logger.Warn($"Unknown shop ID: {metadata.ShopId}");
            return;
        }

        session.Send(ShopPacket.Open(shop));
        foreach (ShopItem shopItem in shop.Items)
        {
            session.Send(ShopPacket.LoadProducts(shopItem));
        }
        session.Send(ShopPacket.Reload());
        session.Send(NpcTalkPacket.Respond(npcFieldObject, NpcType.Default, DialogType.None, 0));
        session.Player.ShopId = shop.Id;
    }
示例#6
0
        public override void Handle(GameSession session, PacketReader packet)
        {
            byte function = packet.ReadByte();

            switch (function)
            {
            case 0:     // Cancel
                return;

            case 1:
                int objectId = packet.ReadInt();
                if (!session.FieldManager.State.Npcs.TryGetValue(objectId, out IFieldObject <Npc> npc))
                {
                    return;     // Invalid NPC
                }
                // If NPC is a shop, load and open the shop
                if (npc.Value.IsShop())
                {
                    ShopHandler.HandleOpen(session, npc);
                    return;
                }
                else if (npc.Value.IsBank())
                {
                    session.Send(HomeBank.OpenBank());
                    return;
                }
                // Stellar Chest: 11004215
                session.Send(NpcTalkPacket.Respond(npc, NpcType.Unk2, DialogType.TalkOption, 0));
                break;

            case 2:                           // Continue chat?
                int index = packet.ReadInt(); // selection index
                session.Send(NpcTalkPacket.Close());
                break;
            }
        }
示例#7
0
        private static void HandleRespond(GameSession session, PacketReader packet)
        {
            List <QuestStatus> npcQuests = new List <QuestStatus>();
            int objectId = packet.ReadInt();

            if (!session.FieldManager.State.Npcs.TryGetValue(objectId, out IFieldObject <Npc> npc))
            {
                return; // Invalid NPC
            }
            foreach (QuestStatus item in session.Player.QuestList.Where(x => !x.Completed))
            {
                if (npc.Value.Id == item.StartNpcId)
                {
                    npcQuests.Add(item);
                }
                if (item.Started && npc.Value.Id == item.CompleteNpcId && !npcQuests.Contains(item))
                {
                    npcQuests.Add(item);
                }
            }
            session.Player.NpcTalk = new NpcTalk(npc.Value, npcQuests);
            // If NPC is a shop, load and open the shop
            if (npc.Value.IsShop())
            {
                ShopHandler.HandleOpen(session, npc);
                return;
            }
            else if (npc.Value.IsBank())
            {
                session.Send(HomeBank.OpenBank());
                return;
            }
            else if (npc.Value.IsBeauty())
            {
                session.Send(NpcTalkPacket.Respond(npc, NpcType.Default, DialogType.Beauty, 1));
                return;
            }

            QuestHelper.UpdateExplorationQuest(session, npc.Value.Id.ToString(), "talk_in");

            if (npcQuests.Count != 0)
            {
                session.Player.NpcTalk.ScriptId = 0;
                session.Send(QuestPacket.SendDialogQuest(objectId, npcQuests));
                session.Send(NpcTalkPacket.Respond(npc, NpcType.Unk2, DialogType.TalkOption, session.Player.NpcTalk.ScriptId));
            }
            else
            {
                ScriptMetadata scriptMetadata = ScriptMetadataStorage.GetNpcScriptMetadata(npc.Value.Id);
                int            firstScript    = scriptMetadata.Options.First(x => x.Type == ScriptType.Script).Id;
                session.Player.NpcTalk.ScriptId = firstScript;

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

                bool       hasNextScript = option.Goto.Count != 0;
                DialogType dialogType    = DialogType.CloseNext1;
                if (option.Goto.Count == 0)
                {
                    session.Player.NpcTalk.ContentIndex++;
                    dialogType = DialogType.CloseNext1;
                }

                if (!hasNextScript)
                {
                    dialogType = DialogType.Close1;
                }

                if (option.AmountContent > 1)
                {
                    dialogType = DialogType.CloseNext;
                }

                session.Send(NpcTalkPacket.Respond(npc, NpcType.Unk3, dialogType, firstScript));
            }
        }
示例#8
0
        private static void HandleContinue(GameSession session, PacketReader packet)
        {
            NpcTalk npcTalk = session.Player.NpcTalk;

            if (npcTalk.Npc.IsBeauty())
            {
                HandleBeauty(session);
                return;
            }

            int index = packet.ReadInt(); // selection index

            // index is quest
            if (index <= npcTalk.Quests.Count - 1 && npcTalk.ScriptId == 0)
            {
                npcTalk.QuestId = npcTalk.Quests[index].Basic.Id;
                npcTalk.IsQuest = true;
            }

            ScriptMetadata scriptMetadata = npcTalk.IsQuest ? ScriptMetadataStorage.GetQuestScriptMetadata(npcTalk.QuestId) : ScriptMetadataStorage.GetNpcScriptMetadata(npcTalk.Npc.Id);
            ResponseType   responseType   = npcTalk.IsQuest ? ResponseType.Quest : ResponseType.Dialog;

            if (npcTalk.ScriptId != 0)
            {
                Option option = scriptMetadata.Options.First(x => x.Id == npcTalk.ScriptId);
                if (option.AmountContent <= npcTalk.ContentIndex && option.Goto.Count == 0)
                {
                    session.Send(NpcTalkPacket.Close());
                    return;
                }
            }

            // Find next script id
            int    nextScript = GetNextScript(scriptMetadata, npcTalk, index);
            Option option2    = scriptMetadata.Options.FirstOrDefault(x => x.Id == npcTalk.ScriptId);

            if (option2?.AmountContent > 1 && option2?.AmountContent > npcTalk.ContentIndex)
            {
                nextScript = npcTalk.ScriptId;
            }

            if (npcTalk.ScriptId != nextScript)
            {
                npcTalk.ContentIndex = 1;
            }
            else
            {
                npcTalk.ContentIndex++;
            }

            Option option1       = scriptMetadata.Options.First(x => x.Id == nextScript);
            bool   hasNextScript = option1.Goto.Count != 0;

            if (option1.AmountContent > npcTalk.ContentIndex)
            {
                hasNextScript = true;
            }
            npcTalk.ScriptId = nextScript;

            DialogType dialogType = GetDialogType(scriptMetadata, npcTalk, hasNextScript);

            session.Send(NpcTalkPacket.ContinueChat(nextScript, responseType, dialogType, npcTalk.ContentIndex - 1, npcTalk.QuestId));
        }
示例#9
0
        private static void HandleRespond(GameSession session, PacketReader packet)
        {
            List <QuestStatus> npcQuests = new List <QuestStatus>();
            int objectId = packet.ReadInt();

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

            // Get all quests for this npc
            foreach (QuestStatus item in session.Player.QuestList.Where(x => !x.Completed))
            {
                if (npc.Value.Id == item.StartNpcId)
                {
                    npcQuests.Add(item);
                }
                if (item.Started && npc.Value.Id == item.CompleteNpcId && !npcQuests.Contains(item))
                {
                    npcQuests.Add(item);
                }
            }
            session.Player.NpcTalk = new NpcTalk(npc.Value, npcQuests);
            ScriptLoader scriptLoader = new ScriptLoader($"Npcs/{npc.Value.Id}", session);

            // If NPC is a shop, load and open the shop
            if (npc.Value.IsShop())
            {
                ShopHandler.HandleOpen(session, npc);
                return;
            }
            else if (npc.Value.IsBank())
            {
                session.Send(HomeBank.OpenBank());
                return;
            }
            else if (npc.Value.IsBeauty())
            {
                NpcMetadata npcTarget = NpcMetadataStorage.GetNpc(session.Player.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)
            {
                session.Player.NpcTalk.ScriptId = 0;
                session.Send(QuestPacket.SendDialogQuest(objectId, npcQuests));
                session.Send(NpcTalkPacket.Respond(npc, NpcType.Unk2, DialogType.TalkOption, session.Player.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);

            session.Player.NpcTalk.ScriptId = firstScriptId;

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

            DialogType dialogType = DialogType.None;

            if (option.Contents[0].Goto.Count == 0)
            {
                dialogType = DialogType.Close1;
            }
            else
            {
                dialogType = DialogType.CloseNextWithDistractor;
            }

            session.Send(NpcTalkPacket.Respond(npc, NpcType.Unk3, 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"));
            }
        }
示例#10
0
        private static void HandleContinue(GameSession session, int index)
        {
            NpcTalk npcTalk = session.Player.NpcTalk;

            if (npcTalk.Npc.IsBeauty())
            {
                HandleBeauty(session);
                return;
            }

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

            // index is quest
            if (index <= npcTalk.Quests.Count - 1 && npcTalk.ScriptId == 0)
            {
                npcTalk.QuestId = npcTalk.Quests[index].Basic.Id;
                npcTalk.IsQuest = true;
            }

            ScriptMetadata scriptMetadata = npcTalk.IsQuest ? ScriptMetadataStorage.GetQuestScriptMetadata(npcTalk.QuestId) : ScriptMetadataStorage.GetNpcScriptMetadata(npcTalk.Npc.Id);
            ResponseType   responseType   = npcTalk.IsQuest ? ResponseType.Quest : ResponseType.Dialog;

            if (npcTalk.ScriptId != 0)
            {
                Option option = scriptMetadata.Options.First(x => x.Id == npcTalk.ScriptId);

                // Find if player has quest condition for type "talk_in" and option id
                QuestHelper.UpdateQuest(session, npcTalk.Npc.Id.ToString(), "talk_in", option.Id.ToString());

                // If npc has no more options, close dialog
                if (option.Contents.Count <= npcTalk.ContentIndex + 1 && option.Contents[npcTalk.ContentIndex].Goto.Count == 0)
                {
                    session.Send(NpcTalkPacket.Close());
                    return;
                }
            }

            int nextScriptId = GetNextScript(scriptMetadata, npcTalk, index, scriptLoader);

            // If last script is different from next, reset content index, else increment content index
            if (npcTalk.ScriptId != nextScriptId)
            {
                npcTalk.ContentIndex = 0;
            }
            else
            {
                npcTalk.ContentIndex++;
            }

            Option nextScript    = scriptMetadata.Options.First(x => x.Id == nextScriptId);
            bool   hasNextScript = nextScript.Contents[npcTalk.ContentIndex].Goto.Count != 0;

            if (nextScript.Contents.Count > npcTalk.ContentIndex + 1)
            {
                hasNextScript = true;
            }
            npcTalk.ScriptId = nextScriptId;

            DialogType dialogType = GetDialogType(scriptMetadata, npcTalk, hasNextScript);

            session.Send(NpcTalkPacket.ContinueChat(nextScriptId, responseType, dialogType, npcTalk.ContentIndex, npcTalk.QuestId));
            // It appears if content has buttonset roulette, it's send again on every continue chat, unsure why since it doesn't break anything
        }
示例#11
0
    public void TalkFunction(GameSession session, int functionId, string function)
    {
        if (functionId == 0)
        {
            return;
        }

        List <ActionType> actions       = new();
        Script            npcScript     = ScriptLoader.GetScript($"Npcs/{Npc.Id}");
        DynValue          actionResults = npcScript?.RunFunction(function);

        if (actionResults == null)
        {
            return;
        }

        switch (actionResults.Type)
        {
        case DataType.Number:
            actions.Add((ActionType)actionResults.Number);
            break;

        case DataType.Tuple:
            foreach (DynValue value in actionResults.Tuple)
            {
                actions.Add((ActionType)value.Number);
            }

            break;

        default:
            return;
        }

        MapPortal portal = new();

        foreach (ActionType action in actions)
        {
            switch (action)
            {
            case ActionType.OpenWindow:
                DynValue windowResults = npcScript.RunFunction("actionWindow");
                session.Send(NpcTalkPacket.Action(ActionType.OpenWindow, windowResults.Tuple[0].String, windowResults.Tuple[1].String));
                break;

            case ActionType.Portal:
                DynValue portalResults = npcScript.RunFunction("actionPortal");
                portal = MapEntityMetadataStorage.GetPortals(session.Player.MapId).FirstOrDefault(portal => portal.Id == portalResults.Number);
                if (portal is null)
                {
                    return;
                }

                session.Send(NpcTalkPacket.Action(ActionType.Portal, "", "", portal.Id));
                break;

            case ActionType.ItemReward:
                DynValue itemResults = npcScript.RunFunction("actionItemReward");     // TODO: Support > 1 item
                Item     item        = new(id : (int)itemResults.Tuple[0].Number,
                                           amount : (int)itemResults.Tuple[2].Number,
                                           rarity : (int)itemResults.Tuple[1].Number);
                session.Player.Inventory.AddItem(session, item, true);
                session.Send(NpcTalkPacket.Action(action, "", "", 0, item));
                break;

            case ActionType.MoveMap:
                DynValue map = npcScript.RunFunction("actionMoveMap");

                int mapId    = (int)map.Tuple[0].Number;
                int portalId = (int)map.Tuple[1].Number;

                MapPortal portalDst = MapEntityMetadataStorage.GetPortals(mapId).FirstOrDefault(x => x.Id == portalId);
                if (portalDst is null)
                {
                    session.Player.Warp(mapId);
                    return;
                }

                session.Player.Warp(mapId, portalDst.Coord, portalDst.Rotation);
                break;
            }
        }

        // this needs to be sent after the UI window action
        if (actions.Contains(ActionType.Portal))
        {
            session.Player.Move(portal.Coord.ToFloat(), portal.Rotation.ToFloat());
        }
    }
示例#12
0
        public override void Handle(GameSession session, PacketReader packet)
        {
            byte function = packet.ReadByte();

            switch (function)
            {
            case 0:     // Cancel
                return;

            case 1:
                int objectId = packet.ReadInt();
                if (!session.FieldManager.State.Npcs.TryGetValue(objectId, out IFieldObject <Npc> npc))
                {
                    return;     // Invalid NPC
                }
                session.Player.NpcTalk = npc;
                // If NPC is a shop, load and open the shop
                if (npc.Value.IsShop())
                {
                    ShopHandler.HandleOpen(session, npc);
                    return;
                }
                else if (npc.Value.IsBank())
                {
                    session.Send(HomeBank.OpenBank());
                    return;
                }
                else if (npc.Value.IsBeauty())
                {
                    session.Send(NpcTalkPacket.Respond(npc, NpcType.Default, DialogType.Beauty, 1));
                    return;
                }
                // Stellar Chest: 11004215
                session.Send(NpcTalkPacket.Respond(npc, NpcType.Unk2, DialogType.TalkOption, 0));
                break;

            case 2:                                                                                                                 // Continue chat?
                int index = packet.ReadInt();                                                                                       // selection index

                if (session.Player.NpcTalk.Value.IsBeauty())                                                                        // This may need a cleaner method
                {
                    MapPortal portal = MapEntityStorage.GetPortals(session.Player.MapId).FirstOrDefault(portal => portal.Id == 99); // unsure how the portalId is determined
                    session.Send(NpcTalkPacket.Action(ActionType.Portal, "", "", portal.Id));
                    NpcMetadata npcTarget = NpcMetadataStorage.GetNpc(session.Player.NpcTalk.Value.Id);

                    switch (npcTarget.ShopId)
                    {
                    case 500:                                                                                  // Dr Dixon
                        session.Send(NpcTalkPacket.Action(ActionType.OpenWindow, "BeautyShopDialog", "face")); // unsure how these strings are determined
                        break;

                    case 501:         // Dr Zenko
                        session.Send(NpcTalkPacket.Action(ActionType.OpenWindow, "BeautyShopDialog", "skin"));
                        break;

                    case 504:         // Rosetta
                    case 509:         //Lolly
                        session.Send(NpcTalkPacket.Action(ActionType.OpenWindow, "BeautyShopDialog", "hair,style"));
                        break;

                    case 505:         // Ren
                        session.Send(NpcTalkPacket.Action(ActionType.OpenWindow, "BeautyShopDialog", "makeup"));
                        break;

                    case 506:         // Douglas
                        session.Send(NpcTalkPacket.Action(ActionType.OpenWindow, "BeautyShopDialog", "itemcolor"));
                        break;

                    case 507:         // Mirror
                        session.Send(NpcTalkPacket.Action(ActionType.OpenWindow, "BeautyShopDialog", "mirror"));
                        break;

                    case 508:         // Paulie
                        session.Send(NpcTalkPacket.Action(ActionType.OpenWindow, "BeautyShopDialog", "hair,random"));
                        break;

                    case 510:         // Mino
                        session.Send(NpcTalkPacket.Action(ActionType.OpenWindow, "BeautyShopDialog", "hair,styleSave"));
                        break;
                    }
                    session.Send(UserMoveByPortalPacket.Move(session, portal.Coord.ToFloat(), portal.Rotation.ToFloat()));
                }
                session.Send(NpcTalkPacket.Close());
                session.Player.NpcTalk = null;
                break;
            }
        }
示例#13
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");
        }
    }