예제 #1
0
    public void Initialize()
    {
        if (instance != null)
        {
            Debug.LogWarning("There should be only one sector manager!");
            Destroy(gameObject);
            return;
        }
        instance = this;

        objects            = new Dictionary <string, GameObject>();
        persistentObjects  = new Dictionary <string, GameObject>();
        battleZone         = gameObject.AddComponent <BattleZoneManager>();
        siegeZone          = gameObject.AddComponent <SiegeZoneManager>();
        battleZone.enabled = false;
        siegeZone.enabled  = false;
        lpg = GetComponent <LandPlatformGenerator>();
        lpg.Initialize();
        sectorBorders               = new GameObject("SectorBorders").AddComponent <LineRenderer>();
        sectorBorders.enabled       = false;
        sectorBorders.positionCount = 4;
        sectorBorders.startWidth    = 0.15f;
        sectorBorders.endWidth      = 0.15f;
        sectorBorders.loop          = true;
        OnSectorLoad    = null;
        SectorGraphLoad = null;

        if (customPath != "" && current == null)
        {
            // jsonPath = customPath;
            jsonMode = true;
        }


        if (SceneManager.GetActiveScene().name == "MainMenu")
        {
            string currentPath;
            if (!File.Exists(Application.persistentDataPath + "\\CurrentSavePath"))
            {
                currentPath = null;
            }
            else
            {
                currentPath = File.ReadAllLines(Application.persistentDataPath + "\\CurrentSavePath")[0];
            }

            if (File.Exists(currentPath))
            {
                string json = File.ReadAllText(currentPath);
                var    save = JsonUtility.FromJson <PlayerSave>(json);
                SetMainMenuSector(save.episode);
            }
            else
            {
                SetMainMenuSector(0);
            }
        }

        jsonMode = false;
    }
예제 #2
0
    protected override void Update()
    {
        if (initialized)
        {
            var enemyTargetFound = false;
            if (BattleZoneManager.getTargets() != null && BattleZoneManager.getTargets().Length > 0)
            {
                foreach (var target in BattleZoneManager.getTargets())
                {
                    if (!FactionManager.IsAllied(target.faction, faction) && !target.GetIsDead())
                    {
                        enemyTargetFound = true;
                        break;
                    }
                }
            }

            foreach (ActiveAbility active in GetComponentsInChildren <ActiveAbility>())
            {
                if (!(active is SpawnDrone) || enemyTargetFound)
                {
                    active.Tick(1);
                }
            }


            base.Update();
            TargetManager.Enqueue(targeter);
        }
    }
예제 #3
0
    // Used by "dumb" stations, that just use their abilities whenever possible
    protected void TickAbilitiesAsStation()
    {
        var enemyTargetFound = SectorManager.instance?.current?.type != Sector.SectorType.BattleZone;

        if (!enemyTargetFound && BattleZoneManager.getTargets() != null && BattleZoneManager.getTargets().Length > 0)
        {
            foreach (var target in BattleZoneManager.getTargets())
            {
                if (!FactionManager.IsAllied(target.faction, faction) && !target.GetIsDead())
                {
                    enemyTargetFound = true;
                    break;
                }
            }
        }

        foreach (ActiveAbility active in GetComponentsInChildren <ActiveAbility>())
        {
            if (!(active is SpawnDrone) || enemyTargetFound)
            {
                active.Tick();
                active.Activate();
            }
        }
    }
