38f1ddb...178a853: v0.8.9.1, removed content folder

This commit is contained in:
Joonas Rikkonen
2019-03-18 19:46:58 +02:00
parent 38f1ddb6fe
commit 6c0679c297
1054 changed files with 151673 additions and 144931 deletions
@@ -1,27 +1,77 @@
using Barotrauma.Networking;
using Lidgren.Network;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System.Linq;
using System.Xml.Linq;
namespace Barotrauma.Items.Components
{
partial class Deconstructor : Powered, IServerSerializable, IClientSerializable
{
GUIProgressBar progressBar;
GUIButton activateButton;
private GUIButton activateButton;
private GUIComponent inputInventoryHolder, outputInventoryHolder;
private GUICustomComponent inputInventoryOverlay;
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
private GUIComponent inSufficientPowerWarning;
partial void InitProjSpecific(XElement element)
{
GuiFrame.Draw(spriteBatch);
var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.9f), GuiFrame.RectTransform, Anchor.Center), childAnchor: Anchor.TopCenter)
{
Stretch = true,
RelativeSpacing = 0.02f
};
inputInventoryHolder = new GUIFrame(new RectTransform(new Vector2(0.2f, 0.7f), paddedFrame.RectTransform), style: null);
inputInventoryOverlay = new GUICustomComponent(new RectTransform(Vector2.One, inputInventoryHolder.RectTransform), DrawOverLay, null)
{
CanBeFocused = false
};
activateButton = new GUIButton(new RectTransform(new Vector2(0.8f, 0.1f), paddedFrame.RectTransform),
TextManager.Get("DeconstructorDeconstruct"))
{
OnClicked = ToggleActive
};
inSufficientPowerWarning = new GUITextBlock(new RectTransform(Vector2.One, activateButton.RectTransform), TextManager.Get("DeconstructorNoPower"),
textColor: Color.Orange, textAlignment: Alignment.Center, color: Color.Black, style: "OuterGlow")
{
HoverColor = Color.Black,
IgnoreLayoutGroups = true,
Visible = false,
CanBeFocused = false
};
outputInventoryHolder = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.3f), paddedFrame.RectTransform), style: null);
}
public override void AddToGUIUpdateList()
partial void OnItemLoadedProjSpecific()
{
GuiFrame.AddToGUIUpdateList();
inputContainer.AllowUIOverlap = true;
inputContainer.Inventory.RectTransform = inputInventoryHolder.RectTransform;
outputContainer.AllowUIOverlap = true;
outputContainer.Inventory.RectTransform = outputInventoryHolder.RectTransform;
}
public override void UpdateHUD(Character character)
private void DrawOverLay(SpriteBatch spriteBatch, GUICustomComponent overlayComponent)
{
GuiFrame.Update((float)Timing.Step);
overlayComponent.RectTransform.SetAsLastChild();
var lastSlot = inputContainer.Inventory.slots.Last();
GUI.DrawRectangle(spriteBatch,
new Rectangle(
lastSlot.Rect.X, lastSlot.Rect.Y + (int)(lastSlot.Rect.Height * (1.0f - progressState)),
lastSlot.Rect.Width, (int)(lastSlot.Rect.Height * progressState)),
Color.Green * 0.5f, isFilled: true);
}
public override void UpdateHUD(Character character, float deltaTime, Camera cam)
{
inSufficientPowerWarning.Visible = powerConsumption > 0 && voltage < minVoltage;
activateButton.Enabled = !inSufficientPowerWarning.Visible;
}
private bool ToggleActive(GUIButton button, object obj)
@@ -1,25 +1,142 @@
using Microsoft.Xna.Framework;
using Barotrauma.Networking;
using Lidgren.Network;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Xml.Linq;
namespace Barotrauma.Items.Components
{
partial class Engine : Powered
partial class Engine : Powered, IDrawableComponent
{
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
{
GuiFrame.Draw(spriteBatch);
private float spriteIndex;
GUI.Font.DrawString(spriteBatch, TextManager.Get("Force") + ": " + (int)(targetForce) + " %", new Vector2(GuiFrame.Rect.X + 30, GuiFrame.Rect.Y + 30), Color.White);
private SpriteSheet propellerSprite;
private GUITickBox powerIndicator;
private GUIScrollBar forceSlider;
public float AnimSpeed
{
get;
private set;
}
public override void AddToGUIUpdateList()
partial void InitProjSpecific(XElement element)
{
GuiFrame.AddToGUIUpdateList();
powerIndicator = new GUITickBox(new RectTransform(new Point(30, 30), GuiFrame.RectTransform) { RelativeOffset = new Vector2(0.05f, 0.15f) },
TextManager.Get("EnginePowered"), style: "IndicatorLightGreen")
{
CanBeFocused = false
};
string powerLabel = TextManager.Get("EngineForce");
new GUITextBlock(new RectTransform(new Vector2(0.9f, 0.3f), GuiFrame.RectTransform, Anchor.BottomCenter)
{ RelativeOffset = new Vector2(0.0f, 0.4f) }, "", textAlignment: Alignment.Center)
{
TextGetter = () => { return powerLabel + ": " + (int)(targetForce) + " %"; }
};
var sliderArea = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.25f), GuiFrame.RectTransform, Anchor.BottomCenter)
{ RelativeOffset = new Vector2(0.0f, 0.2f) }, isHorizontal: true);
new GUITextBlock(new RectTransform(new Vector2(0.2f, 1.0f), sliderArea.RectTransform), TextManager.Get("EngineBackwards"),
font: GUI.SmallFont, textAlignment: Alignment.Center);
forceSlider = new GUIScrollBar(new RectTransform(new Vector2(0.6f, 1.0f), sliderArea.RectTransform), barSize: 0.25f, style: "GUISlider")
{
Step = 0.05f,
OnMoved = (GUIScrollBar scrollBar, float barScroll) =>
{
float newTargetForce = barScroll * 200.0f - 100.0f;
if (Math.Abs(newTargetForce - targetForce) < 0.01) return false;
targetForce = newTargetForce;
if (GameMain.Server != null)
{
item.CreateServerEvent(this);
GameServer.Log(Character.Controlled.LogName + " set the force speed of " + item.Name + " to " + (int)(targetForce) + " %", ServerLog.MessageType.ItemInteraction);
}
else if (GameMain.Client != null)
{
correctionTimer = CorrectionDelay;
item.CreateClientEvent(this);
}
return true;
}
};
new GUITextBlock(new RectTransform(new Vector2(0.2f, 1.0f), sliderArea.RectTransform), TextManager.Get("EngineForwards"),
font: GUI.SmallFont, textAlignment: Alignment.Center);
foreach (XElement subElement in element.Elements())
{
switch (subElement.Name.ToString().ToLowerInvariant())
{
case "propellersprite":
propellerSprite = new SpriteSheet(subElement);
AnimSpeed = subElement.GetAttributeFloat("animspeed", 1.0f);
break;
}
}
}
public override void UpdateHUD(Character character)
public override void UpdateHUD(Character character, float deltaTime, Camera cam)
{
GuiFrame.Update(1.0f / 60.0f);
powerIndicator.Selected = hasPower && IsActive;
if (!PlayerInput.LeftButtonHeld())
{
float newScroll = (targetForce + 100.0f) / 200.0f;
if (Math.Abs(newScroll - forceSlider.BarScroll) > 0.01f)
{
forceSlider.BarScroll = newScroll;
}
}
}
partial void UpdateAnimation(float deltaTime)
{
if (propellerSprite == null) return;
spriteIndex += (force / 100.0f) * AnimSpeed * deltaTime;
if (spriteIndex < 0) spriteIndex = propellerSprite.FrameCount;
if (spriteIndex >= propellerSprite.FrameCount) spriteIndex = 0.0f;
}
public void Draw(SpriteBatch spriteBatch, bool editing)
{
if (propellerSprite != null)
{
Vector2 drawPos = item.DrawPosition;
drawPos += PropellerPos;
drawPos.Y = -drawPos.Y;
propellerSprite.Draw(spriteBatch, (int)Math.Floor(spriteIndex), drawPos, Color.White, propellerSprite.Origin, 0.0f, Vector2.One);
}
if (editing)
{
Vector2 drawPos = item.DrawPosition;
drawPos += PropellerPos;
drawPos.Y = -drawPos.Y;
GUI.DrawRectangle(spriteBatch, drawPos - Vector2.One * 10, Vector2.One * 20, Color.Red);
}
}
public void ClientWrite(NetBuffer msg, object[] extraData = null)
{
//targetForce can only be adjusted at 10% intervals -> no need for more accuracy than this
msg.WriteRangedInteger(-10, 10, (int)(targetForce / 10.0f));
}
public void ClientRead(ServerNetObject type, NetBuffer msg, float sendingTime)
{
if (correctionTimer > 0.0f)
{
StartDelayedCorrection(type, msg.ExtractBits(5), sendingTime);
return;
}
targetForce = msg.ReadRangedInteger(-10, 10) * 10.0f;
}
}
}
@@ -1,4 +1,5 @@
using Barotrauma.Networking;
using Barotrauma.Extensions;
using Barotrauma.Networking;
using Lidgren.Network;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
@@ -13,148 +14,309 @@ namespace Barotrauma.Items.Components
private GUIListBox itemList;
private GUIFrame selectedItemFrame;
private GUIProgressBar progressBar;
private GUIButton activateButton;
private GUIComponent inputInventoryHolder, outputInventoryHolder;
private GUICustomComponent inputInventoryOverlay, outputInventoryOverlay;
private FabricableItem selectedItem;
private GUIComponent inSufficientPowerWarning;
private Pair<Rectangle, string> tooltip;
partial void InitProjSpecific()
{
GuiFrame.Padding = new Vector4(20.0f, 20.0f, 20.0f, 20.0f);
var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.9f), GuiFrame.RectTransform, Anchor.Center), childAnchor: Anchor.TopCenter)
{
Stretch = true,
RelativeSpacing = 0.02f
};
itemList = new GUIListBox(new Rectangle(0, 0, GuiFrame.Rect.Width / 2 - 20, 0), "", GuiFrame);
itemList.OnSelected = SelectItem;
itemList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.5f), paddedFrame.RectTransform))
{
OnSelected = SelectItem
};
inputInventoryHolder = new GUIFrame(new RectTransform(new Vector2(0.7f, 0.15f), paddedFrame.RectTransform), style: null);
inputInventoryOverlay = new GUICustomComponent(new RectTransform(Vector2.One, inputInventoryHolder.RectTransform), DrawInputOverLay, null)
{
CanBeFocused = false
};
var outputArea = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.3f), paddedFrame.RectTransform), isHorizontal: true);
selectedItemFrame = new GUIFrame(new RectTransform(new Vector2(0.75f, 1.0f), outputArea.RectTransform), style: "InnerFrame");
outputInventoryHolder = new GUIFrame(new RectTransform(new Vector2(0.25f, 1.0f), outputArea.RectTransform), style: null);
outputInventoryOverlay = new GUICustomComponent(new RectTransform(Vector2.One, outputArea.RectTransform), DrawOutputOverLay, null)
{
CanBeFocused = false
};
foreach (FabricableItem fi in fabricableItems)
{
GUIFrame frame = new GUIFrame(new Rectangle(0, 0, 0, 50), Color.Transparent, null, itemList)
GUIFrame frame = new GUIFrame(new RectTransform(new Point(itemList.Rect.Width, 50), itemList.Content.RectTransform), style: null)
{
UserData = fi,
Padding = new Vector4(5.0f, 5.0f, 5.0f, 5.0f),
HoverColor = Color.Gold * 0.2f,
SelectedColor = Color.Gold * 0.5f,
ToolTip = fi.TargetItem.Description
};
GUITextBlock textBlock = new GUITextBlock(
new Rectangle(40, 0, 0, 25),
fi.TargetItem.Name,
Color.Transparent, Color.White,
Alignment.Left, Alignment.Left,
null, frame);
textBlock.ToolTip = fi.TargetItem.Description;
textBlock.Padding = new Vector4(5.0f, 0.0f, 5.0f, 0.0f);
if (fi.TargetItem.sprite != null)
GUITextBlock textBlock = new GUITextBlock(new RectTransform(Vector2.Zero, frame.RectTransform, Anchor.CenterLeft) { AbsoluteOffset = new Point(50, 0) },
fi.DisplayName)
{
GUIImage img = new GUIImage(new Rectangle(0, 0, 40, 40), fi.TargetItem.sprite, Alignment.Left, frame);
img.Scale = Math.Min(Math.Min(40.0f / img.SourceRect.Width, 40.0f / img.SourceRect.Height), 1.0f);
img.Color = fi.TargetItem.SpriteColor;
img.ToolTip = fi.TargetItem.Description;
ToolTip = fi.TargetItem.Description
};
var itemIcon = fi.TargetItem.InventoryIcon ?? fi.TargetItem.sprite;
if (itemIcon != null)
{
GUIImage img = new GUIImage(new RectTransform(new Point(40, 40), frame.RectTransform, Anchor.CenterLeft) { AbsoluteOffset = new Point(3, 0) },
itemIcon, scaleToFit: true)
{
Color = fi.TargetItem.InventoryIconColor,
ToolTip = fi.TargetItem.Description
};
}
}
activateButton = new GUIButton(new RectTransform(new Vector2(0.8f, 0.07f), paddedFrame.RectTransform),
TextManager.Get("FabricatorCreate"))
{
OnClicked = StartButtonClicked,
UserData = selectedItem,
Enabled = false
};
inSufficientPowerWarning = new GUITextBlock(new RectTransform(Vector2.One, activateButton.RectTransform), TextManager.Get("FabricatorNoPower"),
textColor: Color.Orange, textAlignment: Alignment.Center, color: Color.Black, style: "OuterGlow")
{
HoverColor = Color.Black,
IgnoreLayoutGroups = true,
Visible = false,
CanBeFocused = false
};
}
partial void OnItemLoadedProjSpecific()
{
inputContainer.AllowUIOverlap = true;
inputContainer.Inventory.RectTransform = inputInventoryHolder.RectTransform;
outputContainer.AllowUIOverlap = true;
outputContainer.Inventory.RectTransform = outputInventoryHolder.RectTransform;
}
partial void SelectProjSpecific(Character character)
{
var nonItems = itemList.Content.Children.Where(c => !(c.UserData is FabricableItem)).ToList();
nonItems.ForEach(i => itemList.Content.RemoveChild(i));
itemList.Content.RectTransform.SortChildren((c1, c2) =>
{
var item1 = c1.GUIComponent.UserData as FabricableItem;
var item2 = c2.GUIComponent.UserData as FabricableItem;
bool hasSkills1 = DegreeOfSuccess(character, item1.RequiredSkills) >= 0.5f;
bool hasSkills2 = DegreeOfSuccess(character, item2.RequiredSkills) >= 0.5f;
if (hasSkills1 != hasSkills2)
{
return hasSkills1 ? -1 : 1;
}
return string.Compare(item1.DisplayName, item2.DisplayName);
});
var sufficientSkillsText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), itemList.Content.RectTransform), "Sufficient skills to fabricate:", textColor: Color.LightGreen)
{
CanBeFocused = false
};
sufficientSkillsText.RectTransform.SetAsFirstChild();
var insufficientSkillsText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), itemList.Content.RectTransform), "Insufficient skills to fabricate:", textColor: Color.Orange)
{
CanBeFocused = false
};
var firstinSufficient = itemList.Content.Children.FirstOrDefault(c => c.UserData is FabricableItem fabricableItem && DegreeOfSuccess(character, fabricableItem.RequiredSkills) < 0.5f);
if (firstinSufficient != null)
{
insufficientSkillsText.RectTransform.RepositionChildInHierarchy(itemList.Content.RectTransform.GetChildIndex(firstinSufficient.RectTransform));
}
}
private void DrawInputOverLay(SpriteBatch spriteBatch, GUICustomComponent overlayComponent)
{
overlayComponent.RectTransform.SetAsLastChild();
FabricableItem targetItem = fabricatedItem ?? selectedItem;
if (targetItem != null)
{
int slotIndex = 0;
var missingItems = new List<FabricableItem.RequiredItem>();
foreach (FabricableItem.RequiredItem requiredItem in targetItem.RequiredItems)
{
for (int i = 0; i < requiredItem.Amount; i++)
{
missingItems.Add(requiredItem);
}
}
foreach (Item item in inputContainer.Inventory.Items)
{
if (item == null) { continue; }
missingItems.Remove(missingItems.FirstOrDefault(mi => mi.ItemPrefab == item.prefab));
}
var availableIngredients = GetAvailableIngredients();
foreach (FabricableItem.RequiredItem requiredItem in missingItems)
{
//highlight suitable ingredients in linked inventories
foreach (Item item in availableIngredients)
{
if (item.ParentInventory != inputContainer.Inventory && IsItemValidIngredient(item, requiredItem))
{
int availableSlotIndex = Array.IndexOf(item.ParentInventory.Items, item);
if (item.ParentInventory.slots[availableSlotIndex].HighlightTimer <= 0.0f)
{
item.ParentInventory.slots[availableSlotIndex].ShowBorderHighlight(Color.LightGreen * 0.5f, 0.5f, 0.5f);
}
}
}
while (slotIndex < inputContainer.Capacity && inputContainer.Inventory.Items[slotIndex] != null)
{
slotIndex++;
}
if (slotIndex >= inputContainer.Capacity) { break; }
var itemIcon = requiredItem.ItemPrefab.InventoryIcon ?? requiredItem.ItemPrefab.sprite;
Rectangle slotRect = inputContainer.Inventory.slots[slotIndex].Rect;
itemIcon.Draw(
spriteBatch,
slotRect.Center.ToVector2(),
color: requiredItem.ItemPrefab.InventoryIconColor * 0.3f,
scale: Math.Min(slotRect.Width / itemIcon.size.X, slotRect.Height / itemIcon.size.Y));
if (slotRect.Contains(PlayerInput.MousePosition))
{
string toolTipText = requiredItem.ItemPrefab.Name;
if (!string.IsNullOrEmpty(requiredItem.ItemPrefab.Description))
{
toolTipText += '\n' + requiredItem.ItemPrefab.Description;
}
tooltip = new Pair<Rectangle, string>(slotRect, toolTipText);
}
slotIndex++;
}
}
}
private void DrawOutputOverLay(SpriteBatch spriteBatch, GUICustomComponent overlayComponent)
{
overlayComponent.RectTransform.SetAsLastChild();
FabricableItem targetItem = fabricatedItem ?? selectedItem;
if (targetItem != null)
{
var itemIcon = targetItem.TargetItem.InventoryIcon ?? targetItem.TargetItem.sprite;
Rectangle slotRect = outputContainer.Inventory.slots[0].Rect;
GUI.DrawRectangle(spriteBatch,
new Rectangle(
slotRect.X, slotRect.Y + (int)(slotRect.Height * (1.0f - progressState)),
slotRect.Width, (int)(slotRect.Height * progressState)),
Color.Green * 0.5f, isFilled: true);
itemIcon.Draw(
spriteBatch,
slotRect.Center.ToVector2(),
color: targetItem.TargetItem.InventoryIconColor * 0.4f,
scale: Math.Min(slotRect.Width / itemIcon.size.X, slotRect.Height / itemIcon.size.Y) * 0.9f);
}
if (tooltip != null)
{
GUIComponent.DrawToolTip(spriteBatch, tooltip.Second, tooltip.First);
tooltip = null;
}
}
private bool SelectItem(GUIComponent component, object obj)
{
FabricableItem targetItem = obj as FabricableItem;
if (targetItem == null) return false;
selectedItem = obj as FabricableItem;
if (selectedItem == null) return false;
if (selectedItemFrame != null) GuiFrame.RemoveChild(selectedItemFrame);
selectedItemFrame.ClearChildren();
var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.9f), selectedItemFrame.RectTransform, Anchor.Center)) { RelativeSpacing = 0.03f, Stretch = true };
//int width = 200, height = 150;
selectedItemFrame = new GUIFrame(new Rectangle(0, 0, (int)(GuiFrame.Rect.Width * 0.4f), 350), Color.Black * 0.8f, Alignment.CenterY | Alignment.Right, null, GuiFrame);
selectedItemFrame.Padding = new Vector4(10.0f, 10.0f, 10.0f, 10.0f);
progressBar = new GUIProgressBar(new Rectangle(0, 0, 0, 20), Color.Green, "", 0.0f, Alignment.BottomCenter, selectedItemFrame);
progressBar.IsHorizontal = true;
if (targetItem.TargetItem.sprite != null)
/*var itemIcon = selectedItem.TargetItem.InventoryIcon ?? selectedItem.TargetItem.sprite;
if (itemIcon != null)
{
int y = 0;
GUIImage img = new GUIImage(new Rectangle(10, 0, 40, 40), targetItem.TargetItem.sprite, Alignment.TopLeft, selectedItemFrame);
img.Scale = Math.Min(Math.Min(40.0f / img.SourceRect.Width, 40.0f / img.SourceRect.Height), 1.0f);
img.Color = targetItem.TargetItem.SpriteColor;
new GUITextBlock(
new Rectangle(60, 0, 0, 25),
targetItem.TargetItem.Name,
Color.Transparent, Color.White,
Alignment.TopLeft,
Alignment.TopLeft, null,
selectedItemFrame, true);
y += 40;
if (!string.IsNullOrWhiteSpace(targetItem.TargetItem.Description))
GUIImage img = new GUIImage(new RectTransform(new Point(40, 40), paddedFrame.RectTransform),
itemIcon, scaleToFit: true)
{
var description = new GUITextBlock(
new Rectangle(0, y, 0, 0),
targetItem.TargetItem.Description,
"", Alignment.TopLeft, Alignment.TopLeft,
selectedItemFrame, true, GUI.SmallFont);
Color = selectedItem.TargetItem.InventoryIconColor
};
}*/
var nameBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedFrame.RectTransform),
selectedItem.TargetItem.Name, textAlignment: Alignment.CenterLeft);
y += description.Rect.Height + 10;
}
List<Skill> inadequateSkills = new List<Skill>();
if (Character.Controlled != null)
if (!string.IsNullOrWhiteSpace(selectedItem.TargetItem.Description))
{
var description = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedFrame.RectTransform),
selectedItem.TargetItem.Description,
font: GUI.SmallFont, wrap: true);
if (description.Rect.Height > paddedFrame.Rect.Height * 0.4f)
{
inadequateSkills = targetItem.RequiredSkills.FindAll(skill => Character.Controlled.GetSkillLevel(skill.Name) < skill.Level);
description.Wrap = false;
description.Text = description.WrappedText.Split('\n').First()+"...";
nameBlock.ToolTip = description.ToolTip = selectedItem.TargetItem.Description;
description.RectTransform.MaxSize = new Point(int.MaxValue, (int)description.Font.MeasureString(description.Text).Y);
}
string text = TextManager.Get("FabricatorRequiredItems")+ ":\n";
foreach (Tuple<ItemPrefab, int, float, bool> ip in targetItem.RequiredItems)
}
List<Skill> inadequateSkills = new List<Skill>();
if (Character.Controlled != null)
{
inadequateSkills = selectedItem.RequiredSkills.FindAll(skill => Character.Controlled.GetSkillLevel(skill.Identifier) < skill.Level);
}
if (selectedItem.RequiredSkills.Any())
{
string text = TextManager.Get("FabricatorRequiredSkills") + ":\n";
foreach (Skill skill in selectedItem.RequiredSkills)
{
text += " - " + ip.Item1.Name + " x" + ip.Item2 + (ip.Item3 < 1.0f ? ", " + ip.Item3 * 100 + "% " + TextManager.Get("FabricatorRequiredCondition") + "\n" : "\n");
text += " - " + TextManager.Get("SkillName." + skill.Identifier) + " " + TextManager.Get("Lvl").ToLower() + " " + skill.Level;
if (skill != selectedItem.RequiredSkills.Last()) { text += "\n"; }
}
text += TextManager.Get("FabricatorRequiredTime") + ": " + targetItem.RequiredTime + " s\n";
var requiredItemsText = new GUITextBlock(
new Rectangle(0, y, 0, 0),
text,
Color.Transparent, Color.White,
Alignment.TopLeft,
Alignment.TopLeft, null,
selectedItemFrame,
font: GUI.SmallFont);
if (targetItem.RequiredSkills.Any())
{
text = TextManager.Get("FabricatorRequiredSkills") + ":\n";
foreach (Skill skill in inadequateSkills)
{
text += " - " + skill.Name + " " + TextManager.Get("Lvl").ToLower() + " " + skill.Level + "\n";
}
new GUITextBlock(
new Rectangle(0, y + requiredItemsText.Rect.Height, 0, 0),
text,
Color.Transparent, inadequateSkills.Any() ? Color.Red : Color.White,
Alignment.TopLeft,
Alignment.TopLeft, null,
selectedItemFrame,
font: GUI.SmallFont);
}
activateButton = new GUIButton(new Rectangle(0, -30, 100, 20), TextManager.Get("FabricatorCreate"), Color.White, Alignment.CenterX | Alignment.Bottom, "", selectedItemFrame);
activateButton.OnClicked = StartButtonClicked;
activateButton.UserData = targetItem;
activateButton.Enabled = false;
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedFrame.RectTransform), text,
textColor: inadequateSkills.Any() ? Color.Red : Color.LightGreen, font: GUI.SmallFont);
}
float degreeOfSuccess = DegreeOfSuccess(Character.Controlled, selectedItem.RequiredSkills);
if (degreeOfSuccess > 0.5f) { degreeOfSuccess = 1.0f; }
float requiredTime = GetRequiredTime(selectedItem, Character.Controlled);
string requiredTimeText = TextManager.Get("FabricatorRequiredTime") + ": " + ToolBox.SecondsToReadableTime(requiredTime);
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedFrame.RectTransform),
requiredTimeText, textColor: ToolBox.GradientLerp(degreeOfSuccess, Color.Red, Color.Yellow, Color.LightGreen), font: GUI.SmallFont);
return true;
}
private bool StartButtonClicked(GUIButton button, object obj)
{
if (selectedItem == null) { return false; }
if (fabricatedItem == null)
{
StartFabricating(obj as FabricableItem, Character.Controlled);
StartFabricating(selectedItem, Character.Controlled);
}
else
{
@@ -173,49 +335,29 @@ namespace Barotrauma.Items.Components
return true;
}
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
public override void UpdateHUD(Character character, float deltaTime, Camera cam)
{
GuiFrame.Draw(spriteBatch);
}
public override void AddToGUIUpdateList()
{
GuiFrame.AddToGUIUpdateList();
}
public override void UpdateHUD(Character character)
{
FabricableItem targetItem = itemList.SelectedData as FabricableItem;
if (targetItem != null)
{
activateButton.Enabled = CanBeFabricated(targetItem, character);
}
activateButton.Enabled = false;
inSufficientPowerWarning.Visible = powerConsumption > 0 && voltage < minVoltage;
var availableIngredients = GetAvailableIngredients();
if (character != null)
{
bool itemsChanged = false;
if (prevContainedItems == null)
foreach (GUIComponent child in itemList.Content.Children)
{
itemsChanged = true;
}
else
{
var itemContainer = item.GetComponent<ItemContainer>();
for (int i = 0; i < itemContainer.Inventory.Items.Length; i++)
var itemPrefab = child.UserData as FabricableItem;
if (itemPrefab == null) continue;
bool canBeFabricated = CanBeFabricated(itemPrefab, availableIngredients);
if (itemPrefab == selectedItem)
{
if (prevContainedItems[i] != itemContainer.Inventory.Items[i])
{
itemsChanged = true;
break;
}
activateButton.Enabled = canBeFabricated;
}
child.GetChild<GUITextBlock>().TextColor = Color.White * (canBeFabricated ? 1.0f : 0.5f);
child.GetChild<GUIImage>().Color = itemPrefab.TargetItem.InventoryIconColor * (canBeFabricated ? 1.0f : 0.5f);
}
if (itemsChanged) CheckFabricableItems(character);
}
GuiFrame.Update((float)Timing.Step);
}
public void ClientWrite(NetBuffer msg, object[] extraData = null)
@@ -227,8 +369,10 @@ namespace Barotrauma.Items.Components
public void ClientRead(ServerNetObject type, NetBuffer msg, float sendingTime)
{
int itemIndex = msg.ReadRangedInteger(-1, fabricableItems.Count - 1);
UInt16 userID = msg.ReadUInt16();
Character user = Entity.FindEntityByID(userID) as Character;
if (itemIndex == -1)
if (itemIndex == -1 || user == null)
{
CancelFabricating();
}
@@ -239,7 +383,7 @@ namespace Barotrauma.Items.Components
if (itemIndex < 0 || itemIndex >= fabricableItems.Count) return;
SelectItem(null, fabricableItems[itemIndex]);
StartFabricating(fabricableItems[itemIndex]);
StartFabricating(fabricableItems[itemIndex], user);
}
}
}
@@ -1,126 +1,225 @@
using Microsoft.Xna.Framework;
using Barotrauma.Extensions;
using FarseerPhysics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
namespace Barotrauma.Items.Components
{
partial class MiniMap : Powered
{
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
private GUIFrame submarineContainer;
private GUIFrame hullInfoFrame;
private GUITextBlock hullNameText, hullBreachText, hullAirQualityText, hullWaterText;
private List<Submarine> displayedSubs = new List<Submarine>();
partial void InitProjSpecific(XElement element)
{
new GUICustomComponent(new RectTransform(new Vector2(0.9f, 0.85f), GuiFrame.RectTransform, Anchor.Center),
DrawHUDBack, null);
submarineContainer = new GUIFrame(new RectTransform(new Vector2(0.9f, 0.85f), GuiFrame.RectTransform, Anchor.Center), style: null);
hullInfoFrame = new GUIFrame(new RectTransform(new Vector2(0.13f, 0.13f), GUI.Canvas, minSize: new Point(250, 150)),
style: "InnerFrame")
{
CanBeFocused = false
};
var hullInfoContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.9f), hullInfoFrame.RectTransform, Anchor.Center))
{
Stretch = true,
RelativeSpacing = 0.05f
};
hullNameText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.4f), hullInfoContainer.RectTransform), "");
hullBreachText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.3f), hullInfoContainer.RectTransform), "");
hullAirQualityText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.3f), hullInfoContainer.RectTransform), "");
hullWaterText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.3f), hullInfoContainer.RectTransform), "");
hullInfoFrame.Children.ForEach(c => { c.CanBeFocused = false; c.Children.ForEach(c2 => c2.CanBeFocused = false); });
}
public override void AddToGUIUpdateList()
{
base.AddToGUIUpdateList();
if (hasPower) hullInfoFrame.AddToGUIUpdateList();
}
public override void OnMapLoaded()
{
base.OnMapLoaded();
CreateHUD();
}
private void CreateHUD()
{
submarineContainer.ClearChildren();
if (item.Submarine == null) return;
int width = GuiFrame.Rect.Width, height = GuiFrame.Rect.Height;
int x = GuiFrame.Rect.X;
int y = GuiFrame.Rect.Y;
item.Submarine.CreateMiniMap(submarineContainer);
displayedSubs.Clear();
displayedSubs.Add(item.Submarine);
displayedSubs.AddRange(item.Submarine.DockedTo);
}
GuiFrame.Draw(spriteBatch);
public override void UpdateHUD(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
!displayedSubs.Contains(item.Submarine) || //current sub not displayer
item.Submarine.DockedTo.Any(s => !displayedSubs.Contains(s)) || //some of the docked subs not diplayed
displayedSubs.Any(s => s != item.Submarine && !item.Submarine.DockedTo.Contains(s))) //displaying a sub that shouldn't be displayed
{
CreateHUD();
}
if (!hasPower) return;
float distort = 1.0f - item.Condition / 100.0f;
foreach (HullData hullData in hullDatas.Values)
{
hullData.DistortionTimer -= deltaTime;
if (hullData.DistortionTimer <= 0.0f)
{
hullData.Distort = Rand.Range(0.0f, 1.0f) < distort * distort;
if (hullData.Distort)
{
hullData.Oxygen = Rand.Range(0.0f, 100.0f);
hullData.Water = Rand.Range(0.0f, 1.0f);
}
hullData.DistortionTimer = Rand.Range(1.0f, 10.0f);
}
}
}
Rectangle miniMap = new Rectangle(x + 20, y + 40, width - 40, height - 60);
private void DrawHUDBack(SpriteBatch spriteBatch, GUICustomComponent container)
{
hullInfoFrame.Visible = false;
if (item.Submarine == null || !hasPower)
{
foreach (Hull hull in Hull.hullList)
{
var hullFrame = submarineContainer.Children.First().FindChild(hull);
if (hullFrame == null) continue;
float size = Math.Min((float)miniMap.Width / (float)item.Submarine.Borders.Width, (float)miniMap.Height / (float)item.Submarine.Borders.Height);
hullFrame.Color = Color.DarkCyan * 0.3f;
hullFrame.Children.First().Color = Color.DarkCyan * 0.3f;
}
}
float scale = 1.0f;
HashSet<Submarine> subs = new HashSet<Submarine>();
foreach (Hull hull in Hull.hullList)
{
Point topLeft = new Point(
miniMap.X + (int)((hull.Rect.X - item.Submarine.HiddenSubPosition.X - item.Submarine.Borders.X) * size),
miniMap.Y - (int)((hull.Rect.Y - item.Submarine.HiddenSubPosition.Y - item.Submarine.Borders.Y) * size));
if (hull.Submarine == null) continue;
var hullFrame = submarineContainer.Children.First().FindChild(hull);
if (hullFrame == null) continue;
Point bottomRight = new Point(
topLeft.X + (int)(hull.Rect.Width * size),
topLeft.Y + (int)(hull.Rect.Height * size));
topLeft.X = (int)MathUtils.RoundTowardsClosest(topLeft.X, 4);
topLeft.Y = (int)MathUtils.RoundTowardsClosest(topLeft.Y, 4);
bottomRight.X = (int)MathUtils.RoundTowardsClosest(bottomRight.X, 4);
bottomRight.Y = (int)MathUtils.RoundTowardsClosest(bottomRight.Y, 4);
Rectangle hullRect = new Rectangle(
topLeft, bottomRight - topLeft);
HullData hullData;
hullDatas.TryGetValue(hull, out hullData);
Color borderColor = Color.Green;
//hull integrity -----------------------------------
hullDatas.TryGetValue(hull, out HullData hullData);
if (hullData == null)
{
hullData = new HullData();
hullDatas.Add(hull, hullData);
}
if (hullData.Distort)
{
hullFrame.Children.First().Color = Color.Lerp(Color.Black, Color.DarkGray * 0.5f, Rand.Range(0.0f, 1.0f));
hullFrame.Color = Color.DarkGray * 0.5f;
continue;
}
subs.Add(hull.Submarine);
scale = Math.Min(
hullFrame.Parent.Rect.Width / (float)hull.Submarine.Borders.Width,
hullFrame.Parent.Rect.Height / (float)hull.Submarine.Borders.Height);
Color borderColor = Color.DarkCyan;
float? gapOpenSum = 0.0f;
if (ShowHullIntegrity)
{
gapOpenSum = hull.ConnectedGaps.Where(g => !g.IsRoomToRoom).Sum(g => g.Open);
borderColor = Color.Lerp(borderColor, Color.Red, Math.Min((float)gapOpenSum, 1.0f));
borderColor = Color.Lerp(Color.DarkCyan, Color.Red, Math.Min((float)gapOpenSum, 1.0f));
}
//oxygen -----------------------------------
float? oxygenAmount = null;
if (RequireOxygenDetectors && (hullData == null || hullData.Oxygen == null))
if (!RequireOxygenDetectors || hullData?.Oxygen != null)
{
borderColor *= 0.5f;
oxygenAmount = RequireOxygenDetectors ? hullData.Oxygen : hull.OxygenPercentage;
GUI.DrawRectangle(spriteBatch, hullFrame.Rect, Color.Lerp(Color.Red * 0.5f, Color.Green * 0.3f, (float)oxygenAmount / 100.0f), true);
}
else
{
oxygenAmount = hullData != null && hullData.Oxygen != null ? (float)hullData.Oxygen : hull.OxygenPercentage;
GUI.DrawRectangle(spriteBatch, hullRect, Color.Lerp(Color.Red * 0.5f, Color.Green * 0.3f, (float)oxygenAmount / 100.0f), true);
}
//water -----------------------------------
float? waterAmount = null;
if (RequireWaterDetectors && (hullData == null || hullData.Water == null))
if (!RequireWaterDetectors || hullData.Water != null)
{
borderColor *= 0.5f;
}
else
{
waterAmount = hullData != null && hullData.Water != null ?
(float)hullData.Water :
Math.Min(hull.WaterVolume / hull.Volume, 1.0f);
if (hullRect.Height * waterAmount > 3.0f)
waterAmount = RequireWaterDetectors ? hullData.Water : Math.Min(hull.WaterVolume / hull.Volume, 1.0f);
if (hullFrame.Rect.Height * waterAmount > 3.0f)
{
Rectangle waterRect = new Rectangle(
hullRect.X,
(int)(hullRect.Y + hullRect.Height * (1.0f - waterAmount)),
hullRect.Width,
(int)(hullRect.Height * waterAmount));
hullFrame.Rect.X, (int)(hullFrame.Rect.Y + hullFrame.Rect.Height * (1.0f - waterAmount)),
hullFrame.Rect.Width, (int)(hullFrame.Rect.Height * waterAmount));
waterRect.Inflate(-3, -3);
GUI.DrawRectangle(spriteBatch, waterRect, Color.DarkBlue, true);
GUI.DrawRectangle(spriteBatch, waterRect, new Color(85, 136, 147), true);
GUI.DrawLine(spriteBatch, new Vector2(waterRect.X, waterRect.Y), new Vector2(waterRect.Right, waterRect.Y), Color.LightBlue);
}
}
if (hullRect.Contains(PlayerInput.MousePosition))
if (GUI.MouseOn == hullFrame || hullFrame.IsParentOf(GUI.MouseOn))
{
borderColor = Color.White;
hullInfoFrame.RectTransform.ScreenSpaceOffset = hullFrame.Rect.Center;
if (gapOpenSum > 0.1f)
{
GUI.DrawString(spriteBatch,
new Vector2(x + 10, y + height - 60),
TextManager.Get("MiniMapHullBreach"), Color.Red, Color.Black * 0.5f, 2, GUI.SmallFont);
}
hullInfoFrame.Visible = true;
hullNameText.Text = hull.RoomName;
GUI.DrawString(spriteBatch,
new Vector2(x + 10, y + height - 60),
oxygenAmount == null ? TextManager.Get("MiniMapAirQualityUnavailable") : TextManager.Get("MiniMapAirQuality") + ": " + (int)oxygenAmount + " %",
oxygenAmount == null ? Color.Red : Color.Lerp(Color.Red, Color.LightGreen, (float)oxygenAmount / 100.0f),
Color.Black * 0.5f, 2, GUI.SmallFont);
hullBreachText.Text = gapOpenSum > 0.1f ? TextManager.Get("MiniMapHullBreach") : "";
hullBreachText.TextColor = Color.Red;
GUI.DrawString(spriteBatch,
new Vector2(x + 10, y + height - 40),
waterAmount == null ? TextManager.Get("MiniMapWaterLevelUnavailable") : TextManager.Get("MiniMapWaterLevel") + ": " + (int)(waterAmount * 100.0f) + " %",
waterAmount == null ? Color.Red : Color.Lerp(Color.LightGreen, Color.Red, (float)waterAmount),
Color.Black * 0.5f, 2, GUI.SmallFont);
hullAirQualityText.Text = oxygenAmount == null ? TextManager.Get("MiniMapAirQualityUnavailable") : TextManager.Get("MiniMapAirQuality") + ": " + (int)oxygenAmount + " %";
hullAirQualityText.TextColor = oxygenAmount == null ? Color.Red : Color.Lerp(Color.Red, Color.LightGreen, (float)oxygenAmount / 100.0f);
hullWaterText.Text = waterAmount == null ? TextManager.Get("MiniMapWaterLevelUnavailable") : TextManager.Get("MiniMapWaterLevel") + ": " + (int)(waterAmount * 100.0f) + " %";
hullWaterText.TextColor = waterAmount == null ? Color.Red : Color.Lerp(Color.LightGreen, Color.Red, (float)waterAmount);
borderColor = Color.Lerp(borderColor, Color.White, 0.5f);
hullFrame.Children.First().Color = Color.White;
}
else
{
hullFrame.Children.First().Color = Color.DarkCyan * 0.8f;
}
hullFrame.Color = borderColor;
}
GUI.DrawRectangle(spriteBatch, hullRect, borderColor, false, 0.0f, 2);
foreach (Submarine sub in subs)
{
if (sub.HullVertices == null) { continue; }
Rectangle worldBorders = sub.GetDockedBorders();
worldBorders.Location += sub.WorldPosition.ToPoint();
scale = Math.Min(
submarineContainer.Rect.Width / (float)worldBorders.Width,
submarineContainer.Rect.Height / (float)worldBorders.Height) * 0.9f;
float displayScale = ConvertUnits.ToDisplayUnits(scale);
Vector2 offset = ConvertUnits.ToSimUnits(sub.WorldPosition - new Vector2(worldBorders.Center.X, worldBorders.Y - worldBorders.Height / 2));
Vector2 center = container.Rect.Center.ToVector2();
for (int i = 0; i < sub.HullVertices.Count; i++)
{
Vector2 start = (sub.HullVertices[i] + offset) * displayScale;
start.Y = -start.Y;
Vector2 end = (sub.HullVertices[(i + 1) % sub.HullVertices.Count] + offset) * displayScale;
end.Y = -end.Y;
GUI.DrawLine(spriteBatch, center + start, center + end, Color.DarkCyan * Rand.Range(0.3f, 0.35f), width: 10);
}
}
}
}
@@ -1,20 +1,62 @@
using Barotrauma.Networking;
using Barotrauma.Particles;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
using System.Xml.Linq;
namespace Barotrauma.Items.Components
{
partial class Pump : Powered, IServerSerializable, IClientSerializable
{
private GUITickBox isActiveTickBox;
private GUIScrollBar isActiveSlider;
private GUIScrollBar pumpSpeedSlider;
private GUITickBox powerIndicator;
partial void InitProjSpecific()
private List<Pair<Vector2, ParticleEmitter>> pumpOutEmitters = new List<Pair<Vector2, ParticleEmitter>>();
private List<Pair<Vector2, ParticleEmitter>> pumpInEmitters = new List<Pair<Vector2, ParticleEmitter>>();
partial void InitProjSpecific(XElement element)
{
isActiveTickBox = new GUITickBox(new Rectangle(0, 0, 20, 20), TextManager.Get("PumpRunning"), Alignment.TopLeft, GuiFrame);
isActiveTickBox.OnSelected = (GUITickBox box) =>
foreach (XElement subElement in element.Elements())
{
switch (subElement.Name.ToString().ToLowerInvariant())
{
case "pumpoutemitter":
pumpOutEmitters.Add(new Pair<Vector2, ParticleEmitter>(
subElement.GetAttributeVector2("position", Vector2.Zero),
new ParticleEmitter(subElement)));
break;
case "pumpinemitter":
pumpInEmitters.Add(new Pair<Vector2, ParticleEmitter>(
subElement.GetAttributeVector2("position", Vector2.Zero),
new ParticleEmitter(subElement)));
break;
}
}
if (GuiFrame == null) { return; }
GUIFrame paddedFrame = new GUIFrame(new RectTransform(new Vector2(0.9f, 0.8f), GuiFrame.RectTransform, Anchor.Center), style: null);
isActiveSlider = new GUIScrollBar(new RectTransform(new Point(50, 100), paddedFrame.RectTransform, Anchor.CenterLeft),
barSize: 0.2f, style: "OnOffLever")
{
IsBooleanSwitch = true,
MinValue = 0.25f,
MaxValue = 0.75f
};
var sliderHandle = isActiveSlider.GetChild<GUIButton>();
sliderHandle.RectTransform.NonScaledSize = new Point(84, sliderHandle.Rect.Height);
isActiveSlider.OnMoved = (GUIScrollBar scrollBar, float barScroll) =>
{
bool active = scrollBar.BarScroll < 0.5f;
if (active == IsActive) return false;
targetLevel = null;
IsActive = !IsActive;
IsActive = active;
if (!IsActive) currPowerConsumption = 0.0f;
if (GameMain.Server != null)
@@ -31,66 +73,102 @@ namespace Barotrauma.Items.Components
return true;
};
var button = new GUIButton(new Rectangle(160, 40, 35, 30), TextManager.Get("PumpOut"), "", GuiFrame);
button.OnClicked = (GUIButton btn, object obj) =>
var rightArea = new GUILayoutGroup(new RectTransform(new Vector2(0.75f, 1.0f), paddedFrame.RectTransform, Anchor.CenterRight)) { RelativeSpacing = 0.1f };
powerIndicator = new GUITickBox(new RectTransform(new Point(30, 30), rightArea.RectTransform), TextManager.Get("PumpPowered"), style: "IndicatorLightGreen")
{
FlowPercentage -= 10.0f;
if (GameMain.Server != null)
{
item.CreateServerEvent(this);
GameServer.Log(Character.Controlled.LogName + " set the pumping speed of " + item.Name + " to " + (int)(flowPercentage) + " %", ServerLog.MessageType.ItemInteraction);
}
else if (GameMain.Client != null)
{
correctionTimer = CorrectionDelay;
item.CreateClientEvent(this);
}
return true;
CanBeFocused = false
};
button = new GUIButton(new Rectangle(210, 40, 35, 30), TextManager.Get("PumpIn"), "", GuiFrame);
button.OnClicked = (GUIButton btn, object obj) =>
var pumpSpeedText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.2f), rightArea.RectTransform) { RelativeOffset = new Vector2(0.25f, 0.0f) },
"", textAlignment: Alignment.BottomLeft);
string pumpSpeedStr = TextManager.Get("PumpSpeed");
pumpSpeedText.TextGetter = () => { return pumpSpeedStr + ": " + (int)flowPercentage + " %"; };
var sliderArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.3f), rightArea.RectTransform, Anchor.CenterLeft), isHorizontal: true)
{
FlowPercentage += 10.0f;
if (GameMain.Server != null)
{
item.CreateServerEvent(this);
GameServer.Log(Character.Controlled.LogName + " set the pumping speed of " + item.Name + " to " + (int)(flowPercentage) + " %", ServerLog.MessageType.ItemInteraction);
}
else if (GameMain.Client != null)
{
correctionTimer = CorrectionDelay;
item.CreateClientEvent(this);
}
return true;
Stretch = true,
RelativeSpacing = 0.05f
};
new GUITextBlock(new RectTransform(new Vector2(0.15f, 1.0f), sliderArea.RectTransform),
TextManager.Get("PumpOut"), textAlignment: Alignment.Center);
pumpSpeedSlider = new GUIScrollBar(new RectTransform(new Vector2(0.8f, 1.0f), sliderArea.RectTransform), barSize: 0.25f, style: "GUISlider")
{
Step = 0.05f,
OnMoved = (GUIScrollBar scrollBar, float barScroll) =>
{
float newValue = barScroll * 200.0f - 100.0f;
if (Math.Abs(newValue - FlowPercentage) < 0.1f) return false;
FlowPercentage = newValue;
if (GameMain.Server != null)
{
item.CreateServerEvent(this);
GameServer.Log(Character.Controlled.LogName + " set the pumping speed of " + item.Name + " to " + (int)(flowPercentage) + " %", ServerLog.MessageType.ItemInteraction);
}
else if (GameMain.Client != null)
{
correctionTimer = CorrectionDelay;
item.CreateClientEvent(this);
}
return true;
}
};
new GUITextBlock(new RectTransform(new Vector2(0.15f, 1.0f), sliderArea.RectTransform),
TextManager.Get("PumpIn"), textAlignment: Alignment.Center);
}
public override void OnItemLoaded()
{
if (pumpSpeedSlider != null)
{
pumpSpeedSlider.BarScroll = (flowPercentage + 100.0f) / 200.0f;
}
}
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
partial void UpdateProjSpecific(float deltaTime)
{
int x = GuiFrame.Rect.X;
int y = GuiFrame.Rect.Y;
GuiFrame.Draw(spriteBatch);
GUI.Font.DrawString(spriteBatch, TextManager.Get("PumpSpeed") + ": " + (int)flowPercentage + " %", new Vector2(x + 40, y + 85), Color.White);
if (FlowPercentage < 0.0f)
{
foreach (Pair<Vector2, ParticleEmitter> pumpOutEmitter in pumpOutEmitters)
{
//only emit "pump out" particles when underwater
Vector2 particlePos = item.Rect.Location.ToVector2() + pumpOutEmitter.First;
if (item.CurrentHull != null && item.CurrentHull.Surface < particlePos.Y) continue;
pumpOutEmitter.Second.Emit(deltaTime, item.WorldRect.Location.ToVector2() + pumpOutEmitter.First * item.Scale, item.CurrentHull,
velocityMultiplier: MathHelper.Lerp(0.5f, 1.0f, -FlowPercentage / 100.0f));
}
}
else if (FlowPercentage > 0.0f)
{
foreach (Pair<Vector2, ParticleEmitter> pumpInEmitter in pumpInEmitters)
{
pumpInEmitter.Second.Emit(deltaTime, item.WorldRect.Location.ToVector2() + pumpInEmitter.First * item.Scale, item.CurrentHull,
velocityMultiplier: MathHelper.Lerp(0.5f, 1.0f, FlowPercentage / 100.0f));
}
}
}
public override void AddToGUIUpdateList()
public override void UpdateHUD(Character character, float deltaTime, Camera cam)
{
GuiFrame.AddToGUIUpdateList();
}
powerIndicator.Selected = hasPower && IsActive;
public override void UpdateHUD(Character character)
{
GuiFrame.Update(1.0f / 60.0f);
}
if (!PlayerInput.LeftButtonHeld())
{
isActiveSlider.BarScroll += (IsActive ? -10.0f : 10.0f) * deltaTime;
float pumpSpeedScroll = (FlowPercentage + 100.0f) / 200.0f;
if (Math.Abs(pumpSpeedScroll - pumpSpeedSlider.BarScroll) > 0.01f)
{
pumpSpeedSlider.BarScroll = pumpSpeedScroll;
}
}
}
public void ClientWrite(Lidgren.Network.NetBuffer msg, object[] extraData = null)
{
//flowpercentage can only be adjusted at 10% intervals -> no need for more accuracy than this
@@ -1,468 +0,0 @@
using Barotrauma.Networking;
using FarseerPhysics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
using Voronoi2;
namespace Barotrauma.Items.Components
{
partial class Radar : Powered, IServerSerializable, IClientSerializable
{
private GUITickBox isActiveTickBox;
private List<RadarBlip> radarBlips;
private static Color[] blipColorGradient =
{
Color.TransparentBlack,
new Color(0, 50, 160),
new Color(0, 133, 166),
new Color(2, 159, 30),
new Color(255, 255, 255)
};
public override void AddToGUIUpdateList()
{
GuiFrame.AddToGUIUpdateList();
}
public override void UpdateHUD(Character character)
{
GuiFrame.Update((float)Timing.Step);
for (int i = radarBlips.Count - 1; i >= 0; i--)
{
radarBlips[i].FadeTimer -= (float)Timing.Step * 0.5f;
if (radarBlips[i].FadeTimer <= 0.0f) radarBlips.RemoveAt(i);
}
if (IsActive)
{
float pingRadius = displayRadius * pingState;
Ping(item.WorldPosition, pingRadius, prevPingRadius, displayScale, range, 2.0f);
prevPingRadius = pingRadius;
return;
}
float passivePingRadius = (float)Math.Sin(Timing.TotalTime * 10);
if (passivePingRadius > 0.0f)
{
foreach (AITarget t in AITarget.List)
{
if (t.SoundRange <= 0.0f) continue;
if (Vector2.Distance(t.WorldPosition, item.WorldPosition) < t.SoundRange)
{
Ping(t.WorldPosition, t.SoundRange * passivePingRadius * 0.2f, t.SoundRange * prevPassivePingRadius * 0.2f, displayScale, t.SoundRange, 0.5f);
radarBlips.Add(new RadarBlip(t.WorldPosition, 1.0f, 1.0f));
}
}
}
prevPassivePingRadius = passivePingRadius;
}
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
{
GuiFrame.Draw(spriteBatch);
int radius = GuiFrame.Rect.Height / 2 - 10;
DrawRadar(spriteBatch, new Rectangle((int)GuiFrame.Center.X - radius, (int)GuiFrame.Center.Y - radius, radius * 2, radius * 2));
}
private void DrawRadar(SpriteBatch spriteBatch, Rectangle rect)
{
center = new Vector2(rect.X + rect.Width * 0.5f, rect.Center.Y);
displayRadius = (rect.Width / 2.0f) * (1.0f - displayBorderSize);
displayScale = displayRadius / range;
if (IsActive)
{
pingCircle.Draw(spriteBatch, center, Color.White * (1.0f - pingState), 0.0f, (displayRadius * 2 / pingCircle.size.X) * pingState);
}
if (item.Submarine != null && !DetectSubmarineWalls)
{
float simScale = displayScale * Physics.DisplayToSimRation;
foreach (Submarine submarine in Submarine.Loaded)
{
if (submarine != item.Submarine && !submarine.DockedTo.Contains(item.Submarine)) continue;
if (submarine.HullVertices == null) continue;
Vector2 offset = ConvertUnits.ToSimUnits(submarine.WorldPosition - item.WorldPosition);
for (int i = 0; i < submarine.HullVertices.Count; i++)
{
Vector2 start = (submarine.HullVertices[i] + offset) * simScale;
start.Y = -start.Y;
Vector2 end = (submarine.HullVertices[(i + 1) % submarine.HullVertices.Count] + offset) * simScale;
end.Y = -end.Y;
GUI.DrawLine(spriteBatch, center + start, center + end, Color.LightBlue);
}
}
}
if (radarBlips.Count > 0)
{
spriteBatch.End();
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Additive);
foreach (RadarBlip radarBlip in radarBlips)
{
DrawBlip(spriteBatch, radarBlip, center, radarBlip.FadeTimer / 2.0f);
}
spriteBatch.End();
spriteBatch.Begin(SpriteSortMode.Immediate, null, null, null, GameMain.ScissorTestEnable);
}
if (GameMain.DebugDraw)
{
GUI.DrawString(spriteBatch, rect.Location.ToVector2(), radarBlips.Count.ToString(), Color.White);
}
if (screenOverlay != null)
{
screenOverlay.Draw(spriteBatch, center, 0.0f, rect.Width / screenOverlay.size.X);
}
if (GameMain.GameSession == null) return;
DrawMarker(spriteBatch,
GameMain.GameSession.StartLocation.Name,
(Level.Loaded.StartPosition - item.WorldPosition), displayScale, center, (rect.Width * 0.5f));
DrawMarker(spriteBatch,
GameMain.GameSession.EndLocation.Name,
(Level.Loaded.EndPosition - item.WorldPosition), displayScale, center, (rect.Width * 0.5f));
if (GameMain.GameSession.Mission != null)
{
var mission = GameMain.GameSession.Mission;
if (!string.IsNullOrWhiteSpace(mission.RadarLabel) && mission.RadarPosition != Vector2.Zero)
{
DrawMarker(spriteBatch,
mission.RadarLabel,
mission.RadarPosition - item.WorldPosition, displayScale, center, (rect.Width * 0.55f));
}
}
foreach (Submarine sub in Submarine.Loaded)
{
if (!sub.OnRadar) continue;
if (item.Submarine == sub || sub.DockedTo.Contains(item.Submarine)) continue;
if (sub.WorldPosition.Y > Level.Loaded.Size.Y) continue;
DrawMarker(spriteBatch, sub.Name, sub.WorldPosition - item.WorldPosition, displayScale, center, (rect.Width * 0.45f));
}
if (!GameMain.DebugDraw) return;
var steering = item.GetComponent<Steering>();
if (steering == null || steering.SteeringPath == null) return;
Vector2 prevPos = Vector2.Zero;
foreach (WayPoint wp in steering.SteeringPath.Nodes)
{
Vector2 pos = (wp.Position - item.WorldPosition) * displayScale;
if (pos.Length() > displayRadius) continue;
pos.Y = -pos.Y;
pos += center;
GUI.DrawRectangle(spriteBatch, new Rectangle((int)pos.X - 3 / 2, (int)pos.Y - 3, 6, 6), (steering.SteeringPath.CurrentNode == wp) ? Color.LightGreen : Color.Green, false);
if (prevPos != Vector2.Zero)
{
GUI.DrawLine(spriteBatch, pos, prevPos, Color.Green);
}
prevPos = pos;
}
}
private void Ping(Vector2 pingSource, float pingRadius, float prevPingRadius, float displayScale, float range, float pingStrength = 1.0f)
{
//inside a hull -> only show the edges of the hull
if (item.CurrentHull != null && DetectSubmarineWalls)
{
CreateBlipsForLine(
new Vector2(item.CurrentHull.WorldRect.X, item.CurrentHull.WorldRect.Y),
new Vector2(item.CurrentHull.WorldRect.Right, item.CurrentHull.WorldRect.Y),
pingRadius, prevPingRadius, 50.0f, 5.0f, range, 2.0f);
CreateBlipsForLine(
new Vector2(item.CurrentHull.WorldRect.X, item.CurrentHull.WorldRect.Y - item.CurrentHull.Rect.Height),
new Vector2(item.CurrentHull.WorldRect.Right, item.CurrentHull.WorldRect.Y - item.CurrentHull.Rect.Height),
pingRadius, prevPingRadius, 50.0f, 5.0f, range, 2.0f);
CreateBlipsForLine(
new Vector2(item.CurrentHull.WorldRect.X, item.CurrentHull.WorldRect.Y),
new Vector2(item.CurrentHull.WorldRect.X, item.CurrentHull.WorldRect.Y - item.CurrentHull.Rect.Height),
pingRadius, prevPingRadius, 50.0f, 5.0f, range, 2.0f);
CreateBlipsForLine(
new Vector2(item.CurrentHull.WorldRect.Right, item.CurrentHull.WorldRect.Y),
new Vector2(item.CurrentHull.WorldRect.Right, item.CurrentHull.WorldRect.Y - item.CurrentHull.Rect.Height),
pingRadius, prevPingRadius, 50.0f, 5.0f, range, 2.0f);
return;
}
foreach (Submarine submarine in Submarine.Loaded)
{
if (item.Submarine == submarine && !DetectSubmarineWalls) continue;
if (item.Submarine != null && item.Submarine.DockedTo.Contains(submarine)) continue;
if (submarine.HullVertices == null) continue;
for (int i = 0; i < submarine.HullVertices.Count; i++)
{
Vector2 start = ConvertUnits.ToDisplayUnits(submarine.HullVertices[i]);
Vector2 end = ConvertUnits.ToDisplayUnits(submarine.HullVertices[(i + 1) % submarine.HullVertices.Count]);
if (item.Submarine == submarine)
{
start += Rand.Vector(500.0f);
end += Rand.Vector(500.0f);
}
CreateBlipsForLine(
start + submarine.WorldPosition,
end + submarine.WorldPosition,
pingRadius, prevPingRadius,
200.0f, 2.0f, range, 1.0f);
}
}
if (Level.Loaded != null && (item.CurrentHull == null || !DetectSubmarineWalls))
{
if (Level.Loaded.Size.Y - pingSource.Y < range)
{
CreateBlipsForLine(
new Vector2(pingSource.X - range, Level.Loaded.Size.Y),
new Vector2(pingSource.X + range, Level.Loaded.Size.Y),
pingRadius, prevPingRadius,
250.0f, 150.0f, range, pingStrength);
}
List<VoronoiCell> cells = Level.Loaded.GetCells(pingSource, 7);
foreach (VoronoiCell cell in cells)
{
foreach (GraphEdge edge in cell.edges)
{
if (!edge.isSolid) continue;
float cellDot = Vector2.Dot(cell.Center - pingSource, (edge.Center + cell.Translation) - cell.Center);
if (cellDot > 0) continue;
float facingDot = Vector2.Dot(
Vector2.Normalize(edge.point1 - edge.point2),
Vector2.Normalize(cell.Center - pingSource));
CreateBlipsForLine(
edge.point1 + cell.Translation,
edge.point2 + cell.Translation,
pingRadius, prevPingRadius,
350.0f, 3.0f * (Math.Abs(facingDot) + 1.0f), range, pingStrength);
}
}
foreach (RuinGeneration.Ruin ruin in Level.Loaded.Ruins)
{
if (!MathUtils.CircleIntersectsRectangle(pingSource, range, ruin.Area)) continue;
foreach (var ruinShape in ruin.RuinShapes)
{
foreach (RuinGeneration.Line wall in ruinShape.Walls)
{
float cellDot = Vector2.Dot(
Vector2.Normalize(ruinShape.Center - pingSource),
Vector2.Normalize((wall.A + wall.B) / 2.0f - ruinShape.Center));
if (cellDot > 0) continue;
CreateBlipsForLine(
wall.A, wall.B,
pingRadius, prevPingRadius,
100.0f, 1000.0f, range, pingStrength);
}
}
}
}
foreach (Character c in Character.CharacterList)
{
if (c.AnimController.CurrentHull != null || !c.Enabled) continue;
if (DetectSubmarineWalls && c.AnimController.CurrentHull == null && item.CurrentHull != null) continue;
foreach (Limb limb in c.AnimController.Limbs)
{
float pointDist = (limb.WorldPosition - pingSource).Length() * displayScale;
if (limb.SimPosition == Vector2.Zero || pointDist > displayRadius) continue;
if (pointDist > prevPingRadius && pointDist < pingRadius)
{
var blip = new RadarBlip(
limb.WorldPosition + Rand.Vector(limb.Mass / 10.0f),
MathHelper.Clamp(limb.Mass, 0.1f, pingStrength),
MathHelper.Clamp(limb.Mass * 0.1f, 0.1f, 2.0f));
radarBlips.Add(blip);
}
}
}
}
private void CreateBlipsForLine(Vector2 point1, Vector2 point2, float pingRadius, float prevPingRadius,
float lineStep, float zStep, float range, float pingStrength)
{
float length = (point1 - point2).Length();
Vector2 lineDir = (point2 - point1) / length;
range *= displayScale;
for (float x = 0; x < length; x += lineStep * Rand.Range(0.8f, 1.2f))
{
Vector2 point = point1 + lineDir * x;
//point += cell.Translation;
float pointDist = Vector2.Distance(item.WorldPosition, point) * displayScale;
if (pointDist > displayRadius) continue;
if (pointDist < prevPingRadius || pointDist > pingRadius) continue;
float alpha = pingStrength * Rand.Range(1.5f, 2.0f);
for (float z = 0; z < displayRadius - pointDist * displayScale; z += zStep)
{
Vector2 pos = point + Rand.Vector(150.0f) + Vector2.Normalize(point - item.WorldPosition) * z / displayScale;
float fadeTimer = alpha * (1.0f - pointDist / range);
int minDist = 200;
radarBlips.RemoveAll(b => b.FadeTimer < fadeTimer && Math.Abs(pos.X - b.Position.X) < minDist && Math.Abs(pos.Y - b.Position.Y) < minDist);
var blip = new RadarBlip(pos, fadeTimer, 1.0f + ((pointDist+z) / displayRadius));
radarBlips.Add(blip);
zStep += 0.5f;
if (z == 0)
{
alpha = Math.Min(alpha - 0.5f, 1.5f);
}
else
{
alpha -= 0.1f;
}
if (alpha < 0) break;
}
}
}
private void DrawBlip(SpriteBatch spriteBatch, RadarBlip blip, Vector2 center, float strength)
{
strength = MathHelper.Clamp(strength, 0.0f, 1.0f);
float scaledT = strength * (blipColorGradient.Length - 1);
Color color = Color.Lerp(blipColorGradient[(int)scaledT], blipColorGradient[(int)Math.Min(scaledT + 1, blipColorGradient.Length - 1)], (scaledT - (int)scaledT));
Vector2 pos = (blip.Position - item.WorldPosition) * displayScale;
pos.Y = -pos.Y;
float posDist = pos.Length();
if (posDist > displayRadius)
{
blip.FadeTimer = 0.0f;
return;
}
if (radarBlip == null)
{
GUI.DrawRectangle(spriteBatch, center + pos, Vector2.One * 4, Color.Magenta, true);
return;
}
Vector2 dir = pos / posDist;
Vector2 normal = new Vector2(dir.Y, -dir.X);
float scale = (strength + 3.0f) * blip.Scale;
radarBlip.Draw(spriteBatch, center + pos, color, radarBlip.Origin, MathUtils.VectorToAngle(pos),
new Vector2(scale * 0.5f, scale) * 0.04f, SpriteEffects.None, 0);
pos += Rand.Range(0.0f, 1.0f) * dir + Rand.Range(-scale, scale) * normal;
radarBlip.Draw(spriteBatch, center + pos, color * 0.5f, radarBlip.Origin, 0, scale * 0.08f, SpriteEffects.None, 0);
}
private void DrawMarker(SpriteBatch spriteBatch, string label, Vector2 position, float scale, Vector2 center, float radius)
{
float dist = position.Length();
position *= scale;
position.Y = -position.Y;
float textAlpha = MathHelper.Clamp(1.5f - dist / 50000.0f, 0.5f, 1.0f);
Vector2 dir = Vector2.Normalize(position);
Vector2 markerPos = (dist * scale > radius) ? dir * radius : position;
markerPos += center;
markerPos.X = (int)markerPos.X;
markerPos.Y = (int)markerPos.Y;
GUI.DrawRectangle(spriteBatch, new Rectangle((int)markerPos.X, (int)markerPos.Y, 5, 5), Color.LightBlue);
if (dir.X < 0.0f) markerPos.X -= GUI.SmallFont.MeasureString(label).X + 10;
string wrappedLabel = ToolBox.WrapText(label, 150, GUI.SmallFont);
wrappedLabel += "\n" + ((int)(dist * Physics.DisplayToRealWorldRatio) + " m");
GUI.DrawString(spriteBatch,
new Vector2(markerPos.X + 10, markerPos.Y),
wrappedLabel,
Color.LightBlue * textAlpha, Color.Black * textAlpha * 0.5f,
2, GUI.SmallFont);
}
public void ClientWrite(Lidgren.Network.NetBuffer msg, object[] extraData = null)
{
msg.Write(IsActive);
}
public void ClientRead(ServerNetObject type, Lidgren.Network.NetBuffer msg, float sendingTime)
{
if (correctionTimer > 0.0f)
{
StartDelayedCorrection(type, msg.ExtractBits(1), sendingTime);
return;
}
IsActive = msg.ReadBoolean();
isActiveTickBox.Selected = IsActive;
}
}
class RadarBlip
{
public float FadeTimer;
public Vector2 Position;
public float Scale;
public RadarBlip(Vector2 pos, float fadeTimer, float scale)
{
Position = pos;
FadeTimer = Math.Max(fadeTimer, 0.0f);
Scale = scale;
}
}
}
@@ -4,200 +4,458 @@ using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
namespace Barotrauma.Items.Components
{
partial class Reactor : Powered, IDrawableComponent, IServerSerializable, IClientSerializable
partial class Reactor : Powered, IServerSerializable, IClientSerializable
{
private GUITickBox autoTempTickBox;
private GUIScrollBar autoTempSlider;
private GUIScrollBar onOffSwitch;
private const int GraphSize = 25;
private float graphTimer;
private int updateGraphInterval = 500;
private Sprite fissionRateMeter, turbineOutputMeter;
private Sprite meterPointer;
private Sprite sectorSprite;
private float[] fissionRateGraph = new float[GraphSize];
private float[] coolingRateGraph = new float[GraphSize];
private float[] tempGraph = new float[GraphSize];
private Sprite tempMeterFrame, tempMeterBar;
private Sprite tempRangeIndicator;
private Sprite graphLine;
private GUIScrollBar fissionRateScrollBar;
private GUIScrollBar turbineOutputScrollBar;
private float[] outputGraph = new float[GraphSize];
private float[] loadGraph = new float[GraphSize];
private GUITickBox criticalHeatWarning;
private GUITickBox lowTemperatureWarning;
private GUITickBox criticalOutputWarning;
partial void InitProjSpecific()
private GUIFrame inventoryContainer;
private GUIComponent leftHUDColumn;
private Dictionary<string, GUIButton> warningButtons = new Dictionary<string, GUIButton>();
private static string[] warningTexts = new string[]
{
var button = new GUIButton(new Rectangle(410, 70, 40, 40), "-", "", GuiFrame);
button.OnPressed = () =>
{
lastUser = Character.Controlled;
if (nextServerLogWriteTime == null)
{
nextServerLogWriteTime = Math.Max(lastServerLogWriteTime + 1.0f, (float)Timing.TotalTime);
}
unsentChanges = true;
ShutDownTemp -= 100.0f;
"ReactorWarningLowTemp","ReactorWarningOverheating",
"ReactorWarningLowOutput", "ReactorWarningHighOutput",
"ReactorWarningLowFuel", "ReactorWarningFuelOut",
"ReactorWarningMeltdown","ReactorWarningSCRAM"
};
return false;
partial void InitProjSpecific(XElement element)
{
foreach (XElement subElement in element.Elements())
{
switch (subElement.Name.ToString().ToLowerInvariant())
{
case "fissionratemeter":
fissionRateMeter = new Sprite(subElement);
break;
case "turbineoutputmeter":
turbineOutputMeter = new Sprite(subElement);
break;
case "meterpointer":
meterPointer = new Sprite(subElement);
break;
case "sectorsprite":
sectorSprite = new Sprite(subElement);
break;
case "tempmeterframe":
tempMeterFrame = new Sprite(subElement);
break;
case "tempmeterbar":
tempMeterBar = new Sprite(subElement);
break;
case "temprangeindicator":
tempRangeIndicator = new Sprite(subElement);
break;
case "graphline":
graphLine = new Sprite(subElement);
break;
}
}
var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.85f), GuiFrame.RectTransform, Anchor.Center), isHorizontal: true)
{
RelativeSpacing = 0.015f,
Stretch = true
};
GUIFrame columnLeft = new GUIFrame(new RectTransform(new Vector2(0.2f, 1.0f), paddedFrame.RectTransform), style: null);
leftHUDColumn = columnLeft;
GUIFrame columnMid = new GUIFrame(new RectTransform(new Vector2(0.45f, 1.0f), paddedFrame.RectTransform), style: null);
GUIFrame columnRight = new GUIFrame(new RectTransform(new Vector2(0.35f, 1.0f), paddedFrame.RectTransform), style: null);
//----------------------------------------------------------
//left column
//----------------------------------------------------------
int buttonsPerRow = 2;
int spacing = 5;
int buttonWidth = columnLeft.Rect.Width / buttonsPerRow - (spacing * (buttonsPerRow - 1));
int buttonHeight = (int)(columnLeft.Rect.Height * 0.5f) / 4;
for (int i = 0; i < warningTexts.Length; i++)
{
var warningBtn = new GUIButton(new RectTransform(new Point(buttonWidth, buttonHeight), columnLeft.RectTransform)
{ AbsoluteOffset = new Point((i % buttonsPerRow) * (buttonWidth + spacing), (int)Math.Floor(i / (float)buttonsPerRow) * (buttonHeight + spacing)) },
TextManager.Get(warningTexts[i]), style: "IndicatorButton");
var btnText = warningBtn.GetChild<GUITextBlock>();
btnText.Font = GUI.SmallFont;
btnText.Wrap = true;
btnText.SetTextPos();
warningButtons.Add(warningTexts[i], warningBtn);
}
inventoryContainer = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.45f), columnLeft.RectTransform, Anchor.BottomLeft), style: null);
//----------------------------------------------------------
//mid column
//----------------------------------------------------------
criticalHeatWarning = new GUITickBox(new RectTransform(new Point(30, 30), columnMid.RectTransform),
TextManager.Get("ReactorWarningCriticalTemp"), font: GUI.SmallFont, style: "IndicatorLightRed")
{
CanBeFocused = false
};
lowTemperatureWarning = new GUITickBox(new RectTransform(new Point(30, 30), columnMid.RectTransform) { RelativeOffset = new Vector2(0.3f, 0.0f) },
TextManager.Get("ReactorWarningCriticalLowTemp"), font: GUI.SmallFont, style: "IndicatorLightRed")
{
CanBeFocused = false
};
criticalOutputWarning = new GUITickBox(new RectTransform(new Point(30, 30), columnMid.RectTransform) { RelativeOffset = new Vector2(0.75f, 0.0f) },
TextManager.Get("ReactorWarningCriticalOutput"), font: GUI.SmallFont, style: "IndicatorLightRed")
{
CanBeFocused = false
};
new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.05f), columnMid.RectTransform) { RelativeOffset = new Vector2(0.0f, 0.25f) },
TextManager.Get("ReactorFissionRate"));
new GUICustomComponent(new RectTransform(new Vector2(0.5f, 0.5f), columnMid.RectTransform) { RelativeOffset = new Vector2(0.0f, 0.3f) },
DrawFissionRateMeter, null)
{
ToolTip = TextManager.Get("ReactorTipFissionRate")
};
button = new GUIButton(new Rectangle(460, 70, 40, 40), "+", "", GuiFrame);
button.OnPressed = () =>
new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.05f), columnMid.RectTransform, Anchor.TopRight) { RelativeOffset = new Vector2(0.0f, 0.25f) },
TextManager.Get("ReactorTurbineOutput"));
new GUICustomComponent(new RectTransform(new Vector2(0.5f, 0.5f), columnMid.RectTransform, Anchor.TopRight) { RelativeOffset = new Vector2(0.0f, 0.3f) },
DrawTurbineOutputMeter, null)
{
lastUser = Character.Controlled;
if (nextServerLogWriteTime == null)
{
nextServerLogWriteTime = Math.Max(lastServerLogWriteTime + 1.0f, (float)Timing.TotalTime);
}
unsentChanges = true;
ShutDownTemp += 100.0f;
return false;
ToolTip = TextManager.Get("ReactorTipTurbineOutput")
};
autoTempTickBox = new GUITickBox(new Rectangle(410, 170, 20, 20), TextManager.Get("ReactorAutoTemp"), Alignment.TopLeft, GuiFrame);
autoTempTickBox.OnSelected = ToggleAutoTemp;
button = new GUIButton(new Rectangle(210, 290, 40, 40), "+", "", GuiFrame);
button.OnPressed = () =>
new GUITextBlock(new RectTransform(new Point(0, 20), columnMid.RectTransform, Anchor.BottomLeft) { AbsoluteOffset = new Point(0, 90) },
TextManager.Get("ReactorFissionRate"));
fissionRateScrollBar = new GUIScrollBar(new RectTransform(new Point(columnMid.Rect.Width, 30), columnMid.RectTransform, Anchor.BottomCenter) { AbsoluteOffset = new Point(0, 60) },
style: "GUISlider", barSize: 0.1f)
{
lastUser = Character.Controlled;
if (nextServerLogWriteTime == null)
OnMoved = (GUIScrollBar bar, float scrollAmount) =>
{
nextServerLogWriteTime = Math.Max(lastServerLogWriteTime + 1.0f, (float)Timing.TotalTime);
}
unsentChanges = true;
FissionRate += 1.0f;
LastUser = Character.Controlled;
if (nextServerLogWriteTime == null)
{
nextServerLogWriteTime = Math.Max(lastServerLogWriteTime + 1.0f, (float)Timing.TotalTime);
}
unsentChanges = true;
targetFissionRate = scrollAmount * 100.0f;
return false;
return false;
}
};
button = new GUIButton(new Rectangle(210, 340, 40, 40), "-", "", GuiFrame);
button.OnPressed = () =>
new GUITextBlock(new RectTransform(new Point(0, 20), columnMid.RectTransform, Anchor.BottomLeft) { AbsoluteOffset = new Point(0, 30) },
TextManager.Get("ReactorTurbineOutput"));
turbineOutputScrollBar = new GUIScrollBar(new RectTransform(new Point(columnMid.Rect.Width, 30), columnMid.RectTransform, Anchor.BottomCenter),
style: "GUISlider", barSize: 0.1f, isHorizontal: true)
{
lastUser = Character.Controlled;
if (nextServerLogWriteTime == null)
OnMoved = (GUIScrollBar bar, float scrollAmount) =>
{
nextServerLogWriteTime = Math.Max(lastServerLogWriteTime + 1.0f, (float)Timing.TotalTime);
}
unsentChanges = true;
FissionRate -= 1.0f;
LastUser = Character.Controlled;
if (nextServerLogWriteTime == null)
{
nextServerLogWriteTime = Math.Max(lastServerLogWriteTime + 1.0f, (float)Timing.TotalTime);
}
unsentChanges = true;
targetTurbineOutput = scrollAmount * 100.0f;
return false;
return false;
}
};
button = new GUIButton(new Rectangle(500, 290, 40, 40), "+", "", GuiFrame);
button.OnPressed = () =>
//----------------------------------------------------------
//right column
//----------------------------------------------------------
new GUITextBlock(new RectTransform(new Point(100, 20), columnRight.RectTransform), TextManager.Get("ReactorAutoTemp"))
{
lastUser = Character.Controlled;
if (nextServerLogWriteTime == null)
{
nextServerLogWriteTime = Math.Max(lastServerLogWriteTime + 1.0f, (float)Timing.TotalTime);
}
unsentChanges = true;
CoolingRate += 1.0f;
return false;
ToolTip = TextManager.Get("ReactorTipAutoTemp")
};
button = new GUIButton(new Rectangle(500, 340, 40, 40), "-", "", GuiFrame);
button.OnPressed = () =>
autoTempSlider = new GUIScrollBar(new RectTransform(new Point(100, 30), columnRight.RectTransform) { AbsoluteOffset = new Point(0, 30) },
barSize: 0.5f, style: "OnOffSlider")
{
lastUser = Character.Controlled;
if (nextServerLogWriteTime == null)
ToolTip = TextManager.Get("ReactorTipAutoTemp"),
IsBooleanSwitch = true,
BarScroll = 1.0f,
OnMoved = (scrollBar, scrollAmount) =>
{
nextServerLogWriteTime = Math.Max(lastServerLogWriteTime + 1.0f, (float)Timing.TotalTime);
LastUser = Character.Controlled;
if (nextServerLogWriteTime == null)
{
nextServerLogWriteTime = Math.Max(lastServerLogWriteTime + 1.0f, (float)Timing.TotalTime);
}
unsentChanges = true;
return true;
}
unsentChanges = true;
CoolingRate -= 1.0f;
return false;
};
onOffSwitch = new GUIScrollBar(new RectTransform(new Point(50, 80), columnRight.RectTransform, Anchor.TopRight),
barSize: 0.2f, style: "OnOffLever")
{
IsBooleanSwitch = true,
MinValue = 0.25f,
MaxValue = 0.75f,
OnMoved = (scrollBar, scrollAmount) =>
{
LastUser = Character.Controlled;
if (nextServerLogWriteTime == null)
{
nextServerLogWriteTime = Math.Max(lastServerLogWriteTime + 1.0f, (float)Timing.TotalTime);
}
unsentChanges = true;
return true;
}
};
var lever = onOffSwitch.GetChild<GUIButton>();
lever.RectTransform.NonScaledSize = new Point(lever.Rect.Width + 30, lever.Rect.Height);
var graphArea = new GUICustomComponent(new RectTransform(new Vector2(1.0f, 0.5f), columnRight.RectTransform, Anchor.BottomCenter) { AbsoluteOffset = new Point(0, 30) },
DrawGraph, null);
var loadText = new GUITextBlock(new RectTransform(new Point(100, 30), graphArea.RectTransform, Anchor.TopLeft, Pivot.BottomLeft),
"Load", textColor: Color.LightBlue, textAlignment: Alignment.CenterLeft)
{
ToolTip = TextManager.Get("ReactorTipLoad")
};
string loadStr = TextManager.Get("ReactorLoad");
loadText.TextGetter += () => { return loadStr.Replace("[kw]", ((int)load).ToString()); };
var outputText = new GUITextBlock(new RectTransform(new Point(100, 30), graphArea.RectTransform, Anchor.BottomLeft, Pivot.TopLeft),
"Output", textColor: Color.LightGreen, textAlignment: Alignment.CenterLeft)
{
ToolTip = TextManager.Get("ReactorTipPower")
};
string outputStr = TextManager.Get("ReactorOutput");
outputText.TextGetter += () => { return outputStr.Replace("[kw]", ((int)-currPowerConsumption).ToString()); };
}
public override void OnItemLoaded()
{
turbineOutputScrollBar.BarScroll = targetTurbineOutput / 100.0f;
fissionRateScrollBar.BarScroll = targetFissionRate / 100.0f;
var itemContainer = item.GetComponent<ItemContainer>();
if (itemContainer != null)
{
itemContainer.AllowUIOverlap = true;
itemContainer.Inventory.RectTransform = inventoryContainer.RectTransform;
}
}
private void DrawGraph(SpriteBatch spriteBatch, GUICustomComponent container)
{
Rectangle graphArea = new Rectangle(container.Rect.X + 30, container.Rect.Y, container.Rect.Width - 30, container.Rect.Height);
float maxLoad = loadGraph.Max();
float xOffset = graphTimer / updateGraphInterval;
DrawGraph(outputGraph, spriteBatch,
graphArea, Math.Max(10000.0f, maxLoad), xOffset, Color.LightGreen);
DrawGraph(loadGraph, spriteBatch,
graphArea, Math.Max(10000.0f, maxLoad), xOffset, Color.LightBlue);
tempMeterFrame.Draw(spriteBatch, new Vector2(graphArea.X - 30, graphArea.Y), Color.White, Vector2.Zero, 0.0f, new Vector2(1.0f, graphArea.Height / tempMeterFrame.size.Y));
float tempFill = temperature / 100.0f;
int barPadding = 5;
Vector2 meterBarPos = new Vector2(graphArea.X - 30 + tempMeterFrame.size.X / 2, graphArea.Bottom - tempMeterBar.size.Y);
while (meterBarPos.Y > graphArea.Bottom - graphArea.Height * tempFill)
{
float tempRatio = 1.0f - ((meterBarPos.Y - graphArea.Y) / graphArea.Height);
Color color = tempRatio < 0.5f ?
Color.Lerp(Color.Green, Color.Orange, tempRatio * 2.0f) :
Color.Lerp(Color.Orange, Color.Red, (tempRatio - 0.5f) * 2.0f);
tempMeterBar.Draw(spriteBatch, meterBarPos, color);
meterBarPos.Y -= (tempMeterBar.size.Y + barPadding);
}
if (temperature > optimalTemperature.Y)
{
GUI.DrawRectangle(spriteBatch,
new Vector2(graphArea.X - 30, graphArea.Y),
new Vector2(tempMeterFrame.SourceRect.Width, (graphArea.Bottom - graphArea.Height * optimalTemperature.Y / 100.0f) - graphArea.Y),
Color.Red * (float)Math.Sin(Timing.TotalTime * 5.0f) * 0.7f, isFilled: true);
}
if (temperature < optimalTemperature.X)
{
GUI.DrawRectangle(spriteBatch,
new Vector2(graphArea.X - 30, graphArea.Bottom - graphArea.Height * optimalTemperature.X / 100.0f),
new Vector2(tempMeterFrame.SourceRect.Width, graphArea.Bottom - (graphArea.Bottom - graphArea.Height * optimalTemperature.X / 100.0f)),
Color.Red * (float)Math.Sin(Timing.TotalTime * 5.0f) * 0.7f, isFilled: true);
}
tempRangeIndicator.Draw(spriteBatch, new Vector2(meterBarPos.X, graphArea.Bottom - graphArea.Height * optimalTemperature.X / 100.0f));
tempRangeIndicator.Draw(spriteBatch, new Vector2(meterBarPos.X, graphArea.Bottom - graphArea.Height * optimalTemperature.Y / 100.0f));
}
private void UpdateGraph(float deltaTime)
{
graphTimer += deltaTime * 1000.0f;
if (graphTimer > updateGraphInterval)
{
UpdateGraph(fissionRateGraph, fissionRate);
UpdateGraph(coolingRateGraph, coolingRate);
UpdateGraph(tempGraph, temperature);
UpdateGraph(outputGraph, -currPowerConsumption);
UpdateGraph(loadGraph, load);
graphTimer = 0.0f;
}
if (autoTemp)
{
fissionRateScrollBar.BarScroll = FissionRate / 100.0f;
turbineOutputScrollBar.BarScroll = TurbineOutput / 100.0f;
}
}
public void Draw(SpriteBatch spriteBatch, bool editing = false)
private void DrawFissionRateMeter(SpriteBatch spriteBatch, GUICustomComponent container)
{
GUI.DrawRectangle(spriteBatch,
new Vector2(item.Rect.X + item.Rect.Width / 2 - 6, -item.Rect.Y + 29),
new Vector2(12, 42), Color.Black);
Rectangle prevScissorRect = spriteBatch.GraphicsDevice.ScissorRectangle;
spriteBatch.End();
spriteBatch.GraphicsDevice.ScissorRectangle = container.Rect;
spriteBatch.Begin(SpriteSortMode.Deferred, rasterizerState: GameMain.ScissorTestEnable);
if (temperature > 0)
GUI.DrawRectangle(spriteBatch,
new Vector2(item.Rect.X + item.Rect.Width / 2 - 5, -item.Rect.Y + 30 + (40.0f * (1.0f - temperature / 10000.0f))),
new Vector2(10, 40 * (temperature / 10000.0f)), new Color(temperature / 10000.0f, 1.0f - (temperature / 10000.0f), 0.0f, 1.0f), true);
DrawMeter(spriteBatch, container.Rect,
fissionRateMeter, FissionRate, new Vector2(0.0f, 100.0f), optimalFissionRate, allowedFissionRate);
spriteBatch.End();
spriteBatch.GraphicsDevice.ScissorRectangle = prevScissorRect;
spriteBatch.Begin(SpriteSortMode.Deferred);
}
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
private void DrawTurbineOutputMeter(SpriteBatch spriteBatch, GUICustomComponent container)
{
DrawMeter(spriteBatch, container.Rect,
turbineOutputMeter, TurbineOutput, new Vector2(0.0f, 100.0f), optimalTurbineOutput, allowedTurbineOutput);
}
public override void UpdateHUD(Character character, float deltaTime, Camera cam)
{
IsActive = true;
int x = GuiFrame.Rect.X;
int y = GuiFrame.Rect.Y;
GuiFrame.Draw(spriteBatch);
float xOffset = graphTimer / updateGraphInterval;
GUI.Font.DrawString(spriteBatch, TextManager.Get("ReactorOutput") + ": " + (int)temperature + " kW",
new Vector2(x + 450, y + 30), Color.Red);
GUI.Font.DrawString(spriteBatch, TextManager.Get("ReactorGridLoad") + ": " + (int)load + " kW",
new Vector2(x + 600, y + 30), Color.Yellow);
bool lightOn = Timing.TotalTime % 0.5f < 0.25f && onOffSwitch.BarScroll < 0.5f;
float maxLoad = 0.0f;
foreach (float loadVal in loadGraph)
fissionRateScrollBar.Enabled = !autoTemp;
turbineOutputScrollBar.Enabled = !autoTemp;
criticalHeatWarning.Selected = temperature > allowedTemperature.Y && lightOn;
lowTemperatureWarning.Selected = temperature < allowedTemperature.X && lightOn;
criticalOutputWarning.Selected = -currPowerConsumption > load * 1.5f && lightOn;
warningButtons["ReactorWarningOverheating"].Selected = temperature > optimalTemperature.Y && lightOn;
warningButtons["ReactorWarningHighOutput"].Selected = -currPowerConsumption > load * 1.1f && lightOn;
warningButtons["ReactorWarningLowTemp"].Selected = temperature < optimalTemperature.X && lightOn;
warningButtons["ReactorWarningLowOutput"].Selected = -currPowerConsumption < load * 0.9f && lightOn;
warningButtons["ReactorWarningFuelOut"].Selected = prevAvailableFuel < fissionRate * 0.01f && lightOn;
warningButtons["ReactorWarningLowFuel"].Selected = prevAvailableFuel < fissionRate && lightOn;
warningButtons["ReactorWarningMeltdown"].Selected = meltDownTimer > MeltdownDelay * 0.5f || item.Condition == 0.0f && lightOn;
warningButtons["ReactorWarningSCRAM"].Selected = temperature > 0.1f && onOffSwitch.BarScroll > 0.5f;
AutoTemp = autoTempSlider.BarScroll < 0.5f;
shutDown = onOffSwitch.BarScroll > 0.5f;
if (shutDown)
{
maxLoad = Math.Max(maxLoad, loadVal);
}
DrawGraph(tempGraph, spriteBatch,
new Rectangle(x + 30, y + 30, 400, 250), Math.Max(10000.0f, maxLoad), xOffset, Color.Red);
DrawGraph(loadGraph, spriteBatch,
new Rectangle(x + 30, y + 30, 400, 250), Math.Max(10000.0f, maxLoad), xOffset, Color.Yellow);
GUI.Font.DrawString(spriteBatch, TextManager.Get("ReactorShutdownTemp") + ": " + (int)shutDownTemp, new Vector2(x + 450, y + 80), Color.White);
y += 300;
GUI.Font.DrawString(spriteBatch, TextManager.Get("ReactorFissionRate") + ": " + (int)fissionRate + " %", new Vector2(x + 30, y), Color.White);
DrawGraph(fissionRateGraph, spriteBatch,
new Rectangle(x + 30, y + 30, 200, 100), 100.0f, xOffset, Color.Orange);
GUI.Font.DrawString(spriteBatch, TextManager.Get("ReactorCoolingRate") + ": " + (int)coolingRate + " %", new Vector2(x + 320, y), Color.White);
DrawGraph(coolingRateGraph, spriteBatch,
new Rectangle(x + 320, y + 30, 200, 100), 100.0f, xOffset, Color.LightBlue);
}
public override void AddToGUIUpdateList()
{
GuiFrame.AddToGUIUpdateList();
}
public override void UpdateHUD(Character character)
{
GuiFrame.Update(1.0f / 60.0f);
fissionRateScrollBar.BarScroll = FissionRate / 100.0f;
turbineOutputScrollBar.BarScroll = TurbineOutput / 100.0f;
}
}
private bool ToggleAutoTemp(GUITickBox tickBox)
{
unsentChanges = true;
autoTemp = tickBox.Selected;
LastUser = Character.Controlled;
return true;
}
private void DrawMeter(SpriteBatch spriteBatch, Rectangle rect, Sprite meterSprite, float value, Vector2 range, Vector2 optimalRange, Vector2 allowedRange)
{
float scale = Math.Min(rect.Width / meterSprite.size.X, rect.Height / meterSprite.size.Y);
Vector2 pos = new Vector2(rect.Center.X, rect.Y + meterSprite.Origin.Y * scale);
Vector2 optimalRangeNormalized = new Vector2(
(optimalRange.X - range.X) / (range.Y - range.X),
(optimalRange.Y - range.X) / (range.Y - range.X));
Vector2 allowedRangeNormalized = new Vector2(
(allowedRange.X - range.X) / (range.Y - range.X),
(allowedRange.Y - range.X) / (range.Y - range.X));
Vector2 sectorRad = new Vector2(-1.57f, 1.57f);
Vector2 optimalSectorRad = new Vector2(
MathHelper.Lerp(sectorRad.X, sectorRad.Y, optimalRangeNormalized.X),
MathHelper.Lerp(sectorRad.X, sectorRad.Y, optimalRangeNormalized.Y));
Vector2 allowedSectorRad = new Vector2(
MathHelper.Lerp(sectorRad.X, sectorRad.Y, allowedRangeNormalized.X),
MathHelper.Lerp(sectorRad.X, sectorRad.Y, allowedRangeNormalized.Y));
if (optimalRangeNormalized.X == optimalRangeNormalized.Y)
{
sectorSprite.Draw(spriteBatch, pos, Color.Red, MathHelper.PiOver2, scale);
}
else
{
spriteBatch.End();
Rectangle prevScissorRect = spriteBatch.GraphicsDevice.ScissorRectangle;
spriteBatch.GraphicsDevice.ScissorRectangle = new Rectangle(0,0,GameMain.GraphicsWidth, (int)(pos.Y + (meterSprite.size.Y - meterSprite.Origin.Y) * scale));
spriteBatch.Begin(SpriteSortMode.Deferred, rasterizerState: GameMain.ScissorTestEnable);
sectorSprite.Draw(spriteBatch, pos, Color.LightGreen, MathHelper.PiOver2, scale);
sectorSprite.Draw(spriteBatch, pos, Color.Orange, optimalSectorRad.X, scale);
sectorSprite.Draw(spriteBatch, pos, Color.Red, allowedSectorRad.X, scale);
sectorSprite.Draw(spriteBatch, pos, Color.Orange, MathHelper.Pi + optimalSectorRad.Y, scale);
sectorSprite.Draw(spriteBatch, pos, Color.Red, MathHelper.Pi + allowedSectorRad.Y, scale);
spriteBatch.End();
spriteBatch.GraphicsDevice.ScissorRectangle = prevScissorRect;
spriteBatch.Begin(SpriteSortMode.Deferred);
}
meterSprite.Draw(spriteBatch, pos, 0, scale);
float normalizedValue = (value - range.X) / (range.Y - range.X);
float valueRad = MathHelper.Lerp(sectorRad.X, sectorRad.Y, normalizedValue);
meterPointer.Draw(spriteBatch, pos, valueRad, scale);
}
static void UpdateGraph<T>(IList<T> graph, T newValue)
{
for (int i = graph.Count - 1; i > 0; i--)
@@ -207,8 +465,13 @@ namespace Barotrauma.Items.Components
graph[0] = newValue;
}
static void DrawGraph(IList<float> graph, SpriteBatch spriteBatch, Rectangle rect, float maxVal, float xOffset, Color color)
private void DrawGraph(IList<float> graph, SpriteBatch spriteBatch, Rectangle rect, float maxVal, float xOffset, Color color)
{
Rectangle prevScissorRect = spriteBatch.GraphicsDevice.ScissorRectangle;
spriteBatch.End();
spriteBatch.GraphicsDevice.ScissorRectangle = rect;
spriteBatch.Begin(SpriteSortMode.Deferred, rasterizerState: GameMain.ScissorTestEnable);
float lineWidth = (float)rect.Width / (float)(graph.Count - 2);
float yScale = (float)rect.Height / maxVal;
@@ -223,8 +486,16 @@ namespace Barotrauma.Items.Components
currX -= lineWidth;
Vector2 newPoint = new Vector2(currX, rect.Bottom - graph[i] * yScale);
GUI.DrawLine(spriteBatch, prevPoint, newPoint - new Vector2(1.0f, 0), color);
if (graphLine == null)
{
GUI.DrawLine(spriteBatch, prevPoint, newPoint - new Vector2(1.0f, 0), color);
}
else
{
Vector2 dir = Vector2.Normalize(newPoint - prevPoint);
GUI.DrawLine(spriteBatch, graphLine.Texture, prevPoint - dir, newPoint + dir, color, 0, 5);
}
prevPoint = newPoint;
}
@@ -232,16 +503,38 @@ namespace Barotrauma.Items.Components
Vector2 lastPoint = new Vector2(rect.X,
rect.Bottom - (graph[graph.Count - 1] + (graph[graph.Count - 2] - graph[graph.Count - 1]) * xOffset) * yScale);
GUI.DrawLine(spriteBatch, prevPoint, lastPoint, color);
if (graphLine == null)
{
GUI.DrawLine(spriteBatch, prevPoint, lastPoint, color);
}
else
{
GUI.DrawLine(spriteBatch, graphLine.Texture, prevPoint, lastPoint + (lastPoint - prevPoint), color, 0, 5);
}
spriteBatch.End();
spriteBatch.GraphicsDevice.ScissorRectangle = prevScissorRect;
spriteBatch.Begin(SpriteSortMode.Deferred);
}
protected override void RemoveComponentSpecific()
{
graphLine.Remove();
fissionRateMeter.Remove();
turbineOutputMeter.Remove();
meterPointer.Remove();
sectorSprite.Remove();
tempMeterFrame.Remove();
tempMeterBar.Remove();
tempRangeIndicator.Remove();
}
public void ClientWrite(NetBuffer msg, object[] extraData = null)
{
msg.Write(autoTemp);
msg.WriteRangedSingle(shutDownTemp, 0.0f, 10000.0f, 15);
msg.WriteRangedSingle(coolingRate, 0.0f, 100.0f, 8);
msg.WriteRangedSingle(fissionRate, 0.0f, 100.0f, 8);
msg.Write(shutDown);
msg.WriteRangedSingle(targetFissionRate, 0.0f, 100.0f, 8);
msg.WriteRangedSingle(targetTurbineOutput, 0.0f, 100.0f, 8);
correctionTimer = CorrectionDelay;
}
@@ -250,17 +543,20 @@ namespace Barotrauma.Items.Components
{
if (correctionTimer > 0.0f)
{
StartDelayedCorrection(type, msg.ExtractBits(16 + 1 + 15 + 8 + 8), sendingTime);
StartDelayedCorrection(type, msg.ExtractBits(1 + 1 + 8 + 8 + 8 + 8), sendingTime);
return;
}
Temperature = msg.ReadRangedSingle(0.0f, 10000.0f, 16);
AutoTemp = msg.ReadBoolean();
ShutDownTemp = msg.ReadRangedSingle(0.0f, 10000.0f, 15);
shutDown = msg.ReadBoolean();
Temperature = msg.ReadRangedSingle(0.0f, 100.0f, 8);
targetFissionRate = msg.ReadRangedSingle(0.0f, 100.0f, 8);
targetTurbineOutput = msg.ReadRangedSingle(0.0f, 100.0f, 8);
degreeOfSuccess = msg.ReadRangedSingle(0.0f, 1.0f, 8);
CoolingRate = msg.ReadRangedSingle(0.0f, 100.0f, 8);
FissionRate = msg.ReadRangedSingle(0.0f, 100.0f, 8);
fissionRateScrollBar.BarScroll = targetFissionRate / 100.0f;
turbineOutputScrollBar.BarScroll = targetTurbineOutput / 100.0f;
onOffSwitch.BarScroll = shutDown ? Math.Max(onOffSwitch.BarScroll, 0.55f) : Math.Min(onOffSwitch.BarScroll, 0.45f);
}
}
}
File diff suppressed because it is too large Load Diff
@@ -1,176 +1,565 @@
using Barotrauma.Networking;
using FarseerPhysics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
namespace Barotrauma.Items.Components
{
partial class Steering : Powered, IServerSerializable, IClientSerializable
{
private GUITickBox autopilotTickBox, maintainPosTickBox;
private GUITickBox levelEndTickBox, levelStartTickBox;
private GUITickBox autopilotTickBox, manualTickBox;
private GUITickBox maintainPosTickBox, levelEndTickBox, levelStartTickBox;
private GUIFrame autoPilotControlsDisabler;
private GUIComponent steerArea;
private GUITextBlock pressureWarningText;
private GUITextBlock tipContainer;
private string noPowerTip, autoPilotMaintainPosTip, autoPilotLevelStartTip, autoPilotLevelEndTip;
private Vector2 keyboardInput = Vector2.Zero;
private float inputCumulation;
private bool levelStartSelected;
public bool LevelStartSelected
{
get { return levelStartTickBox.Selected; }
set { levelStartTickBox.Selected = value; }
}
private bool levelEndSelected;
public bool LevelEndSelected
{
get { return levelEndTickBox.Selected; }
set { levelEndTickBox.Selected = value; }
}
private bool maintainPos;
public bool MaintainPos
{
get { return maintainPosTickBox.Selected; }
set { maintainPosTickBox.Selected = value; }
}
public bool DockingModeEnabled
{
get;
set;
}
public DockingPort DockingSource, DockingTarget;
partial void InitProjSpecific()
{
autopilotTickBox = new GUITickBox(new Rectangle(0, 25, 20, 20), TextManager.Get("SteeringAutoPilot"), Alignment.TopLeft, GuiFrame);
autopilotTickBox.OnSelected = (GUITickBox box) =>
int viewSize = (int)Math.Min(GuiFrame.Rect.Width - 150, GuiFrame.Rect.Height * 0.9f);
var controlContainer = new GUIFrame(new RectTransform(new Vector2(0.3f, 0.35f), GuiFrame.RectTransform, Anchor.CenterLeft)
{ MinSize = new Point(150, 0), AbsoluteOffset = new Point((int)(viewSize * 0.99f), (int)(viewSize * 0.05f)) }, "SonarFrame");
var paddedControlContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.8f), controlContainer.RectTransform, Anchor.Center))
{
AutoPilot = box.Selected;
unsentChanges = true;
return true;
RelativeSpacing = 0.03f,
Stretch = true
};
maintainPosTickBox = new GUITickBox(new Rectangle(5, 50, 15, 15), TextManager.Get("SteeringMaintainPos"), Alignment.TopLeft, GUI.SmallFont, GuiFrame);
maintainPosTickBox.Enabled = false;
maintainPosTickBox.OnSelected = ToggleMaintainPosition;
var statusContainer = new GUIFrame(new RectTransform(new Vector2(0.3f, 0.25f), GuiFrame.RectTransform, Anchor.BottomLeft)
{ MinSize = new Point(150, 0), AbsoluteOffset = new Point((int)(viewSize * 0.9f), 0) }, "SonarFrame");
var paddedStatusContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.9f), statusContainer.RectTransform, Anchor.Center))
{
RelativeSpacing = 0.03f,
Stretch = true
};
levelStartTickBox = new GUITickBox(
new Rectangle(5, 70, 15, 15),
manualTickBox = new GUITickBox(new RectTransform(new Vector2(0.3f, 0.3f), paddedControlContainer.RectTransform),
TextManager.Get("SteeringManual"), style: "GUIRadioButton")
{
Selected = true,
OnSelected = (GUITickBox box) =>
{
AutoPilot = !box.Selected;
unsentChanges = true;
user = Character.Controlled;
return true;
}
};
autopilotTickBox = new GUITickBox(new RectTransform(new Vector2(0.3f, 0.3f), paddedControlContainer.RectTransform),
TextManager.Get("SteeringAutoPilot"), style: "GUIRadioButton")
{
OnSelected = (GUITickBox box) =>
{
AutoPilot = box.Selected;
if (AutoPilot && MaintainPos)
{
posToMaintain = controlledSub == null ? item.WorldPosition : controlledSub.WorldPosition;
}
unsentChanges = true;
user = Character.Controlled;
return true;
}
};
GUITickBox.CreateRadioButtonGroup(new List<GUITickBox> { manualTickBox, autopilotTickBox });
var autoPilotControls = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.6f), paddedControlContainer.RectTransform), "InnerFrame");
var paddedAutoPilotControls = new GUILayoutGroup(new RectTransform(new Vector2(0.8f), autoPilotControls.RectTransform, Anchor.Center))
{
Stretch = true,
RelativeSpacing = 0.03f
};
maintainPosTickBox = new GUITickBox(new RectTransform(new Vector2(0.2f, 0.2f), paddedAutoPilotControls.RectTransform),
TextManager.Get("SteeringMaintainPos"), font: GUI.SmallFont)
{
Enabled = false,
Selected = maintainPos,
OnSelected = tickBox =>
{
if (maintainPos != tickBox.Selected)
{
unsentChanges = true;
user = Character.Controlled;
maintainPos = tickBox.Selected;
if (maintainPos)
{
if (controlledSub == null)
{
posToMaintain = null;
}
else
{
posToMaintain = controlledSub.WorldPosition;
}
}
else if (!LevelEndSelected && !LevelStartSelected)
{
AutoPilot = false;
}
if (!maintainPos)
{
posToMaintain = null;
}
}
return true;
}
};
levelStartTickBox = new GUITickBox(new RectTransform(new Vector2(0.2f, 0.2f), paddedAutoPilotControls.RectTransform),
GameMain.GameSession?.StartLocation == null ? "" : ToolBox.LimitString(GameMain.GameSession.StartLocation.Name, 20),
Alignment.TopLeft, GUI.SmallFont, GuiFrame);
levelStartTickBox.Enabled = false;
levelStartTickBox.OnSelected = SelectDestination;
font: GUI.SmallFont)
{
Enabled = false,
Selected = levelStartSelected,
OnSelected = tickBox =>
{
if (levelStartSelected != tickBox.Selected)
{
unsentChanges = true;
user = Character.Controlled;
levelStartSelected = tickBox.Selected;
levelEndSelected = !levelStartSelected;
if (levelStartSelected)
{
UpdatePath();
}
else if (!MaintainPos && !LevelEndSelected)
{
AutoPilot = false;
}
}
return true;
}
};
levelEndTickBox = new GUITickBox(
new Rectangle(5, 90, 15, 15),
levelEndTickBox = new GUITickBox(new RectTransform(new Vector2(0.2f, 0.2f), paddedAutoPilotControls.RectTransform),
GameMain.GameSession?.EndLocation == null ? "" : ToolBox.LimitString(GameMain.GameSession.EndLocation.Name, 20),
Alignment.TopLeft, GUI.SmallFont, GuiFrame);
levelEndTickBox.Enabled = false;
levelEndTickBox.OnSelected = SelectDestination;
font: GUI.SmallFont)
{
Enabled = false,
Selected = levelEndSelected,
OnSelected = tickBox =>
{
if (levelEndSelected != tickBox.Selected)
{
unsentChanges = true;
user = Character.Controlled;
levelEndSelected = tickBox.Selected;
levelStartSelected = !levelEndSelected;
if (levelEndSelected)
{
UpdatePath();
}
else if (!MaintainPos && !LevelStartSelected)
{
AutoPilot = false;
}
}
return true;
}
};
autoPilotControlsDisabler = new GUIFrame(new RectTransform(Vector2.One, autoPilotControls.RectTransform), "InnerFrame");
GUITickBox.CreateRadioButtonGroup(new List<GUITickBox> { maintainPosTickBox, levelStartTickBox, levelEndTickBox });
string steeringVelX = TextManager.Get("SteeringVelocityX");
string steeringVelY = TextManager.Get("SteeringVelocityY");
string steeringDepth = TextManager.Get("SteeringDepth");
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.25f), paddedStatusContainer.RectTransform), "")
{
TextGetter = () =>
{
Vector2 vel = controlledSub == null ? Vector2.Zero : controlledSub.Velocity;
var realWorldVel = ConvertUnits.ToDisplayUnits(vel.Y * Physics.DisplayToRealWorldRatio) * 3.6f;
return steeringVelY.Replace("[kph]", ((int)-realWorldVel).ToString());
}
};
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.25f), paddedStatusContainer.RectTransform), "")
{
TextGetter = () =>
{
Vector2 vel = controlledSub == null ? Vector2.Zero : controlledSub.Velocity;
var realWorldVel = ConvertUnits.ToDisplayUnits(vel.X * Physics.DisplayToRealWorldRatio) * 3.6f;
return steeringVelX.Replace("[kph]", ((int)realWorldVel).ToString());
}
};
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.25f), paddedStatusContainer.RectTransform), "")
{
TextGetter = () =>
{
Vector2 pos = controlledSub == null ? Vector2.Zero : controlledSub.Position;
float realWorldDepth = Level.Loaded == null ? 0.0f : Math.Abs(pos.Y - Level.Loaded.Size.Y) * Physics.DisplayToRealWorldRatio;
return steeringDepth.Replace("[m]", ((int)realWorldDepth).ToString());
}
};
pressureWarningText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.25f), paddedStatusContainer.RectTransform), TextManager.Get("SteeringDepthWarning"), Color.Red)
{
Visible = false
};
tipContainer = new GUITextBlock(new RectTransform(new Vector2(0.25f, 0.12f), GuiFrame.RectTransform, Anchor.BottomLeft)
{ MinSize = new Point(150, 0), RelativeOffset = new Vector2(0.0f, -0.05f) }, "", wrap: true, style: "GUIToolTip")
{
AutoScale = true
};
noPowerTip = TextManager.Get("SteeringNoPowerTip");
autoPilotMaintainPosTip = TextManager.Get("SteeringAutoPilotMaintainPosTip");
autoPilotLevelStartTip = TextManager.Get("SteeringAutoPilotLocationTip").Replace("[locationname]",
GameMain.GameSession?.StartLocation == null ? "Start" : GameMain.GameSession.StartLocation.Name);
autoPilotLevelEndTip = TextManager.Get("SteeringAutoPilotLocationTip").Replace("[locationname]",
GameMain.GameSession?.EndLocation == null ? "End" : GameMain.GameSession.EndLocation.Name);
steerArea = new GUICustomComponent(new RectTransform(new Point(viewSize), GuiFrame.RectTransform, Anchor.CenterLeft),
(spriteBatch, guiCustomComponent) => { DrawHUD(spriteBatch, guiCustomComponent.Rect); }, null);
}
private bool ToggleMaintainPosition(GUITickBox tickBox)
/// <summary>
/// Makes the sonar view CustomComponent render the steering HUD, preventing it from being drawn behing the sonar
/// </summary>
public void AttachToSonarHUD(GUICustomComponent sonarView)
{
unsentChanges = true;
levelStartTickBox.Selected = false;
levelEndTickBox.Selected = false;
if (item.Submarine == null)
{
posToMaintain = null;
}
else
{
posToMaintain = item.Submarine.WorldPosition;
}
tickBox.Selected = true;
return true;
steerArea.Visible = false;
sonarView.OnDraw += (spriteBatch, guiCustomComponent) => { DrawHUD(spriteBatch, guiCustomComponent.Rect); };
}
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
public void DrawHUD(SpriteBatch spriteBatch, Rectangle rect)
{
//if (voltage < minVoltage) return;
int width = GuiFrame.Rect.Width, height = GuiFrame.Rect.Height;
int x = GuiFrame.Rect.X;
int y = GuiFrame.Rect.Y;
GuiFrame.Draw(spriteBatch);
int width = rect.Width, height = rect.Height;
int x = rect.X;
int y = rect.Y;
if (voltage < minVoltage && currPowerConsumption > 0.0f) return;
Rectangle velRect = new Rectangle(x + 20, y + 20, width - 40, height - 40);
//GUI.DrawRectangle(spriteBatch, velRect, Color.White, false);
if (item.Submarine != null && Level.Loaded != null)
{
Vector2 realWorldVelocity = ConvertUnits.ToDisplayUnits(item.Submarine.Velocity * Physics.DisplayToRealWorldRatio) * 3.6f;
float realWorldDepth = Math.Abs(item.Submarine.Position.Y - Level.Loaded.Size.Y) * Physics.DisplayToRealWorldRatio;
GUI.DrawString(spriteBatch, new Vector2(x + 20, y + height - 65),
TextManager.Get("SteeringVelocityX").Replace("[kph]", ((int)realWorldVelocity.X).ToString()), Color.LightGreen, null, 0, GUI.SmallFont);
GUI.DrawString(spriteBatch, new Vector2(x + 20, y + height - 50),
TextManager.Get("SteeringVelocityY").Replace("[kph]", ((int)-realWorldVelocity.Y).ToString()), Color.LightGreen, null, 0, GUI.SmallFont);
GUI.DrawString(spriteBatch, new Vector2(x + 20, y + height - 30),
TextManager.Get("SteeringDepth").Replace("[m]", ((int)realWorldDepth).ToString()), Color.LightGreen, null, 0, GUI.SmallFont);
}
Rectangle velRect = new Rectangle(x + 20, y + 20, width - 40, height - 40);
GUI.DrawLine(spriteBatch,
new Vector2(velRect.Center.X, velRect.Center.Y),
new Vector2(velRect.Center.X + currVelocity.X, velRect.Center.Y - currVelocity.Y),
Color.Gray);
Vector2 targetVelPos = new Vector2(velRect.Center.X + targetVelocity.X, velRect.Center.Y - targetVelocity.Y);
if (!AutoPilot)
{
Vector2 unitSteeringInput = steeringInput / 100.0f;
//map input from rectangle to circle
Vector2 steeringInputPos = new Vector2(
steeringInput.X * (float)Math.Sqrt(1.0f - 0.5f * unitSteeringInput.Y * unitSteeringInput.Y),
-steeringInput.Y * (float)Math.Sqrt(1.0f - 0.5f * unitSteeringInput.X * unitSteeringInput.X));
steeringInputPos.X += velRect.Center.X;
steeringInputPos.Y += velRect.Center.Y;
GUI.DrawLine(spriteBatch,
new Vector2(velRect.Center.X, velRect.Center.Y),
steeringInputPos,
Color.LightGray);
GUI.DrawRectangle(spriteBatch, new Rectangle((int)steeringInputPos.X - 5, (int)steeringInputPos.Y - 5, 10, 10), Color.White);
//if (keyboardInput.Length() > 0 || Vector2.Distance(PlayerInput.MousePosition, new Vector2(velRect.Center.X, velRect.Center.Y)) < 200.0f)
if (velRect.Contains(PlayerInput.MousePosition))
{
GUI.DrawRectangle(spriteBatch, new Rectangle((int)steeringInputPos.X - 10, (int)steeringInputPos.Y - 10, 20, 20), Color.Red);
}
}
else if (posToMaintain.HasValue && !LevelStartSelected && !LevelEndSelected)
{
Sonar sonar = item.GetComponent<Sonar>();
if (sonar != null && controlledSub != null)
{
Vector2 displayPosToMaintain = ((posToMaintain.Value - sonar.DisplayOffset * sonar.Zoom - controlledSub.WorldPosition)) / sonar.Range * sonar.DisplayRadius * sonar.Zoom;
displayPosToMaintain.Y = -displayPosToMaintain.Y;
displayPosToMaintain = displayPosToMaintain.ClampLength(velRect.Width / 2);
displayPosToMaintain = velRect.Center.ToVector2() + displayPosToMaintain;
float crossHairSize = 8.0f;
Color crosshairColor = Color.Orange * (0.5f + ((float)Math.Sin(Timing.TotalTime * 5.0f) + 1.0f) / 4.0f);
GUI.DrawLine(spriteBatch, displayPosToMaintain + Vector2.UnitY * crossHairSize, displayPosToMaintain - Vector2.UnitY * crossHairSize, crosshairColor, width: 3);
GUI.DrawLine(spriteBatch, displayPosToMaintain + Vector2.UnitX * crossHairSize, displayPosToMaintain - Vector2.UnitX * crossHairSize, crosshairColor, width: 3);
Vector2 neutralPos = ((controlledSub.WorldPosition - sonar.DisplayOffset * sonar.Zoom - controlledSub.WorldPosition)) / sonar.Range * sonar.DisplayRadius * sonar.Zoom;
neutralPos.Y = -neutralPos.Y;
neutralPos = neutralPos.ClampLength(velRect.Width / 2);
neutralPos = velRect.Center.ToVector2() + neutralPos;
GUI.DrawRectangle(spriteBatch, new Rectangle((int)neutralPos.X - 5, (int)neutralPos.Y - 5, 10, 10), Color.Orange);
}
}
//map velocity from rectangle to circle
Vector2 unitTargetVel = targetVelocity / 100.0f;
Vector2 steeringPos = new Vector2(
targetVelocity.X * 0.9f * (float)Math.Sqrt(1.0f - 0.5f * unitTargetVel.Y * unitTargetVel.Y),
-targetVelocity.Y * 0.9f * (float)Math.Sqrt(1.0f - 0.5f * unitTargetVel.X * unitTargetVel.X));
steeringPos.X += velRect.Center.X;
steeringPos.Y += velRect.Center.Y;
GUI.DrawLine(spriteBatch,
new Vector2(velRect.Center.X, velRect.Center.Y),
targetVelPos,
Color.LightGray);
GUI.DrawRectangle(spriteBatch, new Rectangle((int)targetVelPos.X - 5, (int)targetVelPos.Y - 5, 10, 10), Color.White);
if (Vector2.Distance(PlayerInput.MousePosition, new Vector2(velRect.Center.X, velRect.Center.Y)) < 200.0f)
{
GUI.DrawRectangle(spriteBatch, new Rectangle((int)targetVelPos.X - 10, (int)targetVelPos.Y - 10, 20, 20), Color.Red);
}
steeringPos,
Color.CadetBlue, 0, 2);
}
public override void AddToGUIUpdateList()
public void DebugDrawHUD(SpriteBatch spriteBatch, Vector2 transducerCenter, float displayScale, float displayRadius, Vector2 center)
{
GuiFrame.AddToGUIUpdateList();
}
if (SteeringPath == null) return;
public override void UpdateHUD(Character character)
{
GuiFrame.Update(1.0f / 60.0f);
if (voltage < minVoltage && currPowerConsumption > 0.0f) return;
if (Vector2.Distance(PlayerInput.MousePosition, new Vector2(GuiFrame.Rect.Center.X, GuiFrame.Rect.Center.Y)) < 200.0f)
Vector2 prevPos = Vector2.Zero;
foreach (WayPoint wp in SteeringPath.Nodes)
{
if (PlayerInput.LeftButtonHeld())
Vector2 pos = (wp.Position - transducerCenter) * displayScale;
if (pos.Length() > displayRadius) continue;
pos.Y = -pos.Y;
pos += center;
GUI.DrawRectangle(spriteBatch, new Rectangle((int)pos.X - 3 / 2, (int)pos.Y - 3, 6, 6), (SteeringPath.CurrentNode == wp) ? Color.LightGreen : Color.Green, false);
if (prevPos != Vector2.Zero)
{
TargetVelocity = PlayerInput.MousePosition - new Vector2(GuiFrame.Rect.Center.X, GuiFrame.Rect.Center.Y);
targetVelocity.Y = -targetVelocity.Y;
GUI.DrawLine(spriteBatch, pos, prevPos, Color.Green);
}
unsentChanges = true;
prevPos = pos;
}
foreach (ObstacleDebugInfo obstacle in debugDrawObstacles)
{
Vector2 pos1 = (obstacle.Point1 - transducerCenter) * displayScale;
pos1.Y = -pos1.Y;
pos1 += center;
Vector2 pos2 = (obstacle.Point2 - transducerCenter) * displayScale;
pos2.Y = -pos2.Y;
pos2 += center;
GUI.DrawLine(spriteBatch,
pos1,
pos2,
Color.Red * 0.6f, width: 3);
if (obstacle.Intersection.HasValue)
{
Vector2 intersectionPos = (obstacle.Intersection.Value - transducerCenter) *displayScale;
intersectionPos.Y = -intersectionPos.Y;
intersectionPos += center;
GUI.DrawRectangle(spriteBatch, intersectionPos - Vector2.One * 2, Vector2.One * 4, Color.Red);
}
Vector2 obstacleCenter = (pos1 + pos2) / 2;
if (obstacle.AvoidStrength.LengthSquared() > 0.01f)
{
GUI.DrawLine(spriteBatch,
obstacleCenter,
obstacleCenter + new Vector2(obstacle.AvoidStrength.X, -obstacle.AvoidStrength.Y) * 100,
Color.Lerp(Color.Green, Color.Orange, obstacle.Dot), width: 2);
}
}
}
private bool SelectDestination(GUITickBox tickBox)
public override void UpdateHUD(Character character, float deltaTime, Camera cam)
{
unsentChanges = true;
if (tickBox == levelStartTickBox)
if (steerArea.Rect.Contains(PlayerInput.MousePosition))
{
levelEndTickBox.Selected = false;
if (!PlayerInput.KeyDown(InputType.Select) && !PlayerInput.KeyHit(InputType.Select))
{
Character.DisableControls = true;
}
}
autoPilotControlsDisabler.Visible = !AutoPilot;
if (voltage < minVoltage && currPowerConsumption > 0.0f)
{
tipContainer.Visible = true;
tipContainer.Text = noPowerTip;
return;
}
tipContainer.Visible = AutoPilot;
if (AutoPilot)
{
if (maintainPos)
{
tipContainer.Text = autoPilotMaintainPosTip;
}
else if (LevelStartSelected)
{
tipContainer.Text = autoPilotLevelStartTip;
}
else if (LevelEndSelected)
{
tipContainer.Text = autoPilotLevelEndTip;
}
if (DockingModeEnabled && DockingTarget != null)
{
posToMaintain += ConvertUnits.ToDisplayUnits(DockingTarget.Item.Submarine.Velocity) * deltaTime;
}
}
pressureWarningText.Visible = item.Submarine != null && item.Submarine.AtDamageDepth && Timing.TotalTime % 1.0f < 0.5f;
if (Vector2.Distance(PlayerInput.MousePosition, steerArea.Rect.Center.ToVector2()) < steerArea.Rect.Width / 2)
{
if (PlayerInput.LeftButtonHeld())
{
Vector2 inputPos = PlayerInput.MousePosition - steerArea.Rect.Center.ToVector2();
inputPos.Y = -inputPos.Y;
if (AutoPilot && !LevelStartSelected && !LevelEndSelected)
{
posToMaintain = controlledSub == null ?
item.WorldPosition :
controlledSub.WorldPosition + (sonar.DisplayOffset * sonar.Zoom) + inputPos / sonar.DisplayRadius * sonar.Range / sonar.Zoom;
}
else
{
SteeringInput = inputPos;
}
unsentChanges = true;
user = Character.Controlled;
}
}
if (!AutoPilot && Character.DisableControls)
{
steeringAdjustSpeed = character == null ? 0.2f : MathHelper.Lerp(0.2f, 1.0f, character.GetSkillLevel("helm") / 100.0f);
Vector2 input = Vector2.Zero;
if (PlayerInput.KeyDown(InputType.Left))
{
input -= Vector2.UnitX;
}
if (PlayerInput.KeyDown(InputType.Right))
{
input += Vector2.UnitX;
}
if (PlayerInput.KeyDown(InputType.Up))
{
input += Vector2.UnitY;
}
if (PlayerInput.KeyDown(InputType.Down))
{
input -= Vector2.UnitY;
}
if (PlayerInput.KeyDown(Keys.LeftShift))
{
SteeringInput += input * deltaTime * 200;
inputCumulation = 0;
keyboardInput = Vector2.Zero;
unsentChanges = true;
}
else
{
float step = deltaTime * 5;
if (input.Length() > 0)
{
inputCumulation += step;
}
else
{
inputCumulation -= step;
}
float maxCumulation = 1;
inputCumulation = MathHelper.Clamp(inputCumulation, 0, maxCumulation);
float length = MathHelper.Lerp(0, 0.2f, MathUtils.InverseLerp(0, maxCumulation, inputCumulation));
var normalizedInput = Vector2.Normalize(input);
if (MathUtils.IsValid(normalizedInput))
{
keyboardInput += normalizedInput * length;
}
if (keyboardInput.LengthSquared() > 0.01f)
{
SteeringInput += keyboardInput;
unsentChanges = true;
user = Character.Controlled;
keyboardInput *= MathHelper.Clamp(1 - step, 0, 1);
}
}
}
else
{
levelStartTickBox.Selected = false;
inputCumulation = 0;
keyboardInput = Vector2.Zero;
}
maintainPosTickBox.Selected = false;
posToMaintain = null;
tickBox.Selected = true;
UpdatePath();
float closestDist = DockingAssistThreshold * DockingAssistThreshold;
DockingModeEnabled = false;
DockingSource = null;
DockingTarget = null;
foreach (DockingPort sourcePort in DockingPort.List)
{
if (sourcePort.Docked || sourcePort.Item.Submarine == null) { continue; }
if (sourcePort.Item.Submarine != controlledSub) { continue; }
return true;
int sourceDir = sourcePort.IsHorizontal ?
Math.Sign(sourcePort.Item.WorldPosition.X - sourcePort.Item.Submarine.WorldPosition.X) :
Math.Sign(sourcePort.Item.WorldPosition.Y - sourcePort.Item.Submarine.WorldPosition.Y);
foreach (DockingPort targetPort in DockingPort.List)
{
if (targetPort.Docked || targetPort.Item.Submarine == null) { continue; }
if (targetPort.Item.Submarine == controlledSub || targetPort.IsHorizontal != sourcePort.IsHorizontal) { continue; }
if (Level.Loaded != null && targetPort.Item.Submarine.WorldPosition.Y > Level.Loaded.Size.Y) { continue; }
int targetDir = targetPort.IsHorizontal ?
Math.Sign(targetPort.Item.WorldPosition.X - targetPort.Item.Submarine.WorldPosition.X) :
Math.Sign(targetPort.Item.WorldPosition.Y - targetPort.Item.Submarine.WorldPosition.Y);
if (sourceDir == targetDir) { continue; }
float dist = Vector2.DistanceSquared(sourcePort.Item.WorldPosition, targetPort.Item.WorldPosition);
if (dist < closestDist)
{
DockingModeEnabled = true;
DockingSource = sourcePort;
DockingTarget = targetPort;
}
}
}
}
public void ClientWrite(Lidgren.Network.NetBuffer msg, object[] extraData = null)
@@ -180,8 +569,8 @@ namespace Barotrauma.Items.Components
if (!autoPilot)
{
//no need to write steering info if autopilot is controlling
msg.Write(targetVelocity.X);
msg.Write(targetVelocity.Y);
msg.Write(steeringInput.X);
msg.Write(steeringInput.Y);
}
else
{
@@ -202,11 +591,13 @@ namespace Barotrauma.Items.Components
{
long msgStartPos = msg.Position;
bool autoPilot = msg.ReadBoolean();
Vector2 newTargetVelocity = targetVelocity;
bool maintainPos = false;
Vector2? newPosToMaintain = null;
bool headingToStart = false;
bool autoPilot = msg.ReadBoolean();
Vector2 newSteeringInput = steeringInput;
Vector2 newTargetVelocity = targetVelocity;
float newSteeringAdjustSpeed = steeringAdjustSpeed;
bool maintainPos = false;
Vector2? newPosToMaintain = null;
bool headingToStart = false;
if (autoPilot)
{
@@ -224,7 +615,9 @@ namespace Barotrauma.Items.Components
}
else
{
newSteeringInput = new Vector2(msg.ReadFloat(), msg.ReadFloat());
newTargetVelocity = new Vector2(msg.ReadFloat(), msg.ReadFloat());
newSteeringAdjustSpeed = msg.ReadFloat();
}
if (correctionTimer > 0.0f)
@@ -239,11 +632,12 @@ namespace Barotrauma.Items.Components
if (!AutoPilot)
{
targetVelocity = newTargetVelocity;
SteeringInput = newSteeringInput;
TargetVelocity = newTargetVelocity;
steeringAdjustSpeed = newSteeringAdjustSpeed;
}
else
{
MaintainPos = newPosToMaintain != null;
posToMaintain = newPosToMaintain;