예제 #1
0
        public static void BuildQuestRewards(PacketOut Out, Player plr, Quest q)
        {
            Dictionary <Item_Info, uint> choices = GenerateRewards(q, plr);

            Out.WriteByte(Math.Min(q.ChoiceCount, (byte)choices.Count));
            Out.WriteByte(0);
            Out.WriteByte((byte)choices.Count);

            foreach (KeyValuePair <Item_Info, uint> kp in choices)
            {
                Item.BuildItem(ref Out, null, kp.Key, null, 0, (ushort)kp.Value);
            }
        }
예제 #2
0
        public void SendPlotInfo()
        {
            PacketOut Out = new PacketOut((byte)Opcodes.F_GET_CULTIVATION_INFO);

            Out.WriteByte(_index);
            Out.WriteByte((byte)_ownerInterface.GetPlotCount());
            Out.WriteByte(_stage);
            Out.WriteByte(0);
            Out.WriteUInt32(_currentStageTime);
            Out.WriteUInt32((uint)(_stage3Time + _stage2Time + _currentStageTime));

            if (_seedItemID == 0)
            {
                Out.WriteByte(0);
            }
            else
            {
                Item.BuildItem(ref Out, null, ItemService.GetItem_Info(_seedItemID), null, 0, 0);
            }

            if (_soilItemID == 0)
            {
                Out.Fill(0, 5);
            }
            else
            {
                Item.BuildItem(ref Out, null, ItemService.GetItem_Info(_soilItemID), null, 0, 0);
            }

            if (_waterItemID == 0)
            {
                Out.Fill(0, 5);
            }
            else
            {
                Item.BuildItem(ref Out, null, ItemService.GetItem_Info(_waterItemID), null, 0, 0);
            }

            if (_nutrientItemID == 0)
            {
                Out.Fill(0, 5);
            }
            else
            {
                Item.BuildItem(ref Out, null, ItemService.GetItem_Info(_nutrientItemID), null, 0, 0);
            }

            Out.Fill(0, 7);

            _ownerInterface.GetPlayer().SendPacket(Out);
        }
예제 #3
0
        public void SendQuest(Character_quest cQuest)
        {
            if (cQuest == null)
            {
                Log.Error("QuestsInterface", "SendQuest CQuest == null");
                return;
            }

            PacketOut packet = new PacketOut((byte)Opcodes.F_QUEST_INFO);

            packet.WriteUInt16(cQuest.QuestID);
            packet.WriteByte(cQuest.Quest.Type); // Quest Type (database is wrong)
            BuildQuestHeader(packet, GetPlayer(), cQuest.Quest, true);

            Dictionary <Item_Info, uint> rewards = GenerateRewards(cQuest.Quest, GetPlayer());

            packet.WriteByte(cQuest.Quest.ChoiceCount);
            packet.WriteByte(0);
            packet.WriteByte((byte)rewards.Count);

            foreach (KeyValuePair <Item_Info, uint> kp in rewards)
            {
                Item.BuildItem(ref packet, null, kp.Key, null, 0, (ushort)kp.Value);
            }

            packet.WriteByte(0);

            BuildObjectives(packet, cQuest._Objectives);

            List <Quest_Map> SortedMaps = cQuest.Quest.Maps.OrderBy(x => x.Entry).ThenByDescending(x => x.Id).ToList();

            foreach (Quest_Map map in SortedMaps)
            {
                packet.WriteByte(map.Id);
                packet.WritePascalString(map.Name);
                packet.WritePascalString(map.Description);
                packet.WriteUInt16(map.ZoneId);
                packet.WriteUInt16(map.Icon);
                packet.WriteUInt16(map.X);
                packet.WriteUInt16(map.Y);
                packet.WriteUInt16(map.Unk);
                packet.WriteByte(map.When);
            }

            packet.WriteByte(0);

            GetPlayer().SendPacket(packet);
        }
