/// <title>Saga.AddStep</title>
 /// <code>
 /// Saga.AddStep(cid, QuestID, StepId, State);
 /// </code>
 /// <description>
 /// Adds a step to the quest. This can only be done during initialisation.
 /// 0 = Hidden, 1 = Visible, 2 = Completed
 /// </description>
 /// <example>
 ///function QUEST_START(cid)
 ///     -- Initialize all quest steps
 ///     -- Initialize all starting navigation points
 ///
 ///     Saga.AddStep(cid, QuestID, 101, 1);
 ///     Saga.AddStep(cid, QuestID, 102, 0);
 ///     Saga.AddStep(cid, QuestID, 103, 0);
 ///	    Saga.InsertQuest(cid, QuestID, 1);
 ///
 ///     return 0;
 ///end
 /// </example>
 public static bool NpcTakeItem(uint CID, uint ItemId, int ItemCount)
 {
     Character Character;
     if (LifeCycle.TryGetById(CID, out Character))
     {
         foreach (KeyValuePair<byte, Rag2Item> pair in Character.container.GetAllItems())
         {
             if (pair.Value.info.item != ItemId || pair.Value.count < ItemCount) continue;
             int newCount = pair.Value.count -= ItemCount;
             if (newCount > 0)
             {
                 SMSG_ITEMADJUST spkt = new SMSG_ITEMADJUST();
                 spkt.Container = 2;
                 spkt.Function = 4;
                 spkt.Slot = pair.Key;
                 spkt.UpdateReason = (byte)ItemUpdateReason.GiveToNpc;
                 spkt.Value = (byte)pair.Value.count;
                 spkt.SessionId = Character.id;
                 Character.client.Send((byte[])spkt);
             }
             else
             {
                 Character.container.RemoveAt(pair.Key);
                 SMSG_DELETEITEM spkt = new SMSG_DELETEITEM();
                 spkt.Container = 2;
                 spkt.Index = pair.Key;
                 spkt.UpdateReason = (byte)ItemUpdateReason.GiveToNpc;
                 spkt.SessionId = Character.id;
                 Character.client.Send((byte[])spkt);
             }
             return true;
         }
     }
     return false;
 }
        /// <title>Saga.NpcTakeItem</title>
        /// <code>
        /// Saga.NpcTakeItem(cid, QuestID, ItemId, Count);
        /// </code>
        /// <description>
        /// Takes a npc item as with a message that the npc took it.
        /// </description>
        /// <example>
        public static int TakeItem(uint cid, uint itemid, byte count)
        {
            Character value;
            if (LifeCycle.TryGetById(cid, out value))
            {

                //HELPER VARIABLES
                DEFAULT_FACTORY_ITEMS.ItemInfo info;
                Singleton.Item.TryGetItem(itemid, out info);
                //int stackcount = 0;

                Predicate<Rag2Item> callback = delegate(Rag2Item item)
                {
                    bool result = item.info.item == itemid;
                    //if (result) stackcount += item.info.max_stack - item.count;
                    return result;
                };

                //CHECK IF RIGHT AMOUNT OF ITEMS WAS FOUND
                List<int> FoundItems = value.ITEMS.FindAll(callback);
                //if (count > stackcount) return -1;

                //DO THE ACTUAL TAKING
                int acount = count;
                foreach (int currentInxdex in FoundItems)
                {
                    Stackable<Rag2Item> item = value.ITEMS[currentInxdex];
                    int MinCount = Math.Min(acount, Math.Min(item.Count, info.max_stack));
                    acount -= MinCount;

                    if ((item.Count -= MinCount) == 0)
                    {
                        value.ITEMS.RemoveAt(currentInxdex);
                        SMSG_DELETEITEM spkt = new SMSG_DELETEITEM();
                        spkt.Container = 2;
                        spkt.Index = (byte)currentInxdex;
                        spkt.UpdateReason = (byte)ITEMUPDATEREASON.GIVE_TO_NPC;
                        spkt.SessionId = value.id;
                        value.client.Send((byte[])spkt);
                    }
                    else
                    {
                        SMSG_UPDATEITEM spkt = new SMSG_UPDATEITEM();
                        spkt.Amount = (byte)item.Count;
                        spkt.UpdateReason = (byte)ITEMUPDATEREASON.GIVE_TO_NPC;
                        spkt.UpdateType = 4;
                        spkt.Container = 2;
                        spkt.SessionId = value.id;
                        spkt.Index = (byte)currentInxdex;
                        value.client.Send((byte[])spkt);
                        break;
                    }
                }
                return count;
            }
            else
            {
                return -1;
            }
        }
