예제 #1
0
 private void UpgradeBot(GatherBot bot)
 {
     //bot.Upgrade();
     resourceCount -= botUpgradeCost;
     toBeSpent     -= botUpgradeCost;
     inventory.RemoveItem(Item.Type.PureCorvorite, botUpgradeCost);
 }
예제 #2
0
 protected virtual void Signalling()
 {
     signalTimer -= Time.deltaTime;
     if (signalTimer <= 0f)
     {
         for (int i = 0; i < hive.childBots.Count; i++)
         {
             GatherBot sibling = hive.childBots[i];
             sibling.enemies = enemies;
             if (IsInCombat)
             {
                 sibling.SetState(AIState.Escaping);
             }
             else
             {
                 sibling.SetState(AIState.Attacking);
             }
             for (int j = 0; j < enemies.Count; j++)
             {
                 ICombat enemy = enemies[j];
                 enemy.EngageInCombat(sibling);
             }
         }
     }
 }
예제 #3
0
    private void SpendResources(GatherBot b = null)
    {
        int usable        = resourceCount - minLeftoverResources - toBeSpent;
        int creationCount = usable / botCreationCost;
        int tooMuch       = Math.Max(0, creationCount + childBots.Count - maxBotCount);

        creationCount -= tooMuch;
        usable        -= creationCount * botCreationCost;
        int upgradeCount = childBots.Count + creationCount < maxBotCount ? 0 : usable / botUpgradeCost;

        tooMuch       = Math.Max(0, upgradeCount - (creationCount * maxInitialUpgrades + (b == null ? 0 : 1)));
        upgradeCount -= tooMuch;
        usable       -= upgradeCount * botUpgradeCost;

        bool startCreationProcess = needToCreate == 0;

        //update vars
        Debug.Log(string.Format("Current resource count: {0}", resourceCount));
        Debug.Log(string.Format("Creating {0} bots at {1} each: (-{2})",
                                creationCount, botCreationCost, creationCount * botCreationCost));
        needToCreate += creationCount;
        Debug.Log(string.Format("Upgrading {0} bots at {1} each: (-{2})",
                                upgradeCount, botUpgradeCost, upgradeCount * botUpgradeCost));
        needToUpgrade += upgradeCount;
        toBeSpent     += needToCreate * botCreationCost + needToUpgrade * botUpgradeCost;
        Debug.Log(string.Format("New resource count: {0}", resourceCount - toBeSpent));

        if (startCreationProcess)
        {
            CreationProcess(b);
        }
    }
예제 #4
0
    private GatherBot CreateBot(int dockID, bool ignoreCost = false)
    {
        if (!ignoreCost)
        {
            if (resourceCount < botCreationCost + minLeftoverResources)
            {
                return(null);
            }

            resourceCount -= botCreationCost;
            toBeSpent     -= botCreationCost;
            inventory.RemoveItem(Item.Type.PureCorvorite, botCreationCost);
        }
        GatherBot bot = Instantiate(botPrefab);

        bot.Create(this, botBaseHP, dockID);
        bot.Activate(false);
        occupiedDocks[dockID]  = true;
        bot.transform.position = docks[dockID].position;
        bot.transform.rotation = docks[dockID].rotation;
        bot.transform.parent   = transform.parent;
        childBots.Add(bot);
        AssignUnoccupiedCoords(bot);
        BuildBot(dockID);
        return(bot);
    }
예제 #5
0
 public void Store(List <ItemStack> items, GatherBot b)
 {
     b.Activate(false);
     dockAnims[b.dockID].SetTrigger("Dismantle1");
     inventory.Store(items);
     resourceCount = inventory.Count(Item.Type.PureCorvorite);
     SpendResources(b);
 }
예제 #6
0
 protected virtual void AlertAll(ICombat threat)
 {
     for (int i = 0; i < hive?.childBots.Count; i++)
     {
         GatherBot sibling = hive.childBots[i];
         sibling.AddThreat(threat);
         sibling.SetState(AIState.Attacking);
     }
 }
