private Vector2 NextPosition()
        {
            if (rand == null)
            {
                rand = new Random((int)projectile.ai[1]);
            }
            const int    interval    = 60;
            int          arenaWidth  = PuritySpirit.arenaWidth;
            int          arenaHeight = PuritySpirit.arenaHeight;
            NPC          npc         = Main.npc[(int)projectile.ai[0]];
            PuritySpirit modNPC      = (PuritySpirit)npc.modNPC;
            Vector2      nextPos;

            if (projectile.localAI[0] > 300f)
            {
                nextPos = npc.Center;
            }
            else if ((int)projectile.localAI[0] % 100 == 0 || (Main.expertMode && (int)projectile.localAI[0] % 50 == 0))
            {
                int k = modNPC.targets[rand.Next(modNPC.targets.Count)];
                nextPos = Main.player[k].Center;
            }
            else if (rand.Next(5) == 0)
            {
                int k = modNPC.targets[rand.Next(modNPC.targets.Count)];
                nextPos = Main.player[k].Center + interval * new Vector2(Main.rand.Next(-5, 6), Main.rand.Next(-5, 6));
                if (nextPos.X < npc.Center.X - arenaWidth / 2)
                {
                    nextPos.X += arenaWidth;
                }
                else if (nextPos.X > npc.Center.X + arenaWidth / 2)
                {
                    nextPos.X -= arenaWidth;
                }
                if (nextPos.Y < npc.Center.Y - arenaHeight / 2)
                {
                    nextPos.Y += arenaHeight;
                }
                else if (nextPos.Y > npc.Center.Y + arenaHeight / 2)
                {
                    nextPos.Y -= arenaHeight;
                }
            }
            else
            {
                int leftBound  = (-arenaWidth / 2 + 40) / interval;
                int rightBound = (arenaWidth / 2 - 40) / interval + 1;
                int upperBound = (-arenaHeight / 2 + 40) / interval;
                int lowerBound = (arenaHeight / 2 - 40) / interval + 1;
                nextPos = npc.Center + interval * new Vector2(rand.Next(leftBound, rightBound), rand.Next(upperBound, lowerBound));
            }
            nextPos.X -= projectile.width / 2;
            nextPos.Y -= projectile.height / 2;
            return(nextPos);
        }
        private bool?CanBeHitByPlayer(Player player)
        {
            NPC          owner    = Main.npc[(int)npc.ai[0]];
            PuritySpirit modOwner = owner.modNPC == null ? null : owner.modNPC as PuritySpirit;

            if (modOwner != null && !modOwner.targets.Contains(player.whoAmI))
            {
                return(false);
            }
            return(null);
        }
        public override void AI()
        {
            NPC owner = Main.npc[(int)npc.ai[0]];

            if (!owner.active || owner.type != mod.NPCType("PuritySpirit"))
            {
                npc.active = false;
                return;
            }
            PuritySpirit modOwner = (PuritySpirit)owner.modNPC;

            if (npc.localAI[0] == 0f)
            {
                if (modOwner.targets.Contains(Main.myPlayer))
                {
                    Main.PlaySound(2, -1, -1, 2);
                }
                else
                {
                    Main.PlaySound(2, (int)npc.position.X, (int)npc.position.Y, 2);
                }
                npc.localAI[0] = 1f;
            }
            Vector2 targetPos = new Vector2(npc.ai[1], npc.ai[2]);
            Vector2 direction = targetPos - npc.Center;

            if (direction != Vector2.Zero)
            {
                float speed = direction.Length();
                if (speed > 2f)
                {
                    speed = 2f;
                }
                direction.Normalize();
                direction    *= speed;
                npc.position += direction;
            }
            else
            {
                npc.localAI[1] = 1f;
            }
        }
        public override void HandlePacket(BinaryReader reader, int whoAmI)
        {
            MessageType type = (MessageType)reader.ReadByte();

            if (type == MessageType.PuritySpirit)
            {
                PuritySpirit.PuritySpirit spirit = Main.npc[reader.ReadInt32()].modNPC as PuritySpirit.PuritySpirit;
                if (spirit != null && spirit.npc.active)
                {
                    spirit.HandlePacket(reader);
                }
            }
            else if (type == MessageType.HeroLives)
            {
                Player player = Main.player[reader.ReadInt32()];
                int    lives  = reader.ReadInt32();
                player.GetModPlayer <BluemagicPlayer>(this).heroLives = lives;
                if (lives > 0)
                {
                    NetworkText text;
                    if (lives == 1)
                    {
                        text = NetworkText.FromKey("Mods.Bluemagic.LifeLeft", player.name);
                    }
                    else
                    {
                        text = NetworkText.FromKey("Mods.Bluemagic.LivesLeft", player.name, lives);
                    }
                    NetMessage.BroadcastChatMessage(text, new Color(255, 25, 25));
                }
            }
            else if (type == MessageType.ChaosSpirit)
            {
                NPC npc = Main.npc[reader.ReadInt32()];
                if (npc.active)
                {
                    ChaosSpirit.ChaosSpirit spirit = npc.modNPC as ChaosSpirit.ChaosSpirit;
                    if (spirit != null)
                    {
                        spirit.HandlePacket(reader);
                    }
                    ChaosSpirit2 spirit2 = npc.modNPC as ChaosSpirit2;
                    if (spirit2 != null)
                    {
                        spirit2.HandlePacket(reader);
                    }
                    ChaosSpirit3 spirit3 = npc.modNPC as ChaosSpirit3;
                    if (spirit3 != null)
                    {
                        spirit3.HandlePacket(reader);
                    }
                }
            }
            else if (type == MessageType.PushChaosArm)
            {
                NPC     npc  = Main.npc[reader.ReadInt32()];
                Vector2 push = new Vector2(reader.ReadSingle(), reader.ReadSingle());
                if (npc.active)
                {
                    ChaosSpiritArm arm = npc.modNPC as ChaosSpiritArm;
                    if (arm != null)
                    {
                        arm.offset += push;
                        if (Main.netMode == 2)
                        {
                            ModPacket packet = GetPacket();
                            packet.Write((byte)MessageType.PushChaosArm);
                            packet.Write(push.X);
                            packet.Write(push.Y);
                            packet.Send(-1, whoAmI);
                        }
                    }
                }
            }
            else if (type == MessageType.TerraSpirit)
            {
                NPC npc = Main.npc[reader.ReadInt32()];
                if (npc.active)
                {
                    TerraSpirit.TerraSpirit spirit = npc.modNPC as TerraSpirit.TerraSpirit;
                    if (spirit != null)
                    {
                        spirit.HandlePacket(reader);
                    }
                }
            }
            else if (type == MessageType.TerraLives)
            {
                Player player = Main.player[reader.ReadInt32()];
                int    lives  = reader.ReadInt32();
                player.GetModPlayer <BluemagicPlayer>().terraLives = lives;
                if (lives > 0)
                {
                    NetworkText text;
                    if (lives == 1)
                    {
                        text = NetworkText.FromKey("Mods.Bluemagic.LifeLeft", player.name);
                    }
                    else
                    {
                        text = NetworkText.FromKey("Mods.Bluemagic.LivesLeft", player.name, lives);
                    }
                    NetMessage.BroadcastChatMessage(text, new Color(255, 25, 25));
                }
            }
            else if (type == MessageType.GoldBlob)
            {
                NPC   npc   = Main.npc[reader.ReadByte()];
                float value = reader.ReadByte();
                if (npc.active && npc.type == NPCType("GoldBlob"))
                {
                    npc.localAI[0] = value;
                }
            }
            else if (type == MessageType.ExtraLives)
            {
                BluemagicPlayer player = Main.player[Main.myPlayer].GetModPlayer <BluemagicPlayer>();
                if (player.terraLives > 0)
                {
                    player.terraLives += 3;
                }
            }
            else if (type == MessageType.BulletNegative)
            {
                NPC npc = Main.npc[reader.ReadByte()];
                if (npc.active && npc.type == NPCType("TerraSpirit2") && npc.modNPC is TerraSpirit2)
                {
                    var bullets = ((TerraSpirit2)npc.modNPC).bullets;
                    int count   = reader.ReadByte();
                    for (int k = 0; k < count; k++)
                    {
                        bullets.Add(new BulletNegative(reader.ReadVector2(), reader.ReadVector2()));
                    }
                }
            }
            else if (type == MessageType.CustomStats)
            {
                byte            byte1     = reader.ReadByte();
                byte            byte2     = reader.ReadByte();
                Player          player    = Main.player[byte1];
                BluemagicPlayer modPlayer = player.GetModPlayer <BluemagicPlayer>();
                CustomStats     stats     = byte2 == 0 ? modPlayer.chaosStats : modPlayer.cataclysmStats;
                stats.NetReceive(reader);
                if (Main.netMode == 2)
                {
                    ModPacket packet = GetPacket(512);
                    packet.Write(byte1);
                    packet.Write(byte2);
                    stats.NetSend(packet);
                    packet.Send(-1, whoAmI);
                }
            }
        }