/// <summary>
        /// Occurs when you switch between weapons (primary -> secondary)
        /// </summary>
        private void CM_WEAPONSWITCH(CMSG_WEAPONSWITCH cpkt)
        {
            //Helper variables
            byte prev_weapontype = 0;
            byte next_weapontype = 0;

            //Deapplies the currrent stats
            lock (this.character._status)
            {
                int WeaponIndex = (this.character.weapons.ActiveWeaponIndex == 1) ? this.character.weapons.SeconairyWeaponIndex : this.character.weapons.PrimaryWeaponIndex;
                if (WeaponIndex < this.character.weapons.UnlockedWeaponSlots)
                {
                    Weapon CurrentWeapon = this.character.weapons[WeaponIndex];
                    prev_weapontype = CurrentWeapon._weapontype;

                    if (CurrentWeapon != null && CurrentWeapon._active == 1)
                    {
                        //Deapplies the weapon stats
                        this.character._status.MaxWMAttack -= (ushort)CurrentWeapon.Info.max_magic_attack;
                        this.character._status.MinWMAttack -= (ushort)CurrentWeapon.Info.min_magic_attack;
                        this.character._status.MaxWPAttack -= (ushort)CurrentWeapon.Info.max_short_attack;
                        this.character._status.MinWPAttack -= (ushort)CurrentWeapon.Info.min_short_attack;
                        this.character._status.MaxWRAttack -= (ushort)CurrentWeapon.Info.max_range_attack;
                        this.character._status.MinWRAttack -= (ushort)CurrentWeapon.Info.min_range_attack;
                        this.character._status.Updates |= 2;

                        //Deapplies the fusion stone
                        if (CurrentWeapon._fusion > 0)
                            Common.Skills.DeleteStaticAddition(this.character, CurrentWeapon._fusion);

                        //Deapplies alterstone additions
                        for (int i = 0; i < 8; i++)
                        {
                            uint addition = CurrentWeapon.Slots[i];
                            if (addition > 0)
                            {
                                Singleton.Additions.DeapplyAddition(addition, character);
                            }
                        }
                    }
                }
            }

            //Toggles the weapons index
            this.character.weapons.ActiveWeaponIndex ^= 1;
            int ShieldIndex = (this.character.weapons.ActiveWeaponIndex == 1) ? 15 : 14;
            Rag2Item shield = this.character.Equipment[ShieldIndex];

            lock (this.character._status)
            {
                int NewWeaponIndex = (this.character.weapons.ActiveWeaponIndex == 1) ? this.character.weapons.SeconairyWeaponIndex : this.character.weapons.PrimaryWeaponIndex;
                if (NewWeaponIndex < this.character.weapons.UnlockedWeaponSlots)
                {
                    //Apples the battle stats
                    Weapon CurrentWeapon = this.character.weapons[NewWeaponIndex];
                    next_weapontype = CurrentWeapon._weapontype;

                    if (CurrentWeapon != null && CurrentWeapon._active == 1)
                    {
                        this.character._status.MaxWMAttack += (ushort)CurrentWeapon.Info.max_magic_attack;
                        this.character._status.MinWMAttack += (ushort)CurrentWeapon.Info.min_magic_attack;
                        this.character._status.MaxWPAttack += (ushort)CurrentWeapon.Info.max_short_attack;
                        this.character._status.MinWPAttack += (ushort)CurrentWeapon.Info.min_short_attack;
                        this.character._status.MaxWRAttack += (ushort)CurrentWeapon.Info.max_range_attack;
                        this.character._status.MinWRAttack += (ushort)CurrentWeapon.Info.min_range_attack;
                        this.character._status.Updates |= 2;
                    }

                    //Reapplies the fusion stone
                    if (CurrentWeapon._fusion > 0)
                        Common.Skills.CreateAddition(this.character, CurrentWeapon._fusion);

                    //Reapplies alterstone additions
                    for (int i = 0; i < 8; i++)
                    {
                        uint addition = CurrentWeapon.Slots[i];
                        if (addition > 0)
                        {
                            Singleton.Additions.DeapplyAddition(addition, character);
                        }
                    }
                }

                if (prev_weapontype != next_weapontype)
                {
                    foreach (Skill skill in this.character.learnedskills)
                    {
                        //If it's a pasive skill
                        if (skill.info.skilltype == 2)
                        {
                            bool PreviousAble = skill.info.requiredWeapons[prev_weapontype] == 1;
                            bool NextAble = skill.info.requiredWeapons[next_weapontype] == 1;

                            if (PreviousAble == false && NextAble == true)
                            {
                                Singleton.Additions.ApplyAddition(skill.info.addition, this.character);
                                this.character._status.Updates |= 2;
                            }
                            else if (NextAble == false && PreviousAble == true)
                            {
                                Singleton.Additions.DeapplyAddition(skill.info.addition, this.character);
                                this.character._status.Updates |= 2;
                            }
                        }
                    }
                }
            }

            //Switch the weapons
            Point oldPos = this.character.Position;
            Regiontree tree = this.character.currentzone.Regiontree;
            foreach (Character regionObject in tree.SearchActors(this.character, SearchFlags.Characters))
            {
                if (regionObject.id == this.character.id)
                {
                    SMSG_WEAPONSWITCH spkt = new SMSG_WEAPONSWITCH();
                    spkt.slotid = cpkt.slotid;
                    spkt.SessionId = this.character.id;
                    this.Send((byte[])spkt);
                }
                else if (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);

                    SMSG_CHANGEEQUIPMENT spkt2 = new SMSG_CHANGEEQUIPMENT();
                    spkt2.ActorID = this.character.id;
                    spkt2.Slot = (byte)ShieldIndex;
                    spkt2.ItemID = (shield != null) ? shield.info.item : 0;
                    spkt2.Dye = shield.dyecolor;
                    spkt2.SessionId = regionObject.id;
                    regionObject.client.Send((byte[])spkt2);
                }
            }

            //Does the switch
            Tasks.LifeCycle.Update(this.character);
        }
        /// <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>
        /// 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
            }
        }