예제 #4
0
    public void SetOwner(IOwner owner)
    {
        this.owner = owner;
        ai.owner   = owner;
        owner.GetUnitsCommanding().Add(this);
        if (owner as AirCarrier || owner as GroundCarrier)
        {
            // GET THE DRONES TO MOVE
            ai.setMode(AirCraftAI.AIMode.Path);
            var path = ScriptableObject.CreateInstance <Path>();
            path.waypoints = new List <Path.Node>();
            var vec = Vector2.zero;
            if (owner as AirCarrier)
            {
                foreach (var ent in BattleZoneManager.getTargets())
                {
                    if (ent && ent is ICarrier && !FactionManager.IsAllied(ent.faction, owner.GetFaction()) && ent.transform)
                    {
                        vec = ent.transform.position;
                    }
                }
            }
            // otherwise this is a ground carrier, drones are defensive for them so set a path to the drone position currently
            else
            {
                var angle = Random.Range(0F, 360);
                vec = owner.GetTransform().position + new Vector3(5 * Mathf.Sin(angle), 5 * Mathf.Cos(angle));
            }

            // TODO: jank, fix this eventually
            var node = new Path.Node();
            node.position = vec;
            node.ID       = 0;
            node.children = new List <int>();
            if (vec != Vector2.zero)
            {
                path.waypoints.Add(node);
            }
            if (owner as AirCarrier)
            {
                ai.setPath(path);
            }
            else
            {
                NodeEditorFramework.Standard.PathData data = new NodeEditorFramework.Standard.PathData();
                data.waypoints = new List <NodeEditorFramework.Standard.PathData.Node>();
                // TODO: LOL THESE TWO ARE DIFFERENT, unify them
                foreach (var point in path.waypoints)
                {
                    var node2 = new NodeEditorFramework.Standard.PathData.Node();
                    node2.ID       = point.ID;
                    node2.children = point.children;
                    node2.position = point.position;
                    data.waypoints.Add(node2);
                }

                ai.setPath(data, null, true);
            }
        }
    }
예제 #5
0
 bool enemyGroundTargets(bool allEntities)
 {
     Entity[] targets = allEntities ? AIData.entities.ToArray() : BattleZoneManager.getTargets();
     for (int i = 0; i < targets.Length; i++)
     {
         if (!FactionManager.IsAllied(targets[i].faction, craft.faction) && targets[i].Terrain == Entity.TerrainType.Ground)
         {
             return(true);
         }
     }
     return(false);
 }
예제 #6
0
    private void showBattleResults(bool victory)
    {
        if (window)
        {
            endDialogue(0);
        }

        speakerPos = null;

        //create window
        window = Instantiate(battleResultsBoxPrefab).GetComponentInChildren <GUIWindowScripts>();
        window.DestroyOnClose = true;
        window.Activate();
        window.transform.SetSiblingIndex(0);

        if (victory)
        {
            window.transform.Find("Victory").GetComponent <Text>().text = "<color=lime>VICTORY!</color>";
        }
        else
        {
            window.transform.Find("Victory").GetComponent <Text>().text = "<color=red>DEFEAT</color>";
        }

        battleZoneManager = FindObjectOfType <BattleZoneManager>();
        if (!battleZoneManager)
        {
            return;
        }

        string[]      stats      = battleZoneManager.GetStats();
        RectTransform scrollArea = window.transform.Find("Background/ViewBorder/Scroll View/Viewport/Content").GetComponent <RectTransform>();
        GameObject    prefab     = scrollArea.Find("Stats").gameObject;

        for (int i = 0; i < stats.Length; i++)
        {
            var obj = Instantiate(prefab);
            obj.name = "Faction_" + i;
            RectTransform rt   = obj.GetComponent <RectTransform>();
            Text          text = obj.GetComponent <Text>();

            rt.SetParent(scrollArea);
            rt.anchorMin = new Vector2(0f, 0f);
            rt.anchorMax = new Vector2(0f, 1f);
            rt.pivot     = new Vector2(0f, 0.5f);
            rt.offsetMin = new Vector2(120f + 80f * i, 10f);
            rt.offsetMax = new Vector2(128f + 80f * (i + 1), -10f);

            text.text = stats[i];
        }

        scrollArea.sizeDelta = new Vector2(120f + 80f * stats.Length, scrollArea.sizeDelta.y);
    }
