(f0d812055) v0.9.9.0

This commit is contained in:
Joonas Rikkonen
2020-04-23 19:19:37 +03:00
parent b647059b93
commit ac37a3b0e4
391 changed files with 15054 additions and 5420 deletions
@@ -43,6 +43,7 @@ namespace Barotrauma
public Vector2[] SlotPositions;
public static Point SlotSize;
public static int Spacing;
public static int HideButtonWidth;
private Layout layout;
public Layout CurrentLayout
@@ -71,22 +72,44 @@ namespace Barotrauma
{
get { return personalSlotArea; }
}
private GUIImage[] indicators = new GUIImage[5];
private int[] indicatorIndexes = new int[5];
private Vector2 indicatorSpriteSize;
private GUILayoutGroup indicatorGroup;
partial void InitProjSpecific(XElement element)
{
Hidden = true;
hideButton = new GUIButton(new RectTransform(new Point((int)(30 * GUI.Scale), (int)(60 * GUI.Scale)), GUI.Canvas)
hideButton = new GUIButton(new RectTransform(new Point((int)(31f * (HUDLayoutSettings.BottomRightInfoArea.Height / 100f)), HUDLayoutSettings.BottomRightInfoArea.Height), GUI.Canvas)
{ AbsoluteOffset = HUDLayoutSettings.CrewArea.Location },
"", style: "UIToggleButton");
hideButton.Children.ForEach(c => c.SpriteEffects = SpriteEffects.FlipHorizontally);
"", style: "EquipmentToggleButton");
indicatorGroup = new GUILayoutGroup(new RectTransform(Point.Zero, hideButton.RectTransform)) { IsHorizontal = false };
indicatorGroup.ChildAnchor = Anchor.TopCenter;
indicatorSpriteSize = GUI.Style.GetComponentStyle("EquipmentIndicatorDivingSuit").Sprites[GUIComponent.ComponentState.None][0].Sprite.size;
indicators[0] = new GUIImage(new RectTransform(Point.Zero, indicatorGroup.RectTransform), "EquipmentIndicatorDivingSuit");
indicators[1] = new GUIImage(new RectTransform(Point.Zero, indicatorGroup.RectTransform), "EquipmentIndicatorID");
indicators[2] = new GUIImage(new RectTransform(Point.Zero, indicatorGroup.RectTransform), "EquipmentIndicatorOutfit");
indicators[3] = new GUIImage(new RectTransform(Point.Zero, indicatorGroup.RectTransform), "EquipmentIndicatorHeadwear");
indicators[4] = new GUIImage(new RectTransform(Point.Zero, indicatorGroup.RectTransform), "EquipmentIndicatorHeadphones");
indicatorIndexes[0] = FindLimbSlot(InvSlotType.OuterClothes);
indicatorIndexes[1] = FindLimbSlot(InvSlotType.Card);
indicatorIndexes[2] = FindLimbSlot(InvSlotType.InnerClothes);
indicatorIndexes[3] = FindLimbSlot(InvSlotType.Head);
indicatorIndexes[4] = FindLimbSlot(InvSlotType.Headset);
for (int i = 0; i < indicators.Length; i++)
{
indicators[i].CanBeFocused = false;
}
hideButton.OnClicked += (GUIButton btn, object userdata) =>
{
hidePersonalSlots = !hidePersonalSlots;
foreach (GUIComponent child in btn.Children)
{
child.SpriteEffects = hidePersonalSlots ? SpriteEffects.None : SpriteEffects.FlipHorizontally;
}
return true;
};
@@ -245,6 +268,26 @@ namespace Barotrauma
return false;
}
private void SetIndicatorSizes()
{
indicatorGroup.RectTransform.AbsoluteOffset = new Point((int)Math.Round(4 * GUI.Scale), (int)Math.Round(7 * GUI.Scale));
indicatorGroup.RectTransform.NonScaledSize = new Point(hideButton.Rect.Width - indicatorGroup.RectTransform.AbsoluteOffset.X * 2, hideButton.Rect.Height - indicatorGroup.RectTransform.AbsoluteOffset.Y * 2);
indicatorGroup.AbsoluteSpacing = (int)Math.Ceiling(2 * GUI.Scale);
int indicatorHeight = (indicatorGroup.RectTransform.NonScaledSize.Y - indicatorGroup.AbsoluteSpacing * (indicators.Length - 1)) / indicators.Length;
int indicatorWidth = (int)(indicatorSpriteSize.X / (indicatorSpriteSize.Y / indicatorHeight));
if (HideButtonWidth % 2 != indicatorWidth % 2) indicatorWidth++;
Point indicatorSize = new Point(indicatorWidth, indicatorHeight);
for (int i = 0; i < indicators.Length; i++)
{
indicators[i].RectTransform.NonScaledSize = indicatorSize;
}
}
private void SetSlotPositions(Layout layout)
{
bool isFourByThree = GUI.IsFourByThree();
@@ -257,6 +300,8 @@ namespace Barotrauma
Spacing = (int)(8 * UIScale);
}
HideButtonWidth = (int)(31f * (HUDLayoutSettings.BottomRightInfoArea.Height / 100f));
SlotSize = !isFourByThree ? (SlotSpriteSmall.size * UIScale).ToPoint() : (SlotSpriteSmall.size * UIScale * .925f).ToPoint();
int bottomOffset = SlotSize.Y + Spacing * 2 + ContainedIndicatorHeight;
@@ -272,8 +317,7 @@ namespace Barotrauma
int normalSlotCount = SlotTypes.Count(s => !PersonalSlots.HasFlag(s));
int x = GameMain.GraphicsWidth / 2 - normalSlotCount * (SlotSize.X + Spacing) / 2;
int upperX = HUDLayoutSettings.BottomRightInfoArea.X - Spacing * 2 - SlotSize.X - SlotSize.X / 2;
//int upperX = GameMain.GraphicsWidth - personalSlotCount * (slotSize.X + spacing) + (int)(11 * GUI.Scale) + spacing;
int upperX = HUDLayoutSettings.BottomRightInfoArea.X - SlotSize.X - Spacing * 4 - HideButtonWidth;
//make sure the rightmost normal slot doesn't overlap with the personal slots
x -= Math.Max((x + normalSlotCount * (SlotSize.X + Spacing)) - (upperX - personalSlotCount * (SlotSize.X + Spacing)), 0);
@@ -300,11 +344,11 @@ namespace Barotrauma
if (hideButtonSlotIndex > -1)
{
hideButton.RectTransform.SetPosition(Anchor.TopLeft, Pivot.TopLeft);
hideButton.RectTransform.NonScaledSize = new Point(SlotSize.X / 2, HUDLayoutSettings.BottomRightInfoArea.Height);
hideButton.RectTransform.AbsoluteOffset = new Point(
personalSlotArea.Right + Spacing,
HUDLayoutSettings.BottomRightInfoArea.Y);
hideButton.RectTransform.NonScaledSize = new Point(HideButtonWidth, HUDLayoutSettings.BottomRightInfoArea.Height);
hideButton.RectTransform.AbsoluteOffset = new Point(HUDLayoutSettings.BottomRightInfoArea.Left - HideButtonWidth + GUI.IntScaleCeiling(2f), HUDLayoutSettings.BottomRightInfoArea.Y + GUI.IntScaleCeiling(1f));
hideButton.Visible = true;
SetIndicatorSizes();
}
}
break;
@@ -447,7 +491,7 @@ namespace Barotrauma
((selectedSlot != null && selectedSlot.IsSubSlot) || (draggingItem != null && (draggingSlot == null || !draggingSlot.MouseOn())));
if (CharacterHealth.OpenHealthWindow != null) hoverOnInventory = true;
if (layout == Layout.Default)
if (layout == Layout.Default && (Screen.Selected != GameMain.SubEditorScreen || Screen.Selected is SubEditorScreen editor && editor.WiringMode))
{
if (hideButton.Visible)
{
@@ -457,7 +501,8 @@ namespace Barotrauma
hidePersonalSlotsState = hidePersonalSlots ?
Math.Min(hidePersonalSlotsState + deltaTime * 5.0f, 1.0f) :
Math.Max(hidePersonalSlotsState - deltaTime * 5.0f, 0.0f);
bool personalSlotsMoving = hidePersonalSlotsState > 0 && hidePersonalSlotsState < 1f;
for (int i = 0; i < slots.Length; i++)
{
if (!PersonalSlots.HasFlag(SlotTypes[i])) { continue; }
@@ -466,6 +511,7 @@ namespace Barotrauma
if (selectedSlot?.Slot == slots[i]) { selectedSlot = null; }
highlightedSubInventorySlots.RemoveWhere(s => s.Slot == slots[i]);
}
slots[i].IsMoving = personalSlotsMoving;
slots[i].DrawOffset = Vector2.Lerp(Vector2.Zero, new Vector2(personalSlotArea.Width, 0.0f), hidePersonalSlotsState);
}
}
@@ -538,6 +584,19 @@ namespace Barotrauma
}
}
}
// In sub editor we cannot hover over the slot because they are not rendered so we override it here
if (Screen.Selected is SubEditorScreen subEditor && !subEditor.WiringMode)
{
for (int i = 0; i < slots.Length; i++)
{
var subInventory = GetSubInventory(i);
if (subInventory != null)
{
ShowSubInventory(new SlotReference(this, slots[i], i, false, Items[i].GetComponent<ItemContainer>().Inventory), deltaTime, cam, hideSubInventories, true);
}
}
}
foreach (var subInventorySlot in hideSubInventories)
{
@@ -551,6 +610,8 @@ namespace Barotrauma
if (character == Character.Controlled && character.SelectedCharacter == null) // Permanently open subinventories only available when the default UI layout is in use -> not when grabbing characters
{
UpdateEquipmentIndicators();
//remove the highlighted slots of other characters' inventories when not grabbing anyone
highlightedSubInventorySlots.RemoveWhere(s => s.ParentInventory != this && s.ParentInventory?.Owner is Character);
@@ -651,6 +712,39 @@ namespace Barotrauma
}
}
}
private void UpdateEquipmentIndicators()
{
for (int i = 0; i < indicators.Length; i++)
{
Item item = Items[indicatorIndexes[i]];
if (item != null)
{
Wearable wearable = item.GetComponent<Wearable>();
if (wearable != null && wearable.DisplayContainedStatus)
{
float conditionPercentage = item.GetContainedItemConditionPercentage();
if (conditionPercentage != -1)
{
indicators[i].Color = ToolBox.GradientLerp(conditionPercentage, GUI.Style.EquipmentIndicatorRunningOut, GUI.Style.EquipmentIndicatorEquipped);
}
else
{
indicators[i].Color = GUI.Style.EquipmentIndicatorRunningOut;
}
}
else
{
indicators[i].Color = GUI.Style.EquipmentIndicatorEquipped;
}
}
else
{
indicators[i].Color = GUI.Style.EquipmentIndicatorNotEquipped;
}
}
}
private void ShowSubInventory(SlotReference slotRef, float deltaTime, Camera cam, List<SlotReference> hideSubInventories, bool isEquippedSubInventory)
{
@@ -771,7 +865,7 @@ namespace Barotrauma
{
return QuickUseAction.TakeFromCharacter;
}
else if (character.SelectedItems.Any(i => i?.OwnInventory != null && i.OwnInventory.CanBePut(item)))
else if (character.SelectedItems.Any(i => i?.OwnInventory != null && i.OwnInventory.CanBePut(item)) && allowInventorySwap)
{
return QuickUseAction.PutToEquippedItem;
}
@@ -799,13 +893,40 @@ namespace Barotrauma
private void QuickUseItem(Item item, bool allowEquip, bool allowInventorySwap, bool allowApplyTreatment)
{
if (Screen.Selected is SubEditorScreen editor && !editor.WiringMode && !Submarine.Unloading)
{
// Find the slot the item was contained in and flash it
if (item.ParentInventory?.slots != null)
{
var invSlots = item.ParentInventory.slots;
var invItems = item.ParentInventory.Items;
for (int i = 0; i < invSlots.Length; i++)
{
if (i < 0 || invSlots.Length <= i || i < 0 || invItems.Length <= i) { break; }
var slot = invSlots[i];
var slotItem = invItems[i];
if (slotItem == item)
{
slot.ShowBorderHighlight(GUI.Style.Red, 0.1f, 0.4f);
GUI.PlayUISound(GUISoundType.PickItem);
break;
}
}
}
item.Remove();
return;
}
var quickUseAction = GetQuickUseAction(item, allowEquip, allowInventorySwap, allowApplyTreatment);
bool success = false;
switch (quickUseAction)
{
case QuickUseAction.Equip:
//attempt to put in a free slot first
for (int i = 0; i < capacity; i++)
for (int i = capacity - 1; i >= 0; i--)
{
if (Items[i] != null) continue;
if (SlotTypes[i] == InvSlotType.Any || !item.AllowedSlots.Any(a => a.HasFlag(SlotTypes[i]))) continue;
@@ -815,7 +936,7 @@ namespace Barotrauma
if (!success)
{
for (int i = 0; i < capacity; i++)
for (int i = capacity - 1; i >= 0; i--)
{
if (SlotTypes[i] == InvSlotType.Any || !item.AllowedSlots.Any(a => a.HasFlag(SlotTypes[i]))) continue;
//something else already equipped in the slot, attempt to unequip it
@@ -964,7 +1085,7 @@ namespace Barotrauma
if (limbSlotIcons.ContainsKey(SlotTypes[i]))
{
var icon = limbSlotIcons[SlotTypes[i]];
icon.Draw(spriteBatch, slots[i].Rect.Center.ToVector2() + slots[i].DrawOffset, GUIColorSettings.EquipmentSlotIconColor, origin: icon.size / 2, scale: slots[i].Rect.Width / icon.size.X);
icon.Draw(spriteBatch, slots[i].Rect.Center.ToVector2() + slots[i].DrawOffset, GUI.Style.EquipmentSlotIconColor, origin: icon.size / 2, scale: slots[i].Rect.Width / icon.size.X);
}
continue;
}
@@ -52,10 +52,14 @@ namespace Barotrauma.Items.Components
get { return sounds.Count > 0; }
}
private bool[] hasSoundsOfType;
private Dictionary<ActionType, List<ItemSound>> sounds;
private readonly bool[] hasSoundsOfType;
private readonly Dictionary<ActionType, List<ItemSound>> sounds;
private Dictionary<ActionType, SoundSelectionMode> soundSelectionModes;
protected float correctionTimer;
public float IsActiveTimer;
public GUILayoutSettings DefaultLayout { get; protected set; }
public GUILayoutSettings AlternativeLayout { get; protected set; }
@@ -230,20 +234,23 @@ namespace Barotrauma.Items.Components
if (loopingSound != null)
{
float targetGain = 0.0f;
if (Vector3.DistanceSquared(GameMain.SoundManager.ListenerPosition, new Vector3(item.WorldPosition, 0.0f)) > loopingSound.Range * loopingSound.Range ||
(targetGain = GetSoundVolume(loopingSound)) <= 0.0001f)
(GetSoundVolume(loopingSound)) <= 0.0001f)
{
if (loopingSoundChannel != null)
{
loopingSoundChannel.FadeOutAndDispose(); loopingSoundChannel = null;
loopingSoundChannel.FadeOutAndDispose();
loopingSoundChannel = null;
loopingSound = null;
}
return;
}
if (loopingSoundChannel != null && loopingSoundChannel.Sound != loopingSound.RoundSound.Sound)
{
loopingSoundChannel.FadeOutAndDispose(); loopingSoundChannel = null;
loopingSoundChannel.FadeOutAndDispose();
loopingSoundChannel = null;
loopingSound = null;
}
if (loopingSoundChannel == null || !loopingSoundChannel.IsPlaying)
{
@@ -258,8 +265,7 @@ namespace Barotrauma.Items.Components
}
return;
}
ItemSound itemSound = null;
var matchingSounds = sounds[type];
if (loopingSoundChannel == null || !loopingSoundChannel.IsPlaying)
{
@@ -277,7 +283,7 @@ namespace Barotrauma.Items.Components
{
foreach (ItemSound sound in matchingSounds)
{
PlaySound(sound, item.WorldPosition, user);
PlaySound(sound, item.WorldPosition);
}
return;
}
@@ -286,13 +292,12 @@ namespace Barotrauma.Items.Components
index = Rand.Int(matchingSounds.Count);
}
itemSound = matchingSounds[index];
PlaySound(matchingSounds[index], item.WorldPosition, user);
PlaySound(matchingSounds[index], item.WorldPosition);
}
}
private void PlaySound(ItemSound itemSound, Vector2 position, Character user = null)
private void PlaySound(ItemSound itemSound, Vector2 position)
{
if (Vector2.DistanceSquared(new Vector2(GameMain.SoundManager.ListenerPosition.X, GameMain.SoundManager.ListenerPosition.Y), position) > itemSound.Range * itemSound.Range)
{
@@ -301,8 +306,7 @@ namespace Barotrauma.Items.Components
if (itemSound.Loop)
{
loopingSound = itemSound;
if (loopingSoundChannel != null && loopingSoundChannel.Sound != loopingSound.RoundSound.Sound)
if (loopingSoundChannel != null && loopingSoundChannel.Sound != itemSound.RoundSound.Sound)
{
loopingSoundChannel.FadeOutAndDispose(); loopingSoundChannel = null;
}
@@ -310,6 +314,7 @@ namespace Barotrauma.Items.Components
{
float volume = GetSoundVolume(itemSound);
if (volume <= 0.0001f) { return; }
loopingSound = itemSound;
loopingSoundChannel = loopingSound.RoundSound.Sound.Play(
new Vector3(position.X, position.Y, 0.0f),
0.01f,
@@ -3,11 +3,17 @@ using Barotrauma.Lights;
using Barotrauma.Networking;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System.Collections.Generic;
namespace Barotrauma.Items.Components
{
partial class LightComponent : Powered, IServerSerializable, IDrawableComponent
{
private bool? lastReceivedState;
private CoroutineHandle resetPredictionCoroutine;
private float resetPredictionTimer;
public Vector2 DrawSize
{
get { return new Vector2(light.Range * 2, light.Range * 2); }
@@ -32,6 +38,12 @@ namespace Barotrauma.Items.Components
light.Color = LightColor.Multiply(brightness);
}
public override void OnItemLoaded()
{
base.OnItemLoaded();
SetLightSourceState(IsActive, lightBrightness);
}
public void Draw(SpriteBatch spriteBatch, bool editing = false, float itemDepth = -1)
{
if (light.LightSprite != null && (item.body == null || item.body.Enabled) && lightBrightness > 0.0f && IsOn)
@@ -49,9 +61,36 @@ namespace Barotrauma.Items.Components
}
}
partial void OnStateChanged()
{
if (GameMain.Client == null || !lastReceivedState.HasValue) { return; }
//reset to last known server state after the state hasn't changed in 1.0 seconds client-side
resetPredictionTimer = 1.0f;
if (resetPredictionCoroutine == null || !CoroutineManager.IsCoroutineRunning(resetPredictionCoroutine))
{
resetPredictionCoroutine = CoroutineManager.StartCoroutine(ResetPredictionAfterDelay());
}
}
/// <summary>
/// Reset client-side prediction of the light's state to the last known state sent by the server after resetPredictionTimer runs out
/// </summary>
private IEnumerable<object> ResetPredictionAfterDelay()
{
while (resetPredictionTimer > 0.0f)
{
resetPredictionTimer -= CoroutineManager.DeltaTime;
yield return CoroutineStatus.Running;
}
if (lastReceivedState.HasValue) { IsActive = lastReceivedState.Value; }
resetPredictionCoroutine = null;
yield return CoroutineStatus.Success;
}
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
{
IsOn = msg.ReadBoolean();
IsActive = msg.ReadBoolean();
lastReceivedState = IsActive;
}
protected override void RemoveComponentSpecific()
@@ -140,11 +140,11 @@ namespace Barotrauma.Items.Components
var inputArea = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 1f), bottomFrame.RectTransform, Anchor.BottomCenter), isHorizontal: true, childAnchor: Anchor.BottomLeft);
// === INPUT SLOTS === //
inputInventoryHolder = new GUIFrame(new RectTransform(new Vector2(0.8f, 1f), inputArea.RectTransform), style: null);
inputInventoryHolder = new GUIFrame(new RectTransform(new Vector2(0.7f, 1f), inputArea.RectTransform), style: null);
new GUICustomComponent(new RectTransform(Vector2.One, inputInventoryHolder.RectTransform), DrawInputOverLay) { CanBeFocused = false };
// === ACTIVATE BUTTON === //
var buttonFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.2f, 0.8f), inputArea.RectTransform), childAnchor: Anchor.CenterRight);
var buttonFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.3f, 0.8f), inputArea.RectTransform), childAnchor: Anchor.CenterRight);
activateButton = new GUIButton(new RectTransform(new Vector2(1f, 0.6f), buttonFrame.RectTransform),
TextManager.Get("FabricatorCreate"), style: "DeviceButton")
{
@@ -356,6 +356,8 @@ namespace Barotrauma.Items.Components
private void DrawOutputOverLay(SpriteBatch spriteBatch, GUICustomComponent overlayComponent)
{
overlayComponent.RectTransform.SetAsLastChild();
if (outputContainer.Inventory.Items.First() != null) { return; }
FabricationRecipe targetItem = fabricatedItem ?? selectedItem;
if (targetItem != null)
@@ -91,6 +91,7 @@ namespace Barotrauma.Items.Components
if ((item.Submarine == null && displayedSubs.Count > 0) || //item not inside a sub anymore, but display is still showing subs
!displayedSubs.Contains(item.Submarine) || //current sub not displayer
item.Submarine.DockedTo.Any(s => !displayedSubs.Contains(s)) || //some of the docked subs not diplayed
!submarineContainer.Children.Any() || // We lack a GUI
displayedSubs.Any(s => s != item.Submarine && !item.Submarine.DockedTo.Contains(s))) //displaying a sub that shouldn't be displayed
{
CreateHUD();
@@ -116,21 +117,23 @@ namespace Barotrauma.Items.Components
private void DrawHUDFront(SpriteBatch spriteBatch, GUICustomComponent container)
{
if (Voltage < MinVoltage)
{
{
Vector2 textSize = GUI.Font.MeasureString(noPowerTip);
Vector2 textPos = GuiFrame.Rect.Center.ToVector2();
GUI.DrawString(spriteBatch, textPos - textSize / 2, noPowerTip,
GUI.Style.Orange * (float)Math.Abs(Math.Sin(Timing.TotalTime)), Color.Black * 0.8f, font: GUI.SubHeadingFont);
GUI.Style.Orange * (float)Math.Abs(Math.Sin(Timing.TotalTime)), Color.Black * 0.8f, font: GUI.SubHeadingFont);
return;
}
if (!submarineContainer.Children.Any()) { return; }
foreach (GUIComponent child in submarineContainer.Children.First().Children)
{
if (child.UserData is Hull hull)
{
if (hull.Submarine == null || !hull.Submarine.IsOutpost) { continue; }
string text = TextManager.GetWithVariable("MiniMapOutpostDockingInfo", "[outpost]", hull.Submarine.Name);
if (hull.Submarine == null || !hull.Submarine.Info.IsOutpost) { continue; }
string text = TextManager.GetWithVariable("MiniMapOutpostDockingInfo", "[outpost]", hull.Submarine.Info.Name);
Vector2 textSize = GUI.Font.MeasureString(text);
Vector2 textPos = child.Center;
if (textPos.X + textSize.X / 2 > submarineContainer.Rect.Right)
@@ -151,7 +154,7 @@ namespace Barotrauma.Items.Components
foreach (Hull hull in Hull.hullList)
{
var hullFrame = submarineContainer.Children.First().FindChild(hull);
var hullFrame = submarineContainer.Children.FirstOrDefault()?.FindChild(hull);
if (hullFrame == null) { continue; }
if (GUI.MouseOn == hullFrame || hullFrame.IsParentOf(GUI.MouseOn))
@@ -175,7 +178,7 @@ namespace Barotrauma.Items.Components
foreach (Hull hull in Hull.hullList)
{
if (hull.Submarine == null) continue;
var hullFrame = submarineContainer.Children.First().FindChild(hull);
var hullFrame = submarineContainer.Children.FirstOrDefault()?.FindChild(hull);
if (hullFrame == null) continue;
hullDatas.TryGetValue(hull, out HullData hullData);
@@ -99,6 +99,10 @@ namespace Barotrauma.Items.Components
Step = 0.05f,
OnMoved = (GUIScrollBar scrollBar, float barScroll) =>
{
if (pumpSpeedLockTimer <= 0.0f)
{
targetLevel = null;
}
float newValue = barScroll * 200.0f - 100.0f;
if (Math.Abs(newValue - FlowPercentage) < 0.1f) { return false; }
@@ -192,9 +192,10 @@ namespace Barotrauma.Items.Components
{
RelativeOffset = new Vector2(0, fissionMeter.RectTransform.RelativeOffset.Y + meterSize.Y)
},
style: "DeviceSlider", barSize: 0.1f)
style: "DeviceSlider", barSize: 0.15f)
{
Enabled = false,
Step = 1.0f / 255,
OnMoved = (GUIScrollBar bar, float scrollAmount) =>
{
LastUser = Character.Controlled;
@@ -209,9 +210,10 @@ namespace Barotrauma.Items.Components
{
RelativeOffset = new Vector2(0, turbineMeter.RectTransform.RelativeOffset.Y + meterSize.Y)
},
style: "DeviceSlider", barSize: 0.1f, isHorizontal: true)
style: "DeviceSlider", barSize: 0.15f, isHorizontal: true)
{
Enabled = false,
Step = 1.0f / 255,
OnMoved = (GUIScrollBar bar, float scrollAmount) =>
{
LastUser = Character.Controlled;
@@ -715,8 +717,14 @@ namespace Barotrauma.Items.Components
targetTurbineOutput = msg.ReadRangedSingle(0.0f, 100.0f, 8);
degreeOfSuccess = msg.ReadRangedSingle(0.0f, 1.0f, 8);
FissionRateScrollBar.BarScroll = targetFissionRate / 100.0f;
TurbineOutputScrollBar.BarScroll = targetTurbineOutput / 100.0f;
if (Math.Abs(FissionRateScrollBar.BarScroll - targetFissionRate / 100.0f) > 0.01f)
{
FissionRateScrollBar.BarScroll = targetFissionRate / 100.0f;
}
if (Math.Abs(TurbineOutputScrollBar.BarScroll - targetTurbineOutput / 100.0f) > 0.01f)
{
TurbineOutputScrollBar.BarScroll = targetTurbineOutput / 100.0f;
}
IsActive = true;
}
@@ -490,6 +490,7 @@ namespace Barotrauma.Items.Components
disruptedDirections.Clear();
foreach (AITarget t in AITarget.List)
{
if (t.Entity is Character c && c.Params.HideInSonar) { continue; }
if (t.SoundRange <= 0.0f || float.IsNaN(t.SoundRange) || float.IsInfinity(t.SoundRange)) { continue; }
float distSqr = Vector2.DistanceSquared(t.WorldPosition, transducerCenter);
@@ -647,6 +648,8 @@ namespace Barotrauma.Items.Components
if (GameMain.GameSession == null) { return; }
if (Level.Loaded == null) { return; }
DrawMarker(spriteBatch,
GameMain.GameSession.StartLocation.Name,
"outpost",
@@ -699,8 +702,8 @@ namespace Barotrauma.Items.Components
if (sub.WorldPosition.Y > Level.Loaded.Size.Y) { continue; }
DrawMarker(spriteBatch,
sub.Name,
sub.HasTag(SubmarineTag.Shuttle) ? "shuttle" : "submarine",
sub.Info.DisplayName,
sub.Info.HasTag(SubmarineTag.Shuttle) ? "shuttle" : "submarine",
sub.WorldPosition - transducerCenter,
displayScale, center, DisplayRadius * 0.95f);
}
@@ -799,8 +802,11 @@ namespace Barotrauma.Items.Components
{
if (Level.Loaded != null && dockingPort.Item.Submarine.WorldPosition.Y > Level.Loaded.Size.Y) { continue; }
if (dockingPort.Item.Submarine == null) { continue; }
if (dockingPort.Item.Submarine.Info.IsWreck) { continue; }
//don't show the docking ports of the opposing team on the sonar
if (item.Submarine != null && dockingPort.Item.Submarine != null)
if (item.Submarine != null)
{
if ((dockingPort.Item.Submarine.TeamID == Character.TeamType.Team1 && item.Submarine.TeamID == Character.TeamType.Team2) ||
(dockingPort.Item.Submarine.TeamID == Character.TeamType.Team2 && item.Submarine.TeamID == Character.TeamType.Team1))
@@ -1125,6 +1131,7 @@ namespace Barotrauma.Items.Components
foreach (Character c in Character.CharacterList)
{
if (c.AnimController.CurrentHull != null || !c.Enabled) { continue; }
if (c.Params.HideInSonar) { continue; }
if (DetectSubmarineWalls && c.AnimController.CurrentHull == null && item.CurrentHull != null) { continue; }
if (c.AnimController.SimplePhysicsEnabled)
@@ -46,6 +46,8 @@ namespace Barotrauma.Items.Components
private float checkConnectedPortsTimer;
private const float CheckConnectedPortsInterval = 1.0f;
public DockingPort ActiveDockingSource, DockingTarget;
private Vector2 keyboardInput = Vector2.Zero;
private float inputCumulation;
@@ -665,7 +667,7 @@ namespace Barotrauma.Items.Components
if (Vector2.DistanceSquared(PlayerInput.MousePosition, steerArea.Rect.Center.ToVector2()) < steerRadius * steerRadius)
{
if (PlayerInput.PrimaryMouseButtonHeld() && !CrewManager.IsCommandInterfaceOpen && !GameSession.IsInfoFrameOpen)
if (PlayerInput.PrimaryMouseButtonHeld() && !CrewManager.IsCommandInterfaceOpen && !GameSession.IsTabMenuOpen)
{
Vector2 displaySubPos = (-sonar.DisplayOffset * sonar.Zoom) / sonar.Range * sonar.DisplayRadius * sonar.Zoom;
displaySubPos.Y = -displaySubPos.Y;
@@ -0,0 +1,76 @@
using Barotrauma.Networking;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Xml.Linq;
namespace Barotrauma.Items.Components
{
partial class Projectile : ItemComponent
{
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
{
bool isStuck = msg.ReadBoolean();
if (isStuck)
{
ushort submarineID = msg.ReadUInt16();
ushort hullID = msg.ReadUInt16();
Vector2 simPosition = new Vector2(
msg.ReadSingle(),
msg.ReadSingle());
Vector2 axis = new Vector2(
msg.ReadSingle(),
msg.ReadSingle());
UInt16 entityID = msg.ReadUInt16();
Entity entity = Entity.FindEntityByID(entityID);
Submarine submarine = Entity.FindEntityByID(submarineID) as Submarine;
Hull hull = Entity.FindEntityByID(hullID) as Hull;
item.Submarine = submarine;
item.CurrentHull = hull;
item.body.SetTransform(simPosition, item.body.Rotation);
if (entity is Character character)
{
byte limbIndex = msg.ReadByte();
if (limbIndex >= character.AnimController.Limbs.Length)
{
DebugConsole.ThrowError($"Failed to read a projectile update from the server. Limb index out of bounds ({limbIndex}, character: {character.ToString()})");
return;
}
if (character.Removed) { return; }
var limb = character.AnimController.Limbs[limbIndex];
StickToTarget(limb.body.FarseerBody, axis);
}
else if (entity is Structure structure)
{
byte bodyIndex = msg.ReadByte();
if (bodyIndex == 255) { bodyIndex = 0; }
if (bodyIndex >= structure.Bodies.Count)
{
DebugConsole.ThrowError($"Failed to read a projectile update from the server. Structure body index out of bounds ({bodyIndex}, structure: {structure.ToString()})");
return;
}
var body = structure.Bodies[bodyIndex];
StickToTarget(body, axis);
}
else if (entity is Item item)
{
if (item.Removed) { return; }
StickToTarget(item.body.FarseerBody, axis);
}
else if (entity is Submarine sub)
{
StickToTarget(sub.PhysicsBody.FarseerBody, axis);
}
else
{
DebugConsole.ThrowError($"Failed to read a projectile update from the server. Invalid stick target ({entity?.ToString() ?? "null"}, {entityID})");
}
}
else
{
Unstick();
}
}
}
}
@@ -117,9 +117,18 @@ namespace Barotrauma.Items.Components
case "emitter":
case "particleemitter":
particleEmitters.Add(new ParticleEmitter(subElement));
particleEmitterConditionRanges.Add(new Vector2(
subElement.GetAttributeFloat("mincondition", 0.0f),
subElement.GetAttributeFloat("maxcondition", 100.0f)));
float minCondition = subElement.GetAttributeFloat("mincondition", 0.0f);
float maxCondition = subElement.GetAttributeFloat("maxcondition", 100.0f);
if (maxCondition < minCondition)
{
DebugConsole.ThrowError("Invalid damage particle configuration in the Repairable component of " + item.Name + ". MaxCondition needs to be larger than MinCondition.");
float temp = maxCondition;
maxCondition = minCondition;
minCondition = temp;
}
particleEmitterConditionRanges.Add(new Vector2(minCondition, maxCondition));
break;
}
}
@@ -236,15 +245,7 @@ namespace Barotrauma.Items.Components
DeteriorateAlways = msg.ReadBoolean();
ushort currentFixerID = msg.ReadUInt16();
currentFixerAction = (FixActions)msg.ReadRangedInteger(0, 2);
if (currentFixerID == 0)
{
CurrentFixer = null;
}
else
{
CurrentFixer = Entity.FindEntityByID(currentFixerID) as Character;
}
CurrentFixer = currentFixerID != 0 ? Entity.FindEntityByID(currentFixerID) as Character : null;
}
public void ClientWrite(IWriteMessage msg, object[] extraData = null)
@@ -0,0 +1,172 @@
using Barotrauma.Networking;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Xml.Linq;
namespace Barotrauma.Items.Components
{
partial class Rope : ItemComponent, IDrawableComponent
{
private Sprite sprite, startSprite, endSprite;
[Serialize(5, false)]
public int SpriteWidth
{
get;
set;
}
[Serialize("255,255,255,255", false)]
public Color SpriteColor
{
get;
set;
}
[Serialize(false, false)]
public bool Tile
{
get;
set;
}
public Vector2 DrawSize
{
get
{
if (target == null || source == null) { return Vector2.Zero; }
return new Vector2(
Math.Abs(target.DrawPosition.X - source.DrawPosition.X),
Math.Abs(target.DrawPosition.Y - source.DrawPosition.Y)) * 1.5f;
}
}
partial void InitProjSpecific(XElement element)
{
foreach (XElement subElement in element.Elements())
{
switch (subElement.Name.ToString().ToLowerInvariant())
{
case "sprite":
sprite = new Sprite(subElement);
break;
case "startsprite":
startSprite = new Sprite(subElement);
break;
case "endsprite":
endSprite = new Sprite(subElement);
break;
}
}
}
public void Draw(SpriteBatch spriteBatch, bool editing, float itemDepth = -1)
{
if (target == null) { return; }
Vector2 startPos = new Vector2(source.DrawPosition.X, -source.DrawPosition.Y);
var turret = source?.GetComponent<Turret>();
if (turret != null)
{
startPos = new Vector2(source.WorldRect.X + turret.TransformedBarrelPos.X, -(source.WorldRect.Y - turret.TransformedBarrelPos.Y));
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;
}
}
Vector2 endPos = new Vector2(target.DrawPosition.X, -target.DrawPosition.Y);
if (Snapped)
{
float snapState = 1.0f - snapTimer / SnapAnimDuration;
Vector2 diff = target.DrawPosition - source.DrawPosition;
diff.Y = -diff.Y;
int width = (int)(SpriteWidth * snapState);
if (width > 0.0f)
{
DrawRope(spriteBatch, endPos - diff * snapState * 0.5f, endPos, width);
DrawRope(spriteBatch, startPos, startPos + diff * snapState * 0.5f, width);
}
}
else
{
DrawRope(spriteBatch, startPos, endPos, SpriteWidth);
}
if (startSprite != null || endSprite != null)
{
Vector2 dir = endPos - startPos;
float angle = (float)Math.Atan2(dir.Y, dir.X);
if (startSprite != null)
{
float depth = Math.Min(item.GetDrawDepth() + (startSprite.Depth - item.Sprite.Depth), 0.999f);
startSprite?.Draw(spriteBatch, startPos, SpriteColor, angle, depth: depth);
}
if (endSprite != null)
{
float depth = Math.Min(item.GetDrawDepth() + (endSprite.Depth - item.Sprite.Depth), 0.999f);
endSprite?.Draw(spriteBatch, endPos, SpriteColor, angle, depth: depth);
}
}
}
private void DrawRope(SpriteBatch spriteBatch, Vector2 startPos, Vector2 endPos, int width)
{
float depth = sprite == null ?
item.Sprite.Depth + 0.001f :
Math.Min(item.GetDrawDepth() + (sprite.Depth - item.Sprite.Depth), 0.999f);
if (sprite?.Texture == null)
{
GUI.DrawLine(spriteBatch,
startPos,
endPos,
SpriteColor, depth: depth, width: width);
return;
}
if (Tile)
{
float length = Vector2.Distance(startPos, endPos);
Vector2 dir = (endPos - startPos) / length;
float x;
for (x = 0.0f; x <= length - sprite.size.X; x += sprite.size.X)
{
GUI.DrawLine(spriteBatch, sprite,
startPos + dir * (x - 5.0f),
startPos + dir * (x + sprite.size.X),
SpriteColor, depth: depth, width: width);
}
float leftOver = length - x;
if (leftOver > 0.0f)
{
GUI.DrawLine(spriteBatch, sprite,
startPos + dir * (x - 5.0f),
endPos,
SpriteColor, depth: depth, width: width);
}
}
else
{
GUI.DrawLine(spriteBatch, sprite,
startPos,
endPos,
SpriteColor, depth: depth, width: width);
}
}
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
{
snapped = msg.ReadBoolean();
}
protected override void RemoveComponentSpecific()
{
sprite?.Remove(); sprite = null;
startSprite?.Remove(); startSprite = null;
endSprite?.Remove(); endSprite = null;
}
}
}
@@ -45,13 +45,48 @@ namespace Barotrauma.Items.Components
float elementSize = Math.Min(1.0f / visibleElements.Count(), 1);
foreach (CustomInterfaceElement ciElement in visibleElements)
{
if (ciElement.ContinuousSignal)
if (!string.IsNullOrEmpty(ciElement.PropertyName))
{
var layoutGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, elementSize), uiElementContainer.RectTransform), isHorizontal: true)
{
RelativeSpacing = 0.02f,
UserData = ciElement
};
new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), layoutGroup.RectTransform),
TextManager.Get(ciElement.Label, returnNull: true) ?? ciElement.Label);
var textBox = new GUITextBox(new RectTransform(new Vector2(0.5f, 1.0f), layoutGroup.RectTransform), "", style: "GUITextBoxNoIcon")
{
OverflowClip = true,
UserData = ciElement
};
//reset size restrictions set by the Style to make sure the elements can fit the interface
textBox.RectTransform.MinSize = textBox.Frame.RectTransform.MinSize = new Point(0, 0);
textBox.RectTransform.MaxSize = textBox.Frame.RectTransform.MaxSize = new Point(int.MaxValue, int.MaxValue);
textBox.OnDeselected += (tb, key) =>
{
if (GameMain.Client == null)
{
TextChanged(tb.UserData as CustomInterfaceElement, textBox.Text);
}
else
{
item.CreateClientEvent(this);
}
};
textBox.OnEnterPressed += (tb, text) =>
{
tb.Deselect();
return true;
};
uiElements.Add(textBox);
}
else if (ciElement.ContinuousSignal)
{
var tickBox = new GUITickBox(new RectTransform(new Vector2(1.0f, elementSize), uiElementContainer.RectTransform)
{
MaxSize = ElementMaxSize
},
TextManager.Get(ciElement.Label, returnNull: true) ?? ciElement.Label)
}, TextManager.Get(ciElement.Label, returnNull: true) ?? ciElement.Label)
{
UserData = ciElement
};
@@ -148,7 +183,7 @@ namespace Barotrauma.Items.Components
foreach (var uiElement in uiElements)
{
if (!(uiElement.UserData is CustomInterfaceElement element)) { continue; }
bool visible = Screen.Selected == GameMain.SubEditorScreen || element.StatusEffects.Any() || (element.Connection != null && element.Connection.Wires.Any(w => w != null));
bool visible = Screen.Selected == GameMain.SubEditorScreen || element.StatusEffects.Any() || !string.IsNullOrEmpty(element.PropertyName) || (element.Connection != null && element.Connection.Wires.Any(w => w != null));
if (visible) { visibleElementCount++; }
if (uiElement.Visible != visible)
{
@@ -188,6 +223,22 @@ namespace Barotrauma.Items.Components
customInterfaceElementList[i].Label;
tickBox.TextBlock.Wrap = tickBox.Text.Contains(' ');
}
if (uiElements[i] is GUITextBox textBox)
{
var textBlock = textBox.Parent.GetChild<GUITextBlock>();
textBlock.Text = string.IsNullOrWhiteSpace(customInterfaceElementList[i].Label) ?
TextManager.GetWithVariable("connection.signaloutx", "[num]", (i + 1).ToString()) :
customInterfaceElementList[i].Label;
textBlock.Wrap = textBlock.Text.Contains(' ');
foreach (ISerializableEntity e in item.AllPropertyObjects)
{
if (e.SerializableProperties.ContainsKey(customInterfaceElementList[i].PropertyName))
{
textBox.Text = e.SerializableProperties[customInterfaceElementList[i].PropertyName].GetValue(e) as string;
}
}
}
}
uiElementContainer.Recalculate();
@@ -206,6 +257,10 @@ namespace Barotrauma.Items.Components
{
textBlocks.Add(tickBox.TextBlock);
}
else if (element is GUILayoutGroup)
{
textBlocks.Add(element.GetChild<GUITextBlock>());
}
}
uiElementContainer.Recalculate();
GUITextBlock.AutoScaleAndNormalize(textBlocks);
@@ -216,7 +271,11 @@ namespace Barotrauma.Items.Components
//extradata contains an array of buttons clicked by the player (or nothing if the player didn't click anything)
for (int i = 0; i < customInterfaceElementList.Count; i++)
{
if (customInterfaceElementList[i].ContinuousSignal)
if (!string.IsNullOrEmpty(customInterfaceElementList[i].PropertyName))
{
msg.Write(((GUITextBox)uiElements[i]).Text);
}
else if (customInterfaceElementList[i].ContinuousSignal)
{
msg.Write(((GUITickBox)uiElements[i]).Selected);
}
@@ -231,15 +290,22 @@ namespace Barotrauma.Items.Components
{
for (int i = 0; i < customInterfaceElementList.Count; i++)
{
bool elementState = msg.ReadBoolean();
if (customInterfaceElementList[i].ContinuousSignal)
if (!string.IsNullOrEmpty(customInterfaceElementList[i].PropertyName))
{
((GUITickBox)uiElements[i]).Selected = elementState;
TickBoxToggled(customInterfaceElementList[i], elementState);
TextChanged(customInterfaceElementList[i], msg.ReadString());
}
else if (elementState)
else
{
ButtonClicked(customInterfaceElementList[i]);
bool elementState = msg.ReadBoolean();
if (customInterfaceElementList[i].ContinuousSignal)
{
((GUITickBox)uiElements[i]).Selected = elementState;
TickBoxToggled(customInterfaceElementList[i], elementState);
}
else if (elementState)
{
ButtonClicked(customInterfaceElementList[i]);
}
}
}
}
@@ -56,15 +56,6 @@ namespace Barotrauma.Items.Components
};
}
public override void OnItemLoaded()
{
base.OnItemLoaded();
if (!string.IsNullOrEmpty(DisplayedWelcomeMessage))
{
ShowOnDisplay(DisplayedWelcomeMessage);
}
}
private void SendOutput(string input)
{
if (input.Length > MaxMessageLength)
@@ -123,6 +114,11 @@ namespace Barotrauma.Items.Components
public override void AddToGUIUpdateList()
{
base.AddToGUIUpdateList();
if (!string.IsNullOrEmpty(DisplayedWelcomeMessage))
{
ShowOnDisplay(DisplayedWelcomeMessage);
DisplayedWelcomeMessage = "";
}
if (shouldSelectInputBox)
{
inputBox.Select();
@@ -17,14 +17,60 @@ namespace Barotrauma.Items.Components
partial class WireSection
{
public VertexPositionColorTexture[] vertices;
public VertexPositionColorTexture[] shiftedVertices;
private float cachedWidth = 0f;
private void RecalculateVertices(Wire wire, float width)
{
if (MathUtils.NearlyEqual(cachedWidth, width)) { return; }
cachedWidth = width;
vertices = new VertexPositionColorTexture[4];
Vector2 expandDir = start-end;
expandDir.Normalize();
float temp = expandDir.X;
expandDir.X = -expandDir.Y;
expandDir.Y = -temp;
Rectangle srcRect = wire.wireSprite.SourceRect;
expandDir *= width * srcRect.Height * 0.5f;
Vector2 rectLocation = srcRect.Location.ToVector2();
Vector2 rectSize = srcRect.Size.ToVector2();
Vector2 textureSize = new Vector2(wire.wireSprite.Texture.Width, wire.wireSprite.Texture.Height);
Vector2 topLeftUv = rectLocation / textureSize;
Vector2 bottomRightUv = (rectLocation + rectSize) / textureSize;
Vector2 invStart = new Vector2(start.X, -start.Y);
Vector2 invEnd = new Vector2(end.X, -end.Y);
vertices[0] = new VertexPositionColorTexture(new Vector3(invStart + expandDir, 0f), Color.White, topLeftUv);
vertices[2] = new VertexPositionColorTexture(new Vector3(invEnd + expandDir, 0f), Color.White, new Vector2(bottomRightUv.X, topLeftUv.Y));
vertices[1] = new VertexPositionColorTexture(new Vector3(invStart - expandDir, 0f), Color.White, new Vector2(topLeftUv.X, bottomRightUv.Y));
vertices[3] = new VertexPositionColorTexture(new Vector3(invEnd - expandDir, 0f), Color.White, bottomRightUv);
shiftedVertices = (VertexPositionColorTexture[])vertices.Clone();
}
public void Draw(SpriteBatch spriteBatch, Wire wire, Color color, Vector2 offset, float depth, float width = 0.3f)
{
if (width <= 0f) { return; }
RecalculateVertices(wire, width);
for (int i=0;i<vertices.Length;i++)
{
shiftedVertices[i].Color = color;
shiftedVertices[i].Position = vertices[i].Position;
shiftedVertices[i].Position.X += offset.X;
shiftedVertices[i].Position.Y -= offset.Y;
}
spriteBatch.Draw(wire.wireSprite.Texture,
new Vector2(start.X + offset.X, -(start.Y + offset.Y)), null, color,
-angle,
new Vector2(0.0f, wire.wireSprite.size.Y / 2.0f),
new Vector2(length / wire.wireSprite.Texture.Width, width),
SpriteEffects.None,
shiftedVertices,
depth);
}
@@ -34,10 +80,10 @@ namespace Barotrauma.Items.Components
end.Y = -end.Y;
spriteBatch.Draw(wire.wireSprite.Texture,
start, null, color,
start, wire.wireSprite.SourceRect, color,
MathUtils.VectorToAngle(end - start),
new Vector2(0.0f, wire.wireSprite.size.Y / 2.0f),
new Vector2((Vector2.Distance(start, end)) / wire.wireSprite.Texture.Width, width),
new Vector2((Vector2.Distance(start, end)) / wire.wireSprite.size.X, width),
SpriteEffects.None,
depth);
}
@@ -50,6 +96,13 @@ namespace Barotrauma.Items.Components
private static int? selectedNodeIndex;
private static int? highlightedNodeIndex;
[Serialize(0.3f, false)]
public float Width
{
get;
set;
}
public Vector2 DrawSize
{
get { return sectionExtents; }
@@ -72,7 +125,7 @@ namespace Barotrauma.Items.Components
foreach (XElement subElement in element.Elements())
{
if (subElement.Name.ToString().ToLowerInvariant() == "wiresprite")
if (subElement.Name.ToString().Equals("wiresprite", StringComparison.OrdinalIgnoreCase))
{
overrideSprite = new Sprite(subElement);
break;
@@ -103,26 +156,26 @@ namespace Barotrauma.Items.Components
drawOffset = sub.DrawPosition + sub.HiddenSubPosition;
}
float depth = item.IsSelected ? 0.0f : wireSprite.Depth + ((item.ID % 100) * 0.00001f);
float depth = item.IsSelected ? 0.0f : Screen.Selected is SubEditorScreen editor && editor.WiringMode ? 0.00002f : wireSprite.Depth + ((item.ID % 100) * 0.00001f);
if (item.IsHighlighted)
{
foreach (WireSection section in sections)
{
section.Draw(spriteBatch, this, Screen.Selected == GameMain.GameScreen ? higlightColor : editorHighlightColor, drawOffset, depth + 0.00001f, 0.7f);
section.Draw(spriteBatch, this, Screen.Selected == GameMain.GameScreen ? higlightColor : editorHighlightColor, drawOffset, depth + 0.00001f, Width * 2.0f);
}
}
else if (item.IsSelected)
{
foreach (WireSection section in sections)
{
section.Draw(spriteBatch, this, editorSelectedColor, drawOffset, depth + 0.00001f, 0.7f);
section.Draw(spriteBatch, this, editorSelectedColor, drawOffset, depth + 0.00001f, Width * 2.0f);
}
}
foreach (WireSection section in sections)
{
section.Draw(spriteBatch, this, item.Color, drawOffset, depth, 0.3f);
section.Draw(spriteBatch, this, item.Color, drawOffset, depth, Width);
}
if (nodes.Count > 0)
@@ -167,13 +220,13 @@ namespace Barotrauma.Items.Components
spriteBatch, this,
new Vector2(nodes[nodes.Count - 1].X, nodes[nodes.Count - 1].Y) + drawOffset,
new Vector2(newNodePos.X, newNodePos.Y) + drawOffset,
item.Color, 0.0f, 0.3f);
item.Color, 0.0f, Width);
WireSection.Draw(
spriteBatch, this,
new Vector2(newNodePos.X, newNodePos.Y) + drawOffset,
item.DrawPosition,
item.Color, itemDepth, 0.3f);
item.Color, itemDepth, Width);
GUI.DrawRectangle(spriteBatch, new Vector2(newNodePos.X + drawOffset.X, -(newNodePos.Y + drawOffset.Y)) - Vector2.One * 3, Vector2.One * 6, item.Color);
}
@@ -183,7 +236,7 @@ namespace Barotrauma.Items.Components
spriteBatch, this,
new Vector2(nodes[nodes.Count - 1].X, nodes[nodes.Count - 1].Y) + drawOffset,
item.DrawPosition,
item.Color, 0.0f, 0.3f);
item.Color, 0.0f, Width);
}
}
}
@@ -235,7 +288,7 @@ namespace Barotrauma.Items.Components
Wire equippedWire =
Character.Controlled?.SelectedItems[0]?.GetComponent<Wire>() ??
Character.Controlled?.SelectedItems[1]?.GetComponent<Wire>();
if (equippedWire != null)
if (equippedWire != null && GUI.MouseOn == null)
{
if (PlayerInput.PrimaryMouseButtonClicked() && Character.Controlled.SelectedConstruction == null)
{
@@ -404,6 +457,20 @@ namespace Barotrauma.Items.Components
}
}
public bool IsMouseOn()
{
if (GUI.MouseOn == null)
{
Vector2 mousePos = GameMain.SubEditorScreen.Cam.ScreenToWorld(PlayerInput.MousePosition);
if (item.Submarine != null) { mousePos -= (item.Submarine.Position + item.Submarine.HiddenSubPosition); }
if (GetClosestNodeIndex(mousePos, 10, out _) > -1) { return true; }
if (GetClosestSectionIndex(mousePos, 10, out _) > -1) { return true; }
}
return false;
}
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
{
int eventIndex = msg.ReadRangedInteger(0, (int)Math.Ceiling(MaxNodeCount / (float)MaxNodesPerNetworkEvent));
@@ -19,6 +19,8 @@ namespace Barotrauma.Items.Components
private float recoilTimer;
private float RetractionTime => Math.Max(Reload * RetractionDurationMultiplier, RecoilTime);
private RoundSound startMoveSound, endMoveSound, moveSound;
private SoundChannel moveSoundChannel;
@@ -83,6 +85,11 @@ namespace Barotrauma.Items.Components
}
}
public Sprite BarrelSprite
{
get { return barrelSprite; }
}
partial void InitProjSpecific(XElement element)
{
foreach (XElement subElement in element.Elements())
@@ -126,7 +133,7 @@ namespace Barotrauma.Items.Components
partial void LaunchProjSpecific()
{
recoilTimer = Math.Max(Reload, 0.1f);
recoilTimer = RetractionTime;
PlaySound(ActionType.OnUse);
Vector2 particlePos = new Vector2(item.WorldRect.X + transformedBarrelPos.X, item.WorldRect.Y - transformedBarrelPos.Y);
foreach (ParticleEmitter emitter in particleEmitters)
@@ -135,6 +142,12 @@ namespace Barotrauma.Items.Components
}
}
public override void UpdateBroken(float deltaTime, Camera cam)
{
base.UpdateBroken(deltaTime, cam);
recoilTimer -= deltaTime;
}
partial void UpdateProjSpecific(float deltaTime)
{
recoilTimer -= deltaTime;
@@ -223,21 +236,30 @@ namespace Barotrauma.Items.Components
public void Draw(SpriteBatch spriteBatch, bool editing = false, float itemDepth = -1)
{
Vector2 drawPos = new Vector2(item.Rect.X + transformedBarrelPos.X, item.Rect.Y - transformedBarrelPos.Y);
if (item.Submarine != null) drawPos += item.Submarine.DrawPosition;
if (item.Submarine != null)
{
drawPos += item.Submarine.DrawPosition;
}
drawPos.Y = -drawPos.Y;
float recoilOffset = 0.0f;
if (RecoilDistance > 0.0f && recoilTimer > 0.0f)
if (Math.Abs(RecoilDistance) > 0.0f && recoilTimer > 0.0f)
{
//move the barrel backwards 0.1 seconds after launching
if (recoilTimer >= Math.Max(Reload, 0.1f) - 0.1f)
float diff = RetractionTime - RecoilTime;
if (recoilTimer >= diff)
{
recoilOffset = RecoilDistance * (1.0f - (recoilTimer - (Math.Max(Reload, 0.1f) - 0.1f)) / 0.1f);
//move the barrel backwards 0.1 seconds (defined by RecoilTime) after launching
recoilOffset = RecoilDistance * (1.0f - (recoilTimer - diff) / RecoilTime);
}
else if (recoilTimer <= diff - RetractionDelay)
{
//move back to normal position while reloading
float t = diff - RetractionDelay;
recoilOffset = RecoilDistance * recoilTimer / t;
}
//move back to normal position while reloading
else
{
recoilOffset = RecoilDistance * recoilTimer / (Math.Max(Reload, 0.1f) - 0.1f);
recoilOffset = RecoilDistance;
}
}
@@ -369,13 +391,26 @@ namespace Barotrauma.Items.Components
tooltipOffset = new Vector2(size / 2 + 5, -10),
inputAreaMargin = 20,
RequireMouseOn = false
};
};
widgets.Add(id, widget);
initMethod?.Invoke(widget);
}
return widget;
}
private void GetAvailablePower(out float availableCharge, out float availableCapacity)
{
var batteries = item.GetConnectedComponents<PowerContainer>();
availableCharge = 0.0f;
availableCapacity = 0.0f;
foreach (PowerContainer battery in batteries)
{
availableCharge += battery.Charge;
availableCapacity += battery.Capacity;
}
}
/// <summary>
/// Returns correct angle between -2PI and +2PI
/// </summary>
@@ -488,17 +523,31 @@ namespace Barotrauma.Items.Components
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
{
UInt16 projectileID = msg.ReadUInt16();
//projectile removed, do nothing
if (projectileID == 0) return;
float newTargetRotation = msg.ReadRangedSingle(minRotation, maxRotation, 16);
Item projectile = Entity.FindEntityByID(projectileID) as Item;
if (projectile == null)
if (Character.Controlled == null || user != Character.Controlled)
{
DebugConsole.ThrowError("Failed to launch a projectile - item with the ID \"" + projectileID + " not found");
return;
targetRotation = newTargetRotation;
}
//projectile removed, do nothing
if (projectileID == 0) { return; }
//ID ushort.MaxValue = launched without a projectile
if (projectileID == ushort.MaxValue)
{
Launch(null);
}
else
{
if (!(Entity.FindEntityByID(projectileID) is Item projectile))
{
DebugConsole.ThrowError("Failed to launch a projectile - item with the ID \"" + projectileID + " not found");
return;
}
Launch(projectile, launchRotation: newTargetRotation);
}
Launch(projectile);
}
}
}
@@ -150,8 +150,8 @@ namespace Barotrauma.Items.Components
if (joint == null)
{
string errorMsg = "Error while reading a docking port network event (Dock method did not create a joint between the ports)." +
" Submarine: " + (item.Submarine?.Name ?? "null") +
", target submarine: " + (DockingTarget.item.Submarine?.Name ?? "null");
" Submarine: " + (item.Submarine?.Info.Name ?? "null") +
", target submarine: " + (DockingTarget.item.Submarine?.Info.Name ?? "null");
if (item.Submarine?.ConnectedDockingPorts.ContainsKey(DockingTarget.item.Submarine) ?? false)
{
errorMsg += "\nAlready docked.";
@@ -45,12 +45,17 @@ namespace Barotrauma
public float QuickUseTimer;
public string QuickUseButtonToolTip;
public bool IsMoving = false;
private static Rectangle offScreenRect = new Rectangle(new Point(-1000, 0), Point.Zero);
public GUIComponent.ComponentState EquipButtonState;
public Rectangle EquipButtonRect
{
get
{
// Returns a point off-screen, Rectangle.Empty places buttons in the top left of the screen
if (IsMoving) return offScreenRect;
int buttonDir = Math.Sign(SubInventoryDir);
float sizeY = Inventory.UnequippedIndicator.size.Y * Inventory.UIScale * Inventory.IndicatorScaleAdjustment;
@@ -186,7 +191,7 @@ namespace Barotrauma
public Item Item;
public bool IsSubSlot;
public string Tooltip;
public List<ColorData> TooltipColorData;
public List<RichTextData> TooltipRichTextData;
public SlotReference(Inventory parentInventory, InventorySlot slot, int slotIndex, bool isSubSlot, Inventory subInventory = null)
{
@@ -196,7 +201,7 @@ namespace Barotrauma
Inventory = subInventory;
IsSubSlot = isSubSlot;
Item = ParentInventory.Items[slotIndex];
TooltipColorData = ColorData.GetColorData(GetTooltip(Item), out Tooltip);
TooltipRichTextData = RichTextData.GetRichTextData(GetTooltip(Item), out Tooltip);
}
private string GetTooltip(Item item)
@@ -445,12 +450,33 @@ namespace Barotrauma
}
}*/
bool mouseOn = interactRect.Contains(PlayerInput.MousePosition) && !Locked && !mouseOnGUI;
bool mouseOn = interactRect.Contains(PlayerInput.MousePosition) && !Locked && !mouseOnGUI && !slot.Disabled;
// Delete item from container in sub editor
if (SubEditorScreen.IsSubEditor() && PlayerInput.IsCtrlDown())
{
draggingItem = null;
var mouseDrag = SubEditorScreen.MouseDragStart != Vector2.Zero && Vector2.Distance(PlayerInput.MousePosition, SubEditorScreen.MouseDragStart) >= GUI.Scale * 20;
if (mouseOn && (PlayerInput.PrimaryMouseButtonClicked() || mouseDrag))
{
if (item != null)
{
if (mouseDrag) { item.OwnInventory?.DeleteAllItems(); }
slot.ShowBorderHighlight(GUI.Style.Red, 0.1f, 0.4f);
if (!mouseDrag)
{
GUI.PlayUISound(GUISoundType.PickItem);
}
item.Remove();
}
}
}
if (PlayerInput.LeftButtonHeld() && PlayerInput.RightButtonHeld())
{
mouseOn = false;
}
if (selectedSlot != null && selectedSlot.Slot != slot)
{
//subinventory slot highlighted -> don't allow highlighting this one
@@ -471,11 +497,14 @@ namespace Barotrauma
// &&
//(highlightedSubInventories.Count == 0 || highlightedSubInventories.Contains(this) || highlightedSubInventorySlot?.Slot == slot || highlightedSubInventory.Owner == item))
{
slot.State = GUIComponent.ComponentState.Hover;
if (selectedSlot == null || (!selectedSlot.IsSubSlot && isSubSlot))
{
selectedSlot = new SlotReference(this, slot, slotIndex, isSubSlot, Items[slotIndex]?.GetComponent<ItemContainer>()?.Inventory);
var slotRef = new SlotReference(this, slot, slotIndex, isSubSlot, Items[slotIndex]?.GetComponent<ItemContainer>()?.Inventory);
if (Screen.Selected is SubEditorScreen editor && !editor.WiringMode && slotRef.ParentInventory is CharacterInventory) { return; }
selectedSlot = slotRef;
}
if (draggingItem == null)
@@ -663,6 +692,18 @@ namespace Barotrauma
DrawSlot(spriteBatch, this, slots[i], Items[i], i, drawItem);
}
}
/// <summary>
/// Check if the mouse is hovering on top of the slot
/// </summary>
/// <param name="slot">The desired slot we want to check</param>
/// <returns>True if our mouse is hover on the slot, false otherwise</returns>
public static bool IsMouseOnSlot(InventorySlot slot)
{
var rect = new Rectangle(slot.InteractRect.X, slot.InteractRect.Y, slot.InteractRect.Width, slot.InteractRect.Height);
rect.Offset(slot.DrawOffset);
return rect.Contains(PlayerInput.MousePosition);
}
/// <summary>
/// Is the mouse on any inventory element (slot, equip button, subinventory...)
@@ -670,11 +711,12 @@ namespace Barotrauma
/// <returns></returns>
public static bool IsMouseOnInventory()
{
var isSubEditor = Screen.Selected is SubEditorScreen editor && !editor.WiringMode;
if (Character.Controlled == null) return false;
if (draggingItem != null || DraggingInventory != null) return true;
if (Character.Controlled.Inventory != null)
if (Character.Controlled.Inventory != null && !isSubEditor)
{
var inv = Character.Controlled.Inventory;
for (var i = 0; i < inv.slots.Length; i++)
@@ -694,7 +736,8 @@ namespace Barotrauma
}
}
}
if (Character.Controlled.SelectedCharacter?.Inventory != null)
if (Character.Controlled.SelectedCharacter?.Inventory != null && !isSubEditor)
{
var inv = Character.Controlled.SelectedCharacter.Inventory;
for (var i = 0; i < inv.slots.Length; i++)
@@ -825,9 +868,9 @@ namespace Barotrauma
return CursorState.Default;
}
protected static void DrawToolTip(SpriteBatch spriteBatch, string toolTip, Rectangle highlightedSlot, List<ColorData> colorData = null)
protected static void DrawToolTip(SpriteBatch spriteBatch, string toolTip, Rectangle highlightedSlot, List<RichTextData> richTextData = null)
{
GUIComponent.DrawToolTip(spriteBatch, toolTip, highlightedSlot, colorData);
GUIComponent.DrawToolTip(spriteBatch, toolTip, highlightedSlot, richTextData);
}
public void DrawSubInventory(SpriteBatch spriteBatch, int slotIndex)
@@ -941,8 +984,33 @@ namespace Barotrauma
}
else
{
GUI.PlayUISound(GUISoundType.DropItem);
draggingItem.Drop(Character.Controlled);
bool removed = false;
if (Screen.Selected is SubEditorScreen editor)
{
if (editor.EntityMenu.Rect.Contains(PlayerInput.MousePosition))
{
draggingItem.Remove();
removed = true;
}
else
{
if (editor.WiringMode)
{
draggingItem.Remove();
removed = true;
}
else
{
draggingItem.Drop(Character.Controlled);
}
}
}
else
{
draggingItem.Drop(Character.Controlled);
}
GUI.PlayUISound(removed ? GUISoundType.PickItem : GUISoundType.DropItem);
}
}
else if (selectedSlot.ParentInventory.Items[selectedSlot.SlotIndex] != draggingItem)
@@ -1033,7 +1101,9 @@ namespace Barotrauma
}
if (subSlot.Slot.SubInventoryDir < 0)
{
hoverArea.Height -= hoverArea.Bottom - subSlot.Slot.Rect.Bottom;
// 24/2/2020 - the below statement makes the sub inventory extend all the way to the bottom of the screen because of a double negative
// Not sure if it's intentional or not but it was causing hover issues and disabling it seems to have no detrimental effects.
// hoverArea.Height -= hoverArea.Bottom - subSlot.Slot.Rect.Bottom;
}
else
{
@@ -1083,7 +1153,7 @@ namespace Barotrauma
string toolTip = mouseOnHealthInterface ? TextManager.Get("QuickUseAction.UseTreatment") :
Character.Controlled.FocusedItem != null ?
TextManager.GetWithVariable("PutItemIn", "[itemname]", Character.Controlled.FocusedItem.Name, true) :
TextManager.Get("DropItem");
TextManager.Get(Screen.Selected is SubEditorScreen editor && editor.EntityMenu.Rect.Contains(PlayerInput.MousePosition) ? "Delete" : "DropItem");
int textWidth = (int)Math.Max(GUI.Font.MeasureString(draggingItem.Name).X, GUI.SmallFont.MeasureString(toolTip).X);
int textSpacing = (int)(15 * GUI.Scale);
Point shadowBorders = (new Point(40, 10)).Multiply(GUI.Scale);
@@ -1106,7 +1176,7 @@ namespace Barotrauma
{
Rectangle slotRect = selectedSlot.Slot.Rect;
slotRect.Location += selectedSlot.Slot.DrawOffset.ToPoint();
DrawToolTip(spriteBatch, selectedSlot.Tooltip, slotRect, selectedSlot.TooltipColorData);
DrawToolTip(spriteBatch, selectedSlot.Tooltip, slotRect, selectedSlot.TooltipRichTextData);
}
}
@@ -1140,15 +1210,20 @@ namespace Barotrauma
/*if (inventory != null && (CharacterInventory.PersonalSlots.HasFlag(type) || (inventory.isSubInventory && (inventory.Owner as Item) != null
&& (inventory.Owner as Item).AllowedSlots.Any(a => CharacterInventory.PersonalSlots.HasFlag(a)))))
{
slotColor = slot.IsHighlighted ? GUIColorSettings.EquipmentSlotColor : GUIColorSettings.EquipmentSlotColor * 0.8f;
slotColor = slot.IsHighlighted ? GUI.Style.EquipmentSlotColor : GUI.Style.EquipmentSlotColor * 0.8f;
}
else
{
slotColor = slot.IsHighlighted ? GUIColorSettings.InventorySlotColor : GUIColorSettings.InventorySlotColor * 0.8f;
slotColor = slot.IsHighlighted ? GUI.Style.InventorySlotColor : GUI.Style.InventorySlotColor * 0.8f;
}*/
if (inventory != null && inventory.Locked) { slotColor = Color.Gray * 0.5f; }
spriteBatch.Draw(slotSprite.Texture, rect, slotSprite.SourceRect, slotColor);
if (SubEditorScreen.IsSubEditor() && PlayerInput.IsCtrlDown() && selectedSlot?.Slot == slot)
{
GUI.DrawRectangle(spriteBatch, rect, GUI.Style.Red * 0.3f, isFilled: true);
}
bool canBePut = false;
@@ -1203,13 +1278,15 @@ namespace Barotrauma
dir < 0 ? rect.Bottom + HUDLayoutSettings.Padding / 2 : rect.Y - HUDLayoutSettings.Padding / 2 - ContainedIndicatorHeight, rect.Width, ContainedIndicatorHeight);
containedIndicatorArea.Inflate(-4, 0);
Color backgroundColor = GUI.Style.ColorInventoryBackground;
if (itemContainer.ContainedStateIndicator?.Texture == null)
{
containedIndicatorArea.Inflate(0, -2);
GUI.DrawRectangle(spriteBatch, containedIndicatorArea, Color.Gray * 0.9f, true);
GUI.DrawRectangle(spriteBatch, containedIndicatorArea, backgroundColor, true);
GUI.DrawRectangle(spriteBatch,
new Rectangle(containedIndicatorArea.X, containedIndicatorArea.Y, (int)(containedIndicatorArea.Width * containedState), containedIndicatorArea.Height),
ToolBox.GradientLerp(containedState, Color.Red, Color.Orange, Color.LightGreen) * 0.8f, true);
ToolBox.GradientLerp(containedState, GUI.Style.ColorInventoryEmpty, GUI.Style.ColorInventoryHalf, GUI.Style.ColorInventoryFull) * 0.8f, true);
GUI.DrawLine(spriteBatch,
new Vector2(containedIndicatorArea.X + (int)(containedIndicatorArea.Width * containedState), containedIndicatorArea.Y),
new Vector2(containedIndicatorArea.X + (int)(containedIndicatorArea.Width * containedState), containedIndicatorArea.Bottom),
@@ -1228,12 +1305,12 @@ namespace Barotrauma
}
indicatorSprite.Draw(spriteBatch, containedIndicatorArea.Center.ToVector2(),
(inventory != null && inventory.Locked) ? Color.Gray * 0.5f : Color.Gray * 0.9f,
(inventory != null && inventory.Locked) ? backgroundColor * 0.5f : backgroundColor,
origin: indicatorSprite.size / 2,
rotate: 0.0f,
scale: indicatorScale);
Color indicatorColor = ToolBox.GradientLerp(containedState, Color.Red, Color.Orange, Color.LightGreen);
Color indicatorColor = ToolBox.GradientLerp(containedState, GUI.Style.ColorInventoryEmpty, GUI.Style.ColorInventoryHalf, GUI.Style.ColorInventoryFull);
if (inventory != null && inventory.Locked) { indicatorColor *= 0.5f; }
spriteBatch.Draw(indicatorSprite.Texture, containedIndicatorArea.Center.ToVector2(),
@@ -29,14 +29,8 @@ namespace Barotrauma
private bool editingHUDRefreshPending;
private float editingHUDRefreshTimer;
class SpriteState
{
public float RotationState;
public float OffsetState;
public bool IsActive = true;
}
private Dictionary<DecorativeSprite, SpriteState> spriteAnimState = new Dictionary<DecorativeSprite, SpriteState>();
private readonly Dictionary<DecorativeSprite, DecorativeSprite.State> spriteAnimState = new Dictionary<DecorativeSprite, DecorativeSprite.State>();
private Sprite activeSprite;
public override Sprite Sprite
@@ -44,11 +38,20 @@ namespace Barotrauma
get { return activeSprite; }
}
public override bool DrawOverWater
public override Rectangle Rect
{
get { return base.DrawOverWater || (GetComponent<Wire>() != null && IsSelected); }
get { return base.Rect; }
set
{
cachedVisibleSize = null;
base.Rect = value;
}
}
public override bool DrawBelowWater => (!(Screen.Selected is SubEditorScreen editor) || !editor.WiringMode || !isWire) && base.DrawBelowWater;
public override bool DrawOverWater => base.DrawOverWater || (IsSelected || Screen.Selected is SubEditorScreen editor && editor.WiringMode) && isWire;
private GUITextBlock itemInUseWarning;
private GUITextBlock ItemInUseWarning
{
@@ -160,8 +163,16 @@ namespace Barotrauma
foreach (var decorativeSprite in ((ItemPrefab)prefab).DecorativeSprites)
{
decorativeSprite.Sprite.EnsureLazyLoaded();
spriteAnimState.Add(decorativeSprite, new SpriteState());
spriteAnimState.Add(decorativeSprite, new DecorativeSprite.State());
}
UpdateSpriteStates(0.0f);
}
private Vector2? cachedVisibleSize;
public void ResetCachedVisibleSize()
{
cachedVisibleSize = null;
}
public override bool IsVisible(Rectangle worldView)
@@ -173,19 +184,28 @@ namespace Barotrauma
}
//no drawable components and the body has been disabled = nothing to draw
if (drawableComponents.Count == 0 && body != null && !body.Enabled)
if (!hasComponentsToDraw && body != null && !body.Enabled)
{
return false;
}
float padding = 100.0f;
Vector2 size = new Vector2(rect.Width + padding, rect.Height + padding);
foreach (IDrawableComponent drawable in drawableComponents)
Vector2 size;
if (cachedVisibleSize.HasValue)
{
size.X = Math.Max(drawable.DrawSize.X, size.X);
size.Y = Math.Max(drawable.DrawSize.Y, size.Y);
size = cachedVisibleSize.Value;
}
else
{
float padding = 100.0f;
size = new Vector2(rect.Width + padding, rect.Height + padding);
foreach (IDrawableComponent drawable in drawableComponents)
{
size.X = Math.Max(drawable.DrawSize.X, size.X);
size.Y = Math.Max(drawable.DrawSize.Y, size.Y);
}
size *= 0.5f;
cachedVisibleSize = size;
}
size *= 0.5f;
//cache world position so we don't need to calculate it 4 times
Vector2 worldPosition = WorldPosition;
@@ -197,8 +217,8 @@ namespace Barotrauma
public override void Draw(SpriteBatch spriteBatch, bool editing, bool back = true)
{
if (!Visible || (!editing && HiddenInGame)) return;
if (editing && !ShowItems) return;
if (!Visible || (!editing && HiddenInGame)) { return; }
if (editing && !ShowItems) { return; }
Color color = IsHighlighted && !GUI.DisableItemHighlights && Screen.Selected != GameMain.GameScreen ? GUI.Style.Orange : GetSpriteColor();
//if (IsSelected && editing) color = Color.Lerp(color, Color.Gold, 0.5f);
@@ -268,7 +288,7 @@ namespace Barotrauma
float rotation = decorativeSprite.GetRotation(ref spriteAnimState[decorativeSprite].RotationState);
Vector2 offset = decorativeSprite.GetOffset(ref spriteAnimState[decorativeSprite].OffsetState) * Scale;
decorativeSprite.Sprite.Draw(spriteBatch, new Vector2(DrawPosition.X + offset.X, -(DrawPosition.Y + offset.Y)), color,
SpriteRotation + rotation, Scale, activeSprite.effects,
SpriteRotation + rotation, decorativeSprite.Scale * Scale, activeSprite.effects,
depth: Math.Min(depth + (decorativeSprite.Sprite.Depth - activeSprite.Depth), 0.999f));
}
}
@@ -312,7 +332,7 @@ namespace Barotrauma
Vector2 transformedOffset = new Vector2(ca * offset.X + sa * offset.Y, -sa * offset.X + ca * offset.Y);
decorativeSprite.Sprite.Draw(spriteBatch, new Vector2(DrawPosition.X + transformedOffset.X, -(DrawPosition.Y + transformedOffset.Y)), color,
-body.Rotation + rotation, Scale, activeSprite.effects,
-body.Rotation + rotation, decorativeSprite.Scale * Scale, activeSprite.effects,
depth: depth + (decorativeSprite.Sprite.Depth - activeSprite.Depth));
}
}
@@ -398,46 +418,7 @@ namespace Barotrauma
public void UpdateSpriteStates(float deltaTime)
{
foreach (int spriteGroup in Prefab.DecorativeSpriteGroups.Keys)
{
for (int i = 0; i < Prefab.DecorativeSpriteGroups[spriteGroup].Count; i++)
{
var decorativeSprite = Prefab.DecorativeSpriteGroups[spriteGroup][i];
if (decorativeSprite == null) { continue; }
if (spriteGroup > 0)
{
int activeSpriteIndex = ID % Prefab.DecorativeSpriteGroups[spriteGroup].Count;
if (i != activeSpriteIndex)
{
spriteAnimState[decorativeSprite].IsActive = false;
continue;
}
}
//check if the sprite is active (whether it should be drawn or not)
var spriteState = spriteAnimState[decorativeSprite];
spriteState.IsActive = true;
foreach (PropertyConditional conditional in decorativeSprite.IsActiveConditionals)
{
if (!ConditionalMatches(conditional))
{
spriteState.IsActive = false;
break;
}
}
if (!spriteState.IsActive) { continue; }
//check if the sprite should be animated
bool animate = true;
foreach (PropertyConditional conditional in decorativeSprite.AnimationConditionals)
{
if (!ConditionalMatches(conditional)) { animate = false; break; }
}
if (!animate) { continue; }
spriteState.OffsetState += deltaTime;
spriteState.RotationState += deltaTime;
}
}
DecorativeSprite.UpdateSpriteStates(Prefab.DecorativeSpriteGroups, spriteAnimState, ID, deltaTime, ConditionalMatches);
}
public override void UpdateEditing(Camera cam)
@@ -716,6 +697,13 @@ namespace Barotrauma
HUDLayoutSettings.ChatBoxArea.Width + disallowedPadding, HUDLayoutSettings.ChatBoxArea.Height));
}
if (Screen.Selected is SubEditorScreen editor)
{
disallowedAreas.Add(editor.EntityMenu.Rect);
disallowedAreas.Add(editor.TopPanel.Rect);
disallowedAreas.Add(editor.ToggleEntityMenuButton.Rect);
}
GUI.PreventElementOverlap(elementsToMove, disallowedAreas,
new Rectangle(
0, 20,
@@ -871,19 +859,21 @@ namespace Barotrauma
}
readonly List<ColoredText> texts = new List<ColoredText>();
public List<ColoredText> GetHUDTexts(Character character)
public List<ColoredText> GetHUDTexts(Character character, bool recreateHudTexts = true)
{
// Always create the texts if they have not yet been created
if (texts.Any() && !recreateHudTexts) { return texts; }
texts.Clear();
foreach (ItemComponent ic in components)
{
if (string.IsNullOrEmpty(ic.DisplayMsg)) continue;
if (!ic.CanBePicked && !ic.CanBeSelected) continue;
if (ic is Holdable holdable && !holdable.CanBeDeattached()) continue;
if (string.IsNullOrEmpty(ic.DisplayMsg)) { continue; }
if (!ic.CanBePicked && !ic.CanBeSelected) { continue; }
if (ic is Holdable holdable && !holdable.CanBeDeattached()) { continue; }
Color color = Color.Gray;
if (ic.HasRequiredItems(character, false))
{
if (ic is Repairable repairable)
if (ic is Repairable)
{
if (!IsFullCondition) { color = Color.Cyan; }
}
@@ -892,9 +882,12 @@ namespace Barotrauma
color = Color.Cyan;
}
}
texts.Add(new ColoredText(ic.DisplayMsg, color, false));
}
if ((PlayerInput.KeyDown(Keys.LeftShift) || PlayerInput.KeyDown(Keys.RightShift)) && CrewManager.DoesItemHaveContextualOrders(this))
{
texts.Add(new ColoredText(TextManager.ParseInputTypes(TextManager.Get("itemmsgcontextualorders")), Color.Cyan, false));
}
return texts;
}
@@ -902,17 +895,17 @@ namespace Barotrauma
{
if (Screen.Selected is SubEditorScreen)
{
if (editingHUD != null && editingHUD.UserData == this) editingHUD.AddToGUIUpdateList();
if (editingHUD != null && editingHUD.UserData == this) { editingHUD.AddToGUIUpdateList(); }
}
else
{
if (HasInGameEditableProperties)
{
if (editingHUD != null && editingHUD.UserData == this) editingHUD.AddToGUIUpdateList();
if (editingHUD != null && editingHUD.UserData == this) { editingHUD.AddToGUIUpdateList(); }
}
}
if (Character.Controlled != null && Character.Controlled?.SelectedConstruction != this) return;
if (Character.Controlled != null && Character.Controlled?.SelectedConstruction != this) { return; }
bool needsLayoutUpdate = false;
foreach (ItemComponent ic in activeHUDs)
@@ -1218,6 +1211,8 @@ namespace Barotrauma
}
}
byte bodyType = msg.ReadByte();
byte teamID = msg.ReadByte();
bool tagsChanged = msg.ReadBoolean();
string tags = "";
@@ -1256,8 +1251,8 @@ namespace Barotrauma
{
if (itemContainerIndex < 0 || itemContainerIndex >= parentItem.components.Count)
{
string errorMsg = "Failed to spawn item \"" + (itemIdentifier ?? "null") +
"\" in the inventory of \"" + parentItem.prefab.Identifier + "\" (component index out of range). Index: " + itemContainerIndex + ", components: " + parentItem.components.Count + ".";
string errorMsg =
$"Failed to spawn item \"{(itemIdentifier ?? "null")}\" in the inventory of \"{parentItem.prefab.Identifier} ({parentItem.ID})\" (component index out of range). Index: {itemContainerIndex}, components: {parentItem.components.Count}.";
GameAnalyticsManager.AddErrorEventOnce("Item.ReadSpawnData:ContainerIndexOutOfRange" + (itemName ?? "null") + (itemIdentifier ?? "null"),
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
errorMsg);
@@ -1275,6 +1270,11 @@ namespace Barotrauma
ID = itemId
};
if (item.body != null)
{
item.body.BodyType = (BodyType)bodyType;
}
foreach (WifiComponent wifiComponent in item.GetComponents<WifiComponent>())
{
wifiComponent.TeamID = (Character.TeamType)teamID;
@@ -66,16 +66,17 @@ namespace Barotrauma
[Serialize("", false)]
public string ImpactSoundTag { get; private set; }
public override void UpdatePlacing(Camera cam)
{
Vector2 position = Submarine.MouseToWorldGrid(cam, Submarine.MainSub);
if (PlayerInput.SecondaryMouseButtonClicked())
{
selected = null;
return;
}
var potentialContainer = MapEntity.GetPotentialContainer(position);
if (!ResizeHorizontal && !ResizeVertical)
{
@@ -88,6 +89,14 @@ namespace Barotrauma
item.SetTransform(ConvertUnits.ToSimUnits(Submarine.MainSub == null ? item.Position : item.Position - Submarine.MainSub.Position), 0.0f);
item.FindHull();
if (PlayerInput.IsShiftDown())
{
if (potentialContainer?.OwnInventory?.TryPutItem(item, Character.Controlled) ?? false)
{
GUI.PlayUISound(GUISoundType.PickItem);
}
}
placePosition = Vector2.Zero;
return;
}
@@ -124,6 +133,12 @@ namespace Barotrauma
}
}
if (potentialContainer != null)
{
potentialContainer.IsHighlighted = true;
}
//if (PlayerInput.GetMouseState.RightButton == ButtonState.Pressed) selected = null;
}
@@ -141,26 +156,10 @@ namespace Barotrauma
if (!ResizeHorizontal && !ResizeVertical)
{
sprite.Draw(spriteBatch, new Vector2(position.X, -position.Y) + sprite.size / 2.0f * Scale, SpriteColor, scale: Scale);
}
else
{
Vector2 placeSize = size;
if (placePosition == Vector2.Zero)
{
if (PlayerInput.PrimaryMouseButtonHeld()) placePosition = position;
}
else
{
if (ResizeHorizontal)
placeSize.X = Math.Max(position.X - placePosition.X, size.X);
if (ResizeVertical)
placeSize.Y = Math.Max(placePosition.Y - position.Y, size.Y);
position = placePosition;
}
if (sprite != null) sprite.DrawTiled(spriteBatch, new Vector2(position.X, -position.Y), placeSize, color: SpriteColor);
sprite?.DrawTiled(spriteBatch, new Vector2(position.X, -position.Y), size, color: SpriteColor);
}
}