v0.11.0.9

This commit is contained in:
Joonas Rikkonen
2020-12-09 16:34:16 +02:00
parent bbf06f0984
commit f433a7ba10
325 changed files with 13947 additions and 3652 deletions
@@ -318,16 +318,12 @@ namespace Barotrauma.Items.Components
if (!character.IsRemotePlayer || character.ViewTarget == focusTarget)
{
Vector2 centerPos = new Vector2(item.WorldRect.Center.X, item.WorldRect.Center.Y);
Vector2 centerPos = new Vector2(focusTarget.WorldRect.Center.X, focusTarget.WorldRect.Center.Y);
Item targetItem = focusTarget as Item;
if (targetItem != null)
Turret turret = focusTarget.GetComponent<Turret>();
if (turret != null)
{
Turret turret = targetItem.GetComponent<Turret>();
if (turret != null)
{
centerPos = new Vector2(targetItem.WorldRect.X + turret.TransformedBarrelPos.X, targetItem.WorldRect.Y - turret.TransformedBarrelPos.Y);
}
centerPos = new Vector2(focusTarget.WorldRect.X + turret.TransformedBarrelPos.X, focusTarget.WorldRect.Y - turret.TransformedBarrelPos.Y);
}
Vector2 offset = character.CursorWorldPosition - centerPos;
@@ -356,6 +352,9 @@ namespace Barotrauma.Items.Components
public override bool Pick(Character picker)
{
#if CLIENT
if (Screen.Selected == GameMain.SubEditorScreen) { return false; }
#endif
if (IsToggle)
{
if (GameMain.NetworkMember == null || GameMain.NetworkMember.IsServer)
@@ -123,7 +123,7 @@ namespace Barotrauma.Items.Components
//drop all items that are inside the deconstructed item
foreach (ItemContainer ic in targetItem.GetComponents<ItemContainer>())
{
if (ic?.Inventory?.Items == null) { continue; }
if (ic?.Inventory?.Items == null || ic.RemoveContainedItemsOnDeconstruct) { continue; }
foreach (Item containedItem in ic.Inventory.Items)
{
containedItem?.Drop(dropper: null, createNetworkEvent: true);
@@ -113,7 +113,7 @@ namespace Barotrauma.Items.Components
forceMultiplier *= MathHelper.Lerp(0.5f, 2.0f, (float)Math.Sqrt(User.GetSkillLevel("helm") / 100));
}
float voltageFactor = MinVoltage <= 0.0f ? 1.0f : Math.Min(Voltage / MinVoltage, 1.0f);
float voltageFactor = MinVoltage <= 0.0f ? 1.0f : Math.Min(Voltage, 1.0f);
Vector2 currForce = new Vector2(force * maxForce * forceMultiplier * voltageFactor, 0.0f);
//less effective when in a bad condition
currForce *= MathHelper.Lerp(0.5f, 2.0f, item.Condition / item.MaxCondition);
@@ -121,7 +121,7 @@ namespace Barotrauma.Items.Components
UpdatePropellerDamage(deltaTime);
float maxChangeSpeed = 0.5f;
float modifier = 2;
float noise = currForce.Length() * forceMultiplier * modifier / maxForce;
float noise = MathUtils.NearlyEqual(0.0f, maxForce) ? 0.0f : currForce.Length() * forceMultiplier * modifier / maxForce;
float min = Math.Max(1 - maxChangeSpeed, 0);
float max = 1 + maxChangeSpeed;
UpdateAITargets(Math.Clamp(noise, min, max), deltaTime);
@@ -482,9 +482,9 @@ namespace Barotrauma.Items.Components
return componentElement;
}
public override void Load(XElement componentElement, bool usePrefabValues)
public override void Load(XElement componentElement, bool usePrefabValues, IdRemap idRemap)
{
base.Load(componentElement, usePrefabValues);
base.Load(componentElement, usePrefabValues, idRemap);
savedFabricatedItem = componentElement.GetAttributeString("fabricateditemidentifier", "");
savedTimeUntilReady = componentElement.GetAttributeFloat("savedtimeuntilready", 0.0f);
savedRequiredTime = componentElement.GetAttributeFloat("savedrequiredtime", 0.0f);
@@ -8,11 +8,10 @@ namespace Barotrauma.Items.Components
{
class OxygenGenerator : Powered
{
private float powerDownTimer;
private float generatedAmount;
private List<Vent> ventList;
//key = vent, float = total volume of the hull the vent is in and the hulls connected to it
private Dictionary<Vent, float> ventList;
private float totalHullVolume;
@@ -49,17 +48,12 @@ namespace Barotrauma.Items.Components
Voltage = 1.0f;
}
if (item.CurrentHull == null) return;
if (item.CurrentHull == null) { return; }
if (Voltage < MinVoltage)
{
powerDownTimer += deltaTime;
return;
}
else
{
powerDownTimer = 0.0f;
}
CurrFlow = Math.Min(Voltage, 1.0f) * generatedAmount * 100.0f;
@@ -76,24 +70,25 @@ namespace Barotrauma.Items.Components
public override void UpdateBroken(float deltaTime, Camera cam)
{
base.UpdateBroken(deltaTime, cam);
powerDownTimer += deltaTime;
CurrFlow = 0.0f;
}
private void GetVents()
{
ventList.Clear();
ventList = new Dictionary<Vent, float>();
foreach (MapEntity entity in item.linkedTo)
{
Item linkedItem = entity as Item;
if (linkedItem == null) continue;
if (!(entity is Item linkedItem)) { continue; }
Vent vent = linkedItem.GetComponent<Vent>();
if (vent == null) continue;
if (vent?.Item.CurrentHull == null) { continue; }
ventList.Add(vent);
if (linkedItem.CurrentHull != null) totalHullVolume += linkedItem.CurrentHull.Volume;
ventList.Add(vent, 0.0f);
foreach (Hull connectedHull in vent.Item.CurrentHull.GetConnectedHulls(includingThis: true, searchDepth: 10, ignoreClosedGaps: true))
{
totalHullVolume += connectedHull.Volume;
ventList[vent] += connectedHull.Volume;
}
}
}
@@ -101,18 +96,17 @@ namespace Barotrauma.Items.Components
{
if (ventList == null)
{
ventList = new List<Vent>();
GetVents();
}
if (!ventList.Any() || totalHullVolume <= 0.0f) return;
if (!ventList.Any() || totalHullVolume <= 0.0f) { return; }
foreach (Vent v in ventList)
foreach (KeyValuePair<Vent, float> v in ventList)
{
if (v.Item.CurrentHull == null) continue;
if (v.Key?.Item.CurrentHull == null) { continue; }
v.OxygenFlow = deltaOxygen * (v.Item.CurrentHull.Volume / totalHullVolume);
v.IsActive = true;
v.Key.OxygenFlow = deltaOxygen * (v.Value / totalHullVolume);
v.Key.IsActive = true;
}
}
}
@@ -2,7 +2,9 @@
using Microsoft.Xna.Framework;
using System;
using System.Globalization;
using System.Linq;
using System.Xml.Linq;
using Barotrauma.MapCreatures.Behavior;
namespace Barotrauma.Items.Components
{
@@ -11,10 +13,38 @@ namespace Barotrauma.Items.Components
private float flowPercentage;
private float maxFlow;
private float? targetLevel;
public float? TargetLevel;
private bool hijacked;
public bool Hijacked
{
get { return hijacked; }
set
{
if (value == hijacked) { return; }
hijacked = value;
#if SERVER
item.CreateServerEvent(this);
#endif
}
}
private float pumpSpeedLockTimer, isActiveLockTimer;
private bool infected;
[Serialize(false, true, description: "Whether or not the pump is infected with ballast flora spores.")]
public bool Infected
{
get => infected;
set
{
infected = value;
}
}
public string InfectIdentifier;
[Serialize(0.0f, true, description: "How fast the item is currently pumping water (-100 = full speed out, 100 = full speed in). Intended to be used by StatusEffect conditionals (setting this value in XML has no effect).")]
public float FlowPercentage
{
@@ -66,12 +96,12 @@ namespace Barotrauma.Items.Components
{
currFlow = 0.0f;
if (targetLevel != null)
if (TargetLevel != null)
{
pumpSpeedLockTimer -= deltaTime;
float hullPercentage = 0.0f;
if (item.CurrentHull != null) { hullPercentage = (item.CurrentHull.WaterVolume / item.CurrentHull.Volume) * 100.0f; }
FlowPercentage = ((float)targetLevel - hullPercentage) * 10.0f;
FlowPercentage = ((float)TargetLevel - hullPercentage) * 10.0f;
}
currPowerConsumption = powerConsumption * Math.Abs(flowPercentage / 100.0f);
@@ -92,14 +122,41 @@ namespace Barotrauma.Items.Components
//less effective when in a bad condition
currFlow *= MathHelper.Lerp(0.5f, 1.0f, item.Condition / item.MaxCondition);
if (currFlow < 0 && Infected)
{
InfectBallast(InfectIdentifier);
}
Infected = false;
item.CurrentHull.WaterVolume += currFlow;
if (item.CurrentHull.WaterVolume > item.CurrentHull.Volume) { item.CurrentHull.Pressure += 0.5f; }
}
public void InfectBallast(string identifier)
{
Hull hull = item.CurrentHull;
if (hull == null) { return; }
// if the ship is already infected then do nothing
if (Hull.hullList.Where(h => h.Submarine == hull.Submarine).Any(h => h.BallastFlora != null)) { return; }
if (hull.BallastFlora != null) { return; }
Vector2 offset = item.WorldPosition - hull.WorldPosition;
hull.BallastFlora = new BallastFloraBehavior(hull, BallastFloraPrefab.Find(identifier), offset, firstGrowth: true);
#if SERVER
hull.BallastFlora.SendNetworkMessage(hull.BallastFlora, BallastFloraBehavior.NetworkHeader.Spawn);
#endif
}
partial void UpdateProjSpecific(float deltaTime);
public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0.0f, float signalStrength = 1.0f)
{
if (Hijacked) { return; }
if (connection.Name == "toggle")
{
IsActive = !IsActive;
@@ -115,7 +172,7 @@ namespace Barotrauma.Items.Components
if (float.TryParse(signal, NumberStyles.Any, CultureInfo.InvariantCulture, out float tempSpeed))
{
flowPercentage = MathHelper.Clamp(tempSpeed, -100.0f, 100.0f);
targetLevel = null;
TargetLevel = null;
pumpSpeedLockTimer = 0.1f;
}
}
@@ -123,7 +180,7 @@ namespace Barotrauma.Items.Components
{
if (float.TryParse(signal, NumberStyles.Any, CultureInfo.InvariantCulture, out float tempTarget))
{
targetLevel = MathHelper.Clamp(tempTarget + 50.0f, 0.0f, 100.0f);
TargetLevel = MathHelper.Clamp(tempTarget + 50.0f, 0.0f, 100.0f);
pumpSpeedLockTimer = 0.1f;
}
}
@@ -137,7 +137,7 @@ namespace Barotrauma.Items.Components
}
}
[Serialize(0.2f, true, description: "How fast the condition of the contained fuel rods deteriorates per second."), Editable(0.0f, 1000.0f)]
[Serialize(0.2f, true, description: "How fast the condition of the contained fuel rods deteriorates per second."), Editable(0.0f, 1000.0f, decimals: 3)]
public float FuelConsumptionRate
{
get { return fuelConsumptionRate; }
@@ -399,6 +399,8 @@ namespace Barotrauma.Items.Components
//fission rate is clamped to the amount of available fuel
float maxFissionRate = Math.Min(prevAvailableFuel, 100.0f);
if (maxFissionRate >= 100.0f) { return false; }
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
@@ -589,7 +591,7 @@ namespace Barotrauma.Items.Components
if (objective.SubObjectives.None())
{
int itemCount = item.ContainedItems.Count(i => i != null && container.ContainableItems.Any(ri => ri.MatchesItem(i))) + 1;
AIContainItems<Reactor>(container, character, objective, itemCount, equip: false, removeEmpty: true, spawnItemIfNotFound: character.TeamID == Character.TeamType.FriendlyNPC);
AIContainItems<Reactor>(container, character, objective, itemCount, equip: false, removeEmpty: true, spawnItemIfNotFound: character.TeamID == Character.TeamType.FriendlyNPC, dropItemOnDeselected: true);
character.Speak(TextManager.Get("DialogReactorFuel"), null, 0.0f, "reactorfuel", 30.0f);
}
return false;
@@ -604,10 +606,7 @@ namespace Barotrauma.Items.Components
{
if (item != null && container.ContainableItems.Any(ri => ri.MatchesItem(item)))
{
if (!character.Inventory.TryPutItem(item, character, allowedSlots: item.AllowedSlots))
{
item.Drop(character);
}
item.Drop(character);
break;
}
}
@@ -64,6 +64,7 @@ namespace Barotrauma.Items.Components
private bool useDirectionalPing = false;
private Vector2 pingDirection = new Vector2(1.0f, 0.0f);
private bool useMineralScanner;
private bool aiPingCheckPending;
@@ -103,6 +104,10 @@ namespace Barotrauma.Items.Components
set;
}
[Editable, Serialize(false, false, description: "Does the sonar have mineral scanning mode. " +
"Only available in-game when the Item has no Steering component.")]
public bool HasMineralScanner { get; set; }
public float Zoom
{
get { return zoom; }
@@ -343,6 +348,7 @@ namespace Barotrauma.Items.Components
bool isActive = msg.ReadBoolean();
bool directionalPing = useDirectionalPing;
float zoomT = zoom, pingDirectionT = 0.0f;
bool mineralScanner = useMineralScanner;
if (isActive)
{
zoomT = msg.ReadRangedSingle(0.0f, 1.0f, 8);
@@ -351,6 +357,7 @@ namespace Barotrauma.Items.Components
{
pingDirectionT = msg.ReadRangedSingle(0.0f, 1.0f, 8);
}
mineralScanner = msg.ReadBoolean();
}
if (!item.CanClientAccess(c)) { return; }
@@ -366,9 +373,14 @@ namespace Barotrauma.Items.Components
float pingAngle = MathHelper.Lerp(0.0f, MathHelper.TwoPi, pingDirectionT);
pingDirection = new Vector2((float)Math.Cos(pingAngle), (float)Math.Sin(pingAngle));
}
useMineralScanner = mineralScanner;
#if CLIENT
zoomSlider.BarScroll = zoomT;
directionalModeSwitch.Selected = useDirectionalPing;
if (mineralScannerSwitch != null)
{
mineralScannerSwitch.Selected = useMineralScanner;
}
#endif
}
#if SERVER
@@ -388,6 +400,7 @@ namespace Barotrauma.Items.Components
float pingAngle = MathUtils.WrapAngleTwoPi(MathUtils.VectorToAngle(pingDirection));
msg.WriteRangedSingle(MathUtils.InverseLerp(0.0f, MathHelper.TwoPi, pingAngle), 0.0f, 1.0f, 8);
}
msg.Write(useMineralScanner);
}
}
}
@@ -67,7 +67,10 @@ namespace Barotrauma.Items.Components
{
if (pathFinder == null)
{
pathFinder = new PathFinder(WayPoint.WayPointList, false);
pathFinder = new PathFinder(WayPoint.WayPointList, false)
{
GetNodePenalty = GetNodePenalty
};
}
MaintainPos = true;
if (posToMaintain == null)
@@ -87,7 +90,7 @@ namespace Barotrauma.Items.Components
}
}
[Editable(0.0f, 1.0f, decimals: 3),
[Editable(0.0f, 1.0f, decimals: 4),
Serialize(0.5f, true, description: "How full the ballast tanks should be when the submarine is not being steered upwards/downwards."
+ " Can be used to compensate if the ballast tanks are too large/small relative to the size of the submarine.")]
public float NeutralBallastLevel
@@ -417,6 +420,7 @@ namespace Barotrauma.Items.Components
Math.Max(1000.0f * Math.Abs(controlledSub.Velocity.Y), controlledSub.Borders.Height * 0.75f));
float avoidRadius = avoidDist.Length();
float damagingWallAvoidRadius = avoidRadius * 1.5f;
Vector2 newAvoidStrength = Vector2.Zero;
@@ -426,12 +430,26 @@ namespace Barotrauma.Items.Components
var closeCells = Level.Loaded.GetCells(controlledSub.WorldPosition, 4);
foreach (VoronoiCell cell in closeCells)
{
if (cell.DoesDamage)
{
foreach (GraphEdge edge in cell.Edges)
{
Vector2 closestPoint = MathUtils.GetClosestPointOnLineSegment(edge.Point1 + cell.Translation, edge.Point2 + cell.Translation, controlledSub.WorldPosition);
float dist = Vector2.Distance(closestPoint, controlledSub.WorldPosition);
if (dist > damagingWallAvoidRadius) { continue; }
Vector2 diff = controlledSub.WorldPosition - cell.Center;
Vector2 avoid = Vector2.Normalize(diff) * (damagingWallAvoidRadius - dist) / damagingWallAvoidRadius;
newAvoidStrength += avoid;
debugDrawObstacles.Add(new ObstacleDebugInfo(edge, edge.Center, 1.0f, avoid, cell.Translation));
}
continue;
}
foreach (GraphEdge edge in cell.Edges)
{
if (MathUtils.GetLineIntersection(edge.Point1 + cell.Translation, edge.Point2 + cell.Translation, controlledSub.WorldPosition, cell.Center, out Vector2 intersection))
{
Vector2 diff = controlledSub.WorldPosition - intersection;
//far enough -> ignore
if (Math.Abs(diff.X) > avoidDist.X && Math.Abs(diff.Y) > avoidDist.Y)
{
@@ -497,6 +515,15 @@ namespace Barotrauma.Items.Components
}
}
private float? GetNodePenalty(PathNode node, PathNode nextNode)
{
if (node.Waypoint?.Tunnel == null || controlledSub == null || node.Waypoint.Tunnel.Type == Level.TunnelType.MainPath) { return 0.0f; }
//never navigate from the main path to another type of path
if (node.Waypoint.Tunnel.Type == Level.TunnelType.MainPath && nextNode.Waypoint?.Tunnel?.Type != Level.TunnelType.MainPath) { return null; }
//higher cost for side paths (= autopilot prefers the main path, but can still navigate side paths if it ends up on one)
return 1000.0f;
}
private void UpdatePath()
{
if (Level.Loaded == null) { return; }
@@ -13,11 +13,7 @@ namespace Barotrauma.Items.Components
set { oxygenFlow = Math.Max(value, 0.0f); }
}
public Vent (Item item, XElement element)
: base(item, element)
{
}
public Vent (Item item, XElement element) : base(item, element) { }
public override void Update(float deltaTime, Camera cam)
{