v0.14.6.0

This commit is contained in:
Joonas Rikkonen
2021-06-17 17:54:52 +03:00
parent 3f324b14e8
commit c27e2ea5ab
348 changed files with 13156 additions and 4266 deletions
@@ -172,14 +172,23 @@ namespace Barotrauma.Items.Components
float scaledDamageRange = propellerDamage.DamageRange * item.Scale;
Vector2 propellerWorldPos = item.WorldPosition + PropellerPos * item.Scale;
Vector2 propellerWorldPos = item.WorldPosition + PropellerPos * item.Scale;
float broadRange = Math.Max(scaledDamageRange * 2, 500);
foreach (Character character in Character.CharacterList)
{
if (!character.Enabled || character.Removed) { continue; }
float distSqr = Vector2.DistanceSquared(character.WorldPosition, propellerWorldPos);
if (distSqr > scaledDamageRange * scaledDamageRange) { continue; }
character.LastDamageSource = item;
propellerDamage.DoDamage(null, character, propellerWorldPos, 1.0f, true);
if (Math.Abs(character.WorldPosition.X - propellerWorldPos.X) > broadRange) { continue; }
if (Math.Abs(character.WorldPosition.Y - propellerWorldPos.Y) > broadRange) { continue; }
foreach (Limb limb in character.AnimController.Limbs)
{
if (limb.IsSevered || !limb.body.Enabled) { continue; }
float distSqr = Vector2.DistanceSquared(limb.WorldPosition, propellerWorldPos);
if (distSqr > scaledDamageRange * scaledDamageRange) { continue; }
character.LastDamageSource = item;
propellerDamage.DoDamage(null, character, propellerWorldPos, 1.0f, true);
break;
}
}
}
@@ -290,10 +290,12 @@ namespace Barotrauma.Items.Components
{
for (int i = 0; i < ingredient.Amount; i++)
{
var availableItem = availableIngredients.FirstOrDefault(it => it != null && ingredient.ItemPrefabs.Contains(it.Prefab) && it.ConditionPercentage >= ingredient.MinCondition * 100.0f);
var availableItem = availableIngredients.FirstOrDefault(it =>
it != null && ingredient.ItemPrefabs.Contains(it.Prefab) &&
it.ConditionPercentage >= ingredient.MinCondition * 100.0f &&
it.ConditionPercentage <= ingredient.MaxCondition * 100.0f);
if (availableItem == null) { continue; }
//Item4 = use condition bool
if (ingredient.UseCondition && availableItem.ConditionPercentage - ingredient.MinCondition * 100 > 0.0f) //Leave it behind with reduced condition if it has enough to stay above 0
{
availableItem.Condition -= availableItem.Prefab.Health * ingredient.MinCondition;
@@ -493,7 +495,8 @@ namespace Barotrauma.Items.Components
return
item != null &&
requiredItem.ItemPrefabs.Contains(item.prefab) &&
item.Condition / item.Prefab.Health >= requiredItem.MinCondition;
item.Condition / item.Prefab.Health >= requiredItem.MinCondition &&
item.Condition / item.Prefab.Health <= requiredItem.MaxCondition;
}
public override XElement Save(XElement parentElement)
@@ -67,6 +67,9 @@ namespace Barotrauma.Items.Components
public Character LastAIUser { get; private set; }
[Serialize(defaultValue: false, isSaveable: true)]
public bool LastUserWasPlayer { get; private set; }
private Character lastUser;
public Character LastUser
{
@@ -178,8 +181,6 @@ namespace Barotrauma.Items.Components
[Serialize(0.0f, true)]
public float AvailableFuel { get; set; }
public bool LastUserWasPlayer { get; private set; }
public Reactor(Item item, XElement element)
: base(item, element)
{
@@ -241,7 +242,7 @@ namespace Barotrauma.Items.Components
optimalTurbineOutput = new Vector2(correctTurbineOutput - tolerance, correctTurbineOutput + tolerance);
tolerance = MathHelper.Lerp(5.0f, 20.0f, degreeOfSuccess);
allowedTurbineOutput = new Vector2(correctTurbineOutput - tolerance, correctTurbineOutput + tolerance);
optimalTemperature = Vector2.Lerp(new Vector2(40.0f, 60.0f), new Vector2(30.0f, 70.0f), degreeOfSuccess);
allowedTemperature = Vector2.Lerp(new Vector2(30.0f, 70.0f), new Vector2(10.0f, 90.0f), degreeOfSuccess);
@@ -251,11 +252,13 @@ namespace Barotrauma.Items.Components
allowedFissionRate.X = Math.Min(allowedFissionRate.X, allowedFissionRate.Y - 10);
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;
FissionRate = MathHelper.Lerp(fissionRate, Math.Min(targetFissionRate, AvailableFuel), deltaTime);
TurbineOutput = MathHelper.Lerp(turbineOutput, targetTurbineOutput, deltaTime);
float temperatureFactor = Math.Min(temperature / 50.0f, 1.0f);
@@ -311,6 +314,38 @@ namespace Barotrauma.Items.Components
}
}
if (!loadQueue.Any() && PowerOn)
{
//loadQueue is empty, round must've just started
//reset the fission rate, turbine output and
//temperature to optimal levels to prevent fires
//at the start of the round
correctTurbineOutput = currentLoad / MaxPowerOutput * 100.0f;
tolerance = MathHelper.Lerp(2.5f, 10.0f, degreeOfSuccess);
optimalTurbineOutput = new Vector2(correctTurbineOutput - tolerance, correctTurbineOutput + tolerance);
tolerance = MathHelper.Lerp(5.0f, 20.0f, degreeOfSuccess);
allowedTurbineOutput = new Vector2(correctTurbineOutput - tolerance, correctTurbineOutput + tolerance);
DebugConsole.Log($"Degree of success: {degreeOfSuccess}");
DebugConsole.Log($"Current load: {currentLoad}");
DebugConsole.Log($"Max power output: {MaxPowerOutput}");
DebugConsole.Log($"Available fuel: {AvailableFuel}");
float desiredTurbineOutput = MathHelper.Clamp(correctTurbineOutput, 0.0f, 100.0f);
DebugConsole.Log($"Turbine output reset: {targetTurbineOutput}, {turbineOutput} -> {desiredTurbineOutput}");
targetTurbineOutput = desiredTurbineOutput;
turbineOutput = desiredTurbineOutput;
float desiredTemperature = (optimalTemperature.X + optimalTemperature.Y) / 2.0f;
DebugConsole.Log($"Temperature reset: {temperature} -> {desiredTemperature}");
temperature = desiredTemperature;
float desiredFissionRate = GetFissionRateForTargetTemperatureAndTurbineOutput(desiredTemperature, desiredTurbineOutput);
DebugConsole.Log($"Fission rate reset: {targetFissionRate}, {fissionRate} -> {desiredFissionRate}");
targetFissionRate = desiredFissionRate;
fissionRate = desiredFissionRate;
}
loadQueue.Enqueue(currentLoad);
while (loadQueue.Count() > 60.0f)
{
@@ -390,6 +425,12 @@ namespace Barotrauma.Items.Components
return fissionRate * (prevAvailableFuel / 100.0f) * 2.0f;
}
private float GetFissionRateForTargetTemperatureAndTurbineOutput(float temperature, float turbineOutput)
{
if (MathUtils.NearlyEqual(AvailableFuel, 0f)) { return 0f; }
return (temperature + turbineOutput) / (AvailableFuel / 100f) / 2f;
}
/// <summary>
/// Do we need more fuel to generate enough power to match the current load.
/// </summary>
@@ -564,6 +605,7 @@ namespace Barotrauma.Items.Components
public override bool AIOperate(float deltaTime, Character character, AIObjectiveOperateItem objective)
{
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) { return false; }
character.AIController.SteeringManager.Reset();
bool shutDown = objective.Option.Equals("shutdown", StringComparison.OrdinalIgnoreCase);
IsActive = true;
@@ -598,6 +640,7 @@ namespace Barotrauma.Items.Components
void ReportFuelRodCount()
{
if (!character.IsOnPlayerTeam) { return; }
if (character.Submarine != Submarine.MainSub) { return; }
int remainingFuelRods = Submarine.MainSub.GetItems(false).Count(i => i.HasTag("reactorfuel") && i.Condition > 1);
if (remainingFuelRods == 0)
{
@@ -614,6 +657,18 @@ namespace Barotrauma.Items.Components
}
else
{
if (Item.ConditionPercentage <= 0 && AIObjectiveRepairItems.IsValidTarget(Item, character))
{
if (Item.Repairables.Average(r => r.DegreeOfSuccess(character)) > 0.4f)
{
objective.AddSubObjective(new AIObjectiveRepairItem(character, Item, objective.objectiveManager, isPriority: true));
return false;
}
else
{
character.Speak(TextManager.Get("DialogReactorIsBroken"), identifier: "reactorisbroken", minDurationBetweenSimilar: 30.0f);
}
}
if (TooMuchFuel())
{
DropFuel(minCondition: 0.1f, maxCondition: 100);
@@ -728,7 +783,7 @@ namespace Barotrauma.Items.Components
case "set_fissionrate":
if (PowerOn && float.TryParse(signal.value, NumberStyles.Float, CultureInfo.InvariantCulture, out float newFissionRate))
{
targetFissionRate = newFissionRate;
targetFissionRate = MathHelper.Clamp(newFissionRate, 0.0f, 100.0f);
if (GameMain.NetworkMember?.IsServer ?? false) { unsentChanges = true; }
#if CLIENT
FissionRateScrollBar.BarScroll = targetFissionRate / 100.0f;
@@ -738,7 +793,7 @@ namespace Barotrauma.Items.Components
case "set_turbineoutput":
if (PowerOn && float.TryParse(signal.value, NumberStyles.Float, CultureInfo.InvariantCulture, out float newTurbineOutput))
{
targetTurbineOutput = newTurbineOutput;
targetTurbineOutput = MathHelper.Clamp(newTurbineOutput, 0.0f, 100.0f);
if (GameMain.NetworkMember?.IsServer ?? false) { unsentChanges = true; }
#if CLIENT
TurbineOutputScrollBar.BarScroll = targetTurbineOutput / 100.0f;
@@ -57,6 +57,11 @@ namespace Barotrauma.Items.Components
private Submarine controlledSub;
// AI interfacing
public Vector2 AITacticalTarget { get; set; }
public float AIRamTimer { get; set; }
bool navigateTactically; // this will be removed after rewriting steering to use an enum
private bool showIceSpireWarning;
private List<Submarine> connectedSubs = new List<Submarine>();
@@ -305,7 +310,13 @@ namespace Barotrauma.Items.Components
userSkill = user.GetSkillLevel("helm") / 100.0f;
}
if (AutoPilot)
// override autopilot pathing while the AI rams, and go full speed ahead
if (AIRamTimer > 0f)
{
AIRamTimer -= deltaTime;
TargetVelocity = GetSteeringVelocity(AITacticalTarget, 0f);
}
else if (AutoPilot)
{
UpdateAutoPilot(deltaTime);
float throttle = 1.0f;
@@ -352,6 +363,14 @@ namespace Barotrauma.Items.Components
float velY = MathHelper.Lerp((neutralBallastLevel * 100 - 50) * 2, -100 * Math.Sign(targetVelocity.Y), Math.Abs(targetVelocity.Y) / 100.0f);
item.SendSignal(new Signal(velY.ToString(CultureInfo.InvariantCulture), sender: user), "velocity_y_out");
// if our tactical AI pilot has left, revert back to maintaining position
if (navigateTactically && (user == null || user.SelectedConstruction != item))
{
navigateTactically = false;
AIRamTimer = 0f;
SetMaintainPosition();
}
}
private void IncreaseSkillLevel(Character user, float deltaTime)
@@ -580,13 +599,18 @@ namespace Barotrauma.Items.Components
}
Vector2 target;
if (LevelEndSelected)
if (navigateTactically)
{
target = ConvertUnits.ToSimUnits(Level.Loaded.EndPosition);
target = ConvertUnits.ToSimUnits(AITacticalTarget);
}
else if (LevelEndSelected)
{
target = ConvertUnits.ToSimUnits(Level.Loaded.EndExitPosition);
}
else
{
target = ConvertUnits.ToSimUnits(Level.Loaded.StartPosition);
target = ConvertUnits.ToSimUnits(Level.Loaded.StartExitPosition);
}
steeringPath = pathFinder.FindPath(ConvertUnits.ToSimUnits(controlledSub == null ? item.WorldPosition : controlledSub.WorldPosition), target, errorMsgStr: "(Autopilot, target: " + target + ")");
}
@@ -597,6 +621,7 @@ namespace Barotrauma.Items.Components
MaintainPos = false;
posToMaintain = null;
LevelEndSelected = false;
navigateTactically = false;
if (!LevelStartSelected)
{
LevelStartSelected = true;
@@ -610,6 +635,7 @@ namespace Barotrauma.Items.Components
MaintainPos = false;
posToMaintain = null;
LevelStartSelected = false;
navigateTactically = false;
if (!LevelEndSelected)
{
LevelEndSelected = true;
@@ -617,6 +643,36 @@ namespace Barotrauma.Items.Components
}
}
private void SetDestinationTactical()
{
AutoPilot = true;
MaintainPos = false;
posToMaintain = null;
LevelStartSelected = false;
LevelEndSelected = false;
if (!navigateTactically)
{
navigateTactically = true;
UpdatePath();
}
}
private void SetMaintainPosition()
{
if (!MaintainPos)
{
unsentChanges = true;
MaintainPos = true;
}
if (!posToMaintain.HasValue)
{
unsentChanges = true;
posToMaintain = controlledSub != null ?
controlledSub.WorldPosition :
item.Submarine == null ? item.WorldPosition : item.Submarine.WorldPosition;
}
}
/// <summary>
/// Get optimal velocity for moving towards a position
/// </summary>
@@ -640,6 +696,7 @@ namespace Barotrauma.Items.Components
public override bool AIOperate(float deltaTime, Character character, AIObjectiveOperateItem objective)
{
character.AIController.SteeringManager.Reset();
if (objective.Override)
{
if (user != character && user != null && user.SelectedConstruction == item && character.IsOnPlayerTeam)
@@ -648,6 +705,20 @@ namespace Barotrauma.Items.Components
}
}
user = character;
if (Item.ConditionPercentage <= 0 && AIObjectiveRepairItems.IsValidTarget(Item, character))
{
if (Item.Repairables.Average(r => r.DegreeOfSuccess(character)) > 0.4f)
{
objective.AddSubObjective(new AIObjectiveRepairItem(character, Item, objective.objectiveManager, isPriority: true));
return false;
}
else
{
character.Speak(TextManager.Get("DialogNavTerminalIsBroken"), identifier: "navterminalisbroken", minDurationBetweenSimilar: 30.0f);
}
}
if (!AutoPilot)
{
unsentChanges = true;
@@ -659,18 +730,7 @@ namespace Barotrauma.Items.Components
case "maintainposition":
if (objective.Override)
{
if (!MaintainPos)
{
unsentChanges = true;
MaintainPos = true;
}
if (!posToMaintain.HasValue)
{
unsentChanges = true;
posToMaintain = controlledSub != null ?
controlledSub.WorldPosition :
item.Submarine == null ? item.WorldPosition : item.Submarine.WorldPosition;
}
SetMaintainPosition();
}
break;
case "navigateback":
@@ -681,7 +741,7 @@ namespace Barotrauma.Items.Components
}
if (objective.Override)
{
if (MaintainPos || LevelEndSelected || !LevelStartSelected)
if (MaintainPos || LevelEndSelected || !LevelStartSelected || navigateTactically)
{
unsentChanges = true;
}
@@ -696,13 +756,28 @@ namespace Barotrauma.Items.Components
}
if (objective.Override)
{
if (MaintainPos || !LevelEndSelected || LevelStartSelected)
if (MaintainPos || !LevelEndSelected || LevelStartSelected || navigateTactically)
{
unsentChanges = true;
}
SetDestinationLevelEnd();
}
break;
case "navigatetactical":
if (Level.IsLoadedOutpost) { break; }
if (DockingSources.Any(d => d.Docked))
{
item.SendSignal("1", "toggle_docking");
}
if (objective.Override)
{
if (MaintainPos || LevelEndSelected || LevelStartSelected || !navigateTactically)
{
unsentChanges = true;
}
SetDestinationTactical();
}
break;
}
sonar?.AIOperate(deltaTime, character, objective);
if (!MaintainPos && showIceSpireWarning && character.IsOnPlayerTeam)