예제 #4
0
        private void ClientUpdateLoot(Player player)
        {
            PacketOut Out = new PacketOut((byte)Opcodes.F_INTERACT_RESPONSE, 32);

            Out.WriteByte(4);
            Out.WriteByte((byte)LootCount);
            for (byte i = 0; i < LootInfo.Count; ++i)
            {
                if (LootInfo[i] == null)
                {
                    continue;
                }

                Out.WriteByte(i);
                Item.BuildItem(ref Out, null, LootInfo[i].Item, null, 0, 1);
            }
            player.SendPacket(Out);
        }
예제 #5
0
        public void AssignItemCooldown(Item item)
        {
            long curCooldownMS;

            if (item.Info.Unk27[19] != 0)
            {
                ItemGroupCooldowns.TryGetValue(item.Info.Unk27[19], out curCooldownMS);
            }
            else
            {
                Cooldowns.TryGetValue(item.Info.SpellId, out curCooldownMS);
            }

            if (curCooldownMS == 0)
            {
                return;
            }

            item.CharSaveInfo.NextAllowedUseTime = curCooldownMS / 1000;
        }
예제 #6
0
        public void SendMail(Character receiver, string subject, string message, uint money, bool cashOnDelivery, List <ushort> itemSlots = null)
        {
            Player sender = (Player)_Owner;

            Character_mail cMail = new Character_mail
            {
                Guid              = CharMgr.GenerateMailGuid(),
                CharacterId       = receiver.CharacterId,
                CharacterIdSender = sender.CharacterId,
                SenderName        = sender.Info.Name,
                ReceiverName      = receiver.Name,
                SendDate          = (uint)TCPManager.GetTimeStamp(),
                Title             = subject,
                Content           = message,
                Money             = money,
                Cr     = cashOnDelivery,
                Opened = false
            };

            if (itemSlots != null)
            {
                foreach (ushort itmslot in itemSlots)
                {
                    Item itm = sender.ItmInterface.GetItemInSlot(itmslot);
                    // This should never happen, double check.
                    if (itm != null && itm.Info != null)
                    {
                        cMail.Items.Add(new MailItem(itm.Info.Entry, itm.GetTalismans(), itm.GetPrimaryDye(), itm.GetSecondaryDye(), itm.Count));
                        sender.ItmInterface.DeleteItem(itmslot, itm.Count);
                        itm.Owner = null;
                    }
                }
            }

            SendResult(MailResult.TEXT_MAIL_RESULT4);

            CharMgr.AddMail(cMail);

            _nextSend = (uint)TCPManager.GetTimeStamp() + 5;
        }
예제 #7
0
        public void SendMail(Character_mail mail)
        {
            if (mail == null)
            {
                Log.Error("MailInterface", "Attempted to send NULL mail!");
                return;
            }


            if (mail.Content == null)
            {
                Log.Error("MailInterface", "Mail sent with NULL content!");
                return;
            }

            PacketOut Out = new PacketOut((byte)Opcodes.F_MAIL);

            Out.WriteByte(0x0D);

            if (mail.AuctionType == 0)
            {
                Out.WriteByte(0);
            }
            else
            {
                Out.WriteByte(1);
            }

            BuildPreMail(Out, mail);

            if (mail.AuctionType == 0)
            {
                Out.WriteUInt16((ushort)(mail.Content.Length + 1));
                Out.WriteStringBytes(mail.Content);
                Out.WriteByte(0);
            }
            else
            {
                ushort contentLocal = 0;
                if (mail.AuctionType == 1) // Refund (outbid)
                {
                    contentLocal = (ushort)Localized_text.TEXT_AUCTION_MAIL_BODY_REFUND_ITEM_X;
                }
                else if (mail.AuctionType == 2) // Complete
                {
                    contentLocal = (ushort)Localized_text.TEXT_AUCTION_MAIL_BODY_COMPLETE_ITEM_X;
                }
                else if (mail.AuctionType == 3) // Cancelled
                {
                    contentLocal = (ushort)Localized_text.TEXT_AUCTION_MAIL_BODY_CANCELLED;
                }
                else if (mail.AuctionType == 4) // Expired
                {
                    contentLocal = (ushort)Localized_text.TEXT_AUCTION_MAIL_BODY_EXPIRED;
                }
                else if (mail.AuctionType == 5) // Won
                {
                    contentLocal = (ushort)Localized_text.TEXT_AUCTION_MAIL_BODY_WON_ITEM_X;
                }
                else
                {
                    contentLocal = (ushort)Localized_text.TEXT_AUCTION_MAIL_BODY_OTHER;
                }

                Out.WriteUInt16(0);
                Out.WriteUInt16(contentLocal);
                Out.WriteUInt16(0);
                Out.WriteByte(0);

                if (mail.Content.Length == 0)
                {
                    Out.WriteByte(0);
                }
                else
                {
                    Out.WriteByte(1);
                    Out.WriteByte(1);

                    Out.WriteByte(0);
                    Out.WritePascalString(mail.Content);
                }
            }

            Out.WriteByte((byte)mail.Items.Count);
            foreach (MailItem item in mail.Items)
            {
                Item.BuildItem(ref Out, null, null, item, 0, item.count);
            }
            GetPlayer().SendPacket(Out);
        }