예제 #7
0
    public void AssignUnoccupiedCoords(GatherBot b)
    {
        if (b == null)
        {
            return;
        }
        CheckEmptyMarkedCoords();
        botOccupiedCoords.Clear();
        botOccupiedCoords.AddRange(emptyCoords);

        for (int i = 0; i < childBots.Count; i++)
        {
            EntityNetwork.IterateCoordsInRange(
                childBots[i].GetIntendedCoords(),
                1,
                cc =>
            {
                botOccupiedCoords.Add(cc);
                return(false);
            },
                false);
        }

        //find a random nearby coordinate that is not already occupied
        int         searchRange = 1;
        ChunkCoords location    = ChunkCoords.Invalid;

        while (location == ChunkCoords.Invalid)
        {
            EntityNetwork.IterateCoordsOnRangeBorder(
                coords,
                searchRange,
                cc =>
            {
                if (botOccupiedCoords.Contains(cc))
                {
                    return(false);
                }
                if (Random.value < 0.1f)
                {
                    location = cc;
                    return(true);
                }

                return(false);
            },
                false);
            searchRange++;
        }

        Vector2 pos = ChunkCoords.GetCenterCell(location, EntityNetwork.CHUNK_SIZE);

        b.HiveOrders(pos);
    }
예제 #8
0
 private bool SiblingsInRangeOfTarget(Vector2 enemyPos)
 {
     for (int i = 0; i < hive?.childBots.Count; i++)
     {
         GatherBot bot  = hive.childBots[i];
         float     dist = Vector2.Distance(bot.transform.position, enemyPos);
         if (dist < chaseRange)
         {
             return(true);
         }
     }
     return(Vector2.Distance(transform.position, enemyPos) < chaseRange);
 }
예제 #9
0
 public void ActivateBot(int ID, Vector2 position)
 {
     for (int i = 0; i < childBots.Count; i++)
     {
         GatherBot bot = childBots[i];
         if (bot.dockID == ID)
         {
             bot.transform.position = position;
             bot.Activate(true);
             return;
         }
     }
 }
예제 #10
0
 public bool SplitUpGatheringUnits(GatherBot b)
 {
     for (int i = 0; i < childBots.Count; i++)
     {
         GatherBot bot = childBots[i];
         //don't check self
         if (b == bot)
         {
             continue;
         }
         //two bots should gather in different locations to avoid overcrowding
         if (b.GetIntendedCoords() == bot.GetIntendedCoords())
         {
             return(true);
         }
     }
     return(false);
 }
예제 #11
0
 public bool VerifyGatheringTarget(GatherBot b, Entity e = null)
 {
     e = e == null ? b.targetEntity : e;
     for (int i = 0; i < childBots.Count; i++)
     {
         GatherBot bot = childBots[i];
         //don't check self
         if (b == bot)
         {
             continue;
         }
         //two bots shouldn't gather from the same target
         if (e == bot.targetEntity)
         {
             return(false);
         }
     }
     return(true);
 }
예제 #12
0
 public override void DestroyedAnEntity(Entity target)
 {
     for (int i = 0; i < enemies.Count; i++)
     {
         if ((Entity)enemies[i] == target)
         {
             enemies[i].DisengageInCombat(this);
             enemies.RemoveAt(i);
             if (enemies.Count == 0)
             {
                 for (int j = 0; j < hive?.childBots.Count; j++)
                 {
                     GatherBot bot = hive.childBots[j];
                     bot?.SetState(AIState.Collecting);
                 }
             }
             return;
         }
     }
 }
예제 #13
0
    private void CreationProcess(GatherBot b = null)
    {
        if (b != null && needToUpgrade > 0)
        {
            UpgradeBot(b);
            needToUpgrade--;
        }

        while (needToCreate > 0)
        {
            int       dockID = GetAvailableDockID();
            GatherBot newBot = CreateBot(dockID);
            needToCreate--;
            for (int i = 0; i < maxInitialUpgrades && needToUpgrade > 0; i++)
            {
                UpgradeBot(newBot);
                needToUpgrade--;
            }
        }
    }
예제 #14
0
 public Transform GetDock(GatherBot bot) => docks[bot.dockID];