Beispiel #3
0
        /// <summary>
        /// Registers a item from your inventory onto the market.
        /// </summary>
        /// <param name="cpkt"></param>
        private void CM_MARKET_REGISTERITEM(CMSG_MARKETREGISTER cpkt)
        {
            SMSG_MARKETREGISTER spkt = new SMSG_MARKETREGISTER();
            byte result = 0;

            try
            {
                Rag2Item item = this.character.container[cpkt.Index];
                if (item == null) return;
                uint requiredZeny = (uint)(50 * cpkt.Days);

                //NOT ENOUGH MONEY TO REGISTER ITEM
                if (requiredZeny > this.character.ZENY)
                {
                    result = 6;
                }
                //CHECK REGISTERED ITEM COUNT
                else if (Singleton.Database.GetOwnerItemCount(this.character) == 20)
                {
                    result = 8;
                }
                //EVERYTHING OKAY
                else
                {
                    //Create mail argument

                    Rag2Item bitem = item.Clone(cpkt.Count);
                    MarketItemArgument argument = new MarketItemArgument();
                    argument.item = bitem;
                    argument.expires = DateTime.Now.AddDays(cpkt.Days);
                    argument.cat = (byte)item.info.categorie;
                    argument.price = cpkt.Price;
                    argument.sender = this.character.Name;
                    argument.itemname = item.info.name;
                    argument.id = Singleton.Database.RegisterNewMarketItem(this.character, argument);

                    spkt.Item = bitem;
                    spkt.AuctionID = argument.id;
                    spkt.Zeny = cpkt.Price;
                    spkt.ExpireDate = argument.expires;

                    this.character.ZENY -= requiredZeny;
                    CommonFunctions.UpdateZeny(this.character);

                    int newCount = item.count - cpkt.Count;
                    if (newCount > 0)
                    {
                        item.count = newCount;
                        SMSG_UPDATEITEM spkt2 = new SMSG_UPDATEITEM();
                        spkt2.Index = cpkt.Index;
                        spkt2.UpdateReason = (byte)ItemUpdateReason.AuctionRegister;
                        spkt2.UpdateType = 4;
                        spkt2.SessionId = this.character.id;
                        spkt2.Amount = (byte)item.count;
                        spkt2.Container = 2;
                        this.Send((byte[])spkt2);
                    }
                    else
                    {
                        this.character.container.RemoveAt(cpkt.Index);
                        SMSG_DELETEITEM spkt2 = new SMSG_DELETEITEM();
                        spkt2.Index = cpkt.Index;
                        spkt2.UpdateReason = (byte)ItemUpdateReason.AuctionRegister;
                        spkt2.UpdateReason = 4;
                        spkt2.SessionId = this.character.id;
                        spkt2.Container = 2;
                        this.Send((byte[])spkt2);
                    }
                }
            }
            //DATABASE ERROR
            catch (Exception e)
            {
                result = 1;
                Console.WriteLine(e);
            }
            finally
            {
                spkt.SessionId = this.character.id;
                spkt.Result = result;
                this.Send((byte[])spkt);
            }
        }
        /// <summary>
        /// This function occurs when you want to sell a item. The sell price of the item is
        /// one-fourth of the actual market value.
        /// </summary>
        /// <param name="cpkt"></param>
        private void CM_NPCINTERACTION_SHOPSELL(CMSG_NPCSHOPSELL cpkt)
        {
            BaseNPC npc = this.character.Target as BaseNPC;
            BaseShopCollection list = this.character.Tag as BaseShopCollection;
            if (npc != null && list != null)
            {
                #region OBTAIN ITEM FROM INVENTORY

                //OBTAIN THE REQUIRED ITEM FROM THE MERCHANT
                Rag2Item item = this.character.container[cpkt.Index];
                if (item == null || cpkt.Amount > item.count) return;

                #endregion OBTAIN ITEM FROM INVENTORY

                #region MERCHANDISE - CHECK MERCHANTS MONEY

                //CHECK IF THE MERCHANT HAS ENOUGH MONEY

                double durabillity_scalar = (item.info.max_durability > 0) ? item.durabillty / item.info.max_durability : 1;
                uint req_money = (uint)((double)((item.info.price / 4) * cpkt.Amount) * durabillity_scalar);
                if (npc.Zeny < req_money)
                {
                    Common.Errors.GeneralErrorMessage(this.character, 3);
                    return;
                }

                #endregion MERCHANDISE - CHECK MERCHANTS MONEY

                #region MERCHANDISE - CHECK IF ITEM CAN BE SOLD

                //CHECKS IF THE ITEM IS TRADEABLE
                if (item.info.trade == 0)
                {
                    Common.Errors.GeneralErrorMessage(this.character, 4);
                    return;
                }

                #endregion MERCHANDISE - CHECK IF ITEM CAN BE SOLD

                #region MERCHANDISE - UPDATE ZENY

                this.character.ZENY += req_money;
                npc.Zeny -= req_money;

                CommonFunctions.UpdateZeny(this.character);
                CommonFunctions.UpdateShopZeny(this.character);

                #endregion MERCHANDISE - UPDATE ZENY

                #region INVENTORY - ITEM

                int newCount = item.count - cpkt.Amount;
                if (newCount == 0)
                {
                    //SEND INVENTORY - ITEM DELETE REASON WITH REASON: Sold
                    this.character.container.RemoveAt(cpkt.Index);
                    SMSG_DELETEITEM spkt = new SMSG_DELETEITEM();
                    spkt.Container = 2;
                    spkt.Index = cpkt.Index;
                    spkt.UpdateReason = 3;
                    spkt.SessionId = this.character.id;
                    this.Send((byte[])spkt);
                }
                else
                {
                    //SEND INVENTORY - ITEM UPDATE REASON WITH REASON: Sold
                    this.character.container[cpkt.Index].count = newCount;
                    SMSG_UPDATEITEM spkt = new SMSG_UPDATEITEM();
                    spkt.Amount = (byte)newCount;
                    spkt.UpdateReason = 3;
                    spkt.UpdateType = 4;
                    spkt.Container = 2;
                    spkt.SessionId = this.character.id;
                    spkt.Index = cpkt.Index;
                    this.Send((byte[])spkt);
                }

                #endregion INVENTORY - ITEM

                #region MERCHANDISE - STACK ON REBUY LIST

                //STRUCTURIZE NEW STACKED RAG2 ITEM
                Rag2Item newItem = item.Clone(cpkt.Amount);
                this.character.REBUY.Add(newItem);

                //POPS THE FIRST ITEM OFF THE LIST
                if (this.character.REBUY.Count > 16) this.character.REBUY.RemoveAt(0);
                CommonFunctions.SendRebuylist(this.character);

                #endregion MERCHANDISE - STACK ON REBUY LIST

                #region PLAYER - OPTION

                //Type is used to calc type of item
                //(21 seems to be used for Applogy Item)
                if (newItem.info.type == 21)
                {
                    Common.Skills.DeleteAddition(this.character, newItem.info.option_id);
                }

                #endregion PLAYER - OPTION
            }
        }
        /// <summary>
        /// This function is used when a player discards item x from either their storage
        /// or from their inventory. Also here we safely check for any weird stuff.
        /// </summary>
        /// <remarks>
        /// This function should also check if you have the item you want to delete is a quest item
        /// because if the quest is active you shouln't be allowed to discard your item.
        /// </remarks>
        /// <param name="cpkt"></param>
        private void CM_DISCARDITEM(CMSG_DELETEITEM cpkt)
        {
            Rag2Item item = null;
            if (cpkt.Container == 2)
            {
                item = this.character.container[cpkt.Index];
                if (item == null)
                {
                    Common.Errors.GeneralErrorMessage(
                        this.character,
                        (uint)Generalerror.InventoryItemNotFound
                    );
                    return;
                }
                else
                {
                    if (QuestBase.IsDiscardAble(item.info.item, this.character))
                    {
                        Common.Errors.GeneralErrorMessage(
                            this.character,
                            (uint)Generalerror.CannotDiscard
                        );
                        return;
                    }
                }
            }
            else if (cpkt.Container == 3)
            {
                item = this.character.STORAGE[cpkt.Index];
                if (item == null)
                {
                    Common.Errors.GeneralErrorMessage(
                        this.character,
                        (uint)Generalerror.StorageItemNotFound
                    );
                    return;
                }
                else
                {
                    if (QuestBase.IsDiscardAble(item.info.item, this.character))
                    {
                        Common.Errors.GeneralErrorMessage(
                            this.character,
                            (uint)Generalerror.CannotDiscard
                        );
                        return;
                    }
                }
            }
            else
            {
                Common.Errors.GeneralErrorMessage(
                    this.character,
                    (uint)Generalerror.WrongServerIndex
                );

                return;
            }

            //VALIDATE ITEM INFORMATION
            if (cpkt.Amount > item.count || cpkt.Amount > item.info.max_stack) return;

            //PROCESS DISCARDING
            int nCount = item.count - cpkt.Amount;
            if (nCount == 0)
            {
                this.character.container.RemoveAt(cpkt.Index);
                SMSG_DELETEITEM spkt = new SMSG_DELETEITEM();
                spkt.Container = cpkt.Container;
                spkt.Index = cpkt.Index;
                spkt.UpdateReason = 1;
                spkt.SessionId = this.character.id;
                this.Send((byte[])spkt);
            }
            else
            {
                item.count = nCount;
                SMSG_UPDATEITEM spkt2 = new SMSG_UPDATEITEM();
                spkt2.Amount = (byte)nCount;
                spkt2.UpdateReason = 1;
                spkt2.UpdateType = 4;
                spkt2.Container = cpkt.Container;
                spkt2.SessionId = this.character.id;
                spkt2.Index = cpkt.Index;
                this.Send((byte[])spkt2);
            }
        }
        /// <summary>
        /// This function process all inventory interaction. For example to equip a
        /// item or a to switch item from your inventory to the storage. Because this
        /// is populair place to exploit we do some heavy loaded item checking.
        /// </summary>
        /// <param name="cpkt"></param>
        private void CM_MOVEITEM(CMSG_MOVEITEM cpkt)
        {
            if (cpkt.MovementType == 1)
            {
                #region EQUIPMENT TO INVENTORY SWAP

                int result = 0;
                Rag2Item[] Equips = this.character.Equipment;
                Rag2Collection Inventory = this.character.container;

                //PROCESS EQUIPMENT SWAPPING
                int dest = 255;
                if (cpkt.DestinationIndex == 255)
                {
                    Rag2Item temp = Equips[cpkt.SourceIndex];
                    dest = this.character.container.Add(temp);
                    if (dest == -1) { result = 14; goto Notifycation; }
                    Equips[cpkt.SourceIndex] = null;

            #warning "Equipment deapplied"
                    temp.Activate(AdditionContext.Deapplied, this.character);
                    Tasks.LifeCycle.Update(this.character);
                }
                else
                {
                    Rag2Item temp2 = this.character.container[cpkt.DestinationIndex];
                    if (temp2 == null) { result = 16; goto Notifycation; }

                    Rag2Item temp = Equips[cpkt.SourceIndex];
                    Equips[cpkt.SourceIndex] = temp2;
                    this.character.container[cpkt.SourceIndex] = temp;

            #warning "Equipment applied/deapplied"
                    temp.Activate(AdditionContext.Deapplied, this.character);
                    temp2.Activate(AdditionContext.Reapplied, this.character);
                    Tasks.LifeCycle.Update(this.character);
                }

                //MOVE THE ITEM
                SMSG_MOVEITEM spkt = new SMSG_MOVEITEM();
                spkt.DestinationIndex = (byte)dest;
                spkt.SourceIndex = cpkt.SourceIndex;
                spkt.MovementType = cpkt.MovementType;
                spkt.SessionId = this.character.id;
                this.Send((byte[])spkt);

                Regiontree tree = this.character.currentzone.Regiontree;
                int SourceIndex = cpkt.SourceIndex;
                int ShieldIndex = (this.character.weapons.ActiveWeaponIndex == 1) ? 15 : 14;
                if (SourceIndex < 6 || SourceIndex == 8 || SourceIndex == ShieldIndex)
                    foreach (Character regionObject in tree.SearchActors(SearchFlags.Characters))
                    {
                        //FORWARD CHANGE TO ALL ACTORS
                        Rag2Item equip = Equips[cpkt.SourceIndex];
                        SMSG_CHANGEEQUIPMENT spkt2 = new SMSG_CHANGEEQUIPMENT();
                        spkt2.Slot = cpkt.SourceIndex;
                        spkt2.ActorID = this.character.id;
                        spkt2.ItemID = (equip != null) ? equip.info.item : 0;
                        spkt2.Dye = (byte)((equip != null) ? equip.dyecolor : 0);
                        spkt2.SessionId = regionObject.id;
                        regionObject.client.Send((byte[])spkt2);
                    }

            Notifycation:
                //NOTIFY THE USER OF AN ERROR
                SMSG_MOVEREPLY spkt3 = new SMSG_MOVEREPLY();
                spkt3.MovementType = cpkt.MovementType;
                spkt3.Message = (byte)result;
                spkt3.SessionId = this.character.id;
                this.Send((byte[])spkt3);

                #endregion EQUIPMENT TO INVENTORY SWAP
            }
            else if (cpkt.MovementType == 2)
            {
                #region INVENTORY TO EQUIPMENT SWAP

                //INVENTORY TO EQUIPMENT
                byte result = 0;
                Rag2Item[] Equips = this.character.Equipment;

                //CHECK INVENTORY ITEM
                Rag2Item InventoryItem = this.character.container[cpkt.SourceIndex];
                if (InventoryItem == null)
                {
                    result = 16;
                    goto Notifycation;
                }

                //CHECK LEVEL
                if (this.character._level < InventoryItem.info.req_clvl)
                {
                    result = 1;
                    goto Notifycation;
                }

                //CHECK GENDER
                if ((InventoryItem.info.req_male + InventoryItem.info.req_female < 2) &&
                ((InventoryItem.info.req_male == 1 && this.character.gender == 2) ||
                    (InventoryItem.info.req_female == 1 && this.character.gender == 1)))
                {
                    result = 2;
                    goto Notifycation;
                }

                //CHECK RACE
                if ((this.character.race == 1 && InventoryItem.info.req_norman == 1) ||
                    (this.character.race == 2 && InventoryItem.info.req_ellr == 1) ||
                    (this.character.race == 3 && InventoryItem.info.req_dimago == 1))
                {
                    result = 3;
                    goto Notifycation;
                }

                //CHECK STRENGTH
                if (this.character.stats.CHARACTER.strength < InventoryItem.info.req_str)
                {
                    result = 4;
                    goto Notifycation;
                }

                //CHECK DEXTERITY
                if (this.character.stats.CHARACTER.dexterity < InventoryItem.info.req_dex)
                {
                    result = 5;
                    goto Notifycation;
                }

                //CHECK CONCENCENTRATION
                if (this.character.stats.CHARACTER.concentration < InventoryItem.info.req_con)
                {
                    result = 6;
                    goto Notifycation;
                }

                //CHECK LUCK
                if (this.character.stats.CHARACTER.luck < InventoryItem.info.req_luc)
                {
                    result = 7;
                    goto Notifycation;
                }

                //CHECK JOB

                //UNSEAL THE ITEM
                if (InventoryItem.tradeable == true)
                {
                    InventoryItem.tradeable = false;
                    SMSG_UPDATEITEM spkt = new SMSG_UPDATEITEM();
                    spkt.Container = 2;
                    spkt.Index = cpkt.SourceIndex;
                    spkt.UpdateReason = (byte)ItemUpdateReason.NoReason;
                    spkt.UpdateType = 7;
                    spkt.Amount = 1;
                    spkt.SessionId = this.character.id;
                    this.Send((byte[])spkt);
                }

                //EVERYTHING IS OKAY PROCESS SWAPPING
                {
                    InventoryItem.active = 1;
                    SMSG_MOVEITEM spkt = new SMSG_MOVEITEM();
                    spkt.DestinationIndex = cpkt.DestinationIndex;
                    spkt.SourceIndex = cpkt.SourceIndex;
                    spkt.MovementType = cpkt.MovementType;
                    spkt.SessionId = this.character.id;
                    this.Send((byte[])spkt);
                }

                //PROCESS EQUIPMENT SWAPPING
                Rag2Item temp = Equips[cpkt.DestinationIndex];
                Equips[cpkt.DestinationIndex] = this.character.container[cpkt.SourceIndex];
                if (temp != null)
                {
                    this.character.container[cpkt.SourceIndex] = temp;
                    temp.Activate(AdditionContext.Deapplied, this.character);
                    InventoryItem.Activate(AdditionContext.Applied, this.character);
                    Tasks.LifeCycle.Update(this.character);
                }
                else
                {
                    this.character.container.RemoveAt(cpkt.SourceIndex);
                    InventoryItem.Activate(AdditionContext.Applied, this.character);
                    Tasks.LifeCycle.Update(this.character);
                }

                Regiontree tree = this.character.currentzone.Regiontree;
                int DestIndex = cpkt.DestinationIndex;
                int ShieldIndex = (this.character.weapons.ActiveWeaponIndex == 1) ? 15 : 14;
                if (DestIndex < 6 || DestIndex == 8 || DestIndex == ShieldIndex)
                    foreach (Character regionObject in tree.SearchActors(SearchFlags.Characters))
                    {
                        //FORWARD CHANGE TO ALL ACTORS
                        Rag2Item equip = Equips[cpkt.DestinationIndex];
                        SMSG_CHANGEEQUIPMENT spkt2 = new SMSG_CHANGEEQUIPMENT();
                        spkt2.Slot = cpkt.SourceIndex;
                        spkt2.ActorID = this.character.id;
                        spkt2.ItemID = (equip != null) ? equip.info.item : 0;
                        spkt2.Dye = (byte)((equip != null) ? equip.dyecolor : 0);
                        regionObject.client.Send((byte[])spkt2);
                    }

            Notifycation:
                //NOTIFY THE USER OF AN ERROR
                SMSG_MOVEREPLY spkt3 = new SMSG_MOVEREPLY();
                spkt3.MovementType = cpkt.MovementType;
                spkt3.Message = result;
                spkt3.SessionId = this.character.id;
                this.Send((byte[])spkt3);

                #endregion INVENTORY TO EQUIPMENT SWAP
            }
            else if (cpkt.MovementType == 3)
            {
                #region INVENTORY TO STORAGE SWAP

                //STORAGE TO INVENTORY
                byte result = 0;

                //CHECK STORAGE ITEM
                Rag2Item storageItem = null;
                Rag2Item invenItem = this.character.container[cpkt.SourceIndex];
                if (invenItem == null) { result = 16; goto Notifycation; }

                //CHECK PROVIDED AMOUNT
                if (cpkt.Amount > invenItem.count) { result = 25; goto Notifycation; }

                //CHECK MAX STACK LIMITS
                if (cpkt.Amount > invenItem.info.max_stack) { result = 24; goto Notifycation; }

                //CHECK DESTINATION
                if (cpkt.DestinationIndex == 255)
                {
                    if (this.character.STORAGE.Count == this.character.STORAGE.Capacity) { result = 17; goto Notifycation; }
                }
                else
                {
                    storageItem = this.character.STORAGE[cpkt.DestinationIndex];
                    if (storageItem == null) { result = 19; goto Notifycation; }
                    if (storageItem.Equals(invenItem)) { result = 23; goto Notifycation; }
                    if (storageItem.count + cpkt.Amount > invenItem.info.max_stack) { result = 24; goto Notifycation; }
                }

                //PROCESS MOVEMENT - PART 1
                if (cpkt.DestinationIndex == 255)
                {
                    storageItem = invenItem.Clone(cpkt.Amount);
                    int index = this.character.STORAGE.Add(storageItem);

                    SMSG_ADDITEM spkt4 = new SMSG_ADDITEM();
                    spkt4.Container = 3;
                    spkt4.SessionId = this.character.id;
                    spkt4.UpdateReason = 0;
                    spkt4.SetItem(invenItem, index);
                    this.Send((byte[])spkt4);
                }
                else
                {
                    storageItem.count += cpkt.Amount;
                    SMSG_UPDATEITEM spkt4 = new SMSG_UPDATEITEM();
                    spkt4.Amount = (byte)storageItem.count;
                    spkt4.Container = 3;
                    spkt4.Index = cpkt.DestinationIndex;
                    spkt4.UpdateReason = 0;
                    spkt4.UpdateType = 2;
                    this.Send((byte[])spkt4);
                }

                //PROCESS MOVEMENT - PART 2
                int nCount = invenItem.count - cpkt.Amount;
                if (nCount > 0)
                {
                    invenItem.count = nCount;
                    SMSG_UPDATEITEM spkt4 = new SMSG_UPDATEITEM();
                    spkt4.Amount = (byte)nCount;
                    spkt4.Container = 2;
                    spkt4.Index = cpkt.SourceIndex;
                    spkt4.UpdateReason = (byte)ItemUpdateReason.StorageSent;
                    spkt4.UpdateType = 2;
                    this.Send((byte[])spkt4);
                }
                else
                {
                    this.character.container.RemoveAt(cpkt.SourceIndex);
                    SMSG_DELETEITEM spkt2 = new SMSG_DELETEITEM();
                    spkt2.Container = 2;
                    spkt2.Index = cpkt.SourceIndex;
                    spkt2.UpdateReason = (byte)ItemUpdateReason.StorageSent;
                    spkt2.SessionId = this.character.id;
                    this.Send((byte[])spkt2);
                }

            Notifycation:
                SMSG_MOVEREPLY spkt3 = new SMSG_MOVEREPLY();
                spkt3.Message = (byte)result;
                spkt3.MovementType = cpkt.MovementType;
                spkt3.SessionId = this.character.id;
                this.Send((byte[])spkt3);

                //Type is used to calc type of item
                //(21 seems to be used for Applogy Item)
                if (result == 0 && invenItem.info.type == 21)
                {
                    Common.Skills.UpdateAddition(this.character, 101);
                }

                #endregion INVENTORY TO STORAGE SWAP
            }
            else if (cpkt.MovementType == 4)
            {
                #region STORAGE TO INVENTORY SWAP

                //CHECK STORAGE ITEM
                int result = 0;
                Rag2Item invenItem = null;
                Rag2Item storageItem = this.character.STORAGE[cpkt.SourceIndex];
                if (storageItem == null) { result = 19; goto Notifycation; }

                //CHECK PROVIDED AMOUNT
                if (cpkt.Amount > storageItem.count) { result = 25; goto Notifycation; }

                //CHECK MAX STACK LIMITS
                if (cpkt.Amount > storageItem.info.max_stack) { result = 24; goto Notifycation; }

                //CHECK DESTINATION
                if (cpkt.DestinationIndex == 255)
                {
                    if (this.character.container.Count == this.character.container.Capacity) { result = 14; goto Notifycation; }
                }
                else
                {
                    invenItem = this.character.container[cpkt.DestinationIndex];
                    if (invenItem == null) { result = 16; goto Notifycation; }
                    if (invenItem.Equals(storageItem)) { result = 23; goto Notifycation; }
                    if (invenItem.count + cpkt.Amount > storageItem.info.max_stack) { result = 24; goto Notifycation; }
                }

                //PROCESS MOVEMENT - PART 1
                if (cpkt.DestinationIndex == 255)
                {
                    invenItem = storageItem.Clone(cpkt.Amount);
                    int index = this.character.container.Add(invenItem);

                    SMSG_ADDITEM spkt4 = new SMSG_ADDITEM();
                    spkt4.Container = 2;
                    spkt4.SessionId = this.character.id;
                    spkt4.UpdateReason = (byte)ItemUpdateReason.StorageReceived;
                    spkt4.SetItem(invenItem, index);
                    this.Send((byte[])spkt4);
                }
                else
                {
                    invenItem.count += cpkt.Amount;
                    SMSG_UPDATEITEM spkt4 = new SMSG_UPDATEITEM();
                    spkt4.Amount = (byte)invenItem.count;
                    spkt4.Container = 2;
                    spkt4.Index = cpkt.DestinationIndex;
                    spkt4.UpdateReason = (byte)ItemUpdateReason.StorageReceived;
                    spkt4.UpdateType = 2;
                    this.Send((byte[])spkt4);
                }

                //PROCESS MOVEMENT - PART 2
                int nCount = storageItem.count - cpkt.Amount;
                if (nCount > 0)
                {
                    storageItem.count = nCount;
                    SMSG_UPDATEITEM spkt4 = new SMSG_UPDATEITEM();
                    spkt4.Amount = (byte)nCount;
                    spkt4.Container = 3;
                    spkt4.Index = cpkt.SourceIndex;
                    spkt4.UpdateReason = 0;
                    spkt4.UpdateType = 2;
                    this.Send((byte[])spkt4);
                }
                else
                {
                    this.character.STORAGE.RemoveAt(cpkt.SourceIndex);
                    SMSG_DELETEITEM spkt2 = new SMSG_DELETEITEM();
                    spkt2.Container = 3;
                    spkt2.Index = cpkt.SourceIndex;
                    spkt2.UpdateReason = 0;
                    spkt2.SessionId = this.character.id;
                    this.Send((byte[])spkt2);
                }

            Notifycation:
                SMSG_MOVEREPLY spkt3 = new SMSG_MOVEREPLY();
                spkt3.MovementType = cpkt.MovementType;
                spkt3.Message = (byte)result;
                spkt3.SessionId = this.character.id;
                this.Send((byte[])spkt3);

                //Type is used to calc type of item
                //(21 seems to be used for Applogy Item)
                if (result == 0 && invenItem.info.type == 21)
                {
                    Common.Skills.UpdateAddition(this.character, 101);
                }

                #endregion STORAGE TO INVENTORY SWAP
            }
        }
        /// <summary>
        /// This occurs after adding a auge skill to the weaponary
        /// </summary>
        /// <param name="cpkt"></param>
        private void CM_WEAPONAUGE(CMSG_WEAPONAUGE cpkt)
        {
            Rag2Item item = this.character.container[cpkt.Index];
            Weapon wep = this.character.weapons[cpkt.WeaponSlot];
            if (item == null) return;

            wep._augeskill = item.info.skill;
            Point oldPos = this.character.Position;
            Regiontree tree = this.character.currentzone.Regiontree;
            bool IsActiveItem = cpkt.WeaponSlot == (byte)((character.weapons.ActiveWeaponIndex == 0) ? character.weapons.PrimaryWeaponIndex : character.weapons.SeconairyWeaponIndex);

            //Update item count
            int newLength = item.count - 1;
            if (newLength > 0)
            {
                item.count = newLength;
                SMSG_UPDATEITEM spkt2 = new SMSG_UPDATEITEM();
                spkt2.Amount = (byte)newLength;
                spkt2.UpdateReason = 0;
                spkt2.UpdateType = 4;
                spkt2.Container = 2;
                spkt2.SessionId = this.character.id;
                spkt2.Index = cpkt.Index;
                this.Send((byte[])spkt2);
            }
            else
            {
                this.character.container.RemoveAt(cpkt.Index);
                SMSG_DELETEITEM spkt3 = new SMSG_DELETEITEM();
                spkt3.UpdateReason = 0;
                spkt3.Container = 2;
                spkt3.Index = cpkt.Index;
                spkt3.SessionId = this.character.id;
                this.Send((byte[])spkt3);
            }

            //Update all objects
            foreach (Character regionObject in tree.SearchActors(SearchFlags.Characters))
            {
                if (regionObject.id == this.character.id)
                {
                    SMSG_ENCHANTMENT spkt = new SMSG_ENCHANTMENT();
                    spkt.Unknown1 = 1;
                    spkt.Unknown2 = cpkt.WeaponSlot;
                    spkt.Weaponslot = cpkt.Slot;
                    spkt.SkillId = wep._augeskill;
                    spkt.SessionId = this.character.id;
                    this.Send((byte[])spkt);
                }
                else if (IsActiveItem && Point.IsInSightRangeByRadius(regionObject.Position, oldPos))
                {
                    SMSG_SHOWWEAPON spkt = new SMSG_SHOWWEAPON();
                    spkt.ActorID = this.character.id;
                    spkt.AugeID = this.character.ComputeAugeSkill();
                    spkt.SessionId = regionObject.id;
                    regionObject.client.Send((byte[])spkt);
                }
            }
        }
