Example #1
0
        public void NotifyCastSpell(INavGrid navGrid, ISpell s, float x, float y, float xDragEnd, float yDragEnd, uint futureProjNetId,
                                    uint spellNetId)
        {
            var response = new CastSpellResponse(navGrid, s, x, y, xDragEnd, yDragEnd, futureProjNetId, spellNetId);

            _packetHandlerManager.BroadcastPacket(response, Channel.CHL_S2C);
        }
 public CastSpellResponse(INavGrid navGrid, ISpell s, float x, float y, float xDragEnd, float yDragEnd, uint futureProjNetId, uint spellNetId)
     : base(PacketCmd.PKT_S2C_CAST_SPELL_ANS, s.Owner.NetId)
 {
     Write(Environment.TickCount); // syncID
     Write((byte)0);               // Unk
     Write((short)0x66);           // Buffer size from here
     Write((int)s.GetId());        // Spell hash, for example hash("EzrealMysticShot")
     Write((uint)spellNetId);      // Spell net ID
     Write((byte)(s.Level - 1));
     Write(1.0f);                  // attackSpeedMod
     WriteNetId(s.Owner);
     WriteNetId(s.Owner);
     Write((int)s.Owner.GetChampionHash());
     Write((uint)futureProjNetId); // The projectile ID that will be spawned
     Write((float)x);
     Write((float)navGrid.GetHeightAtLocation(x, y));
     Write((float)y);
     Write((float)xDragEnd);
     Write((float)navGrid.GetHeightAtLocation(xDragEnd, yDragEnd));
     Write((float)yDragEnd);
     Write((byte)0);                                              // numTargets (if >0, what follows is a list of {uint32 targetNetId, uint8 hitResult})
     Write((float)s.SpellData.GetCastTime());                     // designerCastTime
     Write(0.0f);                                                 // extraTimeForCast
     Write((float)s.SpellData.GetCastTime() /*+ s.ChannelTime*/); // designerTotalTime
     Write((float)s.GetCooldown());
     Write(0.0f);                                                 // startCastTime
     Write((byte)0);                                              // flags (isAutoAttack, secondAttack, forceCastingOrChannelling, mShouldOverrideCastPosition)
     Write((byte)s.Slot);
     Write((float)s.SpellData.ManaCost[s.Level]);
     Write((float)s.Owner.X);
     Write((float)s.Owner.GetZ());
     Write((float)s.Owner.Y);
     Write((long)1); // Unk
 }
Example #3
0
        public BeginAutoAttack(INavGrid navGrid, IAttackableUnit attacker, IAttackableUnit attacked, uint futureProjNetId, bool isCritical)
            : base(PacketCmd.PKT_S2C_BEGIN_AUTO_ATTACK, attacker.NetId)
        {
            WriteNetId(attacked);
            Write((byte)0x80);            // extraTime
            Write((uint)futureProjNetId); // Basic attack projectile ID, to be spawned later
            if (isCritical)
            {
                Write((byte)0x49); // attackSlot
            }
            else
            {
                Write((byte)0x40); // attackSlot
            }

            Write((byte)0x80); // not sure what this is, but it should be correct (or maybe attacked x z y?) - 4.18
            Write((byte)0x01);
            Write(MovementVector.TargetXToNormalFormat(navGrid, attacked.X));
            Write((byte)0x80);
            Write((byte)0x01);
            Write(MovementVector.TargetYToNormalFormat(navGrid, attacked.Y));
            Write((byte)0xCC);
            Write((byte)0x35);
            Write((byte)0xC4);
            Write((byte)0xD1);
            Write((float)attacker.X);
            Write((float)attacker.Y);
        }
Example #4
0
        public void NotifyCastSpell(INavGrid navGrid, ISpell s, Vector2 start, Vector2 end, uint futureProjNetId,
                                    uint spellNetId)
        {
            var response = new CastSpellResponse(navGrid, s, start.X, start.Y, end.X, end.Y, futureProjNetId, spellNetId);

            _packetHandlerManager.BroadcastPacket(response, Channel.CHL_S2C);
        }
Example #5
0
 public CastSpellResponse(INavGrid navGrid, ISpell s, Vector2 start, Vector2 end, uint futureProjNetId, uint spellNetId)
 {
     NavGrid         = navGrid;
     Spell           = s;
     Start           = start;
     End             = end;
     FutureProjNetId = futureProjNetId;
     SpellNetId      = spellNetId;
 }