예제 #15
0
    protected virtual void Attacking()
    {
        if (enemies.Count == 0)
        {
            SetState(AIState.Collecting);
        }

        Vector2 currentPos = transform.position;

        //if sibling bots are nearby, get them to join the fight
        for (int i = 0; i < hive?.childBots.Count; i++)
        {
            GatherBot sibling = hive.childBots[i];
            if (sibling.state == AIState.Attacking || sibling.state == AIState.Dying)
            {
                continue;
            }

            if (Vector2.Distance(currentPos, sibling.transform.position)
                < Constants.CHUNK_SIZE)
            {
                float scanAngle = -Vector2.SignedAngle(Vector2.up, (Vector2)sibling.transform.position - currentPos);
                StartCoroutine(ScanRings(scanAngle, 30f, false, 0.3f));
                sibling.enemies = enemies;
                sibling.SetState(AIState.Attacking);
            }
        }

        //check if the target is too far away from this bot and its siblings
        targetEntity = (Entity)enemies[0];
        Vector2 enemyPos = targetEntity.transform.position;
        bool    found    = SiblingsInRangeOfTarget(enemyPos);

        //if the target is out of range for too long then disengage from combat
        if (IncrementOutOfRangeCounter(found))
        {
            return;
        }

        //bots attack by circling its target and firing
        float   orbitAngle         = Mathf.PI * 2f / (hive?.childBots.Count ?? 1) * dockID + Pause.timeSinceOpen * orbitSpeed;
        Vector2 orbitPos           = new Vector2(Mathf.Sin(orbitAngle), Mathf.Cos(orbitAngle)) * orbitRange;
        float   distanceFromTarget = Vector2.Distance(currentPos, enemyPos);

        Vector2 direction = enemyPos - currentPos;
        int     count     = Physics2D.RaycastNonAlloc(currentPos, direction, lineOfSight, distanceFromTarget);

        GoToLocation(enemyPos + orbitPos, count > 1, 0.2f, true,
                     distanceFromTarget > firingRange ? null : (Vector2?)targetEntity.transform.position - transform.right);

        //fire will in range
        readyToFire = distanceFromTarget <= firingRange;
        if (readyToFire)
        {
            straightWeapon.aim = targetEntity.transform.position;
        }

        //run away if hp drops below 50% while also having lower health than the target
        if (!IsSwarmInCombat)
        {
            float hpRatio = healthComponent.CurrentRatio;
            if (hpRatio < 0.5f && hpRatio < targetEntity.HealthRatio)
            {
                scaryEntities.Add(targetEntity);
                SetState(AIState.Signalling);
            }
        }
    }
예제 #16
0
    protected virtual void SetState(AIState newState)
    {
        if (state == AIState.Dying || state == newState)
        {
            return;
        }
        bool wasIdle = isIdle;

        isIdle = true;
        bool couldDrill = canDrill;

        canDrill = false;

        switch (newState)
        {
        case AIState.Suspicious:
            suspicionMeter = suspicionMeter ?? Instantiate(radialMeterPrefab);
            suspicionMeter.transform.parent = ParticleGenerator.holder;
            suspicionMeter.material.SetFloat("_ArcAngle", 0);
            break;

        case AIState.Gathering:
            canDrill = true;
            isIdle   = false;
            break;

        case AIState.Spawning:
            transform.position = hive.GetDock(this).position;
            hive.Store(DefaultInventory.ItemStacks, this);
            itemsCollected = 0;
            disassembling  = false;
            unsuspiciousEntities.Clear();
            break;

        case AIState.Signalling:
            for (int i = 0; i < hive.childBots.Count; i++)
            {
                GatherBot sibling = hive.childBots[i];
                if (sibling == null)
                {
                    hive.childBots.Remove(sibling);
                }
                if (sibling == this)
                {
                    continue;
                }
                float scanAngle = -Vector2.SignedAngle(Vector2.up, sibling.transform.position - transform.position);
                StartCoroutine(ScanRings(scanAngle, 30f, false, 0.3f));
            }
            signalTimer = scanDuration;
            break;

        case AIState.Attacking:
            anim.SetTrigger("GunOut");
            isIdle = false;
            break;

        case AIState.Exploring:
            hive.AssignUnoccupiedCoords(this);
            break;

        case AIState.Escaping:
            outOfRangeTimer = 0f;
            break;

        case AIState.Dying:
            dyingTimer     = 0f;
            anim.enabled   = false;
            sprRend.sprite = dyingSprite;
            burningEffectsObj?.SetActive(true);
            ActivateAllColliders(false);
            EjectFromAllDrillers(true);
            break;
        }

        if (isIdle && isIdle != wasIdle)
        {
            anim.SetTrigger("Idle");
        }

        if (canDrill && canDrill != couldDrill)
        {
            anim.SetTrigger("DrillOut");
        }

        if (newState != AIState.Gathering)
        {
            drill.StopDrilling(false);
            anim.SetBool("Drilling", false);
        }

        if (newState != AIState.Suspicious)
        {
            nearbySuspects.Clear();
            intenseScanner.Stop();
            suspicionMeter?.gameObject.SetActive(false);
            suspicionMeter?.material.SetFloat("_ArcAngle", 0);
        }

        state = newState;
    }
예제 #17
0
 public void BotDestroyed(GatherBot bot)
 {
     occupiedDocks[bot.dockID] = false;
     childBots.Remove(bot);
 }