public void Update()
    {
        // TODO: timers & member boolean variables to reduce checks each frame

        if (!useAbilities)
        {
            return;
        }

        if (timer > Time.time)
        {
            return;
        }
        timer = Time.time + interval;

        // Use abilities if needed
        if (!ai.movement.targetIsInRange())
        {
            if (ai.movement.DistanceToTarget > 5f)
            {
                bool allowSpeed = true;
                if (craft.faction == 0 && PlayerCore.Instance != null && !PlayerCore.Instance.GetIsDead() &&
                    ai.movement.GetTarget() != null)
                {
                    // Don't run away or get behind when escorting a player
                    float ownD    = ((Vector2)ai.movement.GetTarget() - (Vector2)craft.transform.position).sqrMagnitude;
                    float playerD = ((Vector2)ai.movement.GetTarget() - (Vector2)PlayerCore.Instance.transform.position).sqrMagnitude;
                    allowSpeed = playerD < ownD;
                }
                if (allowSpeed)
                {
                    var speeds = GetAbilities(1);
                    int half   = Mathf.CeilToInt(speeds.Count() / 2f);
                    int count  = 0;
                    foreach (var booster in speeds)
                    {
                        booster.Activate();
                        if (booster.GetActiveTimeRemaining() > 0)
                        {
                            if (++count >= half)
                            {
                                break;
                            }
                        }
                    }
                }
            }
        }
        if (craft.GetHealth()[0] < craft.GetMaxHealth()[0] * 0.8f)
        {
            var shellBoosts = GetAbilities(2, 17, 26, 29, 30, 31); // shell heal, shell regen, area restore
            foreach (var booster in shellBoosts)
            {
                if (craft.GetHealth()[0] > craft.GetMaxHealth()[0] * 0.9f)
                {
                    break;
                }
                booster.Activate();
            }
        }
        if (craft.GetHealth()[0] < craft.GetMaxHealth()[0] * 0.25f && Time.time > nextStealth)
        {
            var escapeAbilities = GetAbilities(24, 29, 27); // stealth, absorption, pin down
            foreach (var escapeAbility in escapeAbilities)
            {
                escapeAbility.Activate();
                if (escapeAbility.GetActiveTimeRemaining() > 0f)
                {
                    nextStealth = Time.time + escapeAbility.GetActiveTimeRemaining() + 1.0f;
                    break;
                }
            }
        }
        if (craft.GetHealth()[0] < craft.GetMaxHealth()[0] * 0.2f)
        {
            var retreats = GetAbilities(28); // retreat
            foreach (var retreat in retreats)
            {
                bool CD = retreat.TimeUntilReady() > 0f;
                if (!CD)
                {
                    retreat.Activate();
                    if (retreat.TimeUntilReady() > 0f)
                    {
                        break;
                    }
                }
            }
        }
        if (craft.GetHealth()[1] < craft.GetMaxHealth()[1] * 0.5f)
        {
            var core = GetAbilities(11, 31); // core heal & regen
            foreach (var ability in core)
            {
                ability.Activate();
                if (ability.GetActiveTimeRemaining() > 0)
                {
                    break;
                }
            }
        }
        if (craft.GetHealth()[2] < craft.GetMaxHealth()[2] * 0.5f)
        {
            var energy = GetAbilities(12, 32); // energy add & regen
            foreach (var ability in energy)
            {
                ability.Activate();
                if (ability.GetActiveTimeRemaining() > 0)
                {
                    break;
                }
            }
        }
        var target = craft.GetTargetingSystem().GetTarget();

        if (target != null && target)
        {
            Entity targetEntity = target.GetComponent <Entity>();
            if (targetEntity != null && targetEntity && !targetEntity.GetIsDead())
            {
                var damageBoosts = GetAbilities(25, 33); // damage boost, disrupt
                foreach (var damageBoost in damageBoosts)
                {
                    damageBoost.Activate();
                }
                // TODO: use only if the enemy is close enough!
                var pinDown = GetAbilities(27); // pin down
                if (Time.time > nextPin)
                {
                    foreach (var pin in pinDown)
                    {
                        if (pin.GetActiveTimeRemaining() <= 0)
                        {
                            pin.Activate();
                            if (pin.GetActiveTimeRemaining() > 0f)
                            {
                                nextPin = Time.time + pin.GetActiveTimeRemaining() - 1.5f; // 2 sec activation time, leave 0.5 sec for fleeing
                                break;
                            }
                        }
                    }
                }
            }
        }
        if (craft is IOwner && target != null && target)
        {
            IOwner owner = craft as IOwner;

            if (owner.GetUnitsCommanding().Count < owner.GetTotalCommandLimit())
            {
                var droneSpawns = GetAbilities(10); // drone spawn
                foreach (var droneSpawn in droneSpawns)
                {
                    droneSpawn.Activate();
                }
            }
        }
    }
