(7e3aa6097) Merge remote-tracking branch 'origin/docking-interface' into dev

This commit is contained in:
Joonas Rikkonen
2019-05-03 13:48:31 +03:00
parent 8d3a48584b
commit 3701f0e957
12 changed files with 603 additions and 622 deletions

View File

@@ -108,6 +108,61 @@ namespace Barotrauma
}
}
//unconscious/dead characters can't correct their position using AnimController movement
// -> we need to correct it manually
if (!character.AllowInput)
{
float mainLimbDistSqrd = Vector2.DistanceSquared(MainLimb.PullJointWorldAnchorA, Collider.SimPosition);
float mainLimbErrorTolerance = 0.1f;
//if the main limb is roughly at the correct position and the collider isn't moving (much at least),
//don't attempt to correct the position.
if (mainLimbDistSqrd > mainLimbErrorTolerance || Collider.LinearVelocity.LengthSquared() > 0.05f)
{
MainLimb.PullJointWorldAnchorB = Collider.SimPosition;
MainLimb.PullJointEnabled = true;
}
character.SelectedConstruction = character.MemState[0].SelectedItem;
}
if (character.MemState[0].Animation == AnimController.Animation.CPR)
{
character.AnimController.Anim = AnimController.Animation.CPR;
}
else if (character.AnimController.Anim == AnimController.Animation.CPR)
{
character.AnimController.Anim = AnimController.Animation.None;
}
Vector2 newVelocity = Collider.LinearVelocity;
Vector2 newPosition = Collider.SimPosition;
float newRotation = Collider.Rotation;
float newAngularVelocity = Collider.AngularVelocity;
Collider.CorrectPosition(character.MemState, out newPosition, out newVelocity, out newRotation, out newAngularVelocity);
newVelocity = newVelocity.ClampLength(100.0f);
if (!MathUtils.IsValid(newVelocity)) { newVelocity = Vector2.Zero; }
overrideTargetMovement = newVelocity.LengthSquared() > 0.01f ? newVelocity : Vector2.Zero;
Collider.LinearVelocity = newVelocity;
Collider.AngularVelocity = newAngularVelocity;
float distSqrd = Vector2.DistanceSquared(newPosition, Collider.SimPosition);
float errorTolerance = character.AllowInput ? 0.01f : 0.2f;
if (distSqrd > errorTolerance)
{
if (distSqrd > 10.0f || !character.AllowInput)
{
Collider.TargetRotation = newRotation;
SetPosition(newPosition, lerp: distSqrd < 5.0f, ignorePlatforms: false);
}
else
{
Collider.TargetRotation = newRotation;
Collider.TargetPosition = newPosition;
Collider.MoveToTargetPosition(true);
}
}
//unconscious/dead characters can't correct their position using AnimController movement
// -> we need to correct it manually
if (!character.AllowInput)
@@ -151,32 +206,34 @@ namespace Barotrauma
}
}
if (character.MemLocalState.Count > 120) character.MemLocalState.RemoveRange(0, character.MemLocalState.Count - 120);
character.MemState.Clear();
character.MemLocalState.Clear();
}
}
partial void ImpactProjSpecific(float impact, Body body)
{
float volume = MathHelper.Clamp(impact - 3.0f, 0.5f, 1.0f);
if (body.UserData is Limb limb && character.Stun <= 0f)
else
{
if (impact > 3.0f) { PlayImpactSound(limb); }
}
else if (body.UserData is Limb || body == Collider.FarseerBody)
{
if (!character.IsRemotePlayer && impact > ImpactTolerance)
//remove states with a timestamp (there may still timestamp-based states
//in the list if the controlled character switches from timestamp-based interpolation to ID-based)
character.MemState.RemoveAll(m => m.Timestamp > 0.0f);
for (int i = 0; i < character.MemLocalState.Count; i++)
{
SoundPlayer.PlayDamageSound("LimbBlunt", strongestImpact, Collider);
if (character.Submarine == null)
{
//transform in-sub coordinates to outside coordinates
if (character.MemLocalState[i].Position.Y > lowestSubPos)
{
character.MemLocalState[i].TransformInToOutside();
}
}
else if (currentHull?.Submarine != null)
{
//transform outside coordinates to in-sub coordinates
if (character.MemLocalState[i].Position.Y < lowestSubPos)
{
character.MemLocalState[i].TransformOutToInside(currentHull.Submarine);
}
}
}
}
if (Character.Controlled == character)
{
GameMain.GameScreen.Cam.Shake = Math.Min(Math.Max(strongestImpact, GameMain.GameScreen.Cam.Shake), 3.0f);
}
}
if (character.MemState.Count < 1) return;

View File

@@ -128,7 +128,7 @@ namespace Barotrauma
protected Color flashColor;
protected float flashDuration = 1.5f;
private bool useRectangleFlash;
public float FlashTimer
public virtual float FlashTimer
{
get { return flashTimer; }
}

View File

@@ -108,18 +108,18 @@ namespace Barotrauma
{
float scale = Math.Min(Rect.Width / uiSprite.Sprite.size.X, Rect.Height / uiSprite.Sprite.size.Y);
spriteBatch.Draw(uiSprite.Sprite.Texture, Rect.Center.ToVector2(), uiSprite.Sprite.SourceRect, currColor * (currColor.A / 255.0f), Rotation, uiSprite.Sprite.size / 2,
Scale * scale, SpriteEffects.None, 0.0f);
Scale * scale, SpriteEffects, 0.0f);
}
else
{
uiSprite.Draw(spriteBatch, Rect, currColor * (currColor.A / 255.0f), SpriteEffects.None);
uiSprite.Draw(spriteBatch, Rect, currColor * (currColor.A / 255.0f), SpriteEffects);
}
}
}
else if (sprite?.Texture != null)
{
spriteBatch.Draw(sprite.Texture, Rect.Center.ToVector2(), sourceRect, currColor * (currColor.A / 255.0f), Rotation, sprite.size / 2,
Scale, SpriteEffects.None, 0.0f);
Scale, SpriteEffects, 0.0f);
}
}

View File

