Build 0.18.0.0
This commit is contained in:
@@ -99,8 +99,8 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
if (!docked && value)
|
||||
{
|
||||
if (DockingTarget == null) AttemptDock();
|
||||
if (DockingTarget == null) return;
|
||||
if (DockingTarget == null) { AttemptDock(); }
|
||||
if (DockingTarget == null) { return; }
|
||||
|
||||
docked = true;
|
||||
}
|
||||
@@ -126,6 +126,14 @@ namespace Barotrauma.Items.Components
|
||||
/// </summary>
|
||||
public event Action OnUnDocked;
|
||||
|
||||
private bool outpostAutoDockingPromptShown;
|
||||
|
||||
enum AllowOutpostAutoDocking
|
||||
{
|
||||
Ask, Yes, No
|
||||
}
|
||||
private AllowOutpostAutoDocking allowOutpostAutoDocking = AllowOutpostAutoDocking.Ask;
|
||||
|
||||
public DockingPort(Item item, ContentXElement element)
|
||||
: base(item, element)
|
||||
{
|
||||
@@ -622,7 +630,8 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
bodies[i + j * 2] = GameMain.World.CreateEdge(
|
||||
ConvertUnits.ToSimUnits(new Vector2(hullRects[i].X, hullRects[i].Y - hullRects[i].Height * j)),
|
||||
ConvertUnits.ToSimUnits(new Vector2(hullRects[i].Right, hullRects[i].Y - hullRects[i].Height * j)));
|
||||
ConvertUnits.ToSimUnits(new Vector2(hullRects[i].Right, hullRects[i].Y - hullRects[i].Height * j)),
|
||||
BodyType.Static);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -632,7 +641,9 @@ namespace Barotrauma.Items.Components
|
||||
ConvertUnits.ToSimUnits(hullRects[0].Width + hullRects[1].Width),
|
||||
ConvertUnits.ToSimUnits(hullRects[0].Height),
|
||||
density: 0.0f,
|
||||
offset: ConvertUnits.ToSimUnits(new Vector2(hullRects[0].Right, hullRects[0].Y - hullRects[0].Height / 2) - hulls[0].Submarine.HiddenSubPosition));
|
||||
offset: ConvertUnits.ToSimUnits(new Vector2(hullRects[0].Right, hullRects[0].Y - hullRects[0].Height / 2) - hulls[0].Submarine.HiddenSubPosition),
|
||||
Physics.CollisionWall,
|
||||
Physics.CollisionCharacter | Physics.CollisionItem | Physics.CollisionCharacter | Physics.CollisionItemBlocking | Physics.CollisionProjectile);
|
||||
outsideBlocker.UserData = this;
|
||||
}
|
||||
|
||||
@@ -742,7 +753,8 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
bodies[i + j * 2] = GameMain.World.CreateEdge(
|
||||
ConvertUnits.ToSimUnits(new Vector2(hullRects[i].X + hullRects[i].Width * j, hullRects[i].Y)),
|
||||
ConvertUnits.ToSimUnits(new Vector2(hullRects[i].X + hullRects[i].Width * j, hullRects[i].Y - hullRects[i].Height)));
|
||||
ConvertUnits.ToSimUnits(new Vector2(hullRects[i].X + hullRects[i].Width * j, hullRects[i].Y - hullRects[i].Height)),
|
||||
BodyType.Static);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -752,7 +764,9 @@ namespace Barotrauma.Items.Components
|
||||
ConvertUnits.ToSimUnits(hullRects[0].Width),
|
||||
ConvertUnits.ToSimUnits(hullRects[0].Height + hullRects[1].Height),
|
||||
density: 0.0f,
|
||||
offset: ConvertUnits.ToSimUnits(new Vector2(hullRects[0].Center.X, hullRects[0].Y) - hulls[0].Submarine.HiddenSubPosition));
|
||||
offset: ConvertUnits.ToSimUnits(new Vector2(hullRects[0].Center.X, hullRects[0].Y) - hulls[0].Submarine.HiddenSubPosition),
|
||||
Physics.CollisionWall,
|
||||
Physics.CollisionCharacter | Physics.CollisionItem | Physics.CollisionCharacter | Physics.CollisionItemBlocking | Physics.CollisionProjectile);
|
||||
outsideBlocker.UserData = this;
|
||||
}
|
||||
|
||||
@@ -778,8 +792,6 @@ namespace Barotrauma.Items.Components
|
||||
if (body == null) { continue; }
|
||||
body.BodyType = BodyType.Static;
|
||||
body.Friction = 0.5f;
|
||||
|
||||
body.CollisionCategories = Physics.CollisionWall;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -947,7 +959,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
foreach (Body body in bodies)
|
||||
{
|
||||
if (body == null) continue;
|
||||
if (body == null) { continue; }
|
||||
GameMain.World.Remove(body);
|
||||
}
|
||||
bodies = null;
|
||||
@@ -961,6 +973,9 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
item.CreateServerEvent(this);
|
||||
}
|
||||
#elif CLIENT
|
||||
autodockingVerification?.Close();
|
||||
autodockingVerification = null;
|
||||
#endif
|
||||
OnUnDocked?.Invoke();
|
||||
OnUnDocked = null;
|
||||
@@ -1140,27 +1155,86 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public override void ReceiveSignal(Signal signal, Connection connection)
|
||||
{
|
||||
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) { return; }
|
||||
#if CLIENT
|
||||
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient &&
|
||||
!(GameMain.GameSession?.Campaign?.AllowedToManageCampaign(ClientPermissions.ManageMap) ?? false))
|
||||
{
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (dockingCooldown > 0.0f) { return; }
|
||||
|
||||
bool wasDocked = docked;
|
||||
DockingPort prevDockingTarget = DockingTarget;
|
||||
|
||||
bool newDockedState = wasDocked;
|
||||
switch (connection.Name)
|
||||
{
|
||||
case "toggle":
|
||||
if (signal.value != "0")
|
||||
{
|
||||
Docked = !docked;
|
||||
newDockedState = !docked;
|
||||
}
|
||||
break;
|
||||
case "set_active":
|
||||
case "set_state":
|
||||
Docked = signal.value != "0";
|
||||
newDockedState = signal.value != "0";
|
||||
break;
|
||||
}
|
||||
|
||||
if (newDockedState != wasDocked)
|
||||
{
|
||||
bool tryingToToggleOutpostDocking = docked ?
|
||||
DockingTarget?.Item?.Submarine?.Info?.IsOutpost ?? false :
|
||||
FindAdjacentPort()?.Item?.Submarine?.Info?.IsOutpost ?? false;
|
||||
//trying to dock/undock from an outpost and the signal was sent by some automated system instead of a character
|
||||
// -> ask if the player really wants to dock/undock to prevent a softlock if someone's wired the docking port
|
||||
// in a way that makes always makes it dock/undock immediately at the start of the roun
|
||||
if (tryingToToggleOutpostDocking && signal.sender == null)
|
||||
{
|
||||
if (allowOutpostAutoDocking == AllowOutpostAutoDocking.Ask)
|
||||
{
|
||||
#if CLIENT
|
||||
if (!outpostAutoDockingPromptShown)
|
||||
{
|
||||
autodockingVerification = new GUIMessageBox(string.Empty,
|
||||
TextManager.Get(newDockedState ? "autodockverification" : "autoundockverification"),
|
||||
new LocalizedString[] { TextManager.Get("Yes"), TextManager.Get("No") });
|
||||
autodockingVerification.Buttons[0].OnClicked += (btn, userdata) =>
|
||||
{
|
||||
autodockingVerification?.Close();
|
||||
autodockingVerification = null;
|
||||
if (item.Removed || GameMain.Client == null) { return false; }
|
||||
allowOutpostAutoDocking = AllowOutpostAutoDocking.Yes;
|
||||
item.CreateClientEvent(this);
|
||||
return true;
|
||||
};
|
||||
autodockingVerification.Buttons[1].OnClicked += (btn, userdata) =>
|
||||
{
|
||||
autodockingVerification?.Close();
|
||||
autodockingVerification = null;
|
||||
if (item.Removed || GameMain.Client == null) { return false; }
|
||||
allowOutpostAutoDocking = AllowOutpostAutoDocking.No;
|
||||
item.CreateClientEvent(this);
|
||||
return true;
|
||||
};
|
||||
}
|
||||
#endif
|
||||
outpostAutoDockingPromptShown = true;
|
||||
return;
|
||||
}
|
||||
else if (allowOutpostAutoDocking == AllowOutpostAutoDocking.No)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) { return; }
|
||||
|
||||
Docked = newDockedState;
|
||||
}
|
||||
|
||||
#if SERVER
|
||||
if (signal.sender != null && docked != wasDocked)
|
||||
{
|
||||
|
||||
@@ -241,12 +241,14 @@ namespace Barotrauma.Items.Components
|
||||
Body = new PhysicsBody(
|
||||
ConvertUnits.ToSimUnits(Math.Max(doorRect.Width, 1)),
|
||||
ConvertUnits.ToSimUnits(Math.Max(doorRect.Height, 1)),
|
||||
0.0f,
|
||||
1.5f)
|
||||
radius: 0.0f,
|
||||
density: 1.5f,
|
||||
BodyType.Static,
|
||||
Physics.CollisionWall,
|
||||
Physics.CollisionCharacter | Physics.CollisionItem | Physics.CollisionCharacter | Physics.CollisionItemBlocking | Physics.CollisionProjectile,
|
||||
findNewContacts: false)
|
||||
{
|
||||
UserData = item,
|
||||
CollisionCategories = Physics.CollisionWall,
|
||||
BodyType = BodyType.Static,
|
||||
Friction = 0.5f
|
||||
};
|
||||
Body.SetTransformIgnoreContacts(
|
||||
@@ -258,11 +260,16 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
public override void Move(Vector2 amount)
|
||||
public override void Move(Vector2 amount, bool ignoreContacts = false)
|
||||
{
|
||||
base.Move(amount);
|
||||
|
||||
Body?.SetTransform(Body.SimPosition + ConvertUnits.ToSimUnits(amount), 0.0f);
|
||||
if (ignoreContacts)
|
||||
{
|
||||
Body?.SetTransformIgnoreContacts(Body.SimPosition + ConvertUnits.ToSimUnits(amount), 0.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
Body?.SetTransform(Body.SimPosition + ConvertUnits.ToSimUnits(amount), 0.0f);
|
||||
}
|
||||
|
||||
#if CLIENT
|
||||
UpdateConvexHulls();
|
||||
|
||||
@@ -164,6 +164,8 @@ namespace Barotrauma.Items.Components
|
||||
public bool SwingWhenAiming { get; set; }
|
||||
[Editable, Serialize(false, IsPropertySaveable.No, description: "Should the item swing around when it's being used (for example, when firing a weapon or a welding tool).")]
|
||||
public bool SwingWhenUsing { get; set; }
|
||||
[Editable, Serialize(false, IsPropertySaveable.No)]
|
||||
public bool DisableHeadRotation { get; set; }
|
||||
|
||||
[ConditionallyEditable(ConditionallyEditable.ConditionType.Attachable, MinValueFloat = 0.0f, MaxValueFloat = 0.999f, DecimalCount = 3), Serialize(0.55f, IsPropertySaveable.No, description: "Sprite depth that's used when the item is NOT attached to a wall.")]
|
||||
public float SpriteDepthWhenDropped
|
||||
@@ -180,11 +182,12 @@ namespace Barotrauma.Items.Components
|
||||
Pusher = null;
|
||||
if (element.GetAttributeBool("blocksplayers", false))
|
||||
{
|
||||
Pusher = new PhysicsBody(item.body.width, item.body.height, item.body.radius, item.body.Density)
|
||||
Pusher = new PhysicsBody(item.body.width, item.body.height, item.body.radius,
|
||||
item.body.Density,
|
||||
BodyType.Dynamic,
|
||||
Physics.CollisionItemBlocking,
|
||||
Physics.CollisionCharacter | Physics.CollisionProjectile)
|
||||
{
|
||||
BodyType = BodyType.Dynamic,
|
||||
CollidesWith = Physics.CollisionCharacter | Physics.CollisionProjectile,
|
||||
CollisionCategories = Physics.CollisionItemBlocking,
|
||||
Enabled = false,
|
||||
UserData = this
|
||||
};
|
||||
|
||||
+16
-7
@@ -79,11 +79,18 @@ namespace Barotrauma.Items.Components
|
||||
IsActive = true;
|
||||
}
|
||||
|
||||
public override void Move(Vector2 amount)
|
||||
public override void Move(Vector2 amount, bool ignoreContacts = false)
|
||||
{
|
||||
if (trigger != null && amount.LengthSquared() > 0.00001f)
|
||||
{
|
||||
trigger.SetTransform(item.SimPosition, 0.0f);
|
||||
if (ignoreContacts)
|
||||
{
|
||||
trigger.SetTransformIgnoreContacts(item.SimPosition, 0.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
trigger.SetTransform(item.SimPosition, 0.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,17 +126,19 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
|
||||
var body = item.body ?? holdable.Body;
|
||||
|
||||
|
||||
if (body != null)
|
||||
{
|
||||
trigger = new PhysicsBody(body.width, body.height, body.radius, body.Density)
|
||||
trigger = new PhysicsBody(body.width, body.height, body.radius,
|
||||
body.Density,
|
||||
BodyType.Static,
|
||||
Physics.CollisionWall,
|
||||
Physics.CollisionNone,
|
||||
findNewContacts: false)
|
||||
{
|
||||
UserData = item
|
||||
};
|
||||
trigger.FarseerBody.SetIsSensor(true);
|
||||
trigger.FarseerBody.BodyType = BodyType.Static;
|
||||
trigger.FarseerBody.CollisionCategories = Physics.CollisionWall;
|
||||
trigger.FarseerBody.CollidesWith = Physics.CollisionNone;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -111,8 +111,9 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
ActivateNearbySleepingCharacters();
|
||||
reloadTimer = reload;
|
||||
reloadTimer /= (1f + character.GetStatValue(StatTypes.MeleeAttackSpeed));
|
||||
reloadTimer /= (1f + item.GetQualityModifier(Quality.StatType.StrikingSpeedMultiplier));
|
||||
reloadTimer /= 1f + character.GetStatValue(StatTypes.MeleeAttackSpeed);
|
||||
reloadTimer /= 1f + item.GetQualityModifier(Quality.StatType.StrikingSpeedMultiplier);
|
||||
character.AnimController.LockFlippingUntil = (float)Timing.TotalTime + reloadTimer;
|
||||
|
||||
item.body.FarseerBody.CollisionCategories = Physics.CollisionProjectile;
|
||||
item.body.FarseerBody.CollidesWith = Physics.CollisionCharacter | Physics.CollisionWall | Physics.CollisionItemBlocking;
|
||||
@@ -216,6 +217,10 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
hitPos = MathUtils.WrapAnglePi(Math.Min(hitPos + deltaTime * 3f, MathHelper.PiOver4));
|
||||
ac.HoldItem(deltaTime, item, handlePos, aimPos, Vector2.Zero, aim: false, hitPos, holdAngle + hitPos, aimMelee: true);
|
||||
if (ac.InWater)
|
||||
{
|
||||
ac.LockFlippingUntil = (float)Timing.TotalTime + Reload;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -71,6 +71,7 @@ namespace Barotrauma.Items.Components
|
||||
//return if someone is already trying to pick the item
|
||||
if (pickTimer > 0.0f) { return false; }
|
||||
if (picker == null || picker.Inventory == null) { return false; }
|
||||
if (!picker.Inventory.AccessibleWhenAlive && !picker.Inventory.AccessibleByOwner) { return false; }
|
||||
|
||||
if (PickingTime > 0.0f)
|
||||
{
|
||||
@@ -226,7 +227,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
foreach (Connection c in connectionPanel.Connections)
|
||||
{
|
||||
foreach (Wire w in c.Wires)
|
||||
foreach (Wire w in c.Wires.ToArray())
|
||||
{
|
||||
if (w == null) continue;
|
||||
w.Item.Drop(character);
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public override bool Use(float deltaTime, Character character = null)
|
||||
{
|
||||
if (character == null || character.Removed) return false;
|
||||
if (character == null || character.Removed) { return false; }
|
||||
if (!character.IsKeyDown(InputType.Aim) || character.Stun > 0.0f) { return false; }
|
||||
|
||||
IsActive = true;
|
||||
@@ -55,12 +55,11 @@ namespace Barotrauma.Items.Components
|
||||
if (UsableIn == UseEnvironment.Water) { return true; }
|
||||
}
|
||||
|
||||
Vector2 dir = Vector2.Normalize(character.CursorPosition - character.Position);
|
||||
//move upwards if the cursor is at the position of the character
|
||||
if (!MathUtils.IsValid(dir)) dir = Vector2.UnitY;
|
||||
|
||||
Vector2 dir = character.CursorPosition - character.Position;
|
||||
if (!MathUtils.IsValid(dir)) { return true; }
|
||||
float length = 200;
|
||||
dir = dir.ClampLength(length) / length;
|
||||
Vector2 propulsion = dir * Force * character.PropulsionSpeedMultiplier;
|
||||
|
||||
if (character.AnimController.InWater && Force > 0.0f) { character.AnimController.TargetMovement = dir; }
|
||||
|
||||
foreach (Limb limb in character.AnimController.Limbs)
|
||||
|
||||
@@ -416,7 +416,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void Move(Vector2 amount) { }
|
||||
public virtual void Move(Vector2 amount, bool ignoreContacts = false) { }
|
||||
|
||||
/// <summary>a Character has picked the item</summary>
|
||||
public virtual bool Pick(Character picker)
|
||||
|
||||
@@ -315,7 +315,7 @@ namespace Barotrauma.Items.Components
|
||||
IsActive = activeContainedItems.Count > 0 || Inventory.AllItems.Any(it => it.body != null);
|
||||
}
|
||||
|
||||
public override void Move(Vector2 amount)
|
||||
public override void Move(Vector2 amount, bool ignoreContacts = false)
|
||||
{
|
||||
SetContainedItemPositions();
|
||||
}
|
||||
@@ -751,7 +751,11 @@ namespace Barotrauma.Items.Components
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
Inventory.AllItemsMod.ForEach(it => it.Drop(null));
|
||||
//if we're unloading the whole sub, no need to drop anything (everything's going to be removed anyway)
|
||||
if (!Submarine.Unloading)
|
||||
{
|
||||
Inventory.AllItemsMod.ForEach(it => it.Drop(null));
|
||||
}
|
||||
}
|
||||
|
||||
public override void Load(ContentXElement componentElement, bool usePrefabValues, IdRemap idRemap)
|
||||
|
||||
@@ -462,19 +462,8 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
dir = dir == Direction.Left ? Direction.Right : Direction.Left;
|
||||
}
|
||||
|
||||
userPos.X = -UserPos.X;
|
||||
|
||||
for (int i = 0; i < limbPositions.Count; i++)
|
||||
{
|
||||
float diff = (item.Rect.X + limbPositions[i].Position.X * item.Scale) - item.Rect.Center.X;
|
||||
|
||||
Vector2 flippedPos =
|
||||
new Vector2(
|
||||
(item.Rect.Center.X - diff - item.Rect.X) / item.Scale,
|
||||
limbPositions[i].Position.Y);
|
||||
limbPositions[i] = new LimbPos(limbPositions[i].LimbType, flippedPos, limbPositions[i].AllowUsingLimb);
|
||||
}
|
||||
userPos.X = -UserPos.X;
|
||||
FlipLimbPositions();
|
||||
}
|
||||
|
||||
public override void FlipY(bool relativeToSub)
|
||||
@@ -519,6 +508,11 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
if (Screen.Selected == GameMain.SubEditorScreen)
|
||||
{
|
||||
if (item.FlippedX)
|
||||
{
|
||||
FlipLimbPositions();
|
||||
}
|
||||
// Don't save flipped positions.
|
||||
foreach (var limbPos in limbPositions)
|
||||
{
|
||||
element.Add(new XElement("limbposition",
|
||||
@@ -526,6 +520,10 @@ namespace Barotrauma.Items.Components
|
||||
new XAttribute("position", XMLExtensions.Vector2ToString(limbPos.Position)),
|
||||
new XAttribute("allowusinglimb", limbPos.AllowUsingLimb)));
|
||||
}
|
||||
if (item.FlippedX)
|
||||
{
|
||||
FlipLimbPositions();
|
||||
}
|
||||
}
|
||||
return element;
|
||||
}
|
||||
@@ -558,5 +556,29 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void FlipLimbPositions()
|
||||
{
|
||||
for (int i = 0; i < limbPositions.Count; i++)
|
||||
{
|
||||
float diff = (item.Rect.X + limbPositions[i].Position.X * item.Scale) - item.Rect.Center.X;
|
||||
|
||||
Vector2 flippedPos =
|
||||
new Vector2(
|
||||
(item.Rect.Center.X - diff - item.Rect.X) / item.Scale,
|
||||
limbPositions[i].Position.Y);
|
||||
limbPositions[i] = new LimbPos(limbPositions[i].LimbType, flippedPos, limbPositions[i].AllowUsingLimb);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
base.Reset();
|
||||
LoadLimbPositions(originalElement);
|
||||
if (item.FlippedX)
|
||||
{
|
||||
FlipLimbPositions();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,7 +150,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
if (powerOut?.Grid != null) { return powerOut.Grid.Voltage; }
|
||||
}
|
||||
return voltage;
|
||||
return currPowerConsumption <= 0.0f ? 1.0f : voltage;
|
||||
}
|
||||
set
|
||||
{
|
||||
|
||||
@@ -231,6 +231,13 @@ namespace Barotrauma.Items.Components
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize(false, IsPropertySaveable.No, description:"Enable only if you want to make the projectile ignore collisions with other projectiles when it's shot. Doesn't have any effect, if the item is not set to be damaged by projectiles.")]
|
||||
public bool IgnoreProjectilesWhileActive
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public Body StickTarget
|
||||
{
|
||||
get;
|
||||
@@ -405,6 +412,10 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
item.body.CollisionCategories = Physics.CollisionProjectile;
|
||||
item.body.CollidesWith = Physics.CollisionCharacter | Physics.CollisionWall | Physics.CollisionLevel | Physics.CollisionItemBlocking;
|
||||
if (item.Prefab.DamagedByProjectiles && !IgnoreProjectilesWhileActive)
|
||||
{
|
||||
item.body.CollidesWith |= Physics.CollisionProjectile;
|
||||
}
|
||||
|
||||
IsActive = true;
|
||||
|
||||
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
sealed class AndComponent : BooleanOperatorComponent
|
||||
{
|
||||
public AndComponent(Item item, ContentXElement element)
|
||||
: base(item, element) { }
|
||||
|
||||
protected override bool GetOutput(int numTrueInputs) => numTrueInputs >= 2;
|
||||
}
|
||||
}
|
||||
+8
-5
@@ -3,7 +3,7 @@ using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
class AndComponent : ItemComponent
|
||||
abstract class BooleanOperatorComponent : ItemComponent
|
||||
{
|
||||
protected string output, falseOutput;
|
||||
|
||||
@@ -70,22 +70,25 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
public AndComponent(Item item, ContentXElement element)
|
||||
public BooleanOperatorComponent(Item item, ContentXElement element)
|
||||
: base(item, element)
|
||||
{
|
||||
timeSinceReceived = new float[] { Math.Max(timeFrame * 2.0f, 0.1f), Math.Max(timeFrame * 2.0f, 0.1f) };
|
||||
IsActive = true;
|
||||
}
|
||||
|
||||
public override void Update(float deltaTime, Camera cam)
|
||||
protected abstract bool GetOutput(int numTrueInputs);
|
||||
|
||||
public sealed override void Update(float deltaTime, Camera cam)
|
||||
{
|
||||
bool state = true;
|
||||
int receivedInputs = 0;
|
||||
for (int i = 0; i < timeSinceReceived.Length; i++)
|
||||
{
|
||||
if (timeSinceReceived[i] > timeFrame) { state = false; }
|
||||
if (timeSinceReceived[i] <= timeFrame) { receivedInputs += 1; }
|
||||
timeSinceReceived[i] += deltaTime;
|
||||
}
|
||||
|
||||
bool state = GetOutput(receivedInputs);
|
||||
string signalOut = state ? output : falseOutput;
|
||||
if (string.IsNullOrEmpty(signalOut))
|
||||
{
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
sealed class OrComponent : BooleanOperatorComponent
|
||||
{
|
||||
public OrComponent(Item item, ContentXElement element)
|
||||
: base(item, element) { }
|
||||
|
||||
protected override bool GetOutput(int numTrueInputs) => numTrueInputs > 0;
|
||||
}
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
sealed class XorComponent : BooleanOperatorComponent
|
||||
{
|
||||
public XorComponent(Item item, ContentXElement element)
|
||||
: base(item, element) { }
|
||||
|
||||
protected override bool GetOutput(int numTrueInputs) => numTrueInputs == 1;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
@@ -19,11 +20,8 @@ namespace Barotrauma.Items.Components
|
||||
public readonly string Name;
|
||||
public readonly LocalizedString DisplayName;
|
||||
|
||||
private readonly Wire[] wires;
|
||||
public IEnumerable<Wire> Wires
|
||||
{
|
||||
get { return wires; }
|
||||
}
|
||||
private readonly HashSet<Wire> wires;
|
||||
public IReadOnlyCollection<Wire> Wires => wires;
|
||||
|
||||
private readonly Item item;
|
||||
|
||||
@@ -31,7 +29,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public readonly List<StatusEffect> Effects;
|
||||
|
||||
public readonly ushort[] wireId;
|
||||
public readonly List<ushort> LoadedWireIds;
|
||||
|
||||
//The grid the connection is a part of
|
||||
public GridInfo Grid;
|
||||
@@ -92,7 +90,7 @@ namespace Barotrauma.Items.Components
|
||||
MaxWires = Math.Max(element.Elements().Count(e => e.Name.ToString().Equals("link", StringComparison.OrdinalIgnoreCase)), MaxWires);
|
||||
|
||||
MaxPlayerConnectableWires = element.GetAttributeInt("maxplayerconnectablewires", MaxWires);
|
||||
wires = new Wire[MaxWires];
|
||||
wires = new HashSet<Wire>();
|
||||
|
||||
IsOutput = element.Name.ToString() == "output";
|
||||
Name = element.GetAttributeString("name", IsOutput ? "output" : "input");
|
||||
@@ -150,23 +148,15 @@ namespace Barotrauma.Items.Components
|
||||
IsPower = Name == "power_in" || Name == "power" || Name == "power_out";
|
||||
|
||||
|
||||
wireId = new ushort[MaxWires];
|
||||
|
||||
LoadedWireIds = new List<ushort>();
|
||||
foreach (var subElement in element.Elements())
|
||||
{
|
||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||
{
|
||||
case "link":
|
||||
int index = -1;
|
||||
for (int i = 0; i < MaxWires; i++)
|
||||
{
|
||||
if (wireId[i] < 1) { index = i; }
|
||||
}
|
||||
if (index == -1) { break; }
|
||||
|
||||
int id = subElement.GetAttributeInt("w", 0);
|
||||
if (id < 0) { id = 0; }
|
||||
wireId[index] = idRemap.GetOffsetId(id);
|
||||
if (LoadedWireIds.Count < MaxWires) { LoadedWireIds.Add(idRemap.GetOffsetId(id)); }
|
||||
|
||||
break;
|
||||
case "statuseffect":
|
||||
@@ -185,138 +175,111 @@ namespace Barotrauma.Items.Components
|
||||
private void RefreshRecipients()
|
||||
{
|
||||
recipients.Clear();
|
||||
for (int i = 0; i < MaxWires; i++)
|
||||
foreach (var wire in wires)
|
||||
{
|
||||
if (wires[i] == null) continue;
|
||||
Connection recipient = wires[i].OtherConnection(this);
|
||||
if (recipient != null) recipients.Add(recipient);
|
||||
Connection recipient = wire.OtherConnection(this);
|
||||
if (recipient != null) { recipients.Add(recipient); }
|
||||
}
|
||||
recipientsDirty = false;
|
||||
}
|
||||
|
||||
public int FindEmptyIndex()
|
||||
{
|
||||
for (int i = 0; i < MaxWires; i++)
|
||||
{
|
||||
if (wires[i] == null) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public int FindWireIndex(Wire wire)
|
||||
{
|
||||
for (int i = 0; i < MaxWires; i++)
|
||||
{
|
||||
if (wires[i] == wire) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public int FindWireIndex(Item wireItem)
|
||||
{
|
||||
for (int i = 0; i < MaxWires; i++)
|
||||
{
|
||||
if (wires[i] == null && wireItem == null) return i;
|
||||
if (wires[i] != null && wires[i].Item == wireItem) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
public Wire FindWireByItem(Item it)
|
||||
=> Wires.FirstOrDefault(w => w.Item == it);
|
||||
|
||||
public bool WireSlotsAvailable()
|
||||
=> wires.Count < MaxWires;
|
||||
|
||||
public bool TryAddLink(Wire wire)
|
||||
{
|
||||
for (int i = 0; i < MaxWires; i++)
|
||||
if (wire is null
|
||||
|| wires.Contains(wire)
|
||||
|| !WireSlotsAvailable())
|
||||
{
|
||||
if (wires[i] == null)
|
||||
{
|
||||
SetWire(i, wire);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
wires.Add(wire);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void SetWire(int index, Wire wire)
|
||||
public void DisconnectWire(Wire wire)
|
||||
{
|
||||
Wire previousWire = wires[index];
|
||||
if (wire != previousWire && previousWire != null)
|
||||
{
|
||||
var otherConnection = previousWire.OtherConnection(this);
|
||||
if (otherConnection != null)
|
||||
{
|
||||
//Change the connection grids or flag them for updating
|
||||
if (IsPower && otherConnection.IsPower && Grid != null)
|
||||
{
|
||||
//Check if both connections belong to a larger grid
|
||||
if (otherConnection.recipients.Count > 1 && recipients.Count > 1)
|
||||
{
|
||||
Powered.ChangedConnections.Add(otherConnection);
|
||||
Powered.ChangedConnections.Add(this);
|
||||
}
|
||||
else if (recipients.Count > 1)
|
||||
{
|
||||
//This wire was the only one at the other grid
|
||||
otherConnection.Grid?.RemoveConnection(otherConnection);
|
||||
otherConnection.Grid = null;
|
||||
}
|
||||
else if (otherConnection.recipients.Count > 1)
|
||||
{
|
||||
Grid?.RemoveConnection(this);
|
||||
Grid = null;
|
||||
}
|
||||
else if (Grid.Connections.Count == 2)
|
||||
{
|
||||
//Delete the grid as these were the only 2 devices
|
||||
Powered.Grids.Remove(Grid.ID);
|
||||
Grid = null;
|
||||
otherConnection.Grid = null;
|
||||
}
|
||||
}
|
||||
otherConnection.recipientsDirty = true;
|
||||
}
|
||||
}
|
||||
if (wire == null || !wires.Contains(wire)) { return; }
|
||||
|
||||
wires[index] = wire;
|
||||
var prevOtherConnection = wire.OtherConnection(this);
|
||||
if (prevOtherConnection != null)
|
||||
{
|
||||
//Change the connection grids or flag them for updating
|
||||
if (IsPower && prevOtherConnection.IsPower && Grid != null)
|
||||
{
|
||||
//Check if both connections belong to a larger grid
|
||||
if (prevOtherConnection.recipients.Count > 1 && recipients.Count > 1)
|
||||
{
|
||||
Powered.ChangedConnections.Add(prevOtherConnection);
|
||||
Powered.ChangedConnections.Add(this);
|
||||
}
|
||||
else if (recipients.Count > 1)
|
||||
{
|
||||
//This wire was the only one at the other grid
|
||||
prevOtherConnection.Grid?.RemoveConnection(prevOtherConnection);
|
||||
prevOtherConnection.Grid = null;
|
||||
}
|
||||
else if (prevOtherConnection.recipients.Count > 1)
|
||||
{
|
||||
Grid?.RemoveConnection(this);
|
||||
Grid = null;
|
||||
}
|
||||
else if (Grid.Connections.Count == 2)
|
||||
{
|
||||
//Delete the grid as these were the only 2 devices
|
||||
Powered.Grids.Remove(Grid.ID);
|
||||
Grid = null;
|
||||
prevOtherConnection.Grid = null;
|
||||
}
|
||||
}
|
||||
prevOtherConnection.recipientsDirty = true;
|
||||
}
|
||||
wires.Remove(wire);
|
||||
recipientsDirty = true;
|
||||
if (wire != null)
|
||||
}
|
||||
|
||||
public void ConnectWire(Wire wire)
|
||||
{
|
||||
if (wire == null || !TryAddLink(wire)) { return; }
|
||||
ConnectionPanel.DisconnectedWires.Remove(wire);
|
||||
var otherConnection = wire.OtherConnection(this);
|
||||
if (otherConnection != null)
|
||||
{
|
||||
|
||||
ConnectionPanel.DisconnectedWires.Remove(wire);
|
||||
var otherConnection = wire.OtherConnection(this);
|
||||
if (otherConnection != null)
|
||||
//Set the other connection grid if a grid exists already
|
||||
if (Powered.ValidPowerConnection(this, otherConnection))
|
||||
{
|
||||
//Set the other connection grid if a grid exists already
|
||||
if (Powered.ValidPowerConnection(this, otherConnection))
|
||||
if (Grid == null && otherConnection.Grid != null)
|
||||
{
|
||||
if (Grid == null && otherConnection.Grid != null)
|
||||
{
|
||||
otherConnection.Grid.AddConnection(this);
|
||||
Grid = otherConnection.Grid;
|
||||
}
|
||||
else if (Grid != null && otherConnection.Grid == null)
|
||||
{
|
||||
Grid.AddConnection(otherConnection);
|
||||
otherConnection.Grid = Grid;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Flag change so that proper grids can be formed
|
||||
Powered.ChangedConnections.Add(this);
|
||||
Powered.ChangedConnections.Add(otherConnection);
|
||||
}
|
||||
otherConnection.Grid.AddConnection(this);
|
||||
Grid = otherConnection.Grid;
|
||||
}
|
||||
else if (Grid != null && otherConnection.Grid == null)
|
||||
{
|
||||
Grid.AddConnection(otherConnection);
|
||||
otherConnection.Grid = Grid;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Flag change so that proper grids can be formed
|
||||
Powered.ChangedConnections.Add(this);
|
||||
Powered.ChangedConnections.Add(otherConnection);
|
||||
}
|
||||
|
||||
otherConnection.recipientsDirty = true;
|
||||
}
|
||||
|
||||
otherConnection.recipientsDirty = true;
|
||||
}
|
||||
recipientsDirty = true;
|
||||
}
|
||||
|
||||
public void SendSignal(Signal signal)
|
||||
{
|
||||
for (int i = 0; i < MaxWires; i++)
|
||||
foreach (var wire in wires)
|
||||
{
|
||||
if (wires[i] == null) { continue; }
|
||||
|
||||
Connection recipient = wires[i].OtherConnection(this);
|
||||
Connection recipient = wire.OtherConnection(this);
|
||||
if (recipient == null) { continue; }
|
||||
if (recipient.item == this.item || signal.source?.LastSentSignalRecipients.LastOrDefault() == recipient) { continue; }
|
||||
|
||||
@@ -350,35 +313,32 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < MaxWires; i++)
|
||||
foreach (var wire in wires)
|
||||
{
|
||||
if (wires[i] == null) continue;
|
||||
|
||||
wires[i].RemoveConnection(this);
|
||||
wires[i] = null;
|
||||
wire.RemoveConnection(this);
|
||||
recipientsDirty = true;
|
||||
}
|
||||
wires.Clear();
|
||||
}
|
||||
|
||||
public void ConnectLinked()
|
||||
public void InitializeFromLoaded()
|
||||
{
|
||||
if (wireId == null) return;
|
||||
if (LoadedWireIds.Count == 0) { return; }
|
||||
|
||||
for (int i = 0; i < MaxWires; i++)
|
||||
for (int i = 0; i < LoadedWireIds.Count; i++)
|
||||
{
|
||||
if (wireId[i] == 0) { continue; }
|
||||
if (!(Entity.FindEntityByID(LoadedWireIds[i]) is Item wireItem)) { continue; }
|
||||
|
||||
if (!(Entity.FindEntityByID(wireId[i]) is Item wireItem)) { continue; }
|
||||
wires[i] = wireItem.GetComponent<Wire>();
|
||||
recipientsDirty = true;
|
||||
|
||||
if (wires[i] != null)
|
||||
var wire = wireItem.GetComponent<Wire>();
|
||||
if (wire != null && TryAddLink(wire))
|
||||
{
|
||||
if (wires[i].Item.body != null) wires[i].Item.body.Enabled = false;
|
||||
wires[i].Connect(this, false, false);
|
||||
wires[i].FixNodeEnds();
|
||||
if (wire.Item.body != null) wire.Item.body.Enabled = false;
|
||||
wire.Connect(this, false, false);
|
||||
wire.FixNodeEnds();
|
||||
recipientsDirty = true;
|
||||
}
|
||||
}
|
||||
LoadedWireIds.Clear();
|
||||
}
|
||||
|
||||
|
||||
@@ -386,19 +346,10 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
XElement newElement = new XElement(IsOutput ? "output" : "input", new XAttribute("name", Name));
|
||||
|
||||
Array.Sort(wires, delegate (Wire wire1, Wire wire2)
|
||||
foreach (var wire in wires.OrderBy(w => w.Item.ID))
|
||||
{
|
||||
if (wire1 == null) return 1;
|
||||
if (wire2 == null) return -1;
|
||||
return wire1.Item.ID.CompareTo(wire2.Item.ID);
|
||||
});
|
||||
|
||||
for (int i = 0; i < MaxWires; i++)
|
||||
{
|
||||
if (wires[i] == null) continue;
|
||||
|
||||
newElement.Add(new XElement("link",
|
||||
new XAttribute("w", wires[i].Item.ID.ToString())));
|
||||
new XAttribute("w", wire.Item.ID.ToString())));
|
||||
}
|
||||
|
||||
parentElement.Add(newElement);
|
||||
|
||||
+7
-25
@@ -49,7 +49,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public bool TemporarilyLocked
|
||||
{
|
||||
get { return Level.IsLoadedOutpost && item.GetComponent<DockingPort>() != null; }
|
||||
get { return Level.IsLoadedOutpost && (item.GetComponent<DockingPort>()?.Docked ?? false); }
|
||||
}
|
||||
|
||||
//connection panels can't be deactivated externally (by signals or status effects)
|
||||
@@ -99,7 +99,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
foreach (Connection c in Connections)
|
||||
{
|
||||
c.ConnectLinked();
|
||||
c.InitializeFromLoaded();
|
||||
}
|
||||
|
||||
if (disconnectedWireIds != null)
|
||||
@@ -286,25 +286,8 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
for (int i = 0; i < loadedConnections.Count && i < Connections.Count; i++)
|
||||
{
|
||||
if (loadedConnections[i].wireId.Length == Connections[i].wireId.Length)
|
||||
{
|
||||
loadedConnections[i].wireId.CopyTo(Connections[i].wireId, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
//backwards compatibility when maximum number of wires has changed
|
||||
foreach (ushort id in loadedConnections[i].wireId)
|
||||
{
|
||||
for (int j = 0; j < Connections[i].wireId.Length; j++)
|
||||
{
|
||||
if (Connections[i].wireId[j] == 0)
|
||||
{
|
||||
Connections[i].wireId[j] = id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Connections[i].LoadedWireIds.Clear();
|
||||
Connections[i].LoadedWireIds.AddRange(loadedConnections[i].LoadedWireIds);
|
||||
}
|
||||
|
||||
disconnectedWireIds = element.GetAttributeUshortArray("disconnectedwires", Array.Empty<ushort>()).ToList();
|
||||
@@ -361,10 +344,8 @@ namespace Barotrauma.Items.Components
|
||||
DisconnectedWires.Clear();
|
||||
foreach (Connection c in Connections)
|
||||
{
|
||||
foreach (Wire wire in c.Wires)
|
||||
foreach (Wire wire in c.Wires.ToArray())
|
||||
{
|
||||
if (wire == null) { continue; }
|
||||
|
||||
if (wire.OtherConnection(c) == null) //wire not connected to anything else
|
||||
{
|
||||
#if CLIENT
|
||||
@@ -408,13 +389,14 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
foreach (Connection connection in Connections)
|
||||
{
|
||||
msg.WriteVariableUInt32((uint)connection.Wires.Count);
|
||||
foreach (Wire wire in connection.Wires)
|
||||
{
|
||||
msg.Write(wire?.Item == null ? (ushort)0 : wire.Item.ID);
|
||||
}
|
||||
}
|
||||
|
||||
msg.Write((ushort)DisconnectedWires.Count());
|
||||
msg.Write((ushort)DisconnectedWires.Count);
|
||||
foreach (Wire disconnectedWire in DisconnectedWires)
|
||||
{
|
||||
msg.Write(disconnectedWire.Item.ID);
|
||||
|
||||
@@ -187,7 +187,7 @@ namespace Barotrauma.Items.Components
|
||||
set;
|
||||
}
|
||||
|
||||
public override void Move(Vector2 amount)
|
||||
public override void Move(Vector2 amount, bool ignoreContacts = false)
|
||||
{
|
||||
#if CLIENT
|
||||
Light.Position += amount;
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
class OrComponent : AndComponent
|
||||
{
|
||||
public OrComponent(Item item, ContentXElement element)
|
||||
: base(item, element)
|
||||
{
|
||||
IsActive = true;
|
||||
}
|
||||
|
||||
public override void Update(float deltaTime, Camera cam)
|
||||
{
|
||||
bool state = false;
|
||||
for (int i = 0; i < timeSinceReceived.Length; i++)
|
||||
{
|
||||
if (timeSinceReceived[i] <= timeFrame) { state = true; }
|
||||
timeSinceReceived[i] += deltaTime;
|
||||
}
|
||||
|
||||
string signalOut = state ? output : falseOutput;
|
||||
if (string.IsNullOrEmpty(signalOut))
|
||||
{
|
||||
//deactivate the component if state is false and there's no false output (will be woken up by non-zero signals in ReceiveSignal)
|
||||
if (!state) { IsActive = false; }
|
||||
return;
|
||||
}
|
||||
|
||||
item.SendSignal(new Signal(signalOut, sender: signalSender[0] ?? signalSender[1]), "signal_out");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -135,7 +135,7 @@ namespace Barotrauma.Items.Components
|
||||
// = no point in receiving
|
||||
if (!LinkToChat)
|
||||
{
|
||||
if (signalOutConnection == null || !signalOutConnection.Wires.Any(w => w != null))
|
||||
if (signalOutConnection == null || signalOutConnection.Wires.Count <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -143,12 +143,11 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
if (connections[i] == null || connections[i].Item != item) { continue; }
|
||||
|
||||
foreach (Wire wire in connections[i].Wires)
|
||||
if (connections[i].Wires.Contains(this))
|
||||
{
|
||||
if (wire != this) continue;
|
||||
SetConnectedDirty();
|
||||
|
||||
connections[i].SetWire(connections[i].FindWireIndex(wire), null);
|
||||
connections[i].DisconnectWire(this);
|
||||
}
|
||||
|
||||
connections[i] = null;
|
||||
@@ -597,15 +596,16 @@ namespace Barotrauma.Items.Components
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
if (connections[i] == null) { continue; }
|
||||
int wireIndex = connections[i].FindWireIndex(item);
|
||||
if (wireIndex == -1) { continue; }
|
||||
|
||||
var wire = connections[i].FindWireByItem(item);
|
||||
if (wire is null) { continue; }
|
||||
#if SERVER
|
||||
if (!connections[i].Item.Removed && (!connections[i].Item.Submarine?.Loading ?? true) && (!Level.Loaded?.Generating ?? true))
|
||||
{
|
||||
connections[i].Item.CreateServerEvent(connections[i].Item.GetComponent<ConnectionPanel>());
|
||||
}
|
||||
#endif
|
||||
connections[i].SetWire(wireIndex, null);
|
||||
connections[i].DisconnectWire(wire);
|
||||
connections[i] = null;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
class XorComponent : AndComponent
|
||||
{
|
||||
public XorComponent(Item item, ContentXElement element)
|
||||
: base(item, element)
|
||||
{
|
||||
IsActive = true;
|
||||
}
|
||||
|
||||
public override void Update(float deltaTime, Camera cam)
|
||||
{
|
||||
int receivedInputs = 0;
|
||||
for (int i = 0; i < timeSinceReceived.Length; i++)
|
||||
{
|
||||
if (timeSinceReceived[i] <= timeFrame) { receivedInputs += 1; }
|
||||
timeSinceReceived[i] += deltaTime;
|
||||
}
|
||||
|
||||
bool state = receivedInputs == 1;
|
||||
string signalOut = state ? output : falseOutput;
|
||||
if (string.IsNullOrEmpty(signalOut))
|
||||
{
|
||||
//deactivate the component if state is false and there's no false output (will be woken up by non-zero signals in ReceiveSignal)
|
||||
if (!state) { IsActive = false; }
|
||||
return;
|
||||
}
|
||||
|
||||
item.SendSignal(new Signal(signalOut, sender: signalSender[0] ?? signalSender[1]), "signal_out");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,9 +3,8 @@ using FarseerPhysics.Dynamics;
|
||||
using FarseerPhysics.Dynamics.Contacts;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Linq;
|
||||
using System.Linq;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
@@ -93,13 +92,11 @@ namespace Barotrauma.Items.Components
|
||||
base.OnItemLoaded();
|
||||
float radiusAttribute = originalElement.GetAttributeFloat("radius", 10.0f);
|
||||
Radius = ConvertUnits.ToSimUnits(radiusAttribute * item.Scale);
|
||||
PhysicsBody = new PhysicsBody(0.0f, 0.0f, Radius, 1.5f)
|
||||
PhysicsBody = new PhysicsBody(0.0f, 0.0f, Radius, 1.5f, BodyType.Static, Physics.CollisionWall, LevelTrigger.GetCollisionCategories(triggeredBy))
|
||||
{
|
||||
BodyType = BodyType.Static,
|
||||
CollidesWith = LevelTrigger.GetCollisionCategories(triggeredBy),
|
||||
CollisionCategories = Physics.CollisionWall,
|
||||
UserData = item
|
||||
};
|
||||
PhysicsBody.SetTransformIgnoreContacts(item.SimPosition, 0.0f);
|
||||
PhysicsBody.FarseerBody.SetIsSensor(true);
|
||||
PhysicsBody.FarseerBody.OnCollision += OnCollision;
|
||||
PhysicsBody.FarseerBody.OnSeparation += OnSeparation;
|
||||
@@ -215,12 +212,18 @@ namespace Barotrauma.Items.Components
|
||||
body.ApplyForce(force);
|
||||
}
|
||||
|
||||
public override void Move(Vector2 amount)
|
||||
public override void Move(Vector2 amount, bool ignoreContacts = false)
|
||||
{
|
||||
base.Move(amount);
|
||||
if (PhysicsBody != null)
|
||||
{
|
||||
PhysicsBody.SetTransform(PhysicsBody.SimPosition + ConvertUnits.ToSimUnits(amount), 0.0f);
|
||||
if (ignoreContacts)
|
||||
{
|
||||
PhysicsBody.SetTransformIgnoreContacts(PhysicsBody.SimPosition + ConvertUnits.ToSimUnits(amount), 0.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
PhysicsBody.SetTransform(PhysicsBody.SimPosition + ConvertUnits.ToSimUnits(amount), 0.0f);
|
||||
}
|
||||
PhysicsBody.Submarine = item.Submarine;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -661,6 +661,7 @@ namespace Barotrauma.Items.Components
|
||||
while (neededPower > 0.0001f && batteries.Count > 0)
|
||||
{
|
||||
batteries.RemoveAll(b => b.Charge <= 0.0001f || b.MaxOutPut <= 0.0001f);
|
||||
if (!batteries.Any()) { break; }
|
||||
float takePower = neededPower / batteries.Count;
|
||||
takePower = Math.Min(takePower, batteries.Min(b => Math.Min(b.Charge * 3600.0f, b.MaxOutPut)));
|
||||
foreach (PowerContainer battery in batteries)
|
||||
@@ -1151,8 +1152,12 @@ namespace Barotrauma.Items.Components
|
||||
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 (enemy.Submarine != null && enemy.Submarine.TeamID == character.Submarine.TeamID) { continue; }
|
||||
if (enemy.IsDead || !enemy.Enabled) { continue; }
|
||||
if (character.Submarine != null)
|
||||
{
|
||||
if (enemy.Submarine == character.Submarine) { continue; }
|
||||
if (enemy.Submarine != null && enemy.Submarine.TeamID == character.Submarine.TeamID) { continue; }
|
||||
}
|
||||
// Don't aim monsters that are inside any submarine.
|
||||
if (!enemy.IsHuman && enemy.CurrentHull != null) { continue; }
|
||||
if (HumanAIController.IsFriendly(character, enemy)) { continue; }
|
||||
|
||||
@@ -115,7 +115,7 @@ namespace Barotrauma
|
||||
|
||||
private readonly Quality qualityComponent;
|
||||
|
||||
private readonly ConcurrentQueue<float> impactQueue = new ConcurrentQueue<float>();
|
||||
private ConcurrentQueue<float> impactQueue;
|
||||
|
||||
//a dictionary containing lists of the status effects in all the components of the item
|
||||
private readonly bool[] hasStatusEffectsOfType;
|
||||
@@ -835,33 +835,35 @@ namespace Barotrauma
|
||||
var rand = new Random(ID);
|
||||
density = MathHelper.Lerp(minDensity, maxDensity, (float)rand.NextDouble());
|
||||
}
|
||||
body = new PhysicsBody(subElement, ConvertUnits.ToSimUnits(Position), Scale, density);
|
||||
|
||||
string collisionCategory = subElement.GetAttributeString("collisioncategory", null);
|
||||
string collisionCategoryStr = subElement.GetAttributeString("collisioncategory", null);
|
||||
|
||||
Category collisionCategory = Physics.CollisionItem;
|
||||
Category collidesWith = Physics.CollisionWall | Physics.CollisionLevel | Physics.CollisionPlatform;
|
||||
if ((Prefab.DamagedByProjectiles || Prefab.DamagedByMeleeWeapons) && Condition > 0)
|
||||
{
|
||||
//force collision category to Character to allow projectiles and weapons to hit
|
||||
//(we could also do this by making the projectiles and weapons hit CollisionItem
|
||||
//and check if the collision should be ignored in the OnCollision callback, but
|
||||
//that'd make the hit detection more expensive because every item would be included)
|
||||
body.CollisionCategories = Physics.CollisionCharacter;
|
||||
body.CollidesWith = Physics.CollisionWall | Physics.CollisionLevel | Physics.CollisionPlatform | Physics.CollisionProjectile;
|
||||
collisionCategory = Physics.CollisionCharacter;
|
||||
}
|
||||
if (collisionCategory != null)
|
||||
if (collisionCategoryStr != null)
|
||||
{
|
||||
if (!Physics.TryParseCollisionCategory(collisionCategory, out Category cat))
|
||||
if (!Physics.TryParseCollisionCategory(collisionCategoryStr, out Category cat))
|
||||
{
|
||||
DebugConsole.ThrowError("Invalid collision category in item \"" + Name+"\" (" + collisionCategory + ")");
|
||||
DebugConsole.ThrowError("Invalid collision category in item \"" + Name+"\" (" + collisionCategoryStr + ")");
|
||||
}
|
||||
else
|
||||
{
|
||||
body.CollisionCategories = cat;
|
||||
collisionCategory = cat;
|
||||
if (cat.HasFlag(Physics.CollisionCharacter))
|
||||
{
|
||||
body.CollidesWith = Physics.CollisionWall | Physics.CollisionLevel | Physics.CollisionPlatform | Physics.CollisionProjectile;
|
||||
collisionCategory |= Physics.CollisionProjectile;
|
||||
}
|
||||
}
|
||||
}
|
||||
body = new PhysicsBody(subElement, ConvertUnits.ToSimUnits(Position), Scale, density, collisionCategory, collidesWith, findNewContacts: false);
|
||||
body.FarseerBody.AngularDamping = subElement.GetAttributeFloat("angulardamping", 0.2f);
|
||||
body.FarseerBody.LinearDamping = subElement.GetAttributeFloat("lineardamping", 0.1f);
|
||||
body.UserData = this;
|
||||
@@ -1261,12 +1263,7 @@ namespace Barotrauma
|
||||
|
||||
partial void SetActiveSpriteProjSpecific();
|
||||
|
||||
public override void Move(Vector2 amount)
|
||||
{
|
||||
Move(amount, ignoreContacts: false);
|
||||
}
|
||||
|
||||
public void Move(Vector2 amount, bool ignoreContacts)
|
||||
public override void Move(Vector2 amount, bool ignoreContacts = false)
|
||||
{
|
||||
if (!MathUtils.IsValid(amount))
|
||||
{
|
||||
@@ -1289,7 +1286,7 @@ namespace Barotrauma
|
||||
}
|
||||
foreach (ItemComponent ic in components)
|
||||
{
|
||||
ic.Move(amount);
|
||||
ic.Move(amount, ignoreContacts);
|
||||
}
|
||||
|
||||
if (body != null && (Submarine == null || !Submarine.Loading)) { FindHull(); }
|
||||
@@ -1703,9 +1700,12 @@ namespace Barotrauma
|
||||
|
||||
public override void Update(float deltaTime, Camera cam)
|
||||
{
|
||||
while (impactQueue.TryDequeue(out float impact))
|
||||
if (impactQueue != null)
|
||||
{
|
||||
HandleCollision(impact);
|
||||
while (impactQueue.TryDequeue(out float impact))
|
||||
{
|
||||
HandleCollision(impact);
|
||||
}
|
||||
}
|
||||
|
||||
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsServer && (!Submarine?.Loading ?? true))
|
||||
@@ -1959,6 +1959,7 @@ namespace Barotrauma
|
||||
if (contact.FixtureA.Body == f1.Body) { normal = -normal; }
|
||||
float impact = Vector2.Dot(f1.Body.LinearVelocity, -normal);
|
||||
|
||||
impactQueue ??= new ConcurrentQueue<float>();
|
||||
impactQueue.Enqueue(impact);
|
||||
|
||||
return true;
|
||||
@@ -2680,21 +2681,21 @@ namespace Barotrauma
|
||||
foreach (ItemComponent ic in components) { ic.Unequip(character); }
|
||||
}
|
||||
|
||||
public List<Pair<object, SerializableProperty>> GetProperties<T>()
|
||||
public List<(object obj, SerializableProperty property)> GetProperties<T>()
|
||||
{
|
||||
List<Pair<object, SerializableProperty>> allProperties = new List<Pair<object, SerializableProperty>>();
|
||||
List<(object obj, SerializableProperty property)> allProperties = new List<(object obj, SerializableProperty property)>();
|
||||
|
||||
List<SerializableProperty> itemProperties = SerializableProperty.GetProperties<T>(this);
|
||||
foreach (var itemProperty in itemProperties)
|
||||
{
|
||||
allProperties.Add(new Pair<object, SerializableProperty>(this, itemProperty));
|
||||
allProperties.Add((this, itemProperty));
|
||||
}
|
||||
foreach (ItemComponent ic in components)
|
||||
{
|
||||
List<SerializableProperty> componentProperties = SerializableProperty.GetProperties<T>(ic);
|
||||
foreach (var componentProperty in componentProperties)
|
||||
{
|
||||
allProperties.Add(new Pair<object, SerializableProperty>(ic, componentProperty));
|
||||
allProperties.Add((ic, componentProperty));
|
||||
}
|
||||
}
|
||||
return allProperties;
|
||||
@@ -2708,13 +2709,13 @@ namespace Barotrauma
|
||||
SerializableProperty property = extraData.SerializableProperty;
|
||||
if (property != null)
|
||||
{
|
||||
var propertyOwner = allProperties.Find(p => p.Second == property);
|
||||
var propertyOwner = allProperties.Find(p => p.property == property);
|
||||
if (allProperties.Count > 1)
|
||||
{
|
||||
msg.Write((byte)allProperties.FindIndex(p => p.Second == property));
|
||||
msg.Write((byte)allProperties.FindIndex(p => p.property == property));
|
||||
}
|
||||
|
||||
object value = property.GetValue(propertyOwner.First);
|
||||
object value = property.GetValue(propertyOwner.obj);
|
||||
if (value is string stringVal)
|
||||
{
|
||||
msg.Write(stringVal);
|
||||
@@ -2795,7 +2796,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
private List<Pair<object, SerializableProperty>> GetInGameEditableProperties(bool ignoreConditions = false)
|
||||
private List<(object obj, SerializableProperty property)> GetInGameEditableProperties(bool ignoreConditions = false)
|
||||
{
|
||||
if (ignoreConditions)
|
||||
{
|
||||
@@ -2804,7 +2805,7 @@ namespace Barotrauma
|
||||
else
|
||||
{
|
||||
return GetProperties<ConditionallyEditable>()
|
||||
.Where(ce => ce.Second.GetAttribute<ConditionallyEditable>().IsEditable(this))
|
||||
.Where(ce => ce.property.GetAttribute<ConditionallyEditable>().IsEditable(this))
|
||||
.Union(GetProperties<InGameEditable>()).ToList();
|
||||
}
|
||||
}
|
||||
@@ -2823,8 +2824,8 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
bool allowEditing = true;
|
||||
object parentObject = allProperties[propertyIndex].First;
|
||||
SerializableProperty property = allProperties[propertyIndex].Second;
|
||||
object parentObject = allProperties[propertyIndex].obj;
|
||||
SerializableProperty property = allProperties[propertyIndex].property;
|
||||
if (inGameEditableOnly && parentObject is ItemComponent ic)
|
||||
{
|
||||
if (!ic.AllowInGameEditing) { allowEditing = false; }
|
||||
|
||||
@@ -253,6 +253,12 @@ namespace Barotrauma
|
||||
public readonly float MinCondition;
|
||||
public readonly int MinAmount;
|
||||
public readonly int MaxAmount;
|
||||
// Overrides min and max, if defined.
|
||||
public readonly int Amount;
|
||||
public readonly bool CampaignOnly;
|
||||
public readonly bool NotCampaign;
|
||||
public readonly bool TransferOnlyOnePerContainer;
|
||||
public readonly bool AllowTransfersHere = true;
|
||||
|
||||
public PreferredContainer(XElement element)
|
||||
{
|
||||
@@ -261,21 +267,26 @@ namespace Barotrauma
|
||||
SpawnProbability = element.GetAttributeFloat("spawnprobability", 0.0f);
|
||||
MinAmount = element.GetAttributeInt("minamount", 0);
|
||||
MaxAmount = Math.Max(MinAmount, element.GetAttributeInt("maxamount", 0));
|
||||
Amount = element.GetAttributeInt("amount", 0);
|
||||
MaxCondition = element.GetAttributeFloat("maxcondition", 100f);
|
||||
MinCondition = element.GetAttributeFloat("mincondition", 0f);
|
||||
CampaignOnly = element.GetAttributeBool("campaignonly", CampaignOnly);
|
||||
NotCampaign = element.GetAttributeBool("notcampaign", NotCampaign);
|
||||
TransferOnlyOnePerContainer = element.GetAttributeBool("TransferOnlyOnePerContainer", TransferOnlyOnePerContainer);
|
||||
AllowTransfersHere = element.GetAttributeBool("AllowTransfersHere", AllowTransfersHere);
|
||||
|
||||
if (element.Attribute("spawnprobability") == null)
|
||||
if (element.GetAttribute("spawnprobability") == null)
|
||||
{
|
||||
//if spawn probability is not defined but amount is, assume the probability is 1
|
||||
if (MaxAmount > 0)
|
||||
if (MaxAmount > 0 || Amount > 0)
|
||||
{
|
||||
SpawnProbability = 1.0f;
|
||||
}
|
||||
}
|
||||
else if (element.Attribute("minamount") == null && element.Attribute("maxamount") == null)
|
||||
else if (element.GetAttribute("minamount") == null && element.GetAttribute("maxamount") == null && element.GetAttribute("amount") == null)
|
||||
{
|
||||
//spawn probability defined but amount isn't, assume amount is 1
|
||||
MinAmount = MaxAmount = 1;
|
||||
MinAmount = MaxAmount = Amount = 1;
|
||||
SpawnProbability = element.GetAttributeFloat("spawnprobability", 0.0f);
|
||||
}
|
||||
}
|
||||
@@ -600,6 +611,9 @@ namespace Barotrauma
|
||||
|
||||
public ImmutableHashSet<Identifier> AllowDroppingOnSwapWith { get; private set; }
|
||||
|
||||
[Serialize(false, IsPropertySaveable.No)]
|
||||
public bool DontTransferBetweenSubs { get; private set; }
|
||||
|
||||
protected override Identifier DetermineIdentifier(XElement element)
|
||||
{
|
||||
Identifier identifier = base.DetermineIdentifier(element);
|
||||
@@ -1084,7 +1098,7 @@ namespace Barotrauma
|
||||
//legacy support
|
||||
identifier = GenerateLegacyIdentifier(name);
|
||||
}
|
||||
prefab = Find(p => p is ItemPrefab && p.Identifier == identifier) as ItemPrefab;
|
||||
Prefabs.TryGet(identifier, out prefab);
|
||||
|
||||
//not found, see if we can find a prefab with a matching alias
|
||||
if (prefab == null && !string.IsNullOrEmpty(name))
|
||||
@@ -1104,12 +1118,13 @@ namespace Barotrauma
|
||||
return prefab;
|
||||
}
|
||||
|
||||
public bool IsContainerPreferred(Item item, ItemContainer targetContainer, out bool isPreferencesDefined, out bool isSecondary, bool requireConditionRequirement = false)
|
||||
public bool IsContainerPreferred(Item item, ItemContainer targetContainer, out bool isPreferencesDefined, out bool isSecondary, bool requireConditionRequirement = false, bool checkTransferConditions = false)
|
||||
{
|
||||
isPreferencesDefined = PreferredContainers.Any();
|
||||
isSecondary = false;
|
||||
if (!isPreferencesDefined) { return true; }
|
||||
if (PreferredContainers.Any(pc => (!requireConditionRequirement || HasConditionRequirement(pc)) && IsItemConditionAcceptable(item, pc) && IsContainerPreferred(pc.Primary, targetContainer)))
|
||||
if (PreferredContainers.Any(pc => (!requireConditionRequirement || HasConditionRequirement(pc)) && IsItemConditionAcceptable(item, pc) &&
|
||||
IsContainerPreferred(pc.Primary, targetContainer) && (!checkTransferConditions || CanBeTransferred(item.Prefab.Identifier, pc, targetContainer))))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -1132,6 +1147,8 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
private bool IsItemConditionAcceptable(Item item, PreferredContainer pc) => item.ConditionPercentage >= pc.MinCondition && item.ConditionPercentage <= pc.MaxCondition;
|
||||
private bool CanBeTransferred(Identifier item, PreferredContainer pc, ItemContainer targetContainer) =>
|
||||
pc.AllowTransfersHere && (!pc.TransferOnlyOnePerContainer || targetContainer.Inventory.AllItems.None(i => i.Prefab.Identifier == item));
|
||||
|
||||
public static bool IsContainerPreferred(IEnumerable<Identifier> preferences, ItemContainer c) => preferences.Any(id => c.Item.Prefab.Identifier == id || c.Item.HasTag(id));
|
||||
public static bool IsContainerPreferred(IEnumerable<Identifier> preferences, IEnumerable<Identifier> ids) => ids.Any(id => preferences.Contains(id));
|
||||
|
||||
Reference in New Issue
Block a user