Example #1
0
        //a recursive function that goes through all the junctions and adds up
        //all the generated/consumed power of the constructions connected to the grid
        private void CheckJunctions(float deltaTime)
        {
            updateTimer = 1;
            connectedList.Add(this);

            ApplyStatusEffects(ActionType.OnActive, deltaTime, null);

            foreach (Connection c in powerConnections)
            {
                var recipients = c.Recipients;

                foreach (Connection recipient in recipients)
                {
                    if (recipient == null)
                    {
                        continue;
                    }

                    Item it = recipient.Item;
                    if (it == null)
                    {
                        continue;
                    }

                    if (it.Condition <= 0.0f)
                    {
                        continue;
                    }

                    foreach (Powered powered in it.GetComponents <Powered>())
                    {
                        if (powered == null || !powered.IsActive)
                        {
                            continue;
                        }

                        if (connectedList.Contains(powered))
                        {
                            continue;
                        }

                        PowerTransfer powerTransfer = powered as PowerTransfer;
                        if (powerTransfer != null)
                        {
                            powerTransfer.CheckJunctions(deltaTime);
                            continue;
                        }

                        PowerContainer powerContainer = powered as PowerContainer;
                        if (powerContainer != null)
                        {
                            if (recipient.Name == "power_in")
                            {
                                fullLoad += powerContainer.CurrPowerConsumption;
                            }
                            else
                            {
                                fullPower += powerContainer.CurrPowerOutput;
                            }
                        }
                        else
                        {
                            connectedList.Add(powered);
                            //positive power consumption = the construction requires power -> increase load
                            if (powered.CurrPowerConsumption > 0.0f)
                            {
                                fullLoad += powered.CurrPowerConsumption;
                            }
                            else if (powered.CurrPowerConsumption < 0.0f)
                            //negative power consumption = the construction is a
                            //generator/battery or another junction box
                            {
                                fullPower -= powered.CurrPowerConsumption;
                            }
                        }
                    }
                }
            }
        }
