/// <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;
 }
        /// <summary>
        /// Looses durabillity loss on defensive equipment
        /// </summary>
        /// <remarks>
        /// Durabillity loss on kro2 is calculated with a ratio of 50 : 1.
        /// Shield, Shirt, Pants, Shoes each durabillity loss it will rotate
        /// over the next equipment set.
        /// </remarks>
        public static void DoEquipment(Character target, uint damage)
        {
            if (target == null) return;
            bool canupdate = false;
            int NewDurabillity = 0;
            byte Slot = 0;

            target.TakenDamage += damage;
            while (target.TakenDamage > 50)
            {
                target.TakenDamage -= 50;

                switch (target.LastEquipmentDuraLoss)
                {
                    case 0:    //Shield
                        Rag2Item equip = target.Equipment[15];
                        if (equip == null || equip.active == 1 || equip.durabillty == 0) goto case 1;
                        Slot = 15;
                        equip.durabillty -= 1;
                        NewDurabillity = equip.durabillty;
                        target.LastEquipmentDuraLoss = 1;
                        canupdate = true;
                        break;

                    case 1:     //Shirt
                        Rag2Item shirt = target.Equipment[3];
                        if (shirt == null || shirt.active == 1 || shirt.durabillty == 0) goto case 2;
                        Slot = 3;
                        shirt.durabillty -= 1;
                        NewDurabillity = shirt.durabillty;
                        target.LastEquipmentDuraLoss = 2;
                        canupdate = true;
                        break;

                    case 2:     //Pants
                        Rag2Item pants = target.Equipment[4];
                        if (pants == null || pants.active == 1 || pants.durabillty == 0) goto case 3;
                        Slot = 4;
                        pants.durabillty -= 1;
                        NewDurabillity = pants.durabillty;
                        target.LastEquipmentDuraLoss = 3;
                        canupdate = true;
                        break;

                    case 3:     //Shoes
                        Rag2Item shoes = target.Equipment[5];
                        if (shoes == null || shoes.active == 1 || shoes.durabillty == 0) return;
                        Slot = 5;
                        shoes.durabillty -= 1;
                        NewDurabillity = shoes.durabillty;
                        target.LastEquipmentDuraLoss = 0;
                        canupdate = true;
                        break;
                }

                if (canupdate == true)
                {
                    SMSG_ITEMADJUST spkt = new SMSG_ITEMADJUST();
                    spkt.Container = 1;
                    spkt.Function = 3;
                    spkt.Slot = Slot;
                    spkt.SessionId = target.id;
                    spkt.Value = (uint)NewDurabillity;
                    target.client.Send((byte[])spkt);
                }
            }
        }
        /// <summary>
        /// Occurs when repairing equipment
        /// </summary>
        /// <param name="cpkt"></param>
        private void CM_REPAIREQUIPMENT(CMSG_REPAIRITEM cpkt)
        {
            bool HasBadIndex = false;
            double price = 0;
            int amount = cpkt.Amount;

            List<KeyValuePair<byte, byte>> list = new List<KeyValuePair<byte, byte>>();
            for (int i = 0; i < amount; i++)
            {
                //Read the equipment information
                byte index;
                byte container;
                cpkt.ReadEquipmentInfo(out index, out container);
                list.Add(new KeyValuePair<byte, byte>(container, index));

                // Item from weaponary
                if (container == 8)
                {
                    //CHECK IF WEAPON EXISTS
                    Weapon current = this.character.weapons[index];
                    if (current == null) { HasBadIndex = true; continue; }

                    //Compute the repair costs
                    float scalar = (float)(current.Info.max_durabillity - current._durabillity) / (float)current.Info.max_durabillity;
                    double costs = (double)(Singleton.experience.FindRepairCosts(current._weaponlevel) * scalar);

                    //Increment the repair costs
                    price += costs;
                }
                //Increment the repair costs
                else if (container == 1)
                {
                    //Check if equipment exists
                    Rag2Item current = this.character.Equipment[index];
                    if (current == null) { HasBadIndex = true; continue; }

                    //Compute the repair costs
                    double scalar = (double)(current.info.max_durability - current.durabillty) / (double)current.info.max_durability;
                    double costs = (double)
                            Rag2Item.CalculateRepairCosts(
                                 (double)current.info.price,
                                 (double)current.clvl,
                                 (double)current.info.max_durability
                            ) * scalar;

                    //Increment the repair costs
                    price += costs;
                }
                //Item from inventory
                else if (container == 2)
                {
                    //Check if equipment exists
                    Rag2Item current = this.character.container[index];
                    if (current == null) { HasBadIndex = true; continue; }

                    //Compute the repair costs
                    double scalar = (double)(current.info.max_durability - current.durabillty) / (double)current.info.max_durability;
                    double costs = (double)
                           Rag2Item.CalculateRepairCosts(
                                (double)current.info.price,
                                (double)current.clvl,
                                (double)current.info.max_durability
                           ) * scalar;

                    //Increment the repair costs
                    price += costs;
                }
            }

            price = Math.Ceiling(price);

            //Check if a bad index occured
            if (HasBadIndex)
            {
                Common.Errors.GeneralErrorMessage(
                    this.character,
                    (uint)Generalerror.WrongServerIndex
                );
            }
            //Check if our price is right
            uint aprice = (uint)price;
            if (this.character.ZENY >= aprice)
            {
                this.character.ZENY -= aprice;
                foreach (KeyValuePair<byte, byte> pair in list)
                {
                    // Item from weaponary
                    if (pair.Key == 8)
                    {
                        Weapon current = this.character.weapons[pair.Value];
                        if (current._durabillity == 0 &&
                            Common.Skills.HasRootSkillPresent(this.character, current.Info.weapon_skill))
                        {
                            current._active = 1;
                            SMSG_WEAPONADJUST spkt2 = new SMSG_WEAPONADJUST();
                            spkt2.SessionId = this.character.id;
                            spkt2.Function = 6;
                            spkt2.Value = 1;
                            spkt2.Slot = pair.Value;
                            this.Send((byte[])spkt2);
                        }

                        current._durabillity = (ushort)current.Info.max_durabillity;
                        SMSG_WEAPONADJUST spkt = new SMSG_WEAPONADJUST();
                        spkt.SessionId = this.character.id;
                        spkt.Function = 3;
                        spkt.Value = current.Info.max_durabillity;
                        spkt.Slot = pair.Value;
                        this.Send((byte[])spkt);
                    }
                    //Equipment
                    else if (pair.Key == 1)
                    {
                        Rag2Item current = this.character.Equipment[pair.Value];
                        if (current.durabillty == 0 && this.character.jlvl >= current.info.JobRequirement[this.character.job - 1])
                        {
                            current.active = 1;
                            SMSG_ITEMADJUST spkt2 = new SMSG_ITEMADJUST();
                            spkt2.Function = 5;
                            spkt2.Container = pair.Key;
                            spkt2.Slot = pair.Value;
                            spkt2.Value = 1;
                            spkt2.SessionId = this.character.id;
                            this.Send((byte[])spkt2);

            #warning "Equipment applied"
                            current.Activate(AdditionContext.Applied, this.character);
                        }

                        current.durabillty = (int)current.info.max_durability;
                        SMSG_ITEMADJUST spkt = new SMSG_ITEMADJUST();
                        spkt.Function = 3;
                        spkt.Container = pair.Key;
                        spkt.Slot = pair.Value;
                        spkt.Value = (uint)current.durabillty;
                        spkt.SessionId = this.character.id;
                        this.Send((byte[])spkt);
                    }
                    //Inventory
                    else if (pair.Key == 2)
                    {
                        Rag2Item current = this.character.container[pair.Value];
                        current.durabillty = (int)current.info.max_durability;

                        SMSG_ITEMADJUST spkt = new SMSG_ITEMADJUST();
                        spkt.Function = 3;
                        spkt.Container = pair.Key;
                        spkt.Slot = pair.Value;
                        spkt.Value = (uint)current.durabillty;
                        spkt.SessionId = this.character.id;
                        this.Send((byte[])spkt);
                    }
                }

                //Flush all pending updates
                LifeCycle.Update(this.character);

                //Update zeny
                CommonFunctions.UpdateZeny(
                    this.character
                );
            }
            else
            {
                Common.Errors.GeneralErrorMessage(
                    this.character,
                    (uint)Generalerror.NotEnoughMoneyToRepair
                );
            }
        }
        /// <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>
        /// 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
        }