Build 1.1.4.0

This commit is contained in:
Markus Isberg
2023-03-31 18:40:44 +03:00
parent efba17e0ff
commit 9470edead3
483 changed files with 17487 additions and 8548 deletions
@@ -92,9 +92,6 @@ namespace Barotrauma.Items.Components
rect.Height = (int)(rect.Height * (1.0f - openState));
}
//only merge the door's convex hull with overlapping wall segments if it's fully open or fully closed
//it's the heaviest part of changing the convex hull, and doesn't need to be done while the door is still in motion
bool mergeOverlappingSegments = openState <= 0.0f || openState >= 1.0f;
if (Window.Height > 0 && Window.Width > 0)
{
if (IsHorizontal)
@@ -117,7 +114,7 @@ namespace Barotrauma.Items.Components
else
{
convexHull2.Enabled = true;
convexHull2.SetVertices(GetConvexHullCorners(rect2), mergeOverlappingSegments);
SetVertices(convexHull2, rect2);
}
}
}
@@ -141,7 +138,7 @@ namespace Barotrauma.Items.Components
else
{
convexHull2.Enabled = true;
convexHull2.SetVertices(GetConvexHullCorners(rect2), mergeOverlappingSegments);
SetVertices(convexHull2, rect2);
}
}
}
@@ -156,13 +153,28 @@ namespace Barotrauma.Items.Components
else
{
convexHull.Enabled = true;
convexHull.SetVertices(GetConvexHullCorners(rect), mergeOverlappingSegments);
SetVertices(convexHull, rect);
}
convexHull.IsExteriorWall = !linkedGap.IsRoomToRoom;
if (convexHull2 != null) { convexHull2.IsExteriorWall = convexHull.IsExteriorWall; }
}
private void SetVertices(ConvexHull convexHull, Rectangle rect)
{
var verts = GetConvexHullCorners(rect);
Vector2 center = (verts[0] + verts[2]) / 2;
convexHull.SetVertices(
verts,
IsHorizontal ?
new Vector2[] { new Vector2(verts[0].X, center.Y), new Vector2(verts[2].X, center.Y) } :
new Vector2[] { new Vector2(center.X, verts[0].Y), new Vector2(center.X, verts[2].Y) });
}
partial void UpdateProjSpecific(float deltaTime)
{
convexHull.IsExteriorWall = !linkedGap.IsRoomToRoom;
if (convexHull2 != null) { convexHull2.IsExteriorWall = convexHull.IsExteriorWall; }
if (shakeTimer > 0.0f)
{
shakeTimer -= deltaTime;
@@ -182,7 +194,7 @@ namespace Barotrauma.Items.Components
if (brokenSprite == null)
{
//broken doors turn black if no broken sprite has been configured
color *= (item.Condition / item.MaxCondition);
color = color.Multiply(item.Condition / item.MaxCondition);
color.A = 255;
}
@@ -88,6 +88,11 @@ namespace Barotrauma.Items.Components
public void ClientEventRead(IReadMessage msg, float sendingTime)
{
UInt16 userID = msg.ReadUInt16();
if (userID != Entity.NullEntityID)
{
user = Entity.FindEntityByID(userID) as Character;
}
CurrPowerConsumption = powerConsumption;
charging = true;
timer = Duration;
@@ -1,13 +1,10 @@
using Barotrauma.Particles;
using Barotrauma.Sounds;
using FarseerPhysics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
using Barotrauma.IO;
using System.Text;
using System.Xml.Linq;
using Barotrauma.Sounds;
using System.Linq;
namespace Barotrauma.Items.Components
@@ -169,11 +166,11 @@ namespace Barotrauma.Items.Components
partial void LaunchProjSpecific()
{
Vector2 particlePos = item.WorldPosition + ConvertUnits.ToDisplayUnits(TransformedBarrelPos);
float rotation = -item.body.Rotation;
float rotation = item.body.Rotation;
if (item.body.Dir < 0.0f) { rotation += MathHelper.Pi; }
foreach (ParticleEmitter emitter in particleEmitters)
{
emitter.Emit(1.0f, particlePos, hullGuess: item.CurrentHull, angle: rotation, particleRotation: rotation);
emitter.Emit(1.0f, particlePos, hullGuess: item.CurrentHull, angle: rotation, particleRotation: -rotation);
}
}
@@ -505,13 +505,14 @@ namespace Barotrauma.Items.Components
}
ActionType type;
string typeStr = subElement.GetAttributeString("type", "");
try
{
type = (ActionType)Enum.Parse(typeof(ActionType), subElement.GetAttributeString("type", ""), true);
type = (ActionType)Enum.Parse(typeof(ActionType), typeStr, true);
}
catch (Exception e)
{
DebugConsole.ThrowError("Invalid sound type in " + subElement + "!", e);
DebugConsole.ThrowError($"Invalid sound type \"{typeStr}\" in item \"{item.Prefab.Identifier}\"!", e);
break;
}
@@ -524,11 +525,13 @@ namespace Barotrauma.Items.Components
VolumeProperty = subElement.GetAttributeIdentifier("volumeproperty", "")
};
if (soundSelectionModes == null) soundSelectionModes = new Dictionary<ActionType, SoundSelectionMode>();
if (soundSelectionModes == null)
{
soundSelectionModes = new Dictionary<ActionType, SoundSelectionMode>();
}
if (!soundSelectionModes.ContainsKey(type) || soundSelectionModes[type] == SoundSelectionMode.Random)
{
Enum.TryParse(subElement.GetAttributeString("selectionmode", "Random"), out SoundSelectionMode selectionMode);
soundSelectionModes[type] = selectionMode;
soundSelectionModes[type] = subElement.GetAttributeEnum("selectionmode", SoundSelectionMode.Random);
}
if (!sounds.TryGetValue(itemSound.Type, out List<ItemSound> soundList))
@@ -584,6 +587,8 @@ namespace Barotrauma.Items.Components
{
if (GuiFrame != null && GuiFrameSource.GetAttributeBool("draggable", true))
{
bool hideDragIcons = GuiFrameSource.GetAttributeBool("hidedragicons", false);
var handle = new GUIDragHandle(new RectTransform(Vector2.One, GuiFrame.RectTransform, Anchor.Center),
GuiFrame.RectTransform, style: null)
{
@@ -623,7 +628,7 @@ namespace Barotrauma.Items.Components
};
int buttonHeight = (int)(GUIStyle.ItemFrameMargin.Y * 0.4f);
new GUIButton(new RectTransform(new Point(buttonHeight), handle.RectTransform, Anchor.TopLeft) { AbsoluteOffset = new Point(buttonHeight / 4), MinSize = new Point(buttonHeight) },
var settingsIcon = new GUIButton(new RectTransform(new Point(buttonHeight), handle.RectTransform, Anchor.TopLeft) { AbsoluteOffset = new Point(buttonHeight / 4), MinSize = new Point(buttonHeight) },
style: "GUIButtonSettings")
{
OnClicked = (btn, userdata) =>
@@ -648,6 +653,12 @@ namespace Barotrauma.Items.Components
return true;
}
};
if (hideDragIcons)
{
dragIcon.Visible = false;
settingsIcon.Visible = false;
}
}
}
@@ -277,7 +277,8 @@ namespace Barotrauma.Items.Components
int ignoredItemCount = 0;
var subContainableItems = AllSubContainableItems;
float capacity = GetMaxStackSize(targetSlot);
float targetSlotCapacity = GetMaxStackSize(targetSlot);
float capacity = targetSlotCapacity * MainContainerCapacity;
if (subContainableItems != null)
{
bool useMainContainerCapacity = true;
@@ -299,15 +300,11 @@ namespace Barotrauma.Items.Components
}
if (!useMainContainerCapacity) { break; }
}
if (useMainContainerCapacity)
{
capacity *= MainContainerCapacity;
}
else
if (!useMainContainerCapacity)
{
// Ignore all items in the main container.
ignoredItemCount = Inventory.AllItems.Count(it => subContainableItems.Any(ri => !ri.MatchesItem(it)));
capacity *= Capacity - MainContainerCapacity;
capacity = targetSlotCapacity * (Capacity - MainContainerCapacity);
}
}
int itemCount = Inventory.AllItems.Count() - ignoredItemCount;
@@ -391,63 +388,60 @@ namespace Barotrauma.Items.Components
bool isWiringMode = SubEditorScreen.TransparentWiringMode && SubEditorScreen.IsWiringMode();
int i = 0;
foreach (Item containedItem in Inventory.AllItems)
foreach (DrawableContainedItem contained in drawableContainedItems)
{
Vector2 itemPos = currentItemPos;
var relatedItem = FindContainableItem(containedItem);
if (relatedItem != null)
if (contained.Item?.Sprite == null) { continue; }
if (contained.Hide) { continue; }
if (contained.ItemPos.HasValue)
{
if (relatedItem.Hide.HasValue && relatedItem.Hide.Value) { continue; }
if (relatedItem.ItemPos.HasValue)
Vector2 pos = contained.ItemPos.Value;
if (item.body != null)
{
Vector2 pos = relatedItem.ItemPos.Value;
if (item.body != null)
Matrix transform = Matrix.CreateRotationZ(item.body.DrawRotation);
pos.X *= item.body.Dir;
itemPos = Vector2.Transform(pos, transform) + item.body.DrawPosition;
}
else
{
itemPos = pos;
// This code is aped based on above. Not tested.
if (item.FlippedX)
{
Matrix transform = Matrix.CreateRotationZ(item.body.DrawRotation);
pos.X *= item.body.Dir;
itemPos = Vector2.Transform(pos, transform) + item.body.DrawPosition;
itemPos.X = -itemPos.X;
itemPos.X += item.Rect.Width;
}
else
if (item.FlippedY)
{
itemPos = pos;
// This code is aped based on above. Not tested.
if (item.FlippedX)
{
itemPos.X = -itemPos.X;
itemPos.X += item.Rect.Width;
}
if (item.FlippedY)
{
itemPos.Y = -itemPos.Y;
itemPos.Y -= item.Rect.Height;
}
itemPos += new Vector2(item.Rect.X, item.Rect.Y);
if (item.Submarine != null)
{
itemPos += item.Submarine.DrawPosition;
}
if (Math.Abs(item.RotationRad) > 0.01f)
{
Matrix transform = Matrix.CreateRotationZ(-item.RotationRad);
itemPos = Vector2.Transform(itemPos - item.DrawPosition, transform) + item.DrawPosition;
}
itemPos.Y = -itemPos.Y;
itemPos.Y -= item.Rect.Height;
}
itemPos += new Vector2(item.Rect.X, item.Rect.Y);
if (item.Submarine != null)
{
itemPos += item.Submarine.DrawPosition;
}
if (Math.Abs(item.RotationRad) > 0.01f)
{
Matrix transform = Matrix.CreateRotationZ(-item.RotationRad);
itemPos = Vector2.Transform(itemPos - item.DrawPosition, transform) + item.DrawPosition;
}
}
}
if (containedItem?.Sprite == null) { continue; }
if (AutoInteractWithContained)
{
containedItem.IsHighlighted = item.IsHighlighted;
contained.Item.IsHighlighted = item.IsHighlighted;
item.IsHighlighted = false;
}
Vector2 origin = containedItem.Sprite.Origin;
if (item.FlippedX) { origin.X = containedItem.Sprite.SourceRect.Width - origin.X; }
if (item.FlippedY) { origin.Y = containedItem.Sprite.SourceRect.Height - origin.Y; }
Vector2 origin = contained.Item.Sprite.Origin;
if (item.FlippedX) { origin.X = contained.Item.Sprite.SourceRect.Width - origin.X; }
if (item.FlippedY) { origin.Y = contained.Item.Sprite.SourceRect.Height - origin.Y; }
float containedSpriteDepth = ContainedSpriteDepth < 0.0f ? containedItem.Sprite.Depth : ContainedSpriteDepth;
float containedSpriteDepth = ContainedSpriteDepth < 0.0f ? contained.Item.Sprite.Depth : ContainedSpriteDepth;
if (i < containedSpriteDepths.Length)
{
containedSpriteDepth = containedSpriteDepths[i];
@@ -456,9 +450,9 @@ namespace Barotrauma.Items.Components
SpriteEffects spriteEffects = SpriteEffects.None;
float spriteRotation = ItemRotation;
if (relatedItem != null && relatedItem.Rotation != 0)
if (contained.Rotation != 0)
{
spriteRotation = relatedItem.Rotation;
spriteRotation = contained.Rotation;
}
if ((item.body != null && item.body.Dir == -1) || item.FlippedX)
{
@@ -469,17 +463,17 @@ namespace Barotrauma.Items.Components
spriteEffects |= MathUtils.NearlyEqual(spriteRotation % 180, 90.0f) ? SpriteEffects.FlipHorizontally : SpriteEffects.FlipVertically;
}
containedItem.Sprite.Draw(
contained.Item.Sprite.Draw(
spriteBatch,
new Vector2(itemPos.X, -itemPos.Y),
isWiringMode ? containedItem.GetSpriteColor(withHighlight: true) * 0.15f : containedItem.GetSpriteColor(withHighlight: true),
isWiringMode ? contained.Item.GetSpriteColor(withHighlight: true) * 0.15f : contained.Item.GetSpriteColor(withHighlight: true),
origin,
-(containedItem.body == null ? 0.0f : containedItem.body.DrawRotation),
containedItem.Scale,
-(contained.Item.body == null ? 0.0f : contained.Item.body.DrawRotation),
contained.Item.Scale,
spriteEffects,
depth: containedSpriteDepth);
foreach (ItemContainer ic in containedItem.GetComponents<ItemContainer>())
foreach (ItemContainer ic in contained.Item.GetComponents<ItemContainer>())
{
if (ic.hideItems) { continue; }
ic.DrawContainedItems(spriteBatch, containedSpriteDepth);
@@ -14,6 +14,16 @@ namespace Barotrauma.Items.Components
private CoroutineHandle resetPredictionCoroutine;
private float resetPredictionTimer;
/// <summary>
/// The current multiplier for the light color (usually equal to <see cref="lightBrightness"/>, but in the case of e.g. blinking lights the multiplier
/// doesn't go to 0 when the light turns off, because otherwise it'd take a while for it turn back on based on the lightBrightness which is interpolated
/// towards the current voltage).
/// </summary>
private float lightColorMultiplier;
[Serialize(1.0f, IsPropertySaveable.Yes, description: "The scale of the light sprite.")]
public float LightSpriteScale { get; set; }
public Vector2 DrawSize
{
get { return new Vector2(Light.Range * 2, Light.Range * 2); }
@@ -27,21 +37,14 @@ namespace Barotrauma.Items.Components
Light.Position = ParentBody != null ? ParentBody.Position : item.Position;
}
partial void SetLightSourceState(bool enabled, float? brightness)
partial void SetLightSourceState(bool enabled, float brightness)
{
if (Light == null) { return; }
Light.Enabled = enabled;
if (brightness.HasValue)
{
lightBrightness = brightness.Value;
}
else
{
lightBrightness = enabled ? 1.0f : 0.0f;
}
lightColorMultiplier = brightness;
if (enabled)
{
Light.Color = LightColor.Multiply(lightBrightness);
Light.Color = LightColor.Multiply(lightColorMultiplier);
}
}
@@ -92,7 +95,13 @@ namespace Barotrauma.Items.Components
{
color = new Color(lightColor, Light.OverrideLightSpriteAlpha.Value);
}
Light.LightSprite.Draw(spriteBatch, new Vector2(drawPos.X, -drawPos.Y), color * lightBrightness, origin, -Light.Rotation, item.Scale, Light.LightSpriteEffect, itemDepth - 0.0001f);
Light.LightSprite.Draw(spriteBatch,
new Vector2(drawPos.X, -drawPos.Y),
color * lightBrightness,
origin,
-Light.Rotation,
item.Scale * LightSpriteScale,
Light.LightSpriteEffect, itemDepth - 0.0001f);
}
}
@@ -185,6 +185,7 @@ namespace Barotrauma.Items.Components
RefreshActivateButtonText();
if (GameMain.Client != null)
{
pendingFabricatedItem = null;
item.CreateClientEvent(this);
}
return true;
@@ -336,8 +337,11 @@ namespace Barotrauma.Items.Components
int calculatePlacement(FabricationRecipe recipe)
{
if (recipe.RequiresRecipe && !AnyOneHasRecipeForItem(character, recipe.TargetItem))
{
return -2;
}
int placement = FabricationDegreeOfSuccess(character, recipe.RequiredSkills) >= 0.5f ? 0 : -1;
placement += recipe.RequiresRecipe && !AnyOneHasRecipeForItem(character, recipe.TargetItem) ? -2 : 0;
return placement;
}
@@ -524,7 +528,7 @@ namespace Barotrauma.Items.Components
if (slotRect.Contains(PlayerInput.MousePosition))
{
var suitableIngredients = requiredItem.ItemPrefabs.Select(ip => ip.Name);
var suitableIngredients = requiredItem.ItemPrefabs.Select(ip => ip.Name).Distinct();
LocalizedString toolTipText = string.Join(", ", suitableIngredients.Count() > 3 ? suitableIngredients.SkipLast(suitableIngredients.Count() - 3) : suitableIngredients);
if (suitableIngredients.Count() > 3) { toolTipText += "..."; }
if (requiredItem.UseCondition && requiredItem.MinCondition < 1.0f)
@@ -546,9 +550,11 @@ namespace Barotrauma.Items.Components
{
toolTipText = TextManager.GetWithVariable("displayname.emptyitem", "[itemname]", toolTipText);
}
toolTipText = $"‖color:{Color.White.ToStringHex()}‖{toolTipText}‖color:end‖";
if (!requiredItemPrefab.Description.IsNullOrEmpty())
{
toolTipText += '\n' + requiredItemPrefab.Description;
toolTipText = '\n' + requiredItemPrefab.Description;
}
tooltip = new ToolTip { TargetElement = slotRect, Tooltip = toolTipText };
}
@@ -590,7 +596,7 @@ namespace Barotrauma.Items.Components
if (tooltip != null)
{
GUIComponent.DrawToolTip(spriteBatch, tooltip.Tooltip, tooltip.TargetElement);
GUIComponent.DrawToolTip(spriteBatch, RichString.Rich(tooltip.Tooltip), tooltip.TargetElement);
tooltip = null;
}
}
@@ -298,7 +298,7 @@ namespace Barotrauma.Items.Components
}
}
OrderPrefab[] reports = OrderPrefab.Prefabs.Where(o => o.IsReport && o.SymbolSprite != null && !o.Hidden).ToArray();
OrderPrefab[] reports = OrderPrefab.Prefabs.Where(o => o.IsReport && o.SymbolSprite != null && !o.Hidden).OrderBy(o => o.Identifier).ToArray();
GUIFrame bottomFrame = new GUIFrame(new RectTransform(new Vector2(0.5f, 0.15f), paddedContainer.RectTransform, Anchor.BottomCenter) { MaxSize = new Point(int.MaxValue, GUI.IntScale(40)) }, style: null)
{
@@ -452,7 +452,7 @@ namespace Barotrauma.Items.Components
foreach (var (entity, component) in electricalMapComponents)
{
GUIComponent parent = component.RectComponent;
if (!(entity is Item it )) { continue; }
if (entity is not Item it ) { continue; }
Sprite? sprite = it.Prefab.UpgradePreviewSprite;
if (sprite is null) { continue; }
@@ -476,7 +476,7 @@ namespace Barotrauma.Items.Components
{
if (!hullPointsOfInterest.Contains(entity)) { continue; }
if (!(entity is Item it)) { continue; }
if (entity is not Item it) { continue; }
const int borderMaxSize = 2;
if (it.GetComponent<Door>() is { })
@@ -643,7 +643,7 @@ namespace Barotrauma.Items.Components
elementSize = GuiFrame.Rect.Size;
}
float distort = 1.0f - item.Condition / item.MaxCondition;
float distort = item.Repairables.Any(r => r.IsBelowRepairThreshold) ? 1.0f - item.Condition / item.MaxCondition : 0.0f;
foreach (HullData hullData in hullDatas.Values)
{
hullData.DistortionTimer -= deltaTime;
@@ -702,6 +702,12 @@ namespace Barotrauma.Items.Components
private void DrawHUDFront(SpriteBatch spriteBatch, GUICustomComponent container)
{
if (miniMapFrame == null)
{
//frame not created yet, could happen if the item hasn't been inside any sub this round?
return;
}
if (Voltage < MinVoltage)
{
Vector2 textSize = GUIStyle.Font.MeasureString(noPowerTip);
@@ -1130,7 +1136,7 @@ namespace Barotrauma.Items.Components
{
foreach (var (entity, miniMapGuiComponent) in electricalMapComponents)
{
if (!(entity is Item it)) { continue; }
if (entity is not Item it) { continue; }
if (!electricalChildren.TryGetValue(miniMapGuiComponent, out GUIComponent? component)) { continue; }
if (entity.Removed)
@@ -1220,7 +1226,7 @@ namespace Barotrauma.Items.Components
{
foreach (var (entity, component) in hullStatusComponents)
{
if (!(entity is Hull hull)) { continue; }
if (entity is not Hull hull) { continue; }
if (!hullDatas.TryGetValue(hull, out HullData? hullData) || hullData is null) { continue; }
if (hullData.Distort) { continue; }
@@ -17,6 +17,7 @@ namespace Barotrauma.Items.Components
Default,
Disruption,
Destructible,
Door,
LongRange
}
@@ -110,6 +111,10 @@ namespace Barotrauma.Items.Components
BlipType.Destructible,
new Color[] { Color.TransparentBlack, new Color(74, 113, 75) * 0.8f, new Color(151, 236, 172) * 0.8f, new Color(153, 217, 234) * 0.8f }
},
{
BlipType.Door,
new Color[] { Color.TransparentBlack, new Color(73, 78, 86), new Color(66, 94, 100), new Color(47, 115, 58), new Color(255, 255, 255) }
},
{
BlipType.LongRange,
new Color[] { Color.TransparentBlack, Color.TransparentBlack, new Color(254, 68, 19) * 0.8f, Color.TransparentBlack }
@@ -975,7 +980,7 @@ namespace Barotrauma.Items.Components
if (GameMain.GameSession == null || Level.Loaded == null) { return; }
if (Level.Loaded.StartLocation != null)
if (Level.Loaded.StartLocation?.Type is { ShowSonarMarker: true })
{
DrawMarker(spriteBatch,
Level.Loaded.StartLocation.Name,
@@ -985,7 +990,7 @@ namespace Barotrauma.Items.Components
displayScale, center, DisplayRadius);
}
if (Level.Loaded.EndLocation != null && Level.Loaded.Type == LevelData.LevelType.LocationConnection)
if (Level.Loaded is { EndLocation.Type.ShowSonarMarker: true, Type: LevelData.LevelType.LocationConnection })
{
DrawMarker(spriteBatch,
Level.Loaded.EndLocation.Name,
@@ -1010,19 +1015,19 @@ namespace Barotrauma.Items.Components
int missionIndex = 0;
foreach (Mission mission in GameMain.GameSession.Missions)
{
if (!mission.SonarLabel.IsNullOrWhiteSpace())
int i = 0;
foreach ((LocalizedString label, Vector2 position) in mission.SonarLabels)
{
int i = 0;
foreach (Vector2 sonarPosition in mission.SonarPositions)
if (!string.IsNullOrEmpty(label.Value))
{
DrawMarker(spriteBatch,
mission.SonarLabel.Value,
label.Value,
mission.SonarIconIdentifier,
"mission" + missionIndex + ":" + i,
sonarPosition, transducerCenter,
position, transducerCenter,
displayScale, center, DisplayRadius * 0.95f);
i++;
}
i++;
}
missionIndex++;
}
@@ -1176,13 +1181,18 @@ namespace Barotrauma.Items.Components
if (dockingPort.Item.Submarine == null) { continue; }
if (dockingPort.Item.Submarine.Info.IsWreck) { continue; }
// docking ports should be shown even if defined as not, if the submarine is the same as the sonar's
if (!dockingPort.Item.Submarine.ShowSonarMarker && dockingPort.Item.Submarine != item.Submarine && !dockingPort.Item.Submarine.Info.IsOutpost) { continue; }
if (!dockingPort.Item.Submarine.ShowSonarMarker && dockingPort.Item.Submarine != item.Submarine &&
!dockingPort.Item.Submarine.Info.IsOutpost && !dockingPort.Item.Submarine.Info.IsBeacon)
{
continue;
}
//don't show the docking ports of the opposing team on the sonar
if (item.Submarine != null &&
item.Submarine != GameMain.NetworkMember?.RespawnManager?.RespawnShuttle &&
dockingPort.Item.Submarine != GameMain.NetworkMember?.RespawnManager?.RespawnShuttle &&
dockingPort.Item.Submarine.Info.Type != SubmarineType.Outpost)
!dockingPort.Item.Submarine.Info.IsOutpost &&
!dockingPort.Item.Submarine.Info.IsBeacon)
{
// specifically checking for friendlyNPC seems more logical here
if (dockingPort.Item.Submarine.TeamID != item.Submarine.TeamID && dockingPort.Item.Submarine.TeamID != CharacterTeamType.FriendlyNPC) { continue; }
@@ -1348,6 +1358,38 @@ namespace Barotrauma.Items.Components
}
}
public void RegisterExplosion(Explosion explosion, Vector2 worldPosition)
{
if (Character.Controlled?.SelectedItem != item) { return; }
if (explosion.Attack.StructureDamage <= 0 && explosion.Attack.ItemDamage <= 0 && explosion.EmpStrength <= 0) { return; }
Vector2 transducerCenter = GetTransducerPos();
if (Vector2.DistanceSquared(worldPosition, transducerCenter) > range * range) { return; }
int blipCount = MathHelper.Clamp((int)(explosion.Attack.Range / 100.0f), 0, 50);
for (int i = 0; i < blipCount; i++)
{
sonarBlips.Add(new SonarBlip(
worldPosition + Rand.Vector(Rand.Range(0.0f, explosion.Attack.Range)),
1.0f,
Rand.Range(0.5f, 1.0f),
BlipType.Disruption));
}
if (explosion.EmpStrength > 0.0f)
{
int empBlipCount = MathHelper.Clamp((int)(blipCount * explosion.EmpStrength), 10, 50);
for (int i = 0; i < empBlipCount; i++)
{
Vector2 dir = Rand.Vector(1.0f);
var longRangeBlip = new SonarBlip(worldPosition, Rand.Range(1.9f, 2.1f), Rand.Range(1.0f, 1.5f), BlipType.LongRange)
{
Velocity = dir * MathUtils.Round(Rand.Range(4000.0f, 6000.0f), 1000.0f),
Rotation = (float)Math.Atan2(-dir.Y, dir.X)
};
longRangeBlip.Size.Y *= 4.0f;
sonarBlips.Add(longRangeBlip);
}
}
}
private void Ping(Vector2 pingSource, Vector2 transducerPos, float pingRadius, float prevPingRadius, float displayScale, float range, bool passive,
float pingStrength = 1.0f, AITarget needsToBeInSector = null)
{
@@ -1392,6 +1434,16 @@ namespace Barotrauma.Items.Components
if (connectedSubs.Contains(submarine)) { continue; }
}
//display the actual walls if the ping source is inside the sub (but not inside a hull, that's handled above)
//only relevant in the end levels or maybe custom subs with some kind of non-hulled parts
Rectangle worldBorders = submarine.GetDockedBorders();
worldBorders.Location += submarine.WorldPosition.ToPoint();
if (Submarine.RectContains(worldBorders, pingSource))
{
CreateBlipsForSubmarineWalls(submarine, pingSource, transducerPos, pingRadius, prevPingRadius, range, passive);
continue;
}
for (int i = 0; i < submarine.HullVertices.Count; i++)
{
Vector2 start = ConvertUnits.ToDisplayUnits(submarine.HullVertices[i]);
@@ -1608,6 +1660,40 @@ namespace Barotrauma.Items.Components
}
}
private void CreateBlipsForSubmarineWalls(Submarine sub, Vector2 pingSource, Vector2 transducerPos, float pingRadius, float prevPingRadius, float range, bool passive)
{
foreach (Structure structure in Structure.WallList)
{
if (structure.Submarine != sub) { continue; }
CreateBlips(structure.IsHorizontal, structure.WorldPosition, structure.WorldRect);
}
foreach (var door in Door.DoorList)
{
if (door.Item.Submarine != sub || door.IsOpen) { continue; }
CreateBlips(door.IsHorizontal, door.Item.WorldPosition, door.Item.WorldRect, BlipType.Door);
}
void CreateBlips(bool isHorizontal, Vector2 worldPos, Rectangle worldRect, BlipType blipType = BlipType.Default)
{
Vector2 point1, point2;
if (isHorizontal)
{
point1 = new Vector2(worldRect.X, worldPos.Y);
point2 = new Vector2(worldRect.Right, worldPos.Y);
}
else
{
point1 = new Vector2(worldPos.X, worldRect.Y);
point2 = new Vector2(worldPos.X, worldRect.Y - worldRect.Height);
}
CreateBlipsForLine(
point1,
point2,
pingSource, transducerPos,
pingRadius, prevPingRadius, 50.0f, 5.0f, range, 2.0f, passive, blipType);
}
}
private bool CheckBlipVisibility(SonarBlip blip, Vector2 transducerPos)
{
Vector2 pos = (blip.Position - transducerPos) * displayScale * zoom;
@@ -178,8 +178,9 @@ namespace Barotrauma.Items.Components
var autoPilotControls = new GUIFrame(new RectTransform(new Vector2(0.75f, 0.62f), paddedControlContainer.RectTransform, Anchor.BottomCenter), "OutlineFrame");
var paddedAutoPilotControls = new GUIFrame(new RectTransform(new Vector2(0.92f, 0.88f), autoPilotControls.RectTransform, Anchor.Center), style: null);
int textLimit = (int)(paddedAutoPilotControls.Rect.Width * 0.75f);
maintainPosTickBox = new GUITickBox(new RectTransform(new Vector2(1, 0.333f), paddedAutoPilotControls.RectTransform, Anchor.TopCenter),
TextManager.Get("SteeringMaintainPos"), font: GUIStyle.SmallFont, style: "GUIRadioButton")
ToolBox.LimitString(TextManager.Get("SteeringMaintainPos"), GUIStyle.SmallFont, textLimit), font: GUIStyle.SmallFont, style: "GUIRadioButton")
{
UserData = UIHighlightAction.ElementId.MaintainPosTickBox,
Enabled = autoPilot,
@@ -214,7 +215,6 @@ namespace Barotrauma.Items.Components
return true;
}
};
int textLimit = (int)(paddedAutoPilotControls.Rect.Width * 0.75f);
levelStartTickBox = new GUITickBox(new RectTransform(new Vector2(1, 0.333f), paddedAutoPilotControls.RectTransform, Anchor.Center),
GameMain.GameSession?.StartLocation == null ? "" : ToolBox.LimitString(GameMain.GameSession.StartLocation.Name, GUIStyle.SmallFont, textLimit),
font: GUIStyle.SmallFont, style: "GUIRadioButton")
@@ -340,6 +340,10 @@ namespace Barotrauma.Items.Components
centerText = $"({TextManager.Get("Meter")})";
rightTextGetter = () =>
{
if (Level.Loaded is { IsEndBiome: true })
{
return Timing.TotalTime % 5.0f < 0.5f ? Rand.Range(-9000, 9000).ToString() : "ERROR";
}
float realWorldDepth = controlledSub == null ? -1000.0f : controlledSub.RealWorldDepth;
return ((int)realWorldDepth).ToString();
};
@@ -20,6 +20,7 @@ namespace Barotrauma.Items.Components
User = Entity.FindEntityByID(userId) as Character;
Vector2 simPosition = new Vector2(msg.ReadSingle(), msg.ReadSingle());
float rotation = msg.ReadSingle();
SpreadCounter = msg.ReadByte();
if (User != null)
{
Shoot(User, simPosition, simPosition, rotation, ignoredBodies: User.AnimController.Limbs.Where(l => !l.IsSevered).Select(l => l.body.FarseerBody).ToList(), createNetworkEvent: false);
@@ -262,9 +262,11 @@ namespace Barotrauma.Items.Components
}
}
float conditionPercentage = item.Condition / (item.MaxCondition / item.MaxRepairConditionMultiplier) * 100f;
for (int i = 0; i < particleEmitters.Count; i++)
{
if ((item.ConditionPercentage >= particleEmitterConditionRanges[i].X && item.ConditionPercentage <= particleEmitterConditionRanges[i].Y) || FakeBrokenTimer > 0.0f)
if ((conditionPercentage >= particleEmitterConditionRanges[i].X && conditionPercentage <= particleEmitterConditionRanges[i].Y) || FakeBrokenTimer > 0.0f)
{
particleEmitters[i].Emit(deltaTime, item.WorldPosition, item.CurrentHull);
}
@@ -436,12 +438,16 @@ namespace Barotrauma.Items.Components
ushort currentFixerID = msg.ReadUInt16();
currentFixerAction = (FixActions)msg.ReadRangedInteger(0, 2);
CurrentFixer = currentFixerID != 0 ? Entity.FindEntityByID(currentFixerID) as Character : null;
item.MaxRepairConditionMultiplier = GetMaxRepairConditionMultiplier(CurrentFixer);
if (CurrentFixer == null)
if (CurrentFixer is null)
{
qteTimer = QteDuration;
qteCooldown = 0.0f;
}
else
{
item.MaxRepairConditionMultiplier = GetMaxRepairConditionMultiplier(CurrentFixer);
}
}
public void ClientEventWrite(IWriteMessage msg, NetEntityEvent.IData extraData = null)
@@ -108,6 +108,7 @@ namespace Barotrauma.Items.Components
{
startPos += new Vector2((float)Math.Cos(turret.Rotation), (float)Math.Sin(turret.Rotation)) * turret.BarrelSprite.size.Y * turret.BarrelSprite.RelativeOrigin.Y * item.Scale * 0.9f;
}
startPos -= turret.GetRecoilOffset();
}
else if (weapon != null)
{
@@ -259,7 +259,7 @@ namespace Barotrauma.Items.Components
{
bool alreadyConnected = DraggingConnected.IsConnectedTo(panel.Item);
DraggingConnected.RemoveConnection(panel.Item);
if (DraggingConnected.Connect(this, !alreadyConnected, true))
if (DraggingConnected.TryConnect(this, !alreadyConnected, true))
{
var otherConnection = DraggingConnected.OtherConnection(this);
ConnectWire(DraggingConnected);
@@ -110,8 +110,8 @@ namespace Barotrauma.Items.Components
if (HighlightedWire != null)
{
HighlightedWire.Item.IsHighlighted = true;
if (HighlightedWire.Connections[0] != null && HighlightedWire.Connections[0].Item != null) HighlightedWire.Connections[0].Item.IsHighlighted = true;
if (HighlightedWire.Connections[1] != null && HighlightedWire.Connections[1].Item != null) HighlightedWire.Connections[1].Item.IsHighlighted = true;
if (HighlightedWire.Connections[0] != null && HighlightedWire.Connections[0].Item != null) { HighlightedWire.Connections[0].Item.IsHighlighted = true; }
if (HighlightedWire.Connections[1] != null && HighlightedWire.Connections[1].Item != null) { HighlightedWire.Connections[1].Item.IsHighlighted = true; }
}
}
@@ -225,7 +225,7 @@ namespace Barotrauma.Items.Components
foreach (var wire in newWires.Where(w => !connection.Wires.Contains(w)).ToArray())
{
connection.ConnectWire(wire);
wire.Connect(connection, false);
wire.TryConnect(connection, false);
}
}
@@ -12,6 +12,8 @@ namespace Barotrauma.Items.Components
private readonly List<GUIComponent> uiElements = new List<GUIComponent>();
private GUILayoutGroup uiElementContainer;
private bool readingNetworkEvent;
private Point ElementMaxSize => new Point(uiElementContainer.Rect.Width, (int)(65 * GUI.yScale));
public override bool RecreateGUIOnResolutionChange => true;
@@ -100,7 +102,7 @@ namespace Barotrauma.Items.Components
{
ValueChanged(ni.UserData as CustomInterfaceElement, ni.FloatValue);
}
else
else if (!readingNetworkEvent)
{
item.CreateClientEvent(this);
}
@@ -126,7 +128,7 @@ namespace Barotrauma.Items.Components
{
ValueChanged(ni.UserData as CustomInterfaceElement, ni.IntValue);
}
else
else if (!readingNetworkEvent)
{
item.CreateClientEvent(this);
}
@@ -161,7 +163,7 @@ namespace Barotrauma.Items.Components
{
TickBoxToggled(tBox.UserData as CustomInterfaceElement, tBox.Selected);
}
else
else if (!readingNetworkEvent)
{
item.CreateClientEvent(this);
}
@@ -181,12 +183,12 @@ namespace Barotrauma.Items.Components
};
btn.OnClicked += (_, userdata) =>
{
CustomInterfaceElement btnElement = userdata as CustomInterfaceElement;;
CustomInterfaceElement btnElement = userdata as CustomInterfaceElement;
if (GameMain.Client == null)
{
ButtonClicked(btnElement);
}
else
else if (!readingNetworkEvent)
{
item.CreateClientEvent(this, new EventData(btnElement));
}
@@ -297,9 +299,10 @@ namespace Barotrauma.Items.Components
LocalizedString CreateLabelText(int elementIndex)
{
return string.IsNullOrWhiteSpace(customInterfaceElementList[elementIndex].Label) ?
var label = customInterfaceElementList[elementIndex].Label;
return string.IsNullOrWhiteSpace(label) ?
TextManager.GetWithVariable("connection.signaloutx", "[num]", (elementIndex + 1).ToString()) :
customInterfaceElementList[elementIndex].Label;
TextManager.Get(label).Fallback(label);
}
uiElementContainer.Recalculate();
@@ -386,45 +389,53 @@ namespace Barotrauma.Items.Components
public void ClientEventRead(IReadMessage msg, float sendingTime)
{
for (int i = 0; i < customInterfaceElementList.Count; i++)
readingNetworkEvent = true;
try
{
var element = customInterfaceElementList[i];
if (element.HasPropertyName)
for (int i = 0; i < customInterfaceElementList.Count; i++)
{
string newValue = msg.ReadString();
if (!element.IsNumberInput)
var element = customInterfaceElementList[i];
if (element.HasPropertyName)
{
TextChanged(element, newValue);
string newValue = msg.ReadString();
if (!element.IsNumberInput)
{
TextChanged(element, newValue);
}
else
{
switch (element.NumberType)
{
case NumberType.Int when int.TryParse(newValue, out int value):
ValueChanged(element, value);
break;
case NumberType.Float when TryParseFloatInvariantCulture(newValue, out float value):
ValueChanged(element, value);
break;
}
}
}
else
{
switch (element.NumberType)
bool elementState = msg.ReadBoolean();
if (element.ContinuousSignal)
{
case NumberType.Int when int.TryParse(newValue, out int value):
ValueChanged(element, value);
break;
case NumberType.Float when TryParseFloatInvariantCulture(newValue, out float value):
ValueChanged(element, value);
break;
((GUITickBox)uiElements[i]).Selected = elementState;
TickBoxToggled(element, elementState);
}
else if (elementState)
{
ButtonClicked(element);
}
}
}
else
{
bool elementState = msg.ReadBoolean();
if (element.ContinuousSignal)
{
((GUITickBox)uiElements[i]).Selected = elementState;
TickBoxToggled(element, elementState);
}
else if (elementState)
{
ButtonClicked(element);
}
}
}
UpdateSignalsProjSpecific();
UpdateSignalsProjSpecific();
}
finally
{
readingNetworkEvent = false;
}
}
}
}
@@ -1,4 +1,5 @@
using Barotrauma.Networking;
using Barotrauma.Extensions;
using Barotrauma.Networking;
using Microsoft.Xna.Framework;
using System.Linq;
using System.Xml.Linq;
@@ -24,7 +25,9 @@ namespace Barotrauma.Items.Components
partial void InitProjSpecific(XElement element)
{
var layoutGroup = new GUILayoutGroup(new RectTransform(GuiFrame.Rect.Size - GUIStyle.ItemFrameMargin, GuiFrame.RectTransform, Anchor.Center) { AbsoluteOffset = GUIStyle.ItemFrameOffset })
float marginMultiplier = element.GetAttributeFloat("marginmultiplier", 1.0f);
var layoutGroup = new GUILayoutGroup(new RectTransform(GuiFrame.Rect.Size - GUIStyle.ItemFrameMargin.Multiply(marginMultiplier), GuiFrame.RectTransform, Anchor.Center) { AbsoluteOffset = GUIStyle.ItemFrameOffset.Multiply(marginMultiplier) })
{
ChildAnchor = Anchor.TopCenter,
RelativeSpacing = 0.02f,
@@ -33,31 +36,34 @@ namespace Barotrauma.Items.Components
historyBox = new GUIListBox(new RectTransform(new Vector2(1, .9f), layoutGroup.RectTransform), style: null)
{
AutoHideScrollBar = false
AutoHideScrollBar = this.AutoHideScrollbar
};
CreateFillerBlock();
new GUIFrame(new RectTransform(new Vector2(0.9f, 0.01f), layoutGroup.RectTransform), style: "HorizontalLine");
inputBox = new GUITextBox(new RectTransform(new Vector2(1, .1f), layoutGroup.RectTransform), textColor: TextColor)
if (!Readonly)
{
MaxTextLength = MaxMessageLength,
OverflowClip = true,
OnEnterPressed = (GUITextBox textBox, string text) =>
CreateFillerBlock();
new GUIFrame(new RectTransform(new Vector2(0.9f, 0.01f), layoutGroup.RectTransform), style: "HorizontalLine");
inputBox = new GUITextBox(new RectTransform(new Vector2(1, .1f), layoutGroup.RectTransform), textColor: TextColor)
{
if (GameMain.NetworkMember == null)
MaxTextLength = MaxMessageLength,
OverflowClip = true,
OnEnterPressed = (GUITextBox textBox, string text) =>
{
SendOutput(text);
if (GameMain.NetworkMember == null)
{
SendOutput(text);
}
else
{
item.CreateClientEvent(this, new ClientEventData(text));
}
textBox.Text = string.Empty;
return true;
}
else
{
item.CreateClientEvent(this, new ClientEventData(text));
}
textBox.Text = string.Empty;
return true;
}
};
};
}
layoutGroup.Recalculate();
}
@@ -101,7 +107,7 @@ namespace Barotrauma.Items.Components
GUITextBlock newBlock = new GUITextBlock(
new RectTransform(new Vector2(1, 0), historyBox.Content.RectTransform, anchor: Anchor.TopCenter),
"> " + input,
LineStartSymbol + TextManager.Get(input).Fallback(input),
textColor: color, wrap: true, font: UseMonospaceFont ? GUIStyle.MonospacedFont : GUIStyle.Font)
{
CanBeFocused = false
@@ -123,7 +129,10 @@ namespace Barotrauma.Items.Components
historyBox.RecalculateChildren();
historyBox.UpdateScrollBarSize();
historyBox.ScrollBar.BarScrollValue = 1;
if (AutoScrollToBottom)
{
historyBox.ScrollBar.BarScrollValue = 1;
}
}
public override bool Select(Character character)
@@ -138,7 +147,7 @@ namespace Barotrauma.Items.Components
public override void AddToGUIUpdateList(int order = 0)
{
base.AddToGUIUpdateList(order: order);
if (shouldSelectInputBox)
if (shouldSelectInputBox && !Readonly)
{
inputBox.Select();
shouldSelectInputBox = false;
@@ -212,7 +212,7 @@ namespace Barotrauma.Items.Components
Sprite pingCircle = GUIStyle.UIThermalGlow.Value.Sprite;
foreach (Limb limb in c.AnimController.Limbs)
{
if (limb.Mass < 1.0f) { continue; }
if (limb.Mass < 0.5f && limb != c.AnimController.MainLimb) { continue; }
float noise1 = PerlinNoise.GetPerlin((thermalEffectState + limb.Params.ID + c.ID) * 0.01f, (thermalEffectState + limb.Params.ID + c.ID) * 0.02f);
float noise2 = PerlinNoise.GetPerlin((thermalEffectState + limb.Params.ID + c.ID) * 0.01f, (thermalEffectState + limb.Params.ID + c.ID) * 0.008f);
Vector2 spriteScale = ConvertUnits.ToDisplayUnits(limb.body.GetSize()) / pingCircle.size * (noise1 * 0.5f + 2f);
@@ -302,7 +302,18 @@ namespace Barotrauma.Items.Components
Dictionary<AfflictionPrefab, float> combinedAfflictionStrengths = new Dictionary<AfflictionPrefab, float>();
foreach (Affliction affliction in allAfflictions)
{
if (affliction.Strength < affliction.Prefab.ShowInHealthScannerThreshold || affliction.Strength <= 0.0f) { continue; }
if (affliction.Strength <= 0f) { continue; }
if (affliction.Strength < affliction.Prefab.ShowInHealthScannerThreshold)
{
if (target.IsHuman || target.IsOnPlayerTeam || (affliction.Prefab.AfflictionType != AfflictionPrefab.PoisonType && affliction.Prefab.AfflictionType != AfflictionPrefab.ParalysisType))
{
// Always show the poisons on monsters, because poisoning bigger monsters require multiple doses.
// The solution is hacky, but didn't want to introduce an extra property for this.
// We also want to have a relatively high thershold for showing the poisons on the scanner on humans, so that it's not instantly clear that a target is poisoned and especially not which poison was used.
// Paralysis is treated like a poison but isn't technically a poison, so that we can have multiple afflictions that still are treated the same.
continue;
}
}
if (combinedAfflictionStrengths.ContainsKey(affliction.Prefab))
{
combinedAfflictionStrengths[affliction.Prefab] += affliction.Strength;
@@ -333,15 +333,9 @@ namespace Barotrauma.Items.Components
crosshairPointerPos = PlayerInput.MousePosition;
}
public void Draw(SpriteBatch spriteBatch, bool editing = false, float itemDepth = -1)
{
if (!MathUtils.NearlyEqual(item.Rotation, prevBaseRotation) || !MathUtils.NearlyEqual(item.Scale, prevScale))
{
UpdateTransformedBarrelPos();
}
Vector2 drawPos = GetDrawPos();
public Vector2 GetRecoilOffset()
{
float recoilOffset = 0.0f;
if (Math.Abs(RecoilDistance) > 0.0f && recoilTimer > 0.0f)
{
@@ -362,6 +356,17 @@ namespace Barotrauma.Items.Components
recoilOffset = RecoilDistance;
}
}
return new Vector2((float)Math.Cos(rotation), (float)Math.Sin(rotation)) * recoilOffset;
}
public void Draw(SpriteBatch spriteBatch, bool editing = false, float itemDepth = -1)
{
if (!MathUtils.NearlyEqual(item.Rotation, prevBaseRotation) || !MathUtils.NearlyEqual(item.Scale, prevScale))
{
UpdateTransformedBarrelPos();
}
Vector2 drawPos = GetDrawPos();
railSprite?.Draw(spriteBatch,
drawPos,
@@ -370,7 +375,7 @@ namespace Barotrauma.Items.Components
SpriteEffects.None, item.SpriteDepth + (railSprite.Depth - item.Sprite.Depth));
barrelSprite?.Draw(spriteBatch,
drawPos - new Vector2((float)Math.Cos(rotation), (float)Math.Sin(rotation)) * recoilOffset * item.Scale,
drawPos - GetRecoilOffset() * item.Scale,
item.SpriteColor,
rotation + MathHelper.PiOver2, item.Scale,
SpriteEffects.None, item.SpriteDepth + (barrelSprite.Depth - item.Sprite.Depth));