Example #2
0
        public override bool AIOperate(float deltaTime, Character character, AIObjectiveOperateItem objective)
        {
            if (character.AIController.SelectedAiTarget?.Entity is Character previousTarget &&
                previousTarget.IsDead)
            {
                character?.Speak(TextManager.Get("DialogTurretTargetDead"), null, 0.0f, "killedtarget" + previousTarget.ID, 30.0f);
                character.AIController.SelectTarget(null);
            }

            if (GetAvailableBatteryPower() < powerConsumption)
            {
                var batteries = item.GetConnectedComponents <PowerContainer>();

                float          lowestCharge  = 0.0f;
                PowerContainer batteryToLoad = null;
                foreach (PowerContainer battery in batteries)
                {
                    if (batteryToLoad == null || battery.Charge < lowestCharge)
                    {
                        batteryToLoad = battery;
                        lowestCharge  = battery.Charge;
                    }
                }

                if (batteryToLoad == null)
                {
                    return(true);
                }

                if (batteryToLoad.RechargeSpeed < batteryToLoad.MaxRechargeSpeed * 0.4f)
                {
                    objective.AddSubObjective(new AIObjectiveOperateItem(batteryToLoad, character, objective.objectiveManager, option: "", requireEquip: false));
                    return(false);
                }
            }

            int usableProjectileCount = 0;
            int maxProjectileCount    = 0;

            foreach (MapEntity e in item.linkedTo)
            {
                if (!(e is Item projectileContainer))
                {
                    continue;
                }

                var containedItems = projectileContainer.ContainedItems;
                if (containedItems != null)
                {
                    var container = projectileContainer.GetComponent <ItemContainer>();
                    maxProjectileCount += container.Capacity;

                    int projectiles = containedItems.Count(it => it.Condition > 0.0f);
                    usableProjectileCount += projectiles;
                }
            }

            if (usableProjectileCount == 0 || (usableProjectileCount < maxProjectileCount && objective.Option.Equals("fireatwill", StringComparison.OrdinalIgnoreCase)))
            {
                ItemContainer container     = null;
                Item          containerItem = null;
                foreach (MapEntity e in item.linkedTo)
                {
                    containerItem = e as Item;
                    if (containerItem == null)
                    {
                        continue;
                    }
                    container = containerItem.GetComponent <ItemContainer>();
                    if (container != null)
                    {
                        break;
                    }
                }
                if (container == null || container.ContainableItems.Count == 0)
                {
                    return(true);
                }

                if (objective.SubObjectives.None())
                {
                    if (!AIDecontainEmptyItems(character, objective, equip: true, sourceContainer: container))
                    {
                        return(false);
                    }
                }
                if (objective.SubObjectives.None())
                {
                    var loadItemsObjective = AIContainItems <Turret>(container, character, objective, usableProjectileCount + 1, equip: true, removeEmpty: true);
                    loadItemsObjective.ignoredContainerIdentifiers = new string[] { containerItem.prefab.Identifier };
                    character.Speak(TextManager.GetWithVariable("DialogLoadTurret", "[itemname]", item.Name, true), null, 0.0f, "loadturret", 30.0f);
                }
                return(false);
            }

            //enough shells and power
            Character closestEnemy = null;
            float     closestDist  = AIRange * AIRange;

            foreach (Character enemy in Character.CharacterList)
            {
                // Ignore dead, friendly, and those that are inside the same sub
                if (enemy.IsDead || !enemy.Enabled || enemy.Submarine == character.Submarine)
                {
                    continue;
                }
                if (HumanAIController.IsFriendly(character, enemy))
                {
                    continue;
                }

                float dist = Vector2.DistanceSquared(enemy.WorldPosition, item.WorldPosition);
                if (dist > closestDist)
                {
                    continue;
                }

                float angle       = -MathUtils.VectorToAngle(enemy.WorldPosition - item.WorldPosition);
                float midRotation = (minRotation + maxRotation) / 2.0f;
                while (midRotation - angle < -MathHelper.Pi)
                {
                    angle -= MathHelper.TwoPi;
                }
                while (midRotation - angle > MathHelper.Pi)
                {
                    angle += MathHelper.TwoPi;
                }

                if (angle < minRotation || angle > maxRotation)
                {
                    continue;
                }

                closestEnemy = enemy;
                closestDist  = dist;
            }

            if (closestEnemy == null)
            {
                return(false);
            }

            character.AIController.SelectTarget(closestEnemy.AiTarget);

            character.CursorPosition = closestEnemy.WorldPosition;
            if (item.Submarine != null)
            {
                character.CursorPosition -= item.Submarine.Position;
            }

            float enemyAngle  = MathUtils.VectorToAngle(closestEnemy.WorldPosition - item.WorldPosition);
            float turretAngle = -rotation;

            if (Math.Abs(MathUtils.GetShortestAngle(enemyAngle, turretAngle)) > 0.15f)
            {
                return(false);
            }


            Vector2 start = ConvertUnits.ToSimUnits(item.WorldPosition);
            Vector2 end   = ConvertUnits.ToSimUnits(closestEnemy.WorldPosition);

            if (closestEnemy.Submarine != null)
            {
                start -= closestEnemy.Submarine.SimPosition;
                end   -= closestEnemy.Submarine.SimPosition;
            }
            var collisionCategories = Physics.CollisionWall | Physics.CollisionCharacter | Physics.CollisionItem | Physics.CollisionLevel;
            var pickedBody          = Submarine.PickBody(start, end, null, collisionCategories, allowInsideFixture: true,
                                                         customPredicate: (Fixture f) => { return(!item.StaticFixtures.Contains(f)); });

            if (pickedBody == null)
            {
                return(false);
            }
            Character targetCharacter = null;

            if (pickedBody.UserData is Character c)
            {
                targetCharacter = c;
            }
            else if (pickedBody.UserData is Limb limb)
            {
                targetCharacter = limb.character;
            }
            if (targetCharacter != null)
            {
                if (HumanAIController.IsFriendly(character, targetCharacter))
                {
                    // Don't shoot friendly characters
                    return(false);
                }
            }
            else
            {
                if (pickedBody.UserData is ISpatialEntity e)
                {
                    Submarine sub = e.Submarine;
                    if (sub == null)
                    {
                        return(false);
                    }
                    if (sub == Item.Submarine)
                    {
                        return(false);
                    }
                    // Don't shoot non-player submarines, i.e. wrecks or outposts.
                    if (!sub.Info.IsPlayer)
                    {
                        return(false);
                    }
                    // Don't shoot friendly submarines.
                    if (sub.TeamID == Item.Submarine.TeamID)
                    {
                        return(false);
                    }
                }
                else
                {
                    // Hit something else, probably a level wall
                    return(false);
                }
            }
            if (objective.Option.Equals("fireatwill", StringComparison.OrdinalIgnoreCase))
            {
                character?.Speak(TextManager.GetWithVariable("DialogFireTurret", "[itemname]", item.Name, true), null, 0.0f, "fireturret", 5.0f);
                character.SetInput(InputType.Shoot, true, true);
            }
            return(false);
        }