@@ -74,17 +74,12 @@ namespace Barotrauma
public CrewManager(XElement element, bool isSinglePlayer)
: this(isSinglePlayer)
{
if (GameMain.Client != null)
if (!isSinglePlayer)
{
//let the server create random conversations in MP
DebugConsole.ThrowError("Cannot add messages to single player chat box in multiplayer mode!\n" + Environment.StackTrace);
return;
}
List<Character> availableSpeakers = Character.CharacterList.FindAll(c =>
c.AIController is HumanAIController &&
!c.IsDead &&
c.SpeechImpediment <= 100.0f);
pendingConversationLines.AddRange(NPCConversation.CreateRandom(availableSpeakers));
}
if (string.IsNullOrEmpty(text)) { return; }
var characterInfo = new CharacterInfo(subElement);
characterInfos.Add(characterInfo);
@@ -95,6 +90,7 @@ namespace Barotrauma
break;
}
}
ChatBox.AddMessage(ChatMessage.Create(senderName, text, messageType, sender));
}
partial void InitProjectSpecific()
@@ -242,24 +238,27 @@ namespace Barotrauma
public IEnumerable<Character> GetCharacters()
{
if (characterInfos.Contains(characterInfo))
{
DebugConsole.ThrowError("Tried to add the same character info to CrewManager twice.\n" + Environment.StackTrace);
return;
}
if (character?.Inventory == null) return null;
characterInfos.Add(characterInfo);
var radioItem = character.Inventory.Items.FirstOrDefault(it => it != null && it.GetComponent<WifiComponent>() != null);
if (radioItem == null) return null;
if (requireEquipped && !character.HasEquippedItem(radioItem)) return null;
return radioItem.GetComponent<WifiComponent>();
}
public IEnumerable<CharacterInfo> GetCharacterInfos()
{
if (character == null)
if (GameMain.Client != null)
{
DebugConsole.ThrowError("Tried to remove a null character from CrewManager.\n" + Environment.StackTrace);
//let the server create random conversations in MP
return;
}
characters.Remove(character);
if (removeInfo) characterInfos.Remove(character.Info);
List<Character> availableSpeakers = Character.CharacterList.FindAll(c =>
c.AIController is HumanAIController &&
!c.IsDead &&
c.SpeechImpediment <= 100.0f);
pendingConversationLines.AddRange(NPCConversation.CreateRandom(availableSpeakers));
}
public void AddCharacter(Character character)
@@ -633,183 +632,9 @@ namespace Barotrauma
{
characterListBox.BarScroll = roundedPos;
}
var characterArea = new GUIButton(new RectTransform(new Point(characterInfoWidth, frame.Rect.Height), frame.RectTransform, Anchor.CenterLeft), style: "GUITextBox")
{
UserData = character,
Color = frame.Color,
SelectedColor = frame.SelectedColor,
HoverColor = frame.HoverColor,
ToolTip = characterToolTip
};
var soundIcon = new GUIImage(new RectTransform(new Point((int)(characterArea.Rect.Height * 0.5f)), characterArea.RectTransform, Anchor.CenterRight) { AbsoluteOffset = new Point(5, 0) },
"GUISoundIcon")
{
UserData = "soundicon",
CanBeFocused = false,
Visible = true
};
soundIcon.Color = new Color(soundIcon.Color, 0.0f);
new GUIImage(new RectTransform(new Point((int)(characterArea.Rect.Height * 0.5f)), characterArea.RectTransform, Anchor.CenterRight) { AbsoluteOffset = new Point(5, 0) },
"GUISoundIconDisabled")
{
UserData = "soundicondisabled",
CanBeFocused = true,
Visible = false
};
if (isSinglePlayer)
{
characterArea.OnClicked = CharacterClicked;
}
else
{
characterArea.CanBeFocused = false;
characterArea.CanBeSelected = false;
}
var characterImage = new GUICustomComponent(new RectTransform(new Point(characterArea.Rect.Height), characterArea.RectTransform, Anchor.CenterLeft),
onDraw: (sb, component) => character.Info.DrawIcon(sb, component.Rect.Center.ToVector2(), targetAreaSize: component.Rect.Size.ToVector2()))
{
CanBeFocused = false,
HoverColor = Color.White,
SelectedColor = Color.White,
ToolTip = characterToolTip
};
var characterName = new GUITextBlock(new RectTransform(new Point(characterArea.Rect.Width - characterImage.Rect.Width - soundIcon.Rect.Width - 10, characterArea.Rect.Height),
characterArea.RectTransform, Anchor.CenterRight) { AbsoluteOffset = new Point(soundIcon.Rect.Width + 10, 0) },
character.Name, textColor: frame.Color, font: GUI.SmallFont, wrap: true)
{
Color = frame.Color,
HoverColor = Color.Transparent,
SelectedColor = Color.Transparent,
CanBeFocused = false,
ToolTip = characterToolTip,
AutoScale = true
};
//---------------- order buttons ----------------
var orderButtonFrame = new GUILayoutGroup(new RectTransform(new Point(100, frame.Rect.Height), frame.RectTransform)
{ AbsoluteOffset = new Point(characterInfoWidth + spacing, 0) },
isHorizontal: true, childAnchor: Anchor.CenterLeft)
{
AbsoluteSpacing = (int)(10 * GUI.Scale),
UserData = "orderbuttons",
CanBeFocused = false
};
//listbox for holding the orders inappropriate for this character
//(so we can easily toggle their visibility)
var wrongOrderList = new GUIListBox(new RectTransform(new Point(50, orderButtonFrame.Rect.Height), orderButtonFrame.RectTransform), isHorizontal: true, style: null)
{
ScrollBarEnabled = false,
ScrollBarVisible = false,
Enabled = false,
Spacing = spacing,
ClampMouseRectToParent = false
};
wrongOrderList.Content.ClampMouseRectToParent = false;
for (int i = 0; i < orders.Count; i++)
{
var order = orders[i];
if (order.TargetAllCharacters) continue;
RectTransform btnParent = (i >= correctOrderCount + neutralOrderCount) ?
wrongOrderList.Content.RectTransform :
orderButtonFrame.RectTransform;
var btn = new GUIButton(new RectTransform(new Point(iconSize, iconSize), btnParent, Anchor.CenterLeft),
style: null)
{
UserData = order
};
new GUIFrame(new RectTransform(new Vector2(1.5f), btn.RectTransform, Anchor.Center), "OuterGlow")
{
Color = Color.Lerp(order.Color, frame.Color, 0.5f) * 0.8f,
HoverColor = Color.Lerp(order.Color, frame.Color, 0.5f) * 1.0f,
PressedColor = Color.Lerp(order.Color, frame.Color, 0.5f) * 0.6f,
UserData = "selected",
CanBeFocused = false,
Visible = false
};
var img = new GUIImage(new RectTransform(Vector2.One, btn.RectTransform), order.Prefab.SymbolSprite);
img.Scale = iconSize / (float)img.SourceRect.Width;
img.Color = Color.Lerp(order.Color, frame.Color, 0.5f);
img.ToolTip = order.Name;
img.HoverColor = Color.Lerp(img.Color, Color.White, 0.5f);
btn.OnClicked += (GUIButton button, object userData) =>
{
if (Character.Controlled == null || Character.Controlled.SpeechImpediment >= 100.0f) return false;
if (btn.GetChildByUserData("selected").Visible)
{
SetCharacterOrder(character, Order.PrefabList.Find(o => o.AITag == "dismissed"), null, Character.Controlled);
}
else
{
if (order.ItemComponentType != null || order.ItemIdentifiers.Length > 0 || order.Options.Length > 1)
{
CreateOrderTargetFrame(button, character, order);
}
else
{
SetCharacterOrder(character, order, null, Character.Controlled);
}
}
return true;
};
btn.UserData = order;
btn.ToolTip = order.Name;
//divider between different groups of orders
if (i == correctOrderCount - 1 || i == correctOrderCount + neutralOrderCount - 1)
{
//TODO: divider sprite
new GUIFrame(new RectTransform(new Point(8, iconSize), orderButtonFrame.RectTransform), style: "GUIButton");
}
}
var toggleWrongOrderBtn = new GUIButton(new RectTransform(new Point((int)(30 * GUI.Scale), wrongOrderList.Rect.Height), wrongOrderList.Content.RectTransform),
"", style: "UIToggleButton")
{
UserData = "togglewrongorder",
CanBeFocused = false
};
wrongOrderList.RectTransform.NonScaledSize = new Point(
wrongOrderList.Content.Children.Sum(c => c.Rect.Width + wrongOrderList.Spacing),
wrongOrderList.RectTransform.NonScaledSize.Y);
wrongOrderList.RectTransform.SetAsLastChild();
new GUIFrame(new RectTransform(new Point(
wrongOrderList.Rect.Width - toggleWrongOrderBtn.Rect.Width - wrongOrderList.Spacing * 2,
wrongOrderList.Rect.Height), wrongOrderList.Content.RectTransform),
style: null)
{
CanBeFocused = false
};
//scale to fit the content
orderButtonFrame.RectTransform.NonScaledSize = new Point(
orderButtonFrame.Children.Sum(c => c.Rect.Width + orderButtonFrame.AbsoluteSpacing),
orderButtonFrame.RectTransform.NonScaledSize.Y);
frame.RectTransform.NonScaledSize = new Point(
characterInfoWidth + spacing + (orderButtonFrame.Rect.Width - wrongOrderList.Rect.Width),
frame.RectTransform.NonScaledSize.Y);
characterListBox.RectTransform.NonScaledSize = new Point(
characterListBox.Content.Children.Max(c => c.Rect.Width) + wrongOrderList.Rect.Width,
characterListBox.RectTransform.NonScaledSize.Y);
characterListBox.Content.RectTransform.NonScaledSize = characterListBox.RectTransform.NonScaledSize;
characterListBox.UpdateScrollBarSize();
return frame;
soundIcon.Visible = !muted && !mutedLocally;
soundIconDisabled.Visible = muted || mutedLocally;
soundIconDisabled.ToolTip = TextManager.Get(mutedLocally ? "MutedLocally" : "MutedGlobally");
}
private IEnumerable<object> KillCharacterAnim(GUIComponent component)
@@ -953,12 +778,6 @@ namespace Barotrauma
}
return;
}
List<Character> availableSpeakers = Character.CharacterList.FindAll(c =>
c.AIController is HumanAIController &&
!c.IsDead &&
c.SpeechImpediment <= 100.0f);
pendingConversationLines.AddRange(NPCConversation.CreateRandom(availableSpeakers));
}
character.SetOrder(order, option, orderGiver, speak: orderGiver != character);
if (IsSinglePlayer)
@@ -1016,23 +835,19 @@ namespace Barotrauma
}
}
}
character.SetOrder(order, option, orderGiver, speak: orderGiver != character);
if (IsSinglePlayer)
//only one target (or an order with no particular targets), just show options
else
{
orderGiver?.Speak(
order.GetChatMessage(character.Name, orderGiver.CurrentHull?.DisplayName, givingOrderToSelf: character == orderGiver, orderOption: option), null);
}
else if (orderGiver != null)
{
OrderChatMessage msg = new OrderChatMessage(order, option, order.TargetItemComponent?.Item, character, orderGiver);
if (GameMain.Client != null)
orderTargetFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.2f + order.Options.Length * 0.1f, 0.18f), GUI.Canvas)
{ AbsoluteOffset = new Point(orderButton.Rect.Center.X, orderButton.Rect.Bottom) },
isHorizontal: true, childAnchor: Anchor.BottomLeft)
{
GameMain.Client.SendChatMessage(msg);
}
}
DisplayCharacterOrder(character, order);
}
UserData = character,
Stretch = true
};
//line connecting the order button to the option buttons
//TODO: sprite
new GUIFrame(new RectTransform(new Vector2(0.5f, 1.0f), orderTargetFrame.RectTransform), style: null);
/// <summary>
/// Create the UI panel that's used to select the target and options for a given order

