Beispiel #1
0
        public override bool PreAI()
        {
            Player     owner = Main.player[projectile.owner];
            SoulPlayer sp    = owner.GetModPlayer <SoulPlayer>();

            if (owner.active && !owner.dead && sp.BlueSoulNet.soulNPC == NPCID.MotherSlime)
            {
                projectile.timeLeft = 2;
            }

            // A cooldown of 20 seconds (1200 ticks) - 1 second per soul stack (minimum of 720 ticks/12 seconds).
            float summonCooldown = 1260 - (60 * projectile.ai[0]);

            // Spawn a new mini slime.
            if (Main.myPlayer == projectile.owner && projectile.ai[1]++ >= summonCooldown)
            {
                int     damage   = (int)(20 + projectile.ai[0] * 2);
                Vector2 velocity = new Vector2(Main.rand.Next(7) - 3, -4);

                Projectile.NewProjectile(projectile.Center, velocity, ProjectileType <MiniSlimeProj>(), damage, .2f, owner.whoAmI);
                projectile.ai[1] = 0;
            }

            // Apply gravity.
            projectile.velocity.Y += .2f;

            // Animate projectile.
            if (projectile.frameCounter++ >= 10)
            {
                projectile.frameCounter = 0;
                projectile.frame        = (projectile.frame + 1) % Main.projFrames[projectile.type];
            }
            return(false);
        }
Beispiel #2
0
        public override bool SoulUpdate(Player p, short stack)
        {
            SoulPlayer sp = p.GetModPlayer <SoulPlayer>();

            sp.cyanBeetleSoul = !sp.cyanBeetleSoul;
            return(true);
        }
Beispiel #3
0
        public override bool SoulUpdate(Player p, short stack)
        {
            SoulPlayer sp = p.GetModPlayer <SoulPlayer>();

            sp.preHurtModifier += ModifyHit;
            return(true);
        }
Beispiel #4
0
        public override bool SoulUpdate(Player p, short stack)
        {
            SoulPlayer sp = p.GetModPlayer <SoulPlayer>();

            float modifier = .0025f;

            if (stack >= 3)
            {
                modifier += 0.0025f;
            }
            if (stack >= 6)
            {
                modifier += 0.0025f;
            }
            if (stack >= 9)
            {
                modifier += 0.0025f;
            }

            sp.soulDropModifier[0] += modifier;
            sp.soulDropModifier[1] += modifier;
            sp.soulDropModifier[2] += modifier;

            return(true);
        }
Beispiel #5
0
        public override void Update(GameTime gameTime)
        {
            SoulPlayer sp = Main.LocalPlayer.GetModPlayer <SoulPlayer>();

            soulSlots[0].SetSoulReference(sp.RedSoul, false);
            soulSlots[1].SetSoulReference(sp.BlueSoul, false);
            soulSlots[2].SetSoulReference(sp.YellowSoul, false);
        }
Beispiel #6
0
        public override void GrabRange(Item item, Player player, ref int grabRange)
        {
            SoulPlayer sp = Main.LocalPlayer.GetModPlayer <SoulPlayer>();

            if (sp.poltergeistSoul == true)
            {
                grabRange += sp.YellowSoulNet.stack * 3;
            }
        }
Beispiel #7
0
        private void SoulSlotRightClick(UIMouseEvent evt, UIElement e)
        {
            if (!(e is SoulIndexUISoulSlot slot) || slot.soulReference == null)
            {
                return;
            }

            SoulPlayer sp = Main.LocalPlayer.GetModPlayer <SoulPlayer>();

            sp.activeSouls[sp.activeSoulConfig, (int)slot.soulType].soulNPC = 0;
        }
        private void PresetButtonLeftClick(UIMouseEvent evt, UIElement e)
        {
            SoulPlayer sp = Main.LocalPlayer.GetModPlayer <SoulPlayer>();

            if (this.presetIndex >= sp.activeSouls.GetLength(0))
            {
                return;
            }

            sp.activeSoulConfig = this.presetIndex;
            sp.UpdateActiveSoulData();
        }