Example #3
0
        public override bool AIOperate(float deltaTime, Character character, AIObjectiveOperateItem objective)
        {
            if (character.AIController.SelectedAiTarget?.Entity is Character previousTarget &&
                previousTarget.IsDead)
            {
                character?.Speak(TextManager.Get("DialogTurretTargetDead"), null, 0.0f, "killedtarget" + previousTarget.ID, 30.0f);
                character.AIController.SelectTarget(null);
            }

            if (GetAvailablePower() < powerConsumption)
            {
                var batteries = item.GetConnectedComponents <PowerContainer>();

                float          lowestCharge  = 0.0f;
                PowerContainer batteryToLoad = null;
                foreach (PowerContainer battery in batteries)
                {
                    if (batteryToLoad == null || battery.Charge < lowestCharge)
                    {
                        batteryToLoad = battery;
                        lowestCharge  = battery.Charge;
                    }
                }

                if (batteryToLoad == null)
                {
                    return(true);
                }

                if (batteryToLoad.RechargeSpeed < batteryToLoad.MaxRechargeSpeed * 0.4f)
                {
                    objective.AddSubObjective(new AIObjectiveOperateItem(batteryToLoad, character, objective.objectiveManager, option: "", requireEquip: false));
                    return(false);
                }
            }

            int usableProjectileCount = 0;
            int maxProjectileCount    = 0;

            foreach (MapEntity e in item.linkedTo)
            {
                if (!(e is Item projectileContainer))
                {
                    continue;
                }

                var containedItems = projectileContainer.ContainedItems;
                if (containedItems != null)
                {
                    var container = projectileContainer.GetComponent <ItemContainer>();
                    maxProjectileCount += container.Capacity;

                    int projectiles = containedItems.Count(it => it.Condition > 0.0f);
                    usableProjectileCount += projectiles;
                }
            }

            if (usableProjectileCount == 0 || (usableProjectileCount < maxProjectileCount && objective.Option.ToLowerInvariant() != "fireatwill"))
            {
                ItemContainer container     = null;
                Item          containerItem = null;
                foreach (MapEntity e in item.linkedTo)
                {
                    containerItem = e as Item;
                    if (containerItem == null)
                    {
                        continue;
                    }

                    container = containerItem.GetComponent <ItemContainer>();
                    if (container != null)
                    {
                        break;
                    }
                }

                if (container == null || container.ContainableItems.Count == 0)
                {
                    return(true);
                }

                if (container.Inventory.Items[0] != null && container.Inventory.Items[0].Condition <= 0.0f)
                {
                    var removeShellObjective = new AIObjectiveDecontainItem(character, container.Inventory.Items[0], container, objective.objectiveManager);
                    objective.AddSubObjective(removeShellObjective);
                }

                var containShellObjective = new AIObjectiveContainItem(character, container.ContainableItems[0].Identifiers[0], container, objective.objectiveManager);
                character?.Speak(TextManager.GetWithVariable("DialogLoadTurret", "[itemname]", item.Name, true), null, 0.0f, "loadturret", 30.0f);
                containShellObjective.targetItemCount             = usableProjectileCount + 1;
                containShellObjective.ignoredContainerIdentifiers = new string[] { containerItem.prefab.Identifier };
                objective.AddSubObjective(containShellObjective);
                return(false);
            }

            //enough shells and power
            Character closestEnemy = null;
            float     closestDist  = 3000 * 3000;

            foreach (Character enemy in Character.CharacterList)
            {
                // Ignore friendly and those that are inside the sub
                if (enemy.IsDead || enemy.AnimController.CurrentHull != null || !enemy.Enabled)
                {
                    continue;
                }
                if (HumanAIController.IsFriendly(character, enemy))
                {
                    continue;
                }

                float dist = Vector2.DistanceSquared(enemy.WorldPosition, item.WorldPosition);
                if (dist > closestDist)
                {
                    continue;
                }

                float angle       = -MathUtils.VectorToAngle(enemy.WorldPosition - item.WorldPosition);
                float midRotation = (minRotation + maxRotation) / 2.0f;
                while (midRotation - angle < -MathHelper.Pi)
                {
                    angle -= MathHelper.TwoPi;
                }
                while (midRotation - angle > MathHelper.Pi)
                {
                    angle += MathHelper.TwoPi;
                }

                if (angle < minRotation || angle > maxRotation)
                {
                    continue;
                }

                closestEnemy = enemy;
                closestDist  = dist;
            }

            if (closestEnemy == null)
            {
                return(false);
            }

            character.AIController.SelectTarget(closestEnemy.AiTarget);

            character.CursorPosition = closestEnemy.WorldPosition;
            if (item.Submarine != null)
            {
                character.CursorPosition -= item.Submarine.Position;
            }

            float enemyAngle  = MathUtils.VectorToAngle(closestEnemy.WorldPosition - item.WorldPosition);
            float turretAngle = -rotation;

            if (Math.Abs(MathUtils.GetShortestAngle(enemyAngle, turretAngle)) > 0.15f)
            {
                return(false);
            }

            var pickedBody = Submarine.PickBody(ConvertUnits.ToSimUnits(item.WorldPosition), closestEnemy.SimPosition);

            if (pickedBody == null)
            {
                return(false);
            }
            Character target = null;

            if (pickedBody.UserData is Character c)
            {
                target = c;
            }
            else if (pickedBody.UserData is Limb limb)
            {
                target = limb.character;
            }
            if (target == null || HumanAIController.IsFriendly(character, target))
            {
                return(false);
            }

            if (objective.Option.ToLowerInvariant() == "fireatwill")
            {
                character?.Speak(TextManager.GetWithVariable("DialogFireTurret", "[itemname]", item.Name, true), null, 0.0f, "fireturret", 5.0f);
                character.SetInput(InputType.Shoot, true, true);
            }

            return(false);
        }
        public override bool AIOperate(float deltaTime, Character character, AIObjectiveOperateItem objective)
        {
            var projectiles = GetLoadedProjectiles();

            if (projectiles.Count == 0 || (projectiles.Count == 1 && objective.Option.ToLowerInvariant() != "fire at will"))
            {
                ItemContainer container = null;
                foreach (MapEntity e in item.linkedTo)
                {
                    var containerItem = e as Item;
                    if (containerItem == null)
                    {
                        continue;
                    }

                    container = containerItem.GetComponent <ItemContainer>();
                    if (container != null)
                    {
                        break;
                    }
                }

                if (container == null || container.ContainableItems.Count == 0)
                {
                    return(true);
                }

                var containShellObjective = new AIObjectiveContainItem(character, container.ContainableItems[0].Names[0], container);
                containShellObjective.IgnoreAlreadyContainedItems = true;
                objective.AddSubObjective(containShellObjective);
                return(false);
            }
            else if (GetAvailablePower() < powerConsumption)
            {
                var batteries = item.GetConnectedComponents <PowerContainer>();

                float          lowestCharge  = 0.0f;
                PowerContainer batteryToLoad = null;
                foreach (PowerContainer battery in batteries)
                {
                    if (batteryToLoad == null || battery.Charge < lowestCharge)
                    {
                        batteryToLoad = battery;
                        lowestCharge  = battery.Charge;
                    }
                }

                if (batteryToLoad == null)
                {
                    return(true);
                }

                if (batteryToLoad.RechargeSpeed < batteryToLoad.MaxRechargeSpeed * 0.4f)
                {
                    objective.AddSubObjective(new AIObjectiveOperateItem(batteryToLoad, character, "", false));
                    return(false);
                }
            }

            //enough shells and power
            Character closestEnemy = null;
            float     closestDist  = 3000.0f;

            foreach (Character enemy in Character.CharacterList)
            {
                //ignore humans and characters that are inside the sub
                if (enemy.IsDead || enemy.SpeciesName == "human" || enemy.AnimController.CurrentHull != null)
                {
                    continue;
                }

                float dist = Vector2.Distance(enemy.WorldPosition, item.WorldPosition);
                if (dist < closestDist)
                {
                    closestEnemy = enemy;
                    closestDist  = dist;
                }
            }

            if (closestEnemy == null)
            {
                return(false);
            }

            character.CursorPosition = closestEnemy.WorldPosition;
            if (item.Submarine != null)
            {
                character.CursorPosition -= item.Submarine.Position;
            }
            character.SetInput(InputType.Aim, false, true);

            float enemyAngle  = MathUtils.VectorToAngle(closestEnemy.WorldPosition - item.WorldPosition);
            float turretAngle = -rotation;

            if (Math.Abs(MathUtils.GetShortestAngle(enemyAngle, turretAngle)) > 0.01f)
            {
                return(false);
            }

            var pickedBody = Submarine.PickBody(ConvertUnits.ToSimUnits(item.WorldPosition), closestEnemy.SimPosition, null);

            if (pickedBody != null && !(pickedBody.UserData is Limb))
            {
                return(false);
            }

            if (objective.Option.ToLowerInvariant() == "fire at will")
            {
                Use(deltaTime, character);
            }

            return(false);
        }