예제 #8
0
        public void SendPacketMail(PacketIn packet)
        {
            Player plr = GetPlayer();

            if (plr == null)
            {
                return;
            }

            if (_nextSend >= TCPManager.GetTimeStamp())
            {
                SendResult(MailResult.TEXT_MAIL_RESULT6);
                return;
            }

            // Recipient read
            packet.Skip(1);
            byte   nameSize = packet.GetUint8();
            string name     = packet.GetString(nameSize);



            // Subject (client is limited to send 30 chars but its probably a ushort anyway)
            ushort subjectSize = ByteSwap.Swap(packet.GetUint16());
            string subject     = packet.GetString(subjectSize);

            // Message
            ushort messageSize = ByteSwap.Swap(packet.GetUint16());
            string message     = packet.GetString(messageSize);

            // Money
            uint money = ByteSwap.Swap(packet.GetUint32());

            // COD?
            byte cr = packet.GetUint8();

            // Item
            byte itemsToSendCount = packet.GetUint8();

            var isBlackMarket = ((name.ToLower() == "black market") || (name.ToLower() == "blackmarket"));

            List <ushort> itemSlots = new List <ushort>();
            var           itemList  = new List <Item>();

            for (byte i = 0; i < itemsToSendCount; ++i)
            {
                ushort itemSlot = ByteSwap.Swap(packet.GetUint16());
                packet.Skip(2);

                Item item = plr.ItmInterface.GetItemInSlot(itemSlot);
                if (item == null || item.Info == null)
                {
                    SendResult(MailResult.TEXT_MAIL_RESULT16);
                    return;
                }

                // Allow black market items to be sent in mail
                if (!isBlackMarket)
                {
                    if (item.BoundtoPlayer || item.Info.Bind == 1)
                    {
                        SendResult(MailResult.TEXT_MAIL_RESULT9);
                        return;
                    }
                }

                itemSlots.Add(itemSlot);
                itemList.Add(item);
            }

            if (isBlackMarket)
            {
                _logger.Debug($"Sending mail to the BLACK MARKET. Number items {itemsToSendCount}");

                // Ensure that what is being sent is a warlord item
                if (itemsToSendCount == 0)
                {
                    SendResult(MailResult.TEXT_MAIL_RESULT9);
                    return;
                }

                var blackMarketManager = new BlackMarketManager();

                // Sending multiple items.
                foreach (var item in itemList)
                {
                    if (blackMarketManager.IsItemOnBlackMarket(item.Info.Entry))
                    {
                        _logger.Info($"Sending {item.Info.Name} ({item.Info.Entry}) to BlackMarket");
                        blackMarketManager.SendBlackMarketReward(plr, item.Info.Entry);
                        plr.SendClientMessage($"Trusting to your luck, you have sent {string.Join(",", itemList.Select(x => x.Info.Name))} to the Black Market, hoping for just recompense.");
                        _logger.Debug($"Email Sent.");
                        plr.ItmInterface.RemoveItems(item.Info.Entry, 1);
                        _logger.Info($"Removed {item.Info.Name} ({item.Info.Entry}) from {plr.Name}");
                        plr.SendClientMessage($"A suspicious looking package has arrived in your mail.", ChatLogFilters.CHATLOGFILTERS_LOOT);
                    }
                    else
                    {
                        _logger.Debug($"{MailResult.TEXT_MAIL_RESULT9}");
                        return;
                    }
                }

                SendResult(MailResult.TEXT_MAIL_RESULT4);
            }
            else
            {
                Character receiver = CharMgr.GetCharacter(Player.AsCharacterName(name), false);

                if (receiver == null || receiver.Realm != (byte)plr.Realm)
                {
                    SendResult(MailResult.TEXT_MAIL_RESULT7);
                    return;
                }
                if (receiver.Name == plr.Name) // You cannot mail yourself
                {
                    plr.SendLocalizeString("", ChatLogFilters.CHATLOGFILTERS_USER_ERROR, Localized_text.TEXT_PLAYER_CANT_MAIL_YOURSELF);
                    return;
                }
                if ((cr == 0 && !plr.HasMoney(money)) || !plr.RemoveMoney((cr == 0 ? money : 0) + MAIL_PRICE))
                {
                    SendResult(MailResult.TEXT_MAIL_RESULT8);
                    return;
                }

                SendMail(receiver, subject, message, money, cr == 1, itemSlots);

                _logger.Info($"Sending mail {subject} to {receiver.Name} from {plr.Name}. Money={money}, Item Count={itemSlots.Count}");
                foreach (var itemSlot in itemSlots)
                {
                    _logger.Info($"Item : {itemSlot}");
                }
            }
        }