Example #6
0
        public SpawnCampMonster(INavGrid navGrid, IMonster m)
            : base(PacketCmd.PKT_S2C_OBJECT_SPAWN, m.NetId)
        {
            Write((byte)0x79);
            Write((byte)0x01);
            Write((byte)0x77);
            Write((byte)0x01);

            Write((byte)0x63); // 0x63 (99) for jungle monster, 3 for minion
            WriteNetId(m);
            WriteNetId(m);
            Write((byte)0x40);
            Write(m.X);                                                 //x
            Write(m.GetZ());                                            //z
            Write(m.Y);                                                 //y
            Write(m.X);                                                 //x
            Write(m.GetZ());                                            //z
            Write(m.Y);                                                 //y
            Write(m.Facing.X);                                          //facing x
            Write(navGrid.GetHeightAtLocation(m.Facing.X, m.Facing.Y)); //facing z
            Write(m.Facing.Y);                                          //facing y

            WriteConstLengthString(m.Name, 64);

            WriteConstLengthString(m.Model, 64);

            WriteConstLengthString(m.Name, 64);

            WriteConstLengthString(m.SpawnAnimation, 64);

            Write((int)m.Team);          // Probably a short
            Fill(0, 12);                 // Unk
            Write((int)m.CampId);        // Camp id. Camp needs to exist
            Write(0);                    // Unk
            Write((int)m.CampUnk);
            Write(1);                    // Unk
            Write(m.SpawnAnimationTime); // After this many seconds, the camp icon appears in the minimap
            Write(1191.533936f);         // Unk
            Write(1);                    // Unk
            Fill(0, 40);                 // Unk
            Write(1.0f);                 // Unk
            Fill(0, 13);                 // Unk
            Write((byte)3);              //type 3=champ/jungle; 2=minion
            Write((byte)0xF1);           //<-|
            Write((byte)0xFB);           //  |-> Unk
            Write((byte)0x27);           //  |
            Write((byte)0x00);           //<-|
            Write(m.X);                  //x
            Write(m.Y);                  //y
            Write(-0.8589599f);          // rotation1 from -1 to 1
            Write(0.5120428f);           // rotation2 from -1 to 1
        }
Example #7
0
        public MovementResponse(INavGrid navGrid, List <IGameObject> actors)
            : base(PacketCmd.PKT_S2C_MOVE_ANS)
        {
            Write(Environment.TickCount); // syncID
            Write((short)actors.Count);

            foreach (var actor in actors)
            {
                var waypoints = actor.Waypoints;
                var numCoords = waypoints.Count * 2;
                Write((byte)numCoords);
                WriteNetId(actor);
                Write(Movement.EncodeWaypoints(navGrid, waypoints));
            }
        }
Example #8
0
        public SpawnMonster(INavGrid navGrid, IMonster m)
            : base(PacketCmd.PKT_S2C_OBJECT_SPAWN)
        {
            WriteNetId(m);
            Write((short)345);
            Write((short)343);

            Write((byte)0x63); // 0x63 (99) for jungle monster, 3 for minion
            WriteNetId(m);
            WriteNetId(m);
            Write((byte)0x40);
            Write(m.X);                                                 //x
            Write(m.GetZ());                                            //z
            Write(m.Y);                                                 //y
            Write(m.X);                                                 //x
            Write(m.GetZ());                                            //z
            Write(m.Y);                                                 //y
            Write(m.Facing.X);                                          //facing x
            Write(navGrid.GetHeightAtLocation(m.Facing.X, m.Facing.Y)); //facing z
            Write(m.Facing.Y);                                          //facing y

            WriteConstLengthString(m.Name, 64);

            WriteConstLengthString(m.Model, 64);

            WriteConstLengthString(m.Name, 64);

            Fill(0, 64);        // empty

            Write((int)m.Team); // Probably a short
            Fill(0, 12);
            Write(1);           //campId 1
            Write(100);
            Write(74);
            Write((long)1);
            Write(115.0066f);
            Write((byte)0);

            Fill(0, 11);
            Write(1.0f);        // Unk
            Fill(0, 13);
            Write((byte)3);     //type 3=champ/jungle; 2=minion
            Write(13337);
            Write(m.X);         //x
            Write(m.Y);         //y
            Write(-0.8589599f); // rotation1 from -1 to 1
            Write(0.5120428f);  //rotation2 from -1 to 1
        }
