Example #1
0
    public override void Update(AIShipController controller)
    {
        //call to set turret target
        SetTarget(attackObject);

        if (!attackObject.activeInHierarchy)
        {
            attackObject = null;
        }

        if (attackObject != null)
        {
            Debug.DrawLine(controller.Ship.transform.position, attackObject.transform.position);

            Vector3 direction = (attackObject.transform.position - controller.Ship.transform.position).normalized;
            float distance = Vector3.Distance(controller.Ship.transform.position, attackObject.transform.position);

            if (controller.engageType == AIShipController.EngageTypes.launch)
            {
                direction = (attackObject.transform.position - (controller.Ship.transform.position * controller.engageRange)).normalized;
            }

            if (distance < controller.engageRange)
            {
                if (controller.engageType == AIShipController.EngageTypes.pursue ||
                    controller.engageType == AIShipController.EngageTypes.launch)
                {
                    if (distance < 100)
                    {
                        controller.Flee(attackObject.transform.position);
                    }
                    else if (Vector3.Dot(controller.Ship.transform.forward, direction) < 0f)
                    {
                        //loop back on target after a certain distance away
                        controller.SetSpeed(controller.Ship.maxSpeed);
                        controller.SetHeading(controller.Ship.transform.forward); //keep flying straight
                    }
                }
                else if (controller.engageType == AIShipController.EngageTypes.stand)
                {
                    controller.SetSpeed(0);
                    controller.SetHeading(attackObject.transform.position - controller.Ship.transform.position);
                }
                else if (controller.engageType == AIShipController.EngageTypes.broadside)
                {
                    controller.SetSpeed(0);

                    if (Vector3.Dot(controller.Ship.transform.right, direction) < Vector3.Dot(-controller.Ship.transform.right, direction))
                    {
                        //turn left
                        controller.SetHeading(Vector3.Cross(controller.Ship.transform.up, direction));
                    }
                    else
                    {
                        //turn right
                        controller.SetHeading(Vector3.Cross(-controller.Ship.transform.up, direction));
                    }
                }
            }
            else
            {
                Vector3 position = attackObject.transform.position;

                if (controller.Ship.Weapons.Count > 0)
                {
                    position = controller.Ship.Weapons[0].GetLeadPosition(attackObject);
                }

                if (distance > controller.engageRange)
                {
                    position -= direction * controller.engageRange;

                    controller.MoveTowards(position);
                }
            }

            if (distance < controller.engageRange)
            {
                foreach (Weapon weapon in controller.Ship.Weapons)
                {
                    Ray ray = new Ray(weapon.transform.position, weapon.transform.forward);

                    if (weapon.CanFire() && weapon.ChanceToHit(attackObject) > 0.98f)
                    {
                        bool lineToTarget = true;

                        RaycastHit hit;
                        if (Physics.Raycast(ray, out hit, Vector3.Distance(controller.Ship.transform.position, attackObject.transform.position)))
                        {
                            if (hit.collider.tag != "Ship")
                            {
                                lineToTarget = false;
                            }
                            else
                            {
                                Ship ship = hit.collider.gameObject.GetComponent<Ship>();

                                if (ship.FactionID == controller.Ship.FactionID)
                                {
                                    //friendly ship in the way
                                    lineToTarget = false;
                                }
                            }
                        }

                        if (lineToTarget)
                        {
                            if (weapon is MissileLauncher)
                            {
                                MissileLauncher missileLauncher = (MissileLauncher)weapon;
                                missileLauncher.SetTarget(attackObject);
                            }

                            float accuracy = controller.accuracy;
                            Vector3 leadPosition = weapon.GetLeadPosition(attackObject);
                            Vector3 leadDirection = (leadPosition - weapon.transform.position).normalized;
                            Vector3 fireDirection = new Vector3(leadDirection.x + Random.Range(-accuracy, accuracy),
                                                                leadDirection.y + Random.Range(-accuracy, accuracy),
                                                                leadDirection.z);
                            fireDirection.Normalize();
                            Ray fireRay = new Ray(controller.Ship.transform.position, fireDirection);
                            weapon.FireAtAngle(fireRay);

                            AIShipController targetShipController = attackObject.GetComponent<AIShipController>();
                            if (targetShipController != null)
                            {
                                targetShipController.OnAttacked(controller.Ship);
                            }
                        }
                    }
                }
            }

            controller.Target = attackObject;
        }
        else
        {
             //allows the squadron state to set a new target
            controller.SetBehaviour(new IdleState());
        }
    }