Пример #4
0
        /// <summary>
        /// Requests to change the job.
        /// </summary>
        /// <param name="cpkt"></param>
        private void CM_CHARACTER_JOBCHANGE(CMSG_CHANGEJOB cpkt)
        {
            JobChangeCollection collection = this.character.Tag as JobChangeCollection;
            if (collection == null || !collection.IsJobAvailable(cpkt.Job))
            {
                //Job change failed
                SMSG_JOBCHANGED spkt = new SMSG_JOBCHANGED();
                spkt.Job = this.character.job;
                spkt.Result = 1;
                spkt.SessionId = this.character.id;
                spkt.SourceActor = this.character.id;
                this.Send((byte[])spkt);
                return;
            }
            else if (collection.GetJobTrasferFee(cpkt.Job) > this.character.ZENY)
            {
                //Not enough money
                Common.Errors.GeneralErrorMessage(this.character, (uint)Generalerror.NotEnoughMoney);

                SMSG_JOBCHANGED spkt = new SMSG_JOBCHANGED();
                spkt.Job = this.character.job;
                spkt.Result = 1;
                spkt.SessionId = this.character.id;
                spkt.SourceActor = this.character.id;
                this.Send((byte[])spkt);
                return;
            }
            else
            {
                this.character.ZENY -= collection.GetJobTrasferFee(cpkt.Job);
                CommonFunctions.UpdateZeny(this.character);
            }

            //Helper variables
            List<int> EnabledEquipment = new List<int>();
            List<int> DisabledEquipment = new List<int>();
            bool ChangeWeapon = cpkt.ChangeWeapon == 1;
            bool IsActiveWeapon = this.character.weapons.IsActiveSlot(cpkt.WeaponSlot);
            Weapon selectedWeapon = this.character.weapons[cpkt.WeaponSlot];

            #region Update Character Information

            lock (this.character)
            {
                //Change the job and joblevel
                int hpbefore = Singleton.CharacterConfiguration.CalculateMaximumHP(this.character);
                int spbefore = Singleton.CharacterConfiguration.CalculateMaximumSP(this.character);
                this.character.CharacterJobLevel[this.character.job] = this.character.jlvl;
                this.character.jlvl = this.character.CharacterJobLevel[cpkt.Job];
                this.character.job = cpkt.Job;
                this.character.Jexp = Singleton.experience.FindRequiredJexp(this.character.jlvl);
                int hpafter = Singleton.CharacterConfiguration.CalculateMaximumHP(this.character);
                int spafter = Singleton.CharacterConfiguration.CalculateMaximumSP(this.character);
                this.character._status.CurrentHp += (ushort)(hpbefore - hpafter);
                this.character._status.CurrentSp += (ushort)(spbefore - spafter);
                this.character._status.Updates |= 1;
            }

            #endregion Update Character Information

            #region Refresh Weapon

            //Deapply current weapon info
            if (ChangeWeapon && IsActiveWeapon && selectedWeapon != null)
            {
                BattleStatus status = this.character._status;
                status.MaxWMAttack -= (ushort)selectedWeapon.Info.max_magic_attack;
                status.MinWMAttack -= (ushort)selectedWeapon.Info.min_magic_attack;
                status.MaxWPAttack -= (ushort)selectedWeapon.Info.max_short_attack;
                status.MinWPAttack -= (ushort)selectedWeapon.Info.min_short_attack;
                status.MaxWRAttack -= (ushort)selectedWeapon.Info.max_range_attack;
                status.MinWRAttack -= (ushort)selectedWeapon.Info.min_range_attack;
                status.Updates |= 2;

                //Reapplies alterstone additions
                for (int i = 0; i < 8; i++)
                {
                    uint addition = selectedWeapon.Slots[i];
                    if (addition > 0)
                    {
                        Singleton.Additions.DeapplyAddition(addition, character);
                    }
                }
            }

            #endregion Refresh Weapon

            #region Refresh Weapon

            if (ChangeWeapon && selectedWeapon != null)
            {
                Singleton.Weapons.ChangeWeapon(cpkt.Job, cpkt.PostFix, selectedWeapon);
                SMSG_WEAPONCHANGE spkt = new SMSG_WEAPONCHANGE();
                spkt.Auge = selectedWeapon._augeskill;
                spkt.SessionId = this.character.id;
                spkt.Suffix = cpkt.PostFix;
                spkt.Index = cpkt.WeaponSlot;
                spkt.WeaponType = (byte)selectedWeapon._type;
                this.Send((byte[])spkt);
            }

            #endregion Refresh Weapon

            #region Refresh Skills

            {
                //Remove all skills
                foreach (Skill skill in this.character.learnedskills)
                {
                    //Remove the skill
                    SMSG_SKILLREMOVE spkt = new SMSG_SKILLREMOVE();
                    spkt.Unknown = skill.info.skilltype;
                    spkt.SessionId = this.character.id;
                    spkt.SkillId = skill.info.skillid;
                    this.Send((byte[])spkt);

                    //Save only experience if it's maxed-out.
                    Singleton.Database.UpdateSkill(this.character, skill.Id,
                        (skill.Experience == skill.info.maximumexperience) ? skill.info.maximumexperience : 0);

                    //Deapply passive skills
                    bool canUse = Singleton.SpellManager.CanUse(this.character, skill.info);
                    if (skill.info.skilltype == 2 && canUse)
                        Singleton.Additions.DeapplyAddition(skill.info.addition, character);
                }

                //Remove all learned skills in an instant
                this.character.learnedskills.Clear();
                Singleton.Database.LoadSkills(this.character);

                //Retrieve job speciafic skills
                foreach (Skill skill in this.character.learnedskills)
                {
                    //Add the skill
                    SMSG_SKILLADD spkt = new SMSG_SKILLADD();
                    spkt.SessionId = this.character.id;
                    spkt.SkillId = skill.info.skillid;
                    spkt.Slot = 0;
                    this.Send((byte[])spkt);

                    //Deapply passive skills
                    bool canUse = Singleton.SpellManager.CanUse(this.character, skill.info);
                    if (skill.info.skilltype == 2 && canUse)
                        Singleton.Additions.ApplyAddition(skill.info.addition, character);
                }
            }

            #endregion Refresh Skills

            #region Refresh Weapon

            //Apply current weapon info
            if (ChangeWeapon && IsActiveWeapon && selectedWeapon != null)
            {
                //Apply status
                BattleStatus status = this.character._status;
                status.MaxWMAttack += (ushort)selectedWeapon.Info.max_magic_attack;
                status.MinWMAttack += (ushort)selectedWeapon.Info.min_magic_attack;
                status.MaxWPAttack += (ushort)selectedWeapon.Info.max_short_attack;
                status.MinWPAttack += (ushort)selectedWeapon.Info.min_short_attack;
                status.MaxWRAttack += (ushort)selectedWeapon.Info.max_range_attack;
                status.MinWRAttack += (ushort)selectedWeapon.Info.min_range_attack;
                status.Updates |= 2;

                //Reapplies alterstone additions
                for (int i = 0; i < 8; i++)
                {
                    uint addition = selectedWeapon.Slots[i];
                    if (addition > 0)
                    {
                        Singleton.Additions.ApplyAddition(addition, character);
                    }
                }
            }

            #endregion Refresh Weapon

            #region Refresh Equipment

            {
                //Disable equipment
                for (int i = 0; i < 16; i++)
                {
                    //Verify if item exists
                    Rag2Item item = this.character.Equipment[i];
                    if (item == null || item.info == null) continue;

                    //Verify if the item changed states
                    bool Active = item.active == 1;
                    bool NewActive = this.character.jlvl >= item.info.JobRequirement[cpkt.Job - 1];
                    if (Active == NewActive) continue;
                    item.active = (byte)((NewActive == true) ? 1 : 0);

                    //Adjust the item
                    SMSG_ITEMADJUST spkt = new SMSG_ITEMADJUST();
                    spkt.Container = 1;
                    spkt.Function = 5;
                    spkt.Slot = (byte)i;
                    spkt.SessionId = this.character.id;
                    spkt.Value = item.active;
                    this.Send((byte[])spkt);

                    //Deapply additions
                    if (NewActive)
                    {
                        EnabledEquipment.Add(i);
                        Singleton.Additions.ApplyAddition(item.info.option_id, character);
                    }
                    else
                    {
                        DisabledEquipment.Add(i);
                        Singleton.Additions.DeapplyAddition(item.info.option_id, character);
                    }
                }

                //Update other stats
                //Common.Internal.CheckWeaponary(this.character);
                //CommonFunctions.UpdateCharacterInfo(this.character, 0);
                //CommonFunctions.SendBattleStatus(this.character);
            }

            #endregion Refresh Equipment

            #region Refresh Appereance

            {
                Regiontree tree = this.character.currentzone.Regiontree;
                foreach (Character regionObject in tree.SearchActors(SearchFlags.Characters))
                {
                    SMSG_JOBCHANGED spkt = new SMSG_JOBCHANGED();
                    spkt.SessionId = regionObject.id;
                    spkt.SourceActor = this.character.id;
                    spkt.Job = cpkt.Job;
                    regionObject.client.Send((byte[])spkt);

                    if (regionObject.id != this.character.id)
                    {
                        if (IsActiveWeapon)
                        {
                            uint auge = (character.FindRequiredRootSkill(selectedWeapon.Info.weapon_skill)) ? selectedWeapon._augeskill : 0;
                            SMSG_SHOWWEAPON spkt2 = new SMSG_SHOWWEAPON();
                            spkt2.ActorID = this.character.id;
                            spkt2.AugeID = auge;
                            spkt2.SessionId = regionObject.id;
                            regionObject.client.Send((byte[])spkt2);
                        }

                        foreach (byte i in EnabledEquipment)
                        {
                            Rag2Item item = this.character.Equipment[i];
                            SMSG_CHANGEEQUIPMENT spkt2 = new SMSG_CHANGEEQUIPMENT();
                            spkt2.SessionId = regionObject.id;
                            spkt2.ActorID = this.character.id;
                            spkt2.Slot = i;
                            spkt2.ItemID = item.info.item;
                            spkt2.Dye = item.dyecolor;
                            regionObject.client.Send((byte[])spkt2);
                        }

                        foreach (byte i in DisabledEquipment)
                        {
                            SMSG_CHANGEEQUIPMENT spkt2 = new SMSG_CHANGEEQUIPMENT();
                            spkt2.SessionId = regionObject.id;
                            spkt2.ActorID = this.character.id;
                            spkt2.Slot = i;
                            spkt2.ItemID = 0;
                            spkt2.Dye = 0;
                            regionObject.client.Send((byte[])spkt2);
                        }
                    }
                }
            }

            #endregion Refresh Appereance

            #region Refresh Party

            {
                //Process party members
                SMSG_PARTYMEMBERJOB spkt = new SMSG_PARTYMEMBERJOB();
                spkt.Job = cpkt.Job;
                spkt.SessionId = this.character.id;
                spkt.ActorId = this.character.id;
                spkt.Index = 1;

                SMSG_PARTYMEMBERJLVL spkt2 = new SMSG_PARTYMEMBERJLVL();
                spkt2.Jvl = this.character.jlvl;
                spkt2.ActorId = this.character.id;
                spkt2.Index = 1;

                if (this.character.sessionParty != null)
                {
                    foreach (Character target in this.character.sessionParty.GetCharacters())
                    {
                        //Send over Job change
                        spkt.SessionId = target.id;
                        target.client.Send((byte[])spkt);

                        //Send over jlvl change
                        spkt2.SessionId = target.id;
                        target.client.Send((byte[])spkt2);
                    }
                }
            }

            #endregion Refresh Party

            #region Refresh LifeCycle

            Tasks.LifeCycle.Update(this.character);

            #endregion Refresh LifeCycle
        }