Beispiel #9
0
        /// <summary>
        /// Triggers on pickup. Checks if a corresponding soul exists and sets that soul as acquired.
        /// </summary>
        /// <param name="player">The player that interacts with this item.</param>
        /// <returns>Always returns false. This item is not actually added to the players' inventory.</returns>
        public override bool OnPickup(Player player)
        {
            SoulPlayer sp = player.GetModPlayer <SoulPlayer>();

            if (MysticHunter.Instance.SoulDict.TryGetValue(soulNPC, out BaseSoul soul))
            {
                Color c = Color.Red;
                if (soul.soulType == SoulType.Blue)
                {
                    c = Color.Blue;
                }
                else if (soul.soulType == SoulType.Yellow)
                {
                    c = Color.Yellow;
                }

                if (!sp.UnlockedSouls.ContainsKey(soulNPC))
                {
                    sp.UnlockedSouls.Add(soulNPC, 0);
                }

                if (!sp.HasMaxSouls(soulNPC))
                {
                    // Display a message in chat.
                    Main.NewText($"You collected your {numberList[sp.UnlockedSouls[soulNPC]]} {soul.SoulNPCName()} soul.", c);

                    // Increase the stack for this soul.
                    sp.UnlockedSouls[soulNPC]++;

                    // Update the local player soul data and UI.
                    sp.UpdateActiveSoulData();
                    SoulManager.ReloadSoulIndexUI();

                    // Emit a sound a particle effect.
                    Main.PlaySound(mod.GetLegacySoundSlot(SoundType.Custom, "Sounds/SoulPickup"), player.Center);
                    for (int i = 0; i < 5; ++i)
                    {
                        Dust d = Main.dust[Dust.NewDust(player.position, player.width, player.height, DustID.AncientLight, 0f, 0f, 255, c, Main.rand.Next(20, 26) * 0.1f)];
                        d.noLight   = true;
                        d.noGravity = true;
                        d.velocity *= 0.5f;
                    }
                }
            }
            else
            {
                // Debug message for when a soul with the given `soulDataID` cannot be found.
                Main.NewText("Soul with ID '" + soulNPC + "' cannot be found.");
            }

            return(false);
        }
Beispiel #10
0
        public override void AI()
        {
            Player     player = Main.player[projectile.owner];
            SoulPlayer sp     = player.GetModPlayer <SoulPlayer>();

            if (!player.dead && sp.BlueSoulNet.soulNPC == NPCID.ElfCopter)
            {
                projectile.timeLeft = 2;
            }

            if (Main.myPlayer == projectile.owner && shootTimer++ >= 120)
            {
                for (int i = 0; i < Main.maxNPCs; ++i)
                {
                    if (Main.npc[i].CanBeChasedBy(projectile) &&
                        Collision.CanHitLine(projectile.Center, 1, 1, Main.npc[i].Center, 1, 1))
                    {
                        Vector2 newProjVelocity = Vector2.Normalize(Main.npc[i].Center - projectile.Center) * 8;
                        Projectile.NewProjectile(projectile.Center, newProjVelocity, ProjectileID.Bullet, projectile.damage, 1f, projectile.owner);

                        shootTimer = -20;

                        return;
                    }
                }

                shootTimer = 0;
            }

            if (shootTimer < 0)
            {
                if (projectile.frameCounter++ >= 5)
                {
                    projectile.frame = (projectile.frame + 1) % Main.projFrames[projectile.type];
                }

                if (projectile.frame < 4)
                {
                    projectile.frame = 4;
                }
            }
            else
            {
                if (projectile.frame > 3)
                {
                    projectile.frame = 0;
                }
            }
        }
Beispiel #11
0
        private void SetSoulSlot(UIMouseEvent evt, UIElement e)
        {
            if (!(e is SoulIndexUISoulSlot slot))
            {
                return;
            }

            int        soulIndex = (int)slot.soulReference.soulType;
            SoulPlayer sp        = Main.LocalPlayer.GetModPlayer <SoulPlayer>();

            // TODO: Eldrazi - Maybe change the sound?
            Main.PlaySound(SoundID.Item37);
            sp.activeSouls[sp.activeSoulConfig, soulIndex].soulNPC = slot.soulReference.soulNPC;
            sp.UpdateActiveSoulData();
        }