Example #9
0
        public SpawnParticle(INavGrid navGrid, IParticle particle)
            : base(PacketCmd.PKT_S2C_SPAWN_PARTICLE, particle.Owner.NetId)
        {
            Write((byte)1); // number of particles
            Write((uint)particle.Owner.GetChampionHash());
            WriteStringHash(particle.Name);
            Write(0x00000020); // flags ?

            Write((short)0);   // Unk
            WriteStringHash(particle.BoneName);

            Write((byte)1);       // number of targets ?
            WriteNetId(particle.Owner);
            WriteNetId(particle); // Particle net id ?
            WriteNetId(particle.Owner);

            if (particle.Target.IsSimpleTarget)
            {
                Write(0);
            }
            else
            {
                WriteNetId(particle.Target as IGameObject);
            }

            Write(0); // unk

            for (var i = 0; i < 3; ++i)
            {
                var ownerHeight    = navGrid.GetHeightAtLocation(particle.Owner.X, particle.Owner.Y);
                var particleHeight = navGrid.GetHeightAtLocation(particle.X, particle.Y);
                var higherValue    = Math.Max(ownerHeight, particleHeight);
                Write((short)((particle.Target.X - navGrid.MapWidth / 2) / 2));
                Write(higherValue);
                Write((short)((particle.Target.Y - navGrid.MapHeight / 2) / 2));
            }

            Write((uint)0);       // unk
            Write((uint)0);       // unk
            Write((uint)0);       // unk
            Write((uint)0);       // unk
            Write(particle.Size); // Particle size
        }
Example #10
0
        public EnterVisionAgain(INavGrid navGrid, IChampion c)
            : base(PacketCmd.PKT_S2C_OBJECT_SPAWN, c.NetId)
        {
            Write((short)0); // extraInfo
            Write((byte)0);  //c.getInventory().getItems().size(); // itemCount?
            //buffer.Write((short)7; // unknown

            /*
             * for (int i = 0; i < c.getInventory().getItems().size(); i++) {
             * ItemInstance* item = c.getInventory().getItems()[i];
             *
             * if (item != 0 && item.getTemplate() != 0) {
             *    buffer.Write((short)item.getStacks();
             *    buffer.Write((short)0; // unk
             *    buffer.Write((int)item.getTemplate().getId();
             *    buffer.Write((short)item.getSlot();
             * }
             * else {
             *    buffer.fill(0, 7);
             * }
             * }
             */

            Fill(0, 10);
            Write(1.0f);
            Fill(0, 13);

            Write((byte)2);               // Type of data: Waypoints=2
            Write(Environment.TickCount); // unk

            var waypoints = c.Waypoints;

            Write((byte)((waypoints.Count - c.CurWaypoint + 1) * 2)); // coordCount
            WriteNetId(c);
            Write((byte)0);                                           // movement mask; 1=KeepMoving?
            Write(MovementVector.TargetXToNormalFormat(navGrid, c.X));
            Write(MovementVector.TargetYToNormalFormat(navGrid, c.Y));
            for (var i = c.CurWaypoint; i < waypoints.Count; ++i)
            {
                Write(MovementVector.TargetXToNormalFormat(navGrid, waypoints[i].X));
                Write(MovementVector.TargetXToNormalFormat(navGrid, waypoints[i].Y));
            }
        }
Example #11
0
        public Dash(INavGrid navGrid,
                    IAttackableUnit u,
                    ITarget t,
                    float dashSpeed,
                    bool keepFacingLastDirection,
                    float leapHeight = 0.0f,
                    float followTargetMaxDistance = 0.0f,
                    float backDistance            = 0.0f,
                    float travelTime = 0.0f
                    ) : base(PacketCmd.PKT_S2C_DASH)
        {
            Write(Environment.TickCount); // syncID
            Write((short)1);              // Number of dashes
            Write((byte)4);               // Waypoints size * 2
            WriteNetId(u);
            Write(dashSpeed);
            Write(leapHeight);
            Write(u.X);
            Write(u.Y);
            Write((byte)(keepFacingLastDirection ? 0x01 : 0x00));
            if (t.IsSimpleTarget)
            {
                Write((uint)0);
            }
            else
            {
                WriteNetId(t as IGameObject);
            }

            Write(followTargetMaxDistance);
            Write(backDistance);
            Write(travelTime);

            var waypoints = new List <Vector2>
            {
                new Vector2(u.X, u.Y),
                new Vector2(t.X, t.Y)
            };

            Write(Movement.EncodeWaypoints(navGrid, waypoints));
        }
