UnityGameProjectsCode / RelianceGame / AI Control / Friendly Scripts / AttackState.cs
AttackState.cs
Raw
using AIMachineTools;
using System;
using System.Collections;
using UnityEngine;

public class AttackState : State
{
    private static AttackState _instance; //only declared once

    private AttackState() //set instance to itself
    {
        if (_instance != null)
        {
            return;
        }

        _instance = this;
    }

    public static AttackState instance //creates the instance of the first state if it does not exist
    {
        get
        {
            if (_instance == null)
            {
                new AttackState();
            }

            return _instance;
        }
    }

    public override IEnumerator InState(AIMachine owner)
    {
        float timeWaitingToShoot = 0;
        float timeSinceFiring = 0;
        bool shotFired = false;
        bool movingCloserToEnemy = false;

        owner.RemoveMarker();

        while (owner.botMachine.currentState == AttackState.instance)
        {
            if (!owner.disabled)
            {
                if (owner.enemyObject == null)
                {
                    owner.canSeeEnemy = false;
                    owner.enemyHealth = null;

                    LeaveState(owner);
                    yield break;
                }
                else
                {
                    if (shotFired == true)
                    {
                        timeSinceFiring += Time.deltaTime;

                        if (!owner.animator.GetCurrentAnimatorStateInfo(0).IsName("BarrelLightFade"))
                        {
                            owner.laserLine.enabled = false;
                            owner.barrelLight.enabled = false;
                        }

                        if (timeSinceFiring >= owner.fireRate)
                        {
                            timeSinceFiring = 0.0f;
                            shotFired = false;
                        }
                    }

                    if (owner.additionalEnemies.Count >= 2 && owner.nearbyFriendlies.Count <= 1)
                    {
                        for (int i = 0; i < owner.friendlyBots.Count; i++)
                        {
                            if (Vector3.Distance(owner.friendlyBots[i].transform.position, owner.transform.position) <= owner.retreatRadius && Vector3.Distance(owner.friendlyBots[i].transform.position, owner.transform.position) >= 50)
                            {
                                owner.laserLine.enabled = false;
                                owner.barrelLight.enabled = false;

                                owner.botMachine.ChangeState(RetreatState.instance);
                                yield break;
                            }
                        }
                    }

                    int numberOfBotsCalled = 0;

                    for (int i = 0; i < owner.friendlyBots.Count; i++) //if there are any friendly bots within the reinforcementRadius, give them this bots target
                    {
                        if (Vector3.Distance(owner.transform.position, owner.friendlyBots[i].transform.position) <= owner.ReinforcementRadius)
                        {
                            if (owner.friendlyBots[i].GetComponent<AIMachine>().enemyObject == null) //if the current bot doesnt already have a target, set it
                            {
                                owner.friendlyBots[i].GetComponent<AIMachine>().enemyObject = owner.enemyObject;
                                owner.friendlyBots[i].GetComponent<AIMachine>().canSeeEnemy = true;
                                numberOfBotsCalled++;
                            }
                        }
                    }

                    if (numberOfBotsCalled != 0)
                    {
                        owner.logD.RecieveLog(owner.displayName + " called " + numberOfBotsCalled + " bot(s) for help!");
                        numberOfBotsCalled = 0;
                    }

                    if (movingCloserToEnemy == false)
                        owner.thisAgent.SetDestination(owner.transform.position);

                    if (Vector3.Distance(owner.transform.position, owner.enemyObject.transform.position) <= owner.attackDistance && owner.canSeeEnemy)
                    {
                        MoveTurret(owner, owner.enemyObject.GetComponentInChildren<HighlightObject>().gameObject.transform.position);

                        timeWaitingToShoot += Time.deltaTime;

                        if (timeWaitingToShoot >= 5f)
                        {
                            owner.thisAgent.SetDestination(owner.enemyObject.transform.position);
                            movingCloserToEnemy = true;

                            if (Vector3.Distance(owner.transform.position, owner.enemyObject.transform.position) <= 20 || owner.onTarget)
                            {
                                owner.thisAgent.SetDestination(owner.transform.position);
                                movingCloserToEnemy = false;
                            }
                        }

                        if (owner.onTarget == true)
                        {
                            timeWaitingToShoot = 0;

                            if (!shotFired)
                            {
                                timeSinceFiring = 0.0f;
                                shotFired = true;
                                Shoot(owner);
                            }

                            bool removing = false;

                            for (int i = 0; i < owner.friendlyBots.Count; i++)
                            {
                                if (owner.friendlyBots[i].GetComponent<AIMachine>().removingEnemy == true)
                                {
                                    removing = true;
                                    break;
                                }
                            }

                            if (removing == false)
                            {
                                if (owner.enemyObject != null)
                                {
                                    try
                                    {
                                        if (owner.enemyHealth.health <= 0)
                                        {
                                            owner.removingEnemy = true;
                                            OnEnemyDeath(owner);
                                        }
                                    }
                                    catch (Exception e)
                                    {
                                        Debug.LogError(e.StackTrace);
                                    }

                                }
                            }

                        }
                    }
                    else
                    {
                        LeaveState(owner);
                        yield break;
                    }
                }
            }
            else
            {
                owner.thisAgent.SetDestination(owner.transform.position);
            }

            yield return null;
        }
    }

