Merge pull request #9 from Regalis11/master

0.14.9.0
This commit is contained in:
Evil Factory
2021-08-25 13:18:02 -03:00
committed by GitHub
140 changed files with 1448 additions and 621 deletions
@@ -167,10 +167,9 @@ namespace Barotrauma.Items.Components
{
foreach (DockingPort port in list)
{
if (port == this || port.item.Submarine == item.Submarine) continue;
if (Math.Abs(port.item.WorldPosition.X - item.WorldPosition.X) > DistanceTolerance.X) continue;
if (Math.Abs(port.item.WorldPosition.Y - item.WorldPosition.Y) > DistanceTolerance.Y) continue;
if (port == this || port.item.Submarine == item.Submarine || port.IsHorizontal != IsHorizontal) { continue; }
if (Math.Abs(port.item.WorldPosition.X - item.WorldPosition.X) > DistanceTolerance.X) { continue; }
if (Math.Abs(port.item.WorldPosition.Y - item.WorldPosition.Y) > DistanceTolerance.Y) { continue; }
return port;
}
@@ -82,13 +82,13 @@ namespace Barotrauma.Items.Components
get { return nodes; }
}
private readonly List<Pair<Character,Node>> charactersInRange = new List<Pair<Character, Node>>();
private readonly List<(Character character, Node node)> charactersInRange = new List<(Character character, Node node)>();
private bool charging;
private float timer;
private Attack attack;
private readonly Attack attack;
public ElectricalDischarger(Item item, XElement element) :
base(item, element)
@@ -114,8 +114,8 @@ namespace Barotrauma.Items.Components
{
//already active, do nothing
if (IsActive) { return false; }
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) { return false; }
if (character != null && !CharacterUsable) { return false; }
CurrPowerConsumption = powerConsumption;
charging = true;
@@ -182,9 +182,9 @@ namespace Barotrauma.Items.Components
FindNodes(item.WorldPosition, Range);
if (attack != null)
{
foreach (Pair<Character, Node> characterInRange in charactersInRange)
foreach ((Character character, Node node) in charactersInRange)
{
characterInRange.First.ApplyAttack(null, characterInRange.Second.WorldPosition, attack, 1.0f);
character.ApplyAttack(null, node.WorldPosition, attack, 1.0f);
}
}
DischargeProjSpecific();
@@ -315,7 +315,6 @@ namespace Barotrauma.Items.Components
if (closestIndex == -1 || closestDist > currentRange)
{
int originalParentNodeIndex = parentNodeIndex;
//nothing in range, create some arcs to random directions
for (int i = 0; i < Rand.Int(4); i++)
{
@@ -455,7 +454,7 @@ namespace Barotrauma.Items.Components
AddNodesBetweenPoints(currPos, targetPos, 0.25f, ref parentNodeIndex);
nodes.Add(new Node(targetPos, parentNodeIndex));
entitiesInRange.RemoveAt(closestIndex);
charactersInRange.Add(new Pair<Character, Node>(character, nodes[parentNodeIndex]));
charactersInRange.Add((character, nodes[parentNodeIndex]));
FindNodes(entitiesInRange, targetPos, nodes.Count - 1, currentRange);
}
}
@@ -342,7 +342,7 @@ namespace Barotrauma.Items.Components
allowInsideFixture: true);
hitBodies.Clear();
hitBodies.AddRange(bodies);
hitBodies.AddRange(bodies.Distinct());
lastPickedFraction = Submarine.LastPickedFraction;
Type lastHitType = null;
@@ -678,7 +678,7 @@ namespace Barotrauma.Items.Components
Reset();
previousGap = leak;
}
Vector2 fromCharacterToLeak = leak.WorldPosition - character.WorldPosition;
Vector2 fromCharacterToLeak = leak.WorldPosition - character.AnimController.AimSourceWorldPos;
float dist = fromCharacterToLeak.Length();
float reach = AIObjectiveFixLeak.CalculateReach(this, character);
@@ -692,10 +692,10 @@ namespace Barotrauma.Items.Components
if (!character.AnimController.InWater)
{
// TODO: use the collider size?
if (!character.AnimController.InWater && character.AnimController is HumanoidAnimController &&
if (!character.AnimController.InWater && character.AnimController is HumanoidAnimController humanAnim &&
Math.Abs(fromCharacterToLeak.X) < 100.0f && fromCharacterToLeak.Y < 0.0f && fromCharacterToLeak.Y > -150.0f)
{
((HumanoidAnimController)character.AnimController).Crouching = true;
humanAnim.Crouching = true;
}
}
if (dist > reach * 0.8f || dist > reach * 0.5f && character.AnimController.Limbs.Any(l => l.inWater))
@@ -12,6 +12,9 @@ namespace Barotrauma.Items.Components
private bool midAir;
//continuous collision detection is used while the item is moving faster than this
const float ContinuousCollisionThreshold = 5.0f;
public Character CurrentThrower
{
get;
@@ -61,6 +64,13 @@ namespace Barotrauma.Items.Components
if (!item.body.Enabled) { return; }
if (midAir)
{
if (item.body.FarseerBody.IsBullet)
{
if (item.body.LinearVelocity.LengthSquared() < ContinuousCollisionThreshold * ContinuousCollisionThreshold)
{
item.body.FarseerBody.IsBullet = false;
}
}
if (item.body.LinearVelocity.LengthSquared() < 0.01f)
{
CurrentThrower = null;
@@ -156,6 +166,7 @@ namespace Barotrauma.Items.Components
//disable platform collisions until the item comes back to rest again
item.body.CollidesWith = Physics.CollisionWall | Physics.CollisionLevel;
item.body.FarseerBody.IsBullet = true;
midAir = true;
ac.GetLimb(LimbType.Head).body.ApplyLinearImpulse(throwVector * 10.0f, maxVelocity: NetConfig.MaxPhysicsBodyVelocity);
@@ -165,6 +176,7 @@ namespace Barotrauma.Items.Components
item.body.AngularVelocity = rightHand.body.AngularVelocity;
throwPos = 0;
throwDone = true;
IsActive = true;
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsServer)
{
@@ -44,7 +44,7 @@ namespace Barotrauma.Items.Components
protected bool canBeCombined;
protected bool removeOnCombined;
public bool WasUsed;
public bool WasUsed, WasSecondaryUsed;
public readonly Dictionary<ActionType, List<StatusEffect>> statusEffectLists;
@@ -4,6 +4,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using Barotrauma.Extensions;
using FarseerPhysics;
namespace Barotrauma.Items.Components
{
@@ -60,7 +61,21 @@ namespace Barotrauma.Items.Components
Drawable = !hideItems;
}
}
#if DEBUG
[Editable]
#endif
[Serialize("0.0,0.0", false, description: "The position where the contained items get drawn at (offset from the upper left corner of the sprite in pixels).")]
public Vector2 ItemPos { get; set; }
#if DEBUG
[Editable]
#endif
[Serialize("0.0,0.0", false, description: "The interval at which the contained items are spaced apart from each other (in pixels).")]
public Vector2 ItemInterval { get; set; }
[Serialize(100, false, description: "How many items are placed in a row before starting a new row.")]
public int ItemsPerRow { get; set; }
[Serialize(true, false, description: "Should the inventory of this item be visible when the item is selected.")]
public bool DrawInventory
{
@@ -118,6 +133,13 @@ namespace Barotrauma.Items.Components
set;
}
[Serialize(false, false, description: "Should the items configured using SpawnWithId spawn if this item is broken.")]
public bool SpawnWithIdWhenBroken
{
get;
set;
}
[Serialize(false, false)]
public bool RemoveContainedItemsOnDeconstruct { get; set; }
@@ -335,20 +357,66 @@ namespace Barotrauma.Items.Components
public void SetContainedItemPositions()
{
Vector2 simPos = item.SimPosition;
Vector2 displayPos = item.Position;
Vector2 transformedItemPos = ItemPos * item.Scale;
Vector2 transformedItemInterval = ItemInterval * item.Scale;
Vector2 transformedItemIntervalHorizontal = new Vector2(transformedItemInterval.X, 0.0f);
Vector2 transformedItemIntervalVertical = new Vector2(0.0f, transformedItemInterval.Y);
if (item.body == null)
{
if (item.FlippedX)
{
transformedItemPos.X = -transformedItemPos.X;
transformedItemPos.X += item.Rect.Width;
transformedItemInterval.X = -transformedItemInterval.X;
transformedItemIntervalHorizontal.X = -transformedItemIntervalHorizontal.X;
}
if (item.FlippedY)
{
transformedItemPos.Y = -transformedItemPos.Y;
transformedItemPos.Y -= item.Rect.Height;
transformedItemInterval.Y = -transformedItemInterval.Y;
transformedItemIntervalVertical.Y = -transformedItemIntervalVertical.Y;
}
transformedItemPos += new Vector2(item.Rect.X, item.Rect.Y);
if (Math.Abs(item.Rotation) > 0.01f)
{
Matrix transform = Matrix.CreateRotationZ(MathHelper.ToRadians(-item.Rotation));
transformedItemPos = Vector2.Transform(transformedItemPos, transform);
transformedItemInterval = Vector2.Transform(transformedItemInterval, transform);
transformedItemIntervalHorizontal = Vector2.Transform(transformedItemIntervalHorizontal, transform);
transformedItemIntervalVertical = Vector2.Transform(transformedItemIntervalVertical, transform);
}
}
else
{
Matrix transform = Matrix.CreateRotationZ(item.body.Rotation);
if (item.body.Dir == -1.0f)
{
transformedItemPos.X = -transformedItemPos.X;
transformedItemInterval.X = -transformedItemInterval.X;
transformedItemIntervalHorizontal.X = -transformedItemIntervalHorizontal.X;
}
transformedItemPos = Vector2.Transform(transformedItemPos, transform);
transformedItemInterval = Vector2.Transform(transformedItemInterval, transform);
transformedItemIntervalHorizontal = Vector2.Transform(transformedItemIntervalHorizontal, transform);
transformedItemPos += item.Position;
}
float currentRotation = itemRotation;
if (item.body != null)
{
currentRotation += item.body.Rotation;
}
int i = 0;
Vector2 currentItemPos = transformedItemPos;
foreach (Item contained in Inventory.AllItems)
{
if (contained.body != null)
{
try
{
Vector2 simPos = ConvertUnits.ToSimUnits(currentItemPos);
contained.body.FarseerBody.SetTransformIgnoreContacts(ref simPos, currentRotation);
contained.body.SetPrevTransform(contained.body.SimPosition, contained.body.Rotation);
contained.body.UpdateDrawPosition();
@@ -365,14 +433,29 @@ namespace Barotrauma.Items.Components
contained.Rect =
new Rectangle(
(int)(displayPos.X - contained.Rect.Width / 2.0f),
(int)(displayPos.Y + contained.Rect.Height / 2.0f),
(int)(currentItemPos.X - contained.Rect.Width / 2.0f),
(int)(currentItemPos.Y + contained.Rect.Height / 2.0f),
contained.Rect.Width, contained.Rect.Height);
contained.Submarine = item.Submarine;
contained.CurrentHull = item.CurrentHull;
contained.SetContainedItemPositions();
i++;
if (Math.Abs(ItemInterval.X) > 0.001f && Math.Abs(ItemInterval.Y) > 0.001f)
{
//interval set on both axes -> use a grid layout
currentItemPos += transformedItemIntervalHorizontal;
if (i % ItemsPerRow == 0)
{
currentItemPos = transformedItemPos;
currentItemPos += transformedItemIntervalVertical * (i / ItemsPerRow);
}
}
else
{
currentItemPos += transformedItemInterval;
}
}
}
@@ -400,7 +483,7 @@ namespace Barotrauma.Items.Components
foreach (ushort id in itemIds[i])
{
if (!(Entity.FindEntityByID(id) is Item item)) { continue; }
Inventory.TryPutItem(item, i, false, false, null, false);
Inventory.TryPutItem(item, i, false, false, null, createNetworkEvent: false, ignoreCondition: true);
}
}
itemIds = null;
@@ -410,7 +493,7 @@ namespace Barotrauma.Items.Components
private void SpawnAlwaysContainedItems()
{
if (SpawnWithId.Length > 0)
if (SpawnWithId.Length > 0 && (item.Condition > 0.0f || SpawnWithIdWhenBroken))
{
string[] splitIds = SpawnWithId.Split(',');
foreach (string id in splitIds)
@@ -102,6 +102,12 @@ namespace Barotrauma.Items.Components
get { return limbPositions.Count > 0; }
}
public bool UserInCorrectPosition
{
get;
private set;
}
public bool AllowAiming
{
get;
@@ -149,6 +155,7 @@ namespace Barotrauma.Items.Components
public override void Update(float deltaTime, Camera cam)
{
this.cam = cam;
UserInCorrectPosition = false;
if (IsToggle)
{
@@ -189,6 +196,7 @@ namespace Barotrauma.Items.Components
else
{
user.AnimController.TargetMovement = Vector2.Zero;
UserInCorrectPosition = true;
}
}
else
@@ -197,7 +205,7 @@ namespace Barotrauma.Items.Components
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient && user != Character.Controlled)
{
if (Math.Abs(diff.X) > 20.0f)
{
{
//wait for the character to walk to the correct position
return;
}
@@ -218,7 +226,8 @@ namespace Barotrauma.Items.Components
return;
}
}
user.AnimController.TargetMovement = Vector2.Zero;
user.AnimController.TargetMovement = Vector2.Zero;
UserInCorrectPosition = true;
}
}
@@ -365,7 +374,7 @@ namespace Barotrauma.Items.Components
for (int i = item.LastSentSignalRecipients.Count - 1; i >= 0; i--)
{
if (item.LastSentSignalRecipients[i].Item.Condition <= 0.0f) { continue; }
if (item.LastSentSignalRecipients[i].Item.Condition <= 0.0f || item.LastSentSignalRecipients[i].IsPower) { continue; }
if (item.LastSentSignalRecipients[i].Item.Prefab.FocusOnSelected)
{
return item.LastSentSignalRecipients[i].Item;
@@ -211,7 +211,7 @@ namespace Barotrauma.Items.Components
{
for (int i = inputContainer.Inventory.Capacity - 2; i >= 0; i--)
{
while (inputContainer.Inventory.GetItemAt(i) is Item item1 && inputContainer.Inventory.CanBePut(item1, i + 1))
while (inputContainer.Inventory.GetItemAt(i) is Item item1 && inputContainer.Inventory.CanBePutInSlot(item1, i + 1))
{
if (!inputContainer.Inventory.TryPutItem(item1, i + 1, allowSwapping: false, allowCombine: false, user: null, createNetworkEvent: true))
{
@@ -170,7 +170,7 @@ namespace Barotrauma.Items.Components
private void StartFabricating(FabricationRecipe selectedItem, Character user, bool addToServerLog = true)
{
if (selectedItem == null) { return; }
if (!outputContainer.Inventory.CanBePut(selectedItem.TargetItem)) { return; }
if (!outputContainer.Inventory.CanBePut(selectedItem.TargetItem, selectedItem.OutCondition * selectedItem.TargetItem.Health)) { return; }
#if CLIENT
itemList.Enabled = false;
@@ -308,7 +308,7 @@ namespace Barotrauma.Items.Components
}
Character tempUser = user;
int amountFittingContainer = outputContainer.Inventory.HowManyCanBePut(fabricatedItem.TargetItem);
int amountFittingContainer = outputContainer.Inventory.HowManyCanBePut(fabricatedItem.TargetItem, fabricatedItem.OutCondition * fabricatedItem.TargetItem.Health);
for (int i = 0; i < fabricatedItem.Amount; i++)
{
if (i < amountFittingContainer)
@@ -334,7 +334,7 @@ namespace Barotrauma.Items.Components
}
}
if (user != null && !user.Removed)
if (user?.Info != null && !user.Removed)
{
foreach (Skill skill in fabricatedItem.RequiredSkills)
{
@@ -50,7 +50,7 @@ namespace Barotrauma.Items.Components
set { maxFlow = value; }
}
[Editable, Serialize(true, false, alwaysUseInstanceValues: true)]
[Editable, Serialize(true, true, alwaysUseInstanceValues: true)]
public bool IsOn
{
get { return IsActive; }
@@ -234,7 +234,10 @@ namespace Barotrauma.Items.Components
//use a smoothed "correct output" instead of the actual correct output based on the load
//so the player doesn't have to keep adjusting the rate impossibly fast when the load fluctuates heavily
correctTurbineOutput += MathHelper.Clamp((load / MaxPowerOutput * 100.0f) - correctTurbineOutput, -10.0f, 10.0f) * deltaTime;
if (!MathUtils.NearlyEqual(MaxPowerOutput, 0.0f))
{
correctTurbineOutput += MathHelper.Clamp((load / MaxPowerOutput * 100.0f) - correctTurbineOutput, -10.0f, 10.0f) * deltaTime;
}
//calculate tolerances of the meters based on the skills of the user
//more skilled characters have larger "sweet spots", making it easier to keep the power output at a suitable level
@@ -320,7 +323,7 @@ namespace Barotrauma.Items.Components
//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;
correctTurbineOutput = MathUtils.NearlyEqual(MaxPowerOutput, 0.0f) ? 0.0f : 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);
@@ -795,6 +795,7 @@ namespace Barotrauma.Items.Components
steeringInput = XMLExtensions.ParseVector2(signal.value, errorMessages: false);
steeringInput.X = MathHelper.Clamp(steeringInput.X, -100.0f, 100.0f);
steeringInput.Y = MathHelper.Clamp(-steeringInput.Y, -100.0f, 100.0f);
TargetVelocity = steeringInput;
}
else
{
@@ -74,8 +74,6 @@ namespace Barotrauma.Items.Components
[Serialize(100f, true, "How much fertilizer can the planter hold.")]
public float FertilizerCapacity { get; set; }
public string LastAction { get; set; } = "";
public Growable?[] GrowableSeeds = new Growable?[0];
private readonly List<RelatedItem> SuitableFertilizer = new List<RelatedItem>();
@@ -119,7 +117,7 @@ namespace Barotrauma.Items.Components
GrowableSeeds = new Growable[container.Capacity];
}
public override bool HasRequiredItems(Character character, bool addMessage, string msg = null)
public override bool HasRequiredItems(Character character, bool addMessage, string? msg = null)
{
if (container?.Inventory == null) { return false; }
@@ -137,9 +135,16 @@ namespace Barotrauma.Items.Components
return true;
}
Msg = MsgHarvest;
if (GrowableSeeds.Any(s => s != null))
{
Msg = MsgHarvest;
ParseMsg();
return true;
}
Msg = string.Empty;
ParseMsg();
return true;
return false;
}
public override bool Pick(Character character)
@@ -163,9 +168,16 @@ namespace Barotrauma.Items.Components
switch (plantItem.Type)
{
case PlantItemType.Seed:
LastAction = "PlantSeed";
ApplyStatusEffects(ActionType.OnPicked, 1.0f, character);
return container.Inventory.TryPutItem(plantItem.Item, character, new List<InvSlotType> { InvSlotType.Any });
if (GameMain.NetworkMember == null || GameMain.NetworkMember.IsServer)
{
return container.Inventory.TryPutItem(plantItem.Item, character);
}
else
{
//let the server handle moving the item
return false;
}
case PlantItemType.Fertilizer when plantItem.Item != null:
float canAdd = FertilizerCapacity - Fertilizer;
float maxAvailable = plantItem.Item.Condition;
@@ -175,7 +187,6 @@ namespace Barotrauma.Items.Components
#if CLIENT
character.UpdateHUDProgressBar(this, Item.DrawPosition, Fertilizer / FertilizerCapacity, Color.SaddleBrown, Color.SaddleBrown, "entityname.fertilizer");
#endif
LastAction = "ApplyFertilizer";
ApplyStatusEffects(ActionType.OnPicked, 1.0f, character);
return false;
}
@@ -203,7 +214,6 @@ namespace Barotrauma.Items.Components
container?.Inventory.RemoveItem(seed.Item);
Entity.Spawner?.AddToRemoveQueue(seed.Item);
GrowableSeeds[i] = null;
LastAction = "Harvest";
ApplyStatusEffects(ActionType.OnPicked, 1.0f, character);
return true;
}
@@ -133,6 +133,12 @@ namespace Barotrauma.Items.Components
public override void Update(float deltaTime, Camera cam)
{
if (item.Connections == null)
{
IsActive = false;
return;
}
isRunning = true;
float chargeRatio = charge / capacity;
float gridPower = 0.0f;
@@ -173,7 +179,13 @@ namespace Barotrauma.Items.Components
}
else
{
currPowerConsumption = MathHelper.Lerp(currPowerConsumption, rechargeSpeed, 0.05f);
float missingCharge = capacity - charge;
float targetRechargeSpeed = rechargeSpeed;
if (missingCharge < 1.0f)
{
targetRechargeSpeed *= missingCharge;
}
currPowerConsumption = MathHelper.Lerp(currPowerConsumption, targetRechargeSpeed, 0.05f);
Charge += currPowerConsumption * Math.Min(Voltage, 1.0f) / 3600.0f;
}
@@ -408,21 +408,25 @@ namespace Barotrauma.Items.Components
}
}
bool hitSomething = false;
int hitCount = 0;
Vector2 lastHitPos = item.WorldPosition;
hits = hits.OrderBy(h => h.Fraction).ToList();
foreach (HitscanResult h in hits)
for (int i = 0; i < hits.Count; i++)
{
var h = hits[i];
item.SetTransform(h.Point, rotation);
if (HandleProjectileCollision(h.Fixture, h.Normal, Vector2.Zero))
{
LaunchProjSpecific(rayStartWorld, item.WorldPosition);
hitSomething = true;
break;
hitCount++;
if (hitCount >= MaxTargetsToHit || i == hits.Count - 1)
{
LaunchProjSpecific(rayStartWorld, item.WorldPosition);
break;
}
}
}
//the raycast didn't hit anything -> the projectile flew somewhere outside the level and is permanently lost
if (!hitSomething)
//the raycast didn't hit anything (or didn't hit enough targets to stop the projectile) -> the projectile flew somewhere outside the level and is permanently lost
if (hitCount < MaxTargetsToHit)
{
item.body.SetTransformIgnoreContacts(item.body.SimPosition, rotation);
LaunchProjSpecific(rayStartWorld, rayEndWorld);
@@ -467,7 +471,7 @@ namespace Barotrauma.Items.Components
}
if (fixture.Body.UserData is VineTile) { return true; }
if (fixture.Body.UserData is Item item && (item.GetComponent<Door>() == null && !item.Prefab.DamagedByProjectiles || item.Condition <= 0)) { return true; }
if (fixture.Body.UserData as string == "ruinroom") { return true; }
if (fixture.Body.UserData as string == "ruinroom" || fixture.Body.UserData is Hull || fixture.UserData is Hull) { return true; }
//if doing the raycast in a submarine's coordinate space, ignore anything that's not in that sub
if (submarine != null)
@@ -505,7 +509,7 @@ namespace Barotrauma.Items.Components
if (fixture.Body.UserData is VineTile) { return -1; }
if (fixture.Body.UserData is Item item && (item.GetComponent<Door>() == null && !item.Prefab.DamagedByProjectiles || item.Condition <= 0)) { return -1; }
if (fixture.Body?.UserData as string == "ruinroom") { return -1; }
if (fixture.Body.UserData as string == "ruinroom" || fixture.Body?.UserData is Hull || fixture.UserData is Hull) { return -1; }
//ignore everything else than characters, sub walls and level walls
if (!fixture.CollisionCategories.HasFlag(Physics.CollisionCharacter) &&
@@ -640,7 +644,7 @@ namespace Barotrauma.Items.Components
item.body.SimPosition - ConvertUnits.ToSimUnits(sub.Position) - dir,
item.body.SimPosition - ConvertUnits.ToSimUnits(sub.Position) + dir,
collisionCategory: Physics.CollisionWall);
if (wallBody?.FixtureList?.First() != null && wallBody.UserData is Structure &&
if (wallBody?.FixtureList?.First() != null && (wallBody.UserData is Structure || wallBody.UserData is Item) &&
//ignore the hit if it's behind the position the item was launched from, and the projectile is travelling in the opposite direction
Vector2.Dot(item.body.SimPosition - launchPos, dir) > 0)
{
@@ -738,7 +742,15 @@ namespace Barotrauma.Items.Components
}
else if (target.Body.UserData is IDamageable damageable)
{
if (Attack != null) { attackResult = Attack.DoDamage(User ?? Attacker, damageable, item.WorldPosition, 1.0f); }
if (Attack != null)
{
Vector2 pos = item.WorldPosition;
if (item.Submarine == null && damageable is Structure structure && structure.Submarine != null && Vector2.DistanceSquared(item.WorldPosition, structure.WorldPosition) > 10000.0f * 10000.0f)
{
item.Submarine = structure.Submarine;
}
attackResult = Attack.DoDamage(User ?? Attacker, damageable, pos, 1.0f);
}
}
else if (target.Body.UserData is VoronoiCell voronoiCell && voronoiCell.IsDestructible && Attack != null && Math.Abs(Attack.LevelWallDamage) > 0.0f)
{
@@ -139,7 +139,7 @@ namespace Barotrauma.Items.Components
//backwards compatibility
var repairThresholdAttribute =
element.Attributes().FirstOrDefault(a => a.Name.ToString().Equals("showrepairuithreshold", StringComparison.OrdinalIgnoreCase)) ??
element.Attributes().FirstOrDefault(a => a.Name.ToString().Equals("airepairth44reshold", StringComparison.OrdinalIgnoreCase));
element.Attributes().FirstOrDefault(a => a.Name.ToString().Equals("airepairthreshold", StringComparison.OrdinalIgnoreCase));
if (repairThresholdAttribute != null)
{
if (float.TryParse(repairThresholdAttribute.Value, NumberStyles.Float, CultureInfo.InvariantCulture, out float repairThreshold))
@@ -349,7 +349,7 @@ namespace Barotrauma.Items.Components
foreach (Skill skill in requiredSkills)
{
float characterSkillLevel = CurrentFixer.GetSkillLevel(skill.Identifier);
CurrentFixer.Info.IncreaseSkillLevel(skill.Identifier,
CurrentFixer.Info?.IncreaseSkillLevel(skill.Identifier,
SkillSettings.Current.SkillIncreasePerRepair / Math.Max(characterSkillLevel, 1.0f),
CurrentFixer.Position + Vector2.UnitY * 100.0f);
}
@@ -379,7 +379,7 @@ namespace Barotrauma.Items.Components
foreach (Skill skill in requiredSkills)
{
float characterSkillLevel = CurrentFixer.GetSkillLevel(skill.Identifier);
CurrentFixer.Info.IncreaseSkillLevel(skill.Identifier,
CurrentFixer.Info?.IncreaseSkillLevel(skill.Identifier,
SkillSettings.Current.SkillIncreasePerSabotage / Math.Max(characterSkillLevel, 1.0f),
CurrentFixer.Position + Vector2.UnitY * 100.0f);
}
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Xml.Linq;
namespace Barotrauma.Items.Components
@@ -23,7 +24,7 @@ namespace Barotrauma.Items.Components
private int signalQueueSize;
private int delayTicks;
private Queue<DelayedSignal> signalQueue;
private readonly Queue<DelayedSignal> signalQueue;
private DelayedSignal prevQueuedSignal;
@@ -37,7 +38,7 @@ namespace Barotrauma.Items.Components
if (value == delay) { return; }
delay = value;
delayTicks = (int)(delay / Timing.Step);
signalQueueSize = delayTicks * 2;
signalQueueSize = Math.Max(delayTicks, 1) * 2;
}
}
@@ -74,7 +75,14 @@ namespace Barotrauma.Items.Components
var signalOut = signalQueue.Peek();
signalOut.SendDuration -= 1;
item.SendSignal(new Signal(signalOut.Signal.value, strength: signalOut.Signal.strength), "signal_out");
if (signalOut.SendDuration <= 0) { signalQueue.Dequeue(); } else { break; }
if (signalOut.SendDuration <= 0)
{
signalQueue.Dequeue();
}
else
{
break;
}
}
}
@@ -27,7 +27,7 @@ namespace Barotrauma.Items.Components
return retVal;
}
public static bool operator==(Signal a, Signal b) =>
public static bool operator ==(Signal a, Signal b) =>
a.value == b.value &&
a.stepsTaken == b.stepsTaken &&
a.sender == b.sender &&
@@ -35,6 +35,6 @@ namespace Barotrauma.Items.Components
MathUtils.NearlyEqual(a.power, b.power) &&
MathUtils.NearlyEqual(a.strength, b.strength);
public static bool operator!=(Signal a, Signal b) => !(a == b);
public static bool operator !=(Signal a, Signal b) => !(a == b);
}
}
@@ -77,11 +77,10 @@ namespace Barotrauma.Items.Components
//item in water -> we definitely want to send the True output
isInWater = true;
}
else if (item.CurrentHull != null)
else if (item.CurrentHull != null && item.CurrentHull.WaterPercentage > 0.0f)
{
//item in not water -> check if there's water anywhere within the rect of the item
if (item.CurrentHull.Surface > item.CurrentHull.Rect.Y - item.CurrentHull.Rect.Height + 1 &&
item.CurrentHull.Surface > item.Rect.Y - item.Rect.Height)
//(center of the) item in not water -> check if the water surface is below the bottom of the item's rect
if (item.CurrentHull.Surface > item.Rect.Y - item.Rect.Height)
{
isInWater = true;
}
@@ -844,10 +844,11 @@ namespace Barotrauma.Items.Components
ClearConnections();
base.RemoveComponentSpecific();
#if CLIENT
if (DraggingWire == this) { draggingWire = null; }
overrideSprite?.Remove();
overrideSprite = null;
wireSprite = null;
#endif
}
}
}
}
@@ -562,6 +562,7 @@ namespace Barotrauma.Items.Components
//use linked projectile containers in case they have to react to the turret being launched somehow
//(play a sound, spawn more projectiles)
if (!(e is Item linkedItem)) { continue; }
if (!item.prefab.IsLinkAllowed(e.prefab)) { continue; }
if (linkedItem.Condition <= 0.0f)
{
loaderBroken = true;
@@ -971,6 +972,7 @@ namespace Barotrauma.Items.Components
foreach (MapEntity e in item.linkedTo)
{
if (!item.IsInteractable(character)) { continue; }
if (!item.prefab.IsLinkAllowed(e.prefab)) { continue; }
if (e is Item projectileContainer)
{
var container = projectileContainer.GetComponent<ItemContainer>();
@@ -1323,6 +1325,7 @@ namespace Barotrauma.Items.Components
CheckProjectileContainer(item, projectiles, out bool _);
foreach (MapEntity e in item.linkedTo)
{
if (!item.prefab.IsLinkAllowed(e.prefab)) { continue; }
if (e is Item projectileContainer)
{
CheckProjectileContainer(projectileContainer, projectiles, out bool stopSearching);