Example #1
0
        public override void SendUpdatePlayerSkills()
        {
            if (m_gameClient.Player == null)
            {
                return;
            }

            // Get Skills as "Usable Skills" which are in network order ! (with forced update)
            List <Tuple <Skill, Skill> > usableSkills = m_gameClient.Player.GetAllUsableSkills(true);

            bool sent        = false;              // set to true once we can't send packet anymore !
            int  index       = 0;                  // index of our position in the list !
            int  total       = usableSkills.Count; // cache List count.
            int  packetCount = 0;                  // Number of packet sent for the entire list

            while (!sent)
            {
                int packetEntry = 0;                 // needed to tell client how much skill we send
                // using pak
                using (GSTCPPacketOut pak = new GSTCPPacketOut(GetPacketCode(eServerPackets.VariousUpdate)))
                {
                    // Write header
                    pak.WriteByte(0x01);                     //subcode for skill
                    pak.WriteByte((byte)0);                  //packet entries, can't know it for now...
                    pak.WriteByte((byte)0x03);               //subtype for following pages
                    pak.WriteByte((byte)index);              // packet first entry

                    // getting pak filled
                    while (index < total)
                    {
                        // this item will break the limit, send the packet before, keep index as is to continue !
                        if ((index >= byte.MaxValue) || ((pak.Length + 8 + usableSkills[index].Item1.Name.Length) > 1400))
                        {
                            break;
                        }

                        // Enter Packet Values !! Format Level - Type - SpecialField - Bonus - Icon - Name
                        Skill skill        = usableSkills[index].Item1;
                        Skill skillrelated = usableSkills[index].Item2;

                        if (skill is Specialization)
                        {
                            Specialization spec = (Specialization)skill;
                            pak.WriteByte((byte)spec.Level);
                            pak.WriteShort((ushort)spec.InternalID);                             //new 1.112
                            pak.WriteByte((byte)spec.SkillType);
                            pak.WriteShort(0);
                            pak.WriteByte((byte)(m_gameClient.Player.GetModifiedSpecLevel(spec.KeyName) - spec.Level));                             // bonus
                            pak.WriteShort((ushort)spec.Icon);
                            pak.WritePascalString(spec.Name);
                        }
                        else if (skill is Ability)
                        {
                            Ability ab = (Ability)skill;
                            pak.WriteByte((byte)ab.Level);
                            pak.WriteShort((ushort)ab.InternalID);                             //new 1.112
                            pak.WriteByte((byte)ab.SkillType);
                            pak.WriteShort(0);
                            pak.WriteByte((byte)0);
                            pak.WriteShort((ushort)ab.Icon);
                            pak.WritePascalString(ab.Name);
                        }
                        else if (skill is Spell)
                        {
                            Spell spell = (Spell)skill;
                            pak.WriteByte((byte)spell.Level);
                            pak.WriteShort((ushort)spell.InternalID);                             //new 1.112
                            pak.WriteByte((byte)spell.SkillType);

                            // spec index for this Spell - Special for Song and Unknown Indexes...
                            int spin = 0;
                            if (spell.SkillType == eSkillPage.Songs)
                            {
                                spin = 0xFF;
                            }
                            else
                            {
                                // find this line Specialization index !
                                if (skillrelated is SpellLine && !Util.IsEmpty(((SpellLine)skillrelated).Spec))
                                {
                                    spin = usableSkills.FindIndex(sk => (sk.Item1 is Specialization) && ((Specialization)sk.Item1).KeyName == ((SpellLine)skillrelated).Spec);

                                    if (spin == -1)
                                    {
                                        spin = 0xFE;
                                    }
                                }
                                else
                                {
                                    spin = 0xFE;
                                }
                            }

                            pak.WriteShort((ushort)spin);                                                 // special index for spellline
                            pak.WriteByte(0);                                                             // bonus
                            pak.WriteShort(spell.InternalIconID > 0 ? spell.InternalIconID : spell.Icon); // icon
                            pak.WritePascalString(spell.Name);
                        }
                        else if (skill is Style)
                        {
                            Style style = (Style)skill;
                            pak.WriteByte((byte)style.SpecLevelRequirement);
                            pak.WriteShort((ushort)style.InternalID);                             //new 1.112
                            pak.WriteByte((byte)style.SkillType);

                            // Special pre-requisite (First byte is Pre-requisite Icon / second Byte is prerequisite code...)
                            int pre = 0;

                            switch (style.OpeningRequirementType)
                            {
                            case Style.eOpening.Offensive:
                                pre = (int)style.AttackResultRequirement;                                         // last result of our attack against enemy hit, miss, target blocked, target parried, ...
                                if (style.AttackResultRequirement == Style.eAttackResultRequirement.Style)
                                {
                                    // get style requirement value... find prerequisite style index from specs beginning...
                                    int styleindex = Math.Max(0, usableSkills.FindIndex(it => (it.Item1 is Style) && it.Item1.ID == style.OpeningRequirementValue));
                                    int speccount  = Math.Max(0, usableSkills.FindIndex(it => (it.Item1 is Specialization) == false));
                                    pre |= ((byte)(100 + styleindex - speccount)) << 8;
                                }
                                break;

                            case Style.eOpening.Defensive:
                                pre = 100 + (int)style.AttackResultRequirement;                                         // last result of enemies attack against us hit, miss, you block, you parry, ...
                                break;

                            case Style.eOpening.Positional:
                                pre = 200 + style.OpeningRequirementValue;
                                break;
                            }

                            // style required?
                            if (pre == 0)
                            {
                                pre = 0x100;
                            }

                            pak.WriteShort((ushort)pre);
                            pak.WriteByte(GlobalConstants.GetSpecToInternalIndex(style.Spec));                             // index specialization in bonus...
                            pak.WriteShort((ushort)style.Icon);
                            pak.WritePascalString(style.Name);
                        }

                        packetEntry++;
                        index++;
                    }

                    // test if we finished sending packets
                    if (index >= total || index >= byte.MaxValue)
                    {
                        sent = true;
                    }

                    // rewrite header for count.
                    pak.Position = 4;
                    pak.WriteByte((byte)packetEntry);

                    if (!sent)
                    {
                        pak.WriteByte((byte)99);
                    }

                    SendTCP(pak);
                }

                packetCount++;
            }

            // Send List Cast Spells...
            SendNonHybridSpellLines();
            // clear trainer cache
            m_gameClient.TrainerSkillCache = null;

            if (ForceTooltipUpdate)
            {
                SendForceTooltipUpdate(usableSkills.Select(t => t.Item1));
            }
        }