Beispiel #2
0
    private void Update()
    {
        if (!craft.GetIsDead())
        {
            // find target
            Entity target = getNearestEntity <Entity>(craft.transform.position, craft.faction, true, craft.Terrain);
            craft.GetTargetingSystem().SetTarget(target ? target.transform : null);

            foreach (Ability a in craft.GetAbilities())
            {
                if (a)
                {
                    a.Tick(0);
                }
            }

            // shouldn't tick if dead or in cutscene, give control to the cutscene
            if (aggression != AIAggression.KeepMoving && aggroSearchTimer < Time.time && !DialogueSystem.isInCutscene)
            {
                // stop or follow target, give up if it's outside range
                if (target && (target.transform.position - craft.transform.position).sqrMagnitude < 800f)
                {
                    aggroTarget = target;
                    //Debug.Log("AggroTarget: " + aggroTarget.name + " Factions: " + aggroTarget.faction + " - " + craft.faction);
                }

                aggroSearchTimer = Time.time + 1f;
            }

            // shouldn't tick if dead or in cutscene, give control to the cutscene
            if (aggroTarget && !FactionManager.IsAllied(aggroTarget.faction, craft.faction) && !DialogueSystem.isInCutscene)
            {
                if (aggroTarget.GetIsDead() || aggroTarget.IsInvisible)
                {
                    aggroTarget      = null;
                    aggroSearchTimer = 0f;
                }
                else
                {
                    // if(craft as Drone && Input.GetKey(KeyCode.D)) Debug.Log(aggroTarget);
                    switch (aggression)
                    {
                    case AIAggression.FollowInRange:
                        var aggroPos = aggroTarget.transform.position;
                        if (timer >= 0.3F)
                        {
                            timer = 0;
                            movement.SetMoveTarget(aggroPos + new Vector3(Random.Range(-1F, 1F), Random.Range(-1F, 1F)), 9);
                        }
                        else
                        {
                            timer += Time.deltaTime;
                        }
                        float dist = movement.DistanceToTarget;
                        if (dist > 1000f)
                        {
                            aggroTarget = null;
                        }

                        if (module is FollowAI && (module as FollowAI).followTarget)
                        {
                            if (((module as FollowAI).followTarget.position - craft.transform.position).sqrMagnitude > 150f)
                            {
                                aggroTarget = null;
                            }
                        }

                        //// Stealth if module is not BattleAI to not interfere with it
                        //if (!(module is BattleAI) && craft.GetHealth()[0] < craft.GetMaxHealth()[0] * 0.25f)
                        //{
                        //    var abilities = craft.GetAbilities();
                        //    if(abilities != null)
                        //    {
                        //        var stealths = abilities.Where((x) => { return (x != null) && x.GetID() == 24; });
                        //        foreach (var stealth in stealths)
                        //        {
                        //            stealth.Tick("activate");
                        //            if (stealth.GetActiveTimeRemaining() > 0)
                        //                break;
                        //        }
                        //    }
                        //}
                        break;

                    case AIAggression.StopToAttack:
                        movement.SetMoveTarget(craft.transform.position);
                        break;

                    case AIAggression.KeepMoving:
                        // Back to module's movement
                        aggroTarget = null;
                        break;

                    default:
                        break;
                    }
                }
            }
            else
            {
                aggroTarget      = null;
                aggroSearchTimer = 0f;
            }

            if (module != null)
            {
                if (state == AIState.Active)
                {
                    module.StateTick();

                    if (aggroTarget == null)
                    {
                        module.ActionTick();
                    }
                    if (allowRetreat)
                    {
                        // check if retreat necessary
                        if (craft.GetHealth()[0] < retreatTreshold * craft.GetMaxHealth()[0])
                        {
                            state = AIState.Retreating;
                            //Debug.Log(craft.name + "[ " + craft.faction + " ] retreating!");
                        }
                    }
                }
                else if (state == AIState.Retreating)
                {
                    if ((!retreatTargetFound && retreatSearchTimer < Time.time) || retreatSearchTimer < Time.time)
                    {
                        Entity enemy = getNearestEntity <Entity>(craft.transform.position, craft.faction, true, Entity.TerrainType.All);
                        if (enemy && (enemy.transform.position - craft.transform.position).sqrMagnitude < 1600f)
                        {
                            retreatTarget = craft.transform.position + (craft.transform.position - enemy.transform.position).normalized * 20f;

                            //Debug.Log(craft.name + "[ " + craft.faction + " ] Initial retreat target : " + retreatTarget);

                            IntRect bounds = SectorManager.instance.current.bounds;
                            if (!bounds.contains(retreatTarget))
                            {
                                retreatTarget = craft.spawnPoint;
                                //Debug.Log(craft.name + "[ " + craft.faction + " ] Updated to Spawn point : " + retreatTarget);
                            }

                            // stay inside sector (just in case the spawn point is outside)
                            if (retreatTarget.x > bounds.x + bounds.w)
                            {
                                retreatTarget = new Vector2(bounds.x + bounds.w, retreatTarget.y);
                            }
                            if (retreatTarget.x < bounds.x)
                            {
                                retreatTarget = new Vector2(bounds.x, retreatTarget.y);
                            }
                            if (retreatTarget.y < bounds.y - bounds.h)
                            {
                                retreatTarget = new Vector2(retreatTarget.x, bounds.y - bounds.h);
                            }
                            if (retreatTarget.y > bounds.y)
                            {
                                retreatTarget = new Vector2(retreatTarget.x, bounds.y);
                            }

                            retreatTargetFound = true;
                            //Debug.Log(craft.name + "[ " + craft.faction + " ] Sector bounds: " + bounds.x + ", " + bounds.y + ", " + bounds.w + ", " + bounds.h);
                            //Debug.Log(craft.name + "[ " + craft.faction + " ] Found a retreat target! : " + retreatTarget);
                        }
                        else
                        {
                            retreatTarget      = craft.spawnPoint;
                            retreatTargetFound = true;
                        }
                        retreatSearchTimer = Time.time + 3.0f;
                    }
                    else if (retreatTargetFound)
                    {
                        movement.SetMoveTarget(retreatTarget);
                        if (movement.targetIsInRange() && retreatTarget != (Vector2)craft.spawnPoint)
                        {
                            retreatSearchTimer = 0f;
                        }
                    }
                    else
                    {
                        movement.SetMoveTarget(craft.spawnPoint);
                    }
                    // check if retreating is still necessary
                    if (craft.GetHealth()[0] > retreatTreshold * craft.GetMaxHealth()[0])
                    {
                        state = AIState.Active;
                        //Debug.Log(craft.name + "[ " + craft.faction + " ] stopped retreating!");
                    }
                }
                else
                {
                    if (state == AIState.Inactive)
                    {
                        module.Init();
                        state = AIState.Active;
                    }
                }
            }
            //else
            //{
            //    state = AIState.Inactive;
            //}
            movement.Update();
            abilityControl.Update();
        }
    }