예제 #7
0
    public override void Init()
    {
        carriers = new List <Entity>();

        Entity[] targetEntities = BattleZoneManager.getTargets();
        if (targetEntities == null)
        {
            Debug.LogError("Battle zone target list not initialized");
            ai.setMode(AirCraftAI.AIMode.Inactive);
            return;
        }

        for (int i = 0; i < targetEntities.Length; i++)
        {
            if (targetEntities[i] is ICarrier)
            {
                if (targetEntities[i].faction == craft.faction)
                {
                    carriers.Add(targetEntities[i]);
                }
            }
        }

        if (craft is ShellCore)
        {
            shellcore = craft as ShellCore;
        }
        else
        {
            Debug.LogError("Battle zone AI should only be used by shellcores!");
        }

        nextSearchTime     = Time.time;
        nextStateCheckTime = Time.time;

        for (int i = 0; i < AIData.vendors.Count; i++)
        {
            int rockCount = 0;
            for (int j = 0; j < AIData.energyRocks.Count; j++)
            {
                if ((AIData.energyRocks[j].transform.position - AIData.vendors[i].transform.position).sqrMagnitude < 100)
                {
                    rockCount++;
                }
            }
            AITargets.Add(new AITarget(AIData.vendors[i], rockCount + 1f));
        }
        for (int i = 0; i < carriers.Count; i++)
        {
            AITargets.Add(new AITarget(carriers[i], 100f));
        }
    }
예제 #8
0
 ICarrier FindCarrier()
 {
     if (SectorManager.instance.current.type == Sector.SectorType.BattleZone)
     {
         var targets = BattleZoneManager.getTargets();
         for (int i = 0; i < targets.Length; i++)
         {
             if (targets[i] &&
                 !targets[i].GetIsDead() &&
                 targets[i] is ICarrier &&
                 targets[i].faction == faction)
             {
                 return(targets[i] as ICarrier);
             }
         }
     }
     return(null);
 }
예제 #9
0
 protected override void Start()
 {
     category = EntityCategory.Station;
     base.Start();
     BZManager = GameObject.Find("SectorManager").GetComponent <BattleZoneManager>();
 }
예제 #10
0
    public override void Init()
    {
        carriers         = new List <Entity>();
        harvesterTurrets = new Dictionary <EnergyRock, Turret>();

        Entity[] targetEntities = BattleZoneManager.getTargets();
        if (targetEntities == null)
        {
            Debug.LogError("Battle zone target list not initialized");
            ai.setMode(AirCraftAI.AIMode.Inactive);
            return;
        }

        for (int i = 0; i < targetEntities.Length; i++)
        {
            if (targetEntities[i] is ICarrier)
            {
                if (targetEntities[i].faction == craft.faction)
                {
                    carriers.Add(targetEntities[i]);
                }
            }
        }

        if (craft is ShellCore shellCore)
        {
            shellcore = shellCore;
        }
        else
        {
            Debug.LogError("Battle zone AI should only be used by shellcores!");
        }

        foreach (IOwnable ownable in shellcore.GetUnitsCommanding())
        {
            if (ownable is Turret turret && turret.entityName == "Harvester Turret")
            {
                foreach (var rock in AIData.energyRocks)
                {
                    if (!harvesterTurrets.ContainsKey(rock) &&
                        Vector3.SqrMagnitude(rock.transform.position - turret.transform.position) <= 200)
                    {
                        harvesterTurrets.Add(rock, turret);
                        break;
                    }
                }
            }
        }

        nextSearchTime     = Time.time;
        nextStateCheckTime = Time.time;

        for (int i = 0; i < AIData.vendors.Count; i++)
        {
            int rockCount = 0;
            for (int j = 0; j < AIData.energyRocks.Count; j++)
            {
                if ((AIData.energyRocks[j].transform.position - AIData.vendors[i].transform.position).sqrMagnitude < 100)
                {
                    rockCount++;
                }
            }

            AITargets.Add(new AITarget(AIData.vendors[i], rockCount + 1f));
        }

        for (int i = 0; i < carriers.Count; i++)
        {
            AITargets.Add(new AITarget(carriers[i], 100f));
        }
    }
