From db1d0acac94511b45cded9c7f44c8f13d84703af Mon Sep 17 00:00:00 2001 From: Joonas Rikkonen Date: Fri, 29 Mar 2019 17:21:52 +0200 Subject: [PATCH] (4d569f38c) AI characters can take out excess fuel rods from the reactor, and calculate if more fuel is needed to keep the output at a suitable level instead of only adding more fuel when the reactor is completely empty. --- .../Items/Components/Machines/Reactor.cs | 75 ++++++++++++++++--- 1 file changed, 64 insertions(+), 11 deletions(-) diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Reactor.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Reactor.cs index 8e5c9ddb7..d736d48a4 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Reactor.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Reactor.cs @@ -49,7 +49,7 @@ namespace Barotrauma.Items.Components private bool shutDown; - const float AIUpdateInterval = 1.0f; + const float AIUpdateInterval = 0.2f; private float aiUpdateTimer; private Character lastUser; @@ -209,7 +209,7 @@ namespace Barotrauma.Items.Components allowedFissionRate = Vector2.Lerp(new Vector2(20, AvailableFuel), new Vector2(10, AvailableFuel), degreeOfSuccess); allowedFissionRate.X = Math.Min(allowedFissionRate.X, allowedFissionRate.Y - 10); - float heatAmount = fissionRate * (AvailableFuel / 100.0f) * 2.0f; + float heatAmount = GetGeneratedHeat(fissionRate); float temperatureDiff = (heatAmount - turbineOutput) - Temperature; Temperature += MathHelper.Clamp(Math.Sign(temperatureDiff) * 10.0f * deltaTime, -Math.Abs(temperatureDiff), Math.Abs(temperatureDiff)); //if (item.InWater && AvailableFuel < 100.0f) Temperature -= 12.0f * deltaTime; @@ -313,6 +313,43 @@ namespace Barotrauma.Items.Components } } + private float GetGeneratedHeat(float fissionRate) + { + return fissionRate * (prevAvailableFuel / 100.0f) * 2.0f; + } + + private bool NeedMoreFuel() + { + if (prevAvailableFuel <= 0.0f && load > 0.0f) + { + return true; + } + + //fission rate is clamped to the amount of available fuel + float maxFissionRate = Math.Min(prevAvailableFuel, 100.0f); + float maxTurbineOutput = 100.0f; + + //calculate the maximum output if the fission rate is cranked as high as it goes and turbine output is at max + float theoreticalMaxHeat = GetGeneratedHeat(fissionRate: maxFissionRate); + float temperatureFactor = Math.Min(theoreticalMaxHeat / 50.0f, 1.0f); + float theoreticalMaxOutput = Math.Min(maxTurbineOutput / 100.0f, temperatureFactor) * MaxPowerOutput; + + //maximum output not enough, we need more fuel + return theoreticalMaxOutput < load; + } + + private bool TooMuchFuel() + { + var containedItems = item.ContainedItems; + if (containedItems != null && containedItems.Count() <= 1) { return false; } + + //get the amount of heat we'd generate if the fission rate was at the low end of the optimal range + float minimumHeat = GetGeneratedHeat(optimalFissionRate.X); + + //if we need a very high turbine output to keep the engine from overheating, there's too much fuel + return minimumHeat > Math.Min(correctTurbineOutput * 1.5f, 90); + } + private void UpdateFailures(float deltaTime) { if (temperature > allowedTemperature.Y) @@ -367,6 +404,9 @@ namespace Barotrauma.Items.Components targetFissionRate = Math.Min(targetFissionRate + speed * 2 * deltaTime, 100.0f); } targetFissionRate = MathHelper.Clamp(targetFissionRate, 0.0f, 100.0f); + + //don't push the target too far from the current fission rate + targetFissionRate = MathHelper.Clamp(targetFissionRate, FissionRate - 10, FissionRate + 10); } public override void UpdateBroken(float deltaTime, Camera cam) @@ -441,12 +481,18 @@ namespace Barotrauma.Items.Components } } + if (aiUpdateTimer > 0.0f) + { + aiUpdateTimer -= deltaTime; + return false; + } + //we need more fuel - if (-currPowerConsumption < load * 0.5f && prevAvailableFuel <= 0.0f) + if (NeedMoreFuel()) { var containFuelObjective = new AIObjectiveContainItem(character, new string[] { "fuelrod", "reactorfuel" }, item.GetComponent()) { - MinContainedAmount = containedItems.Count(i => i != null && i.Prefab.Identifier == "fuelrod" || i.HasTag("reactorfuel")) + 1, + MinContainedAmount = item.ContainedItems.Count(i => i != null && i.Prefab.Identifier == "fuelrod" || i.HasTag("reactorfuel")) + 1, GetItemPriority = (Item fuelItem) => { if (fuelItem.ParentInventory?.Owner is Item) @@ -461,14 +507,21 @@ namespace Barotrauma.Items.Components character?.Speak(TextManager.Get("DialogReactorFuel"), null, 0.0f, "reactorfuel", 30.0f); + aiUpdateTimer = AIUpdateInterval; return false; } - } - - if (aiUpdateTimer > 0.0f) - { - aiUpdateTimer -= deltaTime; - return false; + else if (TooMuchFuel()) + { + foreach (Item item in item.ContainedItems) + { + //TODO: put in a container instead of dropping? + if (item != null && item.HasTag("reactorfuel")) + { + item.Drop(character); + break; + } + } + } } if (lastUser != character && lastUser != null && lastUser.SelectedConstruction == item) @@ -492,7 +545,7 @@ namespace Barotrauma.Items.Components { AutoTemp = false; unsentChanges = true; - UpdateAutoTemp(2.0f + degreeOfSuccess * 5.0f, 1.0f); + UpdateAutoTemp(MathHelper.Lerp(0.5f, 2.0f, degreeOfSuccess), 1.0f); } #if CLIENT onOffSwitch.BarScroll = 0.0f;