Beispiel #12
0
        public override void PostUpdate(Player player)
        {
            SoulPlayer sp = player.GetModPlayer <SoulPlayer>();

            if (!sp.seaSnailSoul)
            {
                return;
            }

            player.statDefense += sp.BlueSoulNet.stack;
            player.thorns      += (.15f + .05f * sp.BlueSoulNet.stack);

            if (sp.seaSnailAnimationCounter < 24)
            {
                sp.seaSnailAnimationCounter++;
            }
        }
        public override bool PreAI()
        {
            Player     owner = Main.player[projectile.owner];
            SoulPlayer sp    = owner.GetModPlayer <SoulPlayer>();

            // Check to see if the NPC should still be alive.
            if (owner.active && !owner.dead && sp.BlueSoulNet.soulNPC == NPCID.GraniteFlyer)
            {
                projectile.timeLeft = 2;
            }

            if (projectile.localAI[1] == 0)
            {
                SpawnDust();
                projectile.localAI[1] = 1;
            }

            // Start calculating the correct position of the elemental.
            Vector2 newPos = owner.Center + new Vector2(0, 4);

            // We calculate the new position of the NPC based on its given index (npc.ai[1]) and a timer/counter which makes it rotate constantly (npc.ai[2]).
            newPos.X              += (float)Math.Cos((MathHelper.TwoPi / projectile.ai[1]) * projectile.ai[0] + projectile.localAI[0]) * 50;
            newPos.Y              += (float)Math.Sin((MathHelper.TwoPi / projectile.ai[1]) * projectile.ai[0] + projectile.localAI[0]) * 50;
            projectile.Center      = newPos;
            projectile.localAI[0] += .035f;

            // Hit check.
            if (owner.whoAmI == Main.myPlayer)
            {
                for (int i = 0; i < Main.maxProjectiles; ++i)
                {
                    if (Main.projectile[i].active && Main.projectile[i].hostile && projectile.Hitbox.Intersects(Main.projectile[i].Hitbox))
                    {
                        BlockProjectile(Main.projectile[i]);
                    }
                }
            }

            // Animation.
            if (projectile.frameCounter++ >= 6)
            {
                projectile.frame        = (projectile.frame + 1) % 12;
                projectile.frameCounter = 0;
            }
            return(false);
        }        //SoundID.NPCHit7
Beispiel #14
0
        public override void ExtractinatorUse(int extractType, ref int resultType, ref int resultStack)
        {
            SoulPlayer sp = Main.LocalPlayer.GetModPlayer <SoulPlayer>();

            if (sp.undeadMinerSoul)
            {
                int amount = 1;
                int stack  = sp.UnlockedSouls[sp.YellowSoul.soulNPC];

                if (stack >= 5)
                {
                    amount++;
                }
                if (stack >= 9)
                {
                    amount++;
                }

                resultStack += amount;
            }
        }
Beispiel #15
0
        public override void Action(CommandCaller caller, string input, string[] args)
        {
            if (args.Length < 1)
            {
                throw new UsageException("Must provide at least one argument.");
            }
            if (!short.TryParse(args[0], out short type))
            {
                throw new UsageException(args[0] + " is not an short.");
            }
            if (type > Main.maxNPCTypes)
            {
                throw new UsageException(args[0] + " is not a valid NPC type.");
            }

            byte stack;

            if (args.Length > 1)
            {
                if (!byte.TryParse(args[1], out stack))
                {
                    stack = 1;
                }
            }
            else
            {
                stack = 1;
            }

            SoulPlayer sp = Main.LocalPlayer.GetModPlayer <SoulPlayer>();

            if (sp.UnlockedSouls.ContainsKey(type))
            {
                if (sp.UnlockedSouls[type] < stack)
                {
                    stack = sp.UnlockedSouls[type];
                }
                sp.UnlockedSouls[type] -= stack;
            }
        }