Beispiel #8
0
        /// <summary>
        /// Learns a new skill from a skillbook
        /// </summary>
        /// <param name="cpkt"></param>
        private void CM_SKILLS_LEARNFROMSKILLBOOK(CMSG_SKILLLEARN cpkt)
        {
            byte result = 1;
            try
            {
                Saga.Factory.Spells.Info spellinfo;
                Rag2Item item = character.container[cpkt.Index];
                if (item != null)
                {
                    //Helpers predicates
                    Predicate<Skill> FindSkill = delegate(Skill skill)
                    {
                        return skill.Id == item.info.skill;
                    };

                    Predicate<Skill> FindPreviousSkill = delegate(Skill skill)
                    {
                        return skill.Id == item.info.skill - 1;
                    };

                    //HELPER VARIABLES
                    uint baseskill = (item.info.skill / 100) * 100 + 1;
                    int newLength = character.container[cpkt.Index].count - 1;
                    List<Skill> learnedSpells = this.character.learnedskills;
                    Singleton.SpellManager.TryGetSpell(item.info.skill, out spellinfo);
                    Skill CurrentSkill = learnedSpells.FindLast(FindSkill);
                    Skill PreviousSkill = learnedSpells.FindLast(FindPreviousSkill);
                    bool IsBaseSkill = item.info.skill == baseskill;

                    //CHECK IF THE CURRENT JOB CAN LEARN THE SPELL
                    if (item.info.JobRequirement[this.character.job - 1] > this.character.jlvl)
                    {
                        result = (byte)Generalerror.ConditionsNotMet;
                    }
                    //CHECK IF WE ALREADY LEARNED THE SPELL
                    else if (CurrentSkill != null)
                    {
                        result = (byte)Generalerror.AlreadyLearntSkill;
                    }
                    //CHECK IF A PREVIOUS SKILL WAS FOUND
                    else if (!IsBaseSkill && PreviousSkill == null)
                    {
                        result = (byte)Generalerror.PreviousSkillNotFound;
                    }
                    //CHECK SKILL EXP
                    else if (PreviousSkill != null && PreviousSkill.Experience < PreviousSkill.info.maximumexperience)
                    {
                        result = (byte)Generalerror.NotEnoughSkillExperience;
                    }
                    else
                    {
                        //ADD A NEW SKILL
                        if (IsBaseSkill)
                        {
                            //Passive skill
                            bool canUse = Singleton.SpellManager.CanUse(this.character, spellinfo);
                            if (spellinfo.skilltype == 2 && canUse)
                            {
                                Singleton.Additions.ApplyAddition(spellinfo.addition, this.character);

                                int ActiveWeaponIndex = (this.character.weapons.ActiveWeaponIndex == 1) ? this.character.weapons.SeconairyWeaponIndex : this.character.weapons.PrimaryWeaponIndex;
                                if (ActiveWeaponIndex < this.character.weapons.UnlockedWeaponSlots)
                                {
                                    Weapon weapon = this.character.weapons[ActiveWeaponIndex];
                                    if ((baseskill - 1) == weapon.Info.weapon_skill)
                                    {
                                        BattleStatus status = character._status;
                                        status.MaxWMAttack += (ushort)weapon.Info.max_magic_attack;
                                        status.MinWMAttack += (ushort)weapon.Info.min_magic_attack;
                                        status.MaxWPAttack += (ushort)weapon.Info.max_short_attack;
                                        status.MinWPAttack += (ushort)weapon.Info.min_short_attack;
                                        status.MaxWRAttack += (ushort)weapon.Info.max_range_attack;
                                        status.MinWRAttack += (ushort)weapon.Info.min_range_attack;
                                        status.Updates |= 2;
                                    }
                                }
                            }

                            Singleton.Database.InsertNewSkill(this.character, item.info.skill, spellinfo.maximumexperience);
                            CurrentSkill = new Skill();
                            CurrentSkill.info = spellinfo;
                            CurrentSkill.Id = item.info.skill;
                            CurrentSkill.Experience = spellinfo.maximumexperience;
                            learnedSpells.Add(CurrentSkill);
                        }
                        //UPDATE A OLD SKILL
                        else
                        {
                            //Passive skill
                            if (spellinfo.skilltype == 2)
                            {
                                Saga.Factory.Spells.Info oldSpellinfo;
                                Singleton.SpellManager.TryGetSpell(PreviousSkill.info.skillid, out oldSpellinfo);

                                bool canUseOld = Singleton.SpellManager.CanUse(this.character, oldSpellinfo);
                                bool canUseNew = Singleton.SpellManager.CanUse(this.character, spellinfo);

                                if (canUseOld)
                                {
                                    Singleton.Additions.DeapplyAddition(oldSpellinfo.addition, this.character);
                                }

                                if (canUseNew)
                                {
                                    Singleton.Additions.ApplyAddition(spellinfo.addition, this.character);
                                }
                            }

                            Singleton.Database.UpgradeSkill(this.character, PreviousSkill.info.skillid,
                                item.info.skill, spellinfo.maximumexperience);
                            PreviousSkill.info = spellinfo;
                            PreviousSkill.Id = item.info.skill;
                            PreviousSkill.Experience = spellinfo.maximumexperience;
                        }

                        SMSG_SKILLADD spkt2 = new SMSG_SKILLADD();
                        spkt2.Slot = 0;
                        spkt2.SkillId = item.info.skill;
                        spkt2.SessionId = this.character.id;
                        this.Send((byte[])spkt2);

                        if (newLength > 0)
                        {
                            this.character.container[cpkt.Index].count = newLength;
                            SMSG_UPDATEITEM spkt = new SMSG_UPDATEITEM();
                            spkt.Amount = (byte)newLength;
                            spkt.UpdateReason = 8;
                            spkt.UpdateType = 4;
                            spkt.Container = 2;
                            spkt.SessionId = this.character.id;
                            spkt.Index = cpkt.Index;
                            this.Send((byte[])spkt);
                        }
                        else
                        {
                            this.character.container.RemoveAt(cpkt.Index);
                            SMSG_DELETEITEM spkt = new SMSG_DELETEITEM();
                            spkt.UpdateReason = 8;
                            spkt.Container = 2;
                            spkt.Index = cpkt.Index;
                            spkt.SessionId = this.character.id;
                            this.Send((byte[])spkt);
                        }

                        Common.Internal.CheckWeaponary(this.character);
                        Tasks.LifeCycle.Update(this.character);
                        result = 0;
                    }
                }
            }
            finally
            {
                //OUTPUT THE RESULT
                SMSG_SKILLLEARN spkt = new SMSG_SKILLLEARN();
                spkt.Result = result;
                spkt.SessionId = this.character.id;
                this.Send((byte[])spkt);
            }
        }
        /// <summary>
        /// Resets your characters stats.
        /// </summary>
        /// <param name="cpkt"></param>
        private void CM_USESTATRESETITEM(CMSG_STATRESETPOTION cpkt)
        {
            Rag2Item InventoryItem = this.character.container[cpkt.SlotId];
            if (InventoryItem != null)
            {
                //Update stats
                lock (this.character.stats)
                {
                    Saga.PrimaryTypes.CharacterStats.Stats stats = this.character.stats.CHARACTER;
                    int remaining = stats.concentration
                                  + stats.dexterity
                                  + stats.intelligence
                                  + stats.strength
                                  + this.character.stats.REMAINING;

                    lock (character._status)
                    {
                        //Update strength
                        character._status.MaxPAttack -= (ushort)(2 * stats.strength);
                        character._status.MinPAttack -= (ushort)(1 * stats.strength);
                        character._status.MaxHP -= (ushort)(10 * stats.strength);
                        stats.strength = 0;

                        //Update Dextericty
                        character._status.BaseMHitrate -= (ushort)(1 * stats.dexterity);
                        stats.dexterity = 0;

                        //Update Intellect
                        character._status.MaxMAttack -= (ushort)(6 * stats.intelligence);
                        character._status.MinMAttack -= (ushort)(3 * stats.intelligence);
                        character._status.BaseRHitrate -= (ushort)(1 * stats.intelligence);
                        stats.intelligence = 0;

                        //Update Concentration
                        character._status.MaxRAttack -= (ushort)(4 * stats.concentration);
                        character._status.MinRAttack -= (ushort)(2 * stats.concentration);
                        character._status.BasePHitrate -= (ushort)(2 * stats.concentration);
                        stats.concentration = 0;

                        this.character.stats.REMAINING = (ushort)remaining;
                    }
                }

                //Reset stat points
                SMSG_EXTSTATS spkt = new SMSG_EXTSTATS();
                spkt.base_stats_1 = character.stats.BASE;
                spkt.base_stats_2 = character.stats.CHARACTER;
                spkt.base_stats_jobs = character.stats.EQUIPMENT;
                spkt.base_stats_bonus = character.stats.ENCHANTMENT;
                spkt.statpoints = character.stats.REMAINING;
                spkt.SessionId = character.id;
                this.Send((byte[])spkt);

                //Use the item
                int newLength = InventoryItem.count - 1;
                if (newLength > 0)
                {
                    InventoryItem.count = newLength;
                    SMSG_UPDATEITEM spkt2 = new SMSG_UPDATEITEM();
                    spkt2.Amount = (byte)newLength;
                    spkt2.UpdateReason = 0;
                    spkt2.UpdateType = 4;
                    spkt2.Container = 2;
                    spkt2.SessionId = this.character.id;
                    spkt2.Index = cpkt.SlotId;
                    this.Send((byte[])spkt2);
                }
                else
                {
                    this.character.container.RemoveAt(cpkt.SlotId);
                    SMSG_DELETEITEM spkt3 = new SMSG_DELETEITEM();
                    spkt3.UpdateReason = 0;
                    spkt3.Container = 2;
                    spkt3.Index = cpkt.SlotId;
                    spkt3.SessionId = this.character.id;
                    this.Send((byte[])spkt3);
                }
            }
        }
        /// <summary>
        /// Uses a map item to unhide a hidden region.
        /// </summary>
        /// <remarks>
        /// As a programmer would know a byte had eight bits.
        /// Each bit represents a region that can be unhidden.
        /// These bit's are invered however, so 128 means first
        /// region is unhidden. While 255 would mean all eight
        /// regions are unhiden.
        ///
        ///  128 = 7 = Region 1
        ///   64 = 6 = Region 2
        ///   32 = 5 = Region 3
        ///   16 = 4 = Region 4
        ///    8 = 3 = Region 5
        ///    4 = 2 = Region 6
        ///    2 = 1 = Region 7
        ///    1 = 0 = Region 8
        ///
        /// </remarks>
        /// <param name="cpkt"></param>
        private void CM_USEMAPITEM(CMSG_USEMAP cpkt)
        {
            Rag2Item item = character.container[cpkt.Index];
            byte result = 0;
            byte map = 0;
            byte zone = 0;
            int value = 0;

            try
            {
                if (item != null)
                {
                    map = (byte)(item.info.skill / 10);
                    zone = (byte)(item.info.skill % 10);
                    value = (int)Math.Pow(2, (8 - zone));

                    //ALREADY LEARNED
                    if ((this.character.ZoneInformation[map] & value) == value)
                    {
                        result = 1;
                    }
                    //EVERYTHING IS OKAY
                    else
                    {
                        //UPDATE ITEM COUNT
                        int newLength = item.count - 1;
                        if (newLength > 0)
                        {
                            item.count = newLength;
                            SMSG_UPDATEITEM spkt2 = new SMSG_UPDATEITEM();
                            spkt2.Amount = (byte)newLength;
                            spkt2.UpdateReason = 0;
                            spkt2.UpdateType = 4;
                            spkt2.Container = 2;
                            spkt2.SessionId = this.character.id;
                            spkt2.Index = cpkt.Index;
                            this.Send((byte[])spkt2);
                        }
                        else
                        {
                            this.character.container.RemoveAt(cpkt.Index);
                            SMSG_DELETEITEM spkt3 = new SMSG_DELETEITEM();
                            spkt3.UpdateReason = 0;
                            spkt3.Container = 2;
                            spkt3.Index = cpkt.Index;
                            spkt3.SessionId = this.character.id;
                            this.Send((byte[])spkt3);
                        }

                        //UPDATE MAP STATE
                        this.character.ZoneInformation[map] |= (byte)value;
                    }
                }
            }
            catch (Exception e)
            {
                result = 1;
                Console.WriteLine(e);
            }
            finally
            {
                SMSG_SHOWMAP spkt = new SMSG_SHOWMAP();
                spkt.Reason = result;
                spkt.Map = map;
                spkt.Zone = zone;
                spkt.SessionId = this.character.id;
                this.Send((byte[])spkt);
            }
        }
        /// <summary>
        /// This function is sent when you use an dying item
        /// </summary>
        /// <param name="cpkt"></param>
        private void CM_USEDYEITEM(CMSG_USEDYEITEM cpkt)
        {
            Rag2Item dyeitem = null;
            Rag2Item item = null;
            byte result = 0;

            try
            {
                //Get the dyeitem
                dyeitem = this.character.container[cpkt.Index];

                //Get the equipment item
                switch (cpkt.Container)
                {
                    case 1: item = this.character.Equipment[cpkt.Slot]; break;
                    case 2: item = this.character.container[cpkt.Slot]; break;
                    case 3: item = this.character.STORAGE[cpkt.Slot]; break;
                }

                //Check if equipment is found
                if (item == null)
                {
                    result = (byte)Generalerror.InventoryItemNotFound;
                }
                //Check if the dye is found
                else if (dyeitem == null)
                {
                    result = (byte)Generalerror.InventoryItemNotFound;
                }
                //Everything is okay
                else
                {
                    //Set the dye color
                    switch (dyeitem.info.skill)
                    {
                        case 0: item.dyecolor = 0; break; //Nothing
                        case 1: item.dyecolor = (byte)Saga.Utils.Generator.Random(2, 2); break;   //red
                        case 2: item.dyecolor = (byte)Saga.Utils.Generator.Random(10, 10); break;   //Yellow
                        case 3: item.dyecolor = (byte)Saga.Utils.Generator.Random(17, 17); break;   //Green
                        case 4: item.dyecolor = (byte)Saga.Utils.Generator.Random(21, 21); break;   //Blue
                        case 5: item.dyecolor = (byte)Saga.Utils.Generator.Random(34, 34); break;  //Purple
                    }

                    //The appearance has changed
                    bool IsEquipment = cpkt.Container == 1;

                    Regiontree tree = this.character.currentzone.Regiontree;
                    foreach (Character target in tree.SearchActors(this.character, SearchFlags.Characters))
                    {
                        if (!Point.IsInSightRangeByRadius(this.character.Position, target.Position)) continue;
                        if (target.id == this.character.id)
                        {
                            //Adjust the item
                            SMSG_ITEMADJUST spkt2 = new SMSG_ITEMADJUST();
                            spkt2.Container = cpkt.Container;
                            spkt2.Slot = cpkt.Slot;
                            spkt2.Value = item.dyecolor;
                            spkt2.Function = 6;
                            spkt2.SessionId = this.character.id;
                            this.Send((byte[])spkt2);
                        }
                        else if (IsEquipment)
                        {
                            SMSG_CHANGEEQUIPMENT spkt = new SMSG_CHANGEEQUIPMENT();
                            spkt.ActorID = this.character.id;
                            spkt.ItemID = (item != null) ? item.info.item : 0;
                            spkt.Dye = (item != null) ? (byte)item.dyecolor : (byte)0;
                            spkt.Slot = cpkt.Slot;
                            spkt.SessionId = target.id;
                            target.client.Send((byte[])spkt);
                        }
                    }

                    //Remove item
                    if (dyeitem.count - 1 > 0)
                    {
                        dyeitem.count -= 1;
                        SMSG_ITEMADJUST spkt3 = new SMSG_ITEMADJUST();
                        spkt3.Container = 2;
                        spkt3.Slot = cpkt.Index;
                        spkt3.Value = (byte)dyeitem.count;
                        spkt3.Function = 4;
                        spkt3.SessionId = this.character.id;
                        this.Send((byte[])spkt3);
                    }
                    else
                    {
                        this.character.container.RemoveAt(cpkt.Index);
                        SMSG_DELETEITEM spkt3 = new SMSG_DELETEITEM();
                        spkt3.UpdateReason = 0;
                        spkt3.Index = cpkt.Index;
                        spkt3.SessionId = this.character.id;
                        spkt3.Container = 2;
                        this.Send((byte[])spkt3);
                    }
                }
            }
            finally
            {
                SMSG_USEDYEITEM spkt = new SMSG_USEDYEITEM();
                if (dyeitem != null)
                    spkt.ItemId = dyeitem.info.item;
                spkt.Equipment = cpkt.Slot;
                spkt.Container = cpkt.Container;
                spkt.Result = result;
                spkt.SessionId = this.character.id;
                this.Send((byte[])spkt);
            }
        }
        /// <summary>
        /// Function is called when a user tries to unlock a new
        /// weapon slot.
        /// </summary>
        /// <param name="cpkt"></param>
        private void CM_USEADMISSIONWEAPON(CMSG_USEWEAPONADMISSION cpkt)
        {
            byte error = 0;
            try
            {
                Rag2Item item = this.character.container[cpkt.Index];
                if (item == null)
                {
                    error = (byte)Generalerror.InventoryItemNotFound;
                }
                else if (this.character.weapons.UnlockedWeaponSlots >= 5)
                {
                    error = (byte)Generalerror.AllWeaponSlotsOpen;
                }
                else
                {
                    this.character.weapons.UnlockedWeaponSlots++;
                }

                if (item.count - 1 > 0)
                {
                    item.count -= 1;
                    SMSG_ITEMADJUST spkt3 = new SMSG_ITEMADJUST();
                    spkt3.Container = 2;
                    spkt3.Slot = cpkt.Index;
                    spkt3.Value = (byte)item.count;
                    spkt3.Function = 4;
                    spkt3.SessionId = this.character.id;
                    this.Send((byte[])spkt3);
                }
                else
                {
                    this.character.container.RemoveAt(cpkt.Index);
                    SMSG_DELETEITEM spkt3 = new SMSG_DELETEITEM();
                    spkt3.UpdateReason = 0;
                    spkt3.Index = cpkt.Index;
                    spkt3.SessionId = this.character.id;
                    spkt3.Container = 2;
                    this.Send((byte[])spkt3);
                }
            }
            finally
            {
                SMSG_WEAPONMAX spkt = new SMSG_WEAPONMAX();
                spkt.Result = error;
                spkt.Count = this.character.weapons.UnlockedWeaponSlots;
                spkt.SessionId = this.character.id;
                this.Send((byte[])spkt);
            }
        }
        /// <summary>
        /// Occurs when sorting the inventory
        /// </summary>
        /// <param name="cpkt"></param>
        private void CM_IVENTORY_SORT(CMSG_SORTINVENTORYLIST cpkt)
        {
            if (cpkt.SortType > 1) return;
            for (int i = 0; i < this.character.container.Capacity; i++)
            {
                Rag2Item a = character.container[i];
                if (a == null) continue;

                Predicate<KeyValuePair<byte, Rag2Item>> FindRag2Items = delegate(KeyValuePair<byte, Rag2Item> b)
                {
                    return b.Value.info == a.info &&
                           b.Value.clvl == a.clvl;
                };

                bool result = false;
                int count = a.info.max_stack - a.count;

                List<KeyValuePair<byte, Rag2Item>> items = new List<KeyValuePair<byte, Rag2Item>>();
                foreach (KeyValuePair<byte, Rag2Item> b in this.character.container.GetAllItems(FindRag2Items))
                {
                    if (b.Value.count < b.Value.info.max_stack && b.Key != i)
                        items.Add(b);
                }

                foreach (KeyValuePair<byte, Rag2Item> b in items)
                {
                    if (b.Value.count > count)
                    {
                        a.count = a.info.max_stack;
                        b.Value.count -= count;
                        count = 0;

                        SMSG_UPDATEITEM spkt = new SMSG_UPDATEITEM();
                        spkt.Container = 2;
                        spkt.UpdateType = 4;
                        spkt.SessionId = this.character.id;
                        spkt.Index = b.Key;
                        spkt.Amount = (byte)b.Value.count;
                        spkt.UpdateReason = 0;
                        this.Send((byte[])spkt);
                        result = true;
                        break;
                    }
                    else
                    {
                        a.count += b.Value.count;
                        count -= b.Value.count;
                        this.character.container.RemoveAt(b.Key);

                        SMSG_DELETEITEM spkt = new SMSG_DELETEITEM();
                        spkt.Index = b.Key;
                        spkt.UpdateReason = 0;
                        spkt.SessionId = this.character.id;
                        spkt.Container = 2;
                        result = true;
                        this.Send((byte[])spkt);
                    }
                }

                if (result == true)
                {
                    SMSG_UPDATEITEM spkt = new SMSG_UPDATEITEM();
                    spkt.Container = 2;
                    spkt.UpdateType = 4;
                    spkt.SessionId = this.character.id;
                    spkt.Index = (byte)i;
                    spkt.Amount = (byte)a.count;
                    spkt.UpdateReason = 0;
                    this.Send((byte[])spkt);
                }
            }
        }