    private void Shoot(AIMachine _owner)
    {
        _owner.soundMgr.StartMusicCouroutine();

        int randomHitChance = UnityEngine.Random.Range(0, 100);

        float pitchVariance = UnityEngine.Random.Range(0.80f, 1.20f);
        _owner.audioS.pitch = pitchVariance;
        _owner.audioS.PlayOneShot(_owner.GetComponent<MultipleAudioClips>().clips[1]);

        int randomLaserMat = UnityEngine.Random.Range(0, 5);
        _owner.laserLine.material = _owner.lasers[randomLaserMat];
        _owner.laserLine.SetPosition(0, _owner.barrelEnd.position);
        _owner.laserLine.SetPosition(1, _owner.contactPoint);
        _owner.laserLine.enabled = true;
        _owner.barrelLight.enabled = true;

        float adjustedAnimSpeed = 1;
        for (float i = 2f; i > _owner.fireRate; i -= 0.1f)
        {
            adjustedAnimSpeed += 0.01f;
        }

        _owner.animator.SetFloat("shootSpeed", adjustedAnimSpeed);

        _owner.animator.Play("BarrelLightFade", 0);
        _owner.animator.Play("BarrelMove", 2);
        _owner.animator.Play("LaserFade", 1);
        _owner.laserParticles.Play();

        if (randomHitChance <= _owner.hitChance && _owner.enemyObject != null)
        {
            _owner.CreateImpactParticles();

            int randomCritChance = UnityEngine.Random.Range(0, 100);
            int randomHeavyHitChance = UnityEngine.Random.Range(0, 100);

            _owner.enemyObject.GetComponent<AudioSource>().PlayOneShot(_owner.enemyObject.GetComponent<MultipleAudioClips>().clips[0]);

            if (randomCritChance <= _owner.critChance)
            {
                int damageAmt = 2;

                if (randomHeavyHitChance <= _owner.heavyHitChance)
                    damageAmt += _owner.heavyHitModifier;

                try
                {
                    _owner.enemyHealth.HealthReduce(damageAmt);
                }
                catch (Exception e)
                {
                    Debug.LogError(e.StackTrace);
                }

            }
            else
            {
                int damageAmt = 1;

                if (randomHeavyHitChance <= _owner.heavyHitChance)
                    damageAmt += _owner.heavyHitModifier;

                try
                {
                    _owner.enemyHealth.HealthReduce(damageAmt);
                }
                catch (Exception e)
                {
                    Debug.LogError(e.StackTrace);
                }
            }

            if (!_owner.enemyObject.GetComponent<StructureInfo>())
            {
                if (_owner.enemyObject.GetComponent<EnemyAIMachine>().enemyObject == null)
                {
                    _owner.enemyObject.GetComponent<EnemyAIMachine>().enemyObject = _owner.gameObject;
                    _owner.enemyObject.GetComponent<EnemyAIMachine>().canSeeEnemy = true;
                }
            }
        }
        else
        {
            _owner.logD.RecieveLog(_owner.displayName + " missed.");
        }
    }

