Esempio n. 1
0
 public void Update()
 {
     if (m_Balls.Any(b => b.InGame && b.Velocity.Module > 0))
     {
         var    newVelocities = new Dictionary <IBallInternal, NewVelocity>();
         double performed     = 0;
         while (performed < 1)
         {
             newVelocities.Clear();
             var    validBalls = m_Balls.Where(b => b.InGame);
             double step       = Math.Min(1 - performed, validBalls.Where(b => b.Velocity.Module > 0).Select(b => b?.BankDistance).Min() ?? double.PositiveInfinity);
             step = Math.Min(step, m_BallSteps.Where(kvp => kvp.Key.InGame).Min(kvp => kvp.Value.Step));
             foreach (IBallInternal b in validBalls)
             {
                 if (m_BallSteps.ContainsKey(b))
                 {
                     m_BallSteps[b].Update(step);
                 }
                 b.UpdatePosition(step);
                 newVelocities[b] = new NewVelocity(b.Velocity);
             }
             performed += step;
             foreach (var info in m_BallSteps.Where(kvp => kvp.Key.InGame).Where(kvp => kvp.Value.Step.ToleranceEqual(0)))
             {
                 HandleBallCollision(info.Key, info.Value, newVelocities);
             }
             foreach (var data in newVelocities.Where(kvp => kvp.Value.IsValid))
             {
                 data.Key.SetVelocity(data.Value.Value);
             }
             if (newVelocities.Any(kvp => kvp.Value.IsValid) || validBalls.Any(b => b.DirectionUpdated))
             {
                 ComputeSteps();
             }
         }
     }
 }
        public override void Behavior()
        {
            Player      player         = Main.player[projectile.owner];
            const float PlayerStayDist = 40f;

            projectile.ai[0] -= 1 / 60f;
            projectile.ai[1] -= 1 / 60f;

            /****************
            * Chase Player *
            ****************/
            Vector2 Direction = player.Center - projectile.Center;

            Direction.X -= PlayerStayDist * player.direction;
            Direction.Y -= 30f;

            Direction.Normalize();

            float   TargetDist   = Vector2.Distance(player.Center - new Vector2(PlayerStayDist * player.direction, 30f), projectile.Center);
            int     NewDirection = Main.player[projectile.owner].direction;
            Vector2 NewVelocity  = projectile.velocity;

            if (TypeOfAttack != 0 || projectile.ai[0] < 0.01f)
            {
                AUA      = false;
                atacking = false;
            }

            if (TypeOfAttack == 0)
            {
                /****************
                * Shoot to NPC *
                ****************/

                float   targetDist = viewEnemyDist * 6;
                Vector2 targetPos  = new Vector2(0f, 0f);

                Vector2 trgdir = new Vector2(NewDirection, 0);

                for (int k = 0; k < 200; k++)
                {
                    NPC npc = Main.npc[k];

                    if (npc.CanBeChasedBy(this, false))
                    {
                        float distance = Vector2.Distance(npc.Center, player.Center);

                        if ((distance < targetDist) && Collision.CanHitLine(projectile.position, projectile.width, projectile.height, npc.position, npc.width, npc.height))
                        {
                            targetDist = Vector2.Distance(npc.Center, projectile.Center);
                            trgdir     = npc.Center - projectile.Center;
                            trgdir.X   = Math.Sign(trgdir.X);
                            targetPos  = npc.Center;
                            AUA        = true;
                        }
                    }
                }

                if (AUA)
                {
                    if (targetPos == new Vector2(0f, 0f))
                    {
                        AUA = false;
                        projectile.ai[1] = 0f;
                    }
                    ///Direction = targetPos - projectile.Center;
                    ///Direction.Normalize;
                    NewDirection = Math.Sign(trgdir.X);

                    if (projectile.ai[0] < 0.01f || projectile.ai[1] > 0.01f)
                    {
                        if (projectile.ai[1] < 0.01f && projectile.ai[0] < 0.01f)
                        {
                            projectile.ai[1] = 1.09f;
                        }
                        else if (projectile.ai[1] % 0.1f < 1f / 60f)
                        {
                            ///StandoPlayer.Talk((projectile.ai[1] % 0.1f).ToString());
                            Vector2 D = targetPos - projectile.Center;
                            D.Normalize();

                            Vector2 ShootV = D * ShootVel;

                            ShootV = ShootV.RotatedByRandom(Math.PI / 12);

                            int proj = Projectile.NewProjectile(projectile.Center.X + NewDirection * projectile.Size.X * 0.2f, projectile.Center.Y - projectile.Size.Y * 0.2f, ShootV.X, ShootV.Y, Shoot, projectile.damage, projectile.knockBack, projectile.owner, 0f, 0f);
                            Main.projectile[proj].timeLeft  = 300;
                            Main.projectile[proj].netUpdate = true;
                        }

                        projectile.ai[0] = 2f;
                    }

                    atacking = true;
                }
            }
            else if (TypeOfAttack != 0)
            {
                /*************
                * Chase NPC *
                *************/
                float   targetDist = viewEnemyDist;
                Vector2 targetPos  = new Vector2(0f, 0f);

                Vector2 trgdir = new Vector2(NewDirection, 0);

                for (int k = 0; k < 200; k++)
                {
                    NPC npc = Main.npc[k];

                    if (npc.CanBeChasedBy(this, false))
                    {
                        float distance = Vector2.Distance(npc.Center, player.Center);

                        if ((distance < targetDist) /* && Collision.CanHitLine(projectile.position, projectile.width, projectile.height, npc.position, npc.width, npc.height)*/)
                        {
                            targetDist = Vector2.Distance(npc.Center, projectile.Center);
                            trgdir     = npc.Center - projectile.Center;
                            trgdir.Y   = 0f;
                            trgdir.X   = Math.Sign(trgdir.X);
                            targetPos  = npc.Center - trgdir * (npc.width + projectile.width) * 0.45f;
                            AUA        = true;
                        }
                    }
                }

                if (AUA)
                {
                    Direction = targetPos - projectile.Center;
                    Direction.Normalize();
                    NewDirection = Math.Sign(trgdir.X);

                    if (targetDist < projectile.width)
                    {
                        atacking = true;
                    }
                }
            }

            /*************************
            * Check Player distance *
            *************************/
            if (Vector2.Distance(player.Center, projectile.Center) > MaxDist)
            {
                Direction    = player.Center - projectile.Center;
                Direction.X -= 30f * player.direction;
                Direction.Y -= 30f;

                Direction.Normalize();

                AUA = atacking = false;
            }
            if (Vector2.Distance(player.Center, projectile.Center) > maxPlayerDist + 239)
            {
                projectile.position = player.Center - new Vector2(30f * player.direction, 30f);
                TargetDist          = 0;
                NewVelocity         = new Vector2(0, 0);
            }

            /***************************
            * Processing speed(wagon) *
            ***************************/
            if (TargetDist > 1f)
            {
                if (TargetDist > maxPlayerDist)
                {
                    NewVelocity = Direction * Math.Max(player.velocity.Length(), 5f);
                }
                else
                {
                    float temp = inertia * 0.5f;
                    NewVelocity = (projectile.velocity * temp + Direction * chasePlayerSpeed) / (temp + 1);
                }
            }
            else
            {
                NewVelocity *= 0.833333333f;
            }

            if (NewVelocity.HasNaNs())
            {
                NewVelocity = projectile.velocity;  // This is bug fix ^_^
            }
            if (projectile.velocity.Length() > maxSpeed)
            {
                projectile.velocity.Normalize();
                projectile.velocity *= 9;
            }

            projectile.direction       = NewDirection;
            projectile.spriteDirection = projectile.direction;
            projectile.velocity        = NewVelocity;
            SelectFrame();
            CreateDust();
            projectile.netUpdate = true;
        }