Beispiel #16
0
        public override bool PreAI()
        {
            Player     owner = Main.player[projectile.owner];
            SoulPlayer sp    = owner.GetModPlayer <SoulPlayer>();

            if (owner.active && !owner.dead && sp.BlueSoulNet.soulNPC == NPCID.DeadlySphere)
            {
                projectile.timeLeft = 2;
            }

            float swarmAcceleration = 0.05f;

            for (int i = 0; i < Main.maxProjectiles; ++i)
            {
                bool isSame = Main.projectile[i].type == projectile.type;
                if (i != projectile.whoAmI && Main.projectile[i].active && Main.projectile[i].owner == projectile.owner && isSame &&
                    Math.Abs(projectile.position.X - Main.projectile[i].position.X) + Math.Abs(projectile.position.Y - Main.projectile[i].position.Y) < (float)projectile.width)
                {
                    if (projectile.position.X < Main.projectile[i].position.X)
                    {
                        projectile.velocity.X -= swarmAcceleration;
                    }
                    else
                    {
                        projectile.velocity.X += swarmAcceleration;
                    }
                    if (projectile.position.Y < Main.projectile[i].position.Y)
                    {
                        projectile.velocity.Y -= swarmAcceleration;
                    }
                    else
                    {
                        projectile.velocity.Y += swarmAcceleration;
                    }
                }
            }

            return(true);
        }
Beispiel #17
0
        public void ReloadList()
        {
            this.Clear();

            SoulPlayer sp = Main.LocalPlayer.GetModPlayer <SoulPlayer>();

            foreach (short key in sp.UnlockedSouls.Keys)
            {
                if (!MysticHunter.Instance.SoulDict.TryGetValue(key, out BaseSoul value) || value.soulType != filter)
                {
                    continue;
                }

                SoulIndexUISoulSlot newSoulSlot = new SoulIndexUISoulSlot(value);

                newSoulSlot.Width.Pixels = this.Width.Pixels / 2 - 12;

                newSoulSlot.OnClick     += SetSoulSlot;
                newSoulSlot.OnMouseOver += SetDescriptionPanelContent;
                newSoulSlot.OnMouseOut  += ResetDescriptionPanelContent;
                this.Add(newSoulSlot);
            }
        }