    private void OnEnemyDeath(AIMachine _owner)
    {
        var tempEnemyHolder = _owner.enemyObject;

        _owner.enemyObject = null;
        _owner.canSeeEnemy = false;
        _owner.enemyHealth = null;

        if (tempEnemyHolder.GetComponent<StructureInfo>())
        {
            _owner.logD.RecieveLog(tempEnemyHolder.GetComponent<StructureInfo>().displayName + " was destroyed", Color.red);
            _owner.gameManager.OnStructureDestroy(tempEnemyHolder);
            tempEnemyHolder.SetActive(false);
            _owner.botStats.KillExpIncrease(tempEnemyHolder);
        }
        else
        {
            _owner.logD.RecieveLog(tempEnemyHolder.GetComponent<EnemyAIMachine>().displayName + " was destroyed", Color.red);
            tempEnemyHolder.SetActive(false);

            if (tempEnemyHolder.GetComponent<EnemyAIMachine>().turretBot)
                _owner.gameManager.OnTurretKill(tempEnemyHolder);
            else
                _owner.gameManager.OnKill(tempEnemyHolder);

            _owner.botStats.KillExpIncrease(tempEnemyHolder);
        }

        for (int i = 0; i < _owner.friendlyBots.Count; i++)
        {
            AIMachine targetBot = null;
            AIAllyMachine targetAlly = null;

            if (_owner.friendlyBots[i].GetComponent<BotStats>())
                targetBot = _owner.friendlyBots[i].GetComponent<AIMachine>();
            else
                targetAlly = _owner.friendlyBots[i].GetComponent<AIAllyMachine>();

            if (targetAlly == null)
            {
                if (targetBot.enemyObject == tempEnemyHolder && targetBot.gameObject.activeSelf == true)
                {
                    targetBot.enemyObject = null;
                    targetBot.enemyHealth = null;
                    targetBot.canSeeEnemy = false;

                    targetBot.laserLine.enabled = false;
                    targetBot.barrelLight.enabled = false;

                    var currentState = targetBot.botMachine.baseState;

                    if (currentState == SearchState.instance)
                        targetBot.botMachine.ChangeState(ChaseState.instance);
                    else if (currentState == CaptureAreaState.instance)
                        targetBot.botMachine.ChangeState(ChaseState.instance);
                    else if (currentState == FollowState.instance)
                        targetBot.botMachine.ChangeState(FollowState.instance);
                    else if (currentState == PartnerState.instance)
                        targetBot.botMachine.ChangeState(ChaseState.instance);
                    else if (currentState == MoveToState.instance)
                        targetBot.botMachine.ChangeState(ChaseState.instance);
                    else if (currentState == SentryState.instance)
                        targetBot.botMachine.ChangeState(SentryState.instance);
                }
            }
            else
            {
                if (targetAlly.enemyObject == tempEnemyHolder && targetAlly.gameObject.activeSelf == true)
                {
                    targetAlly.enemyObject = null;
                    targetAlly.enemyHealth = null;
                    targetAlly.canSeeEnemy = false;
                    targetAlly.laserLine.enabled = false;
                    targetAlly.barrelLight.enabled = false;

                    var currentState = targetAlly.botMachine.currentState;

                    if (currentState != AllyRetreatState.instance)
                        targetAlly.botMachine.ChangeState(AllyRetreatState.instance);
                }
            }
        }

        GameObject playerEnemy = _owner.playerObject.GetComponent<PlayerCallForHelp>().GetEnemy();

        if (playerEnemy == tempEnemyHolder)
            _owner.playerObject.GetComponent<PlayerCallForHelp>().SetEnemyNull();

        _owner.removingEnemy = false;
    }

    private void MoveTurret(AIMachine _owner, Vector3 hitPos)
    {
        Quaternion turretRot = Quaternion.LookRotation(hitPos - _owner.turretPos.transform.position);

        if (Vector3.Angle(_owner.turretPos.transform.forward, _owner.enemyObject.transform.position - _owner.turretPos.transform.position) > 5)
        {
            _owner.turretPos.transform.rotation = Quaternion.RotateTowards(_owner.turretPos.transform.rotation, turretRot, Time.deltaTime * _owner.turretRotateSpeed);

            _owner.turretPos.transform.localEulerAngles = new Vector3(0, _owner.turretPos.transform.localEulerAngles.y, 0);
        }

        _owner.barrelPos.transform.rotation = Quaternion.RotateTowards(_owner.barrelPos.transform.rotation, turretRot, Time.deltaTime * _owner.barrelMoveSpeed);

        _owner.barrelPos.transform.localEulerAngles = new Vector3(0, _owner.barrelPos.transform.localEulerAngles.y, 0);
    }

    private void LeaveState(AIMachine _owner)
    {
        _owner.laserLine.enabled = false;
        _owner.barrelLight.enabled = false;

        if (_owner.botMachine.baseState == SearchState.instance)
            _owner.botMachine.ChangeState(ChaseState.instance);
        else if (_owner.botMachine.baseState == CaptureAreaState.instance)
            _owner.botMachine.ChangeState(ChaseState.instance);
        else if (_owner.botMachine.baseState == FollowState.instance)
            _owner.botMachine.ChangeState(FollowState.instance);
        else if (_owner.botMachine.baseState == PartnerState.instance)
            _owner.botMachine.ChangeState(ChaseState.instance);
        else if (_owner.botMachine.baseState == MoveToState.instance)
            _owner.botMachine.ChangeState(ChaseState.instance);
        else if (_owner.botMachine.baseState == SentryState.instance)
            _owner.botMachine.ChangeState(SentryState.instance);
    }

}