Example #12
0
        public EnterVisionAgain(INavGrid navGrid, IMinion m)
            : base(PacketCmd.PKT_S2C_OBJECT_SPAWN, m.NetId)
        {
            Fill(0, 13);
            Write(1.0f);
            Fill(0, 13);
            Write((byte)0x02);
            Write(Environment.TickCount); // unk

            var waypoints = m.Waypoints;

            Write((byte)((waypoints.Count - m.CurWaypoint + 1) * 2)); // coordCount
            WriteNetId(m);
            // TODO: Check if Movement.EncodeWaypoints is what we need to use here
            Write((byte)0); // movement mask
            Write(MovementVector.TargetXToNormalFormat(navGrid, m.X));
            Write(MovementVector.TargetYToNormalFormat(navGrid, m.Y));
            for (var i = m.CurWaypoint; i < waypoints.Count; i++)
            {
                Write(MovementVector.TargetXToNormalFormat(navGrid, waypoints[i].X));
                Write(MovementVector.TargetXToNormalFormat(navGrid, waypoints[i].Y));
            }
        }
Example #13
0
 public PacketNotifier(IPacketHandlerManager packetHandlerManager, INavGrid navGrid)
 {
     _packetHandlerManager = packetHandlerManager;
     _navGrid = navGrid;
 }
Example #14
0
        public static byte[] EncodeWaypoints(INavGrid navGrid, List <Vector2> waypoints)
        {
            var mapSize   = navGrid.GetSize();
            var numCoords = waypoints.Count * 2;

            var maskBytes    = new byte[(numCoords - 3) / 8 + 1];
            var tempStream   = new MemoryStream();
            var resultStream = new MemoryStream();
            var tempBuffer   = new BinaryWriter(tempStream);
            var resultBuffer = new BinaryWriter(resultStream);

            var lastCoord  = new Vector2();
            var coordinate = 0;

            foreach (var waypoint in waypoints)
            {
                var curVector = new Vector2((waypoint.X - mapSize.X) / 2, (waypoint.Y - mapSize.Y) / 2);
                if (coordinate == 0)
                {
                    tempBuffer.Write((short)curVector.X);
                    tempBuffer.Write((short)curVector.Y);
                }
                else
                {
                    var relative   = new Vector2(curVector.X - lastCoord.X, curVector.Y - lastCoord.Y);
                    var isAbsolute = IsAbsolute(relative);

                    if (isAbsolute.Item1)
                    {
                        tempBuffer.Write((short)curVector.X);
                    }
                    else
                    {
                        tempBuffer.Write((byte)relative.X);
                    }

                    if (isAbsolute.Item2)
                    {
                        tempBuffer.Write((short)curVector.Y);
                    }
                    else
                    {
                        tempBuffer.Write((byte)relative.Y);
                    }

                    SetBitmaskValue(ref maskBytes, coordinate - 2, !isAbsolute.Item1);
                    SetBitmaskValue(ref maskBytes, coordinate - 1, !isAbsolute.Item2);
                }
                lastCoord   = curVector;
                coordinate += 2;
            }

            if (numCoords > 2)
            {
                resultBuffer.Write(maskBytes);
            }

            resultBuffer.Write(tempStream.ToArray());

            return(resultStream.ToArray());
        }
Example #15
0
 public static void FindPath(INavGrid grid, IGridPoint start, IGridPoint destination)
 {
     AStar.FindPath(start, destination, (p1, p2) => (p1.X - p2.X) * (p1.X - p2.X) + (p1.Y - p2.Y) * (p1.Y - p2.Y), p => grid.getPassableNeighbours(p));
 }
