public static void WriteCastInfo(this ByteWriter writerOrg, CastInfo data) { using (var writer = new ByteWriter()) { writer.WriteUInt32(data.SpellHash); writer.WriteUInt32(data.SpellNetID); writer.WriteByte(data.SpellLevel); writer.WriteFloat(data.AttackSpeedModifier); writer.WriteUInt32(data.CasterNetID); writer.WriteUInt32(data.SpellChainOwnerNetID); writer.WriteUInt32(data.PackageHash); writer.WriteUInt32(data.MissileNetID); writer.WriteVector3(data.TargetPosition); writer.WriteVector3(data.TargetPositionEnd); int targetCount = data.Targets.Count; if (targetCount > 32) { throw new IOException("CastInfo targets > 32!!!"); } writer.WriteByte((byte)targetCount); foreach (var target in data.Targets) { writer.WriteUInt32(target.UnitNetID); writer.WriteByte(target.HitResult); } writer.WriteFloat(data.DesignerCastTime); writer.WriteFloat(data.ExtraCastTime); writer.WriteFloat(data.DesignerTotalTime); writer.WriteFloat(data.Cooldown); writer.WriteFloat(data.StartCastTime); byte bitfield = 0; if (data.IsAutoAttack) { bitfield |= 1; } if (data.IsSecondAutoAttack) { bitfield |= 2; } if (data.IsForceCastingOrChannel) { bitfield |= 4; } if (data.IsOverrideCastPosition) { bitfield |= 8; } if (data.IsClickCasted) { bitfield |= 16; } writer.WriteByte(bitfield); writer.WriteByte(data.SpellSlot); writer.WriteFloat(data.ManaCost); writer.WriteVector3(data.SpellCastLaunchPosition); writer.WriteInt32(data.AmmoUsed); writer.WriteFloat(data.AmmoRechargeTime); var buffer = writer.GetBytes(); writerOrg.WriteUInt16((ushort)(buffer.Length + 2)); writerOrg.WriteBytes(buffer); } }