예제 #9
0
        public void AddComponentToPlot(byte index, ushort itemSlot)
        {
            if (index >= _plots.Count)
            {
                _myPlayer.SendLocalizeString(index.ToString(), ChatLogFilters.CHATLOGFILTERS_CRAFTING, Localized_text.TEXT_CULTIVATION_ILLEGAL_PLOT_NUM);
                return;
            }

            Item itm = _myPlayer.ItmInterface.GetItemInSlot(itemSlot);

            if (itm == null)
            {
                _myPlayer.SendClientMessage("No item was found in the requested inventory slot.", ChatLogFilters.CHATLOGFILTERS_CRAFTING);
                return;
            }

            if (itm.Info.Unk27[14] > _myPlayer._Value.GatheringSkillLevel)
            {
                _myPlayer.SendLocalizeString("", ChatLogFilters.CHATLOGFILTERS_USER_ERROR, Localized_text.TEXT_CULTIVATION_OBJECT_TOO_POWERFUL);
                return;
            }

            if (itm.Info.Unk27.Length == 0 || ((itm.Info.Unk27[15] == 1 || itm.Info.Unk27[15] == 5) && itm.Info.Craftresult.Split(';').Length < 2))
            {
                _myPlayer.SendLocalizeString("", ChatLogFilters.CHATLOGFILTERS_USER_ERROR, Localized_text.TEXT_CULTIVATION_BAD_SEED_DATA);
                return;
            }

            switch (itm.Info.Unk27[15])
            {
            case 5:
            case 1:
                if (_plots[index].AddSeed(itm.Info))
                {
                    _myPlayer.ItmInterface.DeleteItem(itemSlot, 1);
                }
                break;

            case 2:
                if (_plots[index].AddSoil(itm.Info))
                {
                    _myPlayer.ItmInterface.DeleteItem(itemSlot, 1);
                }
                break;

            case 3:
                if (_plots[index].AddWater(itm.Info))
                {
                    _myPlayer.ItmInterface.DeleteItem(itemSlot, 1);
                }
                break;

            case 4:
                if (_plots[index].AddNutrients(itm.Info))
                {
                    _myPlayer.ItmInterface.DeleteItem(itemSlot, 1);
                }
                break;
            }

            SendPlotInfo(index);
        }