View File

@@ -64,6 +64,8 @@ namespace Barotrauma.Items.Components
new Color(255, 255, 255)
};
private float prevDockingDist;
public Vector2 DisplayOffset { get; private set; }
public float DisplayRadius { get; private set; }
@@ -171,6 +173,31 @@ namespace Barotrauma.Items.Components
sonarMode.Selected = Mode.Passive;
GuiFrame.CanBeFocused = false;
foreach (XElement subElement in element.Elements())
{
switch (subElement.Name.ToString().ToLowerInvariant())
{
case "pingcircle":
pingCircle = new Sprite(subElement);
break;
case "directionalpingcircle":
directionalPingCircle = new Sprite(subElement);
break;
case "screenoverlay":
screenOverlay = new Sprite(subElement);
break;
case "screenbackground":
screenBackground = new Sprite(subElement);
break;
case "blip":
sonarBlip = new Sprite(subElement);
break;
case "linesprite":
lineSprite = new Sprite(subElement);
break;
}
}
}
public override void OnItemLoaded()
@@ -235,8 +262,7 @@ namespace Barotrauma.Items.Components
return;
}
Vector2 transducerCenter = UseTransducers ? GetTransducerCenter() : item.WorldPosition;
transducerCenter += DisplayOffset;
Vector2 transducerCenter = GetTransducerPos() + DisplayOffset;
if (Level.Loaded != null)
{
@@ -285,8 +311,31 @@ namespace Barotrauma.Items.Components
sonarBlips.Add(flowBlip);
}
}
}
}
Steering steering = item.GetComponent<Steering>();
if (steering != null && steering.DockingModeEnabled)
{
float dockingDist = Vector2.Distance(steering.DockingSource.Item.WorldPosition, steering.DockingTarget.Item.WorldPosition);
if (prevDockingDist > steering.DockingAssistThreshold && dockingDist <= steering.DockingAssistThreshold)
{
zoom = Math.Max(zoom, MathHelper.Lerp(MinZoom, MaxZoom, 0.25f));
}
else if (prevDockingDist > steering.DockingAssistThreshold * 0.75f && dockingDist <= steering.DockingAssistThreshold * 0.75f)
{
zoom = Math.Max(zoom, MathHelper.Lerp(MinZoom, MaxZoom, 0.5f));
}
else if (prevDockingDist > steering.DockingAssistThreshold * 0.5f && dockingDist <= steering.DockingAssistThreshold * 0.5f)
{
zoom = Math.Max(zoom, MathHelper.Lerp(MinZoom, MaxZoom, 0.25f));
}
prevDockingDist = Math.Min(dockingDist, prevDockingDist);
}
else
{
prevDockingDist = float.MaxValue;
}
if (IsActive)
{
float pingRadius = DisplayRadius * pingState / zoom;
@@ -357,7 +406,7 @@ namespace Barotrauma.Items.Components
}
}
Vector2 transducerCenter = UseTransducers && connectedTransducers.Count > 0 ? GetTransducerCenter() : item.WorldPosition;
Vector2 transducerCenter = GetTransducerPos();
if (item.Submarine != null && !DetectSubmarineWalls)
{
@@ -370,7 +419,6 @@ namespace Barotrauma.Items.Components
DisplayOffset = Vector2.Zero;
}
if (sonarBlips.Count > 0)
{
zoomSqrt = (float)Math.Sqrt(zoom);
@@ -391,8 +439,8 @@ namespace Barotrauma.Items.Components
{
Vector2 sector1 = MathUtils.RotatePointAroundTarget(pingDirection * DisplayRadius, Vector2.Zero, DirectionalPingSector * 0.5f);
Vector2 sector2 = MathUtils.RotatePointAroundTarget(pingDirection * DisplayRadius, Vector2.Zero, -DirectionalPingSector * 0.5f);
GUI.DrawLine(spriteBatch, center, center + sector1, Color.LightCyan * 0.2f * directionalPingVisibility, width: 3);
GUI.DrawLine(spriteBatch, center, center + sector2, Color.LightCyan * 0.2f * directionalPingVisibility, width: 3);
DrawLine(spriteBatch, center, center + sector1, Color.LightCyan * 0.2f * directionalPingVisibility, width: 3);
DrawLine(spriteBatch, center, center + sector2, Color.LightCyan * 0.2f * directionalPingVisibility, width: 3);
}
if (GameMain.DebugDraw)
@@ -495,7 +543,7 @@ namespace Barotrauma.Items.Components
Vector2 end = (submarine.HullVertices[(i + 1) % submarine.HullVertices.Count] + offset) * simScale;
end.Y = -end.Y;
DrawLine(spriteBatch, start, end, Color.LightBlue * signalStrength * 0.5f, width: 3);
DrawLine(spriteBatch, start, end, Color.LightBlue * signalStrength * 0.5f, width: 4);
}
}
}
@@ -512,22 +560,38 @@ namespace Barotrauma.Items.Components
{
if (MathUtils.GetLineCircleIntersections(Vector2.Zero, DisplayRadius, end, start, true, out Vector2? intersection1, out Vector2? intersection2) == 1)
{
GUI.DrawLine(spriteBatch, center + intersection1.Value, center + end, color, width: width);
DrawLineSprite(spriteBatch, center + intersection1.Value, center + end, color, width: width);
}
}
else if (endOutside)
{
if (MathUtils.GetLineCircleIntersections(Vector2.Zero, DisplayRadius, start, end, true, out Vector2? intersection1, out Vector2? intersection2) == 1)
{
GUI.DrawLine(spriteBatch, center + start, center + intersection1.Value, color, width: width);
DrawLineSprite(spriteBatch, center + start, center + intersection1.Value, color, width: width);
}
}
else
{
GUI.DrawLine(spriteBatch, center + start, center + end, color, width: width);
DrawLineSprite(spriteBatch, center + start, center + end, color, width: width);
}
}
private void DrawLineSprite(SpriteBatch spriteBatch, Vector2 start, Vector2 end, Color color, int width)
{
if (lineSprite == null)
{
GUI.DrawLine(spriteBatch, start, end, color, width: width);
}
else
{
Vector2 dir = end - start;
float angle = (float)Math.Atan2(dir.Y, dir.X);
lineSprite.Draw(spriteBatch, start, color, origin: lineSprite.Origin, rotate: angle,
scale: new Vector2(dir.Length() / lineSprite.size.X, 1.0f));
}
}
private void DrawDockingPorts(SpriteBatch spriteBatch, Vector2 transducerCenter, float signalStrength)
{
float scale = displayScale * zoom;
@@ -535,61 +599,12 @@ namespace Barotrauma.Items.Components
Steering steering = item.GetComponent<Steering>();
if (steering != null && steering.DockingModeEnabled)
{
DisplayOffset =
Vector2.Lerp(DisplayOffset,
(steering.DockingSource.Item.WorldPosition + steering.DockingTarget.Item.WorldPosition) / 2.0f - transducerCenter,
0.1f);
transducerCenter += DisplayOffset;
Vector2 sourcePortDiff = (steering.DockingSource.Item.WorldPosition - transducerCenter) * scale;
Vector2 sourcePortPos = new Vector2(sourcePortDiff.X, -sourcePortDiff.Y);
Vector2 targetPortDiff = (steering.DockingTarget.Item.WorldPosition - transducerCenter) * scale;
Vector2 targetPortPos = new Vector2(targetPortDiff.X, -targetPortDiff.Y);
Vector2 midPos = (sourcePortPos + targetPortPos) / 2.0f;
System.Diagnostics.Debug.Assert(steering.DockingSource.IsHorizontal == steering.DockingTarget.IsHorizontal);
float xDist = Math.Abs(steering.DockingSource.Item.WorldPosition.X - steering.DockingTarget.Item.WorldPosition.X);
float normalizedXDist = xDist / steering.DockingSource.DistanceTolerance.X;
float yDist = Math.Abs(steering.DockingSource.Item.WorldPosition.Y - steering.DockingTarget.Item.WorldPosition.Y);
float normalizedYDist = yDist / steering.DockingSource.DistanceTolerance.Y;
Color xColor = normalizedXDist <= 1.0f ? Color.Lime : Color.Lerp(Color.Orange, Color.Red, normalizedXDist - 1.0f);
Color yColor = normalizedYDist <= 1.0f ? Color.Lime : Color.Lerp(Color.Orange, Color.Red, normalizedYDist - 1.0f);
if (steering.DockingSource.IsHorizontal)
{
if (yDist < steering.DockingSource.DistanceTolerance.Y)
{
DrawLine(spriteBatch, sourcePortPos, new Vector2(targetPortPos.X, sourcePortPos.Y), xColor, width: 3);
}
else
{
DrawLine(spriteBatch, sourcePortPos, new Vector2(midPos.X, sourcePortPos.Y), xColor, width: 3);
DrawLine(spriteBatch, targetPortPos, new Vector2(midPos.X, targetPortPos.Y), xColor, width: 3);
DrawLine(spriteBatch, new Vector2(midPos.X, sourcePortPos.Y), new Vector2(midPos.X, targetPortPos.Y), yColor, width: 3);
}
}
else
{
if (xDist < steering.DockingSource.DistanceTolerance.X)
{
DrawLine(spriteBatch, sourcePortPos, new Vector2(sourcePortPos.X, targetPortPos.Y), yColor, width: 3);
}
else
{
DrawLine(spriteBatch, sourcePortPos, new Vector2(sourcePortPos.X, midPos.Y), yColor, width: 3);
DrawLine(spriteBatch, targetPortPos, new Vector2(targetPortPos.X, midPos.Y), yColor, width: 3);
DrawLine(spriteBatch, new Vector2(sourcePortPos.X, midPos.Y), new Vector2(targetPortPos.X, midPos.Y), xColor, width: 3);
}
}
DrawDockingIndicator(spriteBatch, steering, ref transducerCenter);
}
else
{
DisplayOffset = Vector2.Lerp(DisplayOffset, Vector2.Zero, 0.1f);
}
}
foreach (DockingPort dockingPort in DockingPort.List)
{
@@ -608,9 +623,102 @@ namespace Barotrauma.Items.Components
{
size.Y = 0.0f;
}
GUI.DrawLine(spriteBatch, center + offset - size / 2, center + offset + size / 2, Color.LightGreen, width: (int)(zoom));
GUI.DrawLine(spriteBatch, center + offset - size, center + offset + size, Color.LightGreen, width: (int)(zoom * 2.5f));
}
}
private void DrawDockingIndicator(SpriteBatch spriteBatch, Steering steering, ref Vector2 transducerCenter)
{
float scale = displayScale * zoom;
Vector2 worldFocusPos = (steering.DockingSource.Item.WorldPosition + steering.DockingTarget.Item.WorldPosition) / 2.0f;
worldFocusPos.X = steering.DockingTarget.Item.WorldPosition.X;
DisplayOffset = Vector2.Lerp(DisplayOffset, worldFocusPos - transducerCenter, 0.1f);
transducerCenter += DisplayOffset;
Vector2 sourcePortDiff = (steering.DockingSource.Item.WorldPosition - transducerCenter) * scale;
Vector2 sourcePortPos = new Vector2(sourcePortDiff.X, -sourcePortDiff.Y);
Vector2 targetPortDiff = (steering.DockingTarget.Item.WorldPosition - transducerCenter) * scale;
Vector2 targetPortPos = new Vector2(targetPortDiff.X, -targetPortDiff.Y);
Vector2 midPos = (sourcePortPos + targetPortPos) / 2.0f;
System.Diagnostics.Debug.Assert(steering.DockingSource.IsHorizontal == steering.DockingTarget.IsHorizontal);
Vector2 diff = steering.DockingTarget.Item.WorldPosition - steering.DockingSource.Item.WorldPosition;
float dist = diff.Length();
bool readyToDock =
Math.Abs(diff.X) < steering.DockingTarget.DistanceTolerance.X &&
Math.Abs(diff.Y) < steering.DockingTarget.DistanceTolerance.Y;
Vector2 dockingDir = sourcePortPos - targetPortPos;
Vector2 normalizedDockingDir = Vector2.Normalize(dockingDir);
if (!DynamicDockingIndicator)
{
if (steering.DockingSource.IsHorizontal)
{
normalizedDockingDir = new Vector2(Math.Sign(normalizedDockingDir.X), 0.0f);
}
else
{
normalizedDockingDir = new Vector2(0.0f, Math.Sign(normalizedDockingDir.Y));
}
}
Color staticLineColor = Color.White * 0.2f;
float sector = MathHelper.ToRadians(MathHelper.Lerp(10.0f, 45.0f, MathHelper.Clamp(dist / steering.DockingAssistThreshold, 0.0f, 1.0f)));
float sectorLength = DisplayRadius;
//use law of cosines to calculate the length of the center line
float midLength = (float)(Math.Cos(sector) * sectorLength);
Vector2 midNormal = new Vector2(-normalizedDockingDir.Y, normalizedDockingDir.X);
DrawLine(spriteBatch, targetPortPos, targetPortPos + normalizedDockingDir * midLength, readyToDock ? Color.LightGreen : staticLineColor, width: 2);
DrawLine(spriteBatch, targetPortPos,
targetPortPos + MathUtils.RotatePoint(normalizedDockingDir, sector) * sectorLength, staticLineColor, width: 2);
DrawLine(spriteBatch, targetPortPos,
targetPortPos + MathUtils.RotatePoint(normalizedDockingDir, -sector) * sectorLength, staticLineColor, width: 2);
for (float z = 0; z < 1.0f; z += 0.1f * zoom)
{
Vector2 linePos = targetPortPos + normalizedDockingDir * midLength * z;
DrawLine(spriteBatch, linePos + midNormal * 3.0f, linePos - midNormal * 3.0f, staticLineColor, width: 3);
}
if (readyToDock)
{
Color indicatorColor = Color.LightGreen * 0.8f;
float indicatorSize = (float)Math.Sin((float)Timing.TotalTime * 5.0f) * DisplayRadius * 0.75f;
Vector2 midPoint = (sourcePortPos + targetPortPos) / 2.0f;
DrawLine(spriteBatch,
midPoint + Vector2.UnitY * indicatorSize,
midPoint - Vector2.UnitY * indicatorSize,
indicatorColor, width: 3);
DrawLine(spriteBatch,
midPoint + Vector2.UnitX * indicatorSize,
midPoint - Vector2.UnitX * indicatorSize,
indicatorColor, width: 3);
}
else
{
float indicatorSector = sector * 0.75f;
float indicatorSectorLength = (float)(midLength / Math.Cos(indicatorSector));
bool withinSector =
(Math.Abs(diff.X) < steering.DockingSource.DistanceTolerance.X && Math.Abs(diff.Y) < steering.DockingSource.DistanceTolerance.Y) ||
Vector2.Dot(normalizedDockingDir, MathUtils.RotatePoint(normalizedDockingDir, indicatorSector)) <
Vector2.Dot(normalizedDockingDir, Vector2.Normalize(dockingDir));
Color indicatorColor = withinSector ? Color.LightGreen * 0.8f : Color.Red * 0.8f;
DrawLine(spriteBatch, targetPortPos,
targetPortPos + MathUtils.RotatePoint(normalizedDockingDir,indicatorSector) * indicatorSectorLength, indicatorColor, width: 3);
DrawLine(spriteBatch, targetPortPos,
targetPortPos + MathUtils.RotatePoint(normalizedDockingDir, -indicatorSector) * indicatorSectorLength, indicatorColor, width: 3);
}
}
private void UpdateDisruptions(Vector2 pingSource, float worldPingRadius, float worldPrevPingRadius)

