예제 #1
0
    public override BehaviourSM.StateResponse Update(AIController controller)
    {
        Vector3 lookDirection = controller.target != null? controller.target.transform.position - controller.transform.position : controller.transform.forward;
        lookDirection.Normalize();

        // lerp towards the current look direction
        Vector3 currentFacing = controller.headTransform.up;
        controller.headTransform.up = Vector3.RotateTowards(currentFacing, lookDirection, controller.baseAimRotSpeed * Time.deltaTime, 0.0f);

        if(isBursting) {
            controller.SetCanMove(false);
        }
        else {
            controller.SetCanMove(true);
        }

        // Update the current weapon
        if(controller.MechComponent != null && controller.MechComponent.leftWeapon != null) {
            controller.MechComponent.leftWeapon.UpdateAIAttackState(controller);
        }

        bool hasLos = controller.HasLOSTarget();
        if(hasLos) {
            lastSawTargetTime = Time.time;
            lastKnownTargetPos = controller.target.transform.position;

            // move to new shooting position at random intervals
            if(Time.time - lastMoveTime > currentMoveInterval) {
                lastMoveTime = Time.time;
                currentMoveInterval = Random.Range(minMoveInterval, maxMoveInterval);

                float engagementRange = controller.GetAttackRange();

                // the ideal location is some distance away from target, slightly random direction offset though
                Vector3 offsetDirection = (lookDirection + (Vector3)Random.insideUnitCircle).normalized;
                Vector3 shootingPosition = controller.target.transform.position - offsetDirection * engagementRange;

                controller.SetMovetoTarget(shootingPosition);
            }
        }
        else {
            // If its run out of LOS, move towards the last known position of the target
            if(controller.target != null) {
                controller.SetMovetoTarget(controller.target.transform.position);
            }
        }

        // Handle firing at target
        AttackTarget(controller);

        // TRANSITIONS:
        // give up looking for target, go to previous state
        if(!hasLos && Time.time - lastSawTargetTime > attentionSpan ||controller.target == null) {
            controller.InterruptPath();
            return new BehaviourSM.StateResponse(BehaviourSM.TransitionMode.PopPrevious);
        }

        return new BehaviourSM.StateResponse(BehaviourSM.TransitionMode.NoChange);
    }
예제 #2
0
    private bool CanShootTarget(AIController controller)
    {
        // otherwise, check that there are no other mechs in the way
        Vector3 fireOrigin = GetWeaponOrigin(controller);

        // Some enemies do not shoot when they are not visible on screen
        if(controller.doesntShootOffScreen &&
           !WorldManager.instance.ObjectOnScreen(controller.gameObject)) {
            return false;
        }

        Vector3 toTarget = controller.target.transform.position - fireOrigin;
        float arcToTarget = Vector3.Dot(controller.headTransform.up, toTarget.normalized);

        // constrain the shooting to within an arc
        if(arcToTarget < maxFireArc || toTarget.magnitude > controller.GetAttackRange()) {
            return false;
        }

        if(!controller.CheckLOSFrom(fireOrigin, controller.target.transform.position, 100.0f)) {
            controller.OnLostSightOfTarget();
            return false;
        }
        else if(!controller.isTrackingTarget) {
            controller.OnAquireTarget();
        }

        // allow the weapon to decide if it can shoot yet, or if it is doing something
        if(controller.MechComponent != null && controller.MechComponent.leftWeapon != null &&
           !controller.MechComponent.leftWeapon.AI_AllowFire(controller)) {
               return false;
        }

        return true;
    }