Example #5
0
        //a recursive function that goes through all the junctions and adds up
        //all the generated/consumed power of the constructions connected to the grid
        private void CheckPower(float deltaTime)
        {
            updateTimer = 1;

            connectedPoweredList.Clear();

            foreach (Connection c in powerConnections)
            {
                HashSet <Connection> recipients = connectedRecipients[c];
                foreach (Connection recipient in recipients)
                {
                    if (recipient == null)
                    {
                        continue;
                    }

                    Item it = recipient.Item;
                    if (it == null || it.Condition <= 0.0f)
                    {
                        continue;
                    }

                    foreach (Powered powered in it.GetComponents <Powered>())
                    {
                        if (powered == null || !powered.IsActive)
                        {
                            continue;
                        }
                        PowerTransfer powerTransfer = powered as PowerTransfer;
                        if (powerTransfer != null)
                        {
                            connectedPoweredList.Add(powerTransfer);
                            powerTransfer.updateTimer = 1;
                            continue;
                        }

                        PowerContainer powerContainer = powered as PowerContainer;
                        if (powerContainer != null)
                        {
                            if (recipient.Name == "power_in")
                            {
                                fullLoad += powerContainer.CurrPowerConsumption;
                            }
                            else
                            {
                                fullPower += powerContainer.CurrPowerOutput;
                            }
                        }
                        else
                        {
                            //positive power consumption = the construction requires power -> increase load
                            if (powered.CurrPowerConsumption > 0.0f)
                            {
                                fullLoad += powered.CurrPowerConsumption;
                            }
                            else if (powered.CurrPowerConsumption < 0.0f)
                            //negative power consumption = the construction is a /generator/battery
                            {
                                fullPower -= powered.CurrPowerConsumption;
                            }
                        }
                    }
                }
            }
        }