Beispiel #18
0
        public override bool PreAI()
        {
            Player     owner = Main.player[projectile.owner];
            SoulPlayer sp    = owner.GetModPlayer <SoulPlayer>();

            if (owner.active && !owner.dead && sp.BlueSoulNet.soulNPC == NPCID.StardustJellyfishBig)
            {
                projectile.timeLeft = 2;
            }

            for (int i = 0; i < Main.maxProjectiles; ++i)
            {
                if (Main.projectile[i].active && Main.projectile[i].owner == projectile.owner && Main.projectile[i].type == projectile.type)
                {
                    Vector2 directionToOther = projectile.Center - Main.projectile[i].Center;
                    if (directionToOther.HasNaNs() || directionToOther == Vector2.Zero)
                    {
                        directionToOther = -Vector2.UnitY;
                    }

                    if (directionToOther.Length() <= projectile.width * 2)
                    {
                        projectile.velocity += Vector2.Normalize(directionToOther) * 0.05f;
                    }
                }
            }

            if (projectile.ai[1] == 0)
            {
                projectile.ai[1] = 1;
                bodyParts        = new BodyPart[bodyLength];
                for (int i = 0; i < bodyParts.Length; ++i)
                {
                    bodyParts[i] = new BodyPart(projectile.position);
                }
            }
            else
            {
                Vector2 targetPosition = owner.Center;

                // Searching for a target.
                if (this.target == 255)
                {
                    float distance = maxTargetingDistance;
                    for (int i = 0; i < Main.maxNPCs; ++i)
                    {
                        if (Main.npc[i].CanBeChasedBy(projectile))
                        {
                            float d = Vector2.Distance(Main.npc[i].Center, owner.Center);
                            if (d <= distance)
                            {
                                target               = i;
                                distance             = d;
                                projectile.netUpdate = true;
                            }
                        }
                    }
                }
                else
                {
                    if (!Main.npc[target].active || Vector2.Distance(Main.npc[target].Center, owner.Center) > maxTargetingDistance * 2)
                    {
                        this.target = 255;
                    }
                    else
                    {
                        targetPosition = Main.npc[target].Center;
                    }
                }

                // Calculate desired velocity towards target.
                Vector2 projectileCenter = new Vector2((int)(projectile.Center.X / 16) * 16, (int)(projectile.Center.Y / 16) * 16);
                targetPosition = new Vector2((int)(targetPosition.X / 16) * 16, (int)(targetPosition.Y / 16) * 16);

                targetPosition = Vector2.Normalize(targetPosition - projectileCenter) * speed;
                if (this.target != 255)
                {
                    targetPosition *= 2;
                }
                else
                {
                    if ((projectile.position - owner.position).Length() >= 800)
                    {
                        DustEffect();
                        projectile.position = owner.Center + new Vector2(Main.rand.NextFloat(-1, 1) * 60, Main.rand.NextFloat(-1, 1) * 60);
                        DustEffect();
                    }
                }

                // Update velocity.
                if (Math.Sign(projectile.velocity.X) == Math.Sign(targetPosition.X) ||
                    Math.Sign(projectile.velocity.Y) == Math.Sign(targetPosition.Y))
                {
                    if (projectile.velocity.X < targetPosition.X)
                    {
                        projectile.velocity.X += acceleration;
                    }
                    else if (projectile.velocity.X > targetPosition.X)
                    {
                        projectile.velocity.X -= acceleration;
                    }

                    if (projectile.velocity.Y < targetPosition.Y)
                    {
                        projectile.velocity.Y += acceleration;
                    }
                    else if (projectile.velocity.Y > targetPosition.Y)
                    {
                        projectile.velocity.Y -= acceleration;
                    }

                    if (Math.Abs(targetPosition.Y) < speed * .2f && ((projectile.velocity.X > 0 && targetPosition.X < 0) || (projectile.velocity.X < 0 && targetPosition.X > 0)))
                    {
                        if (projectile.velocity.Y > 0)
                        {
                            projectile.velocity.Y += acceleration * 2f;
                        }
                        else
                        {
                            projectile.velocity.Y -= acceleration * 2;
                        }
                    }
                    if (Math.Abs(targetPosition.X) < speed * .2 && ((projectile.velocity.Y > 0 && targetPosition.Y < 0) || (projectile.velocity.Y < 0 && targetPosition.Y > 0)))
                    {
                        if (projectile.velocity.X > 0)
                        {
                            projectile.velocity.X += acceleration * .2f;
                        }
                        else
                        {
                            projectile.velocity.X -= acceleration * .2f;
                        }
                    }
                }
                else if (Math.Abs(targetPosition.X) > Math.Abs(targetPosition.Y))
                {
                    if (projectile.velocity.X < targetPosition.X)
                    {
                        projectile.velocity.X += acceleration * 1.1f;
                    }
                    else if (projectile.velocity.X > targetPosition.X)
                    {
                        projectile.velocity.X -= acceleration * 1.1f;
                    }

                    if (Math.Abs(projectile.velocity.X) + Math.Abs(projectile.velocity.Y) < speed * .5f)
                    {
                        if (projectile.velocity.Y > 0)
                        {
                            projectile.velocity.Y += acceleration;
                        }
                        else
                        {
                            projectile.velocity.Y -= acceleration;
                        }
                    }
                }
                else
                {
                    if (projectile.velocity.Y < targetPosition.Y)
                    {
                        projectile.velocity.Y += acceleration * 1.1f;
                    }
                    else if (projectile.velocity.Y > targetPosition.Y)
                    {
                        projectile.velocity.Y -= acceleration * 1.1f;
                    }

                    if (Math.Abs(projectile.velocity.X) + Math.Abs(projectile.velocity.Y) < speed * .5f)
                    {
                        if (projectile.velocity.X > 0)
                        {
                            projectile.velocity.X += acceleration;
                        }
                        else
                        {
                            projectile.velocity.X -= acceleration;
                        }
                    }
                }

                UpdateBodyParts();
            }

            projectile.rotation = projectile.velocity.ToRotation() + MathHelper.PiOver2;

            return(false);
        }