예제 #10
0
        public static void F_USE_ITEM(BaseClient client, PacketIn packet)
        {
            GameClient cclient = client as GameClient;

            if (!cclient.IsPlaying())
            {
                return;
            }

            Player Plr = cclient.Plr;

            if (Plr.AbtInterface.IsOnGlobalCooldown())
            {
                return;
            }

            ushort slot = packet.GetUint16();

            Item item = Plr.ItmInterface.GetItemInSlot(slot);

            if (item == null || item._Count == 0)
            {
                return;
            }

            if (!item.CanBeUsedBy(Plr))
            {
                return;
            }

            if (item.Info.Entry == 1337)
            {
                Plr.SetLevel((byte)40);
                Plr.ItmInterface.DeleteItem(slot, 1);
            }

            // Honor rewards
            var honorReward = HonorService.HonorRewards.SingleOrDefault(x => x.ItemId == item.Info.Entry);

            if (honorReward != null)
            {
                if (Plr.Info.HonorRank < honorReward.HonorRank)
                {
                    Plr.SendClientMessage("You can no longer use this item, as you do not have a high enough Honor Rank.");
                    return;
                }
            }

            if ((item.Info.Entry == 208477) || (item.Info.Entry == 208474))
            {
                Plr.ItmInterface.CreateItem(208470, 6);
                Plr.ItmInterface.DeleteItem(slot, 1);
            }

            // Oil
            if (item.Info.Entry == 86203 || item.Info.Entry == 86207 || item.Info.Entry == 86211 || item.Info.Entry == 86215 || item.Info.Entry == 86219 || item.Info.Entry == 86223) // siege oil
            {
                BattleFrontKeep keep = Plr.Region.Campaign.GetClosestFriendlyKeep(Plr.WorldPosition, Plr.Realm);

                if (keep.Realm == Plr.Realm)
                {
                    keep.SpawnOil(Plr, slot);
                }
            }

            if (item.ModelId == 1566 || item.ModelId == 3850)  // currency conversion boxes
            {
                Plr.ItmInterface.OpenBox(slot, item);
            }

            #region Loot bags

            if (item.Info.Entry == 9980 || item.Info.Entry == 9940 || item.Info.Entry == 9941 || item.Info.Entry == 9942 || item.Info.Entry == 9943)  // lootbags
            {
                packet.Skip(5);
                byte mode = packet.GetUint8();

                if (mode == 0)
                {
                    Plr.ItmInterface.SendMysteryBag(slot);
                }
                else
                {
                    Plr.ItmInterface.GetItemfromMysterybag(slot, mode);
                }
            }

            #endregion

            // Banner hack for standards.
            if (item.ModelId >= 6188 && item.ModelId < 6194)
            {
                Plr.Standard(item.Info.SpellId, true);
            }

            if (item.Info.Crafts.Length > 0 && CraftingApoInterface.GetCraft(5, item.Info.Crafts) == 4 && (CraftingApoInterface.GetCraft(8, item.Info.Crafts) < 5 || CraftingApoInterface.GetCraft(8, item.Info.Crafts) == 18))
            {
                CultivationInterface.ReapResin(Plr, slot);
            }

            #region Dye
            if (item.Info.Type == 27)
            {
                Item dye = Plr.ItmInterface.GetItemInSlot(slot);
                if (dye == null)
                {
                    return;
                }

                byte prisek = packet.GetUint8();
                packet.Skip(4);
                byte Slot = packet.GetUint8();

                Item itemtodye = Plr.ItmInterface.GetItemInSlot(Slot);


                if (dye.Info.BaseColor1 == 0)
                {
                    Plr.ItmInterface.RemoveDye(itemtodye, prisek == 1, prisek == 2);
                }
                else
                {
                    if (prisek == 1)
                    {
                        Plr.ItmInterface.DyeItem(itemtodye, dye.Info.BaseColor1, 0);
                    }
                    else
                    {
                        Plr.ItmInterface.DyeItem(itemtodye, 0, dye.Info.BaseColor1);
                    }
                }
                Plr.ItmInterface.DeleteItem(slot, 1);
            }

            #endregion

            if (item.Info.SpellId == 0)
            {
                return;
            }

            var numberSiegeTypeBeforeCast = 0;
            var numberSiegeTypeAfterCast  = 0;
            var siegeType = Siege.GetSiegeType(item.Info.Entry);

            if (item.Info.IsSiege)
            {
                if (siegeType == null)
                {
                    _logger.Warn($"Could not locate SiegeType for {item.Info.Entry}");
                    return;
                }

                if (item.Info.IsSiege)
                {
                    numberSiegeTypeBeforeCast = Plr.Region.Campaign.SiegeManager.GetNumberByType(siegeType.Value, Plr.Realm);
                }
            }

            #region Ability Cast

            if (!Plr.AbtInterface.CanCastCooldown(item.Info.SpellId))
            {
                Plr.SendLocalizeString("", ChatLogFilters.CHATLOGFILTERS_USER_ERROR, Localized_text.TEXT_ITEM_CANT_BE_USED_YET);
                return;
            }

            if (!Plr.AbtInterface.StartCast(Plr, item.Info.SpellId, 1, item.Info.Unk27?[19] ?? 0, item.Info.ObjectLevel))
            {
                return;
            }

            if (item.Info.MaxStack > 1)
            {
                Plr.ItmInterface.DeleteItem(slot, 1);
            }

            // Determine whether to remove the siege item from inventory.
            if (item.Info.IsSiege)
            {
                // If the siege exists, and the cast was not blocked or interrupted.
                numberSiegeTypeAfterCast = Plr.Region.Campaign.SiegeManager.GetNumberByType(siegeType.Value, Plr.Realm);

                if ((item.Owner as Player).CharacterId == Plr.CharacterId)
                {
                    if (item.Info.IsValid)
                    {
                        // If there is a Ram now, but there wasnt one before, remove it from inventory
                        if (numberSiegeTypeBeforeCast + 1 == numberSiegeTypeAfterCast)
                        {
                            Plr.ItmInterface.DeleteItem(slot, 1);
                        }
                    }
                }
            }

            WorldMgr.GeneralScripts.OnWorldPlayerEvent("USE_ITEM", Plr, item);

            #endregion
        }