Example #16
0
        public MinionSpawn(INavGrid navGrid, IMinion m)
            : base(PacketCmd.PKT_S2C_OBJECT_SPAWN, m.NetId)
        {
            Write((uint)0x00150017); // unk
            Write((byte)0x03);       // SpawnType - 3 = minion
            WriteNetId(m);
            WriteNetId(m);
            Write((uint)m.SpawnPosition);
            Write((byte)0xFF); // unk
            Write((byte)1);    // wave number ?

            Write((byte)m.MinionSpawnType);

            if (m.MinionSpawnType == MinionSpawnType.MINION_TYPE_MELEE)
            {
                Write((byte)0); // unk
            }
            else
            {
                Write((byte)1); // unk
            }

            Write((byte)0); // unk

            if (m.MinionSpawnType == MinionSpawnType.MINION_TYPE_CASTER)
            {
                Write(0x00010007); // unk
            }
            else if (m.MinionSpawnType == MinionSpawnType.MINION_TYPE_MELEE)
            {
                Write(0x0001000A); // unk
            }
            else if (m.MinionSpawnType == MinionSpawnType.MINION_TYPE_CANNON)
            {
                Write(0x0001000D);
            }
            else
            {
                Write(0x00010007);        // unk
            }
            Write(0x00000000);            // unk
            Write(0x00000000);            // unk
            Write((short)0x0000);         // unk
            Write(1.0f);                  // unk
            Write(0x00000000);            // unk
            Write(0x00000000);            // unk
            Write(0x00000000);            // unk
            Write((short)0x0200);         // unk
            Write(Environment.TickCount); // unk

            var waypoints = m.Waypoints;

            Write((byte)((waypoints.Count - m.CurWaypoint + 1) * 2)); // coordCount
            WriteNetId(m);
            Write((byte)0);                                           // movement mask
            Write(MovementVector.TargetXToNormalFormat(navGrid, m.X));
            Write(MovementVector.TargetYToNormalFormat(navGrid, m.Y));
            for (var i = m.CurWaypoint; i < waypoints.Count; ++i)
            {
                Write(MovementVector.TargetXToNormalFormat(navGrid, waypoints[i].X));
                Write(MovementVector.TargetXToNormalFormat(navGrid, waypoints[i].Y));
            }
        }
Example #17
0
 public static short TargetYToNormalFormat(INavGrid navGrid, float value)
 {
     return(FormatCoordinate(value, navGrid.MiddleOfMap.Y));
 }
Example #18
0
    public static Path <T> FindPath <T>(INavGrid <T> navGrid, T start, T destination, AccessibilityPredicate IsAccessible) where T : IEquatable <T>
    {
        Vector2Int startIndices       = navGrid.GetGridPosition(start);
        Vector2Int destinationIndices = navGrid.GetGridPosition(destination);

        if (!IsAccessible(startIndices.x, startIndices.y) || !IsAccessible(destinationIndices.x, destinationIndices.y))
        {
            return(null);
        }

        if (start.Equals(destination))
        {
            return(new Path <T>(start));
        }

        int length = navGrid.Length;
        int width  = navGrid.Width;

        bool[,] closedList = new bool[length, width];

        AStarTile <T>[,] tiles = new AStarTile <T> [length, width];

        for (int x = 0; x < length; x++)
        {
            for (int y = 0; y < width; y++)
            {
                tiles[x, y].indices  = new Vector2Int(x, y);
                tiles[x, y].previous = new Vector2Int(-1, -1);
                tiles[x, y].f        = float.MaxValue;
                tiles[x, y].g        = float.MaxValue;
                tiles[x, y].h        = float.MaxValue;
            }
        }

        FibonacciHeap <AStarTile <T> > openList = new FibonacciHeap <AStarTile <T> >();
        Dictionary <Vector2Int, FibonacciHeapNode <AStarTile <T> > > openListMap = new Dictionary <Vector2Int, FibonacciHeapNode <AStarTile <T> > >();

        tiles[startIndices.x, startIndices.y].indices  = startIndices;
        tiles[startIndices.x, startIndices.y].previous = startIndices;
        tiles[startIndices.x, startIndices.y].f        = 0;
        tiles[startIndices.x, startIndices.y].g        = 0;
        tiles[startIndices.x, startIndices.y].h        = 0;

        openListMap.Add(startIndices, openList.Push(tiles[startIndices.x, startIndices.y]));

        while (!openList.IsEmpty())
        {
            AStarTile <T> current = openList.Pop().Value;

            Vector2Int currentIndices = current.indices;
            int        x = currentIndices.x;
            int        y = currentIndices.y;

            closedList[x, y] = true;

            List <Vector2Int> adjacentGridPositions = navGrid.GetAdjacentGridPositions(x, y);
            for (int i = 0; i < adjacentGridPositions.Count; i++)
            {
                Vector2Int neighborIndices = adjacentGridPositions[i];

                int xi = neighborIndices.x;
                int yi = neighborIndices.y;

                if (neighborIndices == destinationIndices)
                {
                    tiles[xi, yi].previous = currentIndices;

                    LinkedList <T> wayPoints = new LinkedList <T>();

                    while (neighborIndices != startIndices)
                    {
                        wayPoints.AddFirst(navGrid.GetTile(neighborIndices));
                        neighborIndices = tiles[neighborIndices.x, neighborIndices.y].previous;
                    }

                    return(new Path <T>(start, wayPoints));
                }

                if (closedList[xi, yi] || !IsAccessible(xi, yi))
                {
                    continue;
                }

                float gNew = current.g + MathUtility.ManhattanDistance(xi, yi, x, y);
                float hNew = MathUtility.ManhattanDistance(xi, yi, destinationIndices.x, destinationIndices.y);
                float fNew = gNew + hNew;

                if (tiles[xi, yi].f < fNew)
                {
                    continue;
                }

                tiles[xi, yi].previous = currentIndices;
                tiles[xi, yi].g        = gNew;
                tiles[xi, yi].h        = hNew;
                tiles[xi, yi].f        = fNew;

                if (!openListMap.ContainsKey(neighborIndices))
                {
                    openListMap.Add(neighborIndices, openList.Push(tiles[xi, yi]));
                }
                else
                {
                    openList.Decrement(openListMap[neighborIndices], tiles[xi, yi]);
                }
            }
        }

        return(null);
    }