예제 #11
0
    public override void ActionTick()
    {
        if (waitingDraggable != null && waitingDraggable)
        {
            ai.movement.SetMoveTarget(waitingDraggable.transform.position, 100f);

            Vector2 delta = waitingDraggable.transform.position - craft.transform.position;
            if (ai.movement.targetIsInRange() && shellcore.GetTractorTarget() != null && shellcore.GetTractorTarget().gameObject.GetComponent <EnergySphereScript>() == null)
            {
                shellcore.SetTractorTarget(waitingDraggable);
            }
        }

        var turretIsHarvester = shellcore.GetTractorTarget() &&
                                shellcore.GetTractorTarget().GetComponent <Turret>() &&
                                shellcore.GetTractorTarget().GetComponent <Turret>().entityName == "Harvester Turret";

        switch (state)
        {
        case BattleState.Attack:
            if (shellcore.GetTractorTarget() == null)
            {
                if (attackTurret == null)
                {
                    Turret t           = null;
                    float  minDistance = float.MaxValue;
                    for (int i = 0; i < AIData.entities.Count; i++)
                    {
                        if (AIData.entities[i] != null && AIData.entities[i] &&
                            AIData.entities[i] is Turret &&
                            AIData.entities[i].faction == craft.faction &&
                            AIData.entities[i].GetComponentInChildren <WeaponAbility>() != null &&
                            AIData.entities[i].GetComponentInChildren <WeaponAbility>().GetID() != 16)
                        {
                            float d = (AIData.entities[i].transform.position - craft.transform.position).sqrMagnitude;
                            if (d < minDistance)
                            {
                                t           = AIData.entities[i] as Turret;
                                minDistance = d;
                            }
                        }
                    }

                    attackTurret = t;
                }
                else
                {
                    float d = (attackTurret.transform.position - shellcore.transform.position).sqrMagnitude;
                    if (d < 150)
                    {
                        shellcore.SetTractorTarget(attackTurret.GetComponent <Draggable>());
                    }
                }
            }

            // go to nearest enemy construct, attack units / turrets if in visual range
            if ((primaryTarget == null && nextSearchTime < Time.time) || nextSearchTime < Time.time - 3f)
            {
                // get nearest construct
                primaryTarget  = AirCraftAI.getNearestEntity <AirConstruct>(craft, true);   //TODO: Exclude turrets?
                nextSearchTime = Time.time + 1f;

                //if(primaryTarget)
                //    Debug.Log("AggroTarget: " + primaryTarget.name + " Factions: " + primaryTarget.faction + " - " + craft.faction);
            }

            if (primaryTarget != null)
            {
                ai.movement.SetMoveTarget(primaryTarget.transform.position);
                //craft.MoveCraft((primaryTarget.transform.position - craft.transform.position).normalized);
            }

            //TODO: AI Attack:
            // action sequences
            // Use existing turrets:
            // -Drag torpedo turrets to enemy bunkers
            // -Drag siege turrets to outposts
            // ground attack location = own bunker location
            // drag tanks from one platform to another "LandPlatformGenerator.getEnemiesOnPlatform(Vector2 platformLocation, int faction)"?
            // how to react to different pressures on land and air?
            break;

        case BattleState.Defend:
            // destroy enemy units around base, ignore everything outside siege range
            if (primaryTarget && !primaryTarget.GetIsDead())
            {
                ai.movement.SetMoveTarget(primaryTarget.transform.position);
            }

            // buy a turret matching the biggest threat's element, if possible
            break;

        case BattleState.Collect:
            // go from outpost to outpost, (also less fortified enemy outposts [count enemy units nearby {TODO}]) and collect energy
            if (findNewTarget || collectTarget == null)
            {
                // Find new target
                float      minD       = float.MaxValue;
                EnergyRock targetRock = null;
                int        maxEnergy  = -1;

                for (int i = 0; i < AIData.energyRocks.Count; i++)
                {
                    if (AirCraftAI.getEnemyCountInRange(AIData.energyRocks[i].transform.position, 10f, craft.faction) > 2)
                    {
                        continue;
                    }

                    int energy = 0;
                    for (int j = 0; j < AIData.energySpheres.Count; j++)
                    {
                        if ((AIData.energySpheres[j].transform.position - AIData.energyRocks[i].transform.position).sqrMagnitude < 16)
                        {
                            energy++;
                        }
                    }

                    float d = (craft.transform.position - AIData.energyRocks[i].transform.position).sqrMagnitude;
                    if ((maxEnergy < energy || d * 1.5f < minD || (maxEnergy == energy && d < minD)) && AIData.energyRocks[i] != collectTarget)
                    {
                        minD       = d;
                        maxEnergy  = energy;
                        targetRock = AIData.energyRocks[i];
                    }
                }

                collectTarget = targetRock;

                if (collectTarget != null)
                {
                    findNewTarget = false;
                }

                //Debug.LogFormat("Faction {0} collect target: {1}", craft.faction, collectTarget);
            }

            if (collectTarget != null)
            {
                ai.movement.SetMoveTarget(collectTarget.transform.position);
                if (ai.movement.targetIsInRange())
                {
                    if (harvesterTurrets.ContainsKey(collectTarget) &&
                        (!harvesterTurrets[collectTarget] || harvesterTurrets[collectTarget].GetIsDead()))
                    {
                        harvesterTurrets.Remove(collectTarget);
                    }

                    if (turretIsHarvester && !harvesterTurrets.ContainsKey(collectTarget))
                    {
                        harvesterTurrets.Add(collectTarget, shellcore.GetTractorTarget().GetComponent <Turret>());
                        shellcore.SetTractorTarget(null);
                        state = BattleState.Attack;
                    }

                    findNewTarget = true;
                }
            }

            break;

        case BattleState.Fortify:
            // TODO: place turrets
            // set primary target to an outpost with least defending turrets
            if (fortificationTarget == null || !fortificationTarget)
            {
                UpdateTargetInfluences();

                float closestToZero = float.MaxValue;

                for (int i = 0; i < AITargets.Count; i++)
                {
                    if (Mathf.Abs(AITargets[i].influence) < closestToZero && AITargets[i].entity.faction == shellcore.faction)
                    {
                        fortificationTarget = AITargets[i].entity;
                    }
                }
            }
            else if (attackTurret == null || !attackTurret)
            {
                UpdateTargetInfluences();

                float minDistance = float.MaxValue;

                for (int i = 0; i < AIData.entities.Count; i++)
                {
                    if (AIData.entities[i] is Turret)
                    {
                        float d  = (craft.transform.position - AIData.entities[i].transform.position).sqrMagnitude;
                        float d2 = (fortificationTarget.transform.position - AIData.entities[i].transform.position).sqrMagnitude;
                        if (d < minDistance && d2 > 150f)
                        {
                            minDistance  = d;
                            attackTurret = AIData.entities[i] as Turret;
                        }
                    }
                }

                if (attackTurret == null)
                {
                    state = BattleState.Attack;
                    ActionTick();
                    nextStateCheckTime += 1f;
                    return;
                }
            }
            else if (shellcore.GetTractorTarget() != attackTurret)
            {
                ai.movement.SetMoveTarget(attackTurret.transform.position, 100f);
                if (ai.movement.targetIsInRange())
                {
                    var target = shellcore.GetTractorTarget();
                    if (target != null && target)
                    {
                        if (target.gameObject.GetComponent <EnergySphereScript>() == null)
                        {
                            shellcore.SetTractorTarget(attackTurret.GetComponent <Draggable>());
                        }
                    }
                }
            }
            else
            {
                Vector2 turretDelta    = fortificationTarget.transform.position - attackTurret.transform.position;
                Vector2 targetPosition = (Vector2)fortificationTarget.transform.position + turretDelta.normalized * 16f;
                Vector2 delta          = targetPosition - (Vector2)craft.transform.position;
                if (turretDelta.sqrMagnitude < 16f)
                {
                    shellcore.SetTractorTarget(null);
                }
            }

            break;

        case BattleState.ReinforceGround:
            //head to nearest bunker to produce tanks
            float dist  = float.MaxValue;
            int   index = -1;
            for (int i = 0; i < AITargets.Count; i++)
            {
                if (AITargets[i].entity.Terrain == Entity.TerrainType.Ground && AITargets[i].entity && AITargets[i].entity.faction == shellcore.faction && Vector2.SqrMagnitude(craft.transform.position - AITargets[i].entity.transform.position) < dist)
                {
                    dist  = Vector2.SqrMagnitude(craft.transform.position - AITargets[i].entity.transform.position);
                    index = i;
                }
            }
            if (index != -1 && dist >= 100f)
            {
                ai.movement.SetMoveTarget(AITargets[index].entity.transform.position);
                dist = Vector2.SqrMagnitude(craft.transform.position - AITargets[index].entity.transform.position);
            }
            break;

        default:
            break;
        }

        // always drop harvester turrets on close energy rocks
        turretIsHarvester = shellcore.GetTractorTarget() &&
                            shellcore.GetTractorTarget().GetComponent <Turret>() &&
                            shellcore.GetTractorTarget().GetComponent <Turret>().entityName == "Harvester Turret";
        if (turretIsHarvester)
        {
            var turret = shellcore.GetTractorTarget().GetComponent <Turret>();
            if (harvesterTurrets.ContainsValue(turret))
            {
                harvesterTurrets.Remove(harvesterTurrets.First(kvp => kvp.Value == turret).Key);
            }

            foreach (var rock in AIData.energyRocks)
            {
                if ((rock.transform.position - shellcore.transform.position).sqrMagnitude > 150f)
                {
                    continue;
                }

                if (harvesterTurrets.ContainsKey(rock) &&
                    (!harvesterTurrets[rock] || harvesterTurrets[rock].GetIsDead()))
                {
                    harvesterTurrets.Remove(rock);
                }

                if (!harvesterTurrets.ContainsKey(rock))
                {
                    harvesterTurrets.Add(rock, shellcore.GetTractorTarget().GetComponent <Turret>());
                    shellcore.SetTractorTarget(null);
                    break;
                }
            }
        }

        int energyCount = 0;

        // always collect energy
        if (shellcore.GetTractorTarget() != null && shellcore.GetTractorTarget().gameObject.GetComponent <EnergySphereScript>() == null)
        {
            for (int i = 0; i < AIData.energySpheres.Count; i++)
            {
                if ((AIData.energySpheres[i].transform.position - shellcore.transform.position).sqrMagnitude < 150)
                {
                    energyCount++;
                    if (shellcore.GetTractorTarget() != null)
                    {
                        waitingDraggable = shellcore.GetTractorTarget();
                        shellcore.SetTractorTarget(null);
                    }
                }
            }
        }
        else if (shellcore.GetTractorTarget() == null && waitingDraggable != null)
        {
            for (int i = 0; i < AIData.energySpheres.Count; i++)
            {
                if ((AIData.energySpheres[i].transform.position - shellcore.transform.position).sqrMagnitude < 150)
                {
                    energyCount++;
                }
            }

            if (energyCount == 0)
            {
                shellcore.SetTractorTarget(waitingDraggable);
                if (shellcore.GetTractorTarget() == waitingDraggable)
                {
                    waitingDraggable = null;
                }
            }
        }

        // always buy more turrets/tanks
        if (shellcore.unitsCommanding.Count < shellcore.GetTotalCommandLimit() && energyCount == 0 || state == BattleState.ReinforceGround)
        {
            for (int i = 0; i < AIData.vendors.Count; i++)
            {
                if ((AIData.vendors[i].transform.position - craft.transform.position).sqrMagnitude <= 100f && AIData.vendors[i].faction == craft.faction)
                {
                    IVendor vendor = AIData.vendors[i] as IVendor;

                    if (vendor.GetVendingBlueprint() == null)
                    {
                        continue;
                    }

                    int itemIndex          = -1;
                    int ownGroundStation   = 0;
                    int ownTank            = 0;
                    int enemyTank          = 0;
                    int enemyGroundStation = 0;
                    for (int j = 0; j < AIData.entities.Count; j++)
                    {
                        if (FactionManager.IsAllied(AIData.entities[j].faction, craft.faction) && AIData.entities[j].Terrain == Entity.TerrainType.Ground && AIData.entities[j].category == Entity.EntityCategory.Station)
                        {
                            ownGroundStation += 1;
                        }
                        if (!FactionManager.IsAllied(AIData.entities[j].faction, craft.faction) && AIData.entities[j].Terrain == Entity.TerrainType.Ground && AIData.entities[j].category == Entity.EntityCategory.Station)
                        {
                            enemyGroundStation += 1;
                        }
                        if (FactionManager.IsAllied(AIData.entities[j].faction, craft.faction) && AIData.entities[j].Terrain == Entity.TerrainType.Ground && AIData.entities[j].category == Entity.EntityCategory.Unit)
                        {
                            ownTank += 1;
                        }
                        if (!FactionManager.IsAllied(AIData.entities[j].faction, craft.faction) && AIData.entities[j].Terrain == Entity.TerrainType.Ground && AIData.entities[j].category == Entity.EntityCategory.Unit)
                        {
                            enemyTank += 1;
                        }
                    }
                    if (mostNeeded == null)
                    {
                        if (enemyTank > ownTank)
                        {
                            if ((shellcore.GetPower() >= 150 && Random.Range(0, 5) < 4) || Random.Range(0, 3) == 1)
                            {
                                if (Random.Range(0, 2) == 0)
                                {
                                    mostNeeded = ("Beam Tank");
                                }
                                else
                                {
                                    mostNeeded = ("Laser Tank");
                                }
                            }
                            else if (shellcore.GetPower() >= 100 || Random.Range(0, 2) == 1)
                            {
                                mostNeeded = ("Bullet Tank");
                            }
                            else
                            {
                                mostNeeded = ("Speeder Tank");
                            }
                        }
                        else if (enemyGroundStation + enemyTank > ownTank)
                        {
                            if (shellcore.GetPower() >= 150 || Random.Range(0, 3) == 1)
                            {
                                if (Random.Range(0, 3) == 0)
                                {
                                    mostNeeded = ("Beam Tank");
                                }
                                else
                                {
                                    mostNeeded = ("Siege Tank");
                                }
                            }
                            else if (shellcore.GetPower() >= 100 || Random.Range(0, 2) == 1)
                            {
                                mostNeeded = ("Bullet Tank");
                            }
                            else
                            {
                                mostNeeded = ("Speeder Tank");
                            }
                        }
                        else
                        {
                            if ((shellcore.GetPower() >= 200 && Random.Range(0, 4) < 3) || Random.Range(0, 2) == 1)
                            {
                                mostNeeded = ("Missile Tank");
                            }
                            else
                            {
                                mostNeeded = ("Laser Tank");
                            }
                        }
                    }

                    if (state == BattleState.Attack)
                    {
                        if (vendor.GetVendingBlueprint().items[0].entityBlueprint.intendedType == EntityBlueprint.IntendedType.Turret)
                        {
                            bool ownGroundExists = false;
                            for (int j = 0; j < AIData.entities.Count; j++)
                            {
                                if (AIData.entities[j].faction == craft.faction && AIData.entities[j].Terrain == Entity.TerrainType.Ground)
                                {
                                    ownGroundExists = true;
                                    break;
                                }
                            }
                            if (!ownGroundExists && enemyGroundTargets(true) && shellcore.GetPower() >= 150)
                            {
                                // Attack & enemy holds all ground
                                itemIndex = vendor.GetVendingBlueprint().getItemIndex("Torpedo Turret");
                            }
                            else
                            {
                                if (shellcore.GetPower() >= 200)
                                {
                                    itemIndex = vendor.GetVendingBlueprint().getItemIndex("Missile Turret");
                                }
                                else if (shellcore.GetPower() >= 100)
                                {
                                    itemIndex = vendor.GetVendingBlueprint().getItemIndex("Defense Turret");
                                }
                            }
                        }
                        else if (vendor.GetVendingBlueprint().items[0].entityBlueprint.intendedType == EntityBlueprint.IntendedType.Tank)
                        {
                            itemIndex = vendor.GetVendingBlueprint().getItemIndex(mostNeeded);
                        }
                    }
                    if (state == BattleState.ReinforceGround)
                    {
                        itemIndex = vendor.GetVendingBlueprint().getItemIndex(mostNeeded);
                    }
                    if (itemIndex == -1)
                    {
                        if (harvesterTurrets.Count < Mathf.Min(5, AIData.energyRocks.Count) &&
                            shellcore.GetPower() >= 100)
                        {
                            itemIndex = vendor.GetVendingBlueprint().getItemIndex("Harvester Turret");
                            foreach (var turret in harvesterTurrets.Values)
                            {
                                if (turret && Vector3.SqrMagnitude(turret.transform.position - shellcore.transform.position) <= 200)
                                {
                                    itemIndex = -1;
                                }
                            }
                        }
                        else
                        {
                            for (int j = 0; j < vendor.GetVendingBlueprint().items.Count; j++)
                            {
                                if (itemIndex != -1 && vendor.GetVendingBlueprint().items[j].cost <= vendor.GetVendingBlueprint().items[itemIndex].cost && vendor.GetVendingBlueprint().items[0].entityBlueprint.intendedType != EntityBlueprint.IntendedType.Tank) // more expensive => better (TODO: choose based on the situation)
                                {
                                    if (itemIndex != -1 && vendor.GetVendingBlueprint().items[j].cost <= vendor.GetVendingBlueprint().items[itemIndex].cost)                                                                                                        // more expensive => better (TODO: choose based on the situation)
                                    {
                                        continue;
                                    }

                                    if (vendor.GetVendingBlueprint().items[j].entityBlueprint.name != mostNeeded && vendor.GetVendingBlueprint().items[0].entityBlueprint.intendedType == EntityBlueprint.IntendedType.Tank) //TODO: get turret / tank attack category from somewhere else
                                    {
                                        continue;
                                    }

                                    itemIndex = j;
                                }
                            }
                        }
                    }

                    if (itemIndex != -1)
                    {
                        if (vendor.GetVendingBlueprint().items[itemIndex].cost <= shellcore.GetPower())
                        {
                            mostNeeded = null;
                        }
                        else
                        {
                            break;
                        }
                        var ent = VendorUI.BuyItem(shellcore, itemIndex, (AIData.vendors[i] as IVendor));
                        if (itemIndex == vendor.GetVendingBlueprint().getItemIndex("Harvester Turret"))
                        {
                            EnergyRock closestRock = null;
                            foreach (var rock in AIData.energyRocks.FindAll(e => !harvesterTurrets.ContainsKey(e)))
                            {
                                if (closestRock == null || Vector2.SqrMagnitude(rock.transform.position - shellcore.transform.position)
                                    < Vector2.SqrMagnitude(closestRock.transform.position - shellcore.transform.position))
                                {
                                    closestRock = rock;
                                }
                            }

                            harvesterTurrets.Add(closestRock, ent as Turret);
                            shellcore.SetTractorTarget(ent.GetComponent <Draggable>());
                        }

                        break;
                    }
                }
            }
        }

        void UpdateTargetInfluences()
        {
            for (int i = 0; i < AITargets.Count; i++)
            {
                var t = AITargets[i];
                if (t.entity == null || t.entity.GetIsDead())
                {
                    Debug.LogWarning("AI Warning: AI target null or dead!");
                    continue;
                }

                t.influence = 0f;
                for (int j = 0; j < AIData.entities.Count; j++)
                {
                    if (AIData.entities[j] is Turret)
                    {
                        if ((AIData.entities[j].transform.position - t.entity.transform.position).sqrMagnitude < 150f)
                        {
                            t.influence += FactionManager.IsAllied(AIData.entities[j].faction, t.entity.faction) ? 1f : -1f;
                        }
                    }
                }
            }
        }

        bool enemyGroundTargets(bool allEntities)
        {
            Entity[] targets = allEntities ? AIData.entities.ToArray() : BattleZoneManager.getTargets();
            for (int i = 0; i < targets.Length; i++)
            {
                if (!FactionManager.IsAllied(targets[i].faction, craft.faction) && targets[i].Terrain == Entity.TerrainType.Ground)
                {
                    return(true);
                }
            }

            return(false);
        }
    }