예제 #11
0
        public static void F_INTERFACE_COMMAND(BaseClient client, PacketIn packet)
        {
            GameClient cclient = client as GameClient;

            Player Plr = cclient.Plr;

            if (Plr == null)
            {
                return;
            }

            byte CommandId = packet.GetUint8();

            switch (CommandId)
            {
            case 1:     // ????
            {
            } break;

            case 2:     // Resurrect Button
            {
                Plr.PreRespawnPlayer();
            } break;

            case 3:     // Buff remove
            {
                Plr.BuffInterface.RemoveBuffByID(packet.GetUint8());
            } break;

            case 4:     // Moral ability to slot
            {
                if (Plr.CbtInterface.IsInCombat)
                {
                    Plr.SendLocalizeString(ChatLogFilters.CHATLOGFILTERS_USER_ERROR, Localized_text.TEXT_PLAYER_CANT_CHANGE_MORALE_IN_COMBAT);
                    return;
                }

                byte   slotIndex    = packet.GetUint8();
                ushort abilityEntry = packet.GetUint16();

                Plr._Value.SetMorale(slotIndex, abilityEntry);
                CharMgr.Database.SaveObject(Plr._Value);

                Plr.SendMoraleAbilities();
            } break;

            case 7:     // Select title
            {
                CommandSelectTitle(cclient.Plr, packet);
            } break;

            case 10:     // Talisman Fuse
            {
                byte   command  = packet.GetUint8();
                byte   unk2     = packet.GetUint8();
                byte   slot     = packet.GetUint8();
                ushort itemslot = packet.GetUint16();
                byte   unk4     = packet.GetUint8();

                switch (command)
                {
                case 0:
                    Plr.ItmInterface.MoveSlot(itemslot, 255, 1);
                    break;

                case 1:

                    Item modifiedItem = Plr.ItmInterface.GetItemInSlot(255);
                    if (modifiedItem == null)
                    {
                        break;
                    }

                    List <uint> unfused = modifiedItem.AbortFuseTalisman();

                    foreach (uint entry in unfused)
                    {
                        Plr.ItmInterface.CreateItem(entry, 1);
                    }

                    Plr.ItmInterface.MoveSlot(255, Plr.ItmInterface.GetFreeInventorySlot(Plr.ItmInterface.GetItemInSlot(255).Info, true), 1);
                    break;

                case 2:                    // add Talis
                    if (Plr.ItmInterface.GetItemInSlot(255) != null && Plr.ItmInterface.GetItemInSlot(255).AddTalisman(Plr.ItmInterface.GetItemInSlot(itemslot).Info.Entry, slot))
                    {
                        Plr.ItmInterface.DeleteItem(itemslot, 1);
                        Plr.ItmInterface.SendItemInSlot(Plr, 255);
                    }
                    break;

                case 3:                  //  remove talis
                    Plr.ItmInterface.CreateItem(Plr.ItmInterface.GetItemInSlot(255).RemoveTalisman(slot), 1);
                    Plr.ItmInterface.SendItemInSlot(Plr, 255);
                    break;

                case 4:                   // fuse
                    Plr.ItmInterface.GetItemInSlot(255).FuseTalisman();
                    Plr.ItmInterface.MoveSlot(255, Plr.ItmInterface.GetFreeInventorySlot(Plr.ItmInterface.GetItemInSlot(255).Info, true), 1);
                    break;
                }
            } break;

            case 12:     // cultivation
            {
                if (Plr.CultivInterface == null)
                {
                    Plr.SendClientMessage("You don't have the Cultivating skill.", ChatLogFilters.CHATLOGFILTERS_CRAFTING);
                    return;
                }

                byte command = packet.GetUint8();
                //Log.Info("command", "" + command);   // 0 plant seed soul   3 uproot 4 client request
                byte   unk2      = packet.GetUint8();
                byte   plotIndex = packet.GetUint8();
                ushort itemSlot  = packet.GetUint16();

                switch (command)
                {
                case 0:
                    Plr.CultivInterface.AddComponentToPlot(plotIndex, itemSlot);
                    break;

                case 1:
                    Plr.CultivInterface.Harvest(plotIndex);
                    break;

                case 3:
                    Plr.CultivInterface.Uproot(plotIndex);
                    break;

                case 4:
                    Plr.CultivInterface.SendPlotInfo(plotIndex);
                    break;
                }
            } break;

            case 13:     // Resurrection handler
            {
                Plr.BuffInterface.NotifyCombatEvent((byte)BuffCombatEvents.OnAcceptResurrection, null, packet.GetUint8() > 0 ? Plr : null);
            } break;

            case 14:     // apotekari
            {
                byte command = packet.GetUint8();
                //Log.Info("command", "" + command);   // 0 plant seed soul   3 uproot 4 client request
                byte   unk2     = packet.GetUint8();
                byte   pot      = packet.GetUint8();
                ushort itemslot = packet.GetUint16();
                //Log.Info("Pot", "" + pot);
                //Log.Info("itemslot", "" + itemslot);
                //Log.Info("unk2", "" + packet.GetUint8());

                if (Plr._Value.CraftingSkill == 4)
                {
                    switch (command)
                    {
                    case 1: Plr.CraftApoInterface.AddContainer(itemslot); break;

                    case 2: Plr.CraftApoInterface.AddContainer(itemslot); break;

                    case 3: Plr.CraftApoInterface.RemoveContainer(itemslot); break;

                    case 4: Plr.CraftApoInterface.Craft(); break;

                    case 5: Plr.CraftApoInterface.Reset(0); break;
                    }
                }
                if (Plr._Value.CraftingSkill == 5)
                {
                    switch (command)
                    {
                    case 1: Plr.CraftTalInterface.AddContainer(itemslot); break;

                    case 2: Plr.CraftTalInterface.AddContainer(itemslot); break;

                    case 3: Plr.CraftTalInterface.RemoveContainer(itemslot); break;

                    case 4: Plr.CraftTalInterface.Craft(); break;

                    case 5: Plr.CraftTalInterface.Reset(); break;
                    }
                }
            } break;

            case 28:     // Leave scenario
            {
                Plr.ScnInterface.Scenario?.EnqueueScenarioAction(new ScenarioQueueAction(EScenarioQueueAction.RemovePlayer, Plr));
            }
            break;
            }
        }