Example #19
0
 public MovementResponse(INavGrid navGrid, IGameObject obj)
     : this(navGrid, new List <IGameObject> {
     obj
 })
 {
 }
Example #20
0
        public SpawnProjectile(INavGrid navGrid, IProjectile p)
            : base(PacketCmd.PKT_S2C_SPAWN_PROJECTILE, p.NetId)
        {
            var targetZ = navGrid.GetHeightAtLocation(p.Target.X, p.Target.Y);

            Write(p.X);
            Write(p.GetZ() + 100.0f);
            Write(p.Y);
            Write(p.X);
            Write(p.GetZ());
            Write(p.Y);
            Write(-0.992436f);    // Rotation X
            Write(0);             // Rotation Z
            Write(-0.122766f);    // Rotation Y
            Write(-1984.871338f); // Unk
            Write(-166.666656f);  // Unk
            Write(-245.531418f);  // Unk
            Write(p.X);
            Write(p.GetZ() + 100.0f);
            Write(p.Y);
            Write(p.Target.X);
            Write(navGrid.GetHeightAtLocation(p.Target.X, p.Target.Y));
            Write(p.Target.Y);
            Write(p.X);
            Write(p.GetZ());
            Write(p.Y);
            Write(0);                // Unk ((float)castDelay ?)
            Write(p.GetMoveSpeed()); // Projectile speed
            Write(0);                // Unk
            Write(0);                // Unk
            Write(0x7f7fffff);       // Unk
            Write((byte)0);          // Unk
            if (!p.Target.IsSimpleTarget)
            {
                Write((short)0x6B); // Buffer size from here
            }
            else
            {
                Write((short)0x66); // Buffer size from here
            }
            Write(p.ProjectileId);  // projectile ID (hashed name)
            Write(0);               // Second net ID
            Write((byte)0);         // spellLevel
            Write(1.0f);            // attackSpeedMod
            WriteNetId(p.Owner);
            WriteNetId(p.Owner);

            if (p.Owner is IChampion c)
            {
                Write(c.GetChampionHash());
            }
            else
            {
                Write(0);
            }

            WriteNetId(p);
            Write(p.Target.X);
            Write(navGrid.GetHeightAtLocation(p.Target.X, p.Target.Y));
            Write(p.Target.Y);
            Write(p.Target.X);
            Write(navGrid.GetHeightAtLocation(p.Target.X, p.Target.Y) + 100.0f);
            Write(p.Target.Y);
            if (!p.Target.IsSimpleTarget)
            {
                Write((byte)0x01); // numTargets
                WriteNetId(p.Target as IAttackableUnit);
                Write((byte)0);    // hitResult
            }
            else
            {
                Write((byte)0); // numTargets
            }
            Write(1.0f);        // designerCastTime -- Doesn't seem to matter
            Write(0);           // extraTimeForCast -- Doesn't seem to matter
            Write(1.0f);        // designerTotalTime -- Doesn't seem to matter
            Write(0.0f);        // cooldown -- Doesn't seem to matter
            Write(0.0f);        // startCastTime -- Doesn't seem to matter
            Write((byte)0x00);  // flags?
            Write((byte)0x30);  // slot?
            Write(0.0f);        // manaCost?
            Write(p.X);
            Write(p.GetZ());
            Write(p.Y);
            Write(0); // Unk
            Write(0); // Unk
        }