Beispiel #19
0
        public override void PostUpdate(Player player)
        {
            SoulPlayer sp = player.GetModPlayer <SoulPlayer>();

            if (sp.eocSoulDash && dashTime > 0)
            {
                Rectangle rectangle = new Rectangle((int)(player.position.X + player.velocity.X * 0.5 - 4.0), (int)(player.position.Y + player.velocity.Y * 0.5 - 4.0), player.width + 8, player.height + 8);

                for (int i = 0; i < Main.maxNPCs; ++i)
                {
                    NPC npc = Main.npc[i];
                    if (npc.active && !npc.dontTakeDamage && !npc.friendly)
                    {
                        Rectangle rect = npc.getRect();
                        if (rectangle.Intersects(rect) && (npc.noTileCollide || player.CanHit(npc)))
                        {
                            bool  crit      = false;
                            float knockback = 9f;
                            float damage    = (25 + 3 * sp.UnlockedSouls[this.soulNPC]) * player.meleeDamage;

                            if (player.kbGlove)
                            {
                                knockback *= 2;
                            }
                            if (player.kbBuff)
                            {
                                knockback *= 1.5f;
                            }

                            if (Main.rand.Next(100) < player.meleeCrit)
                            {
                                crit = true;
                            }

                            int dir = player.direction;
                            if (player.velocity.X < 0)
                            {
                                dir = -1;
                            }
                            if (player.velocity.X > 0)
                            {
                                dir = 1;
                            }

                            if (player.whoAmI == Main.myPlayer)
                            {
                                player.ApplyDamageToNPC(npc, (int)damage, knockback, dir, crit);
                            }

                            // Make sure the EoC shield dash doesn't stack.
                            player.eocDash       = 10;
                            player.dashDelay     = 30;
                            player.immune        = true;
                            player.immuneNoBlink = true;
                            player.immuneTime    = 4;
                        }
                    }
                }
            }

            if (dashTime > 0)
            {
                dashTime--;
                if (dashTime <= 0)
                {
                    player.GetModPlayer <SoulPlayer>().eocSoulDash = false;
                }
            }
        }