View File

@@ -4,7 +4,9 @@ using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Linq;
using System.Collections.Generic;
using System.Xml.Linq;
namespace Barotrauma.Items.Components
{
@@ -25,6 +27,11 @@ namespace Barotrauma.Items.Components
};
private GUITickBox maintainPosTickBox, levelEndTickBox, levelStartTickBox;
private GUIComponent statusContainer, dockingContainer;
private GUIButton dockingButton;
private string dockText, undockText;
private GUIFrame autoPilotControlsDisabler;
private GUIComponent steerArea;
@@ -35,6 +42,9 @@ namespace Barotrauma.Items.Components
private string noPowerTip, autoPilotMaintainPosTip, autoPilotLevelStartTip, autoPilotLevelEndTip;
private Sprite maintainPosIndicator, maintainPosOriginIndicator;
private Sprite steeringIndicator;
private Vector2 keyboardInput = Vector2.Zero;
private float inputCumulation;
@@ -66,10 +76,12 @@ namespace Barotrauma.Items.Components
get;
set;
}
public DockingPort DockingSource, DockingTarget;
partial void InitProjSpecific()
private bool searchedConnectedDockingPort;
partial void InitProjSpecific(XElement element)
{
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)
@@ -80,7 +92,7 @@ namespace Barotrauma.Items.Components
Stretch = true
};
var statusContainer = new GUIFrame(new RectTransform(new Vector2(0.3f, 0.25f), GuiFrame.RectTransform, Anchor.BottomLeft)
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))
{
@@ -123,7 +135,9 @@ namespace Barotrauma.Items.Components
AutoPilot = box.Selected;
if (AutoPilot && MaintainPos)
{
posToMaintain = controlledSub == null ? item.WorldPosition : controlledSub.WorldPosition;
posToMaintain = controlledSub != null ?
controlledSub.WorldPosition :
item.Submarine == null ? item.WorldPosition : item.Submarine.WorldPosition;
}
unsentChanges = true;
user = Character.Controlled;
@@ -294,6 +308,80 @@ namespace Barotrauma.Items.Components
steerArea = new GUICustomComponent(new RectTransform(new Point(viewSize), GuiFrame.RectTransform, Anchor.CenterLeft),
(spriteBatch, guiCustomComponent) => { DrawHUD(spriteBatch, guiCustomComponent.Rect); }, null);
//docking interface ----------------------------------------------------
dockingContainer = 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) }, style: null);
var paddedDockingContainer = new GUIFrame(new RectTransform(new Vector2(0.9f, 0.9f), dockingContainer.RectTransform, Anchor.Center), style: null);
//TODO: add new texts for these ("Dock" & "Undock")
dockText = TextManager.Get("captain.dock");
undockText = TextManager.Get("captain.undock");
dockingButton = new GUIButton(new RectTransform(new Vector2(0.5f, 0.5f), paddedDockingContainer.RectTransform, Anchor.Center), dockText, style: "GUIButtonLarge")
{
OnClicked = (btn, userdata) =>
{
item.SendSignal(0, "1", "toggle_docking", sender: Character.Controlled);
return true;
}
};
dockingButton.Font = GUI.SmallFont;
var leftButton = new GUIButton(new RectTransform(new Vector2(0.2f, 0.5f), paddedDockingContainer.RectTransform, Anchor.CenterLeft), "")
{
OnClicked = NudgeButtonClicked,
UserData = -Vector2.UnitX
};
new GUIImage(new RectTransform(new Vector2(0.7f), leftButton.RectTransform, Anchor.Center), "GUIButtonHorizontalArrow").SpriteEffects = SpriteEffects.FlipHorizontally;
var rightButton = new GUIButton(new RectTransform(new Vector2(0.2f, 0.5f), paddedDockingContainer.RectTransform, Anchor.CenterRight), "")
{
OnClicked = NudgeButtonClicked,
UserData = Vector2.UnitX
};
new GUIImage(new RectTransform(new Vector2(0.7f), rightButton.RectTransform, Anchor.Center), "GUIButtonHorizontalArrow");
var upButton = new GUIButton(new RectTransform(new Vector2(0.5f, 0.2f), paddedDockingContainer.RectTransform, Anchor.TopCenter), "")
{
OnClicked = NudgeButtonClicked,
UserData = Vector2.UnitY
};
new GUIImage(new RectTransform(new Vector2(0.7f), upButton.RectTransform, Anchor.Center), "GUIButtonVerticalArrow");
var downButton = new GUIButton(new RectTransform(new Vector2(0.5f, 0.2f), paddedDockingContainer.RectTransform, Anchor.BottomCenter), "")
{
OnClicked = NudgeButtonClicked,
UserData = -Vector2.UnitY
};
new GUIImage(new RectTransform(new Vector2(0.7f), downButton.RectTransform, Anchor.Center), "GUIButtonVerticalArrow").SpriteEffects = SpriteEffects.FlipVertically;
foreach (XElement subElement in element.Elements())
{
switch (subElement.Name.ToString().ToLowerInvariant())
{
case "steeringindicator":
steeringIndicator = new Sprite(subElement);
break;
case "maintainposindicator":
maintainPosIndicator = new Sprite(subElement);
break;
case "maintainposoriginindicator":
maintainPosOriginIndicator = new Sprite(subElement);
break;
}
}
}
private void FindConnectedDockingPort()
{
DockingSource =
(item.linkedTo.FirstOrDefault(l => l is Item item && item.GetComponent<DockingPort>() != null) as Item)?.GetComponent<DockingPort>();
if (DockingSource == null)
{
var dockingConnection = item.Connections.FirstOrDefault(c => c.Name == "toggle_docking");
if (dockingConnection != null)
{
var connectedPorts = item.GetConnectedComponentsRecursive<DockingPort>(dockingConnection);
DockingSource = connectedPorts.Find(p => p.Item.Submarine == item.Submarine);
}
}
}
/// <summary>
@@ -305,6 +393,12 @@ namespace Barotrauma.Items.Components
sonarView.OnDraw += (spriteBatch, guiCustomComponent) => { DrawHUD(spriteBatch, guiCustomComponent.Rect); };
}
public void DrawHUD(SpriteBatch spriteBatch, Rectangle rect)
{
int width = rect.Width, height = rect.Height;
int x = rect.X;
int y = rect.Y;
public void DrawHUD(SpriteBatch spriteBatch, Rectangle rect)
{
int width = rect.Width, height = rect.Height;
@@ -313,12 +407,12 @@ namespace Barotrauma.Items.Components
if (voltage < minVoltage && currPowerConsumption > 0.0f) return;
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);
Rectangle velRect = new Rectangle(x + 20, y + 20, width - 40, height - 40);
Vector2 displaySubPos = (-sonar.DisplayOffset * sonar.Zoom) / sonar.Range * sonar.DisplayRadius * sonar.Zoom;
displaySubPos.Y = -displaySubPos.Y;
displaySubPos = displaySubPos.ClampLength(velRect.Width / 2);
displaySubPos = steerArea.Rect.Center.ToVector2() + displaySubPos;
if (!AutoPilot)
{
Vector2 unitSteeringInput = steeringInput / 100.0f;
@@ -326,20 +420,24 @@ namespace Barotrauma.Items.Components
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;
steeringInputPos += displaySubPos;
GUI.DrawLine(spriteBatch,
new Vector2(velRect.Center.X, velRect.Center.Y),
steeringInputPos,
Color.LightGray);
if (steeringIndicator != null)
{
Vector2 dir = steeringInputPos - displaySubPos;
float angle = (float)Math.Atan2(dir.Y, dir.X);
steeringIndicator.Draw(spriteBatch, displaySubPos, Color.White, origin: steeringIndicator.Origin, rotate: angle,
scale: new Vector2(dir.Length() / steeringIndicator.size.X, 1.0f));
}
else
{
GUI.DrawLine(spriteBatch, displaySubPos, steeringInputPos, Color.LightGray);
GUI.DrawRectangle(spriteBatch, new Rectangle((int)steeringInputPos.X - 5, (int)steeringInputPos.Y - 5, 10, 10), Color.White);
}
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);
GUI.DrawRectangle(spriteBatch, new Rectangle((int)steeringInputPos.X - 4, (int)steeringInputPos.Y - 4, 8, 8), Color.Red, thickness: 2);
}
}
else if (posToMaintain.HasValue && !LevelStartSelected && !LevelEndSelected)
@@ -350,35 +448,53 @@ namespace Barotrauma.Items.Components
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;
displayPosToMaintain = steerArea.Rect.Center.ToVector2() + displayPosToMaintain;
float crossHairSize = 8.0f;
Color crosshairColor = Color.Orange * (0.5f + ((float)Math.Sin(Timing.TotalTime * 5.0f) + 1.0f) / 4.0f);
if (maintainPosIndicator != null)
{
maintainPosIndicator.Draw(spriteBatch, displayPosToMaintain, crosshairColor, scale: 0.5f * sonar.Zoom);
}
else
{
float crossHairSize = 8.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);
}
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);
if (maintainPosOriginIndicator != null)
{
maintainPosOriginIndicator.Draw(spriteBatch, displaySubPos, Color.Orange, scale: 0.5f * sonar.Zoom);
}
else
{
GUI.DrawRectangle(spriteBatch, new Rectangle((int)displaySubPos.X - 5, (int)displaySubPos.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;
steeringPos += displaySubPos;
GUI.DrawLine(spriteBatch,
new Vector2(velRect.Center.X, velRect.Center.Y),
steeringPos,
Color.CadetBlue, 0, 2);
if (steeringIndicator != null)
{
Vector2 dir = steeringPos - displaySubPos;
float angle = (float)Math.Atan2(dir.Y, dir.X);
steeringIndicator.Draw(spriteBatch, displaySubPos, Color.Gray, origin: steeringIndicator.Origin, rotate: angle,
scale: new Vector2(dir.Length() / steeringIndicator.size.X, 0.7f));
}
else
{
GUI.DrawLine(spriteBatch,
displaySubPos,
steeringPos,
Color.CadetBlue, 0, 2);
}
}
public void DebugDrawHUD(SpriteBatch spriteBatch, Vector2 transducerCenter, float displayScale, float displayRadius, Vector2 center)
@@ -435,7 +551,6 @@ namespace Barotrauma.Items.Components
Color.Lerp(Color.Green, Color.Orange, obstacle.Dot), width: 2);
}
}
}
public override void UpdateHUD(Character character, float deltaTime, Camera cam)
{
@@ -448,6 +563,12 @@ namespace Barotrauma.Items.Components
}
}
if (!searchedConnectedDockingPort)
{
FindConnectedDockingPort();
searchedConnectedDockingPort = true;
}
if (steerArea.Rect.Contains(PlayerInput.MousePosition))
{
if (!PlayerInput.KeyDown(InputType.Deselect) && !PlayerInput.KeyHit(InputType.Deselect))
@@ -456,6 +577,38 @@ namespace Barotrauma.Items.Components
}
}
dockingContainer.Visible = DockingModeEnabled;
statusContainer.Visible = !DockingModeEnabled;
if (DockingModeEnabled)
{
if (Math.Abs(DockingSource.Item.WorldPosition.X - DockingTarget.Item.WorldPosition.X) < DockingSource.DistanceTolerance.X &&
Math.Abs(DockingSource.Item.WorldPosition.Y - DockingTarget.Item.WorldPosition.Y) < DockingSource.DistanceTolerance.Y)
{
dockingButton.Text = dockText;
if (dockingButton.FlashTimer <= 0.0f)
{
dockingButton.Flash(Color.LightGreen, 0.5f);
dockingButton.Pulsate(Vector2.One, Vector2.One * 1.2f, dockingButton.FlashTimer);
}
}
}
else if (DockingSource != null && DockingSource.Docked)
{
dockingButton.Text = undockText;
dockingContainer.Visible = true;
statusContainer.Visible = false;
if (dockingButton.FlashTimer <= 0.0f)
{
dockingButton.Flash(Color.OrangeRed);
dockingButton.Pulsate(Vector2.One, Vector2.One * 1.2f, dockingButton.FlashTimer);
}
}
else
{
dockingButton.Text = dockText;
}
autoPilotControlsDisabler.Visible = !AutoPilot;
if (voltage < minVoltage && currPowerConsumption > 0.0f)
@@ -493,13 +646,17 @@ namespace Barotrauma.Items.Components
{
if (PlayerInput.LeftButtonHeld())
{
Vector2 inputPos = PlayerInput.MousePosition - steerArea.Rect.Center.ToVector2();
Vector2 displaySubPos = (-sonar.DisplayOffset * sonar.Zoom) / sonar.Range * sonar.DisplayRadius * sonar.Zoom;
displaySubPos.Y = -displaySubPos.Y;
displaySubPos = steerArea.Rect.Center.ToVector2() + displaySubPos;
Vector2 inputPos = PlayerInput.MousePosition - displaySubPos;
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;
posToMaintain = controlledSub != null ?
controlledSub.WorldPosition + inputPos / sonar.DisplayRadius * sonar.Range / sonar.Zoom :
item.Submarine == null ? item.WorldPosition : item.Submarine.WorldPosition;
}
else
{
@@ -565,16 +722,6 @@ namespace Barotrauma.Items.Components
if (sourcePort.Docked || sourcePort.Item.Submarine == null) { continue; }
if (sourcePort.Item.Submarine != controlledSub) { continue; }
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; }
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);
@@ -602,6 +749,34 @@ namespace Barotrauma.Items.Components
}
}
private bool NudgeButtonClicked(GUIButton btn, object userdata)
{
if (!MaintainPos || !AutoPilot)
{
AutoPilot = true;
posToMaintain = item.Submarine.WorldPosition;
}
MaintainPos = true;
if (userdata is Vector2)
{
Sonar sonar = item.GetComponent<Sonar>();
Vector2 nudgeAmount = (Vector2)userdata;
if (sonar != null)
{
nudgeAmount *= sonar == null ? 500.0f : 500.0f / sonar.Zoom;
}
PosToMaintain += nudgeAmount;
}
return true;
}
protected override void RemoveComponentSpecific()
{
maintainPosIndicator?.Remove();
maintainPosOriginIndicator?.Remove();
steeringIndicator?.Remove();
}
public void ClientWrite(Lidgren.Network.NetBuffer msg, object[] extraData = null)
{
msg.Write(autoPilot);

View File

@@ -70,6 +70,8 @@ namespace Barotrauma
private GUILayoutGroup subPreviewContainer;
private GUILayoutGroup subPreviewContainer;
private GUIButton loadGameButton;
public Action<Submarine, string, string> StartNewGame;

View File

@@ -376,6 +376,9 @@
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Assemblies\WindowedAutoDoor.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Command\NavUI.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Door\door2.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>

View File

@@ -47,8 +47,9 @@ namespace Barotrauma.Items.Components
//was the last ping sent with directional pinging
private bool isLastPingDirectional;
private readonly Sprite pingCircle, directionalPingCircle, screenOverlay, screenBackground;
private readonly Sprite sonarBlip;
private Sprite pingCircle, directionalPingCircle, screenOverlay, screenBackground;
private Sprite sonarBlip;
private Sprite lineSprite;
private bool aiPingCheckPending;
@@ -86,6 +87,16 @@ namespace Barotrauma.Items.Components
get { return zoom; }
}
//TODO: remove, only for testing
#if DEBUG
[Serialize(false, false), Editable]
public bool DynamicDockingIndicator
{
get;
set;
}
#endif
public override bool IsActive
{
get
@@ -111,29 +122,7 @@ namespace Barotrauma.Items.Components
: base(item, element)
{
connectedTransducers = new List<ConnectedTransducer>();
foreach (XElement subElement in element.Elements())
{
switch (subElement.Name.ToString().ToLowerInvariant())
{
case "pingcircle":
pingCircle = new Sprite(subElement);
break;
case "directionalpingcircle":
directionalPingCircle = new Sprite(subElement);
break;
case "screenoverlay":
screenOverlay = new Sprite(subElement);
break;
case "screenbackground":
screenBackground = new Sprite(subElement);
break;
case "blip":
sonarBlip = new Sprite(subElement);
break;
}
}
IsActive = false;
InitProjSpecific(element);
}
@@ -205,6 +194,7 @@ namespace Barotrauma.Items.Components
directionalPingCircle?.Remove();
screenOverlay?.Remove();
screenBackground?.Remove();
lineSprite?.Remove();
}
public override bool AIOperate(float deltaTime, Character character, AIObjectiveOperateItem objective)
@@ -262,12 +252,21 @@ namespace Barotrauma.Items.Components
return TextManager.Get("roomname.subdiroclock").Replace("[dir]", clockDir.ToString());
}
private Vector2 GetTransducerCenter()
private Vector2 GetTransducerPos()
{
if (!UseTransducers || connectedTransducers.Count == 0) return Vector2.Zero;
if (!UseTransducers || connectedTransducers.Count == 0)
{
//use the position of the sub if the item is static (no body) and inside a sub
return item.Submarine != null && item.body == null ? item.Submarine.WorldPosition : item.WorldPosition;
}
Vector2 transducerPosSum = Vector2.Zero;
foreach (ConnectedTransducer transducer in connectedTransducers)
{
if (transducer.Transducer.Item.Submarine != null)
{
return transducer.Transducer.Item.Submarine.WorldPosition;
}
transducerPosSum += transducer.Transducer.Item.WorldPosition;
}
return transducerPosSum / connectedTransducers.Count;

View File

@@ -172,227 +172,6 @@ namespace Barotrauma.Items.Components
return true;
}
public override void OnItemLoaded()
{
sonar = item.GetComponent<Sonar>();
}
public override bool Select(Character character)
{
if (!CanBeSelected) return false;
user = character;
return true;
}
public override void OnItemLoaded()
{
sonar = item.GetComponent<Sonar>();
}
public override bool Select(Character character)
{
if (!CanBeSelected) return false;
user = character;
return true;
}
public override void OnItemLoaded()
{
sonar = item.GetComponent<Sonar>();
}
public override bool Select(Character character)
{
if (!CanBeSelected) return false;
user = character;
return true;
}
public override void OnItemLoaded()
{
sonar = item.GetComponent<Sonar>();
}
public override bool Select(Character character)
{
if (!CanBeSelected) return false;
user = character;
return true;
}
public override void OnItemLoaded()
{
sonar = item.GetComponent<Sonar>();
}
public override bool Select(Character character)
{
if (!CanBeSelected) return false;
user = character;
return true;
}
public override void OnItemLoaded()
{
sonar = item.GetComponent<Sonar>();
}
public override bool Select(Character character)
{
if (!CanBeSelected) return false;
user = character;
return true;
}
public override void OnItemLoaded()
{
sonar = item.GetComponent<Sonar>();
}
public override bool Select(Character character)
{
if (!CanBeSelected) return false;
user = character;
return true;
}
public override void OnItemLoaded()
{
sonar = item.GetComponent<Sonar>();
}
public override bool Select(Character character)
{
if (!CanBeSelected) return false;
user = character;
return true;
}
public override void OnItemLoaded()
{
sonar = item.GetComponent<Sonar>();
}
public override bool Select(Character character)
{
if (!CanBeSelected) return false;
user = character;
return true;
}
public override void OnItemLoaded()
{
sonar = item.GetComponent<Sonar>();
}
public override bool Select(Character character)
{
if (!CanBeSelected) return false;
user = character;
return true;
}
public override void OnItemLoaded()
{
sonar = item.GetComponent<Sonar>();
}
public override bool Select(Character character)
{
if (!CanBeSelected) return false;
user = character;
return true;
}
public override void OnItemLoaded()
{
sonar = item.GetComponent<Sonar>();
}
public override bool Select(Character character)
{
if (!CanBeSelected) return false;
user = character;
return true;
}
public override void OnItemLoaded()
{
sonar = item.GetComponent<Sonar>();
}
public override bool Select(Character character)
{
if (!CanBeSelected) return false;
user = character;
return true;
}
public override void OnItemLoaded()
{
sonar = item.GetComponent<Sonar>();
}
public override bool Select(Character character)
{
if (!CanBeSelected) return false;
user = character;
return true;
}
public override void OnItemLoaded()
{
sonar = item.GetComponent<Sonar>();
}
public override bool Select(Character character)
{
if (!CanBeSelected) return false;
user = character;
return true;
}
public override void OnItemLoaded()
{
sonar = item.GetComponent<Sonar>();
}
public override bool Select(Character character)
{
if (!CanBeSelected) return false;
user = character;
return true;
}
public override void OnItemLoaded()
{
sonar = item.GetComponent<Sonar>();
}
public override bool Select(Character character)
{
if (!CanBeSelected) return false;
user = character;
return true;
}
public override void Update(float deltaTime, Camera cam)
{
networkUpdateTimer -= deltaTime;
@@ -695,7 +474,9 @@ namespace Barotrauma.Items.Components
if (!posToMaintain.HasValue)
{
unsentChanges = true;
posToMaintain = controlledSub == null ? item.WorldPosition : controlledSub.WorldPosition;
posToMaintain = controlledSub != null ?
controlledSub.WorldPosition :
item.Submarine == null ? item.WorldPosition : item.Submarine.WorldPosition;
}
if (!AutoPilot || !MaintainPos) unsentChanges = true;

View File

@@ -1269,7 +1269,7 @@ namespace Barotrauma
if (recursive)
{
List<Item> alreadySearched = new List<Item>() { this };
HashSet<Connection> alreadySearched = new HashSet<Connection>();
GetConnectedComponentsRecursive(alreadySearched, connectedComponents);
return connectedComponents;
@@ -1291,7 +1291,7 @@ namespace Barotrauma
return connectedComponents;
}
private void GetConnectedComponentsRecursive<T>(List<Item> alreadySearched, List<T> connectedComponents) where T : ItemComponent
private void GetConnectedComponentsRecursive<T>(HashSet<Connection> alreadySearched, List<T> connectedComponents) where T : ItemComponent
{
ConnectionPanel connectionPanel = GetComponent<ConnectionPanel>();
if (connectionPanel == null) { return; }
@@ -1315,28 +1315,35 @@ namespace Barotrauma
}
}
recipient.Item.GetConnectedComponentsRecursive<T>(alreadySearched, connectedComponents);
}
}
}
public List<T> GetConnectedComponentsRecursive<T>(Connection c) where T : ItemComponent
{
List<T> connectedComponents = new List<T>();
List<Item> alreadySearched = new List<Item>() { this };
List<T> connectedComponents = new List<T>();
HashSet<Connection> alreadySearched = new HashSet<Connection>();
GetConnectedComponentsRecursive(c, alreadySearched, connectedComponents);
return connectedComponents;
}
private void GetConnectedComponentsRecursive<T>(Connection c, List<Item> alreadySearched, List<T> connectedComponents) where T : ItemComponent
private static readonly Pair<string, string>[] connectionPairs = new Pair<string, string>[]
{
alreadySearched.Add(this);
new Pair<string, string>("power_in", "power_out"),
new Pair<string, string>("signal_in1", "signal_out1"),
new Pair<string, string>("signal_in2", "signal_out2"),
new Pair<string, string>("signal_in3", "signal_out3"),
new Pair<string, string>("signal_in4", "signal_out4"),
new Pair<string, string>("signal_in", "signal_out"),
new Pair<string, string>("signal_in1", "signal_out"),
new Pair<string, string>("signal_in2", "signal_out")
};
private void GetConnectedComponentsRecursive<T>(Connection c, HashSet<Connection> alreadySearched, List<T> connectedComponents) where T : ItemComponent
{
alreadySearched.Add(c);
var recipients = c.Recipients;
foreach (Connection recipient in recipients)
{
if (alreadySearched.Contains(recipient.Item)) continue;
if (alreadySearched.Contains(recipient)) { continue; }
var component = recipient.Item.GetComponent<T>();
if (component != null)
@@ -1345,7 +1352,29 @@ namespace Barotrauma
}
recipient.Item.GetConnectedComponentsRecursive(recipient, alreadySearched, connectedComponents);
}
}
foreach (Pair<string, string> connectionPair in connectionPairs)
{
if (connectionPair.First == c.Name)
{
var pairedConnection = c.Item.Connections.FirstOrDefault(c2 => c2.Name == connectionPair.Second);
if (pairedConnection != null)
{
if (alreadySearched.Contains(pairedConnection)) { continue; }
GetConnectedComponentsRecursive(pairedConnection, alreadySearched, connectedComponents);
}
}
else if (connectionPair.Second == c.Name)
{
var pairedConnection = c.Item.Connections.FirstOrDefault(c2 => c2.Name == connectionPair.First);
if (pairedConnection != null)
{
if (alreadySearched.Contains(pairedConnection)) { continue; }
GetConnectedComponentsRecursive(pairedConnection, alreadySearched, connectedComponents);
}
}
}
}

View File

@@ -795,6 +795,18 @@ namespace Barotrauma
return new Vector2((float)x, (float)y);
}
/// <summary>
/// Rotates a point in 2d space around the origin
/// </summary>
public static Vector2 RotatePoint(Vector2 point, float radians)
{
var sin = Math.Sin(radians);
var cos = Math.Cos(radians);
var x = (cos * point.X) - (sin * point.Y);
var y = (sin * point.X) + (cos * point.Y);
return new Vector2((float)x, (float)y);
}
/// <summary>
/// Returns the corners of an imaginary rectangle.
/// Unlike the XNA rectangle, this can be rotated with the up parameter.