v1.6.17.0 (Unto the Breach update)

This commit is contained in:
Regalis11
2024-10-22 17:29:04 +03:00
parent e74b3cdb17
commit 6e6c17e100
417 changed files with 17166 additions and 5870 deletions
@@ -48,25 +48,46 @@ namespace Barotrauma.Items.Components
description += '\n' + containedDescription;
}
}
if (GameMain.DevMode && Tainted && selectedTaintedEffect != null)
{
description = $"{description}\n{selectedTaintedEffect.Name}: {selectedTaintedEffect.GetDescription(0f, AfflictionPrefab.Description.TargetType.OtherCharacter)}";
}
}
public void ModifyDeconstructInfo(Deconstructor deconstructor, ref LocalizedString buttonText, ref LocalizedString infoText)
{
if (deconstructor.InputContainer.Inventory.AllItems.Count() == 2)
{
var otherGeneticMaterial =
deconstructor.InputContainer.Inventory.AllItems.FirstOrDefault(it => it != item && it.Prefab == item.Prefab)?.GetComponent<GeneticMaterial>();
var otherItem = deconstructor.InputContainer.Inventory.AllItems.FirstOrDefault(it => it != item);
if (otherItem == null)
{
return;
}
var otherGeneticMaterial = otherItem.GetComponent<GeneticMaterial>();
if (otherGeneticMaterial == null)
{
buttonText = TextManager.Get("researchstation.combine");
infoText = TextManager.Get("researchstation.combine.infotext");
return;
}
else
var combineRefineResult = GetCombineRefineResult(otherGeneticMaterial);
if (combineRefineResult == CombineResult.None)
{
infoText = TextManager.Get("researchstation.novalidcombination");
}
else if (combineRefineResult == CombineResult.Refined)
{
buttonText = TextManager.Get("researchstation.refine");
int taintedProbability = (int)(GetTaintedProbabilityOnRefine(otherGeneticMaterial, Character.Controlled) * 100);
infoText = TextManager.GetWithVariable("researchstation.refine.infotext", "[taintedprobability]", taintedProbability.ToString());
}
else
{
buttonText = TextManager.Get("researchstation.combine");
infoText = TextManager.Get("researchstation.combine.infotext");
}
}
}
@@ -177,6 +177,8 @@ namespace Barotrauma.Items.Components
//don't draw the crosshair if the item is in some other type of equip slot than hands (e.g. assault rifle in the bag slot)
if (!character.HeldItems.Contains(item)) { return; }
base.DrawHUD(spriteBatch, character);
GUI.HideCursor = (crosshairSprite != null || crosshairPointerSprite != null) &&
GUI.MouseOn == null && !Inventory.IsMouseOnInventory && !GameMain.Instance.Paused;
@@ -216,6 +216,7 @@ namespace Barotrauma.Items.Components
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
{
if (character == null || !character.IsKeyDown(InputType.Aim)) { return; }
base.DrawHUD(spriteBatch, character);
GUI.HideCursor = targetSections.Count > 0;
}
@@ -150,6 +150,17 @@ namespace Barotrauma.Items.Components
public GUIFrame GuiFrame { get; set; }
/// <summary>
/// Overlay (just a non-interactable sprite) drawn when the item is selected, equipped or focused to via Controllers (e.g. when operating a turret via a periscope or a camera via a monitor).
/// </summary>
public Sprite HUDOverlay { get; set; }
public float HUDOverlayAnimSpeed
{
get;
set;
}
private GUIDragHandle guiFrameDragHandle;
private bool guiFrameUpdatePending;
@@ -161,6 +172,13 @@ namespace Barotrauma.Items.Components
set;
}
[Serialize(true, IsPropertySaveable.No)]
public bool CloseByClickingOutsideGUIFrame
{
get;
set;
}
private ItemComponent linkToUIComponent;
[Serialize("", IsPropertySaveable.No)]
public string LinkUIToComponent
@@ -261,7 +279,7 @@ namespace Barotrauma.Items.Components
if (GameMain.Client?.MidRoundSyncing ?? false) { return; }
//above the top boundary of the level (in an inactive respawn shuttle?)
if (item.Submarine != null && Level.Loaded != null && item.Submarine.WorldPosition.Y > Level.Loaded.Size.Y)
if (item.Submarine != null && item.Submarine.IsAboveLevel)
{
return;
}
@@ -340,7 +358,7 @@ namespace Barotrauma.Items.Components
}
else if (soundSelectionMode == SoundSelectionMode.Manual)
{
index = Math.Clamp(ManuallySelectedSound, 0, matchingSounds.Count);
index = Math.Clamp(ManuallySelectedSound, 0, matchingSounds.Count - 1);
}
else
{
@@ -416,12 +434,23 @@ namespace Barotrauma.Items.Components
if (sound == null) { return 0.0f; }
if (sound.VolumeProperty == "") { return sound.VolumeMultiplier; }
if (SerializableProperties.TryGetValue(sound.VolumeProperty, out SerializableProperty property))
SerializableProperty property = null;
ISerializableEntity targetEntity = null;
if (SerializableProperties.TryGetValue(sound.VolumeProperty, out property))
{
targetEntity = this;
}
else if (Item.SerializableProperties.TryGetValue(sound.VolumeProperty, out property))
{
targetEntity = Item;
}
if (property != null)
{
float newVolume;
try
{
newVolume = property.GetFloatValue(this);
newVolume = property.GetFloatValue(targetEntity);
}
catch
{
@@ -470,7 +499,24 @@ namespace Barotrauma.Items.Components
return linkToUIComponent;
}
public virtual void DrawHUD(SpriteBatch spriteBatch, Character character) { }
public virtual void DrawHUD(SpriteBatch spriteBatch, Character character)
{
if (HUDOverlay != null)
{
Vector2 screenSize = new Vector2(GameMain.GraphicsWidth, GameMain.GraphicsHeight);
if (HUDOverlay is SpriteSheet spriteSheet)
{
spriteSheet.Draw(spriteBatch,
spriteIndex: (int)(Math.Floor(Timing.TotalTimeUnpaused * HUDOverlayAnimSpeed) % spriteSheet.FrameCount),
pos: screenSize / 2, color: Color.White, origin: HUDOverlay.Origin, rotate: 0, scale: screenSize / spriteSheet.FrameSize.ToVector2());
}
else
{
HUDOverlay.Draw(spriteBatch,
pos: screenSize / 2, color: Color.White, origin: HUDOverlay.Origin, rotate: 0, scale: screenSize / HUDOverlay.size);
}
}
}
public virtual void AddToGUIUpdateList(int order = 0)
{
@@ -513,6 +559,13 @@ namespace Barotrauma.Items.Components
GuiFrameSource = subElement;
ReloadGuiFrame();
break;
case "hudoverlayanimated":
HUDOverlay = new SpriteSheet(subElement);
HUDOverlayAnimSpeed = subElement.GetAttributeFloat("animspeed", 1.0f);
break;
case "hudoverlay":
HUDOverlay = new Sprite(subElement);
break;
case "alternativelayout":
AlternativeLayout = GUILayoutSettings.Load(subElement);
break;
@@ -458,54 +458,14 @@ namespace Barotrauma.Items.Components
public void DrawContainedItems(SpriteBatch spriteBatch, float itemDepth, Color? overrideColor = null)
{
Vector2 transformedItemPos = ItemPos * item.Scale;
Vector2 transformedItemInterval = ItemInterval * item.Scale;
Vector2 transformedItemIntervalHorizontal = new Vector2(transformedItemInterval.X, 0.0f);
Vector2 transformedItemIntervalVertical = new Vector2(0.0f, transformedItemInterval.Y);
var rootBody = item.RootContainer?.body ?? item.body;
if (item.body == null)
{
if (item.FlippedX)
{
transformedItemPos.X = -transformedItemPos.X;
transformedItemPos.X += item.Rect.Width;
transformedItemInterval.X = -transformedItemInterval.X;
transformedItemIntervalHorizontal.X = -transformedItemIntervalHorizontal.X;
}
if (item.FlippedY)
{
transformedItemPos.Y = -transformedItemPos.Y;
transformedItemPos.Y -= item.Rect.Height;
transformedItemInterval.Y = -transformedItemInterval.Y;
transformedItemIntervalVertical.Y = -transformedItemIntervalVertical.Y;
}
transformedItemPos += new Vector2(item.Rect.X, item.Rect.Y);
if (item.Submarine != null) { transformedItemPos += item.Submarine.DrawPosition; }
if (Math.Abs(item.RotationRad) > 0.01f)
{
Matrix transform = Matrix.CreateRotationZ(-item.RotationRad);
transformedItemPos = Vector2.Transform(transformedItemPos - item.DrawPosition, transform) + item.DrawPosition;
transformedItemInterval = Vector2.Transform(transformedItemInterval, transform);
transformedItemIntervalHorizontal = Vector2.Transform(transformedItemIntervalHorizontal, transform);
transformedItemIntervalVertical = Vector2.Transform(transformedItemIntervalVertical, transform);
}
}
else
{
Matrix transform = Matrix.CreateRotationZ(item.body.DrawRotation);
if (item.body.Dir == -1.0f)
{
transformedItemPos.X = -transformedItemPos.X;
transformedItemInterval.X = -transformedItemInterval.X;
transformedItemIntervalHorizontal.X = -transformedItemIntervalHorizontal.X;
}
transformedItemPos = Vector2.Transform(transformedItemPos, transform);
transformedItemInterval = Vector2.Transform(transformedItemInterval, transform);
transformedItemIntervalHorizontal = Vector2.Transform(transformedItemIntervalHorizontal, transform);
transformedItemPos += item.body.DrawPosition;
}
Vector2 transformedItemPos = GetContainedPosition(
drawPosition: true,
out Vector2 transformedItemIntervalHorizontal,
out Vector2 transformedItemIntervalVertical,
out bool flippedX,
out bool flippedY);
Vector2 currentItemPos = transformedItemPos;
@@ -525,19 +485,19 @@ namespace Barotrauma.Items.Components
if (item.body != null)
{
Matrix transform = Matrix.CreateRotationZ(item.body.DrawRotation);
pos.X *= item.body.Dir;
pos.X *= rootBody.Dir;
itemPos = Vector2.Transform(pos, transform) + item.body.DrawPosition;
}
else
{
itemPos = pos;
// This code is aped based on above. Not tested.
if (item.FlippedX)
if (flippedX)
{
itemPos.X = -itemPos.X;
itemPos.X += item.Rect.Width;
}
if (item.FlippedY)
if (flippedY)
{
itemPos.Y = -itemPos.Y;
itemPos.Y -= item.Rect.Height;
@@ -555,15 +515,15 @@ namespace Barotrauma.Items.Components
}
}
if (AutoInteractWithContained)
if (CanAutoInteractWithContained(contained.Item) && Screen.Selected is not { IsEditor: true })
{
contained.Item.IsHighlighted = item.IsHighlighted;
item.IsHighlighted = false;
}
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; }
if (flippedX) { origin.X = contained.Item.Sprite.SourceRect.Width - origin.X; }
if (flippedY) { origin.Y = contained.Item.Sprite.SourceRect.Height - origin.Y; }
float containedSpriteDepth = ContainedSpriteDepth < 0.0f ? contained.Item.Sprite.Depth : ContainedSpriteDepth;
if (i < containedSpriteDepths.Length)
@@ -578,12 +538,13 @@ namespace Barotrauma.Items.Components
{
spriteRotation = contained.Rotation;
}
bool flipX = (item.body != null && item.body.Dir == -1) || item.FlippedX;
bool flipX = rootBody is { Dir: -1 } || flippedX;
if (flipX)
{
spriteEffects |= MathUtils.NearlyEqual(spriteRotation % 180, 90.0f) ? SpriteEffects.FlipVertically : SpriteEffects.FlipHorizontally;
}
bool flipY = item.FlippedY;
bool flipY = flippedY;
if (flipY)
{
spriteEffects |= MathUtils.NearlyEqual(spriteRotation % 180, 90.0f) ? SpriteEffects.FlipHorizontally : SpriteEffects.FlipVertically;
@@ -598,7 +559,8 @@ namespace Barotrauma.Items.Components
contained.Item.Scale,
spriteEffects,
depth: containedSpriteDepth);
contained.Item.DrawDecorativeSprites(spriteBatch, itemPos, flipX,flipY, (contained.Item.body == null ? 0.0f : contained.Item.body.DrawRotation),
contained.Item.DrawDecorativeSprites(spriteBatch, itemPos, flipX, flipY, (contained.Item.body == null ? 0.0f : contained.Item.body.DrawRotation),
containedSpriteDepth, overrideColor);
foreach (ItemContainer ic in contained.Item.GetComponents<ItemContainer>())
@@ -620,7 +582,7 @@ namespace Barotrauma.Items.Components
}
else
{
currentItemPos += transformedItemInterval;
currentItemPos += transformedItemIntervalHorizontal + transformedItemIntervalVertical;
}
}
}
@@ -41,7 +41,7 @@ namespace Barotrauma.Items.Components
}
private string text;
[Serialize("", IsPropertySaveable.Yes, translationTextTag: "Label.", description: "The text displayed in the label.", alwaysUseInstanceValues: true), Editable(100)]
[Serialize("", IsPropertySaveable.Yes, translationTextTag: "Label.", description: "The text displayed in the label.", alwaysUseInstanceValues: true), Editable(MaxLength = 100)]
public string Text
{
get { return text; }
@@ -11,6 +11,7 @@ namespace Barotrauma.Items.Components
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
{
base.DrawHUD(spriteBatch, character);
if (focusTarget != null && character.ViewTarget == focusTarget)
{
foreach (ItemComponent ic in focusTarget.Components)
@@ -23,6 +24,15 @@ namespace Barotrauma.Items.Components
}
}
public override void AddToGUIUpdateList(int order = 0)
{
base.AddToGUIUpdateList(order);
if (focusTarget != null && Character.Controlled.ViewTarget == focusTarget)
{
focusTarget.AddToGUIUpdateList(order);
}
}
partial void HideHUDs(bool value)
{
if (isHUDsHidden == value) { return; }
@@ -154,12 +154,14 @@ namespace Barotrauma.Items.Components
{
infoArea.Text = TextManager.Get(InfoText).Fallback(InfoText);
}
if (IsActive)
{
activateButton.Text = TextManager.Get("DeconstructorCancel");
infoArea.Text = string.Empty;
return;
}
bool outputsFound = false;
foreach (var (inputItem, deconstructItem) in GetAvailableOutputs(checkRequiredOtherItems: true))
{
@@ -174,27 +176,34 @@ namespace Barotrauma.Items.Components
}
inputItem.GetComponent<GeneticMaterial>()?.ModifyDeconstructInfo(this, ref buttonText, ref infoText);
activateButton.Text = buttonText;
if (infoArea != null)
{
infoArea.Text = infoText;
}
infoArea.Text = infoText;
return;
}
}
LocalizedString activateButtonText = TextManager.Get(ActivateButtonText);
activateButton.Enabled = outputsFound || !InputContainer.Inventory.IsEmpty();
activateButton.Text = activateButtonText;
//no valid outputs found: check if we're missing some required items from the input slots and display a message about it if possible
if (!outputsFound && infoArea != null)
{
foreach (var (inputItem, deconstructItem) in GetAvailableOutputs(checkRequiredOtherItems: false))
{
LocalizedString infoText = string.Empty;
if (deconstructItem.RequiredOtherItem.Any() && !string.IsNullOrEmpty(deconstructItem.InfoTextOnOtherItemMissing))
{
LocalizedString missingItemName = TextManager.Get("entityname." + deconstructItem.RequiredOtherItem.First());
infoArea.Text = TextManager.GetWithVariable(deconstructItem.InfoTextOnOtherItemMissing, "[itemname]", missingItemName);
infoText = TextManager.GetWithVariable(deconstructItem.InfoTextOnOtherItemMissing, "[itemname]", missingItemName);
}
inputItem.GetComponent<GeneticMaterial>()?.ModifyDeconstructInfo(this, ref activateButtonText, ref infoText);
activateButton.Text = activateButtonText;
infoArea.Text = infoText;
}
}
activateButton.Enabled = outputsFound || !InputContainer.Inventory.IsEmpty();
activateButton.Text = TextManager.Get(ActivateButtonText);
};
}
@@ -415,7 +424,7 @@ namespace Barotrauma.Items.Components
public override void UpdateHUDComponentSpecific(Character character, float deltaTime, Camera cam)
{
inSufficientPowerWarning.Visible = IsActive && !hasPower;
inSufficientPowerWarning.Visible = IsActive && !HasPower;
}
private bool OnActivateButtonClicked(GUIButton button, object obj)
@@ -10,45 +10,27 @@ using Microsoft.Xna.Framework.Input;
namespace Barotrauma.Items.Components
{
internal readonly struct MiniMapGUIComponent
internal readonly record struct MiniMapGUIComponent(GUIComponent RectComponent, GUIComponent BorderComponent)
{
public readonly GUIComponent RectComponent;
public readonly GUIComponent BorderComponent;
public MiniMapGUIComponent(GUIComponent rectComponent)
public MiniMapGUIComponent(GUIComponent rectComponent) : this(rectComponent, rectComponent)
{
RectComponent = rectComponent;
BorderComponent = rectComponent;
}
public MiniMapGUIComponent(GUIComponent frame, GUIComponent linkedHullComponent)
{
RectComponent = frame;
BorderComponent = linkedHullComponent;
}
public void Deconstruct(out GUIComponent component, out GUIComponent borderComponent)
{
component = RectComponent;
borderComponent = BorderComponent;
}
}
internal readonly struct MiniMapSprite
internal readonly record struct MiniMapSprite(Sprite? Sprite, Color Color)
{
public readonly Sprite? Sprite;
public readonly Color Color;
public MiniMapSprite(JobPrefab prefab)
public MiniMapSprite(JobPrefab prefab) : this(prefab.IconSmall, prefab.UIColor)
{
Sprite = prefab.IconSmall;
Color = prefab.UIColor;
}
public MiniMapSprite(Order order)
public MiniMapSprite(Order order) : this(order.SymbolSprite, order.Color)
{
Sprite = order.SymbolSprite;
Color = order.Color;
}
}
@@ -223,7 +205,27 @@ namespace Barotrauma.Items.Components
NoPowerColor = MiniMapBaseColor * 0.1f,
ElectricalBaseColor = GUIStyle.Orange,
NoPowerElectricalColor = ElectricalBaseColor * 0.1f;
// If this is portable, only allow displaying data in the player sub (not enemy subs, ruins, wrecks or other unknown places)
private bool IsPortableItemAllowed
{
get
{
if (IsUsableOutsidePlayerSub) { return true; }
if (item.Submarine == null) { return false; }
if (item.GetComponent<Pickable>() is not Pickable handheldItem) { return true; }
// This will effectively make sure wherever we are, it belongs to the player
return handheldItem.Picker?.TeamID == item.Submarine.TeamID;
}
}
[Serialize(false, IsPropertySaveable.No, description: "If this item is portable, should it be usable outside the player submarine?")]
public bool IsUsableOutsidePlayerSub
{
get;
set;
}
partial void InitProjSpecific()
{
hullDatas = new Dictionary<Hull, HullData>();
@@ -425,22 +427,25 @@ namespace Barotrauma.Items.Components
return false;
}
private bool VisibleOnItemFinder(Item it)
private bool VisibleOnItemFinder(Item targetItem)
{
if (it?.Submarine == null) { return false; }
if (item.Submarine == null || !item.Submarine.IsEntityFoundOnThisSub(it, includingConnectedSubs: true)) { return false; }
if (it.NonInteractable || it.IsHidden) { return false; }
if (it.GetComponent<Pickable>() == null) { return false; }
if (targetItem?.Submarine == null || item.Submarine == null) { return false; }
var holdable = it.GetComponent<Holdable>();
if (!IsPortableItemAllowed) { return false; }
if (!item.Submarine.IsEntityFoundOnThisSub(targetItem, includingConnectedSubs: true)) { return false; }
if (targetItem.NonInteractable || targetItem.IsHidden) { return false; }
if (targetItem.GetComponent<Pickable>() == null) { return false; }
var holdable = targetItem.GetComponent<Holdable>();
if (holdable != null && holdable.Attached) { return false; }
var wire = it.GetComponent<Wire>();
var wire = targetItem.GetComponent<Wire>();
if (wire != null && wire.Connections.Any(c => c != null)) { return false; }
if (it.Container?.GetComponent<ItemContainer>() is { DrawInventory: false } or { AllowAccess: false }) { return false; }
if (targetItem.Container?.GetComponent<ItemContainer>() is { DrawInventory: false } or { AllowAccess: false }) { return false; }
if (it.HasTag(Tags.TraitorMissionItem)) { return false; }
if (targetItem.HasTag(Tags.TraitorMissionItem)) { return false; }
return true;
}
@@ -454,18 +459,24 @@ namespace Barotrauma.Items.Components
searchAutoComplete?.AddToGUIUpdateList(order: order + 1);
}
}
private void CreateHUD()
private void ClearHUD()
{
subEntities.Clear();
prevResolution = new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight);
submarineContainer.ClearChildren();
displayedSubs.Clear();
}
if (item.Submarine is null)
private void RefreshHUD()
{
ClearHUD();
if (item.Submarine is null || !IsPortableItemAllowed)
{
displayedSubs.Clear();
return;
}
prevResolution = new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight);
scissorComponent = new GUIScissorComponent(new RectTransform(Vector2.One, submarineContainer.RectTransform, Anchor.Center));
miniMapContainer = new GUIFrame(new RectTransform(Vector2.One, scissorComponent.Content.RectTransform, Anchor.Center), style: null) { CanBeFocused = false };
@@ -574,18 +585,25 @@ namespace Barotrauma.Items.Components
public override void UpdateHUDComponentSpecific(Character character, float deltaTime, Camera cam)
{
//recreate HUD if the subs we should display have changed
if (item.Submarine == null && displayedSubs.Count > 0 || // item not inside a sub anymore, but display is still showing subs
// Refresh HUD (including possibly just clearing it away) if the subs we should display have changed
if (item.Submarine == null && displayedSubs.Count > 0 || // item not inside a sub anymore, but display is still showing subs
item.Submarine is { } itemSub &&
(
!displayedSubs.Contains(itemSub) || // current sub not displayed
itemSub.DockedTo.Where(s => s.TeamID == item.Submarine.TeamID).Any(s => !displayedSubs.Contains(s) && itemSub.ConnectedDockingPorts[s].IsLocked) || // some of the docked subs not displayed
displayedSubs.Any(s => s != itemSub && !itemSub.DockedTo.Contains(s)) // displaying a sub that shouldn't be displayed
// current sub not displayed
!displayedSubs.Contains(itemSub) ||
// some of the docked subs not displayed
itemSub.DockedTo.Where(s => s.TeamID == item.Submarine.TeamID).Any(s => !displayedSubs.Contains(s) && itemSub.ConnectedDockingPorts[s].IsLocked) ||
// displaying a sub that shouldn't be displayed
displayedSubs.Any(s => s != itemSub && !itemSub.DockedTo.Contains(s))
) ||
prevResolution.X != GameMain.GraphicsWidth || prevResolution.Y != GameMain.GraphicsHeight || // resolution changed
!submarineContainer.Children.Any()) // We lack a GUI
// If this item is portable and not in a player sub and using it otherwise is disallowed
!IsPortableItemAllowed ||
// resolution changed
prevResolution.X != GameMain.GraphicsWidth || prevResolution.Y != GameMain.GraphicsHeight ||
// We lack a GUI
!submarineContainer.Children.Any())
{
CreateHUD();
RefreshHUD();
}
//reset data if we haven't received anything in a while
@@ -737,7 +755,7 @@ namespace Barotrauma.Items.Components
return;
}
if (Voltage < MinVoltage)
if (!HasPower)
{
Vector2 textSize = GUIStyle.Font.MeasureString(noPowerTip);
Vector2 textPos = GuiFrame.Rect.Center.ToVector2();
@@ -747,7 +765,7 @@ namespace Barotrauma.Items.Components
return;
}
if (currentMode == MiniMapMode.HullStatus && item.Submarine != null)
if (currentMode == MiniMapMode.HullStatus && item.Submarine != null && IsPortableItemAllowed)
{
Rectangle prevScissorRect = spriteBatch.GraphicsDevice.ScissorRectangle;
spriteBatch.End();
@@ -958,19 +976,19 @@ namespace Barotrauma.Items.Components
MiniMapBlips = positions.ToImmutableHashSet();
if (searchAutoComplete is null) { return; }
searchAutoComplete.Visible = false;
HideGUIComponent(searchAutoComplete);
}
private void UpdateHUDBack()
{
if (item.Submarine == null) { return; }
if (hullInfoFrame != null) { hullInfoFrame.Visible = false; }
reportFrame.Visible = false;
searchBarFrame.Visible = false;
electricalFrame.Visible = false;
miniMapFrame.Visible = false;
// Clear up mode-specific elements before checking if drawing should continue, so they'll be gone if not
HideModeSpecificFrames();
if (item.Submarine == null || !IsPortableItemAllowed)
{
ClearHUD();
return;
}
switch (currentMode)
{
@@ -988,7 +1006,24 @@ namespace Barotrauma.Items.Components
break;
}
}
private void HideModeSpecificFrames()
{
HideGUIComponent(hullInfoFrame);
HideGUIComponent(reportFrame);
HideGUIComponent(searchBarFrame);
HideGUIComponent(electricalFrame);
HideGUIComponent(miniMapFrame);
}
private static void HideGUIComponent(GUIComponent? component)
{
if (component != null)
{
component.Visible = false;
}
}
private void UpdateHullStatus()
{
bool canHoverOverHull = true;
@@ -1007,7 +1042,7 @@ namespace Barotrauma.Items.Components
child.Color = child.OutlineColor = NoPowerDoorColor;
}
if (Voltage < MinVoltage) { continue; }
if (!HasPower) { continue; }
child.Color = child.OutlineColor = DoorIndicatorColor;
if (GUI.MouseOn == child)
@@ -1037,7 +1072,7 @@ namespace Barotrauma.Items.Components
}
}
if (Voltage < MinVoltage) { continue; }
if (!HasPower) { continue; }
hullDatas.TryGetValue(hull, out HullData? hullData);
if (hullData is null)
@@ -1187,7 +1222,7 @@ namespace Barotrauma.Items.Components
component.Color = component.OutlineColor = NoPowerElectricalColor;
}
if (Voltage < MinVoltage || !miniMapGuiComponent.RectComponent.Visible) { continue; }
if (!HasPower || !miniMapGuiComponent.RectComponent.Visible) { continue; }
int durability = (int)(it.Condition / (it.MaxCondition / it.MaxRepairConditionMultiplier) * 100f);
Color color = ToolBox.GradientLerp(durability / 100f, GUIStyle.Red, GUIStyle.Orange, GUIStyle.Green, GUIStyle.Green);
@@ -1229,11 +1264,11 @@ namespace Barotrauma.Items.Components
private void DrawHUDBack(SpriteBatch spriteBatch, GUICustomComponent container)
{
if (item.Submarine == null) { return; }
if (item.Submarine == null || !IsPortableItemAllowed) { return; }
DrawSubmarine(spriteBatch);
DrawSubmarine(spriteBatch);
if (Voltage < MinVoltage) { return; }
if (!HasPower) { return; }
Rectangle prevScissorRect = spriteBatch.GraphicsDevice.ScissorRectangle;
spriteBatch.End();
spriteBatch.Begin(SpriteSortMode.Deferred, samplerState: GUI.SamplerState, rasterizerState: GameMain.ScissorTestEnable);
@@ -144,6 +144,7 @@ namespace Barotrauma.Items.Components
private bool isConnectedToSteering;
private static LocalizedString caveLabel;
private static LocalizedString enemyLabel;
[Serialize(false, IsPropertySaveable.Yes)]
@@ -164,6 +165,8 @@ namespace Barotrauma.Items.Components
TextManager.Get("cave").Fallback(
TextManager.Get("missiontype.nest"));
enemyLabel = TextManager.Get("enemysubmarine");
foreach (var subElement in element.Elements())
{
switch (subElement.Name.ToString().ToLowerInvariant())
@@ -1019,6 +1022,38 @@ namespace Barotrauma.Items.Components
cave.StartPos.ToVector2(), transducerCenter,
DisplayScale, center, DisplayRadius);
}
if (GameMain.NetworkMember is { } networkMember && GameMain.GameSession?.GameMode is PvPMode)
{
if (networkMember.ServerSettings.TrackOpponentInPvP
&& Submarine.MainSubs[0] is { } coalitionSub
&& Submarine.MainSubs[1] is { } separatistSub
&& Character.Controlled is { } player)
{
Submarine whichSubToDraw = player.TeamID switch
{
CharacterTeamType.Team1 => separatistSub,
CharacterTeamType.Team2 => coalitionSub,
_ => null
};
if (whichSubToDraw != null)
{
DrawOffsetMarker(spriteBatch,
enemyLabel.Value,
Tags.Submarine,
Tags.Enemy,
whichSubToDraw.WorldPosition,
transducerCenter,
distanceThresholds: new Range<float>(start: MetersToUnits(150), end: MetersToUnits(1600)),
offset: new Range<float>(start: MetersToUnits(100), end: MetersToUnits(400)),
minOffset: MetersToUnits(10));
static float MetersToUnits(float m)
=> m / Physics.DisplayToRealWorldRatio;
}
}
}
}
int missionIndex = 0;
@@ -1042,7 +1077,8 @@ namespace Barotrauma.Items.Components
}
if (HasMineralScanner && UseMineralScanner && CurrentMode == Mode.Active && MineralClusters != null &&
(item.CurrentHull == null || !DetectSubmarineWalls))
(item.CurrentHull == null || !DetectSubmarineWalls) &&
HasPower)
{
foreach (var c in MineralClusters)
{
@@ -1076,7 +1112,7 @@ namespace Barotrauma.Items.Components
{
if (!sub.ShowSonarMarker) { continue; }
if (connectedSubs.Contains(sub)) { continue; }
if (Level.Loaded != null && sub.WorldPosition.Y > Level.Loaded.Size.Y) { continue; }
if (sub.IsAboveLevel) { continue; }
if (item.Submarine != null || Character.Controlled != null)
{
@@ -1185,7 +1221,7 @@ namespace Barotrauma.Items.Components
foreach (DockingPort dockingPort in DockingPort.List)
{
if (Level.Loaded != null && dockingPort.Item.Submarine.WorldPosition.Y > Level.Loaded.Size.Y) { continue; }
if (dockingPort.Item.Submarine.IsAboveLevel) { continue; }
if (dockingPort.Item.IsHidden) { continue; }
if (dockingPort.Item.Submarine == null) { continue; }
if (dockingPort.Item.Submarine.Info.IsWreck) { continue; }
@@ -1198,8 +1234,8 @@ namespace Barotrauma.Items.Components
//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 &&
!item.Submarine.IsRespawnShuttle &&
!dockingPort.Item.Submarine.IsRespawnShuttle &&
!dockingPort.Item.Submarine.Info.IsOutpost &&
!dockingPort.Item.Submarine.Info.IsBeacon)
{
@@ -1792,8 +1828,47 @@ namespace Barotrauma.Items.Components
sonarBlip.Draw(spriteBatch, center + pos, color * 0.5f * blip.Alpha, sonarBlip.Origin, 0, scale, SpriteEffects.None, 0);
}
/// <summary>
/// Used in DrawOffsetMarker to cache the randomized location of the marker
/// </summary>
private readonly Dictionary<Identifier, CachedLocation> cachedLocations = new Dictionary<Identifier, CachedLocation>();
private void DrawOffsetMarker(SpriteBatch spriteBatch, string label, Identifier iconIdentifier, Identifier targetIdentifier, Vector2 worldPosition, Vector2 transducerPosition, Range<float> distanceThresholds, Range<float> offset, float minOffset)
{
Vector2 pos;
if (!cachedLocations.TryGetValue(targetIdentifier, out CachedLocation cachedLocation))
{
cachedLocation = CreateCachedLocation();
cachedLocations.Add(targetIdentifier, cachedLocation);
pos = cachedLocation.Location;
}
else
{
if (Timing.TotalTime > cachedLocation.RecalculationTime)
{
cachedLocation = CreateCachedLocation();
cachedLocations[targetIdentifier] = cachedLocation;
}
pos = cachedLocation.Location;
}
DrawMarker(spriteBatch, label, iconIdentifier, targetIdentifier, pos, transducerPosition, DisplayScale, center, DisplayRadius);
CachedLocation CreateCachedLocation()
{
float distance = Vector2.Distance(worldPosition, transducerPosition);
float maxOffset = MathHelper.Lerp(offset.Start, offset.End, MathHelper.Clamp((distance - distanceThresholds.Start) / (distanceThresholds.End - distanceThresholds.Start), 0.0f, 1.0f));
Vector2 randomPos = Rand.Vector(Rand.Range(minOffset, maxOffset));
return new CachedLocation(worldPosition + randomPos, Timing.TotalTime + Rand.Range(10.0f, 30.0f));
}
}
private void DrawMarker(SpriteBatch spriteBatch, string label, Identifier iconIdentifier, object targetIdentifier, Vector2 worldPosition, Vector2 transducerPosition, float scale, Vector2 center, float radius,
bool onlyShowTextOnMouseOver = false)
bool onlyShowTextOnMouseOver = false)
{
float linearDist = Vector2.Distance(worldPosition, transducerPosition);
float dist = linearDist;
@@ -554,7 +554,7 @@ namespace Barotrauma.Items.Components
int x = rect.X;
int y = rect.Y;
if (Voltage < MinVoltage) { return; }
if (!HasPower) { return; }
Rectangle velRect = new Rectangle(x + 20, y + 20, width - 40, height - 40);
Vector2 steeringOrigin = steerArea.Rect.Center.ToVector2();
@@ -759,7 +759,7 @@ namespace Barotrauma.Items.Components
dockingButton.Text = dockText;
}
if (Voltage < MinVoltage)
if (!HasPower)
{
tipContainer.Visible = true;
tipContainer.Text = noPowerTip;
@@ -829,7 +829,7 @@ namespace Barotrauma.Items.Components
}
if (!AutoPilot && Character.DisableControls && GUI.KeyboardDispatcher.Subscriber == null)
{
steeringAdjustSpeed = character == null ? DefaultSteeringAdjustSpeed : MathHelper.Lerp(0.2f, 1.0f, character.GetSkillLevel("helm") / 100.0f);
steeringAdjustSpeed = character == null ? DefaultSteeringAdjustSpeed : MathHelper.Lerp(0.2f, 1.0f, character.GetSkillLevel(Tags.HelmSkill) / 100.0f);
Vector2 input = Vector2.Zero;
if (PlayerInput.KeyDown(InputType.Left)) { input -= Vector2.UnitX; }
if (PlayerInput.KeyDown(InputType.Right)) { input += Vector2.UnitX; }
@@ -909,7 +909,7 @@ namespace Barotrauma.Items.Components
if (targetPort.Docked || targetPort.Item.Submarine == null) { continue; }
if (targetPort.Item.Submarine == controlledSub || targetPort.IsHorizontal != sourcePort.IsHorizontal) { continue; }
if (targetPort.Item.Submarine.DockedTo?.Contains(sourcePort.Item.Submarine) ?? false) { continue; }
if (Level.Loaded != null && targetPort.Item.Submarine.WorldPosition.Y > Level.Loaded.Size.Y) { continue; }
if (targetPort.Item.Submarine.IsAboveLevel) { continue; }
if (sourceDir == targetPort.GetDir()) { continue; }
float dist = Vector2.DistanceSquared(sourcePort.Item.WorldPosition, targetPort.Item.WorldPosition);
@@ -6,6 +6,7 @@ namespace Barotrauma.Items.Components
{
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
{
base.DrawHUD(spriteBatch, character);
currentTarget?.DrawHUD(spriteBatch, Screen.Selected.Cam, character);
}
@@ -299,6 +299,8 @@ namespace Barotrauma.Items.Components
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
{
base.DrawHUD(spriteBatch, character);
IsActive = true;
float defaultMaxCondition = (item.MaxCondition / item.MaxRepairConditionMultiplier);
@@ -52,9 +52,11 @@ namespace Barotrauma.Items.Components
Vector2 sourcePos = GetSourcePos();
//need to double the size because this is essentially just the radius, we need the diameter
// + some extra margin to be on the safe side
return new Vector2(
Math.Abs(target.DrawPosition.X - sourcePos.X),
Math.Abs(target.DrawPosition.Y - sourcePos.Y)) * 1.5f;
Math.Abs(target.DrawPosition.Y - sourcePos.Y)) * 2.2f;
}
}
@@ -122,7 +124,7 @@ namespace Barotrauma.Items.Components
{
if (turret.BarrelSprite != null)
{
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 += new Vector2((float)Math.Cos(turret.Rotation), (float)Math.Sin(turret.Rotation)) * turret.BarrelSprite.size.Y * turret.BarrelSprite.RelativeOrigin.Y * turret.Item.Scale * BarrelLengthMultiplier;
}
startPos -= turret.GetRecoilOffset();
}
@@ -3,7 +3,6 @@ using Barotrauma.Networking;
using Microsoft.Xna.Framework;
using System;
using System.Linq;
using System.Xml.Linq;
namespace Barotrauma.Items.Components
{
@@ -16,7 +15,7 @@ namespace Barotrauma.Items.Components
partial void InitProjSpecific(ContentXElement element)
{
terminalButtonStyles = new string[RequiredSignalCount];
terminalButtonStyles = new string[requiredSignalCount];
int i = 0;
foreach (var childElement in element.GetChildElements("TerminalButton"))
{
@@ -38,11 +37,11 @@ namespace Barotrauma.Items.Components
};
paddedFrame.OnAddedToGUIUpdateList += (component) =>
{
bool buttonsEnabled = AllowUsingButtons;
foreach (var child in component.Children)
bool buttonsEnabled = IsActivated;
foreach (GUIComponent child in component.Children)
{
if (!(child is GUIButton)) { continue; }
if (!(child.UserData is int)) { continue; }
if (child is not GUIButton) { continue; }
if (child.UserData is not int) { continue; }
child.Enabled = buttonsEnabled;
child.Children.ForEach(c => c.Enabled = buttonsEnabled);
}
@@ -59,7 +58,7 @@ namespace Barotrauma.Items.Components
containerIndicator.OverrideState = itemsContained ? GUIComponent.ComponentState.Selected : GUIComponent.ComponentState.None;
};
float x = 1.0f / (1 + RequiredSignalCount);
float x = 1.0f / (1 + requiredSignalCount);
float y = Math.Min((x * paddedFrame.Rect.Width) / paddedFrame.Rect.Height, 0.5f);
Vector2 relativeSize = new Vector2(x, y);
@@ -69,7 +68,7 @@ namespace Barotrauma.Items.Components
containerIndicator = new GUIImage(new RectTransform(new Vector2(0.5f, 0.5f * (1.0f - y)), containerSection.RectTransform, anchor: Anchor.BottomCenter),
style: "IndicatorLightRed", scaleToFit: true);
for (int i = 0; i < RequiredSignalCount; i++)
for (int i = 0; i < requiredSignalCount; i++)
{
var button = new GUIButton(new RectTransform(relativeSize, paddedFrame.RectTransform), style: null)
{
@@ -111,7 +110,7 @@ namespace Barotrauma.Items.Components
public void ClientEventRead(IReadMessage msg, float sendingTime)
{
SendSignal(msg.ReadRangedInteger(0, Signals.Length - 1), sender: null, isServerMessage: true);
SendSignal(msg.ReadRangedInteger(0, Signals.Length - 1), sender: null, ignoreState: true);
}
}
}
@@ -1,4 +1,4 @@
#nullable enable
#nullable enable
using System;
using System.Collections.Generic;
@@ -129,7 +129,7 @@ namespace Barotrauma.Items.Components
public void RemoveComponents(IReadOnlyCollection<CircuitBoxComponent> node)
{
if (Locked) { return; }
if (IsLocked()) { return; }
var ids = node.Select(static n => n.ID).ToImmutableArray();
if (GameMain.NetworkMember is null)
@@ -146,7 +146,7 @@ namespace Barotrauma.Items.Components
public void AddWire(CircuitBoxConnection one, CircuitBoxConnection two)
{
if (Locked) { return; }
if (IsLocked()) { return; }
if (GameMain.NetworkMember is null)
{
Connect(one, two, static delegate { }, CircuitBoxWire.SelectedWirePrefab);
@@ -160,7 +160,7 @@ namespace Barotrauma.Items.Components
public void RemoveWires(IReadOnlyCollection<CircuitBoxWire> wires)
{
if (Locked) { return; }
if (IsLocked()) { return; }
var ids = wires.Select(static w => w.ID).ToImmutableArray();
if (GameMain.NetworkMember is null)
{
@@ -230,7 +230,7 @@ namespace Barotrauma.Items.Components
public void MoveComponent(Vector2 moveAmount, IReadOnlyCollection<CircuitBoxNode> moveables)
{
if (Locked) { return; }
if (IsLocked()) { return; }
var ids = ImmutableArray.CreateBuilder<ushort>();
var ios = ImmutableArray.CreateBuilder<CircuitBoxInputOutputNode.Type>();
var labelIds = ImmutableArray.CreateBuilder<ushort>();
@@ -265,7 +265,7 @@ namespace Barotrauma.Items.Components
public void AddComponent(ItemPrefab prefab, Vector2 pos)
{
if (Locked) { return; }
if (IsLocked()) { return; }
if (GameMain.NetworkMember is null)
{
ItemPrefab resource;
@@ -292,7 +292,7 @@ namespace Barotrauma.Items.Components
public void RenameLabel(CircuitBoxLabelNode label, Color color, NetLimitedString header, NetLimitedString body)
{
if (Locked) { return; }
if (IsLocked()) { return; }
if (GameMain.NetworkMember is null)
{
label.EditText(header, body);
@@ -316,7 +316,7 @@ namespace Barotrauma.Items.Components
public void ResizeNode(CircuitBoxNode node, CircuitBoxResizeDirection dir, Vector2 amount)
{
if (Locked) { return; }
if (IsLocked()) { return; }
var resize = node.ResizeBy(dir, amount);
if (GameMain.NetworkMember is null)
{
@@ -341,7 +341,7 @@ namespace Barotrauma.Items.Components
public void AddLabel(Vector2 pos)
{
if (Locked) { return; }
if (IsLocked()) { return; }
if (GameMain.NetworkMember is null)
{
AddLabelInternal(ICircuitBoxIdentifiable.FindFreeID(Labels), GUIStyle.Blue, pos, CircuitBoxLabelNode.DefaultHeaderText, NetLimitedString.Empty);
@@ -353,7 +353,7 @@ namespace Barotrauma.Items.Components
public void RemoveLabel(IReadOnlyCollection<CircuitBoxLabelNode> labels)
{
if (Locked) { return; }
if (IsLocked()) { return; }
if (!labels.Any()) { return; }
var ids = labels.Select(static n => n.ID).ToImmutableArray();
@@ -14,6 +14,8 @@ namespace Barotrauma.Items.Components
private bool readingNetworkEvent;
private GUIComponent insufficientPowerWarning;
private Point ElementMaxSize => new Point(uiElementContainer.Rect.Width, (int)(65 * GUI.yScale));
public override bool RecreateGUIOnResolutionChange => true;
@@ -40,7 +42,7 @@ namespace Barotrauma.Items.Components
float elementSize = Math.Min(1.0f / visibleElements.Count(), 1);
foreach (CustomInterfaceElement ciElement in visibleElements)
{
if (ciElement.HasPropertyName)
if (ciElement.InputType is CustomInterfaceElement.InputTypeOption.Number or CustomInterfaceElement.InputTypeOption.Text)
{
var layoutGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, elementSize), uiElementContainer.RectTransform), isHorizontal: true)
{
@@ -49,7 +51,7 @@ namespace Barotrauma.Items.Components
};
new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), layoutGroup.RectTransform),
TextManager.Get(ciElement.Label).Fallback(ciElement.Label));
if (!ciElement.IsNumberInput)
if (ciElement.InputType is CustomInterfaceElement.InputTypeOption.Text)
{
var textBox = new GUITextBox(new RectTransform(new Vector2(0.5f, 1.0f), layoutGroup.RectTransform), ciElement.Signal, style: "GUITextBoxNoIcon")
{
@@ -149,7 +151,7 @@ namespace Barotrauma.Items.Components
}
}
}
else if (ciElement.ContinuousSignal)
else if (ciElement.InputType is CustomInterfaceElement.InputTypeOption.TickBox)
{
var tickBox = new GUITickBox(new RectTransform(new Vector2(1.0f, elementSize), uiElementContainer.RectTransform)
{
@@ -175,7 +177,7 @@ namespace Barotrauma.Items.Components
tickBox.RectTransform.MaxSize = new Point(int.MaxValue, int.MaxValue);
uiElements.Add(tickBox);
}
else
else if (ciElement.InputType is CustomInterfaceElement.InputTypeOption.Button)
{
var btn = new GUIButton(new RectTransform(new Vector2(1.0f, elementSize), uiElementContainer.RectTransform),
TextManager.Get(ciElement.Label).Fallback(ciElement.Label), style: "DeviceButton")
@@ -203,6 +205,16 @@ namespace Barotrauma.Items.Components
uiElements.Add(btn);
}
}
if (ShowInsufficientPowerWarning)
{
insufficientPowerWarning = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.1f), GuiFrame.RectTransform, Anchor.BottomCenter, Pivot.TopCenter) { MinSize = new Point(0, GUI.IntScale(30)) },
TextManager.Get("SteeringNoPowerTip"), font: GUIStyle.Font, wrap: true, style: "GUIToolTip", textAlignment: Alignment.Center)
{
AutoScaleHorizontal = true,
Visible = false
};
}
}
public override void CreateEditingHUD(SerializableEntityEditor editor)
@@ -253,7 +265,20 @@ namespace Barotrauma.Items.Components
{
if (uiElement.UserData is not CustomInterfaceElement element) { continue; }
bool visible = Screen.Selected == GameMain.SubEditorScreen || element.StatusEffects.Any() || element.HasPropertyName || (element.Connection != null && element.Connection.Wires.Count > 0);
if (visible) { visibleElementCount++; }
if (visible)
{
visibleElementCount++;
if (element.GetValueInterval > 0.0f)
{
element.GetValueTimer -= deltaTime;
if (element.GetValueTimer <= 0.0f)
{
SetSignalToPropertyValue(element);
UpdateSignalProjSpecific(uiElement);
element.GetValueTimer = element.GetValueInterval;
}
}
}
if (uiElement.Visible != visible)
{
uiElement.Visible = visible;
@@ -274,6 +299,11 @@ namespace Barotrauma.Items.Components
GuiFrame.Visible = visibleElementCount > 0;
uiElementContainer.Recalculate();
}
if (insufficientPowerWarning != null)
{
insufficientPowerWarning.Visible = item.GetComponents<Powered>().Any(p => p.PowerConsumption > 0.0f && p.Voltage < p.MinVoltage);
}
}
partial void UpdateLabelsProjSpecific()
@@ -336,22 +366,32 @@ namespace Barotrauma.Items.Components
if (signals == null) { return; }
for (int i = 0; i < signals.Length && i < uiElements.Count; i++)
{
string signal = customInterfaceElementList[i].Signal;
if (uiElements[i] is GUITextBox tb)
UpdateSignalProjSpecific(uiElements[i]);
}
}
private void UpdateSignalProjSpecific(GUIComponent uiElement)
{
if (uiElement.UserData is not CustomInterfaceElement element) { return; }
string signal = element.Signal;
if (uiElement is GUITextBox tb)
{
tb.Text = Screen.Selected is { IsEditor: true } ?
signal :
TextManager.Get(signal).Fallback(signal).Value;
}
else if (uiElement is GUINumberInput ni)
{
if (ni.InputType == NumberType.Int)
{
tb.Text = Screen.Selected is { IsEditor: true } ?
signal :
TextManager.Get(signal).Fallback(signal).Value;
}
else if (uiElements[i] is GUINumberInput ni)
{
if (ni.InputType == NumberType.Int)
{
int.TryParse(signal, out int value);
ni.IntValue = value;
}
int.TryParse(signal, out int value);
ni.IntValue = value;
}
}
else if (uiElement is GUITickBox tickBox)
{
tickBox.Selected = signal.Equals("true", StringComparison.OrdinalIgnoreCase);
}
}
public void ClientEventWrite(IWriteMessage msg, NetEntityEvent.IData extraData = null)
@@ -360,14 +400,9 @@ namespace Barotrauma.Items.Components
for (int i = 0; i < customInterfaceElementList.Count; i++)
{
var element = customInterfaceElementList[i];
if (element.HasPropertyName)
switch (element.InputType)
{
if (!element.IsNumberInput)
{
msg.WriteString(((GUITextBox)uiElements[i]).Text);
}
else
{
case CustomInterfaceElement.InputTypeOption.Number:
switch (element.NumberType)
{
case NumberType.Float:
@@ -378,15 +413,16 @@ namespace Barotrauma.Items.Components
msg.WriteString(((GUINumberInput)uiElements[i]).IntValue.ToString());
break;
}
}
}
else if (element.ContinuousSignal)
{
msg.WriteBoolean(((GUITickBox)uiElements[i]).Selected);
}
else
{
msg.WriteBoolean(extraData is Item.ComponentStateEventData { ComponentData: EventData eventData } && eventData.BtnElement == customInterfaceElementList[i]);
break;
case CustomInterfaceElement.InputTypeOption.Text:
msg.WriteString(((GUITextBox)uiElements[i]).Text);
break;
case CustomInterfaceElement.InputTypeOption.TickBox:
msg.WriteBoolean(((GUITickBox)uiElements[i]).Selected);
break;
case CustomInterfaceElement.InputTypeOption.Button:
msg.WriteBoolean(extraData is Item.ComponentStateEventData { ComponentData: EventData eventData } && eventData.BtnElement == customInterfaceElementList[i]);
break;
}
}
}
@@ -399,15 +435,10 @@ namespace Barotrauma.Items.Components
for (int i = 0; i < customInterfaceElementList.Count; i++)
{
var element = customInterfaceElementList[i];
if (element.HasPropertyName)
switch (element.InputType)
{
string newValue = msg.ReadString();
if (!element.IsNumberInput)
{
TextChanged(element, newValue);
}
else
{
case CustomInterfaceElement.InputTypeOption.Number:
string newValue = msg.ReadString();
switch (element.NumberType)
{
case NumberType.Int when int.TryParse(newValue, out int value):
@@ -417,20 +448,23 @@ namespace Barotrauma.Items.Components
ValueChanged(element, value);
break;
}
}
}
else
{
bool elementState = msg.ReadBoolean();
if (element.ContinuousSignal)
{
((GUITickBox)uiElements[i]).Selected = elementState;
TickBoxToggled(element, elementState);
}
else if (elementState)
{
ButtonClicked(element);
}
break;
case CustomInterfaceElement.InputTypeOption.Text:
string newTextValue = msg.ReadString();
TextChanged(element, newTextValue);
break;
case CustomInterfaceElement.InputTypeOption.TickBox:
bool tickBoxState = msg.ReadBoolean();
((GUITickBox)uiElements[i]).Selected = tickBoxState;
TickBoxToggled(element, tickBoxState);
break;
case CustomInterfaceElement.InputTypeOption.Button:
bool buttonState = msg.ReadBoolean();
if (buttonState)
{
ButtonClicked(element);
}
break;
}
}
@@ -106,7 +106,7 @@ namespace Barotrauma.Items.Components
private static int? selectedNodeIndex;
private static int? highlightedNodeIndex;
[Serialize(0.3f, IsPropertySaveable.No)]
[Serialize(0.3f, IsPropertySaveable.No), Editable(MinValueFloat = 0.01f, MaxValueFloat = 10.0f, DecimalCount = 2)]
public float Width
{
get;
@@ -175,6 +175,8 @@ namespace Barotrauma.Items.Components
{
if (character == null) { return; }
base.DrawHUD(spriteBatch, character);
if (OverlayColor.A > 0)
{
GUIStyle.UIGlow.Draw(spriteBatch, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight),
@@ -206,44 +208,51 @@ namespace Barotrauma.Items.Components
if (ThermalGoggles)
{
spriteBatch.End();
GameMain.LightManager.SolidColorEffect.Parameters["color"].SetValue(Color.Red.ToVector4() * (0.3f + MathF.Sin(thermalEffectState) * 0.05f));
GameMain.LightManager.SolidColorEffect.CurrentTechnique = GameMain.LightManager.SolidColorEffect.Techniques["SolidColorBlur"];
GameMain.LightManager.SolidColorEffect.Parameters["blurDistance"].SetValue(0.01f + MathF.Sin(thermalEffectState) * 0.005f);
GameMain.LightManager.SolidColorEffect.CurrentTechnique.Passes[0].Apply();
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Additive, transformMatrix: Screen.Selected.Cam.Transform, effect: GameMain.LightManager.SolidColorEffect);
Entity refEntity = equipper;
if (!isEquippable || refEntity == null)
{
refEntity = item;
}
DrawThermalOverlay(spriteBatch, refEntity, character, OverlayColor, Range, thermalEffectState, ShowDeadCharacters);
foreach (Character c in Character.CharacterList)
{
if (c == character || !c.Enabled || c.Removed || c.Params.HideInThermalGoggles) { continue; }
if (!ShowDeadCharacters && c.IsDead) { continue; }
float dist = Vector2.DistanceSquared(refEntity.WorldPosition, c.WorldPosition);
if (dist > Range * Range) { continue; }
Sprite pingCircle = GUIStyle.UIThermalGlow.Value.Sprite;
foreach (Limb limb in c.AnimController.Limbs)
{
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);
Vector2 drawPos = new Vector2(limb.body.DrawPosition.X + (noise1 - 0.5f) * 100, -limb.body.DrawPosition.Y + (noise2 - 0.5f) * 100);
pingCircle.Draw(spriteBatch, drawPos, 0.0f, scale: Math.Max(spriteScale.X, spriteScale.Y));
}
}
spriteBatch.End();
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied);
}
}
public static void DrawThermalOverlay(SpriteBatch spriteBatch, Entity refEntity, Character user, Color overlayColor, float range, float effectState, bool showDeadCharacters)
{
spriteBatch.End();
float colorIntensityBase = 0.5f; //Multiplies the overlay color by this amount, the higher the value, the more bright/vibrant the color.
float colorIntensityVariance = 0.05f; //The variance of the pulse effect affecting the color's brightness/vibrance
GameMain.LightManager.SolidColorEffect.Parameters["color"].SetValue(overlayColor.ToVector4() * (colorIntensityBase + MathF.Sin(effectState) * colorIntensityVariance));
GameMain.LightManager.SolidColorEffect.CurrentTechnique = GameMain.LightManager.SolidColorEffect.Techniques["SolidColorBlur"];
GameMain.LightManager.SolidColorEffect.Parameters["blurDistance"].SetValue(0.01f + MathF.Sin(effectState) * 0.005f);
GameMain.LightManager.SolidColorEffect.CurrentTechnique.Passes[0].Apply();
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Additive, transformMatrix: Screen.Selected.Cam.Transform, effect: GameMain.LightManager.SolidColorEffect);
foreach (Character c in Character.CharacterList)
{
if (c == user || !c.Enabled || c.Removed || c.Params.HideInThermalGoggles) { continue; }
if (!showDeadCharacters && c.IsDead) { continue; }
float dist = Vector2.DistanceSquared(refEntity.WorldPosition, c.WorldPosition);
if (dist > range * range) { continue; }
Sprite pingCircle = GUIStyle.UIThermalGlow.Value.Sprite;
foreach (Limb limb in c.AnimController.Limbs)
{
if (limb.Mass < 0.5f && limb != c.AnimController.MainLimb) { continue; }
float noise1 = PerlinNoise.GetPerlin((effectState + limb.Params.ID + c.ID) * 0.01f, (effectState + limb.Params.ID + c.ID) * 0.02f);
float noise2 = PerlinNoise.GetPerlin((effectState + limb.Params.ID + c.ID) * 0.01f, (effectState + limb.Params.ID + c.ID) * 0.008f);
Vector2 spriteScale = ConvertUnits.ToDisplayUnits(limb.body.GetSize()) / pingCircle.size * (noise1 * 0.5f + 2f);
Vector2 drawPos = new Vector2(limb.body.DrawPosition.X + (noise1 - 0.5f) * 100, -limb.body.DrawPosition.Y + (noise2 - 0.5f) * 100);
pingCircle.Draw(spriteBatch, drawPos, 0.0f, scale: Math.Max(spriteScale.X, spriteScale.Y));
}
}
spriteBatch.End();
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied);
}
private void DrawCharacterInfo(SpriteBatch spriteBatch, Character target, float alpha = 1.0f)
{
Vector2 hudPos = GameMain.GameScreen.Cam.WorldToScreen(target.DrawPosition);
@@ -1,12 +1,28 @@
using Barotrauma.Networking;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
namespace Barotrauma.Items.Components
{
partial class TriggerComponent : ItemComponent, IServerSerializable
partial class TriggerComponent : ItemComponent, IServerSerializable, IDrawableComponent
{
public Vector2 DrawSize =>
Vector2.One *
(Radius > 0.0f ? Radius * 2 : Math.Max(Width, Height));
public void Draw(SpriteBatch spriteBatch, bool editing, float itemDepth = -1, Color? overrideColor = null)
{
if (editing)
{
PhysicsBody.DebugDraw(spriteBatch, Color.LightGray * 0.7f);
}
}
public void ClientEventRead(IReadMessage msg, float sendingTime)
{
CurrentForceFluctuation = msg.ReadRangedSingle(0.0f, 1.0f, 8);
}
}
}
@@ -385,17 +385,20 @@ namespace Barotrauma.Items.Components
if (item.Condition > 0.0f || !HideBarrelWhenBroken)
{
railSprite?.Draw(spriteBatch,
var currentRailSprite = item.Condition <= 0.0f && railSpriteBroken != null ? railSpriteBroken : railSprite;
var currentBarrelSprite = item.Condition <= 0.0f && barrelSpriteBroken != null ? barrelSpriteBroken : barrelSprite;
currentRailSprite?.Draw(spriteBatch,
drawPos,
overrideColor ?? item.SpriteColor,
Rotation + MathHelper.PiOver2, item.Scale,
SpriteEffects.None, item.SpriteDepth + (railSprite.Depth - item.Sprite.Depth));
SpriteEffects.None, item.SpriteDepth + (currentRailSprite.Depth - item.Sprite.Depth));
barrelSprite?.Draw(spriteBatch,
currentBarrelSprite?.Draw(spriteBatch,
drawPos - GetRecoilOffset() * item.Scale,
overrideColor ?? item.SpriteColor,
Rotation + MathHelper.PiOver2, item.Scale,
SpriteEffects.None, item.SpriteDepth + (barrelSprite.Depth - item.Sprite.Depth));
SpriteEffects.None, item.SpriteDepth + (currentBarrelSprite.Depth - item.Sprite.Depth));
float chargeRatio = currentChargeTime / MaxChargeTime;
@@ -702,12 +705,14 @@ namespace Barotrauma.Items.Components
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
{
base.DrawHUD(spriteBatch, character);
if (HudTint.A > 0)
{
GUI.DrawRectangle(spriteBatch, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight),
new Color(HudTint.R, HudTint.G, HudTint.B) * (HudTint.A / 255.0f), true);
}
GetAvailablePower(out float batteryCharge, out float batteryCapacity);
List<Item> availableAmmo = new List<Item>();