Beispiel #20
0
        public override bool PreAI()
        {
            Player     owner = Main.player[projectile.owner];
            SoulPlayer sp    = owner.GetModPlayer <SoulPlayer>();

            if (owner.active && !owner.dead && sp.BlueSoulNet.soulNPC == NPCID.SolarCrawltipedeHead)
            {
                projectile.timeLeft = 2;
            }

            // Projectile state management.
            float   maxSpeed       = .25f;
            Vector2 targetPosition = Vector2.Zero;

            // Projectile state: Idle.
            if (projectile.ai[0] == -1)
            {
                maxSpeed = 1;

                // Default position right above the player's head.
                targetPosition.X = owner.position.X + (owner.width / 2) * projectile.scale;
                targetPosition.Y = owner.position.Y - 20;

                if (++randomIdleRotationTimer >= 60)
                {
                    randomIdleRotationTimer = 0;
                    projectile.localAI[0]   = Main.rand.NextFloat(-MathHelper.PiOver4, MathHelper.PiOver4);
                }

                //projectile.rotation = (float)(owner.direction == -1 ? Math.PI : 0) - MathHelper.PiOver2;
                projectile.rotation = MathHelper.Lerp(projectile.rotation, (owner.direction == -1 ? MathHelper.Pi : 0) + projectile.localAI[0] - MathHelper.PiOver2, 0.05f);

                if (projectile.direction != -owner.direction)
                {
                    projectile.direction = -owner.direction;
                    projectile.rotation += MathHelper.Pi * projectile.direction;
                }

                // Projectile target acquisition.
                if (++projectile.ai[1] >= 120)
                {
                    for (int i = 0; i < Main.maxNPCs; ++i)
                    {
                        if (Main.npc[i].CanBeChasedBy(projectile) && Vector2.Distance(owner.Center, Main.npc[i].Center) <= TailLength)
                        {
                            projectile.ai[0]     = i;
                            projectile.ai[1]     = 0;
                            projectile.netUpdate = true;
                            break;
                        }
                    }
                }
            }
            // Projectile state: target acquired.
            else
            {
                // Check if target NPC is still alive and in-range.
                NPC target = Main.npc[(int)projectile.ai[0]];
                if (Main.myPlayer == projectile.owner && (!target.active || Vector2.Distance(owner.Center, target.Center) > TailLength))
                {
                    projectile.ai[0]     = -1;
                    projectile.netUpdate = true;
                    return(false);
                }

                targetPosition      = target.Center;
                projectile.rotation = (targetPosition - projectile.Center).ToRotation() - MathHelper.PiOver2;
            }

            // Teleport in case there's too much distance between projectile and owner.
            if (Vector2.Distance(projectile.Center, owner.Center) > TailLength * 1.5f)
            {
                Vector2 teleportDir = Vector2.Normalize(owner.Center - projectile.Center);
                projectile.Center    = owner.Center + teleportDir * (TailLength * .75f);
                projectile.netUpdate = true;
            }

            targetPosition     -= projectile.Center;
            targetPosition     *= (maxSpeed / TailLength) * targetPosition.Length();
            projectile.velocity = targetPosition;

            projectile.spriteDirection = -projectile.direction;

            return(false);
        }
        public override bool PreAI()
        {
            Player     owner = Main.player[projectile.owner];
            SoulPlayer sp    = owner.GetModPlayer <SoulPlayer>();

            // Check to see if the NPC should still be alive.
            if (owner.active && !owner.dead && sp.RedSoulNet.soulNPC != NPCID.EaterofSouls)
            {
                projectile.timeLeft = 2;
            }

            bool hasTarget = true;
            NPC  target    = Main.npc[targetIndex];

            if (!target.CanBeChasedBy() || Vector2.Distance(projectile.Center, target.Center) > maxTargetingDistance)
            {
                TargetClosestNPC();
                target = Main.npc[targetIndex];
                if (targetIndex == 0)
                {
                    hasTarget = false;
                }
            }

            Vector2 targetPosition = owner.Center;

            if (hasTarget)
            {
                targetPosition = target.Center;
            }

            // Calculate position relative to target and move accordingly.
            Vector2 direction = ((targetPosition / 8) * 8) - ((projectile.Center / 8) * 8);
            float   length    = direction.Length();

            // direction vector normalization with speed parameter.
            if (length != 0)
            {
                direction *= (speed / length);
            }

            // If the projectile does not have a target, make sure it can follow the player properly.
            if (!hasTarget && !Collision.CanHitLine(projectile.position, projectile.width, projectile.height, owner.position, owner.width, owner.height))
            {
                projectile.tileCollide = false;
            }
            // If it *does* have a target but is set to not collide with tiles, takes proper measurements.
            else if (projectile.tileCollide == false)
            {
                if (!Collision.SolidCollision(projectile.position, projectile.width, projectile.height))
                {
                    projectile.tileCollide = true;
                }
            }

            if (length > 100f)
            {
                if (projectile.ai[0]++ > 0f)
                {
                    projectile.velocity.Y += .023f;
                }
                else
                {
                    projectile.velocity.Y -= .023f;
                }
                if (projectile.ai[0] < -100f || projectile.ai[0] > 100f)
                {
                    projectile.velocity.X += .023f;
                }
                else
                {
                    projectile.velocity.X -= .023f;
                }

                if (projectile.ai[0] > 200f)
                {
                    projectile.ai[0] = -200f;
                }
            }
            if (length < 150f)
            {
                projectile.velocity.X += direction.X * .007f;
                projectile.velocity.Y += direction.Y * .007f;
            }

            // Set velocity accordingly.
            if (projectile.velocity.X < direction.X)
            {
                projectile.velocity.X += acceleration;
            }
            else if (projectile.velocity.X > direction.X)
            {
                projectile.velocity.X -= acceleration;
            }

            if (projectile.velocity.Y < direction.Y)
            {
                projectile.velocity.Y += acceleration;
            }
            else if (projectile.velocity.Y > direction.Y)
            {
                projectile.velocity.Y -= acceleration;
            }

            // Set the correct rotation for the projectile.
            projectile.rotation = (float)Math.Atan2(direction.Y, direction.X) - MathHelper.PiOver2;

            // Netupdate if the velocity has changed 'dramatically'.
            if ((projectile.velocity.X > 0f && projectile.oldVelocity.X < 0f) || (projectile.velocity.X < 0f && projectile.oldVelocity.X > 0f) || (projectile.velocity.Y > 0f && projectile.oldVelocity.Y < 0f) || (projectile.velocity.Y < 0f && projectile.oldVelocity.Y > 0f))
            {
                projectile.netUpdate = true;
            }

            // Spawn some fancy particles.
            if (Main.rand.Next(20) == 0)
            {
                Dust d = Main.dust[Dust.NewDust(new Vector2(projectile.position.X, projectile.position.Y + projectile.height * 0.25f),