Beispiel #14
0
        /// <summary>
        /// Sends a new mail message
        /// </summary>
        private void CM_NEWMAILITEM(CMSG_SENDMAIL cpkt)
        {
            //HELPER VARIABLES
            byte result = 1;
            uint req_zeny = 0;
            Rag2Item item = null;
            MailItem mailmessage = new MailItem();
            mailmessage.Content = cpkt.Content;
            mailmessage.Recieptent = cpkt.Name;
            mailmessage.Topic = cpkt.Topic;
            mailmessage.item = item;

            if ((cpkt.HasItem & 2) == 2)
            {
                item = this.character.container[cpkt.Slot];
                if (item != null)
                {
                    req_zeny = 10;
                    mailmessage.item = item.Clone(cpkt.StackCount);
                }
            }
            if ((cpkt.HasItem & 1) == 1)
            {
                req_zeny = 10 + cpkt.Zeny;
                mailmessage.Zeny = cpkt.Zeny;
            }

            try
            {
                //RECIEVER DOES NOT EXISTS
                if (!Singleton.Database.VerifyNameExists(mailmessage.Recieptent))
                {
                    result = 2;
                }
                //NOT ENOUGH MONEY
                else if (this.character.ZENY < req_zeny)
                {
                    result = 3;
                }
                //CHECK ITEM INVENTORY
                else if (item != null && cpkt.StackCount > item.count)
                {
                    result = 5;
                }
                //CHECK IF OWNER OUTBOX IF FULL
                else if (Singleton.Database.GetInboxMailCount(this.character.Name) == 20)
                {
                    result = 6;
                }
                //CHECK IF SENDER INBOX IS FULL
                else if (Singleton.Database.GetInboxMailCount(mailmessage.Recieptent) == 20)
                {
                    result = 7;
                }
                //DATABASE ERROR
                else if (!Singleton.Database.InsertNewMailItem(this.character, mailmessage))
                {
                    result = 1;
                }
                //EVERYTHING IS OKAY
                else
                {
                    if (cpkt.HasItem > 0)
                    {
                        this.character.ZENY -= req_zeny;
                        CommonFunctions.UpdateZeny(this.character);
                    }

                    //UPDATE ITEM COUNT AS FORM OF A ATTACHMENT
                    if ((cpkt.HasItem & 2) == 2)
                    {
                        item.count -= cpkt.StackCount;
                        if (item.count > 0)
                        {
                            SMSG_UPDATEITEM spkt = new SMSG_UPDATEITEM();
                            spkt.Amount = (byte)item.count;
                            spkt.UpdateReason = (byte)ItemUpdateReason.AttachmentReceived;
                            spkt.UpdateType = 4;
                            spkt.Container = 2;
                            spkt.SessionId = this.character.id;
                            spkt.Index = cpkt.Slot;
                            this.Send((byte[])spkt);
                        }
                        else
                        {
                            this.character.container.RemoveAt(cpkt.Slot);
                            SMSG_DELETEITEM spkt = new SMSG_DELETEITEM();
                            spkt.Container = 2;
                            spkt.Index = cpkt.Slot;
                            spkt.UpdateReason = (byte)ItemUpdateReason.AttachmentReceived;
                            spkt.SessionId = this.character.id;
                            this.Send((byte[])spkt);
                        }
                    }

                    //EVERYTHING OKAY
                    result = 0;
                }
            }
            finally
            {
                SMSG_MAILSENDAWNSER spkt = new SMSG_MAILSENDAWNSER();
                spkt.Result = result;
                spkt.SessionId = cpkt.SessionId;
                this.Send((byte[])spkt);
            }
        }
        /// <summary>
        /// Uses a supplement stone.
        /// </summary>
        /// <param name="cpkt"></param>
        private void CM_USESUPLEMENTSTONE(CMSG_USESUPPLEMENTSTONE cpkt)
        {
            //TODO: ADD HANDLER SO SUPPLY STONES TAKE EFFECT

            byte result = 0;
            uint skill = 0;

            try
            {
                Rag2Item Supplement = this.character.container[cpkt.IventoryId];
                Rag2Item Equipment = (cpkt.Container == 1) ? this.character.container[cpkt.ContainerSlot] : this.character.Equipment[cpkt.ContainerSlot];

                bool IsEquipmentItem = cpkt.Container != 1;

                if (Supplement == null || Equipment == null)
                {
                    result = (byte)Generalerror.ItemEnchantmentFailed;
                }
                else
                {
                    skill = Supplement.info.skill;

                    //If it is a equipment item and activated
                    //(active is set to 0 if durabillity is 0 or doesn't meet job criteria)
                    if (IsEquipmentItem && Equipment.active == 1)
                    {
                        uint oldskill = Equipment.Enchantments[cpkt.EnchantmentSlot];
                        if (oldskill > 0)
                        {
            #warning "Skill Deapplied"

                            Factory.Spells.Info info1;
                            Factory.Additions.Info info2;
                            if (skill > 0)
                            {
                                if (Singleton.SpellManager.TryGetSpell(oldskill, out info1)
                                && Singleton.Additions.TryGetAddition(info1.addition, out info2))
                                {
                                    info2.Do(character, character, AdditionContext.Deapplied);
                                }
                            }
                        }

                        if (skill > 0)
                        {
            #warning "Skill Applied"

                            Factory.Spells.Info info1;
                            Factory.Additions.Info info2;
                            if (skill > 0)
                            {
                                if (Singleton.SpellManager.TryGetSpell(skill, out info1)
                                && Singleton.Additions.TryGetAddition(info1.addition, out info2))
                                {
                                    info2.Do(character, character, AdditionContext.Applied);
                                }
                            }
                        }
                    }

                    Equipment.Enchantments[cpkt.EnchantmentSlot] = skill;

                    int newLength = Supplement.count - 1;
                    if (newLength > 0)
                    {
                        Supplement.count = newLength;
                        SMSG_UPDATEITEM spkt2 = new SMSG_UPDATEITEM();
                        spkt2.Amount = (byte)newLength;
                        spkt2.UpdateReason = 0;
                        spkt2.UpdateType = 4;
                        spkt2.Container = 2;
                        spkt2.SessionId = this.character.id;
                        spkt2.Index = cpkt.IventoryId;
                        this.Send((byte[])spkt2);
                    }
                    else
                    {
                        this.character.container.RemoveAt(cpkt.IventoryId);
                        SMSG_DELETEITEM spkt3 = new SMSG_DELETEITEM();
                        spkt3.UpdateReason = 0;
                        spkt3.Container = 2;
                        spkt3.Index = cpkt.IventoryId;
                        spkt3.SessionId = this.character.id;
                        this.Send((byte[])spkt3);
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                result = (byte)Generalerror.ItemEnchantmentFailed;
            }
            finally
            {
                SMSG_USESUPPLEMENTSTONE spkt = new SMSG_USESUPPLEMENTSTONE();
                spkt.Result = result;
                spkt.InventoryId = cpkt.IventoryId;
                spkt.Container = cpkt.Container;
                spkt.ContainerSlot = cpkt.ContainerSlot;
                spkt.EnchantmentSlot = cpkt.EnchantmentSlot;
                spkt.Skill = skill;
                spkt.SessionId = this.character.id;
                this.Send((byte[])spkt);
            }
        }
        private void CM_QUESTITEMSTART(CMSG_QUESTITEMSTART cpkt)
        {
            Rag2Item item = this.character.container[cpkt.Index];
            if (item == null) return;
            if (item.info.quest == 0) return;

            byte result = 1;
            if (Singleton.Database.IsQuestComplete(this.character, item.info.quest))
            {
                result = 1;
            }
            else if (this.character.QuestObjectives[item.info.quest] != null)
            {
                result = 2;
            }
            else
            {
                try
                {
                    QuestBase Quest;
                    if (Singleton.Quests.TryFindQuests(item.info.quest, out Quest) == false || Quest.OnStart(this.character.id) < 0)
                    {
                        result = 1;
                        QuestBase.InvalidateQuest(Quest, this.character);
                    }
                    else
                    {
                        result = 0;
                        int newLength = this.character.container[cpkt.Index].count - 1;
                        if (newLength > 0)
                        {
                            this.character.container[cpkt.Index].count = newLength;
                            SMSG_UPDATEITEM spkt2 = new SMSG_UPDATEITEM();
                            spkt2.Amount = (byte)newLength;
                            spkt2.UpdateReason = 8;
                            spkt2.UpdateType = 4;
                            spkt2.Container = 2;
                            spkt2.SessionId = this.character.id;
                            spkt2.Index = cpkt.Index;
                            this.Send((byte[])spkt2);
                        }
                        else
                        {
                            this.character.container.RemoveAt(cpkt.Index);
                            SMSG_DELETEITEM spkt3 = new SMSG_DELETEITEM();
                            spkt3.UpdateReason = 8;
                            spkt3.Container = 2;
                            spkt3.Index = cpkt.Index;
                            spkt3.SessionId = this.character.id;
                            this.Send((byte[])spkt3);
                        }

                        Quest.CheckQuest(this.character);
                    }
                }
                catch (Exception)
                {
                    Trace.TraceError("Error starting quest: {0}", item.info.quest);
                }
            }

            SMSG_USEQUESTITEM spkt = new SMSG_USEQUESTITEM();
            spkt.Index = cpkt.Index;
            spkt.Result = result;
            spkt.SessionId = this.character.id;
            this.Send((byte[])spkt);
        }
Beispiel #17
0
        /// <summary>
        /// Occurs when using a item that uses a skill
        /// </summary>
        /// <param name="cpkt"></param>
        private void CM_ITEMTOGGLE(CMSG_ITEMTOGLE cpkt)
        {
            lock (this.character.cooldowncollection)
            {
                try
                {
                    Rag2Item item = this.character.container[cpkt.Index];
                    MapObject target;
                    uint skillid = cpkt.SkillID;
                    byte skilltype = cpkt.SkillType;
                    ItemSkillUsageEventArgs argument = null;

                    bool cancast = Regiontree.TryFind(cpkt.TargetActor, this.character, out target)
                              && ItemSkillUsageEventArgs.Create(item, this.character, target, out argument)
                              && argument.SpellInfo.casttime > -1 && (argument.SpellInfo.casttime == 0 || this.character._lastcastedskill == skillid)
                              && ((long)((uint)Environment.TickCount) - this.character._lastcastedtick) > 0
                              && (argument.SpellInfo.delay == 0 || !this.character.cooldowncollection.IsCoolDown(skillid))
                              && (argument.SpellInfo.maximumrange == 0 || argument.SpellInfo.IsInRangeOf((int)(Vector.GetDistance2D(this.character.Position, target.Position))))
                              && argument.SpellInfo.requiredWeapons[this.character.weapons.GetCurrentWeaponType()] == 1
                              && this.character.jlvl > argument.SpellInfo.requiredJobs[this.character.job - 1]
                              && argument.SpellInfo.IsTarget(this.character, target)
                              && item.count > 0;

                    if (cancast && argument.Use())
                    {
                        int delay = (int)(argument.SpellInfo.delay - ((character.stats.Dexterity * 2) + (character.stats.Concentration * 2)));
                        if (delay > 0) this.character.cooldowncollection.Add(skillid, delay);
                        this.character.cooldowncollection.Update();

                        int newLength = this.character.container[cpkt.Index].count - 1;
                        if (newLength > 0)
                        {
                            this.character.container[cpkt.Index].count = newLength;
                            SMSG_UPDATEITEM spkt2 = new SMSG_UPDATEITEM();
                            spkt2.Amount = (byte)newLength;
                            spkt2.UpdateReason = 8;
                            spkt2.UpdateType = 4;
                            spkt2.Container = 2;
                            spkt2.SessionId = this.character.id;
                            spkt2.Index = cpkt.Index;
                            this.Send((byte[])spkt2);
                        }
                        else
                        {
                            this.character.container.RemoveAt(cpkt.Index);
                            SMSG_DELETEITEM spkt3 = new SMSG_DELETEITEM();
                            spkt3.UpdateReason = 8;
                            spkt3.Container = 2;
                            spkt3.Index = cpkt.Index;
                            spkt3.SessionId = this.character.id;
                            this.Send((byte[])spkt3);
                        }

                        //Preprocess packet
                        SMSG_ITEMTOGGLE spkt = new SMSG_ITEMTOGGLE();
                        spkt.Container = cpkt.Container;
                        spkt.SkillMessage = (byte)argument.Result;
                        spkt.Index = cpkt.Index;
                        spkt.SkillID = cpkt.SkillID;
                        spkt.SkillType = cpkt.SkillType;
                        spkt.SourceActor = this.character.id;
                        spkt.TargetActor = cpkt.TargetActor;
                        spkt.Value = argument.Damage;

                        //Send packets in one-mighty blow
                        Regiontree tree = this.character.currentzone.Regiontree;
                        foreach (Character regionObject in tree.SearchActors(this.character, SearchFlags.Characters))
                        {
                            if (character.client.isloaded == false || !Point.IsInSightRangeByRadius(this.character.Position, regionObject.Position)) continue;
                            spkt.SessionId = target.id;
                            regionObject.client.Send((byte[])spkt);
                        }
                    }
                }
                catch (Exception)
                {
                    Trace.TraceError("Error processing item skill");
                }
            }
        }