(99feac023) Unstable 0.9.704.0
This commit is contained in:
@@ -28,6 +28,7 @@ namespace Barotrauma
|
||||
}
|
||||
ShapeExtensions.DrawCircle(spriteBatch, pos, SoundRange, 100, color, thickness: 1 / Screen.Selected.Cam.Zoom);
|
||||
ShapeExtensions.DrawCircle(spriteBatch, pos, 3, 8, color, thickness: 2 / Screen.Selected.Cam.Zoom);
|
||||
GUI.DrawLine(spriteBatch, pos, pos + Vector2.UnitY * SoundRange, color, width: (int)(1 / Screen.Selected.Cam.Zoom) + 1);
|
||||
}
|
||||
if (sightRange > 0.0f)
|
||||
{
|
||||
@@ -39,8 +40,6 @@ namespace Barotrauma
|
||||
else if (Entity is Item)
|
||||
{
|
||||
color = Color.CadetBlue;
|
||||
// disable the indicators for items, because they clutter the debug view
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -50,6 +49,7 @@ namespace Barotrauma
|
||||
}
|
||||
ShapeExtensions.DrawCircle(spriteBatch, pos, SightRange, 100, color, thickness: 1 / Screen.Selected.Cam.Zoom);
|
||||
ShapeExtensions.DrawCircle(spriteBatch, pos, 6, 8, color, thickness: 2 / Screen.Selected.Cam.Zoom);
|
||||
GUI.DrawLine(spriteBatch, pos, pos + Vector2.UnitY * SightRange, color, width: (int)(1 / Screen.Selected.Cam.Zoom) + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,9 +16,9 @@ namespace Barotrauma
|
||||
}*/
|
||||
}
|
||||
|
||||
partial void SetOrderProjSpecific(Order order)
|
||||
partial void SetOrderProjSpecific(Order order, string option)
|
||||
{
|
||||
GameMain.GameSession.CrewManager.DisplayCharacterOrder(Character, order);
|
||||
GameMain.GameSession.CrewManager.DisplayCharacterOrder(Character, order, option);
|
||||
}
|
||||
|
||||
public override void DebugDraw(Microsoft.Xna.Framework.Graphics.SpriteBatch spriteBatch)
|
||||
|
||||
@@ -171,10 +171,10 @@ namespace Barotrauma
|
||||
if (GUI.DisableHUD) { return; }
|
||||
|
||||
character.CharacterHealth.Alignment = Alignment.Right;
|
||||
if (Screen.Selected == GameMain.GameScreen)
|
||||
/*if (Screen.Selected == GameMain.GameScreen)
|
||||
{
|
||||
GUI.InfoAreaBackground.Draw(spriteBatch, Vector2.Zero, scale: GUI.Scale);
|
||||
}
|
||||
}*/
|
||||
|
||||
if (GameMain.GameSession?.CrewManager != null)
|
||||
{
|
||||
@@ -318,7 +318,7 @@ namespace Barotrauma
|
||||
if (ShouldDrawInventory(character))
|
||||
{
|
||||
character.Inventory.Locked = LockInventory(character);
|
||||
character.Inventory.DrawOwn(spriteBatch);
|
||||
character.Inventory.DrawThis(spriteBatch);
|
||||
character.Inventory.CurrentLayout = CharacterHealth.OpenHealthWindow == null && character.SelectedCharacter == null ?
|
||||
CharacterInventory.Layout.Default :
|
||||
CharacterInventory.Layout.Right;
|
||||
@@ -333,7 +333,7 @@ namespace Barotrauma
|
||||
{
|
||||
///character.Inventory.CurrentLayout = Alignment.Left;
|
||||
character.SelectedCharacter.Inventory.CurrentLayout = CharacterInventory.Layout.Left;
|
||||
character.SelectedCharacter.Inventory.DrawOwn(spriteBatch);
|
||||
character.SelectedCharacter.Inventory.DrawThis(spriteBatch);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -134,7 +134,8 @@ namespace Barotrauma
|
||||
private float heartbeatTimer;
|
||||
private Texture2D heartrateFade;
|
||||
|
||||
private HeartratePosition[] heartbeatPattern = {
|
||||
private readonly HeartratePosition[] heartbeatPattern =
|
||||
{
|
||||
new HeartratePosition() { Time = 0.0f, Height = 0.0f },
|
||||
new HeartratePosition() { Time = 0.15f, Height = 0.2f },
|
||||
new HeartratePosition() { Time = 0.2f, Height = -0.2f },
|
||||
@@ -174,7 +175,7 @@ namespace Barotrauma
|
||||
|
||||
// 0-1
|
||||
private float damageIntensity;
|
||||
private float damageIntensityDropdownRate = 0.1f;
|
||||
private readonly float damageIntensityDropdownRate = 0.1f;
|
||||
|
||||
public float DamageOverlayTimer { get; private set; }
|
||||
|
||||
@@ -259,14 +260,14 @@ namespace Barotrauma
|
||||
|
||||
bool horizontal = true;
|
||||
healthBar = new GUIProgressBar(HUDLayoutSettings.ToRectTransform(HUDLayoutSettings.HealthBarAreaLeft, GUI.Canvas),
|
||||
barSize: 1.0f, color: GUIColorSettings.HealthBarColorHigh, style: horizontal ? "CharacterHealthBar" : "GUIProgressBarVertical", false)
|
||||
barSize: 1.0f, color: GUIColorSettings.HealthBarColorHigh, style: horizontal ? "CharacterHealthBar" : "GUIProgressBarVertical")
|
||||
{
|
||||
Enabled = true,
|
||||
HoverCursor = CursorState.Hand,
|
||||
IsHorizontal = horizontal
|
||||
};
|
||||
healthBarShadow = new GUIProgressBar(HUDLayoutSettings.ToRectTransform(HUDLayoutSettings.HealthBarAreaLeft, GUI.Canvas),
|
||||
barSize: 1.0f, color: Color.Green, style: horizontal ? "CharacterHealthBar" : "GUIProgressBarVertical", false)
|
||||
barSize: 1.0f, color: Color.Green, style: horizontal ? "CharacterHealthBar" : "GUIProgressBarVertical", showFrame: false)
|
||||
{
|
||||
IsHorizontal = horizontal
|
||||
};
|
||||
@@ -281,9 +282,13 @@ namespace Barotrauma
|
||||
//limb selection frame
|
||||
healthWindow = new GUIFrame(new RectTransform(new Vector2(0.95f, 0.9f), healthWindowContainer.RectTransform, Anchor.CenterRight, Pivot.CenterRight), style: "GUIFrameListBox");
|
||||
|
||||
var healthWindowVerticalLayout = new GUILayoutGroup(new RectTransform(Vector2.One * 0.95f, healthWindow.RectTransform, Anchor.Center));
|
||||
var healthWindowVerticalLayout = new GUILayoutGroup(new RectTransform(Vector2.One * 0.95f, healthWindow.RectTransform, Anchor.Center))
|
||||
{
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.03f
|
||||
};
|
||||
|
||||
var paddedHealthWindow = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.95f), healthWindowVerticalLayout.RectTransform), true)
|
||||
var paddedHealthWindow = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.95f), healthWindowVerticalLayout.RectTransform), isHorizontal: true)
|
||||
{
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.03f
|
||||
@@ -292,7 +297,7 @@ namespace Barotrauma
|
||||
var limbSelection = new GUICustomComponent(new RectTransform(new Vector2(0.6f, 1.0f), paddedHealthWindow.RectTransform),
|
||||
(spriteBatch, component) =>
|
||||
{
|
||||
DrawHealthWindow(spriteBatch, component.RectTransform.Rect, true, false);
|
||||
DrawHealthWindow(spriteBatch, component.RectTransform.Rect, true);
|
||||
},
|
||||
(deltaTime, component) =>
|
||||
{
|
||||
@@ -332,11 +337,15 @@ namespace Barotrauma
|
||||
|
||||
GUILayoutGroup selectedLimbLayout = new GUILayoutGroup(new RectTransform(Vector2.One, rightSide.RectTransform));
|
||||
|
||||
selectedLimbText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.08f), selectedLimbLayout.RectTransform), "", font: GUI.LargeFont);
|
||||
selectedLimbText.AutoScaleHorizontal = true;
|
||||
selectedLimbText = new GUITextBlock(new RectTransform(new Vector2(0.8f, 0.08f), selectedLimbLayout.RectTransform), "", font: GUI.LargeFont, textAlignment: Alignment.Center)
|
||||
{
|
||||
AutoScaleHorizontal = true
|
||||
};
|
||||
|
||||
afflictionIconContainer = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.92f), selectedLimbLayout.RectTransform), style: null);
|
||||
afflictionIconContainer.KeepSpaceForScrollBar = true;
|
||||
afflictionIconContainer = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.92f), selectedLimbLayout.RectTransform), style: null)
|
||||
{
|
||||
KeepSpaceForScrollBar = true
|
||||
};
|
||||
|
||||
var healthBarContainer = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.07f), healthWindowVerticalLayout.RectTransform), style: null);
|
||||
|
||||
@@ -393,7 +402,7 @@ namespace Barotrauma
|
||||
|
||||
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.01f), textLayout.RectTransform), style: "HorizontalLine");
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), textLayout.RectTransform, Anchor.TopLeft), TextManager.Get("SuitableTreatments"), textAlignment: Alignment.TopLeft);
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), textLayout.RectTransform, Anchor.TopLeft), TextManager.Get("SuitableTreatments"), font: GUI.SubHeadingFont);
|
||||
|
||||
treatmentLayout = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.15f), textLayout.RectTransform), true)
|
||||
{
|
||||
@@ -431,9 +440,11 @@ namespace Barotrauma
|
||||
|
||||
heartbeatTimer = 0.46f;
|
||||
|
||||
heartratePositions = new List<HeartratePosition>();
|
||||
heartratePositions.Add(heartbeatPattern.First());
|
||||
heartratePositions.Add(heartbeatPattern.Last());
|
||||
heartratePositions = new List<HeartratePosition>
|
||||
{
|
||||
heartbeatPattern.First(),
|
||||
heartbeatPattern.Last()
|
||||
};
|
||||
|
||||
cprButton = new GUIButton(new RectTransform(new Vector2(1.0f, 1.0f), cprLayout.RectTransform, scaleBasis: ScaleBasis.Smallest), text: "", style: "CPRButton")
|
||||
{
|
||||
@@ -718,16 +729,17 @@ namespace Barotrauma
|
||||
|
||||
if (afflictionTooltip == null || afflictionTooltip.UserData != affliction)
|
||||
{
|
||||
afflictionTooltip = new GUIListBox(new RectTransform(new Vector2(0.4f, 0.2f), GUI.Canvas, scaleBasis: ScaleBasis.Smallest));
|
||||
afflictionTooltip.UserData = affliction;
|
||||
|
||||
afflictionTooltip.CanBeFocused = false;
|
||||
afflictionTooltip = new GUIListBox(new RectTransform(new Vector2(0.4f, 0.2f), GUI.Canvas, scaleBasis: ScaleBasis.Smallest))
|
||||
{
|
||||
UserData = affliction,
|
||||
CanBeFocused = false
|
||||
};
|
||||
|
||||
CreateAfflictionInfoElements(afflictionTooltip.Content, affliction);
|
||||
|
||||
int height = afflictionTooltip.Content.Children.Sum(c => c.Rect.Height) + 10;
|
||||
afflictionTooltip.RectTransform.Resize(new Point(afflictionTooltip.Rect.Width, height), true);
|
||||
afflictionTooltip.RectTransform.AbsoluteOffset = GUI.MouseOn.Rect.Center;
|
||||
afflictionTooltip.RectTransform.AbsoluteOffset = new Point(GUI.MouseOn.Rect.Right, GUI.MouseOn.Rect.Y);
|
||||
afflictionTooltip.ScrollBarVisible = false;
|
||||
|
||||
var labelContainer = afflictionTooltip.Content.GetChildByUserData("label");
|
||||
@@ -1105,6 +1117,9 @@ namespace Barotrauma
|
||||
Dictionary<string, float> treatmentSuitability = new Dictionary<string, float>();
|
||||
GetSuitableTreatments(treatmentSuitability, normalize: true, randomization: randomVariance);
|
||||
|
||||
Affliction mostSevereAffliction = afflictions.FirstOrDefault(a => !a.Prefab.IsBuff && !afflictions.Any(a2 => !a2.Prefab.IsBuff && a2.Strength > a.Strength)) ?? afflictions.FirstOrDefault();
|
||||
GUIButton buttonToSelect = null;
|
||||
|
||||
foreach (Affliction affliction in afflictions)
|
||||
{
|
||||
var child = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.25f), afflictionIconContainer.Content.RectTransform, Anchor.TopCenter))
|
||||
@@ -1117,16 +1132,24 @@ namespace Barotrauma
|
||||
Color = Color.Gray.Multiply(0.1f).Opaque(),
|
||||
HoverColor = Color.Gray.Multiply(0.4f).Opaque(),
|
||||
SelectedColor = Color.Gray.Multiply(0.25f).Opaque(),
|
||||
PressedColor = Color.Black,
|
||||
PressedColor = Color.Gray.Multiply(0.2f).Opaque(),
|
||||
UserData = "selectaffliction",
|
||||
OnClicked = SelectAffliction
|
||||
};
|
||||
|
||||
new GUIImage(new RectTransform(Vector2.One * 0.9f, button.RectTransform, Anchor.Center), affliction.Prefab.Icon, scaleToFit: true)
|
||||
if (affliction == mostSevereAffliction)
|
||||
{
|
||||
buttonToSelect = button;
|
||||
}
|
||||
|
||||
var afflictionIcon = new GUIImage(new RectTransform(Vector2.One * 0.9f, button.RectTransform, Anchor.Center), affliction.Prefab.Icon, scaleToFit: true)
|
||||
{
|
||||
Color = GetAfflictionIconColor(affliction.Prefab, affliction),
|
||||
CanBeFocused = false
|
||||
};
|
||||
afflictionIcon.PressedColor = afflictionIcon.Color;
|
||||
afflictionIcon.HoverColor = Color.Lerp(afflictionIcon.Color, Color.White, 0.6f);
|
||||
afflictionIcon.SelectedColor = Color.Lerp(afflictionIcon.Color, Color.White, 0.5f);
|
||||
|
||||
float afflictionVitalityDecrease = affliction.GetVitalityDecrease(this);
|
||||
|
||||
@@ -1140,7 +1163,7 @@ namespace Barotrauma
|
||||
afflictionEffectColor = GUI.Style.Green;
|
||||
}
|
||||
|
||||
new GUIProgressBar(new RectTransform(new Vector2(1.0f, 0.1f), child.RectTransform), 0.0f, afflictionEffectColor)
|
||||
new GUIProgressBar(new RectTransform(new Vector2(1.0f, 0.1f), child.RectTransform), 0.0f, afflictionEffectColor, style: "CharacterHealthBar")
|
||||
{
|
||||
UserData = "afflictionstrength"
|
||||
};
|
||||
@@ -1148,6 +1171,8 @@ namespace Barotrauma
|
||||
child.Recalculate();
|
||||
}
|
||||
|
||||
if (buttonToSelect != null) { buttonToSelect.OnClicked(buttonToSelect, "selectaffliction"); }
|
||||
|
||||
afflictionIconContainer.RecalculateChildren();
|
||||
|
||||
List<KeyValuePair<string, float>> treatmentSuitabilities = treatmentSuitability.OrderByDescending(t => t.Value).ToList();
|
||||
@@ -1157,8 +1182,7 @@ namespace Barotrauma
|
||||
{
|
||||
count++;
|
||||
if (count > 5) { break; }
|
||||
ItemPrefab item = MapEntityPrefab.Find(name: null, identifier: treatment.Key, showErrorMessages: false) as ItemPrefab;
|
||||
if (item == null) continue;
|
||||
if (!(MapEntityPrefab.Find(name: null, identifier: treatment.Key, showErrorMessages: false) is ItemPrefab item)) { continue; }
|
||||
|
||||
var itemSlot = new GUIFrame(new RectTransform(new Vector2(1.0f / 7.0f, 1.0f), recommendedTreatmentContainer.Content.RectTransform, Anchor.TopLeft),
|
||||
style: null)
|
||||
@@ -1299,7 +1323,9 @@ namespace Barotrauma
|
||||
|
||||
private void UpdateHeartrate(float deltaTime, GUICustomComponent component)
|
||||
{
|
||||
heartbeatTimer -= deltaTime * 0.75f;
|
||||
if (GameMain.Instance.Paused) { return; }
|
||||
|
||||
heartbeatTimer -= deltaTime * 0.5f;
|
||||
|
||||
if (heartbeatTimer <= 0.0f)
|
||||
{
|
||||
@@ -1335,7 +1361,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
currentHeartrateTime += deltaTime * 0.75f;
|
||||
currentHeartrateTime += deltaTime * 0.5f;
|
||||
while (currentHeartrateTime >= 1.0f)
|
||||
{
|
||||
currentHeartrateTime -= 1.0f;
|
||||
@@ -1377,9 +1403,9 @@ namespace Barotrauma
|
||||
|
||||
Rectangle sourceRect = heartrateFade.Bounds;
|
||||
|
||||
Rectangle destinationRectangle = new Rectangle();
|
||||
destinationRectangle.Location = new Point((int)(currentHeartrateTime * targetRect.Width) + targetRect.Left - targetRect.Height, targetRect.Top);
|
||||
destinationRectangle.Size = new Point((int)(targetRect.Height * ((float)sourceRect.Width / (float)sourceRect.Height)), targetRect.Height);
|
||||
Rectangle destinationRectangle = new Rectangle(
|
||||
new Point((int)(currentHeartrateTime * targetRect.Width) + targetRect.Left - targetRect.Height, targetRect.Top),
|
||||
new Point((int)(targetRect.Height * ((float)sourceRect.Width / (float)sourceRect.Height)), targetRect.Height));
|
||||
|
||||
if (destinationRectangle.Left < targetRect.Left)
|
||||
{
|
||||
@@ -1557,7 +1583,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawHealthWindow(SpriteBatch spriteBatch, Rectangle drawArea, bool allowHighlight, bool highlightAll)
|
||||
private void DrawHealthWindow(SpriteBatch spriteBatch, Rectangle drawArea, bool allowHighlight)
|
||||
{
|
||||
if (Character.Removed) { return; }
|
||||
|
||||
@@ -1586,16 +1612,16 @@ namespace Barotrauma
|
||||
float midPoint = (float)limbEffectiveArea.Center.Y / (float)limbHealth.IndicatorSprite.Texture.Height;
|
||||
float fadeDist = 0.6f * (float)limbEffectiveArea.Height / (float)limbHealth.IndicatorSprite.Texture.Height;
|
||||
|
||||
if (negativeEffect > 0.0f && negativeEffect < 5.0f) { negativeEffect = 5.0f; }
|
||||
if (positiveEffect > 0.0f && positiveEffect < 5.0f) { positiveEffect = 5.0f; }
|
||||
if (negativeEffect > 0.0f && negativeEffect < 5.0f) { negativeEffect = 10.0f; }
|
||||
if (positiveEffect > 0.0f && positiveEffect < 5.0f) { positiveEffect = 10.0f; }
|
||||
|
||||
Color positiveColor = Color.Lerp(Color.Orange, Color.Lime, Math.Min(positiveEffect / 15.0f, 1.0f));
|
||||
Color negativeColor = Color.Lerp(Color.Orange, Color.Red, Math.Min(negativeEffect / 15.0f, 1.0f));
|
||||
Color positiveColor = Color.Lerp(Color.Orange, Color.Lime, Math.Min(positiveEffect / 25.0f, 1.0f));
|
||||
Color negativeColor = Color.Lerp(Color.Orange, Color.Red, Math.Min(negativeEffect / 25.0f, 1.0f));
|
||||
|
||||
Color color1 = Color.Orange;
|
||||
Color color2 = Color.Orange;
|
||||
|
||||
if (negativeEffect+positiveEffect > 0.0f)
|
||||
if (negativeEffect + positiveEffect > 0.0f)
|
||||
{
|
||||
if (negativeEffect >= positiveEffect)
|
||||
{
|
||||
@@ -1614,11 +1640,6 @@ namespace Barotrauma
|
||||
color1 = Color.Lerp(color1, Color.Black, 0.75f);
|
||||
color2 = Color.Lerp(color2, Color.Black, 0.75f);
|
||||
}
|
||||
if (((i == highlightedLimbIndex || i == selectedLimbIndex) && allowHighlight) || highlightAll)
|
||||
{
|
||||
color1 = Color.Lerp(color1, Color.White, 0.5f);
|
||||
color2 = Color.Lerp(color2, Color.White, 0.5f);
|
||||
}
|
||||
|
||||
GameMain.GameScreen.GradientEffect.Parameters["color1"].SetValue(color1.ToVector4());
|
||||
GameMain.GameScreen.GradientEffect.Parameters["color2"].SetValue(color2.ToVector4());
|
||||
@@ -1666,36 +1687,75 @@ namespace Barotrauma
|
||||
limbIndicatorOverlay.Draw(spriteBatch, frame, drawArea.Center.ToVector2(), Color.Gray, origin: limbIndicatorOverlay.FrameSize.ToVector2() / 2, rotate: 0.0f,
|
||||
scale: Vector2.One * overlayScale);
|
||||
|
||||
if (allowHighlight)
|
||||
{
|
||||
i = 0;
|
||||
foreach (LimbHealth limbHealth in limbHealths)
|
||||
{
|
||||
if (limbHealth.HighlightSprite == null) { continue; }
|
||||
|
||||
float scale = Math.Min(drawArea.Width / (float)limbHealth.HighlightSprite.SourceRect.Width, drawArea.Height / (float)limbHealth.HighlightSprite.SourceRect.Height);
|
||||
|
||||
int drawCount = 0;
|
||||
if (i == highlightedLimbIndex) { drawCount++; }
|
||||
if (i == selectedLimbIndex) { drawCount++; }
|
||||
for (int j = 0; j < drawCount; j++)
|
||||
{
|
||||
limbHealth.HighlightSprite.Draw(spriteBatch,
|
||||
drawArea.Center.ToVector2(), Color.White,
|
||||
limbHealth.HighlightSprite.Origin,
|
||||
0, scale);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
spriteBatch.End();
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, blendState: BlendState.NonPremultiplied, rasterizerState: GameMain.ScissorTestEnable);
|
||||
|
||||
i = 0;
|
||||
foreach (LimbHealth limbHealth in limbHealths)
|
||||
{
|
||||
if (limbHealth.IndicatorSprite == null) continue;
|
||||
IEnumerable<Affliction> thisAfflictions = limbHealth.Afflictions.Where(a => a.Strength >= a.Prefab.ShowIconThreshold);
|
||||
thisAfflictions = thisAfflictions.Concat(afflictions.Where(a =>
|
||||
{
|
||||
Limb indicatorLimb = Character.AnimController.GetLimb(a.Prefab.IndicatorLimb);
|
||||
return (indicatorLimb != null && indicatorLimb.HealthIndex == i && a.Strength >= a.Prefab.ShowIconThreshold);
|
||||
}));
|
||||
|
||||
if (thisAfflictions.Count() <= 0) { i++; continue; }
|
||||
if (limbHealth.IndicatorSprite == null) { continue; }
|
||||
|
||||
float scale = Math.Min(drawArea.Width / (float)limbHealth.IndicatorSprite.SourceRect.Width, drawArea.Height / (float)limbHealth.IndicatorSprite.SourceRect.Height);
|
||||
|
||||
Rectangle highlightArea = GetLimbHighlightArea(limbHealth, drawArea);
|
||||
|
||||
float scale = Math.Min(drawArea.Width / (float)limbHealth.IndicatorSprite.SourceRect.Width, drawArea.Height / (float)limbHealth.IndicatorSprite.SourceRect.Height);
|
||||
|
||||
float iconScale = 0.3f * scale;
|
||||
float iconScale = 0.25f * scale;
|
||||
Vector2 iconPos = highlightArea.Center.ToVector2();
|
||||
foreach (Affliction affliction in limbHealth.Afflictions)
|
||||
|
||||
Affliction mostSevereAffliction = thisAfflictions.FirstOrDefault(a => !a.Prefab.IsBuff && !thisAfflictions.Any(a2 => !a2.Prefab.IsBuff && a2.Strength > a.Strength)) ?? thisAfflictions.FirstOrDefault();
|
||||
|
||||
if (mostSevereAffliction != null) { DrawLimbAfflictionIcon(spriteBatch, mostSevereAffliction, iconScale, ref iconPos); }
|
||||
|
||||
if (thisAfflictions.Count() > 1)
|
||||
{
|
||||
DrawLimbAfflictionIcon(spriteBatch, affliction, iconScale, ref iconPos);
|
||||
string additionalAfflictionCount = $"+{thisAfflictions.Count() - 1}";
|
||||
Vector2 displace = GUI.SubHeadingFont.MeasureString(additionalAfflictionCount);
|
||||
GUI.SubHeadingFont.DrawString(spriteBatch, additionalAfflictionCount, iconPos + new Vector2(displace.X * 1.1f, -displace.Y * 0.45f), Color.Black * 0.75f);
|
||||
GUI.SubHeadingFont.DrawString(spriteBatch, additionalAfflictionCount, iconPos + new Vector2(displace.X, -displace.Y * 0.5f), Color.White);
|
||||
}
|
||||
|
||||
foreach (Affliction affliction in afflictions)
|
||||
{
|
||||
Limb indicatorLimb = Character.AnimController.GetLimb(affliction.Prefab.IndicatorLimb);
|
||||
if (indicatorLimb != null && indicatorLimb.HealthIndex == i)
|
||||
{
|
||||
DrawLimbAfflictionIcon(spriteBatch, affliction, iconScale, ref iconPos);
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
|
||||
if (selectedLimbIndex > -1)
|
||||
{
|
||||
var selectedLimbArea = GetLimbHighlightArea(limbHealths[selectedLimbIndex], drawArea);
|
||||
GUI.DrawLine(spriteBatch,
|
||||
new Vector2(selectedLimbText.Rect.X, selectedLimbText.Rect.Center.Y),
|
||||
selectedLimbArea.Center.ToVector2(),
|
||||
Color.LightGray * 0.5f, width: 4);
|
||||
}
|
||||
|
||||
if (draggingMed != null)
|
||||
{
|
||||
GUIImage itemImage = draggingMed.GetChild<GUIImage>();
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace Barotrauma
|
||||
font: GUI.SmallFont);
|
||||
}
|
||||
|
||||
if (!ItemNames.TryGetValue(variant, out var itemNames)) { return backFrame; }
|
||||
if (!ItemIdentifiers.TryGetValue(variant, out var itemIdentifiers)) { return backFrame; }
|
||||
var itemContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.45f, 0.5f), paddedFrame.RectTransform, Anchor.TopRight)
|
||||
{ RelativeOffset = new Vector2(0.0f, 0.2f + descriptionBlock.RectTransform.RelativeSize.Y) })
|
||||
{
|
||||
@@ -40,11 +40,12 @@ namespace Barotrauma
|
||||
};
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), itemContainer.RectTransform),
|
||||
TextManager.Get("Items", fallBackTag: "mapentitycategory.equipment"), font: GUI.LargeFont);
|
||||
foreach (string itemName in itemNames.Distinct())
|
||||
foreach (string identifier in itemIdentifiers.Distinct())
|
||||
{
|
||||
int count = itemNames.Count(i => i == itemName);
|
||||
if (!(MapEntityPrefab.Find(name: null, identifier: identifier) is ItemPrefab itemPrefab)) { continue; }
|
||||
int count = itemIdentifiers.Count(i => i == identifier);
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), itemContainer.RectTransform),
|
||||
" - " + (count == 1 ? itemName : itemName + " x" + count),
|
||||
" - " + (count == 1 ? itemPrefab.Name : itemPrefab.Name + " x" + count),
|
||||
font: GUI.SmallFont);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
using Barotrauma.Networking;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
partial class CargoMission : Mission
|
||||
{
|
||||
public override void ClientReadInitial(IReadMessage msg)
|
||||
{
|
||||
ushort itemCount = msg.ReadUInt16();
|
||||
for (int i = 0; i < itemCount; i++)
|
||||
{
|
||||
items.Add(Item.ReadSpawnData(msg));
|
||||
}
|
||||
if (items.Contains(null))
|
||||
{
|
||||
throw new System.Exception("Error in CargoMission.ClientReadInitial: item list contains null (mission: " + Prefab.Identifier + ")");
|
||||
}
|
||||
if (items.Count != itemCount)
|
||||
{
|
||||
throw new System.Exception("Error in CargoMission.ClientReadInitial: item count does not match the server count (" + itemCount + " != " + items.Count + "mission: " + Prefab.Identifier + ")");
|
||||
}
|
||||
if (requiredDeliveryAmount == 0) { requiredDeliveryAmount = items.Count; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
namespace Barotrauma
|
||||
using Barotrauma.Networking;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
partial class CombatMission
|
||||
{
|
||||
@@ -18,5 +20,10 @@
|
||||
return descriptions[GameMain.Client.Character.TeamID == Character.TeamType.Team1 ? 1 : 2];
|
||||
}
|
||||
}
|
||||
|
||||
public override void ClientReadInitial(IReadMessage msg)
|
||||
{
|
||||
//do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,5 +23,7 @@ namespace Barotrauma
|
||||
{
|
||||
State = msg.ReadInt16();
|
||||
}
|
||||
|
||||
public abstract void ClientReadInitial(IReadMessage msg);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
using Barotrauma.Networking;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
partial class MonsterMission : Mission
|
||||
{
|
||||
public override void ClientReadInitial(IReadMessage msg)
|
||||
{
|
||||
byte monsterCount = msg.ReadByte();
|
||||
for (int i = 0; i < monsterCount; i++)
|
||||
{
|
||||
monsters.Add(Character.ReadSpawnData(msg));
|
||||
}
|
||||
if (monsters.Contains(null))
|
||||
{
|
||||
throw new System.Exception("Error in MonsterMission.ClientReadInitial: monster list contains null (mission: " + Prefab.Identifier + ")");
|
||||
}
|
||||
if (monsters.Count != monsterCount)
|
||||
{
|
||||
throw new System.Exception("Error in MonsterMission.ClientReadInitial: monster count does not match the server count (" + monsterCount + " != " + monsters.Count + "mission: " + Prefab.Identifier + ")");
|
||||
}
|
||||
InitializeMonsters(monsters);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using Barotrauma.Networking;
|
||||
using FarseerPhysics;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
partial class SalvageMission : Mission
|
||||
{
|
||||
public override void ClientReadInitial(IReadMessage msg)
|
||||
{
|
||||
item = Item.ReadSpawnData(msg);
|
||||
if (item == null)
|
||||
{
|
||||
throw new System.Exception("Error in SalvageMission.ClientReadInitial: spawned item was null (mission: " + Prefab.Identifier + ")");
|
||||
}
|
||||
|
||||
item.body.FarseerBody.BodyType = BodyType.Kinematic;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -37,6 +37,8 @@ namespace Barotrauma
|
||||
}
|
||||
private float openState;
|
||||
|
||||
public bool CloseAfterMessageSent;
|
||||
|
||||
private float prevUIScale;
|
||||
|
||||
//individual message texts that pop up when the chatbox is hidden
|
||||
@@ -286,6 +288,10 @@ namespace Barotrauma
|
||||
public void SetVisibility(bool visible)
|
||||
{
|
||||
GUIFrame.Parent.Visible = visible;
|
||||
if (GameMain.GameSession?.CrewManager?.ReportButtonFrame != null)
|
||||
{
|
||||
GameMain.GameSession.CrewManager.ReportButtonFrame.Visible = visible;
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerable<object> UpdateMessageAnimation(GUIComponent message, float animDuration)
|
||||
@@ -330,6 +336,17 @@ namespace Barotrauma
|
||||
prevUIScale = GUI.Scale;
|
||||
}
|
||||
|
||||
//hide chatbox when accessing the inventory of another character to prevent overlaps
|
||||
if (Character.Controlled?.SelectedCharacter?.Inventory != null &&
|
||||
Character.Controlled.SelectedCharacter.CanInventoryBeAccessed)
|
||||
{
|
||||
SetVisibility(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetVisibility(true);
|
||||
}
|
||||
|
||||
if (showNewMessagesButton.Visible && chatBox.ScrollBar.BarScroll == 1f)
|
||||
{
|
||||
showNewMessagesButton.Visible = false;
|
||||
|
||||
@@ -59,11 +59,15 @@ namespace Barotrauma
|
||||
|
||||
public readonly GUIStyle Style;
|
||||
|
||||
public readonly string Name;
|
||||
|
||||
public int? Width { get; private set; }
|
||||
public int? Height { get; private set; }
|
||||
|
||||
public GUIComponentStyle(XElement element, GUIStyle style)
|
||||
{
|
||||
Name = element.Name.LocalName;
|
||||
|
||||
Style = style;
|
||||
Element = element;
|
||||
|
||||
|
||||
@@ -133,6 +133,7 @@ namespace Barotrauma
|
||||
public static ScalableFont LargeFont => Style?.LargeFont;
|
||||
public static ScalableFont SubHeadingFont => Style?.SubHeadingFont;
|
||||
public static ScalableFont DigitalFont => Style?.DigitalFont;
|
||||
public static ScalableFont HotkeyFont => Style?.HotkeyFont;
|
||||
|
||||
public static ScalableFont CJKFont { get; private set; }
|
||||
|
||||
@@ -988,6 +989,7 @@ namespace Barotrauma
|
||||
Debug.Assert(updateList.Count == updateListSet.Count);
|
||||
updateList.ForEach(c => c.UpdateAuto(deltaTime));
|
||||
UpdateMessages(deltaTime);
|
||||
UpdateInput();
|
||||
}
|
||||
|
||||
private static void UpdateMessages(float deltaTime)
|
||||
@@ -1027,6 +1029,32 @@ namespace Barotrauma
|
||||
messages.RemoveAll(m => m.Timer <= 0.0f);
|
||||
}
|
||||
|
||||
private static void UpdateInput()
|
||||
{
|
||||
if (PlayerInput.KeyHit(InputType.ToggleInventory))
|
||||
{
|
||||
if (Character.Controlled?.Inventory != null)
|
||||
{
|
||||
Character.Controlled.Inventory.ToggleInventory();
|
||||
}
|
||||
}
|
||||
|
||||
if (PlayerInput.KeyHit(Keys.Escape) && GameMain.WindowActive)
|
||||
{
|
||||
HandleEscFunctionality();
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
if (GameMain.NetworkMember == null)
|
||||
{
|
||||
if (PlayerInput.KeyHit(Keys.P) && !(KeyboardDispatcher.Subscriber is GUITextBox))
|
||||
{
|
||||
DebugConsole.Paused = !DebugConsole.Paused;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#region Element drawing
|
||||
|
||||
public static void DrawIndicator(SpriteBatch spriteBatch, Vector2 worldPosition, Camera cam, float hideDist, Sprite sprite, Color color)
|
||||
@@ -1760,32 +1788,30 @@ namespace Barotrauma
|
||||
if (!rect1.Intersects(rect2)) continue;
|
||||
|
||||
intersections = true;
|
||||
int rect1Area = rect1.Width * rect1.Height;
|
||||
int rect2Area = rect2.Width * rect2.Height;
|
||||
Point centerDiff = rect1.Center - rect2.Center;
|
||||
//move the interfaces away from each other, in a random direction if they're at the same position
|
||||
Vector2 moveAmount = centerDiff == Point.Zero ? Rand.Vector(1.0f) : Vector2.Normalize(centerDiff.ToVector2());
|
||||
|
||||
//if the horizontal move amount is much larger than vertical, only move horizontally
|
||||
//(= attempt to place the elements side-by-side if they're more apart horizontally than vertically)
|
||||
if (Math.Abs(moveAmount.X) > Math.Abs(moveAmount.Y) * 5.0f)
|
||||
if (Math.Abs(moveAmount.X) > Math.Abs(moveAmount.Y) * 8.0f)
|
||||
{
|
||||
moveAmount.Y = 0.0f;
|
||||
}
|
||||
//same for the y-axis
|
||||
else if (Math.Abs(moveAmount.Y) > Math.Abs(moveAmount.X) * 5.0f)
|
||||
else if (Math.Abs(moveAmount.Y) > Math.Abs(moveAmount.X) * 8.0f)
|
||||
{
|
||||
moveAmount.X = 0.0f;
|
||||
}
|
||||
|
||||
//make sure we don't move the interfaces out of the screen
|
||||
Vector2 moveAmount1 = ClampMoveAmount(rect1, area, moveAmount * 20.0f * rect1Area / (rect1Area + rect2Area));
|
||||
Vector2 moveAmount2 = ClampMoveAmount(rect2, area, -moveAmount * 20.0f * rect1Area / (rect1Area + rect2Area));
|
||||
Vector2 moveAmount1 = ClampMoveAmount(rect1, area, moveAmount * 10.0f);
|
||||
Vector2 moveAmount2 = ClampMoveAmount(rect2, area, -moveAmount * 10.0f);
|
||||
|
||||
//move by 10 units in the desired direction and repeat until nothing overlaps
|
||||
//(or after 100 iterations, in which case we'll just give up and let them overlap)
|
||||
elements[i].RectTransform.ScreenSpaceOffset += (moveAmount1).ToPoint();
|
||||
elements[j].RectTransform.ScreenSpaceOffset += (moveAmount2).ToPoint();
|
||||
elements[i].RectTransform.ScreenSpaceOffset += moveAmount1.ToPoint();
|
||||
elements[j].RectTransform.ScreenSpaceOffset += moveAmount2.ToPoint();
|
||||
}
|
||||
|
||||
if (disallowedAreas == null) continue;
|
||||
@@ -1834,6 +1860,50 @@ namespace Barotrauma
|
||||
#endregion
|
||||
|
||||
#region Misc
|
||||
private static void HandleEscFunctionality()
|
||||
{
|
||||
// Check if a text input is selected.
|
||||
if (KeyboardDispatcher.Subscriber != null)
|
||||
{
|
||||
if (KeyboardDispatcher.Subscriber is GUITextBox textBox)
|
||||
{
|
||||
textBox.Deselect();
|
||||
}
|
||||
KeyboardDispatcher.Subscriber = null;
|
||||
}
|
||||
//if a verification prompt (are you sure you want to x) is open, close it
|
||||
else if (GUIMessageBox.VisibleBox as GUIMessageBox != null &&
|
||||
GUIMessageBox.VisibleBox.UserData as string == "verificationprompt")
|
||||
{
|
||||
((GUIMessageBox)GUIMessageBox.VisibleBox).Close();
|
||||
}
|
||||
else if (Tutorials.Tutorial.Initialized && Tutorials.Tutorial.ContentRunning)
|
||||
{
|
||||
(GameMain.GameSession.GameMode as TutorialMode).Tutorial.CloseActiveContentGUI();
|
||||
}
|
||||
else if (PauseMenuOpen)
|
||||
{
|
||||
TogglePauseMenu();
|
||||
}
|
||||
//open the pause menu if not controlling a character OR if the character has no UIs active that can be closed with ESC
|
||||
else if ((Character.Controlled == null || !itemHudActive())
|
||||
//TODO: do we need to check Inventory.SelectedSlot?
|
||||
&& Inventory.SelectedSlot == null && CharacterHealth.OpenHealthWindow == null
|
||||
&& !CrewManager.IsCommandInterfaceOpen)
|
||||
{
|
||||
// Otherwise toggle pausing, unless another window/interface is open.
|
||||
TogglePauseMenu();
|
||||
}
|
||||
|
||||
bool itemHudActive()
|
||||
{
|
||||
if (Character.Controlled?.SelectedConstruction == null) { return false; }
|
||||
return
|
||||
Character.Controlled.SelectedConstruction.ActiveHUDs.Any(ic => ic.GuiFrame != null) ||
|
||||
((Character.Controlled.ViewTarget as Item)?.Prefab?.FocusOnSelected ?? false);
|
||||
}
|
||||
}
|
||||
|
||||
public static void TogglePauseMenu()
|
||||
{
|
||||
if (Screen.Selected == GameMain.MainMenuScreen) return;
|
||||
|
||||
@@ -5,22 +5,23 @@ namespace Barotrauma
|
||||
public class GUIColorSettings
|
||||
{
|
||||
// Inventory
|
||||
public static Color InventorySlotColor = new Color(78, 114, 88);
|
||||
public static Color EquipmentSlotColor = new Color(72, 58, 25);
|
||||
public static Color EquipmentSlotIconColor = new Color(99, 70, 64);
|
||||
public static readonly Color InventorySlotColor = new Color(27, 140, 132);
|
||||
public static readonly Color InventorySlotEquippedColor = new Color(211, 227, 217);
|
||||
public static readonly Color EquipmentSlotEmptyColor = new Color(152, 148, 128);
|
||||
public static readonly Color EquipmentSlotColor = new Color(225, 211, 189);
|
||||
public static readonly Color EquipmentSlotIconColor = new Color(99, 70, 64);
|
||||
|
||||
// Health HUD
|
||||
public static Color BuffColorLow = Color.LightGreen;
|
||||
public static Color BuffColorMedium = Color.Green;
|
||||
public static Color BuffColorHigh = Color.DarkGreen;
|
||||
public static readonly Color BuffColorLow = Color.LightGreen;
|
||||
public static readonly Color BuffColorMedium = Color.Green;
|
||||
public static readonly Color BuffColorHigh = Color.DarkGreen;
|
||||
|
||||
public static Color DebuffColorLow = Color.DarkSalmon;
|
||||
public static Color DebuffColorMedium = Color.Red;
|
||||
public static Color DebuffColorHigh = Color.DarkRed;
|
||||
|
||||
public static Color HealthBarColorLow = Color.Red;
|
||||
public static Color HealthBarColorMedium = Color.Orange;
|
||||
public static Color HealthBarColorHigh = new Color(78, 114, 88);
|
||||
public static readonly Color DebuffColorLow = Color.DarkSalmon;
|
||||
public static readonly Color DebuffColorMedium = Color.Red;
|
||||
public static readonly Color DebuffColorHigh = Color.DarkRed;
|
||||
|
||||
public static readonly Color HealthBarColorLow = Color.Red;
|
||||
public static readonly Color HealthBarColorMedium = Color.Orange;
|
||||
public static readonly Color HealthBarColorHigh = new Color(78, 114, 88);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -517,6 +517,7 @@ namespace Barotrauma
|
||||
return state switch
|
||||
{
|
||||
ComponentState.Hover => HoverColor,
|
||||
ComponentState.HoverSelected => HoverColor,
|
||||
ComponentState.Pressed => PressedColor,
|
||||
ComponentState.Selected => SelectedColor,
|
||||
_ => Color,
|
||||
|
||||
@@ -83,7 +83,7 @@ namespace Barotrauma
|
||||
get { return floatValue; }
|
||||
set
|
||||
{
|
||||
if (value == floatValue) return;
|
||||
if (MathUtils.NearlyEqual(value, floatValue)) return;
|
||||
floatValue = value;
|
||||
ClampFloatValue();
|
||||
float newValue = floatValue;
|
||||
@@ -134,7 +134,6 @@ namespace Barotrauma
|
||||
if (value == intValue) return;
|
||||
intValue = value;
|
||||
UpdateText();
|
||||
OnValueChanged?.Invoke(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ namespace Barotrauma
|
||||
public ScalableFont LargeFont { get; private set; }
|
||||
public ScalableFont SubHeadingFont { get; private set; }
|
||||
public ScalableFont DigitalFont { get; private set; }
|
||||
public ScalableFont HotkeyFont { get; private set; }
|
||||
|
||||
public Dictionary<ScalableFont, bool> ForceFontUpperCase
|
||||
{
|
||||
@@ -63,8 +64,8 @@ namespace Barotrauma
|
||||
public Color TextColorDark { get; private set; } = Color.Black * 0.9f;
|
||||
public Color TextColorDim { get; private set; } = Color.White * 0.6f;
|
||||
|
||||
public static Point ItemFrameMargin = new Point(50, 56).Multiply(GUI.SlicedSpriteScale);
|
||||
public static Point ItemFrameOffset = new Point(0, 3).Multiply(GUI.SlicedSpriteScale);
|
||||
public static Point ItemFrameMargin => new Point(50, 56).Multiply(GUI.SlicedSpriteScale);
|
||||
public static Point ItemFrameOffset => new Point(0, 3).Multiply(GUI.SlicedSpriteScale);
|
||||
|
||||
public GUIStyle(XElement element, GraphicsDevice graphicsDevice)
|
||||
{
|
||||
@@ -148,6 +149,10 @@ namespace Barotrauma
|
||||
DigitalFont = LoadFont(subElement, graphicsDevice);
|
||||
ForceFontUpperCase[DigitalFont] = subElement.GetAttributeBool("forceuppercase", false);
|
||||
break;
|
||||
case "hotkeyfont":
|
||||
HotkeyFont = LoadFont(subElement, graphicsDevice);
|
||||
ForceFontUpperCase[HotkeyFont] = subElement.GetAttributeBool("forceuppercase", false);
|
||||
break;
|
||||
case "objectivetitle":
|
||||
case "subheading":
|
||||
SubHeadingFont = LoadFont(subElement, graphicsDevice);
|
||||
@@ -236,8 +241,20 @@ namespace Barotrauma
|
||||
return new ScalableFont(file, size, graphicsDevice, dynamicLoading, isCJK);
|
||||
}
|
||||
|
||||
private uint GetFontSize(XElement element)
|
||||
private uint GetFontSize(XElement element, uint defaultSize = 14)
|
||||
{
|
||||
//check if any of the language override fonts want to override the font size as well
|
||||
foreach (XElement subElement in element.Elements())
|
||||
{
|
||||
if (subElement.Name.ToString().ToLowerInvariant() != "override") { continue; }
|
||||
string language = subElement.GetAttributeString("language", "").ToLowerInvariant();
|
||||
if (GameMain.Config.Language.ToLowerInvariant() == language)
|
||||
{
|
||||
uint overrideFontSize = GetFontSize(subElement, 0);
|
||||
if (overrideFontSize > 0) { return overrideFontSize; }
|
||||
}
|
||||
}
|
||||
|
||||
foreach (XElement subElement in element.Elements())
|
||||
{
|
||||
if (subElement.Name.ToString().ToLowerInvariant() != "size") { continue; }
|
||||
@@ -247,7 +264,7 @@ namespace Barotrauma
|
||||
return (uint)subElement.GetAttributeInt("size", 14);
|
||||
}
|
||||
}
|
||||
return 14;
|
||||
return defaultSize;
|
||||
}
|
||||
|
||||
private string GetFontFilePath(XElement element)
|
||||
|
||||
@@ -6,14 +6,18 @@ using System.Collections.Generic;
|
||||
using System.Xml.Linq;
|
||||
using Barotrauma.Media;
|
||||
using System.Linq;
|
||||
using Barotrauma.Extensions;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
class LoadingScreen
|
||||
{
|
||||
private Texture2D backgroundTexture;
|
||||
private readonly Texture2D defaultBackgroundTexture, overlay;
|
||||
private readonly SpriteSheet decorativeGraph, decorativeMap;
|
||||
private Texture2D currentBackgroundTexture;
|
||||
private Sprite noiseSprite;
|
||||
|
||||
private RenderTarget2D renderTarget;
|
||||
private string randText = "";
|
||||
|
||||
private Sprite languageSelectionCursor;
|
||||
private ScalableFont languageSelectionFont, languageSelectionFontCJK;
|
||||
@@ -65,15 +69,9 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
private float state;
|
||||
|
||||
private string selectedTip;
|
||||
|
||||
public Vector2 BackgroundPosition;
|
||||
|
||||
public Vector2 TitlePosition;
|
||||
|
||||
private object loadMutex = new object();
|
||||
private readonly object loadMutex = new object();
|
||||
private float? loadState;
|
||||
|
||||
public float? LoadState
|
||||
@@ -109,15 +107,13 @@ namespace Barotrauma
|
||||
|
||||
public LoadingScreen(GraphicsDevice graphics)
|
||||
{
|
||||
backgroundTexture = TextureLoader.FromFile("Content/UI/titleBackground.png");
|
||||
defaultBackgroundTexture = TextureLoader.FromFile("Content/Map/LocationPortraits/AlienRuins.png");
|
||||
|
||||
renderTarget = new RenderTarget2D(graphics, GameMain.GraphicsWidth, GameMain.GraphicsHeight);
|
||||
GameMain.Instance.OnResolutionChanged += () =>
|
||||
{
|
||||
renderTarget?.Dispose();
|
||||
renderTarget = new RenderTarget2D(graphics, GameMain.GraphicsWidth, GameMain.GraphicsHeight);
|
||||
};
|
||||
decorativeMap = new SpriteSheet("Content/Map/MapHUD.png", 6, 5, Vector2.Zero, sourceRect: new Rectangle(0, 0, 2048, 640));
|
||||
decorativeGraph = new SpriteSheet("Content/Map/MapHUD.png", 4, 10, Vector2.Zero, sourceRect: new Rectangle(1025, 1259, 1024, 732));
|
||||
|
||||
overlay = TextureLoader.FromFile("Content/UI/LoadingScreenOverlay.png");
|
||||
noiseSprite = new Sprite("Content/UI/noise.png", Vector2.Zero);
|
||||
DrawLoadingText = true;
|
||||
selectedTip = TextManager.Get("LoadingScreenTip", true);
|
||||
}
|
||||
@@ -147,41 +143,35 @@ namespace Barotrauma
|
||||
|
||||
drawn = true;
|
||||
|
||||
graphics.SetRenderTarget(renderTarget);
|
||||
|
||||
float backgroundScale = GameMain.GraphicsHeight / 1500.0f;
|
||||
float titleScale = MathHelper.SmoothStep(0.8f, 1.0f, state / 10.0f) * GameMain.GraphicsHeight / 1000.0f;
|
||||
|
||||
state += deltaTime;
|
||||
|
||||
if (DrawLoadingText)
|
||||
{
|
||||
BackgroundPosition = new Vector2(GameMain.GraphicsWidth * 0.3f, GameMain.GraphicsHeight * 0.45f);
|
||||
TitlePosition = new Vector2(GameMain.GraphicsWidth * 0.5f, GameMain.GraphicsHeight * 0.45f);
|
||||
}
|
||||
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, samplerState: GUI.SamplerState);
|
||||
graphics.Clear(Color.Black);
|
||||
|
||||
spriteBatch.Draw(backgroundTexture, BackgroundPosition, null, Color.White * Math.Min(state / 5.0f, 1.0f), 0.0f,
|
||||
new Vector2(backgroundTexture.Width / 2.0f, backgroundTexture.Height / 2.0f),
|
||||
backgroundScale * 1.5f, SpriteEffects.None, 0.2f);
|
||||
|
||||
titleSprite?.Draw(spriteBatch, TitlePosition, Color.White * Math.Min((state - 1.0f) / 5.0f, 1.0f), scale: titleScale);
|
||||
|
||||
spriteBatch.End();
|
||||
|
||||
graphics.SetRenderTarget(null);
|
||||
|
||||
if (WaterRenderer.Instance != null)
|
||||
{
|
||||
WaterRenderer.Instance.ScrollWater(Vector2.One * 10.0f, deltaTime);
|
||||
WaterRenderer.Instance.RenderWater(spriteBatch, renderTarget, null);
|
||||
}
|
||||
currentBackgroundTexture ??= defaultBackgroundTexture;
|
||||
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, samplerState: GUI.SamplerState);
|
||||
|
||||
titleSprite?.Draw(spriteBatch, TitlePosition, Color.White * Math.Min((state - 1.0f) / 5.0f, 1.0f), scale: titleScale);
|
||||
float scale = (GameMain.GraphicsWidth / (float)currentBackgroundTexture.Width) * 1.2f;
|
||||
float paddingX = currentBackgroundTexture.Width * scale - GameMain.GraphicsWidth;
|
||||
float paddingY = currentBackgroundTexture.Height * scale - GameMain.GraphicsHeight;
|
||||
|
||||
double noiseT = (Timing.TotalTime * 0.02f);
|
||||
Vector2 pos = new Vector2((float)PerlinNoise.CalculatePerlin(noiseT, noiseT, 0) - 0.5f, (float)PerlinNoise.CalculatePerlin(noiseT, noiseT, 0.5f) - 0.5f);
|
||||
pos = new Vector2(pos.X * paddingX, pos.Y * paddingY);
|
||||
|
||||
spriteBatch.Draw(currentBackgroundTexture,
|
||||
new Vector2(GameMain.GraphicsWidth, GameMain.GraphicsHeight) / 2 + pos,
|
||||
null, Color.White, 0.0f, new Vector2(currentBackgroundTexture.Width / 2, currentBackgroundTexture.Height / 2),
|
||||
scale, SpriteEffects.None, 0.0f);
|
||||
|
||||
spriteBatch.Draw(overlay, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), null, Color.White, 0.0f, Vector2.Zero, SpriteEffects.None, 0.0f);
|
||||
|
||||
float noiseStrength = (float)PerlinNoise.CalculatePerlin(noiseT, noiseT, 0);
|
||||
float noiseScale = (float)PerlinNoise.CalculatePerlin(noiseT * 5.0f, noiseT * 2.0f, 0) * 4.0f;
|
||||
noiseSprite.DrawTiled(spriteBatch, Vector2.Zero, new Vector2(GameMain.GraphicsWidth, GameMain.GraphicsHeight),
|
||||
startOffset: new Point(Rand.Range(0, noiseSprite.SourceRect.Width), Rand.Range(0, noiseSprite.SourceRect.Height)),
|
||||
color: Color.White * noiseStrength * 0.1f,
|
||||
textureScale: Vector2.One * noiseScale);
|
||||
|
||||
titleSprite?.Draw(spriteBatch, new Vector2(GameMain.GraphicsWidth * 0.05f, GameMain.GraphicsHeight * 0.125f),
|
||||
Color.White, origin: new Vector2(0.0f, titleSprite.SourceRect.Height / 2.0f),
|
||||
scale: GameMain.GraphicsHeight / 2000.0f);
|
||||
|
||||
if (WaitForLanguageSelection)
|
||||
{
|
||||
@@ -218,7 +208,7 @@ namespace Barotrauma
|
||||
if (GUI.LargeFont != null)
|
||||
{
|
||||
GUI.LargeFont.DrawString(spriteBatch, loadText.ToUpper(),
|
||||
new Vector2(GameMain.GraphicsWidth / 2.0f - GUI.LargeFont.MeasureString(loadText).X / 2.0f, GameMain.GraphicsHeight * 0.7f),
|
||||
new Vector2(GameMain.GraphicsWidth / 2.0f - GUI.LargeFont.MeasureString(loadText.ToUpper()).X / 2.0f, GameMain.GraphicsHeight * 0.75f),
|
||||
Color.White);
|
||||
}
|
||||
}
|
||||
@@ -232,12 +222,49 @@ namespace Barotrauma
|
||||
for (int i = 0; i < lines.Length; i++)
|
||||
{
|
||||
GUI.Font.DrawString(spriteBatch, lines[i],
|
||||
new Vector2((int)(GameMain.GraphicsWidth / 2.0f - GUI.Font.MeasureString(lines[i]).X / 2.0f), (int)(GameMain.GraphicsHeight * 0.78f + i * lineHeight)), Color.White);
|
||||
new Vector2((int)(GameMain.GraphicsWidth / 2.0f - GUI.Font.MeasureString(lines[i]).X / 2.0f), (int)(GameMain.GraphicsHeight * 0.8f + i * lineHeight)), Color.White);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
spriteBatch.End();
|
||||
|
||||
spriteBatch.Begin(blendState: BlendState.Additive);
|
||||
|
||||
Vector2 decorativeScale = new Vector2(GameMain.GraphicsHeight / 1080.0f);
|
||||
|
||||
float noiseVal = (float)PerlinNoise.CalculatePerlin(Timing.TotalTime * 0.25f, Timing.TotalTime * 0.5f, 0);
|
||||
decorativeGraph.Draw(spriteBatch, (int)(decorativeGraph.FrameCount * noiseVal),
|
||||
new Vector2(GameMain.GraphicsWidth * 0.001f, GameMain.GraphicsHeight * 0.24f),
|
||||
Color.White, Vector2.Zero, 0.0f, decorativeScale, SpriteEffects.FlipVertically);
|
||||
|
||||
decorativeMap.Draw(spriteBatch, (int)(decorativeMap.FrameCount * noiseVal),
|
||||
new Vector2(GameMain.GraphicsWidth * 0.99f, GameMain.GraphicsHeight * 0.66f),
|
||||
Color.White, decorativeMap.FrameSize.ToVector2(), 0.0f, decorativeScale);
|
||||
|
||||
if (noiseVal < 0.2f)
|
||||
{
|
||||
//SCP-CB reference
|
||||
randText = (new string[] { "NIL", "black white gray", "Sometimes we would have had time to scream", "e8m106]af", "NO" }).GetRandom();
|
||||
}
|
||||
else if (noiseVal < 0.3f)
|
||||
{
|
||||
randText = ToolBox.RandomSeed(9);
|
||||
}
|
||||
else if (noiseVal < 0.5f)
|
||||
{
|
||||
randText =
|
||||
Rand.Int(100).ToString().PadLeft(2, '0') + " " +
|
||||
Rand.Int(100).ToString().PadLeft(2, '0') + " " +
|
||||
Rand.Int(100).ToString().PadLeft(2, '0') + " " +
|
||||
Rand.Int(100).ToString().PadLeft(2, '0');
|
||||
}
|
||||
|
||||
GUI.LargeFont?.DrawString(spriteBatch, randText,
|
||||
new Vector2(GameMain.GraphicsWidth - decorativeMap.FrameSize.X * decorativeScale.X * 0.8f, GameMain.GraphicsHeight * 0.57f),
|
||||
Color.White * (1.0f - noiseVal));
|
||||
|
||||
spriteBatch.End();
|
||||
}
|
||||
|
||||
private void DrawLanguageSelectionPrompt(SpriteBatch spriteBatch, GraphicsDevice graphicsDevice)
|
||||
@@ -336,6 +363,7 @@ namespace Barotrauma
|
||||
drawn = false;
|
||||
LoadState = null;
|
||||
selectedTip = TextManager.Get("LoadingScreenTip", true);
|
||||
currentBackgroundTexture = LocationType.List.GetRandom()?.GetPortrait(Rand.Int(int.MaxValue))?.Texture;
|
||||
|
||||
while (!drawn)
|
||||
{
|
||||
|
||||
@@ -701,8 +701,16 @@ namespace Barotrauma
|
||||
|
||||
public void MatchPivotToAnchor() => MatchPivotToAnchor(Anchor);
|
||||
|
||||
|
||||
private Point? animTargetPos;
|
||||
public Point AnimTargetPos
|
||||
{
|
||||
get { return animTargetPos ?? AbsoluteOffset; }
|
||||
}
|
||||
|
||||
public void MoveOverTime(Point targetPos, float duration)
|
||||
{
|
||||
animTargetPos = targetPos;
|
||||
CoroutineManager.StartCoroutine(DoMoveAnimation(targetPos, duration));
|
||||
}
|
||||
public void ScaleOverTime(Point targetSize, float duration)
|
||||
@@ -721,6 +729,7 @@ namespace Barotrauma
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
AbsoluteOffset = targetPos;
|
||||
animTargetPos = null;
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
private IEnumerable<object> DoScaleAnimation(Point targetSize, float duration)
|
||||
|
||||
@@ -37,6 +37,12 @@ namespace Barotrauma
|
||||
private set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// How much the borders of a sliced sprite are allowed to scale
|
||||
/// You may for example want to prevent a 1-pixel border from scaling down (and disappearing) on small resolutions
|
||||
/// </summary>
|
||||
private float minBorderScale = 0.1f, maxBorderScale = 10.0f;
|
||||
|
||||
public bool CrossFadeIn { get; private set; } = true;
|
||||
public bool CrossFadeOut { get; private set; } = true;
|
||||
|
||||
@@ -58,6 +64,9 @@ namespace Barotrauma
|
||||
Vector4 sliceVec = element.GetAttributeVector4("slice", Vector4.Zero);
|
||||
if (sliceVec != Vector4.Zero)
|
||||
{
|
||||
minBorderScale = element.GetAttributeFloat("minborderscale", 0.1f);
|
||||
maxBorderScale = element.GetAttributeFloat("minborderscale", 10.0f);
|
||||
|
||||
Rectangle slice = new Rectangle((int)sliceVec.X, (int)sliceVec.Y, (int)(sliceVec.Z - sliceVec.X), (int)(sliceVec.W - sliceVec.Y));
|
||||
|
||||
Slice = true;
|
||||
@@ -103,7 +112,8 @@ namespace Barotrauma
|
||||
scale.Y = MathHelper.Clamp((float)rect.Height / (Slices[0].Height + Slices[6].Height), 0, 1);
|
||||
scale.X = MathHelper.Clamp((float)rect.Width / (Slices[0].Width + Slices[2].Width), 0, 1);
|
||||
|
||||
scale.X = scale.Y = Math.Min(Math.Min(scale.X, scale.Y), GUI.SlicedSpriteScale);
|
||||
scale.X = scale.Y =
|
||||
MathHelper.Clamp(Math.Min(Math.Min(scale.X, scale.Y), GUI.SlicedSpriteScale), minBorderScale, maxBorderScale);
|
||||
int centerHeight = rect.Height - (int)((Slices[0].Height + Slices[6].Height) * scale.Y);
|
||||
int centerWidth = rect.Width - (int)((Slices[0].Width + Slices[2].Width) * scale.X);
|
||||
|
||||
|
||||
@@ -764,60 +764,6 @@ namespace Barotrauma
|
||||
|
||||
SoundPlayer.Update((float)Timing.Step);
|
||||
|
||||
if (PlayerInput.KeyHit(Keys.Escape) && WindowActive)
|
||||
{
|
||||
// Check if a text input is selected.
|
||||
if (GUI.KeyboardDispatcher.Subscriber != null)
|
||||
{
|
||||
if (GUI.KeyboardDispatcher.Subscriber is GUITextBox textBox)
|
||||
{
|
||||
textBox.Deselect();
|
||||
}
|
||||
GUI.KeyboardDispatcher.Subscriber = null;
|
||||
}
|
||||
//if a verification prompt (are you sure you want to x) is open, close it
|
||||
else if (GUIMessageBox.VisibleBox as GUIMessageBox != null &&
|
||||
GUIMessageBox.VisibleBox.UserData as string == "verificationprompt")
|
||||
{
|
||||
((GUIMessageBox)GUIMessageBox.VisibleBox).Close();
|
||||
}
|
||||
else if (Tutorial.Initialized && Tutorial.ContentRunning)
|
||||
{
|
||||
(GameSession.GameMode as TutorialMode).Tutorial.CloseActiveContentGUI();
|
||||
}
|
||||
else if (GUI.PauseMenuOpen)
|
||||
{
|
||||
GUI.TogglePauseMenu();
|
||||
}
|
||||
//open the pause menu if not controlling a character OR if the character has no UIs active that can be closed with ESC
|
||||
else if ((Character.Controlled == null || !itemHudActive())
|
||||
//TODO: do we need to check Inventory.SelectedSlot?
|
||||
&& Inventory.SelectedSlot == null && CharacterHealth.OpenHealthWindow == null
|
||||
&& !CrewManager.IsCommandInterfaceOpen)
|
||||
{
|
||||
// Otherwise toggle pausing, unless another window/interface is open.
|
||||
GUI.TogglePauseMenu();
|
||||
}
|
||||
|
||||
bool itemHudActive()
|
||||
{
|
||||
if (Character.Controlled?.SelectedConstruction == null) { return false; }
|
||||
return
|
||||
Character.Controlled.SelectedConstruction.ActiveHUDs.Any(ic => ic.GuiFrame != null) ||
|
||||
((Character.Controlled.ViewTarget as Item)?.Prefab?.FocusOnSelected ?? false);
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
if (GameMain.NetworkMember == null)
|
||||
{
|
||||
if (PlayerInput.KeyHit(Keys.P) && !(GUI.KeyboardDispatcher.Subscriber is GUITextBox))
|
||||
{
|
||||
DebugConsole.Paused = !DebugConsole.Paused;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
GUI.ClearUpdateList();
|
||||
Paused = (DebugConsole.IsOpen || GUI.PauseMenuOpen || GUI.SettingsMenuOpen || Tutorial.ContentRunning || DebugConsole.Paused) &&
|
||||
(NetworkMember == null || !NetworkMember.GameStarted);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -560,7 +560,7 @@ namespace Barotrauma
|
||||
}
|
||||
};
|
||||
|
||||
GUITextBlock particleLimitText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform), TextManager.Get("ParticleLimit"), font: GUI.SubHeadingFont);
|
||||
GUITextBlock particleLimitText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform), TextManager.Get("ParticleLimit"), font: GUI.SubHeadingFont, wrap: true);
|
||||
GUIScrollBar particleScrollBar = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform), style: "GUISlider",
|
||||
barSize: 0.1f)
|
||||
{
|
||||
@@ -576,7 +576,7 @@ namespace Barotrauma
|
||||
};
|
||||
particleScrollBar.OnMoved(particleScrollBar, particleScrollBar.BarScroll);
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform), TextManager.Get("LosEffect"), font: GUI.SubHeadingFont);
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform), TextManager.Get("LosEffect"), font: GUI.SubHeadingFont, wrap: true);
|
||||
var losModeDD = new GUIDropDown(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform));
|
||||
losModeDD.AddItem(TextManager.Get("LosModeNone"), LosMode.None);
|
||||
losModeDD.AddItem(TextManager.Get("LosModeTransparent"), LosMode.Transparent);
|
||||
@@ -594,7 +594,7 @@ namespace Barotrauma
|
||||
return true;
|
||||
};
|
||||
|
||||
GUITextBlock LightText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform), TextManager.Get("LightMapScale"), font: GUI.SubHeadingFont)
|
||||
GUITextBlock LightText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform), TextManager.Get("LightMapScale"), font: GUI.SubHeadingFont, wrap: true)
|
||||
{
|
||||
ToolTip = TextManager.Get("LightMapScaleToolTip")
|
||||
};
|
||||
@@ -638,7 +638,7 @@ namespace Barotrauma
|
||||
}
|
||||
};
|
||||
|
||||
GUITextBlock HUDScaleText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform), TextManager.Get("HUDScale"), font: GUI.SubHeadingFont);
|
||||
GUITextBlock HUDScaleText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform), TextManager.Get("HUDScale"), font: GUI.SubHeadingFont, wrap: true);
|
||||
GUIScrollBar HUDScaleScrollBar = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform),
|
||||
style: "GUISlider", barSize: 0.1f)
|
||||
{
|
||||
|
||||
@@ -11,7 +11,7 @@ using System.Xml.Linq;
|
||||
namespace Barotrauma
|
||||
{
|
||||
partial class CharacterInventory : Inventory
|
||||
{
|
||||
{
|
||||
public enum Layout
|
||||
{
|
||||
Default,
|
||||
@@ -35,13 +35,18 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
private static Dictionary<InvSlotType, Sprite> limbSlotIcons;
|
||||
|
||||
private static Sprite inventoryBackgroundSprite, inventoryExtendButton, inventoryExtendUpArrow, inventoryExtendDownArrow;
|
||||
|
||||
public Rectangle InventoryToggleArea;
|
||||
public bool InventoryToggleContains = false;
|
||||
private Vector2 inventoryExtendButtonOffset, inventoryArrowOffset;
|
||||
private int inventoryOpeningOffset;
|
||||
|
||||
public const InvSlotType PersonalSlots = InvSlotType.Card | InvSlotType.Headset | InvSlotType.InnerClothes | InvSlotType.OuterClothes | InvSlotType.Head;
|
||||
|
||||
private Point screenResolution;
|
||||
|
||||
public Vector2[] SlotPositions;
|
||||
|
||||
private Vector2 bgScale;
|
||||
|
||||
private Layout layout;
|
||||
public Layout CurrentLayout
|
||||
{
|
||||
@@ -50,7 +55,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (layout == value) return;
|
||||
layout = value;
|
||||
SetSlotPositions(layout);
|
||||
SetSlotPositions();
|
||||
}
|
||||
}
|
||||
public bool Hidden { get; set; }
|
||||
@@ -59,6 +64,8 @@ namespace Barotrauma
|
||||
private float hidePersonalSlotsState;
|
||||
private GUIButton hideButton;
|
||||
private Rectangle personalSlotArea;
|
||||
private bool inventoryOpen = false;
|
||||
private bool wasInventoryToggledAutomatically = false;
|
||||
|
||||
public bool HidePersonalSlots
|
||||
{
|
||||
@@ -103,10 +110,17 @@ namespace Barotrauma
|
||||
limbSlotIcons.Add(InvSlotType.LeftHand, new Sprite("Content/UI/InventoryUIAtlas.png", new Rectangle(634, 0, 128, 128)));
|
||||
limbSlotIcons.Add(InvSlotType.RightHand, new Sprite("Content/UI/InventoryUIAtlas.png", new Rectangle(762, 0, 128, 128)));
|
||||
limbSlotIcons.Add(InvSlotType.OuterClothes, new Sprite("Content/UI/MainIconsAtlas.png", new Rectangle(256 + margin, 128 + margin, 128 - margin * 2, 128 - margin * 2)));
|
||||
|
||||
inventoryBackgroundSprite = new Sprite("Content/UI/InventoryUIAtlas.png", new Rectangle(252, 317, 263, 197));
|
||||
inventoryExtendButton = new Sprite("Content/UI/InventoryUIAtlas.png", new Rectangle(533, 300, 96, 19));
|
||||
inventoryExtendUpArrow = new Sprite("Content/UI/InventoryUIAtlas.png", new Rectangle(640, 310, 10, 10));
|
||||
inventoryExtendDownArrow = new Sprite("Content/UI/InventoryUIAtlas.png", new Rectangle(668, 310, 10, 10));
|
||||
}
|
||||
|
||||
SlotPositions = new Vector2[SlotTypes.Length];
|
||||
CurrentLayout = Layout.Default;
|
||||
SetSlotPositions(layout);
|
||||
SetSlotPositions();
|
||||
GameMain.Instance.OnResolutionChanged += SetSlotPositions;
|
||||
}
|
||||
|
||||
protected override ItemInventory GetActiveEquippedSubInventory(int slotIndex)
|
||||
@@ -193,31 +207,54 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
screenResolution = new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight);
|
||||
CalculateBackgroundFrame();
|
||||
}
|
||||
|
||||
protected override void CalculateBackgroundFrame()
|
||||
{
|
||||
Rectangle frame = Rectangle.Empty;
|
||||
int firstSlotLocationY = 0;
|
||||
int lastSlotLocationY = 0;
|
||||
|
||||
for (int i = 0; i < capacity; i++)
|
||||
{
|
||||
if (HideSlot(i)) continue;
|
||||
if (PersonalSlots.HasFlag(SlotTypes[i])) continue;
|
||||
if (IsHandSlot(SlotTypes[i])) continue;
|
||||
if (frame == Rectangle.Empty)
|
||||
{
|
||||
firstSlotLocationY = slots[i].Rect.Location.Y;
|
||||
frame = slots[i].Rect;
|
||||
continue;
|
||||
}
|
||||
frame = Rectangle.Union(frame, slots[i].Rect);
|
||||
lastSlotLocationY = slots[i].Rect.Location.Y;
|
||||
}
|
||||
frame.Inflate(10, 30);
|
||||
frame.Location -= new Point(0, 25);
|
||||
|
||||
frame.Inflate(25f * UIScale, 25f * UIScale);
|
||||
|
||||
if (layout == Layout.Default)
|
||||
{
|
||||
inventoryOpeningOffset = firstSlotLocationY - lastSlotLocationY;
|
||||
|
||||
bgScale = new Vector2((float)frame.Width / (float)inventoryBackgroundSprite.SourceRect.Width, (float)frame.Height / (float)inventoryBackgroundSprite.SourceRect.Height);
|
||||
|
||||
inventoryExtendButtonOffset = new Vector2(inventoryExtendButton.size.X * UIScale * 1.5f / 2f, inventoryExtendButton.size.Y * UIScale * 1.5f / 2f + UIScale * 6);
|
||||
inventoryArrowOffset = new Vector2(inventoryExtendUpArrow.size.X * UIScale * 1.25f / 2f, inventoryExtendUpArrow.size.Y * UIScale * 1.25f / 2f);
|
||||
InventoryToggleArea = new Rectangle(new Point(frame.Center.X, frame.Top) - inventoryExtendButtonOffset.ToPoint(), inventoryExtendButton.size.ToPoint() + new Point(0, (int)(UIScale * 6f)));
|
||||
if (!inventoryOpen)
|
||||
{
|
||||
frame.Offset(0, inventoryOpeningOffset);
|
||||
InventoryToggleArea.Offset(0, inventoryOpeningOffset);
|
||||
}
|
||||
}
|
||||
|
||||
BackgroundFrame = frame;
|
||||
}
|
||||
|
||||
protected override bool HideSlot(int i)
|
||||
{
|
||||
if (slots[i].Disabled || (hideEmptySlot[i] && Items[i] == null)) return true;
|
||||
if (slots[i].Disabled) return true;
|
||||
|
||||
if (layout == Layout.Default)
|
||||
{
|
||||
@@ -230,19 +267,17 @@ namespace Barotrauma
|
||||
return true;
|
||||
}
|
||||
|
||||
//don't show the equip slot if the item is also in the default inventory
|
||||
if (SlotTypes[i] != InvSlotType.Any && Items[i] != null)
|
||||
{
|
||||
for (int j = 0; j < capacity; j++)
|
||||
{
|
||||
if (SlotTypes[j] == InvSlotType.Any && Items[j] == Items[i]) return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
private void SetSlotPositions(Layout layout)
|
||||
|
||||
protected override bool IsSlotHiddenDueToToggleState(int i)
|
||||
{
|
||||
return layout == Layout.Default && !inventoryOpen && slots[i].QuickUseKey == Keys.None && SlotTypes[i] == InvSlotType.Any;
|
||||
}
|
||||
|
||||
private void SetSlotPositions()
|
||||
{
|
||||
Layout layout = CurrentLayout;
|
||||
int spacing = (int)(10 * UIScale);
|
||||
Point slotSize = (SlotSpriteSmall.size * UIScale).ToPoint();
|
||||
int bottomOffset = slotSize.Y + spacing * 2 + ContainedIndicatorHeight;
|
||||
@@ -258,27 +293,47 @@ namespace Barotrauma
|
||||
int personalSlotCount = SlotTypes.Count(s => PersonalSlots.HasFlag(s));
|
||||
int normalSlotCount = SlotTypes.Count(s => !PersonalSlots.HasFlag(s));
|
||||
|
||||
int x = GameMain.GraphicsWidth / 2 - normalSlotCount * (slotSize.X + spacing) / 2;
|
||||
int upperX = GameMain.GraphicsWidth - slotSize.X * 2;
|
||||
int firstRowSlotCount = hotkeyCount > normalSlotCount ? normalSlotCount : hotkeyCount;
|
||||
|
||||
int startX = GameMain.GraphicsWidth / 2 - firstRowSlotCount * (slotSize.X + spacing) / 2;
|
||||
int x = startX;
|
||||
int equipmentX = GameMain.GraphicsWidth - slotSize.X * 2;
|
||||
int buttonIndex = 0;
|
||||
int startY = GameMain.GraphicsHeight - bottomOffset;
|
||||
int y = startY;
|
||||
int handIndex = 1;
|
||||
|
||||
//make sure the rightmost normal slot doesn't overlap with the personal slots
|
||||
x -= Math.Max((x + normalSlotCount * (slotSize.X + spacing)) - (upperX - personalSlotCount * (slotSize.X + spacing)), 0);
|
||||
x -= Math.Max(x + firstRowSlotCount * (slotSize.X + spacing) - (equipmentX - personalSlotCount * (slotSize.X + spacing)), 0);
|
||||
|
||||
int hideButtonSlotIndex = -1;
|
||||
for (int i = 0; i < SlotPositions.Length; i++)
|
||||
{
|
||||
if (PersonalSlots.HasFlag(SlotTypes[i]))
|
||||
{
|
||||
SlotPositions[i] = new Vector2(upperX, GameMain.GraphicsHeight - bottomOffset);
|
||||
upperX -= slotSize.X + spacing;
|
||||
SlotPositions[i] = new Vector2(equipmentX, startY);
|
||||
equipmentX -= slotSize.X + spacing;
|
||||
personalSlotArea = (hideButtonSlotIndex == -1) ?
|
||||
new Rectangle(SlotPositions[i].ToPoint(), slotSize) :
|
||||
Rectangle.Union(personalSlotArea, new Rectangle(SlotPositions[i].ToPoint(), slotSize));
|
||||
hideButtonSlotIndex = i;
|
||||
}
|
||||
else if (IsHandSlot(SlotTypes[i]))
|
||||
{
|
||||
SlotPositions[i] = new Vector2(startX - (slotSize.X + spacing * 4) - (slotSize.X + spacing) * handIndex, startY);
|
||||
handIndex--;
|
||||
}
|
||||
else
|
||||
{
|
||||
SlotPositions[i] = new Vector2(x, GameMain.GraphicsHeight - bottomOffset);
|
||||
if (buttonIndex >= hotkeyCount)
|
||||
{
|
||||
y -= bottomOffset;
|
||||
buttonIndex = 0;
|
||||
x = startX;
|
||||
}
|
||||
|
||||
buttonIndex++;
|
||||
SlotPositions[i] = new Vector2(x, y);
|
||||
x += slotSize.X + spacing;
|
||||
}
|
||||
}
|
||||
@@ -296,7 +351,6 @@ namespace Barotrauma
|
||||
break;
|
||||
case Layout.Right:
|
||||
{
|
||||
int extraOffset = 0;
|
||||
int x = HUDLayoutSettings.InventoryAreaLower.Right;
|
||||
int personalSlotX = HUDLayoutSettings.InventoryAreaLower.Right - slotSize.X - spacing;
|
||||
for (int i = 0; i < slots.Length; i++)
|
||||
@@ -307,24 +361,35 @@ namespace Barotrauma
|
||||
//upperX -= slotSize.X + spacing;
|
||||
}
|
||||
else
|
||||
{
|
||||
x -= slotSize.X + spacing;
|
||||
{
|
||||
if (i < slots.Length - 5)
|
||||
{
|
||||
x -= slotSize.X + spacing;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int lowerX = x;
|
||||
int y = GameMain.GraphicsHeight - bottomOffset;
|
||||
|
||||
for (int i = 0; i < SlotPositions.Length; i++)
|
||||
{
|
||||
if (HideSlot(i)) continue;
|
||||
if (PersonalSlots.HasFlag(SlotTypes[i]))
|
||||
{
|
||||
SlotPositions[i] = new Vector2(personalSlotX, GameMain.GraphicsHeight - bottomOffset * 2 - extraOffset - spacing * 2);
|
||||
SlotPositions[i] = new Vector2(personalSlotX, y - bottomOffset);
|
||||
personalSlotX -= slots[i].Rect.Width + spacing;
|
||||
}
|
||||
else
|
||||
{
|
||||
SlotPositions[i] = new Vector2(x, GameMain.GraphicsHeight - bottomOffset - extraOffset);
|
||||
SlotPositions[i] = new Vector2(x, y);
|
||||
x += slots[i].Rect.Width + spacing;
|
||||
|
||||
if (i == SlotPositions.Length - 6)
|
||||
{
|
||||
x = lowerX + (slots[i].Rect.Width + spacing) * 2;
|
||||
y -= bottomOffset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -333,28 +398,37 @@ namespace Barotrauma
|
||||
{
|
||||
if (!HideSlot(i)) continue;
|
||||
x -= slots[i].Rect.Width + spacing;
|
||||
SlotPositions[i] = new Vector2(x, GameMain.GraphicsHeight - bottomOffset - extraOffset);
|
||||
SlotPositions[i] = new Vector2(x, y);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Layout.Left:
|
||||
{
|
||||
int x = HUDLayoutSettings.InventoryAreaLower.X;
|
||||
int x = HUDLayoutSettings.InventoryAreaLower.Left;
|
||||
int y = GameMain.GraphicsHeight - bottomOffset;
|
||||
int personalSlotX = x;
|
||||
|
||||
for (int i = 0; i < SlotPositions.Length; i++)
|
||||
{
|
||||
if (HideSlot(i)) continue;
|
||||
if (PersonalSlots.HasFlag(SlotTypes[i]))
|
||||
{
|
||||
SlotPositions[i] = new Vector2(personalSlotX, GameMain.GraphicsHeight - bottomOffset * 2 - spacing * 2);
|
||||
SlotPositions[i] = new Vector2(personalSlotX, y - bottomOffset);
|
||||
personalSlotX += slots[i].Rect.Width + spacing;
|
||||
}
|
||||
else
|
||||
{
|
||||
SlotPositions[i] = new Vector2(x, GameMain.GraphicsHeight - bottomOffset);
|
||||
SlotPositions[i] = new Vector2(x, y);
|
||||
x += slots[i].Rect.Width + spacing;
|
||||
|
||||
if (i == SlotPositions.Length - 7)
|
||||
{
|
||||
x -= (slots[i].Rect.Width + spacing) * 6;
|
||||
y -= bottomOffset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < SlotPositions.Length; i++)
|
||||
{
|
||||
if (!HideSlot(i)) continue;
|
||||
@@ -406,7 +480,11 @@ namespace Barotrauma
|
||||
{
|
||||
HUDLayoutSettings.InventoryTopY = slots[0].EquipButtonRect.Y - (int)(15 * GUI.Scale);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private bool IsHandSlot(InvSlotType slotType)
|
||||
{
|
||||
return slotType == InvSlotType.LeftHand || slotType == InvSlotType.RightHand;
|
||||
}
|
||||
|
||||
protected override void ControlInput(Camera cam)
|
||||
@@ -419,6 +497,32 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public void ToggleInventory(bool automaticToggle = false)
|
||||
{
|
||||
if (Character.Controlled == null || !Character.Controlled.IsHuman || wasInventoryToggledAutomatically || inventoryOpen && automaticToggle) return;
|
||||
inventoryOpen = !inventoryOpen;
|
||||
if (inventoryOpen)
|
||||
{
|
||||
wasInventoryToggledAutomatically = automaticToggle;
|
||||
BackgroundFrame.Offset(0, -inventoryOpeningOffset);
|
||||
InventoryToggleArea.Offset(0, -inventoryOpeningOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
BackgroundFrame.Offset(0, inventoryOpeningOffset);
|
||||
InventoryToggleArea.Offset(0, inventoryOpeningOffset);
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleAutomaticInventoryState()
|
||||
{
|
||||
if (wasInventoryToggledAutomatically && inventoryOpen && Character.Controlled.SelectedConstruction == null && Character.Controlled.SelectedCharacter == null)
|
||||
{
|
||||
wasInventoryToggledAutomatically = false;
|
||||
ToggleInventory();
|
||||
}
|
||||
}
|
||||
|
||||
public override void Update(float deltaTime, Camera cam, bool isSubInventory = false)
|
||||
{
|
||||
if (!AccessibleWhenAlive && !character.IsDead)
|
||||
@@ -427,6 +531,8 @@ namespace Barotrauma
|
||||
return;
|
||||
}
|
||||
|
||||
HandleAutomaticInventoryState();
|
||||
|
||||
base.Update(deltaTime, cam);
|
||||
|
||||
bool hoverOnInventory = GUI.MouseOn == null &&
|
||||
@@ -460,7 +566,7 @@ namespace Barotrauma
|
||||
for (int i = 0; i < capacity; i++)
|
||||
{
|
||||
if (Items[i] != null && Items[i] != draggingItem && Character.Controlled?.Inventory == this &&
|
||||
GUI.KeyboardDispatcher.Subscriber == null &&
|
||||
GUI.KeyboardDispatcher.Subscriber == null && !CrewManager.IsCommandInterfaceOpen &&
|
||||
slots[i].QuickUseKey != Keys.None && PlayerInput.KeyHit(slots[i].QuickUseKey))
|
||||
{
|
||||
QuickUseItem(Items[i], true, false, true);
|
||||
@@ -608,7 +714,10 @@ namespace Barotrauma
|
||||
|
||||
private void HandleButtonEquipStates(Item item, InventorySlot slot, float deltaTime)
|
||||
{
|
||||
slot.EquipButtonState = slot.EquipButtonRect.Contains(PlayerInput.MousePosition) ?
|
||||
Rectangle modifiedRect = slot.EquipButtonRect;
|
||||
modifiedRect.Width = slot.InteractRect.Width;
|
||||
|
||||
slot.EquipButtonState = modifiedRect.Contains(PlayerInput.MousePosition) ?
|
||||
GUIComponent.ComponentState.Hover : GUIComponent.ComponentState.None;
|
||||
if (PlayerInput.LeftButtonHeld() && PlayerInput.RightButtonHeld())
|
||||
{
|
||||
@@ -682,6 +791,8 @@ namespace Barotrauma
|
||||
continue;
|
||||
}
|
||||
|
||||
if (num > hotkeyCount) break;
|
||||
|
||||
if (SlotTypes[i] == InvSlotType.Any)
|
||||
{
|
||||
slots[i].QuickUseKey = Keys.D0 + num % 10;
|
||||
@@ -827,7 +938,7 @@ namespace Barotrauma
|
||||
if (character.SelectedCharacter != null && character.SelectedCharacter.Inventory != null)
|
||||
{
|
||||
//player has selected the inventory of another character -> attempt to move the item there
|
||||
success = character.SelectedCharacter.Inventory.TryPutItem(item, Character.Controlled, item.AllowedSlots, true);
|
||||
success = character.SelectedCharacter.Inventory.TryPutItem(item, Character.Controlled, item.AllowedSlots, true, true);
|
||||
}
|
||||
break;
|
||||
case QuickUseAction.PutToContainer:
|
||||
@@ -843,7 +954,7 @@ namespace Barotrauma
|
||||
character.SelectedBy.Inventory != null)
|
||||
{
|
||||
//item is in the inventory of another character -> attempt to get the item from there
|
||||
success = character.SelectedBy.Inventory.TryPutItemWithAutoEquipCheck(item, Character.Controlled, item.AllowedSlots, true);
|
||||
success = character.SelectedBy.Inventory.TryPutItemWithAutoEquipCheck(item, Character.Controlled, item.AllowedSlots, true, true);
|
||||
}
|
||||
break;
|
||||
case QuickUseAction.TakeFromContainer:
|
||||
@@ -862,7 +973,7 @@ namespace Barotrauma
|
||||
// No subinventory found or placing unsuccessful -> attempt to put in the character's inventory
|
||||
if (!success)
|
||||
{
|
||||
success = TryPutItemWithAutoEquipCheck(item, Character.Controlled, item.AllowedSlots, true);
|
||||
success = TryPutItemWithAutoEquipCheck(item, Character.Controlled, item.AllowedSlots, true, true);
|
||||
}
|
||||
break;
|
||||
case QuickUseAction.PutToEquippedItem:
|
||||
@@ -894,107 +1005,87 @@ namespace Barotrauma
|
||||
GUI.PlayUISound(success ? GUISoundType.PickItem : GUISoundType.PickItemFail);
|
||||
}
|
||||
|
||||
public void DrawOwn(SpriteBatch spriteBatch)
|
||||
public void DrawThis(SpriteBatch spriteBatch)
|
||||
{
|
||||
if (!AccessibleWhenAlive && !character.IsDead) return;
|
||||
if (slots == null) CreateSlots();
|
||||
if (GameMain.GraphicsWidth != screenResolution.X ||
|
||||
GameMain.GraphicsHeight != screenResolution.Y ||
|
||||
prevUIScale != UIScale ||
|
||||
prevHUDScale != GUI.Scale)
|
||||
{
|
||||
SetSlotPositions(layout);
|
||||
prevUIScale = UIScale;
|
||||
prevHUDScale = GUI.Scale;
|
||||
}
|
||||
|
||||
if (layout == Layout.Center)
|
||||
{
|
||||
CalculateBackgroundFrame();
|
||||
GUI.DrawRectangle(spriteBatch, BackgroundFrame, Color.Black * 0.8f, true);
|
||||
GUI.DrawString(spriteBatch,
|
||||
new Vector2((int)(BackgroundFrame.Center.X - GUI.Font.MeasureString(character.Name).X / 2), (int)BackgroundFrame.Y + 5),
|
||||
character.Name, Color.White * 0.9f);
|
||||
}
|
||||
|
||||
for (int i = 0; i < capacity; i++)
|
||||
{
|
||||
if (HideSlot(i)) continue;
|
||||
|
||||
Rectangle interactRect = slots[i].InteractRect;
|
||||
interactRect.Location += slots[i].DrawOffset.ToPoint();
|
||||
|
||||
//don't draw the item if it's being dragged out of the slot
|
||||
bool drawItem = draggingItem == null || draggingItem != Items[i] || interactRect.Contains(PlayerInput.MousePosition);
|
||||
DrawSlot(spriteBatch, this, slots[i], Items[i], i, drawItem, SlotTypes[i]);
|
||||
}
|
||||
|
||||
if (hideButton != null && hideButton.Visible && !Locked)
|
||||
{
|
||||
hideButton.DrawManually(spriteBatch, alsoChildren: true);
|
||||
}
|
||||
|
||||
if (layout == Layout.Default)
|
||||
{
|
||||
inventoryBackgroundSprite.Draw(spriteBatch, BackgroundFrame.Location.ToVector2(), Color.White, Vector2.Zero, rotate: 0, scale: bgScale);
|
||||
|
||||
Vector2 backgroundFrameCenter = new Vector2(BackgroundFrame.Center.X, BackgroundFrame.Top);
|
||||
inventoryExtendButton.Draw(spriteBatch, backgroundFrameCenter - inventoryExtendButtonOffset, Color.White, scale: UIScale * 1.5f);
|
||||
|
||||
Vector2 arrowPosition = backgroundFrameCenter - inventoryArrowOffset;
|
||||
if (inventoryOpen)
|
||||
{
|
||||
inventoryExtendDownArrow.Draw(spriteBatch, arrowPosition, Color.White, scale: UIScale * 1.25f);
|
||||
}
|
||||
else
|
||||
{
|
||||
inventoryExtendUpArrow.Draw(spriteBatch, arrowPosition, Color.White, scale: UIScale * 1.25f);
|
||||
}
|
||||
|
||||
GUI.DrawString(spriteBatch, arrowPosition + new Vector2(UIScale * 25, -3 * UIScale), GameMain.Config.KeyBindText(InputType.ToggleInventory), Color.White, font: GUI.HotkeyFont);
|
||||
|
||||
InventoryToggleContains = InventoryToggleArea.Contains(PlayerInput.MousePosition);
|
||||
if (InventoryToggleContains && PlayerInput.PrimaryMouseButtonClicked())
|
||||
{
|
||||
ToggleInventory();
|
||||
}
|
||||
}
|
||||
|
||||
InventorySlot highlightedQuickUseSlot = null;
|
||||
for (int i = 0; i < capacity; i++)
|
||||
{
|
||||
if (HideSlot(i)) continue;
|
||||
if (IsSlotHiddenDueToToggleState(i)) continue;
|
||||
|
||||
if (Items[i] == null ||
|
||||
(draggingItem == Items[i] && !slots[i].InteractRect.Contains(PlayerInput.MousePosition)) ||
|
||||
!Items[i].AllowedSlots.Any(a => a != InvSlotType.Any))
|
||||
InventorySlot slot = slots[i];
|
||||
|
||||
Item item = Items[i];
|
||||
InvSlotType slotType = SlotTypes[i];
|
||||
|
||||
Rectangle interactRect = slot.InteractRect;
|
||||
interactRect.Location += slot.DrawOffset.ToPoint();
|
||||
|
||||
//don't draw the item if it's being dragged out of the slot
|
||||
bool drawItem = draggingItem == null || draggingItem != item || interactRect.Contains(PlayerInput.MousePosition);
|
||||
DrawSlot(spriteBatch, this, slot, item, i, drawItem, slotType);
|
||||
|
||||
if (item == null || (draggingItem == item && !slot.InteractRect.Contains(PlayerInput.MousePosition)) || !item.AllowedSlots.Any(a => a != InvSlotType.Any))
|
||||
{
|
||||
//draw limb icons on empty slots
|
||||
if (limbSlotIcons.ContainsKey(SlotTypes[i]))
|
||||
if (limbSlotIcons.ContainsKey(slotType))
|
||||
{
|
||||
var icon = limbSlotIcons[SlotTypes[i]];
|
||||
icon.Draw(spriteBatch, slots[i].Rect.Center.ToVector2() + slots[i].DrawOffset, GUIColorSettings.EquipmentSlotIconColor, origin: icon.size / 2, scale: slots[i].Rect.Width / icon.size.X);
|
||||
var icon = limbSlotIcons[slotType];
|
||||
icon.Draw(spriteBatch, slot.Rect.Center.ToVector2() + slot.DrawOffset, GUIColorSettings.EquipmentSlotIconColor, origin: icon.size / 2, scale: slot.Rect.Width / icon.size.X);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (draggingItem == Items[i] && !slots[i].IsHighlighted) continue;
|
||||
|
||||
//draw hand icons if the item is equipped in a hand slot
|
||||
if (IsInLimbSlot(Items[i], InvSlotType.LeftHand))
|
||||
{
|
||||
var icon = limbSlotIcons[InvSlotType.LeftHand];
|
||||
icon.Draw(spriteBatch, new Vector2(slots[i].Rect.X, slots[i].Rect.Bottom) + slots[i].DrawOffset, Color.White * 0.6f, origin: new Vector2(icon.size.X * 0.35f, icon.size.Y * 0.75f), scale: slots[i].Rect.Width / icon.size.X * 0.7f);
|
||||
}
|
||||
if (IsInLimbSlot(Items[i], InvSlotType.RightHand))
|
||||
{
|
||||
var icon = limbSlotIcons[InvSlotType.RightHand];
|
||||
icon.Draw(spriteBatch, new Vector2(slots[i].Rect.Right, slots[i].Rect.Bottom) + slots[i].DrawOffset, Color.White * 0.6f, origin: new Vector2(icon.size.X * 0.65f, icon.size.Y * 0.75f), scale: slots[i].Rect.Width / icon.size.X * 0.7f);
|
||||
}
|
||||
|
||||
Color color = slots[i].EquipButtonState == GUIComponent.ComponentState.Pressed ? Color.Gray : Color.White * 0.8f;
|
||||
if (slots[i].EquipButtonState == GUIComponent.ComponentState.Hover)
|
||||
{
|
||||
color = Color.White;
|
||||
highlightedQuickUseSlot = slots[i];
|
||||
}
|
||||
if (Locked) { color *= 0.3f; }
|
||||
// Draw always on hotkeys
|
||||
if (slot.QuickUseKey != Keys.None)
|
||||
{
|
||||
DrawIndicatorAndHotkey(spriteBatch, slot, slot.EquipButtonState == GUIComponent.ComponentState.Hover);
|
||||
}
|
||||
|
||||
if (!Items[i].AllowedSlots.Any(a => a == InvSlotType.Any))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
EquipIndicator.Draw(spriteBatch, slots[i].EquipButtonRect.Center.ToVector2(), color, EquipIndicator.Origin, 0, UIScale);
|
||||
/*slots[i].QuickUseTimer = Math.Min(slots[i].QuickUseTimer, 1.0f);
|
||||
if (slots[i].QuickUseTimer > 0.0f)
|
||||
{
|
||||
float indicatorFillAmount = character.HasEquippedItem(Items[i]) ? 1.0f - slots[i].QuickUseTimer : slots[i].QuickUseTimer;
|
||||
quickUseHighlight.DrawTiled(spriteBatch,
|
||||
slots[i].EquipButtonRect.Center.ToVector2() - quickUseHighlight.Origin * UIScale * 0.85f,
|
||||
new Vector2(quickUseIndicator.SourceRect.Width * indicatorFillAmount, quickUseIndicator.SourceRect.Height) * UIScale * 0.85f,
|
||||
null,
|
||||
color * 0.9f,
|
||||
null,
|
||||
Vector2.One * UIScale * 0.85f);
|
||||
}
|
||||
else*/ if (character.HasEquippedItem(Items[i]))
|
||||
{
|
||||
EquipIndicatorHighlight.Draw(spriteBatch, slots[i].EquipButtonRect.Center.ToVector2(), color * 0.9f, EquipIndicatorHighlight.Origin, 0, UIScale * 0.85f);
|
||||
}
|
||||
if (draggingItem == item && !slot.IsHighlighted) continue;
|
||||
|
||||
bool hover = slot.EquipButtonState == GUIComponent.ComponentState.Hover;
|
||||
if (hover) highlightedQuickUseSlot = slot;
|
||||
|
||||
if (!item.AllowedSlots.Any(a => a == InvSlotType.Any)) continue;
|
||||
|
||||
DrawIndicatorAndHotkey(spriteBatch, slot, hover);
|
||||
|
||||
}
|
||||
|
||||
if (highlightedQuickUseSlot != null && !string.IsNullOrEmpty(highlightedQuickUseSlot.QuickUseButtonToolTip))
|
||||
@@ -1002,5 +1093,30 @@ namespace Barotrauma
|
||||
GUIComponent.DrawToolTip(spriteBatch, highlightedQuickUseSlot.QuickUseButtonToolTip, highlightedQuickUseSlot.EquipButtonRect);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawIndicatorAndHotkey(SpriteBatch spriteBatch, InventorySlot slot, bool hover)
|
||||
{
|
||||
|
||||
Color indicatorColor = (hover) ? Color.White : Color.White * 0.8f;
|
||||
|
||||
/*if (character.HasEquippedItem(item))
|
||||
{
|
||||
indicatorColor = hover ? GUIColorSettings.InventorySlotEquippedColor : GUIColorSettings.InventorySlotEquippedColor * 0.8f;
|
||||
}
|
||||
else
|
||||
{
|
||||
indicatorColor = hover ? GUIColorSettings.InventorySlotColor : GUIColorSettings.InventorySlotColor * 0.8f;
|
||||
}*/
|
||||
|
||||
if (Locked) indicatorColor *= 0.3f;
|
||||
|
||||
Rectangle equipRect = slot.EquipButtonRect;
|
||||
EquipIndicator.Draw(spriteBatch, new Vector2(equipRect.Center.X, equipRect.Bottom), indicatorColor, EquipIndicator.Origin, 0, UIScale * 0.6f);
|
||||
|
||||
if (slot.QuickUseKey != Keys.None)
|
||||
{
|
||||
GUI.DrawString(spriteBatch, new Vector2(slot.Rect.Center.X - 2, slot.Rect.Top), slot.QuickUseKey.ToString().Substring(1, 1), Color.Black, font: GUI.HotkeyFont);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ namespace Barotrauma.Items.Components
|
||||
shakeTimer -= deltaTime;
|
||||
Vector2 noisePos = new Vector2((float)PerlinNoise.CalculatePerlin(shakeTimer * 10.0f, shakeTimer * 10.0f, 0) - 0.5f, (float)PerlinNoise.CalculatePerlin(shakeTimer * 10.0f, shakeTimer * 10.0f, 0.5f) - 0.5f);
|
||||
shakePos = noisePos * shake * 2.0f;
|
||||
shake = Math.Min(shake, shakeTimer);
|
||||
shake = Math.Min(shake, shakeTimer * 10.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace Barotrauma.Items.Components
|
||||
var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.90f, 0.80f), GuiFrame.RectTransform, Anchor.Center), childAnchor: Anchor.TopCenter)
|
||||
{
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.02f
|
||||
RelativeSpacing = 0.08f
|
||||
};
|
||||
|
||||
var topFrame = new GUIFrame(new RectTransform(new Vector2(1f, 0.5f), paddedFrame.RectTransform), style: null);
|
||||
@@ -51,15 +51,15 @@ namespace Barotrauma.Items.Components
|
||||
inputLabel.RectTransform.Resize(new Point((int) inputLabel.Font.MeasureString(inputLabel.Text).X, inputLabel.RectTransform.Rect.Height));
|
||||
new GUIFrame(new RectTransform(Vector2.One, inputLabelArea.RectTransform), style: "HorizontalLine");
|
||||
|
||||
var inputArea = new GUILayoutGroup(new RectTransform(new Vector2(1f, 1.2f), topFrame.RectTransform, Anchor.CenterLeft), childAnchor: Anchor.BottomLeft, isHorizontal: true) { Stretch = true, RelativeSpacing = 0.05f };
|
||||
var inputArea = new GUILayoutGroup(new RectTransform(new Vector2(1f, 1f), topFrame.RectTransform, Anchor.CenterLeft), childAnchor: Anchor.BottomLeft, isHorizontal: true) { Stretch = true, RelativeSpacing = 0.05f };
|
||||
|
||||
// === INPUT SLOTS === //
|
||||
inputInventoryHolder = new GUIFrame(new RectTransform(new Vector2(0.7f, 1f), inputArea.RectTransform), style: null);
|
||||
inputInventoryOverlay = new GUICustomComponent(new RectTransform(Vector2.One, inputInventoryHolder.RectTransform), DrawOverLay, null) { CanBeFocused = false };
|
||||
|
||||
// === ACTIVATE BUTTON === //
|
||||
var buttonContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.4f, 0.75f), inputArea.RectTransform), childAnchor: Anchor.CenterLeft);
|
||||
activateButton = new GUIButton(new RectTransform(new Vector2(0.95f, 0.65f), buttonContainer.RectTransform), TextManager.Get("DeconstructorDeconstruct"), style: "DeviceButton")
|
||||
var buttonContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.4f, 0.7f), inputArea.RectTransform), childAnchor: Anchor.CenterLeft);
|
||||
activateButton = new GUIButton(new RectTransform(new Vector2(0.95f, 0.8f), buttonContainer.RectTransform), TextManager.Get("DeconstructorDeconstruct"), style: "DeviceButton")
|
||||
{
|
||||
TextBlock = { AutoScaleHorizontal = true },
|
||||
OnClicked = ToggleActive
|
||||
@@ -87,7 +87,7 @@ namespace Barotrauma.Items.Components
|
||||
new GUIFrame(new RectTransform(Vector2.One, outputLabelArea.RectTransform), style: "HorizontalLine");
|
||||
|
||||
// === OUTPUT SLOTS === //
|
||||
outputInventoryHolder = new GUIFrame(new RectTransform(new Vector2(1f, 1.2f), bottomFrame.RectTransform, Anchor.CenterLeft), style: null);
|
||||
outputInventoryHolder = new GUIFrame(new RectTransform(new Vector2(1f, 1f), bottomFrame.RectTransform, Anchor.CenterLeft), style: null);
|
||||
}
|
||||
|
||||
public override bool Select(Character character)
|
||||
|
||||
@@ -299,6 +299,11 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
foreach (FabricationRecipe.RequiredItem requiredItem in missingItems)
|
||||
{
|
||||
while (slotIndex < inputContainer.Capacity && inputContainer.Inventory.Items[slotIndex] != null)
|
||||
{
|
||||
slotIndex++;
|
||||
}
|
||||
|
||||
//highlight suitable ingredients in linked inventories
|
||||
foreach (Item item in availableIngredients)
|
||||
{
|
||||
@@ -311,26 +316,24 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
if (item.ParentInventory.slots[availableSlotIndex].HighlightTimer <= 0.0f)
|
||||
{
|
||||
item.ParentInventory.slots[availableSlotIndex].ShowBorderHighlight(GUI.Style.Green * 0.5f, 0.5f, 0.5f);
|
||||
item.ParentInventory.slots[availableSlotIndex].ShowBorderHighlight(GUI.Style.Green, 0.5f, 0.5f);
|
||||
if (slotIndex < inputContainer.Capacity)
|
||||
{
|
||||
inputContainer.Inventory.slots[slotIndex].ShowBorderHighlight(GUI.Style.Green, 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 * (availableIngredients.Any(i => IsItemValidIngredient(i, requiredItem)) ? 1.0f : 0.3f),
|
||||
color: requiredItem.ItemPrefab.InventoryIconColor * 0.3f,
|
||||
scale: Math.Min(slotRect.Width / itemIcon.size.X, slotRect.Height / itemIcon.size.Y));
|
||||
|
||||
if (slotRect.Contains(PlayerInput.MousePosition))
|
||||
|
||||
@@ -59,7 +59,7 @@ namespace Barotrauma.Items.Components
|
||||
public override void AddToGUIUpdateList()
|
||||
{
|
||||
base.AddToGUIUpdateList();
|
||||
hullInfoFrame.AddToGUIUpdateList();
|
||||
hullInfoFrame.AddToGUIUpdateList(order: 1);
|
||||
}
|
||||
|
||||
public override void OnMapLoaded()
|
||||
@@ -257,8 +257,11 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
|
||||
if (mouseOnHull == hull)
|
||||
{
|
||||
{
|
||||
hullInfoFrame.RectTransform.ScreenSpaceOffset = hullFrame.Rect.Center;
|
||||
if (hullInfoFrame.Rect.Right > GameMain.GraphicsWidth) { hullInfoFrame.RectTransform.ScreenSpaceOffset -= new Point(hullInfoFrame.Rect.Width, 0); }
|
||||
if (hullInfoFrame.Rect.Bottom > GameMain.GraphicsHeight) { hullInfoFrame.RectTransform.ScreenSpaceOffset -= new Point(0, hullInfoFrame.Rect.Height); }
|
||||
|
||||
hullInfoFrame.Visible = true;
|
||||
hullNameText.Text = hull.DisplayName;
|
||||
|
||||
|
||||
@@ -236,7 +236,6 @@ namespace Barotrauma.Items.Components
|
||||
var directionalModeSwitchText = new GUITextBlock(new RectTransform(new Vector2(0.7f, 1), directionalModeFrame.RectTransform, Anchor.CenterRight),
|
||||
TextManager.Get("SonarDirectionalPing"), GUI.Style.TextColor, GUI.SubHeadingFont, Alignment.CenterLeft);
|
||||
|
||||
signalWarningText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), paddedControlContainer.RectTransform), "", warningColor, textAlignment: Alignment.Center);
|
||||
|
||||
GuiFrame.CanBeFocused = false;
|
||||
|
||||
@@ -245,11 +244,14 @@ namespace Barotrauma.Items.Components
|
||||
sonarView = new GUICustomComponent(new RectTransform(Vector2.One * 0.7f, GuiFrame.RectTransform, Anchor.BottomRight, scaleBasis: ScaleBasis.BothHeight),
|
||||
(spriteBatch, guiCustomComponent) => { DrawSonar(spriteBatch, guiCustomComponent.Rect); }, null);
|
||||
|
||||
signalWarningText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.25f), sonarView.RectTransform, Anchor.Center, Pivot.BottomCenter),
|
||||
"", warningColor, GUI.LargeFont, Alignment.Center);
|
||||
|
||||
// Setup layout for nav terminal
|
||||
if (isConnectedToSteering)
|
||||
{
|
||||
controlContainer.RectTransform.SetPosition(Anchor.TopLeft);
|
||||
controlContainer.RectTransform.RelativeOffset = controlBoxOffset;
|
||||
controlContainer.RectTransform.SetPosition(Anchor.TopLeft);
|
||||
sonarView.RectTransform.ScaleBasis = ScaleBasis.Smallest;
|
||||
sonarView.RectTransform.SetPosition(Anchor.CenterRight);
|
||||
sonarView.RectTransform.Resize(Vector2.One * GUI.RelativeHorizontalAspectRatio * sonarAreaSize);
|
||||
|
||||
@@ -108,10 +108,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
private void CreateGUI()
|
||||
{
|
||||
controlContainer = new GUIFrame(new RectTransform(new Vector2(Sonar.controlBoxSize.X, Sonar.controlBoxSize.Y + 0.02f), GuiFrame.RectTransform, Anchor.CenterLeft)
|
||||
{
|
||||
RelativeOffset = new Vector2(0, 0) // The y offset should be based on the relative size difference of the steering and the status windows
|
||||
}, "ItemUI");
|
||||
controlContainer = new GUIFrame(new RectTransform(new Vector2(Sonar.controlBoxSize.X, 1 - Sonar.controlBoxSize.Y * 2), GuiFrame.RectTransform, Anchor.CenterLeft), "ItemUI");
|
||||
var paddedControlContainer = new GUIFrame(new RectTransform(controlContainer.Rect.Size - GUIStyle.ItemFrameMargin, controlContainer.RectTransform, Anchor.Center)
|
||||
{
|
||||
AbsoluteOffset = GUIStyle.ItemFrameOffset
|
||||
@@ -120,7 +117,7 @@ namespace Barotrauma.Items.Components
|
||||
var steeringModeArea = new GUIFrame(new RectTransform(new Vector2(1, 0.4f), paddedControlContainer.RectTransform, Anchor.TopLeft), style: null);
|
||||
steeringModeSwitch = new GUIButton(new RectTransform(new Vector2(0.2f, 1), steeringModeArea.RectTransform), string.Empty, style: "SwitchVertical")
|
||||
{
|
||||
Selected = false,
|
||||
Selected = autoPilot,
|
||||
Enabled = true,
|
||||
OnClicked = (button, data) =>
|
||||
{
|
||||
@@ -141,34 +138,26 @@ namespace Barotrauma.Items.Components
|
||||
manualPilotIndicator = new GUITickBox(new RectTransform(new Vector2(1, 0.45f), steeringModeRightSide.RectTransform, Anchor.TopLeft),
|
||||
TextManager.Get("SteeringManual"), font: GUI.SubHeadingFont, style: "IndicatorLightRedSmall")
|
||||
{
|
||||
Selected = true,
|
||||
Selected = !autoPilot,
|
||||
Enabled = false
|
||||
};
|
||||
autopilotIndicator = new GUITickBox(new RectTransform(new Vector2(1, 0.45f), steeringModeRightSide.RectTransform, Anchor.BottomLeft),
|
||||
TextManager.Get("SteeringAutoPilot"), font: GUI.SubHeadingFont, style: "IndicatorLightRedSmall")
|
||||
{
|
||||
Selected = false,
|
||||
Selected = autoPilot,
|
||||
Enabled = false
|
||||
};
|
||||
manualPilotIndicator.TextBlock.OverrideTextColor(GUI.Style.TextColor);
|
||||
autopilotIndicator.TextBlock.OverrideTextColor(GUI.Style.TextColor);
|
||||
GUITextBlock.AutoScaleAndNormalize(manualPilotIndicator.TextBlock, autopilotIndicator.TextBlock);
|
||||
|
||||
var autoPilotControls = new GUIFrame(new RectTransform(new Vector2(0.8f, 0.6f), paddedControlContainer.RectTransform, Anchor.BottomCenter)
|
||||
{
|
||||
RelativeOffset = new Vector2(0, 0.02f)
|
||||
}, "OutlineFrame");
|
||||
var paddedAutoPilotControls = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.85f), autoPilotControls.RectTransform, Anchor.Center))
|
||||
{
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.03f,
|
||||
ChildAnchor = Anchor.TopLeft
|
||||
};
|
||||
var autoPilotControls = new GUIFrame(new RectTransform(new Vector2(0.75f, 0.62f), paddedControlContainer.RectTransform, Anchor.BottomCenter), "OutlineFrame");
|
||||
var paddedAutoPilotControls = new GUIFrame(new RectTransform(new Vector2(0.92f, 0.88f), autoPilotControls.RectTransform, Anchor.Center), style: null);
|
||||
|
||||
maintainPosTickBox = new GUITickBox(new RectTransform(new Vector2(1, 0.3f), paddedAutoPilotControls.RectTransform),
|
||||
maintainPosTickBox = new GUITickBox(new RectTransform(new Vector2(1, 0.333f), paddedAutoPilotControls.RectTransform, Anchor.TopCenter),
|
||||
TextManager.Get("SteeringMaintainPos"), font: GUI.SmallFont, style: "GUIRadioButton")
|
||||
{
|
||||
Enabled = false,
|
||||
Enabled = autoPilot,
|
||||
Selected = maintainPos,
|
||||
OnSelected = tickBox =>
|
||||
{
|
||||
@@ -200,12 +189,12 @@ namespace Barotrauma.Items.Components
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
levelStartTickBox = new GUITickBox(new RectTransform(new Vector2(1, 0.3f), paddedAutoPilotControls.RectTransform),
|
||||
GameMain.GameSession?.StartLocation == null ? "" : ToolBox.LimitString(GameMain.GameSession.StartLocation.Name, 30),
|
||||
int textLimit = (int)(MathHelper.Clamp(25 * GUI.xScale, 15, 35));
|
||||
levelStartTickBox = new GUITickBox(new RectTransform(new Vector2(1, 0.333f), paddedAutoPilotControls.RectTransform, Anchor.Center),
|
||||
GameMain.GameSession?.StartLocation == null ? "" : ToolBox.LimitString(GameMain.GameSession.StartLocation.Name, textLimit),
|
||||
font: GUI.SmallFont, style: "GUIRadioButton")
|
||||
{
|
||||
Enabled = false,
|
||||
Enabled = autoPilot,
|
||||
Selected = levelStartSelected,
|
||||
OnSelected = tickBox =>
|
||||
{
|
||||
@@ -228,11 +217,11 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
};
|
||||
|
||||
levelEndTickBox = new GUITickBox(new RectTransform(new Vector2(1, 0.3f), paddedAutoPilotControls.RectTransform),
|
||||
GameMain.GameSession?.EndLocation == null ? "" : ToolBox.LimitString(GameMain.GameSession.EndLocation.Name, 30),
|
||||
levelEndTickBox = new GUITickBox(new RectTransform(new Vector2(1, 0.333f), paddedAutoPilotControls.RectTransform, Anchor.BottomCenter),
|
||||
GameMain.GameSession?.EndLocation == null ? "" : ToolBox.LimitString(GameMain.GameSession.EndLocation.Name, textLimit),
|
||||
font: GUI.SmallFont, style: "GUIRadioButton")
|
||||
{
|
||||
Enabled = false,
|
||||
Enabled = autoPilot,
|
||||
Selected = levelEndSelected,
|
||||
OnSelected = tickBox =>
|
||||
{
|
||||
@@ -254,14 +243,14 @@ namespace Barotrauma.Items.Components
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
GUITextBlock.AutoScaleAndNormalize(maintainPosTickBox.TextBlock, levelStartTickBox.TextBlock, levelEndTickBox.TextBlock);
|
||||
maintainPosTickBox.RectTransform.IsFixedSize = levelStartTickBox.RectTransform.IsFixedSize = levelEndTickBox.RectTransform.IsFixedSize = false;
|
||||
maintainPosTickBox.RectTransform.MaxSize = levelStartTickBox.RectTransform.MaxSize = levelEndTickBox.RectTransform.MaxSize =
|
||||
new Point(int.MaxValue, paddedAutoPilotControls.Rect.Height / 3);
|
||||
maintainPosTickBox.RectTransform.MinSize = levelStartTickBox.RectTransform.MinSize = levelEndTickBox.RectTransform.MinSize =
|
||||
Point.Zero;
|
||||
|
||||
GUITextBlock.AutoScaleAndNormalize(scaleHorizontal: false, scaleVertical: true, maintainPosTickBox.TextBlock, levelStartTickBox.TextBlock, levelEndTickBox.TextBlock);
|
||||
|
||||
GUIRadioButtonGroup destinations = new GUIRadioButtonGroup();
|
||||
destinations.AddRadioButton((int)Destination.MaintainPos, maintainPosTickBox);
|
||||
destinations.AddRadioButton((int)Destination.LevelStart, levelStartTickBox);
|
||||
@@ -401,11 +390,12 @@ namespace Barotrauma.Items.Components
|
||||
(spriteBatch, guiCustomComponent) => { DrawHUD(spriteBatch, guiCustomComponent.Rect); }, null);
|
||||
steerRadius = steerArea.Rect.Width / 2;
|
||||
|
||||
// Tooltip/helper text
|
||||
pressureWarningText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.25f), paddedStatusContainer.RectTransform), TextManager.Get("SteeringDepthWarning"), GUI.Style.Red)
|
||||
pressureWarningText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.25f), steerArea.RectTransform, Anchor.Center, Pivot.TopCenter),
|
||||
TextManager.Get("SteeringDepthWarning"), Color.Red, GUI.LargeFont, Alignment.Center)
|
||||
{
|
||||
Visible = false
|
||||
};
|
||||
// Tooltip/helper text
|
||||
tipContainer = new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.1f), steerArea.RectTransform, Anchor.BottomCenter, Pivot.TopCenter)
|
||||
, "", font: GUI.Font, wrap: true, style: "GUIToolTip", textAlignment: Alignment.Center)
|
||||
{
|
||||
@@ -423,6 +413,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
GuiFrame.ClearChildren();
|
||||
CreateGUI();
|
||||
UpdateGUIElements();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -152,7 +152,10 @@ namespace Barotrauma.Items.Components
|
||||
DraggingConnected.Connections[1]?.ConnectionPanel == panel)
|
||||
{
|
||||
DraggingConnected.RemoveConnection(panel.Item);
|
||||
panel.DisconnectedWires.Add(DraggingConnected);
|
||||
if (DraggingConnected.Item.ParentInventory == null)
|
||||
{
|
||||
panel.DisconnectedWires.Add(DraggingConnected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -134,46 +134,57 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
if (IsActive && item.ParentInventory?.Owner is Character user && user == Character.Controlled)// && Vector2.Distance(newNodePos, nodes[nodes.Count - 1]) > nodeDistance)
|
||||
{
|
||||
Vector2 gridPos = Character.Controlled.Position;
|
||||
Vector2 roundedGridPos = new Vector2(
|
||||
MathUtils.RoundTowardsClosest(Character.Controlled.Position.X, Submarine.GridSize.X),
|
||||
MathUtils.RoundTowardsClosest(Character.Controlled.Position.Y, Submarine.GridSize.Y));
|
||||
//Vector2 attachPos = GetAttachPosition(user);
|
||||
|
||||
if (item.Submarine == null)
|
||||
if (user.CanInteract)
|
||||
{
|
||||
Structure attachTarget = Structure.GetAttachTarget(item.WorldPosition);
|
||||
if (attachTarget != null)
|
||||
Vector2 gridPos = Character.Controlled.Position;
|
||||
Vector2 roundedGridPos = new Vector2(
|
||||
MathUtils.RoundTowardsClosest(Character.Controlled.Position.X, Submarine.GridSize.X),
|
||||
MathUtils.RoundTowardsClosest(Character.Controlled.Position.Y, Submarine.GridSize.Y));
|
||||
//Vector2 attachPos = GetAttachPosition(user);
|
||||
|
||||
if (item.Submarine == null)
|
||||
{
|
||||
if (attachTarget.Submarine != null)
|
||||
Structure attachTarget = Structure.GetAttachTarget(item.WorldPosition);
|
||||
if (attachTarget != null)
|
||||
{
|
||||
//set to submarine-relative position
|
||||
gridPos += attachTarget.Submarine.Position;
|
||||
roundedGridPos += attachTarget.Submarine.Position;
|
||||
if (attachTarget.Submarine != null)
|
||||
{
|
||||
//set to submarine-relative position
|
||||
gridPos += attachTarget.Submarine.Position;
|
||||
roundedGridPos += attachTarget.Submarine.Position;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gridPos += item.Submarine.Position;
|
||||
roundedGridPos += item.Submarine.Position;
|
||||
}
|
||||
|
||||
Submarine.DrawGrid(spriteBatch, 14, gridPos, roundedGridPos, alpha: 0.7f);
|
||||
|
||||
WireSection.Draw(
|
||||
spriteBatch, this,
|
||||
new Vector2(nodes[nodes.Count - 1].X, nodes[nodes.Count - 1].Y) + drawOffset,
|
||||
new Vector2(newNodePos.X, newNodePos.Y) + drawOffset,
|
||||
item.Color, 0.0f, 0.3f);
|
||||
|
||||
WireSection.Draw(
|
||||
spriteBatch, this,
|
||||
new Vector2(newNodePos.X, newNodePos.Y) + drawOffset,
|
||||
item.DrawPosition,
|
||||
item.Color, itemDepth, 0.3f);
|
||||
|
||||
GUI.DrawRectangle(spriteBatch, new Vector2(newNodePos.X + drawOffset.X, -(newNodePos.Y + drawOffset.Y)) - Vector2.One * 3, Vector2.One * 6, item.Color);
|
||||
}
|
||||
else
|
||||
{
|
||||
gridPos += item.Submarine.Position;
|
||||
roundedGridPos += item.Submarine.Position;
|
||||
WireSection.Draw(
|
||||
spriteBatch, this,
|
||||
new Vector2(nodes[nodes.Count - 1].X, nodes[nodes.Count - 1].Y) + drawOffset,
|
||||
item.DrawPosition,
|
||||
item.Color, 0.0f, 0.3f);
|
||||
}
|
||||
|
||||
Submarine.DrawGrid(spriteBatch, 14, gridPos, roundedGridPos, alpha: 0.7f);
|
||||
|
||||
WireSection.Draw(
|
||||
spriteBatch, this,
|
||||
new Vector2(nodes[nodes.Count - 1].X, nodes[nodes.Count - 1].Y) + drawOffset,
|
||||
new Vector2(newNodePos.X, newNodePos.Y) + drawOffset,
|
||||
item.Color, 0.0f, 0.3f);
|
||||
|
||||
WireSection.Draw(
|
||||
spriteBatch, this,
|
||||
new Vector2(newNodePos.X, newNodePos.Y) + drawOffset,
|
||||
item.DrawPosition,
|
||||
item.Color, itemDepth, 0.3f);
|
||||
|
||||
GUI.DrawRectangle(spriteBatch, new Vector2(newNodePos.X + drawOffset.X, -(newNodePos.Y + drawOffset.Y)) - Vector2.One * 3, Vector2.One * 6, item.Color);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -53,14 +53,10 @@ namespace Barotrauma
|
||||
{
|
||||
int buttonDir = Math.Sign(SubInventoryDir);
|
||||
|
||||
Vector2 equipIndicatorPos = new Vector2(
|
||||
Rect.Center.X - Inventory.EquipIndicator.size.X / 2 * Inventory.UIScale,
|
||||
Rect.Center.Y + (Rect.Height / 2 + 25 * Inventory.UIScale) * buttonDir - Inventory.EquipIndicator.size.Y / 2 * Inventory.UIScale);
|
||||
Vector2 equipIndicatorPos = new Vector2(Rect.Left, Rect.Top);
|
||||
equipIndicatorPos += DrawOffset;
|
||||
|
||||
return new Rectangle(
|
||||
(int)(equipIndicatorPos.X), (int)(equipIndicatorPos.Y),
|
||||
(int)(Inventory.EquipIndicator.size.X * Inventory.UIScale), (int)(Inventory.EquipIndicator.size.Y * Inventory.UIScale));
|
||||
return new Rectangle((int)equipIndicatorPos.X, (int)equipIndicatorPos.Y, Rect.Width, (int)(Inventory.EquipIndicator.size.Y * Inventory.UIScale));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,11 +128,27 @@ namespace Barotrauma
|
||||
protected Point prevScreenResolution;
|
||||
|
||||
protected static Sprite slotHotkeySprite;
|
||||
public static Sprite SlotSpriteSmall;
|
||||
public static Sprite EquipIndicator, EquipIndicatorHighlight;
|
||||
|
||||
private static Sprite slotSpriteSmall;
|
||||
public static Sprite SlotSpriteSmall
|
||||
{
|
||||
get
|
||||
{
|
||||
if (slotSpriteSmall == null)
|
||||
{
|
||||
//TODO: define these in xml
|
||||
slotSpriteSmall = new Sprite("Content/UI/InventoryUIAtlas.png", new Rectangle(12, 9, 115, 115), null, 0);
|
||||
slotSpriteSmall.size = new Vector2(SlotSpriteSmall.SourceRect.Width * 0.682f, SlotSpriteSmall.SourceRect.Height * 0.682f);
|
||||
}
|
||||
return slotSpriteSmall;
|
||||
}
|
||||
}
|
||||
public static Sprite DraggableIndicator;
|
||||
public static Sprite EquipIndicator;
|
||||
|
||||
public static Inventory DraggingInventory;
|
||||
|
||||
public Rectangle BackgroundFrame { get; protected set; }
|
||||
public Rectangle BackgroundFrame;
|
||||
|
||||
private ushort[] receivedItemIDs;
|
||||
private CoroutineHandle syncItemsCoroutine;
|
||||
@@ -151,6 +163,8 @@ namespace Barotrauma
|
||||
private Point savedPosition, originalPos;
|
||||
private bool canMove = false;
|
||||
private bool positionUpdateQueued = false;
|
||||
private Vector2 draggableIndicatorOffset;
|
||||
private float draggableIndicatorScale;
|
||||
|
||||
public class SlotReference
|
||||
{
|
||||
@@ -291,7 +305,7 @@ namespace Barotrauma
|
||||
int columns = Math.Min(slotsPerRow, capacity);
|
||||
|
||||
Vector2 spacing = new Vector2(5.0f * UIScale);
|
||||
spacing.Y += (this is CharacterInventory) ? EquipIndicator.size.Y * UIScale : ContainedIndicatorHeight;
|
||||
spacing.Y += (this is CharacterInventory) ? EquipIndicator.size.Y : ContainedIndicatorHeight;
|
||||
Vector2 rectSize = new Vector2(60.0f * UIScale);
|
||||
|
||||
padding = new Vector4(spacing.X, spacing.Y, spacing.X, spacing.X);
|
||||
@@ -370,7 +384,12 @@ namespace Barotrauma
|
||||
|
||||
protected virtual bool HideSlot(int i)
|
||||
{
|
||||
return slots[i].Disabled || (hideEmptySlot[i] && Items[i] == null);
|
||||
return slots[i].Disabled;
|
||||
}
|
||||
|
||||
protected virtual bool IsSlotHiddenDueToToggleState(int i)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public virtual void Update(float deltaTime, Camera cam, bool subInventory = false)
|
||||
@@ -386,7 +405,7 @@ namespace Barotrauma
|
||||
{
|
||||
for (int i = 0; i < capacity; i++)
|
||||
{
|
||||
if (HideSlot(i)) { continue; }
|
||||
if (HideSlot(i) || IsSlotHiddenDueToToggleState(i)) { continue; }
|
||||
UpdateSlot(slots[i], i, Items[i], subInventory);
|
||||
}
|
||||
if (!isSubInventory)
|
||||
@@ -516,6 +535,9 @@ namespace Barotrauma
|
||||
{
|
||||
if (PlayerInput.PrimaryMouseButtonDown())
|
||||
{
|
||||
// Prevent us from dragging an item
|
||||
draggingItem = null;
|
||||
draggingSlot = null;
|
||||
DraggingInventory = subInventory;
|
||||
}
|
||||
}
|
||||
@@ -535,7 +557,7 @@ namespace Barotrauma
|
||||
var slot = slots[slotIndex];
|
||||
int dir = slot.SubInventoryDir;
|
||||
Rectangle subRect = slot.Rect;
|
||||
Vector2 spacing = new Vector2(10 * UIScale, (10 + EquipIndicator.size.Y) * UIScale);
|
||||
Vector2 spacing = new Vector2(10 * UIScale, (10 * UIScale + EquipIndicator.size.Y));
|
||||
|
||||
int columns = (int)Math.Max(Math.Floor(Math.Sqrt(itemCapacity)), 1);
|
||||
while (itemCapacity / columns * (subRect.Height + spacing.Y) > GameMain.GraphicsHeight * 0.5f)
|
||||
@@ -631,18 +653,24 @@ namespace Barotrauma
|
||||
/// Is the mouse on any inventory element (slot, equip button, subinventory...)
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static bool IsMouseOnInventory()
|
||||
public static bool IsMouseOnInventory(bool ignoreDrag = false)
|
||||
{
|
||||
if (Character.Controlled == null) return false;
|
||||
|
||||
if (draggingItem != null || DraggingInventory != null) return true;
|
||||
if (!ignoreDrag && draggingItem != null || DraggingInventory != null) return true;
|
||||
|
||||
if (Character.Controlled.Inventory != null)
|
||||
{
|
||||
var inv = Character.Controlled.Inventory;
|
||||
|
||||
if (inv.BackgroundFrame.Contains(PlayerInput.MousePosition) || inv.InventoryToggleContains) return true;
|
||||
|
||||
for (var i = 0; i < inv.slots.Length; i++)
|
||||
{
|
||||
var slot = inv.slots[i];
|
||||
|
||||
if (inv.HideSlot(i) || inv.IsSlotHiddenDueToToggleState(i)) continue;
|
||||
|
||||
if (slot.InteractRect.Contains(PlayerInput.MousePosition))
|
||||
{
|
||||
return true;
|
||||
@@ -715,6 +743,11 @@ namespace Barotrauma
|
||||
|
||||
if (inv == null) { return CursorState.Default; }
|
||||
|
||||
if (inv.InventoryToggleContains)
|
||||
{
|
||||
return CursorState.Hand;
|
||||
}
|
||||
|
||||
foreach (var item in inv.Items)
|
||||
{
|
||||
var container = item?.GetComponent<ItemContainer>();
|
||||
@@ -765,8 +798,12 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var slot in inv.slots)
|
||||
for (int i = 0; i < inv.slots.Length; i++)
|
||||
{
|
||||
InventorySlot slot = inv.slots[i];
|
||||
|
||||
if (inv.IsSlotHiddenDueToToggleState(i)) continue;
|
||||
|
||||
if (slot.EquipButtonRect.Contains(PlayerInput.MousePosition))
|
||||
{
|
||||
return CursorState.Hand;
|
||||
@@ -783,6 +820,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return CursorState.Default;
|
||||
}
|
||||
|
||||
@@ -850,6 +888,12 @@ namespace Barotrauma
|
||||
{
|
||||
if (positionUpdateQueued) // Wait a frame before updating the positioning of the container after a resolution change to have everything working
|
||||
{
|
||||
int height = (int)(movableFrameRectHeight * UIScale);
|
||||
CreateSlots();
|
||||
container.Inventory.movableFrameRect = new Rectangle(container.Inventory.BackgroundFrame.X, container.Inventory.BackgroundFrame.Y - height, container.Inventory.BackgroundFrame.Width, height);
|
||||
draggableIndicatorScale = 1.25f * UIScale;
|
||||
draggableIndicatorOffset = DraggableIndicator.size * draggableIndicatorScale / 2f;
|
||||
draggableIndicatorOffset += new Vector2(height / 2f - draggableIndicatorOffset.Y);
|
||||
container.Inventory.originalPos = container.Inventory.savedPosition = container.Inventory.movableFrameRect.Center;
|
||||
positionUpdateQueued = false;
|
||||
}
|
||||
@@ -862,12 +906,13 @@ namespace Barotrauma
|
||||
prevScreenResolution = new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight);
|
||||
prevUIScale = UIScale;
|
||||
prevHUDScale = GUI.Scale;
|
||||
int height = (int)(movableFrameRectHeight * UIScale);
|
||||
container.Inventory.movableFrameRect = new Rectangle(container.Inventory.BackgroundFrame.X, container.Inventory.BackgroundFrame.Y - height, container.Inventory.BackgroundFrame.Width, height);
|
||||
positionUpdateQueued = true;
|
||||
}
|
||||
|
||||
GUI.DrawRectangle(spriteBatch, container.Inventory.movableFrameRect, movableFrameRectColor, true);
|
||||
else
|
||||
{
|
||||
GUI.DrawRectangle(spriteBatch, container.Inventory.movableFrameRect, movableFrameRectColor, true);
|
||||
DraggableIndicator.Draw(spriteBatch, container.Inventory.movableFrameRect.Location.ToVector2() + draggableIndicatorOffset, 0, draggableIndicatorScale);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -886,17 +931,20 @@ namespace Barotrauma
|
||||
|
||||
if (selectedSlot == null)
|
||||
{
|
||||
if (DraggingItemToWorld &&
|
||||
Character.Controlled.FocusedItem?.OwnInventory != null &&
|
||||
Character.Controlled.FocusedItem.OwnInventory.CanBePut(draggingItem) &&
|
||||
Character.Controlled.FocusedItem.OwnInventory.TryPutItem(draggingItem, Character.Controlled))
|
||||
if (!IsMouseOnInventory(true))
|
||||
{
|
||||
GUI.PlayUISound(GUISoundType.PickItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
GUI.PlayUISound(GUISoundType.DropItem);
|
||||
draggingItem.Drop(Character.Controlled);
|
||||
if (DraggingItemToWorld &&
|
||||
Character.Controlled.FocusedItem?.OwnInventory != null &&
|
||||
Character.Controlled.FocusedItem.OwnInventory.CanBePut(draggingItem) &&
|
||||
Character.Controlled.FocusedItem.OwnInventory.TryPutItem(draggingItem, Character.Controlled))
|
||||
{
|
||||
GUI.PlayUISound(GUISoundType.PickItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
GUI.PlayUISound(GUISoundType.DropItem);
|
||||
draggingItem.Drop(Character.Controlled);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (selectedSlot.ParentInventory.Items[selectedSlot.SlotIndex] != draggingItem)
|
||||
@@ -1028,7 +1076,7 @@ namespace Barotrauma
|
||||
|
||||
bool mouseOnHealthInterface = CharacterHealth.OpenHealthWindow != null && CharacterHealth.OpenHealthWindow.MouseOnElement;
|
||||
|
||||
if ((GUI.MouseOn == null || mouseOnHealthInterface) && selectedSlot == null)
|
||||
if ((GUI.MouseOn == null || mouseOnHealthInterface) && selectedSlot == null && !IsMouseOnInventory(true))
|
||||
{
|
||||
var shadowSprite = GUI.Style.GetComponentStyle("OuterGlow").Sprites[GUIComponent.ComponentState.None][0];
|
||||
string toolTip = mouseOnHealthInterface ? TextManager.Get("QuickUseAction.UseTreatment") :
|
||||
@@ -1053,7 +1101,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
if (selectedSlot != null && selectedSlot.Item != null)
|
||||
if (selectedSlot != null && selectedSlot.Item != null && selectedSlot.Slot.EquipButtonState != GUIComponent.ComponentState.Hover)
|
||||
{
|
||||
Rectangle slotRect = selectedSlot.Slot.Rect;
|
||||
slotRect.Location += selectedSlot.Slot.DrawOffset.ToPoint();
|
||||
@@ -1091,11 +1139,26 @@ namespace Barotrauma
|
||||
if (inventory != null && (CharacterInventory.PersonalSlots.HasFlag(type) || (inventory.isSubInventory && (inventory.Owner as Item) != null
|
||||
&& (inventory.Owner as Item).AllowedSlots.Any(a => CharacterInventory.PersonalSlots.HasFlag(a)))))
|
||||
{
|
||||
slotColor = slot.IsHighlighted ? GUIColorSettings.EquipmentSlotColor : GUIColorSettings.EquipmentSlotColor * 0.8f;
|
||||
if (item == null)
|
||||
{
|
||||
slotColor = slot.IsHighlighted ? GUIColorSettings.EquipmentSlotEmptyColor : GUIColorSettings.EquipmentSlotEmptyColor * 0.8f;
|
||||
}
|
||||
else
|
||||
{
|
||||
slotColor = slot.IsHighlighted ? GUIColorSettings.EquipmentSlotColor : GUIColorSettings.EquipmentSlotColor * 0.8f;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
slotColor = slot.IsHighlighted ? GUIColorSettings.InventorySlotColor : GUIColorSettings.InventorySlotColor * 0.8f;
|
||||
if (item != null && Character.Controlled.HasEquippedItem(item))
|
||||
{
|
||||
slotColor = slot.IsHighlighted ? GUIColorSettings.InventorySlotEquippedColor : GUIColorSettings.InventorySlotEquippedColor * 0.8f;
|
||||
}
|
||||
else
|
||||
{
|
||||
slotColor = slot.IsHighlighted ? GUIColorSettings.InventorySlotColor : GUIColorSettings.InventorySlotColor * 0.8f;
|
||||
}
|
||||
}
|
||||
|
||||
if (inventory != null && inventory.Locked) { slotColor = Color.Gray * 0.5f; }
|
||||
@@ -1210,7 +1273,7 @@ namespace Barotrauma
|
||||
if (GameMain.DebugDraw)
|
||||
{
|
||||
GUI.DrawRectangle(spriteBatch, rect, Color.White, false, 0, 1);
|
||||
GUI.DrawRectangle(spriteBatch, slot.EquipButtonRect, Color.White, false, 0, 1);
|
||||
GUI.DrawRectangle(spriteBatch, slot.EquipButtonRect, Color.Red, false, 0, 1);
|
||||
}
|
||||
|
||||
if (slot.HighlightColor != Color.Transparent)
|
||||
@@ -1221,8 +1284,11 @@ namespace Barotrauma
|
||||
if (item != null && drawItem)
|
||||
{
|
||||
Sprite sprite = item.Prefab.InventoryIcon ?? item.Sprite;
|
||||
float scale = Math.Min(Math.Min((rect.Width - 10) / sprite.size.X, (rect.Height - 10) / sprite.size.Y), 2.0f);
|
||||
Vector2 itemPos = rect.Center.ToVector2();
|
||||
|
||||
float equipButtonHeightAdjustment = inventory == Character.Controlled?.Inventory ? slot.EquipButtonRect.Height : 0;
|
||||
|
||||
float scale = Math.Min(Math.Min((rect.Width - 10) / sprite.size.X, (rect.Height - 5 - equipButtonHeightAdjustment) / sprite.size.Y), 2.0f);
|
||||
Vector2 itemPos = rect.Center.ToVector2() + new Vector2(0, equipButtonHeightAdjustment / 2f);
|
||||
if (itemPos.Y > GameMain.GraphicsHeight)
|
||||
{
|
||||
itemPos.Y -= Math.Min(
|
||||
@@ -1248,15 +1314,6 @@ namespace Barotrauma
|
||||
}
|
||||
sprite.Draw(spriteBatch, itemPos, spriteColor, rotation, scale);
|
||||
}
|
||||
|
||||
if (inventory != null &&
|
||||
!inventory.Locked &&
|
||||
Character.Controlled?.Inventory == inventory &&
|
||||
slot.QuickUseKey != Keys.None)
|
||||
{
|
||||
spriteBatch.Draw(slotHotkeySprite.Texture, rect.ScaleSize(1.25f), slotHotkeySprite.SourceRect, slotColor);
|
||||
GUI.DrawString(spriteBatch, rect.Location.ToVector2() + new Vector2(1, -2), slot.QuickUseKey.ToString().Substring(1, 1), Color.Black, font: GUI.SmallFont);
|
||||
}
|
||||
}
|
||||
|
||||
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
||||
@@ -1273,7 +1330,7 @@ namespace Barotrauma
|
||||
//prevents the inventory from briefly reverting to an old state if items are moved around in quick succession
|
||||
|
||||
//also delay if we're still midround syncing, some of the items in the inventory may not exist yet
|
||||
if (syncItemsDelay > 0.0f || GameMain.Client.MidRoundSyncing)
|
||||
if (syncItemsDelay > 0.0f || GameMain.Client.MidRoundSyncing || NetIdUtils.IdMoreRecent(lastEventID, GameMain.Client.EntityEventManager.LastReceivedID))
|
||||
{
|
||||
if (syncItemsCoroutine != null) CoroutineManager.StopCoroutines(syncItemsCoroutine);
|
||||
syncItemsCoroutine = CoroutineManager.StartCoroutine(SyncItemsAfterDelay(lastEventID));
|
||||
|
||||
@@ -698,16 +698,19 @@ namespace Barotrauma
|
||||
//reset positions first
|
||||
List<GUIComponent> elementsToMove = new List<GUIComponent>();
|
||||
|
||||
if (editingHUD != null && editingHUD.UserData == this)
|
||||
if (editingHUD != null && editingHUD.UserData == this &&
|
||||
((HasInGameEditableProperties && Character.Controlled?.SelectedConstruction == this) || Screen.Selected == GameMain.SubEditorScreen))
|
||||
{
|
||||
elementsToMove.Add(editingHUD);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
debugInitialHudPositions.Clear();
|
||||
foreach (ItemComponent ic in activeHUDs)
|
||||
{
|
||||
if (ic.GuiFrame == null || ic.AllowUIOverlap || ic.GetLinkUIToComponent() != null) continue;
|
||||
if (ic.GuiFrame == null || ic.AllowUIOverlap || ic.GetLinkUIToComponent() != null) { continue; }
|
||||
ic.GuiFrame.RectTransform.ScreenSpaceOffset = Point.Zero;
|
||||
elementsToMove.Add(ic.GuiFrame);
|
||||
debugInitialHudPositions.Add(ic.GuiFrame.Rect);
|
||||
}
|
||||
|
||||
List<Rectangle> disallowedAreas = new List<Rectangle>();
|
||||
@@ -728,18 +731,22 @@ namespace Barotrauma
|
||||
|
||||
foreach (ItemComponent ic in activeHUDs)
|
||||
{
|
||||
if (ic.GuiFrame == null) continue;
|
||||
if (ic.GuiFrame == null) { continue; }
|
||||
|
||||
|
||||
var linkUIToComponent = ic.GetLinkUIToComponent();
|
||||
if (linkUIToComponent == null) continue;
|
||||
|
||||
if (linkUIToComponent == null) { continue; }
|
||||
|
||||
ic.GuiFrame.RectTransform.ScreenSpaceOffset = linkUIToComponent.GuiFrame.RectTransform.ScreenSpaceOffset;
|
||||
}
|
||||
}
|
||||
|
||||
private readonly List<Rectangle> debugInitialHudPositions = new List<Rectangle>();
|
||||
|
||||
public void UpdateHUD(Camera cam, Character character, float deltaTime)
|
||||
{
|
||||
bool editingHUDCreated = false;
|
||||
if (HasInGameEditableProperties ||
|
||||
if ((HasInGameEditableProperties && character.SelectedConstruction == this) ||
|
||||
Screen.Selected == GameMain.SubEditorScreen)
|
||||
{
|
||||
GUIComponent prevEditingHUD = editingHUD;
|
||||
@@ -850,6 +857,23 @@ namespace Barotrauma
|
||||
ic.DrawHUD(spriteBatch, character);
|
||||
}
|
||||
}
|
||||
|
||||
if (GameMain.DebugDraw)
|
||||
{
|
||||
int i = 0;
|
||||
foreach (ItemComponent ic in activeHUDs)
|
||||
{
|
||||
if (i >= debugInitialHudPositions.Count) { break; }
|
||||
if (activeHUDs[i].GuiFrame == null) { continue; }
|
||||
if (ic.GuiFrame == null || ic.AllowUIOverlap || ic.GetLinkUIToComponent() != null) { continue; }
|
||||
|
||||
GUI.DrawRectangle(spriteBatch, debugInitialHudPositions[i], Color.Orange);
|
||||
GUI.DrawRectangle(spriteBatch, ic.GuiFrame.Rect, Color.LightGreen);
|
||||
GUI.DrawLine(spriteBatch, debugInitialHudPositions[i].Location.ToVector2(), ic.GuiFrame.Rect.Location.ToVector2(), Color.Orange);
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
readonly List<ColoredText> texts = new List<ColoredText>();
|
||||
@@ -1249,10 +1273,9 @@ namespace Barotrauma
|
||||
{
|
||||
inventory = container.Inventory;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var item = new Item(itemPrefab, pos, sub)
|
||||
{
|
||||
ID = itemId
|
||||
@@ -1262,8 +1285,8 @@ namespace Barotrauma
|
||||
{
|
||||
wifiComponent.TeamID = (Character.TeamType)teamID;
|
||||
}
|
||||
if (descriptionChanged) item.Description = itemDesc;
|
||||
if (tagsChanged) item.Tags = tags;
|
||||
if (descriptionChanged) { item.Description = itemDesc; }
|
||||
if (tagsChanged) { item.Tags = tags; }
|
||||
|
||||
if (sub != null)
|
||||
{
|
||||
@@ -1276,7 +1299,7 @@ namespace Barotrauma
|
||||
if (inventorySlotIndex >= 0 && inventorySlotIndex < 255 &&
|
||||
inventory.TryPutItem(item, inventorySlotIndex, false, false, null, false))
|
||||
{
|
||||
return null;
|
||||
return item;
|
||||
}
|
||||
inventory.TryPutItem(item, null, item.AllowedSlots, false);
|
||||
}
|
||||
|
||||
@@ -11,6 +11,12 @@ namespace Barotrauma
|
||||
{
|
||||
base.ControlInput(cam);
|
||||
cam.OffsetAmount = 0;
|
||||
|
||||
if (Character.Controlled?.Inventory != null)
|
||||
{
|
||||
Character.Controlled.Inventory.ToggleInventory(true);
|
||||
}
|
||||
|
||||
//if this is used, we need to implement syncing this inventory with the server
|
||||
/*Character.DisableControls = true;
|
||||
if (Character.Controlled != null)
|
||||
@@ -19,7 +25,7 @@ namespace Barotrauma
|
||||
{
|
||||
Character.Controlled.SelectedConstruction = null;
|
||||
}
|
||||
}*/
|
||||
}*/
|
||||
}
|
||||
|
||||
protected override void CalculateBackgroundFrame()
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace Barotrauma
|
||||
|
||||
public string Filename
|
||||
{
|
||||
get { return Sound.Filename; }
|
||||
get { return Sound?.Filename; }
|
||||
}
|
||||
|
||||
public RoundSound(XElement element, Sound sound)
|
||||
|
||||
@@ -307,6 +307,8 @@ namespace Barotrauma.Networking
|
||||
Status = FileTransferStatus.Finished,
|
||||
FileSize = 0
|
||||
};
|
||||
|
||||
Md5Hash.RemoveFromCache(directTransfer.FilePath);
|
||||
OnFinished(directTransfer);
|
||||
}
|
||||
break;
|
||||
@@ -376,6 +378,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
finishedTransfers.Add(new Pair<int, double>(transferId, Timing.TotalTime));
|
||||
StopTransfer(activeTransfer);
|
||||
Md5Hash.RemoveFromCache(activeTransfer.FilePath);
|
||||
OnFinished(activeTransfer);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -364,15 +364,7 @@ namespace Barotrauma.Networking
|
||||
updateInterval = new TimeSpan(0, 0, 0, 0, 150);
|
||||
|
||||
CoroutineManager.StartCoroutine(WaitForStartingInfo(), "WaitForStartingInfo");
|
||||
}
|
||||
|
||||
private bool RetryConnection(GUIButton button, object obj)
|
||||
{
|
||||
if (clientPeer != null) { clientPeer.Close(); }
|
||||
clientPeer = null;
|
||||
ConnectToServer(serverEndpoint, serverName);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private bool ReturnToPreviousMenu(GUIButton button, object obj)
|
||||
{
|
||||
@@ -850,13 +842,14 @@ namespace Barotrauma.Networking
|
||||
disconnectReason == DisconnectReason.ExcessiveDesyncOldEvent ||
|
||||
disconnectReason == DisconnectReason.ExcessiveDesyncRemovedEvent ||
|
||||
disconnectReason == DisconnectReason.SyncTimeout;
|
||||
|
||||
|
||||
if (allowReconnect &&
|
||||
(disconnectReason == DisconnectReason.Unknown || eventSyncError))
|
||||
{
|
||||
if (eventSyncError)
|
||||
{
|
||||
GameMain.NetLobbyScreen.Select();
|
||||
GameMain.GameSession?.EndRound("");
|
||||
gameStarted = false;
|
||||
myCharacter = null;
|
||||
}
|
||||
@@ -1244,6 +1237,8 @@ namespace Barotrauma.Networking
|
||||
mirrorLevel: campaign.Map.CurrentLocation != campaign.Map.SelectedConnection.Locations[0]);
|
||||
}
|
||||
|
||||
GameMain.GameSession.Mission?.ClientReadInitial(inc);
|
||||
|
||||
if (GameMain.GameSession.Submarine.IsFileCorrupted)
|
||||
{
|
||||
DebugConsole.ThrowError($"Failed to start a round. Could not load the submarine \"{GameMain.GameSession.Submarine.Name}\".");
|
||||
@@ -1635,9 +1630,9 @@ namespace Barotrauma.Networking
|
||||
break;
|
||||
case ServerNetObject.ENTITY_POSITION:
|
||||
UInt16 id = inc.ReadUInt16();
|
||||
byte msgLength = inc.ReadByte();
|
||||
uint msgLength = inc.ReadVariableUInt32();
|
||||
|
||||
int msgEndPos = inc.BitPosition + msgLength * 8;
|
||||
int msgEndPos = (int)(inc.BitPosition + msgLength * 8);
|
||||
|
||||
var entity = Entity.FindEntityByID(id) as IServerSerializable;
|
||||
if (entity != null)
|
||||
@@ -2367,9 +2362,14 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
textBox.Deselect();
|
||||
}
|
||||
|
||||
textBox.Text = "";
|
||||
|
||||
if (ChatBox.CloseAfterMessageSent)
|
||||
{
|
||||
ChatBox.ToggleOpen = false;
|
||||
ChatBox.CloseAfterMessageSent = false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2443,13 +2443,16 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
msgBox.AddToGUIUpdateList();
|
||||
ChatBox.GUIFrame.Flash(Color.DarkGreen, 0.5f);
|
||||
ChatBox.CloseAfterMessageSent = !ChatBox.ToggleOpen;
|
||||
ChatBox.ToggleOpen = true;
|
||||
ChatBox.CloseAfterMessageSent = !ChatBox.ToggleOpen;
|
||||
}
|
||||
|
||||
if (radioKeyHit)
|
||||
{
|
||||
msgBox.AddToGUIUpdateList();
|
||||
ChatBox.GUIFrame.Flash(Color.YellowGreen, 0.5f);
|
||||
ChatBox.CloseAfterMessageSent = !ChatBox.ToggleOpen;
|
||||
ChatBox.ToggleOpen = true;
|
||||
if (!msgBox.Text.StartsWith(ChatBox.RadioChatString))
|
||||
{
|
||||
|
||||
@@ -195,7 +195,10 @@ namespace Barotrauma.Networking
|
||||
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.025f), content.RectTransform), style: null);
|
||||
|
||||
var serverMsg = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.3f), content.RectTransform)) { ScrollBarVisible = true };
|
||||
var msgText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), serverMsg.Content.RectTransform), ServerMessage, font: GUI.SmallFont, wrap: true) { CanBeFocused = true };
|
||||
var msgText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), serverMsg.Content.RectTransform), ServerMessage, font: GUI.SmallFont, wrap: true)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
serverMsg.Content.RectTransform.SizeChanged += () => { msgText.CalculateHeightFromText(); };
|
||||
msgText.RectTransform.SizeChanged += () => { serverMsg.UpdateScrollBarSize(); };
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Barotrauma.Extensions;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -35,12 +36,13 @@ namespace Barotrauma
|
||||
|
||||
GameMain.NetLobbyScreen.Frame.FindChild("modevotes", true).Visible = value;
|
||||
|
||||
//gray out modes that can't be voted
|
||||
foreach (GUITextBlock comp in GameMain.NetLobbyScreen.ModeList.Content.Children)
|
||||
// Disable modes that cannot be voted on
|
||||
foreach (var guiComponent in GameMain.NetLobbyScreen.ModeList.Content.Children)
|
||||
{
|
||||
comp.TextColor =
|
||||
new Color(comp.TextColor.R, comp.TextColor.G, comp.TextColor.B,
|
||||
!allowModeVoting || ((GameModePreset)comp.UserData).Votable ? (byte)255 : (byte)100);
|
||||
if (guiComponent is GUIFrame frame)
|
||||
{
|
||||
frame.CanBeFocused = !allowModeVoting || ((GameModePreset) frame.UserData).Votable;
|
||||
}
|
||||
}
|
||||
|
||||
UpdateVoteTexts(null, VoteType.Mode);
|
||||
|
||||
@@ -234,7 +234,7 @@ namespace Barotrauma
|
||||
!ItemPrefab.Prefabs.Any(ep => ep.Category.HasFlag(c) && ep.CanBeBought));
|
||||
foreach (MapEntityCategory category in itemCategories)
|
||||
{
|
||||
var categoryButton = new GUIButton(new RectTransform(new Point(categoryButtonContainer.Rect.Width), categoryButtonContainer.RectTransform),
|
||||
var categoryButton = new GUIButton(new RectTransform(new Point(categoryButtonContainer.Rect.Width, categoryButtonContainer.Rect.Width), categoryButtonContainer.RectTransform),
|
||||
"", style: "ItemCategory" + category.ToString())
|
||||
{
|
||||
UserData = category,
|
||||
@@ -253,7 +253,14 @@ namespace Barotrauma
|
||||
};
|
||||
itemCategoryButtons.Add(categoryButton);
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(0.9f, 0.25f), categoryButton.RectTransform, Anchor.BottomCenter) { RelativeOffset = new Vector2(0.0f, 0.02f) },
|
||||
categoryButton.RectTransform.SizeChanged += () =>
|
||||
{
|
||||
var sprite = categoryButton.Frame.sprites[GUIComponent.ComponentState.None].First();
|
||||
categoryButton.RectTransform.NonScaledSize =
|
||||
new Point(categoryButton.Rect.Width, (int)(categoryButton.Rect.Width * ((float)sprite.Sprite.SourceRect.Height / sprite.Sprite.SourceRect.Width)));
|
||||
};
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(0.95f, 0.256f), categoryButton.RectTransform, Anchor.BottomCenter) { RelativeOffset = new Vector2(0.0f, 0.02f) },
|
||||
TextManager.Get("MapEntityCategory." + category), textAlignment: Alignment.Center, textColor: categoryButton.TextColor)
|
||||
{
|
||||
Padding = Vector4.Zero,
|
||||
@@ -262,7 +269,7 @@ namespace Barotrauma
|
||||
HoverColor = Color.Transparent,
|
||||
PressedColor = Color.Transparent,
|
||||
SelectedColor = Color.Transparent,
|
||||
CanBeFocused = false
|
||||
CanBeFocused = true
|
||||
};
|
||||
}
|
||||
FillStoreItemList();
|
||||
@@ -715,11 +722,12 @@ namespace Barotrauma
|
||||
for (int i = 0; i < availableMissions.Count; i++)
|
||||
{
|
||||
var mission = availableMissions[i];
|
||||
var tickBox = new GUITickBox(new RectTransform(new Vector2(0.1f, 0.1f), missionContent.RectTransform),
|
||||
var tickBox = new GUITickBox(new RectTransform(new Vector2(0.65f, 0.1f), missionContent.RectTransform),
|
||||
mission?.Name ?? TextManager.Get("NoMission"), style: "GUIRadioButton")
|
||||
{
|
||||
Enabled = GameMain.Client == null || GameMain.Client.HasPermission(Networking.ClientPermissions.ManageCampaign)
|
||||
};
|
||||
tickBox.TextBlock.Wrap = true;
|
||||
missionTickBoxes.Add(tickBox);
|
||||
missionRadioButtonGroup.AddRadioButton(i, tickBox);
|
||||
}
|
||||
@@ -833,7 +841,7 @@ namespace Barotrauma
|
||||
var content = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 1.0f), frame.RectTransform, Anchor.Center),
|
||||
isHorizontal: true, childAnchor: Anchor.CenterLeft)
|
||||
{
|
||||
RelativeSpacing = 0.02f,
|
||||
AbsoluteSpacing = (int)(5 * GUI.Scale),
|
||||
Stretch = true
|
||||
};
|
||||
|
||||
@@ -874,8 +882,11 @@ namespace Barotrauma
|
||||
UserData = pi,
|
||||
IntValue = pi.Quantity
|
||||
};
|
||||
amountInput.TextBox.OnSelected += (sender, key) => { suppressBuySell = true; };
|
||||
amountInput.TextBox.OnDeselected += (sender, key) => { suppressBuySell = false; amountInput.OnValueChanged?.Invoke(amountInput); };
|
||||
amountInput.OnValueChanged += (numberInput) =>
|
||||
{
|
||||
if (suppressBuySell) { return; }
|
||||
PurchasedItem purchasedItem = numberInput.UserData as PurchasedItem;
|
||||
|
||||
//Attempting to buy
|
||||
@@ -889,7 +900,6 @@ namespace Barotrauma
|
||||
{
|
||||
BuyItem(numberInput, purchasedItem);
|
||||
}
|
||||
numberInput.IntValue = purchasedItem.Quantity;
|
||||
}
|
||||
//Attempting to sell
|
||||
else
|
||||
@@ -901,14 +911,15 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
};
|
||||
frame.HoverColor = frame.SelectedColor = Color.Transparent;
|
||||
}
|
||||
listBox.RecalculateChildren();
|
||||
content.Recalculate();
|
||||
content.RectTransform.RecalculateChildren(true, true);
|
||||
amountInput?.LayoutGroup.Recalculate();
|
||||
textBlock.Text = ToolBox.LimitString(textBlock.Text, textBlock.Font, textBlock.Rect.Width);
|
||||
/*content.RectTransform.IsFixedSize = true;
|
||||
content.RectTransform.Children.ForEach(c => c.IsFixedSize = true);*/
|
||||
//content.RectTransform.IsFixedSize = true;
|
||||
content.RectTransform.Children.ForEach(c => c.IsFixedSize = true);
|
||||
|
||||
return frame;
|
||||
}
|
||||
@@ -946,21 +957,33 @@ namespace Barotrauma
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool suppressBuySell;
|
||||
|
||||
private void RefreshMyItems()
|
||||
{
|
||||
HashSet<GUIComponent> existingItemFrames = new HashSet<GUIComponent>();
|
||||
foreach (PurchasedItem pi in Campaign.CargoManager.PurchasedItems)
|
||||
{
|
||||
var itemFrame = myItemList.Content.GetChildByUserData(pi);
|
||||
var itemFrame = myItemList.Content.Children.FirstOrDefault(c =>
|
||||
c.UserData is PurchasedItem pi2 && pi.ItemPrefab == pi2.ItemPrefab);
|
||||
if (itemFrame == null)
|
||||
{
|
||||
var priceInfo = pi.ItemPrefab.GetPrice(Campaign.Map.CurrentLocation);
|
||||
if (priceInfo == null) { continue; }
|
||||
itemFrame = CreateItemFrame(pi, priceInfo, myItemList);
|
||||
itemFrame.Flash(GUI.Style.Green);
|
||||
itemFrame.Flash(GUI.Style.Green);
|
||||
}
|
||||
else
|
||||
{
|
||||
itemFrame.UserData = itemFrame.GetChild(0).GetChild<GUINumberInput>().UserData = pi;
|
||||
}
|
||||
itemFrame.GetChild(0).GetChild<GUINumberInput>().IntValue = pi.Quantity;
|
||||
existingItemFrames.Add(itemFrame);
|
||||
|
||||
suppressBuySell = true;
|
||||
var numInput = itemFrame.GetChild(0).GetChild<GUINumberInput>();
|
||||
if (numInput.IntValue != pi.Quantity) { itemFrame.Flash(GUI.Style.Green); }
|
||||
numInput.IntValue = (itemFrame.UserData as PurchasedItem).Quantity = pi.Quantity;
|
||||
suppressBuySell = false;
|
||||
}
|
||||
|
||||
var removedItemFrames = myItemList.Content.Children.Except(existingItemFrames).ToList();
|
||||
|
||||
@@ -204,7 +204,7 @@ namespace Barotrauma
|
||||
Submarine.DrawBack(spriteBatch, false, e => !(e is Structure) || e.SpriteDepth < 0.9f);
|
||||
foreach (Character c in Character.CharacterList)
|
||||
{
|
||||
if (c.AnimController.Limbs.Any(l => l.DeformSprite != null) || !c.IsVisible) { continue; }
|
||||
if (!c.IsVisible || c.AnimController.Limbs.Any(l => l.DeformSprite != null)) { continue; }
|
||||
c.Draw(spriteBatch, Cam);
|
||||
}
|
||||
spriteBatch.End();
|
||||
|
||||
@@ -1111,7 +1111,7 @@ namespace Barotrauma
|
||||
Alignment textAlignment = Alignment.CenterLeft;
|
||||
Vector2 textFieldSize = new Vector2(0.5f, 1.0f);
|
||||
Vector2 tickBoxSize = new Vector2(0.4f, 0.07f);
|
||||
var content = new GUILayoutGroup(new RectTransform(new Vector2(0.6f, 0.9f), menuTabs[(int)Tab.HostServer].RectTransform, Anchor.Center), childAnchor: Anchor.TopCenter)
|
||||
var content = new GUILayoutGroup(new RectTransform(new Vector2(0.7f, 0.9f), menuTabs[(int)Tab.HostServer].RectTransform, Anchor.Center), childAnchor: Anchor.TopCenter)
|
||||
{
|
||||
RelativeSpacing = 0.02f,
|
||||
Stretch = true
|
||||
@@ -1122,7 +1122,7 @@ namespace Barotrauma
|
||||
|
||||
//play style -----------------------------------------------------
|
||||
|
||||
var playstyleContainer = new GUIFrame(new RectTransform(new Vector2(1.5f, 0.1f), parent.RectTransform), style: null, color: Color.Black);
|
||||
var playstyleContainer = new GUIFrame(new RectTransform(new Vector2(1.35f, 0.1f), parent.RectTransform), style: null, color: Color.Black);
|
||||
|
||||
playstyleBanner = new GUIImage(new RectTransform(new Vector2(1.0f, 0.1f), playstyleContainer.RectTransform),
|
||||
ServerListScreen.PlayStyleBanners[0], scaleToFit: true)
|
||||
@@ -1263,7 +1263,7 @@ namespace Barotrauma
|
||||
|
||||
var tickboxAreaLower = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, tickBoxSize.Y), parent.RectTransform), isHorizontal: true);
|
||||
|
||||
karmaEnabledBox = new GUITickBox(new RectTransform(new Vector2(0.4f, 1.0f), tickboxAreaLower.RectTransform), TextManager.Get("ServerSettingsUseKarma"))
|
||||
karmaEnabledBox = new GUITickBox(new RectTransform(new Vector2(0.5f, 1.0f), tickboxAreaLower.RectTransform), TextManager.Get("ServerSettingsUseKarma"))
|
||||
{
|
||||
ToolTip = TextManager.Get("karmaexplanation"),
|
||||
OnSelected = (tb) =>
|
||||
@@ -1272,7 +1272,7 @@ namespace Barotrauma
|
||||
return true;
|
||||
}
|
||||
};
|
||||
karmaPresetDD = new GUIDropDown(new RectTransform(new Vector2(0.6f, 1.0f), tickboxAreaLower.RectTransform))
|
||||
karmaPresetDD = new GUIDropDown(new RectTransform(new Vector2(0.5f, 1.0f), tickboxAreaLower.RectTransform))
|
||||
{
|
||||
ButtonEnabled = false,
|
||||
Enabled = false
|
||||
|
||||
@@ -24,6 +24,8 @@ namespace Barotrauma
|
||||
private GUIListBox chatBox, playerList;
|
||||
private GUIListBox serverLogBox, serverLogFilterTicks;
|
||||
|
||||
private GUIComponent jobVariantTooltip;
|
||||
|
||||
private GUITextBox chatInput;
|
||||
private GUITextBox serverLogFilter;
|
||||
public GUITextBox ChatInput
|
||||
@@ -419,14 +421,14 @@ namespace Barotrauma
|
||||
RelativeSpacing = 0.05f
|
||||
};
|
||||
FileTransferTitle = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), fileTransferContent.RectTransform), "", font: GUI.SmallFont);
|
||||
var fileTransferBottom = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.5f), fileTransferContent.RectTransform), isHorizontal: true)
|
||||
var fileTransferBottom = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.5f), fileTransferContent.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft)
|
||||
{
|
||||
Stretch = true
|
||||
};
|
||||
FileTransferProgressBar = new GUIProgressBar(new RectTransform(new Vector2(0.6f, 1.0f), fileTransferBottom.RectTransform), 0.0f, Color.DarkGreen);
|
||||
FileTransferProgressText = new GUITextBlock(new RectTransform(Vector2.One, FileTransferProgressBar.RectTransform), "",
|
||||
font: GUI.SmallFont, textAlignment: Alignment.CenterLeft);
|
||||
new GUIButton(new RectTransform(new Vector2(0.4f, 1.0f), fileTransferBottom.RectTransform), TextManager.Get("cancel"))
|
||||
new GUIButton(new RectTransform(new Vector2(0.4f, 1.0f), fileTransferBottom.RectTransform), TextManager.Get("cancel"), style: "GUIButtonSmall")
|
||||
{
|
||||
OnClicked = (btn, userdata) =>
|
||||
{
|
||||
@@ -458,7 +460,7 @@ namespace Barotrauma
|
||||
myCharacterFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.5f), sideBar.RectTransform));
|
||||
playerInfoContainer = new GUIFrame(new RectTransform(new Vector2(0.9f, 0.9f), myCharacterFrame.RectTransform, Anchor.Center), style: null);
|
||||
|
||||
spectateBox = new GUITickBox(new RectTransform(new Vector2(0.06f, 0.06f), myCharacterFrame.RectTransform) { RelativeOffset = new Vector2(0.05f, 0.05f) },
|
||||
spectateBox = new GUITickBox(new RectTransform(new Vector2(0.4f, 0.06f), myCharacterFrame.RectTransform) { RelativeOffset = new Vector2(0.05f, 0.05f) },
|
||||
TextManager.Get("spectatebutton"))
|
||||
{
|
||||
Selected = false,
|
||||
@@ -1477,6 +1479,39 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateJobVariantTooltip(JobPrefab jobPrefab, int variant, GUIComponent parentSlot)
|
||||
{
|
||||
jobVariantTooltip = new GUIFrame(new RectTransform(new Point((int)(500 * GUI.Scale), (int)(200 * GUI.Scale)), GUI.Canvas, pivot: Pivot.TopRight),
|
||||
style: "GUIToolTip")
|
||||
{
|
||||
UserData = new Pair<JobPrefab, int>(jobPrefab, variant)
|
||||
};
|
||||
jobVariantTooltip.RectTransform.AbsoluteOffset = new Point(parentSlot.Rect.Right, parentSlot.Rect.Bottom);
|
||||
|
||||
var content = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.95f), jobVariantTooltip.RectTransform, Anchor.Center))
|
||||
{
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.02f
|
||||
};
|
||||
|
||||
string name =
|
||||
TextManager.Get("jobname." + jobPrefab.Identifier + (variant + 1), returnNull: true) ??
|
||||
jobPrefab.Name;
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), content.RectTransform), name, font: GUI.SubHeadingFont);
|
||||
|
||||
string description =
|
||||
TextManager.Get("jobdescription." + jobPrefab.Identifier + (variant + 1), returnNull: true) ??
|
||||
TextManager.Get("jobdescription." + jobPrefab.Identifier, returnNull: true) ??
|
||||
"";
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), content.RectTransform), description, wrap: true, font: GUI.SmallFont);
|
||||
new GUICustomComponent(new RectTransform(new Vector2(1.0f, 0.3f), content.RectTransform, Anchor.BottomLeft),
|
||||
onDraw: (sb, component) => { DrawJobVariantItems(sb, component, new Pair<JobPrefab, int>(jobPrefab, variant)); });
|
||||
|
||||
jobVariantTooltip.RectTransform.MinSize = new Point(0, content.RectTransform.Children.Sum(c => c.Rect.Height));
|
||||
}
|
||||
|
||||
public bool ToggleSpectate(GUITickBox tickBox)
|
||||
{
|
||||
SetSpectate(tickBox.Selected);
|
||||
@@ -2210,6 +2245,22 @@ namespace Barotrauma
|
||||
JobList.Deselect();
|
||||
JobSelectionFrame.Visible = false;
|
||||
}
|
||||
|
||||
if (GUI.MouseOn?.UserData is Pair<JobPrefab, int> jobPrefab && GUI.MouseOn.Style?.Name == "JobVariantButton")
|
||||
{
|
||||
var prevVisibleVariant = jobVariantTooltip?.UserData as Pair<JobPrefab, int>;
|
||||
if (jobVariantTooltip == null || prevVisibleVariant.First != jobPrefab.First || prevVisibleVariant.Second != jobPrefab.Second)
|
||||
{
|
||||
CreateJobVariantTooltip(jobPrefab.First, jobPrefab.Second, GUI.MouseOn.Parent);
|
||||
}
|
||||
}
|
||||
if (jobVariantTooltip != null)
|
||||
{
|
||||
jobVariantTooltip?.AddToGUIUpdateList();
|
||||
Rectangle mouseRect = jobVariantTooltip.MouseRect;
|
||||
mouseRect.Inflate(60 * GUI.Scale, 60 * GUI.Scale);
|
||||
if (!mouseRect.Contains(PlayerInput.MousePosition)) { jobVariantTooltip = null; }
|
||||
}
|
||||
}
|
||||
public override void Draw(double deltaTime, GraphicsDevice graphics, SpriteBatch spriteBatch)
|
||||
{
|
||||
@@ -2251,6 +2302,52 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawJobVariantItems(SpriteBatch spriteBatch, GUICustomComponent component, Pair<JobPrefab, int> jobPrefab)
|
||||
{
|
||||
var itemIdentifiers = jobPrefab.First.ItemIdentifiers[jobPrefab.Second]
|
||||
.Distinct()
|
||||
.Where(id => jobPrefab.First.ShowItemPreview[jobPrefab.Second][id]);
|
||||
|
||||
Point slotSize = new Point(component.Rect.Height);
|
||||
int spacing = (int)(5 * GUI.Scale);
|
||||
int slotCount = itemIdentifiers.Count();
|
||||
|
||||
float totalWidth = slotSize.X * slotCount + spacing * (slotCount - 1);
|
||||
if (totalWidth > component.Rect.Width)
|
||||
{
|
||||
slotSize = slotSize.Multiply(component.Rect.Width / totalWidth);
|
||||
}
|
||||
int i = 0;
|
||||
foreach (string itemIdentifier in itemIdentifiers)
|
||||
{
|
||||
if (!(MapEntityPrefab.Find(null, identifier: itemIdentifier, showErrorMessages: false) is ItemPrefab itemPrefab)) { continue; }
|
||||
|
||||
Vector2 slotPos = new Vector2(component.Rect.X + (slotSize.X + spacing) * i, component.Rect.Center.Y - slotSize.Y / 2);
|
||||
|
||||
Rectangle slotRect = new Rectangle(slotPos.ToPoint(), slotSize);
|
||||
Inventory.SlotSpriteSmall.Draw(spriteBatch, slotPos,
|
||||
scale: slotSize.X / (float)Inventory.SlotSpriteSmall.SourceRect.Width,
|
||||
color: slotRect.Contains(PlayerInput.MousePosition) ? Color.White : Color.White * 0.6f);
|
||||
|
||||
Sprite icon = itemPrefab.InventoryIcon ?? itemPrefab.sprite;
|
||||
float iconScale = Math.Min(Math.Min(slotSize.X / icon.size.X, slotSize.Y / icon.size.Y), 2.0f) * 0.9f;
|
||||
icon.Draw(spriteBatch, slotPos + slotSize.ToVector2() * 0.5f, scale: iconScale);
|
||||
|
||||
int count = jobPrefab.First.ItemIdentifiers[jobPrefab.Second].Count(id => id == itemIdentifier);
|
||||
if (count > 1)
|
||||
{
|
||||
string itemCountText = "x" + count;
|
||||
GUI.Font.DrawString(spriteBatch, itemCountText, slotPos + slotSize.ToVector2() - GUI.Font.MeasureString(itemCountText) - Vector2.UnitX * 5, Color.White);
|
||||
}
|
||||
|
||||
if (slotRect.Contains(PlayerInput.MousePosition))
|
||||
{
|
||||
GUIComponent.DrawToolTip(spriteBatch, itemPrefab.Name+'\n'+itemPrefab.Description, slotRect);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
public void NewChatMessage(ChatMessage message)
|
||||
{
|
||||
float prevSize = chatBox.BarSize;
|
||||
@@ -3012,8 +3109,10 @@ namespace Barotrauma
|
||||
(variantIndex + 1).ToString(), style: "JobVariantButton")
|
||||
{
|
||||
Selected = jobPrefab.Second == variantIndex,
|
||||
//ToolTip = TextManager.Get("jobdescription." + jobPrefab.First.Identifier + (variantIndex + 1), returnNull: true) ?? "",
|
||||
UserData = new Pair<JobPrefab, int>(jobPrefab.First, variantIndex),
|
||||
};
|
||||
|
||||
return btn;
|
||||
}
|
||||
|
||||
|
||||
@@ -1102,6 +1102,8 @@ namespace Barotrauma
|
||||
return true;
|
||||
};
|
||||
|
||||
nameBox.Text = subNameLabel?.Text ?? "";
|
||||
|
||||
submarineNameCharacterCount.Text = nameBox.Text.Length + " / " + submarineNameLimit;
|
||||
|
||||
var descriptionHeaderGroup = new GUILayoutGroup(new RectTransform(new Vector2(.975f, 0.03f), leftColumn.RectTransform), true);
|
||||
|
||||
@@ -66,7 +66,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (sound?.Sound == null)
|
||||
{
|
||||
string errorMsg = $"Error in StatusEffect.ApplyProjSpecific1 (sound \"{sound.Filename ?? "unknown"}\" was null)\n" + Environment.StackTrace;
|
||||
string errorMsg = $"Error in StatusEffect.ApplyProjSpecific1 (sound \"{sound?.Filename ?? "unknown"}\" was null)\n" + Environment.StackTrace;
|
||||
GameAnalyticsManager.AddErrorEventOnce("StatusEffect.ApplyProjSpecific:SoundNull1" + Environment.StackTrace, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||
return;
|
||||
}
|
||||
@@ -92,7 +92,7 @@ namespace Barotrauma
|
||||
var selectedSound = sounds[selectedSoundIndex];
|
||||
if (selectedSound?.Sound == null)
|
||||
{
|
||||
string errorMsg = $"Error in StatusEffect.ApplyProjSpecific2 (sound \"{selectedSound.Filename ?? "unknown"}\" was null)\n" + Environment.StackTrace;
|
||||
string errorMsg = $"Error in StatusEffect.ApplyProjSpecific2 (sound \"{selectedSound?.Filename ?? "unknown"}\" was null)\n" + Environment.StackTrace;
|
||||
GameAnalyticsManager.AddErrorEventOnce("StatusEffect.ApplyProjSpecific:SoundNull2" + Environment.StackTrace, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<RootNamespace>Barotrauma</RootNamespace>
|
||||
<Authors>FakeFish, Undertow Games</Authors>
|
||||
<Product>Barotrauma</Product>
|
||||
<Version>0.9.703.0</Version>
|
||||
<Version>0.9.704.0</Version>
|
||||
<Copyright>Copyright © FakeFish 2018-2020</Copyright>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<AssemblyName>Barotrauma</AssemblyName>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<RootNamespace>Barotrauma</RootNamespace>
|
||||
<Authors>FakeFish, Undertow Games</Authors>
|
||||
<Product>Barotrauma</Product>
|
||||
<Version>0.9.702.0</Version>
|
||||
<Version>0.9.704.0</Version>
|
||||
<Copyright>Copyright © FakeFish 2018-2020</Copyright>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<AssemblyName>Barotrauma</AssemblyName>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<RootNamespace>Barotrauma</RootNamespace>
|
||||
<Authors>FakeFish, Undertow Games</Authors>
|
||||
<Product>Barotrauma</Product>
|
||||
<Version>0.9.703.0</Version>
|
||||
<Version>0.9.704.0</Version>
|
||||
<Copyright>Copyright © FakeFish 2018-2020</Copyright>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<AssemblyName>Barotrauma</AssemblyName>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<RootNamespace>Barotrauma</RootNamespace>
|
||||
<Authors>FakeFish, Undertow Games</Authors>
|
||||
<Product>Barotrauma Dedicated Server</Product>
|
||||
<Version>0.9.703.0</Version>
|
||||
<Version>0.9.704.0</Version>
|
||||
<Copyright>Copyright © FakeFish 2018-2020</Copyright>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<AssemblyName>DedicatedServer</AssemblyName>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<RootNamespace>Barotrauma</RootNamespace>
|
||||
<Authors>FakeFish, Undertow Games</Authors>
|
||||
<Product>Barotrauma Dedicated Server</Product>
|
||||
<Version>0.9.703.0</Version>
|
||||
<Version>0.9.704.0</Version>
|
||||
<Copyright>Copyright © FakeFish 2018-2020</Copyright>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<AssemblyName>DedicatedServer</AssemblyName>
|
||||
|
||||
@@ -394,7 +394,7 @@ namespace Barotrauma
|
||||
|
||||
tempBuffer.WritePadBits();
|
||||
|
||||
msg.Write((byte)tempBuffer.LengthBytes);
|
||||
msg.WriteVariableUInt32((uint)tempBuffer.LengthBytes);
|
||||
msg.Write(tempBuffer.Buffer, 0, tempBuffer.LengthBytes);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -439,7 +439,7 @@ namespace Barotrauma
|
||||
client.GivePermission(permission);
|
||||
GameMain.Server.UpdateClientPermissions(client);
|
||||
NewMessage("Granted " + perm + " permissions to " + client.Name + ".", Color.White);
|
||||
}, args, 2);
|
||||
}, args, 1);
|
||||
});
|
||||
|
||||
AssignOnExecute("revokeperm", (string[] args) =>
|
||||
@@ -474,7 +474,7 @@ namespace Barotrauma
|
||||
client.RemovePermission(permission);
|
||||
GameMain.Server.UpdateClientPermissions(client);
|
||||
NewMessage("Revoked " + perm + " permissions from " + client.Name + ".", Color.White);
|
||||
}, args, 2);
|
||||
}, args, 1);
|
||||
});
|
||||
|
||||
AssignOnExecute("giverank", (string[] args) =>
|
||||
@@ -511,7 +511,7 @@ namespace Barotrauma
|
||||
client.SetPermissions(preset.Permissions, preset.PermittedCommands);
|
||||
GameMain.Server.UpdateClientPermissions(client);
|
||||
NewMessage("Assigned the rank \"" + preset.Name + "\" to " + client.Name + ".", Color.White);
|
||||
}, args, 2);
|
||||
}, args, 1);
|
||||
});
|
||||
|
||||
AssignOnExecute("givecommandperm", (string[] args) =>
|
||||
@@ -552,7 +552,7 @@ namespace Barotrauma
|
||||
client.SetPermissions(client.Permissions, client.PermittedConsoleCommands.Union(grantedCommands).Distinct().ToList());
|
||||
GameMain.Server.UpdateClientPermissions(client);
|
||||
NewMessage("Gave the client \"" + client.Name + "\" the permission to use console commands " + string.Join(", ", grantedCommands.Select(c => c.names[0])) + ".", Color.White);
|
||||
}, args, 2);
|
||||
}, args, 1);
|
||||
});
|
||||
|
||||
AssignOnExecute("revokecommandperm", (string[] args) =>
|
||||
@@ -592,7 +592,7 @@ namespace Barotrauma
|
||||
client.SetPermissions(client.Permissions, client.PermittedConsoleCommands.Except(revokedCommands).ToList());
|
||||
GameMain.Server.UpdateClientPermissions(client);
|
||||
NewMessage("Revoked \"" + client.Name + "\"'s permission to use the console commands " + string.Join(", ", revokedCommands.Select(c => c.names[0])) + ".", Color.White);
|
||||
}, args, 2);
|
||||
}, args, 1);
|
||||
});
|
||||
|
||||
AssignOnExecute("showperm", (string[] args) =>
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
using Barotrauma.Networking;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
partial class CargoMission : Mission
|
||||
{
|
||||
public override void ServerWriteInitial(IWriteMessage msg, Client c)
|
||||
{
|
||||
msg.Write((ushort)items.Count);
|
||||
foreach (Item item in items)
|
||||
{
|
||||
item.WriteSpawnData(msg, item.ID);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -109,5 +109,10 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void ServerWriteInitial(IWriteMessage msg, Client c)
|
||||
{
|
||||
//do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,5 +13,7 @@ namespace Barotrauma
|
||||
|
||||
GameServer.Log(TextManager.Get("MissionInfo") + ": " + header + " - " + message, ServerLog.MessageType.ServerMessage);
|
||||
}
|
||||
|
||||
public abstract void ServerWriteInitial(IWriteMessage msg, Client c);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using Barotrauma.Networking;
|
||||
using System;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
partial class MonsterMission : Mission
|
||||
{
|
||||
public override void ServerWriteInitial(IWriteMessage msg, Client c)
|
||||
{
|
||||
if (monsters.Count == 0 && monsterFiles.Count > 0)
|
||||
{
|
||||
throw new InvalidOperationException("Server attempted to write monster mission data when no monsters had been spawned.");
|
||||
}
|
||||
|
||||
msg.Write((byte)monsters.Count);
|
||||
foreach (Character monster in monsters)
|
||||
{
|
||||
monster.WriteSpawnData(msg, monster.ID);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using Barotrauma.Networking;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
partial class SalvageMission : Mission
|
||||
{
|
||||
public override void ServerWriteInitial(IWriteMessage msg, Client c)
|
||||
{
|
||||
item.WriteSpawnData(msg, item.ID);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -273,10 +273,8 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
Map.SelectLocation(selectedLocIndex == UInt16.MaxValue ? -1 : selectedLocIndex);
|
||||
if (Map.SelectedConnection != null)
|
||||
{
|
||||
Map.SelectMission(selectedMissionIndex);
|
||||
}
|
||||
if (Map.SelectedLocation == null) { Map.SelectRandomLocation(preferUndiscovered: true); }
|
||||
if (Map.SelectedConnection != null) { Map.SelectMission(selectedMissionIndex); }
|
||||
|
||||
List<PurchasedItem> currentItems = new List<PurchasedItem>(CargoManager.PurchasedItems);
|
||||
foreach (PurchasedItem pi in currentItems)
|
||||
|
||||
@@ -345,7 +345,7 @@ namespace Barotrauma
|
||||
|
||||
IWriteMessage tempBuffer = new WriteOnlyMessage();
|
||||
body.ServerWrite(tempBuffer, c, extraData);
|
||||
msg.Write((byte)tempBuffer.LengthBytes);
|
||||
msg.WriteVariableUInt32((uint)tempBuffer.LengthBytes);
|
||||
msg.Write(tempBuffer.Buffer, 0, tempBuffer.LengthBytes);
|
||||
msg.WritePadBits();
|
||||
}
|
||||
|
||||
@@ -1783,6 +1783,17 @@ namespace Barotrauma.Networking
|
||||
|
||||
if (campaign != null)
|
||||
{
|
||||
if (campaign.Map == null)
|
||||
{
|
||||
throw new Exception("Campaign map was null.");
|
||||
}
|
||||
if (campaign.Map.SelectedConnection == null)
|
||||
{
|
||||
//this should not happen, there should always be some destination selected
|
||||
DebugConsole.ThrowError("No connection between locations was selected when starting the round. Choosing a random location...");
|
||||
campaign.Map.SelectRandomLocation(preferUndiscovered: true);
|
||||
}
|
||||
|
||||
GameMain.GameSession.StartRound(campaign.Map.SelectedConnection.Level,
|
||||
reloadSub: true,
|
||||
loadSecondSub: teamCount > 1,
|
||||
@@ -2007,6 +2018,8 @@ namespace Barotrauma.Networking
|
||||
|
||||
serverSettings.WriteMonsterEnabled(msg);
|
||||
|
||||
GameMain.GameSession.Mission?.ServerWriteInitial(msg, client);
|
||||
|
||||
serverPeer.Send(msg, client.Connection, DeliveryMethod.Reliable);
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,11 @@ namespace Barotrauma.Networking
|
||||
get { return createTime; }
|
||||
}
|
||||
|
||||
public void ResetCreateTime()
|
||||
{
|
||||
createTime = Timing.TotalTime;
|
||||
}
|
||||
|
||||
public ServerEntityEvent(IServerSerializable serializableEntity, UInt16 id)
|
||||
: base(serializableEntity, id)
|
||||
{
|
||||
@@ -223,6 +228,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
lastWarningTime = Timing.TotalTime;
|
||||
GameServer.Log("WARNING: ServerEntityEventManager is lagging behind! Last sent id: " + lastSentToAnyone.ToString() + ", latest create id: " + ID.ToString(), ServerLog.MessageType.ServerMessage);
|
||||
events.ForEach(e => e.ResetCreateTime());
|
||||
//TODO: reset clients if this happens, maybe do it if a majority are behind rather than all of them?
|
||||
}
|
||||
|
||||
|
||||
@@ -175,6 +175,7 @@ namespace Barotrauma.Networking
|
||||
GameMain.NetworkMember?.KarmaManager?.SaveCustomPreset();
|
||||
GameMain.NetworkMember?.KarmaManager?.Save();
|
||||
}
|
||||
SaveSettings();
|
||||
GameMain.NetLobbyScreen.LastUpdateID++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<RootNamespace>Barotrauma</RootNamespace>
|
||||
<Authors>FakeFish, Undertow Games</Authors>
|
||||
<Product>Barotrauma Dedicated Server</Product>
|
||||
<Version>0.9.703.0</Version>
|
||||
<Version>0.9.704.0</Version>
|
||||
<Copyright>Copyright © FakeFish 2018-2020</Copyright>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<AssemblyName>DedicatedServer</AssemblyName>
|
||||
|
||||
@@ -142,16 +142,8 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public AITarget(Entity e, XElement element) : this(e)
|
||||
public void Reset()
|
||||
{
|
||||
SightRange = element.GetAttributeFloat("sightrange", 0.0f);
|
||||
SoundRange = element.GetAttributeFloat("soundrange", 0.0f);
|
||||
MinSightRange = element.GetAttributeFloat("minsightrange", 0f);
|
||||
MinSoundRange = element.GetAttributeFloat("minsoundrange", 0f);
|
||||
MaxSightRange = element.GetAttributeFloat("maxsightrange", SightRange);
|
||||
MaxSoundRange = element.GetAttributeFloat("maxsoundrange", SoundRange);
|
||||
FadeOutTime = element.GetAttributeFloat("fadeouttime", FadeOutTime);
|
||||
Static = element.GetAttributeBool("static", Static);
|
||||
if (Static)
|
||||
{
|
||||
SightRange = MaxSightRange;
|
||||
@@ -163,7 +155,18 @@ namespace Barotrauma
|
||||
SightRange = MinSightRange;
|
||||
SoundRange = MinSoundRange;
|
||||
}
|
||||
}
|
||||
|
||||
public AITarget(Entity e, XElement element) : this(e)
|
||||
{
|
||||
SightRange = element.GetAttributeFloat("sightrange", 0.0f);
|
||||
SoundRange = element.GetAttributeFloat("soundrange", 0.0f);
|
||||
MinSightRange = element.GetAttributeFloat("minsightrange", 0f);
|
||||
MinSoundRange = element.GetAttributeFloat("minsoundrange", 0f);
|
||||
MaxSightRange = element.GetAttributeFloat("maxsightrange", SightRange);
|
||||
MaxSoundRange = element.GetAttributeFloat("maxsoundrange", SoundRange);
|
||||
FadeOutTime = element.GetAttributeFloat("fadeouttime", FadeOutTime);
|
||||
Static = element.GetAttributeBool("static", Static);
|
||||
SonarDisruption = element.GetAttributeFloat("sonardisruption", 0.0f);
|
||||
SonarLabel = element.GetAttributeString("sonarlabel", "");
|
||||
SonarIconIdentifier = element.GetAttributeString("sonaricon", "");
|
||||
@@ -172,6 +175,7 @@ namespace Barotrauma
|
||||
{
|
||||
Type = t;
|
||||
}
|
||||
Reset();
|
||||
}
|
||||
|
||||
public AITarget(Entity e)
|
||||
|
||||
@@ -270,6 +270,17 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
if (isStateChanged)
|
||||
{
|
||||
if (State == AIState.Idle)
|
||||
{
|
||||
stateResetTimer -= deltaTime;
|
||||
if (stateResetTimer <= 0)
|
||||
{
|
||||
ResetOriginalState();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (targetIgnoreTimer > 0)
|
||||
{
|
||||
targetIgnoreTimer -= deltaTime;
|
||||
@@ -662,7 +673,7 @@ namespace Barotrauma
|
||||
attackSimPos = Character.GetRelativeSimPosition(SelectedAiTarget.Entity);
|
||||
}
|
||||
|
||||
if (CanEnterSubmarine)
|
||||
if (Character.AnimController.CanEnterSubmarine)
|
||||
{
|
||||
//targeting a wall section that can be passed through -> steer manually through the hole
|
||||
if (wallTarget != null && wallTarget.SectionIndex > -1 && CanPassThroughHole(wallTarget.Structure, wallTarget.SectionIndex))
|
||||
@@ -674,21 +685,20 @@ namespace Barotrauma
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Don't think we need this
|
||||
//else if (wallTarget == null && SelectedAiTarget.Entity is Structure wall)
|
||||
//{
|
||||
// for (int i = 0; i < wall.Sections.Length; i++)
|
||||
// {
|
||||
// WallSection section = wall.Sections[i];
|
||||
// if (CanPassThroughHole(wall, i) && section?.gap != null)
|
||||
// {
|
||||
// if (SteerThroughGap(wall, section, section.gap.WorldPosition, deltaTime))
|
||||
// {
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
else if (SelectedAiTarget.Entity is Structure wall)
|
||||
{
|
||||
for (int i = 0; i < wall.Sections.Length; i++)
|
||||
{
|
||||
WallSection section = wall.Sections[i];
|
||||
if (CanPassThroughHole(wall, i) && section?.gap != null)
|
||||
{
|
||||
if (SteerThroughGap(wall, section, section.gap.WorldPosition, deltaTime))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (SelectedAiTarget.Entity is Item i)
|
||||
{
|
||||
var door = i.GetComponent<Door>();
|
||||
@@ -1024,7 +1034,7 @@ namespace Barotrauma
|
||||
var door = pathSteering.CurrentPath.CurrentNode?.ConnectedDoor ?? pathSteering.CurrentPath.NextNode?.ConnectedDoor;
|
||||
if (door != null && !door.IsOpen)
|
||||
{
|
||||
if (SelectedAiTarget != door.Item.AiTarget)
|
||||
if (door.Item.AiTarget != null && SelectedAiTarget != door.Item.AiTarget)
|
||||
{
|
||||
SelectTarget(door.Item.AiTarget, selectedTargetMemory.Priority);
|
||||
return;
|
||||
@@ -1076,15 +1086,15 @@ namespace Barotrauma
|
||||
LatchOntoAI?.DeattachFromBody();
|
||||
Character.AnimController.ReleaseStuckLimbs();
|
||||
Hull targetHull = section.gap?.FlowTargetHull;
|
||||
SelectedAiTarget = targetHull != null ? targetHull.AiTarget : wall.AiTarget;
|
||||
float distance = Vector2.DistanceSquared(Character.WorldPosition, targetWorldPos);
|
||||
float maxDistance = Math.Min(wall.Rect.Width, wall.Rect.Height);
|
||||
if (distance * distance > maxDistance * maxDistance)
|
||||
if (Vector2.DistanceSquared(Character.WorldPosition, targetWorldPos) > maxDistance * maxDistance)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (targetHull != null)
|
||||
{
|
||||
// If already inside, target the hull, else target the wall.
|
||||
SelectedAiTarget = Character.CurrentHull != null ? targetHull.AiTarget : wall.AiTarget;
|
||||
if (wall.IsHorizontal)
|
||||
{
|
||||
targetWorldPos.Y = targetHull.WorldRect.Y - targetHull.Rect.Height / 2;
|
||||
@@ -1094,6 +1104,7 @@ namespace Barotrauma
|
||||
targetWorldPos.X = targetHull.WorldRect.Center.X;
|
||||
}
|
||||
steeringManager.SteeringManual(deltaTime, Vector2.Normalize(targetWorldPos - Character.WorldPosition));
|
||||
SteeringManager.SteeringAvoid(deltaTime, lookAheadDistance: avoidLookAheadDistance, weight: 15);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -1102,9 +1113,16 @@ namespace Barotrauma
|
||||
private bool CanAttack(Entity target)
|
||||
{
|
||||
if (target == null) { return false; }
|
||||
if (target is Character ch)
|
||||
if (target is Character c)
|
||||
{
|
||||
if (Character.CurrentHull == null && ch.CurrentHull != null || Character.CurrentHull != null && ch.CurrentHull == null)
|
||||
if (Character.CurrentHull == null && c.CurrentHull != null || Character.CurrentHull != null && c.CurrentHull == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (target is Item i && i.GetComponent<Door>() == null)
|
||||
{
|
||||
if (Character.CurrentHull == null && i.CurrentHull != null || Character.CurrentHull != null && i.CurrentHull == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -1175,7 +1193,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (wall.SectionBodyDisabled(i))
|
||||
{
|
||||
if (CanEnterSubmarine && CanPassThroughHole(wall, i))
|
||||
if (Character.AnimController.CanEnterSubmarine && CanPassThroughHole(wall, i))
|
||||
{
|
||||
sectionIndex = i;
|
||||
break;
|
||||
@@ -1204,12 +1222,12 @@ namespace Barotrauma
|
||||
sectionPos.X += (wall.BodyWidth <= 0.0f ? wall.Rect.Width : wall.BodyWidth) / 2 * attachTargetNormal.X;
|
||||
}
|
||||
LatchOntoAI?.SetAttachTarget(wall.Submarine.PhysicsBody.FarseerBody, wall.Submarine, ConvertUnits.ToSimUnits(sectionPos), attachTargetNormal);
|
||||
if (CanEnterSubmarine || !wall.SectionBodyDisabled(sectionIndex) && !IsWallDisabled(wall))
|
||||
if (Character.AnimController.CanEnterSubmarine || !wall.SectionBodyDisabled(sectionIndex) && !IsWallDisabled(wall))
|
||||
{
|
||||
wallTarget = new WallTarget(sectionPos, wall, sectionIndex);
|
||||
}
|
||||
}
|
||||
if (!CanEnterSubmarine && wallTarget == null)
|
||||
if (!Character.AnimController.CanEnterSubmarine && wallTarget == null)
|
||||
{
|
||||
if (closestBody.UserData is Structure w && w.Submarine != null || closestBody.UserData is Item i && i.Submarine != null)
|
||||
{
|
||||
@@ -1251,12 +1269,18 @@ namespace Barotrauma
|
||||
return;
|
||||
}
|
||||
|
||||
if (attackResult.Damage > 0.0f && Character.Params.AI.AttackWhenProvoked)
|
||||
if (attackResult.Damage > 0.0f)
|
||||
{
|
||||
if (attacker.Submarine == Character.Submarine && canAttackCharacters ||
|
||||
attacker.Submarine != null && canAttackSub)
|
||||
if (Character.Params.AI.AttackWhenProvoked)
|
||||
{
|
||||
ChangeTargetState(attacker, AIState.Attack, 100);
|
||||
if (attacker.Submarine == Character.Submarine && canAttackCharacters || attacker.Submarine != null && canAttackSub)
|
||||
{
|
||||
ChangeTargetState(attacker, AIState.Attack, 100);
|
||||
}
|
||||
}
|
||||
else if (!AIParams.HasTag(attacker.SpeciesName))
|
||||
{
|
||||
ChangeTargetState(attacker, AIState.Flee, 100);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1306,7 +1330,8 @@ namespace Barotrauma
|
||||
SelectTarget(aiTarget, GetTargetMemory(SelectedAiTarget).Priority);
|
||||
}
|
||||
}
|
||||
if (SelectedAiTarget.Entity is IDamageable damageTarget)
|
||||
IDamageable damageTarget = wallTarget != null ? wallTarget.Structure : SelectedAiTarget.Entity as IDamageable;
|
||||
if (damageTarget != null)
|
||||
{
|
||||
if (attackingLimb.UpdateAttack(deltaTime, attackSimPos, damageTarget, out AttackResult attackResult, distance, targetLimb))
|
||||
{
|
||||
@@ -1480,9 +1505,9 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
// Don't attack targets that are not in the same submarine
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
if (targetCharacter.IsDead)
|
||||
{
|
||||
@@ -1578,7 +1603,7 @@ namespace Barotrauma
|
||||
continue;
|
||||
}
|
||||
valueModifier = 1;
|
||||
if (!CanEnterSubmarine && IsWallDisabled(s))
|
||||
if (!Character.AnimController.CanEnterSubmarine && IsWallDisabled(s))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -1587,7 +1612,7 @@ namespace Barotrauma
|
||||
var section = s.Sections[i];
|
||||
if (section.gap == null) { continue; }
|
||||
bool leadsInside = !section.gap.IsRoomToRoom && section.gap.FlowTargetHull != null;
|
||||
if (CanEnterSubmarine)
|
||||
if (Character.AnimController.CanEnterSubmarine)
|
||||
{
|
||||
if (CanPassThroughHole(s, i))
|
||||
{
|
||||
@@ -1766,7 +1791,7 @@ namespace Barotrauma
|
||||
removals.ForEach(r => targetMemories.Remove(r));
|
||||
}
|
||||
|
||||
private const float targetIgnoreTime = 5;
|
||||
private readonly float targetIgnoreTime = 5;
|
||||
private float targetIgnoreTimer;
|
||||
private readonly HashSet<AITarget> ignoredTargets = new HashSet<AITarget>();
|
||||
public void IgnoreTarget(AITarget target)
|
||||
@@ -1775,25 +1800,16 @@ namespace Barotrauma
|
||||
ignoredTargets.Add(target);
|
||||
targetIgnoreTimer = targetIgnoreTime * Rand.Range(0.75f, 1.25f);
|
||||
}
|
||||
|
||||
protected override void OnTargetChanged(AITarget previousTarget, AITarget newTarget)
|
||||
{
|
||||
if (previousTarget == null || newTarget == null) { return; }
|
||||
var previousCharacter = previousTarget.Entity as Character;
|
||||
var newCharacter = newTarget.Entity as Character;
|
||||
if (previousCharacter == null && newCharacter == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (previousCharacter != null && newCharacter != null && previousCharacter.SpeciesName == newCharacter.SpeciesName)
|
||||
{
|
||||
return;
|
||||
}
|
||||
modifiedParams.Keys.ForEachMod(tag => TryResetOriginalState(tag));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region State switching
|
||||
/// <summary>
|
||||
/// How long do we hold on to the current state after losing a target before we reset back to the original state.
|
||||
/// In other words, how long do we have to idle before the original state is restored.
|
||||
/// </summary>
|
||||
private readonly float stateResetCooldown = 10;
|
||||
private float stateResetTimer;
|
||||
private bool isStateChanged;
|
||||
|
||||
/// <summary>
|
||||
/// Resets the target's state to the original value defined in the xml.
|
||||
@@ -1806,6 +1822,7 @@ namespace Barotrauma
|
||||
modifiedParams.Remove(tag);
|
||||
if (tempParams.ContainsKey(tag))
|
||||
{
|
||||
tempParams.Values.ForEach(t => AIParams.RemoveTarget(t));
|
||||
tempParams.Remove(tag);
|
||||
}
|
||||
targetParams.Reset();
|
||||
@@ -1829,23 +1846,39 @@ namespace Barotrauma
|
||||
/// </summary>
|
||||
private void ChangeTargetState(Character target, AIState state, float? priority = null)
|
||||
{
|
||||
isStateChanged = true;
|
||||
SetStateResetTimer();
|
||||
ChangeParams(target.SpeciesName);
|
||||
// If the target is shooting from the submarine, we might not perceive it because it doesn't move.
|
||||
// --> Target the submarine too.
|
||||
if (target.Submarine != null && state == AIState.Attack && canAttackSub)
|
||||
// Target also items, because if we are blind and the target doesn't move, we can only perceive the target when it uses items
|
||||
if (state == AIState.Attack || state == AIState.Flee)
|
||||
{
|
||||
ChangeParams("room");
|
||||
ChangeParams("wall");
|
||||
ChangeParams("door");
|
||||
ChangeParams("weapon");
|
||||
ChangeParams("tool");
|
||||
}
|
||||
if (state == AIState.Attack)
|
||||
{
|
||||
// If the target is shooting from the submarine, we might not perceive it because it doesn't move.
|
||||
// --> Target the submarine too.
|
||||
if (target.Submarine != null && canAttackSub)
|
||||
{
|
||||
ChangeParams("room");
|
||||
ChangeParams("wall");
|
||||
ChangeParams("door");
|
||||
}
|
||||
ChangeParams("provocative", onlyExisting: true);
|
||||
ChangeParams("light", onlyExisting: true);
|
||||
}
|
||||
|
||||
void ChangeParams(string tag)
|
||||
void ChangeParams(string tag, bool onlyExisting = false)
|
||||
{
|
||||
if (!AIParams.TryGetTarget(tag, out CharacterParams.TargetParams targetParams))
|
||||
{
|
||||
if (AIParams.TryAddNewTarget(tag, state, priority ?? 100, out targetParams))
|
||||
if (!onlyExisting && !tempParams.ContainsKey(tag))
|
||||
{
|
||||
tempParams.Add(tag, targetParams);
|
||||
if (AIParams.TryAddNewTarget(tag, state, priority ?? 100, out targetParams))
|
||||
{
|
||||
tempParams.Add(tag, targetParams);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (targetParams != null)
|
||||
@@ -1862,6 +1895,12 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ResetOriginalState()
|
||||
{
|
||||
isStateChanged = false;
|
||||
modifiedParams.Keys.ForEachMod(tag => TryResetOriginalState(tag));
|
||||
}
|
||||
#endregion
|
||||
|
||||
protected override void OnStateChanged(AIState from, AIState to)
|
||||
@@ -1873,8 +1912,14 @@ namespace Barotrauma
|
||||
escapeMargin = 0;
|
||||
allGapsSearched = false;
|
||||
unreachableGaps.Clear();
|
||||
if (isStateChanged && to == AIState.Idle && from != to)
|
||||
{
|
||||
SetStateResetTimer();
|
||||
}
|
||||
}
|
||||
|
||||
private void SetStateResetTimer() => stateResetTimer = stateResetCooldown * Rand.Range(0.75f, 1.25f);
|
||||
|
||||
private float GetPerceivingRange(AITarget target) => Math.Max(target.SightRange * Sight, target.SoundRange * Hearing);
|
||||
|
||||
private bool CanPerceive(AITarget target, float dist = -1, float distSquared = -1)
|
||||
|
||||
@@ -711,6 +711,7 @@ namespace Barotrauma
|
||||
|
||||
public void SetOrder(Order order, string option, Character orderGiver, bool speak = true)
|
||||
{
|
||||
SetOrderProjSpecific(order, option);
|
||||
CurrentOrderOption = option;
|
||||
CurrentOrder = order;
|
||||
objectiveManager.SetOrder(order, option, orderGiver);
|
||||
@@ -749,10 +750,9 @@ namespace Barotrauma
|
||||
Character.Speak(TextManager.Get("DialogAffirmative"), null, 1.0f);
|
||||
}
|
||||
}
|
||||
SetOrderProjSpecific(order);
|
||||
}
|
||||
|
||||
partial void SetOrderProjSpecific(Order order);
|
||||
partial void SetOrderProjSpecific(Order order, string option);
|
||||
|
||||
public override void SelectTarget(AITarget target)
|
||||
{
|
||||
@@ -970,8 +970,8 @@ namespace Barotrauma
|
||||
{
|
||||
bool isValidTarget(Character e) => IsActive(e) && !IsFriendly(character, e);
|
||||
int enemyCount = visibleHulls == null ?
|
||||
Character.CharacterList.Count(e => e.CurrentHull == hull && isValidTarget(e)) :
|
||||
Character.CharacterList.Count(e => visibleHulls.Contains(e.CurrentHull) && isValidTarget(e));
|
||||
Character.CharacterList.Count(e => isValidTarget(e) && e.CurrentHull == hull) :
|
||||
Character.CharacterList.Count(e => isValidTarget(e) && visibleHulls.Contains(e.CurrentHull));
|
||||
// The hull safety decreases 90% per enemy up to 100% (TODO: test smaller percentages)
|
||||
enemyFactor = MathHelper.Lerp(1, 0, MathHelper.Clamp(enemyCount * 0.9f, 0, 1));
|
||||
}
|
||||
@@ -988,7 +988,7 @@ namespace Barotrauma
|
||||
return sameSpecies && !differentTeam;
|
||||
}
|
||||
|
||||
public static bool IsActive(Character other) => !other.Removed && !other.IsDead && !other.IsUnconscious;
|
||||
public static bool IsActive(Character other) => other != null && !other.Removed && !other.IsDead && !other.IsUnconscious;
|
||||
|
||||
public static bool IsTrueForAllCrewMembers(Character character, Func<HumanAIController, bool> predicate)
|
||||
{
|
||||
|
||||
@@ -145,9 +145,14 @@ namespace Barotrauma
|
||||
},
|
||||
onAbandon: () =>
|
||||
{
|
||||
// Don't ignore any hulls if outside, because apparently it happens that we can't find a path, in which case we just want to try again.
|
||||
// If we ignore the hull, it might be the only airlock in the target sub, which ignores the whole sub.
|
||||
if (currentHull != null && goToObjective != null)
|
||||
{
|
||||
HumanAIController.UnreachableHulls.Add(goToObjective.Target as Hull);
|
||||
if (goToObjective.Target is Hull hull)
|
||||
{
|
||||
HumanAIController.UnreachableHulls.Add(hull);
|
||||
}
|
||||
}
|
||||
RemoveSubObjective(ref goToObjective);
|
||||
});
|
||||
@@ -172,7 +177,7 @@ namespace Barotrauma
|
||||
}
|
||||
foreach (Character enemy in Character.CharacterList)
|
||||
{
|
||||
if (HumanAIController.IsFriendly(enemy) || !HumanAIController.IsActive(enemy)) { continue; }
|
||||
if (!HumanAIController.IsActive(enemy) || HumanAIController.IsFriendly(enemy)) { continue; }
|
||||
if (HumanAIController.VisibleHulls.Contains(enemy.CurrentHull))
|
||||
{
|
||||
Vector2 dir = character.Position - enemy.Position;
|
||||
|
||||
@@ -265,6 +265,14 @@ namespace Barotrauma
|
||||
{
|
||||
get
|
||||
{
|
||||
if (SteeringManager == PathSteering && PathSteering.CurrentPath?.CurrentNode?.Ladders != null)
|
||||
{
|
||||
//don't consider the character to be close enough to the target while climbing ladders,
|
||||
//UNLESS the last node in the path has been reached
|
||||
//otherwise characters can let go of the ladders too soon once they're close enough to the target
|
||||
if (PathSteering.CurrentPath.NextNode != null) { return false; }
|
||||
}
|
||||
|
||||
bool closeEnough = Vector2.DistanceSquared(Target.WorldPosition, character.WorldPosition) < CloseEnough * CloseEnough;
|
||||
if (closeEnough)
|
||||
{
|
||||
|
||||
@@ -25,6 +25,7 @@ namespace Barotrauma
|
||||
public static Sprite ShortcutNode { get; private set; }
|
||||
public static Sprite ExpandNode { get; private set; }
|
||||
public static Sprite NodeContainer { get; private set; }
|
||||
public static Sprite HotkeyContainer { get; private set; }
|
||||
public static Sprite CommandBackground { get; private set; }
|
||||
public static List<Order> PrefabList { get; private set; }
|
||||
public static Order GetPrefab(string identifier)
|
||||
@@ -163,6 +164,9 @@ namespace Barotrauma
|
||||
case "nodecontainer":
|
||||
NodeContainer = new Sprite(spriteElement, lazyLoad: true);
|
||||
break;
|
||||
case "hotkeycontainer":
|
||||
HotkeyContainer = new Sprite(spriteElement, lazyLoad: true);
|
||||
break;
|
||||
case "commandbackground":
|
||||
CommandBackground = new Sprite(spriteElement, lazyLoad: true);
|
||||
break;
|
||||
|
||||
@@ -312,22 +312,15 @@ namespace Barotrauma
|
||||
selectedCharacter.selectedBy = null;
|
||||
selectedCharacter = value;
|
||||
if (selectedCharacter != null)
|
||||
{
|
||||
selectedCharacter.selectedBy = this;
|
||||
|
||||
#if CLIENT
|
||||
if (GameMain.GameSession == null) return;
|
||||
// Quick & dirty hiding of the chat whenever a character with an accessible inventory is selected to prevent overlaps
|
||||
if (GameMain.GameSession.CrewManager.IsSinglePlayer)
|
||||
{
|
||||
if (GameMain.GameSession.CrewManager.ChatBox == null) return;
|
||||
GameMain.GameSession.CrewManager.ChatBox.SetVisibility(!(IsHumanoid && value != null && value.Inventory != null && value.CanInventoryBeAccessed));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GameMain.Client?.ChatBox == null) return;
|
||||
GameMain.Client.ChatBox.SetVisibility(!(IsHumanoid && value != null && value.Inventory != null && value.CanInventoryBeAccessed));
|
||||
}
|
||||
if (Inventory != null)
|
||||
{
|
||||
Inventory.ToggleInventory(true);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2315,14 +2308,21 @@ namespace Barotrauma
|
||||
aiTarget.SoundRange = MathHelper.Clamp(range, 0, 10000);
|
||||
}
|
||||
|
||||
public bool CanHearCharacter(Character speaker)
|
||||
{
|
||||
if (speaker == null || speaker.SpeechImpediment > 100.0f) { return false; }
|
||||
ChatMessageType messageType = ChatMessage.CanUseRadio(speaker) && ChatMessage.CanUseRadio(this) ?
|
||||
ChatMessageType.Radio :
|
||||
ChatMessageType.Default;
|
||||
return !string.IsNullOrEmpty(ChatMessage.ApplyDistanceEffect("message", messageType, speaker, this));
|
||||
}
|
||||
|
||||
public void SetOrder(Order order, string orderOption, Character orderGiver, bool speak = true)
|
||||
{
|
||||
if (orderGiver != null)
|
||||
{
|
||||
//set the character order only if the character is close enough to hear the message
|
||||
ChatMessageType messageType = ChatMessage.CanUseRadio(orderGiver) && ChatMessage.CanUseRadio(this) ?
|
||||
ChatMessageType.Radio : ChatMessageType.Default;
|
||||
if (string.IsNullOrEmpty(ChatMessage.ApplyDistanceEffect("message", messageType, orderGiver, this))) return;
|
||||
if (!CanHearCharacter(orderGiver)) { return; }
|
||||
}
|
||||
|
||||
HumanAIController humanAI = AIController as HumanAIController;
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace Barotrauma
|
||||
class LimbHealth
|
||||
{
|
||||
public Sprite IndicatorSprite;
|
||||
public Sprite HighlightSprite;
|
||||
|
||||
public Rectangle HighlightArea;
|
||||
|
||||
@@ -44,6 +45,9 @@ namespace Barotrauma
|
||||
IndicatorSprite = new Sprite(subElement);
|
||||
HighlightArea = subElement.GetAttributeRect("highlightarea", new Rectangle(0, 0, (int)IndicatorSprite.size.X, (int)IndicatorSprite.size.Y));
|
||||
break;
|
||||
case "highlightsprite":
|
||||
HighlightSprite = new Sprite(subElement);
|
||||
break;
|
||||
case "vitalitymultiplier":
|
||||
if (subElement.Attribute("name") != null)
|
||||
{
|
||||
|
||||
@@ -61,7 +61,8 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
public readonly Dictionary<int, XElement> ItemSets = new Dictionary<int, XElement>();
|
||||
public readonly Dictionary<int, List<string>> ItemNames = new Dictionary<int, List<string>>();
|
||||
public readonly Dictionary<int, List<string>> ItemIdentifiers = new Dictionary<int, List<string>>();
|
||||
public readonly Dictionary<int, Dictionary<string, bool>> ShowItemPreview = new Dictionary<int, Dictionary<string, bool>>();
|
||||
public readonly List<SkillPrefab> Skills = new List<SkillPrefab>();
|
||||
public readonly List<AutonomousObjective> AutomaticOrders = new List<AutonomousObjective>();
|
||||
public readonly List<string> AppropriateOrders = new List<string>();
|
||||
@@ -184,9 +185,10 @@ namespace Barotrauma
|
||||
{
|
||||
case "itemset":
|
||||
ItemSets.Add(variant, subElement);
|
||||
var itemNames = new List<string>();
|
||||
loadItemNames(subElement, itemNames);
|
||||
ItemNames.Add(variant++, itemNames);
|
||||
ItemIdentifiers[variant] = new List<string>();
|
||||
ShowItemPreview[variant] = new Dictionary<string, bool>();
|
||||
loadItemIdentifiers(subElement, variant);
|
||||
variant++;
|
||||
break;
|
||||
case "skills":
|
||||
foreach (XElement skillElement in subElement.Elements())
|
||||
@@ -201,20 +203,19 @@ namespace Barotrauma
|
||||
case "appropriateorders":
|
||||
subElement.Elements().ForEach(order => AppropriateOrders.Add(order.GetAttributeString("identifier", "").ToLowerInvariant()));
|
||||
break;
|
||||
case "icon":
|
||||
case "jobicon":
|
||||
Icon = new Sprite(subElement.FirstElement());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void loadItemNames(XElement parentElement, List<string> itemNames)
|
||||
void loadItemIdentifiers(XElement parentElement, int variant)
|
||||
{
|
||||
foreach (XElement itemElement in parentElement.GetChildElements("Item"))
|
||||
{
|
||||
if (itemElement.Element("name") != null)
|
||||
{
|
||||
DebugConsole.ThrowError("Error in job config \"" + Name + "\" - use identifiers instead of names to configure the items.");
|
||||
itemNames.Add(itemElement.GetAttributeString("name", ""));
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -222,22 +223,13 @@ namespace Barotrauma
|
||||
if (string.IsNullOrWhiteSpace(itemIdentifier))
|
||||
{
|
||||
DebugConsole.ThrowError("Error in job config \"" + Name + "\" - item with no identifier.");
|
||||
itemNames.Add("");
|
||||
}
|
||||
else
|
||||
{
|
||||
var prefab = MapEntityPrefab.Find(null, itemIdentifier) as ItemPrefab;
|
||||
if (prefab == null)
|
||||
{
|
||||
DebugConsole.ThrowError("Error in job config \"" + Name + "\" - item prefab \"" + itemIdentifier + "\" not found.");
|
||||
itemNames.Add("");
|
||||
}
|
||||
else
|
||||
{
|
||||
itemNames.Add(prefab.Name);
|
||||
}
|
||||
ItemIdentifiers[variant].Add(itemIdentifier);
|
||||
ShowItemPreview[variant][itemIdentifier] = itemElement.GetAttributeBool("showpreview", true);
|
||||
}
|
||||
loadItemNames(itemElement, itemNames);
|
||||
loadItemIdentifiers(itemElement, variant);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -536,7 +536,6 @@ namespace Barotrauma
|
||||
|
||||
|
||||
private readonly List<Body> contactBodies = new List<Body>();
|
||||
private List<Body> ignoredBodies;
|
||||
/// <summary>
|
||||
/// Returns true if the attack successfully hit something. If the distance is not given, it will be calculated.
|
||||
/// </summary>
|
||||
@@ -556,20 +555,11 @@ namespace Barotrauma
|
||||
case HitDetection.Distance:
|
||||
if (dist < attack.DamageRange)
|
||||
{
|
||||
if (ignoredBodies == null)
|
||||
{
|
||||
ignoredBodies = character.AnimController.Limbs.Select(l => l.body.FarseerBody).ToList();
|
||||
ignoredBodies.Add(character.AnimController.Collider.FarseerBody);
|
||||
}
|
||||
|
||||
structureBody = Submarine.PickBody(
|
||||
SimPosition, attackSimPos,
|
||||
ignoredBodies, Physics.CollisionWall);
|
||||
|
||||
if (damageTarget is Item)
|
||||
structureBody = Submarine.PickBody(SimPosition, attackSimPos, collisionCategory: Physics.CollisionWall | Physics.CollisionLevel, allowInsideFixture: true);
|
||||
if (damageTarget is Item i && i.GetComponent<Items.Components.Door>() != null)
|
||||
{
|
||||
// If the attack is aimed to an item and hits an item, it's successful.
|
||||
// Ignore blocking on items, because it causes cases where a Mudraptor cannot hit the hatch, for example.
|
||||
// Ignore blocking checks on doors, because it causes cases where a Mudraptor cannot hit the hatch, for example.
|
||||
wasHit = true;
|
||||
}
|
||||
else if (damageTarget is Structure wall && structureBody != null &&
|
||||
|
||||
@@ -464,7 +464,7 @@ namespace Barotrauma
|
||||
private bool TryAddTarget(XElement targetElement, out TargetParams target)
|
||||
{
|
||||
string tag = targetElement.GetAttributeString("tag", null);
|
||||
if (!CheckTag(tag))
|
||||
if (!HasTag(tag))
|
||||
{
|
||||
target = null;
|
||||
DebugConsole.ThrowError($"Multiple targets with the same tag ('{tag}') defined! Only the first will be used!");
|
||||
@@ -487,15 +487,18 @@ namespace Barotrauma
|
||||
if (TryAddTarget(element, out targetParams))
|
||||
{
|
||||
Element.Add(element);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return targetParams != null;
|
||||
}
|
||||
|
||||
private bool CheckTag(string tag)
|
||||
public bool HasTag(string tag)
|
||||
{
|
||||
if (tag == null) { return false; }
|
||||
tag = tag.ToLowerInvariant();
|
||||
return targets.None(t => t.Tag == tag);
|
||||
return targets.None(t => t.Tag.Equals(tag, StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
public bool RemoveTarget(TargetParams target) => RemoveSubParam(target, targets);
|
||||
|
||||
@@ -511,7 +511,7 @@ namespace Barotrauma
|
||||
try
|
||||
{
|
||||
int count = args.Length == 0 ? 10 : int.Parse(args[0]);
|
||||
Entity.DumpIds(count);
|
||||
Entity.DumpIds(count, args.Length >= 2 ? args[1] : null);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -1550,6 +1550,7 @@ namespace Barotrauma
|
||||
if (args != null && args.Length > argCount)
|
||||
{
|
||||
onAnswered(args[argCount]);
|
||||
return;
|
||||
}
|
||||
|
||||
#if CLIENT
|
||||
|
||||
@@ -5,11 +5,11 @@ using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
class CargoMission : Mission
|
||||
partial class CargoMission : Mission
|
||||
{
|
||||
private XElement itemConfig;
|
||||
private readonly XElement itemConfig;
|
||||
|
||||
private List<Item> items;
|
||||
private readonly List<Item> items = new List<Item>();
|
||||
|
||||
private int requiredDeliveryAmount;
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace Barotrauma
|
||||
|
||||
private void InitItems()
|
||||
{
|
||||
items = new List<Item>();
|
||||
items.Clear();
|
||||
|
||||
if (itemConfig == null)
|
||||
{
|
||||
@@ -35,7 +35,7 @@ namespace Barotrauma
|
||||
LoadItemAsChild(subElement, null);
|
||||
}
|
||||
|
||||
if (requiredDeliveryAmount == 0) requiredDeliveryAmount = items.Count;
|
||||
if (requiredDeliveryAmount == 0) { requiredDeliveryAmount = items.Count; }
|
||||
}
|
||||
|
||||
private void LoadItemAsChild(XElement element, Item parent)
|
||||
@@ -90,8 +90,6 @@ namespace Barotrauma
|
||||
|
||||
var item = new Item(itemPrefab, position, cargoRoom.Submarine);
|
||||
item.FindHull();
|
||||
|
||||
|
||||
items.Add(item);
|
||||
|
||||
if (parent != null) parent.Combine(item, user: null);
|
||||
@@ -108,7 +106,10 @@ namespace Barotrauma
|
||||
|
||||
public override void Start(Level level)
|
||||
{
|
||||
InitItems();
|
||||
if (!IsClient)
|
||||
{
|
||||
InitItems();
|
||||
}
|
||||
}
|
||||
|
||||
public override void End()
|
||||
@@ -127,8 +128,9 @@ namespace Barotrauma
|
||||
|
||||
foreach (Item item in items)
|
||||
{
|
||||
if (!item.Removed) item.Remove();
|
||||
if (!item.Removed) { item.Remove(); }
|
||||
}
|
||||
items.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using Barotrauma.Networking;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
partial class Mission
|
||||
abstract partial class Mission
|
||||
{
|
||||
public readonly MissionPrefab Prefab;
|
||||
protected bool completed;
|
||||
@@ -192,9 +193,7 @@ namespace Barotrauma
|
||||
|
||||
public void GiveReward()
|
||||
{
|
||||
var mode = GameMain.GameSession.GameMode as CampaignMode;
|
||||
if (mode == null) return;
|
||||
|
||||
if (!(GameMain.GameSession.GameMode is CampaignMode mode)) { return; }
|
||||
mode.Money += Reward;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,14 +3,18 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System;
|
||||
using System.Xml.Linq;
|
||||
using Barotrauma.Extensions;
|
||||
using Barotrauma.Networking;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
class MonsterMission : Mission
|
||||
partial class MonsterMission : Mission
|
||||
{
|
||||
private readonly string monsterFile;
|
||||
private readonly int monsterCount;
|
||||
private readonly HashSet<Tuple<string, int>> monsterFiles = new HashSet<Tuple<string, int>>();
|
||||
|
||||
//string = filename, point = min,max
|
||||
private readonly HashSet<Tuple<string, Point>> monsterFiles = new HashSet<Tuple<string, Point>>();
|
||||
private readonly List<Character> monsters = new List<Character>();
|
||||
private readonly List<Vector2> sonarPositions = new List<Vector2>();
|
||||
|
||||
@@ -50,7 +54,7 @@ namespace Barotrauma
|
||||
|
||||
maxSonarMarkerDistance = prefab.ConfigElement.GetAttributeFloat("maxsonarmarkerdistance", 10000.0f);
|
||||
|
||||
monsterCount = prefab.ConfigElement.GetAttributeInt("monstercount", 1);
|
||||
monsterCount = Math.Min(prefab.ConfigElement.GetAttributeInt("monstercount", 1), 255);
|
||||
string monsterFileName = monsterFile;
|
||||
foreach (var monsterElement in prefab.ConfigElement.GetChildElements("monster"))
|
||||
{
|
||||
@@ -64,9 +68,9 @@ namespace Barotrauma
|
||||
{
|
||||
defaultCount = monsterElement.GetAttributeInt("amount", 1);
|
||||
}
|
||||
int min = monsterElement.GetAttributeInt("min", defaultCount);
|
||||
int max = Math.Max(min, monsterElement.GetAttributeInt("max", defaultCount));
|
||||
monsterFiles.Add(new Tuple<string, int>(monster, Rand.Range(min, max + 1, Rand.RandSync.Server)));
|
||||
int min = Math.Min(monsterElement.GetAttributeInt("min", defaultCount), 255);
|
||||
int max = Math.Min(Math.Max(min, monsterElement.GetAttributeInt("max", defaultCount)), 255);
|
||||
monsterFiles.Add(new Tuple<string, Point>(monster, new Point(min, max)));
|
||||
}
|
||||
description = description.Replace("[monster]",
|
||||
TextManager.Get("character." + System.IO.Path.GetFileNameWithoutExtension(monsterFileName)));
|
||||
@@ -74,45 +78,50 @@ namespace Barotrauma
|
||||
|
||||
public override void Start(Level level)
|
||||
{
|
||||
Level.Loaded.TryGetInterestingPosition(true, Level.PositionType.MainPath, Level.Loaded.Size.X * 0.3f, out Vector2 spawnPos);
|
||||
|
||||
bool isClient = IsClient;
|
||||
|
||||
if (monsters.Count > 0)
|
||||
{
|
||||
throw new Exception($"monsters.Count > 0 ({monsters.Count})");
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(monsterFile))
|
||||
{
|
||||
for (int i = 0; i < monsterCount; i++)
|
||||
{
|
||||
monsters.Add(Character.Create(monsterFile, spawnPos, ToolBox.RandomSeed(8), null, isClient, true, false));
|
||||
}
|
||||
}
|
||||
foreach (var monster in monsterFiles)
|
||||
{
|
||||
for (int i = 0; i < monster.Item2; i++)
|
||||
{
|
||||
monsters.Add(Character.Create(monster.Item1, spawnPos, ToolBox.RandomSeed(8), null, isClient, true, false));
|
||||
}
|
||||
}
|
||||
|
||||
if (tempSonarPositions.Count > 0)
|
||||
{
|
||||
throw new Exception($"tempSonarPositions.Count > 0 ({tempSonarPositions.Count})");
|
||||
}
|
||||
|
||||
if (!IsClient)
|
||||
{
|
||||
Level.Loaded.TryGetInterestingPosition(true, Level.PositionType.MainPath, Level.Loaded.Size.X * 0.3f, out Vector2 spawnPos);
|
||||
if (!string.IsNullOrEmpty(monsterFile))
|
||||
{
|
||||
for (int i = 0; i < monsterCount; i++)
|
||||
{
|
||||
monsters.Add(Character.Create(monsterFile, spawnPos, ToolBox.RandomSeed(8), createNetworkEvent: false));
|
||||
}
|
||||
}
|
||||
foreach (var monster in monsterFiles)
|
||||
{
|
||||
int amount = Rand.Range(monster.Item2.X, monster.Item2.Y + 1);
|
||||
for (int i = 0; i < amount; i++)
|
||||
{
|
||||
monsters.Add(Character.Create(monster.Item1, spawnPos, ToolBox.RandomSeed(8), createNetworkEvent: false));
|
||||
}
|
||||
}
|
||||
|
||||
InitializeMonsters(monsters);
|
||||
}
|
||||
}
|
||||
|
||||
private void InitializeMonsters(IEnumerable<Character> monsters)
|
||||
{
|
||||
monsters.ForEach(m => m.Enabled = false);
|
||||
SwarmBehavior.CreateSwarm(monsters.Cast<AICharacter>());
|
||||
for (int i = 0; i < monsters.Count; i++)
|
||||
foreach (Character monster in monsters)
|
||||
{
|
||||
tempSonarPositions.Add(spawnPos + Rand.Vector(maxSonarMarkerDistance));
|
||||
tempSonarPositions.Add(monster.WorldPosition + Rand.Vector(maxSonarMarkerDistance));
|
||||
}
|
||||
|
||||
if (monsters.Count != tempSonarPositions.Count)
|
||||
if (monsters.Count() != tempSonarPositions.Count)
|
||||
{
|
||||
throw new Exception($"monsters.Count != tempSonarPositions.Count ({monsters.Count} != {tempSonarPositions.Count})");
|
||||
throw new Exception($"monsters.Count != tempSonarPositions.Count ({monsters.Count()} != {tempSonarPositions.Count})");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -183,5 +192,6 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
public bool IsEliminated(Character enemy) => enemy.Removed || enemy.IsDead || enemy.AIController is EnemyAIController ai && ai.State == AIState.Flee;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,13 +6,13 @@ using System.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
class SalvageMission : Mission
|
||||
partial class SalvageMission : Mission
|
||||
{
|
||||
private readonly ItemPrefab itemPrefab;
|
||||
|
||||
private Item item;
|
||||
|
||||
private Level.PositionType spawnPositionType;
|
||||
private readonly Level.PositionType spawnPositionType;
|
||||
|
||||
public override IEnumerable<Vector2> SonarPositions
|
||||
{
|
||||
@@ -62,23 +62,26 @@ namespace Barotrauma
|
||||
|
||||
public override void Start(Level level)
|
||||
{
|
||||
//ruin items are allowed to spawn close to the sub
|
||||
float minDistance = spawnPositionType == Level.PositionType.Ruin ? 0.0f : Level.Loaded.Size.X * 0.3f;
|
||||
Vector2 position = Level.Loaded.GetRandomItemPos(spawnPositionType, 100.0f, minDistance, 30.0f);
|
||||
|
||||
item = new Item(itemPrefab, position, null);
|
||||
item.body.FarseerBody.BodyType = BodyType.Kinematic;
|
||||
|
||||
if (item.HasTag("alien"))
|
||||
if (!IsClient)
|
||||
{
|
||||
//try to find an artifact holder and place the artifact inside it
|
||||
foreach (Item it in Item.ItemList)
|
||||
{
|
||||
if (it.Submarine != null || !it.HasTag("artifactholder")) continue;
|
||||
//ruin items are allowed to spawn close to the sub
|
||||
float minDistance = spawnPositionType == Level.PositionType.Ruin ? 0.0f : Level.Loaded.Size.X * 0.3f;
|
||||
Vector2 position = Level.Loaded.GetRandomItemPos(spawnPositionType, 100.0f, minDistance, 30.0f);
|
||||
|
||||
item = new Item(itemPrefab, position, null);
|
||||
item.body.FarseerBody.BodyType = BodyType.Kinematic;
|
||||
|
||||
var itemContainer = it.GetComponent<Items.Components.ItemContainer>();
|
||||
if (itemContainer == null) continue;
|
||||
if (itemContainer.Combine(item, user: null)) break; // Placement successful
|
||||
if (item.HasTag("alien"))
|
||||
{
|
||||
//try to find an artifact holder and place the artifact inside it
|
||||
foreach (Item it in Item.ItemList)
|
||||
{
|
||||
if (it.Submarine != null || !it.HasTag("artifactholder")) continue;
|
||||
|
||||
var itemContainer = it.GetComponent<Items.Components.ItemContainer>();
|
||||
if (itemContainer == null) { continue; }
|
||||
if (itemContainer.Combine(item, user: null)) { break; } // Placement successful
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -108,7 +111,8 @@ namespace Barotrauma
|
||||
{
|
||||
if (item.CurrentHull?.Submarine == null || !item.CurrentHull.Submarine.AtEndPosition || item.Removed) { return; }
|
||||
|
||||
item.Remove();
|
||||
item?.Remove();
|
||||
item = null;
|
||||
GiveReward();
|
||||
completed = true;
|
||||
}
|
||||
|
||||
@@ -49,14 +49,13 @@ namespace Barotrauma
|
||||
{
|
||||
PurchasedItem purchasedItem = PurchasedItems.Find(pi => pi.ItemPrefab == item);
|
||||
|
||||
if (purchasedItem != null && quantity == 1)
|
||||
campaign.Money -= item.GetPrice(campaign.Map.CurrentLocation).BuyPrice * quantity;
|
||||
if (purchasedItem != null)
|
||||
{
|
||||
campaign.Money -= item.GetPrice(campaign.Map.CurrentLocation).BuyPrice;
|
||||
purchasedItem.Quantity += 1;
|
||||
purchasedItem.Quantity += quantity;
|
||||
}
|
||||
else
|
||||
{
|
||||
campaign.Money -= item.GetPrice(campaign.Map.CurrentLocation).BuyPrice * quantity;
|
||||
purchasedItem = new PurchasedItem(item, quantity);
|
||||
purchasedItems.Add(purchasedItem);
|
||||
}
|
||||
|
||||
@@ -159,6 +159,10 @@ namespace Barotrauma
|
||||
|
||||
public void StartRound(Level level, bool reloadSub = true, bool loadSecondSub = false, bool mirrorLevel = false)
|
||||
{
|
||||
//make sure no status effects have been carried on from the next round
|
||||
//(they should be stopped in EndRound, this is a safeguard against cases where the round is ended ungracefully)
|
||||
StatusEffect.StopAll();
|
||||
|
||||
#if CLIENT
|
||||
GameMain.LightManager.LosEnabled = GameMain.Client == null || GameMain.Client.CharacterInfo != null;
|
||||
if (GameMain.Client == null) GameMain.LightManager.LosMode = GameMain.Config.LosMode;
|
||||
@@ -260,7 +264,18 @@ namespace Barotrauma
|
||||
|
||||
if (GameMode.Mission != null) { Mission = GameMode.Mission; }
|
||||
if (GameMode != null) { GameMode.Start(); }
|
||||
if (GameMode.Mission != null) { Mission.Start(Level.Loaded); }
|
||||
if (GameMode.Mission != null)
|
||||
{
|
||||
int prevEntityCount = Entity.GetEntityList().Count;
|
||||
Mission.Start(Level.Loaded);
|
||||
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient && Entity.GetEntityList().Count != prevEntityCount)
|
||||
{
|
||||
DebugConsole.ThrowError(
|
||||
"Entity count has changed after starting a mission as a client. " +
|
||||
"The clients should not instantiate entities themselves when starting the mission," +
|
||||
" but instead the server should inform the client of the spawned entities using Mission.ServerWriteInitial.");
|
||||
}
|
||||
}
|
||||
|
||||
EventManager.StartRound(level);
|
||||
SteamAchievementManager.OnStartRound();
|
||||
|
||||
@@ -16,6 +16,7 @@ namespace Barotrauma
|
||||
|
||||
partial class CharacterInventory : Inventory
|
||||
{
|
||||
private const int hotkeyCount = 5;
|
||||
private Character character;
|
||||
|
||||
public InvSlotType[] SlotTypes
|
||||
@@ -52,16 +53,7 @@ namespace Barotrauma
|
||||
{
|
||||
DebugConsole.ThrowError("Error in the inventory config of \"" + character.SpeciesName + "\" - " + slotTypeNames[i] + " is not a valid inventory slot type.");
|
||||
}
|
||||
SlotTypes[i] = parsedSlotType;
|
||||
switch (SlotTypes[i])
|
||||
{
|
||||
//case InvSlotType.Head:
|
||||
//case InvSlotType.OuterClothes:
|
||||
case InvSlotType.LeftHand:
|
||||
case InvSlotType.RightHand:
|
||||
hideEmptySlot[i] = true;
|
||||
break;
|
||||
}
|
||||
SlotTypes[i] = parsedSlotType;
|
||||
}
|
||||
|
||||
InitProjSpecific(element);
|
||||
@@ -130,25 +122,25 @@ namespace Barotrauma
|
||||
/// <summary>
|
||||
/// If there is no room in the generic inventory (InvSlotType.Any), check if the item can be auto-equipped into its respective limbslot
|
||||
/// </summary>
|
||||
public bool TryPutItemWithAutoEquipCheck(Item item, Character user, List<InvSlotType> allowedSlots = null, bool createNetworkEvent = true)
|
||||
public bool TryPutItemWithAutoEquipCheck(Item item, Character user, List<InvSlotType> allowedSlots = null, bool createNetworkEvent = true, bool preferNonHotkeys = false)
|
||||
{
|
||||
// Does not auto-equip the item if specified and no suitable any slot found (for example handcuffs are not auto-equipped)
|
||||
if (item.AllowedSlots.Contains(InvSlotType.Any))
|
||||
{
|
||||
var wearable = item.GetComponent<Wearable>();
|
||||
if (wearable != null && !wearable.AutoEquipWhenFull && CheckIfAnySlotAvailable(item, false) == -1)
|
||||
if (wearable != null && !wearable.AutoEquipWhenFull && CheckIfAnySlotAvailable(item, false, preferNonHotkeys) == -1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return TryPutItem(item, user, allowedSlots, createNetworkEvent);
|
||||
return TryPutItem(item, user, allowedSlots, createNetworkEvent, preferNonHotkeys);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If there is room, puts the item in the inventory and returns true, otherwise returns false
|
||||
/// </summary>
|
||||
public override bool TryPutItem(Item item, Character user, List<InvSlotType> allowedSlots = null, bool createNetworkEvent = true)
|
||||
public override bool TryPutItem(Item item, Character user, List<InvSlotType> allowedSlots = null, bool createNetworkEvent = true, bool preferNonHotkeys = false)
|
||||
{
|
||||
if (allowedSlots == null || !allowedSlots.Any()) return false;
|
||||
|
||||
@@ -172,7 +164,7 @@ namespace Barotrauma
|
||||
//try to place the item in a LimbSlot.Any slot if that's allowed
|
||||
if (allowedSlots.Contains(InvSlotType.Any) && item.AllowedSlots.Contains(InvSlotType.Any))
|
||||
{
|
||||
int freeIndex = CheckIfAnySlotAvailable(item, inWrongSlot);
|
||||
int freeIndex = CheckIfAnySlotAvailable(item, inWrongSlot, preferNonHotkeys);
|
||||
if (freeIndex > -1)
|
||||
{
|
||||
PutItem(item, freeIndex, user, true, createNetworkEvent);
|
||||
@@ -215,60 +207,30 @@ namespace Barotrauma
|
||||
#if CLIENT
|
||||
if (PersonalSlots.HasFlag(SlotTypes[i])) { hidePersonalSlots = false; }
|
||||
#endif
|
||||
bool removeFromOtherSlots = item.ParentInventory != this;
|
||||
if (placedInSlot == -1 && inWrongSlot)
|
||||
{
|
||||
if (!hideEmptySlot[i] || SlotTypes[currentSlot] != InvSlotType.Any) removeFromOtherSlots = true;
|
||||
}
|
||||
|
||||
bool removeFromOtherSlots = item.ParentInventory != this || (placedInSlot == -1 && inWrongSlot);
|
||||
PutItem(item, i, user, removeFromOtherSlots, createNetworkEvent);
|
||||
item.Equip(character);
|
||||
placedInSlot = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (placedInSlot > -1)
|
||||
{
|
||||
if (item.AllowedSlots.Contains(InvSlotType.Any) && hideEmptySlot[placedInSlot])
|
||||
{
|
||||
bool isInAnySlot = false;
|
||||
for (int i = 0; i < capacity; i++)
|
||||
{
|
||||
if (SlotTypes[i] == InvSlotType.Any && Items[i]==item)
|
||||
{
|
||||
isInAnySlot = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!isInAnySlot)
|
||||
{
|
||||
for (int i = 0; i < capacity; i++)
|
||||
{
|
||||
if (SlotTypes[i] == InvSlotType.Any && Items[i] == null)
|
||||
{
|
||||
Items[i] = item;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return placedInSlot > -1;
|
||||
}
|
||||
|
||||
public int CheckIfAnySlotAvailable(Item item, bool inWrongSlot)
|
||||
public int CheckIfAnySlotAvailable(Item item, bool inWrongSlot, bool preferNonHotkeys)
|
||||
{
|
||||
for (int i = 0; i < capacity; i++)
|
||||
for (int i = 0; i < capacity; i++)
|
||||
{
|
||||
if (SlotTypes[i] != InvSlotType.Any) continue;
|
||||
if (Items[i] == item)
|
||||
{
|
||||
if (SlotTypes[i] != InvSlotType.Any) continue;
|
||||
if (Items[i] == item)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
if (!preferNonHotkeys)
|
||||
{
|
||||
for (int i = 0; i < capacity; i++)
|
||||
{
|
||||
if (SlotTypes[i] != InvSlotType.Any) continue;
|
||||
@@ -283,11 +245,45 @@ namespace Barotrauma
|
||||
|
||||
return i;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int hotkeysCounted = 0;
|
||||
// First go through non-hotkeyed slots
|
||||
for (int i = 0; i < capacity; i++)
|
||||
{
|
||||
if (SlotTypes[i] != InvSlotType.Any) continue;
|
||||
hotkeysCounted++;
|
||||
|
||||
if (hotkeysCounted <= hotkeyCount) continue;
|
||||
|
||||
if (inWrongSlot)
|
||||
{
|
||||
if (Items[i] != item && Items[i] != null) continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Items[i] != null) continue;
|
||||
}
|
||||
|
||||
#if CLIENT
|
||||
if (!inventoryOpen)
|
||||
{
|
||||
ToggleInventory();
|
||||
}
|
||||
#endif
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
// Then redo with no preference
|
||||
return CheckIfAnySlotAvailable(item, inWrongSlot, false);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
public override bool TryPutItem(Item item, int index, bool allowSwapping, bool allowCombine, Character user, bool createNetworkEvent = true)
|
||||
public override bool TryPutItem(Item item, int index, bool allowSwapping, bool allowCombine, Character user, bool createNetworkEvent = true, bool avoidHotkeys = false)
|
||||
{
|
||||
if (index < 0 || index >= Items.Length)
|
||||
{
|
||||
|
||||
@@ -110,6 +110,12 @@ namespace Barotrauma.Items.Components
|
||||
hitTargets.Clear();
|
||||
|
||||
IsActive = true;
|
||||
|
||||
if (item.AiTarget != null)
|
||||
{
|
||||
item.AiTarget.SoundRange = item.AiTarget.MaxSoundRange;
|
||||
item.AiTarget.SightRange = item.AiTarget.MaxSightRange;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public virtual bool OnPicked(Character picker)
|
||||
{
|
||||
if (picker.Inventory.TryPutItemWithAutoEquipCheck(item, picker, allowedSlots))
|
||||
if (picker.Inventory.TryPutItemWithAutoEquipCheck(item, picker, allowedSlots, true, true))
|
||||
{
|
||||
if (!picker.HasSelectedItem(item) && item.body != null) item.body.Enabled = false;
|
||||
this.picker = picker;
|
||||
|
||||
@@ -36,7 +36,6 @@ namespace Barotrauma.Items.Components
|
||||
public Propulsion(Item item, XElement element)
|
||||
: base(item,element)
|
||||
{
|
||||
ResetSoundRange();
|
||||
}
|
||||
|
||||
public override bool Use(float deltaTime, Character character = null)
|
||||
@@ -106,19 +105,5 @@ namespace Barotrauma.Items.Components
|
||||
item.AiTarget.SoundRange = item.AiTarget.MaxSoundRange;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Unequip(Character character)
|
||||
{
|
||||
base.Unequip(character);
|
||||
ResetSoundRange();
|
||||
}
|
||||
|
||||
private void ResetSoundRange()
|
||||
{
|
||||
if (item.AiTarget != null)
|
||||
{
|
||||
item.AiTarget.SoundRange = item.AiTarget.MinSoundRange;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,14 +82,21 @@ namespace Barotrauma.Items.Components
|
||||
degreeOfFailure *= degreeOfFailure;
|
||||
return MathHelper.ToRadians(MathHelper.Lerp(Spread, UnskilledSpread, degreeOfFailure));
|
||||
}
|
||||
|
||||
|
||||
public override bool Use(float deltaTime, Character character = null)
|
||||
{
|
||||
if (character == null || character.Removed) return false;
|
||||
if ((item.RequireAimToUse && !character.IsKeyDown(InputType.Aim)) || reloadTimer > 0.0f) return false;
|
||||
if (character == null || character.Removed) { return false; }
|
||||
if ((item.RequireAimToUse && !character.IsKeyDown(InputType.Aim)) || reloadTimer > 0.0f) { return false; }
|
||||
|
||||
IsActive = true;
|
||||
reloadTimer = reload;
|
||||
|
||||
if (item.AiTarget != null)
|
||||
{
|
||||
item.AiTarget.SoundRange = item.AiTarget.MaxSoundRange;
|
||||
item.AiTarget.SightRange = item.AiTarget.MaxSightRange;
|
||||
}
|
||||
|
||||
List<Body> limbBodies = new List<Body>();
|
||||
foreach (Limb l in character.AnimController.Limbs)
|
||||
{
|
||||
|
||||
@@ -95,8 +95,10 @@ namespace Barotrauma.Items.Components
|
||||
Force = MathHelper.Lerp(force, (Voltage < MinVoltage) ? 0.0f : targetForce, 0.1f);
|
||||
if (Math.Abs(Force) > 1.0f)
|
||||
{
|
||||
//arbitrary multiplier that was added to changes in submarine mass without having to readjust all engines
|
||||
float forceMultiplier = 0.1f;
|
||||
float voltageFactor = MinVoltage <= 0.0f ? 1.0f : Math.Min(Voltage / MinVoltage, 1.0f);
|
||||
Vector2 currForce = new Vector2((force / 10.0f) * maxForce * voltageFactor, 0.0f);
|
||||
Vector2 currForce = new Vector2(force * maxForce * forceMultiplier * voltageFactor, 0.0f);
|
||||
//less effective when in a bad condition
|
||||
currForce *= MathHelper.Lerp(0.5f, 2.0f, item.Condition / item.MaxCondition);
|
||||
|
||||
@@ -107,12 +109,12 @@ namespace Barotrauma.Items.Components
|
||||
if (item.AiTarget != null)
|
||||
{
|
||||
var aiTarget = item.AiTarget;
|
||||
aiTarget.SoundRange = MathHelper.Lerp(aiTarget.MinSoundRange, aiTarget.MaxSoundRange, currForce.Length() / maxForce);
|
||||
aiTarget.SoundRange = MathHelper.Lerp(aiTarget.MinSoundRange, aiTarget.MaxSoundRange, Math.Min(currForce.Length() * forceMultiplier / maxForce, 1.0f));
|
||||
}
|
||||
if (item.CurrentHull != null)
|
||||
{
|
||||
var aiTarget = item.CurrentHull.AiTarget;
|
||||
float noise = MathHelper.Lerp(aiTarget.MinSoundRange, aiTarget.MaxSoundRange, currForce.Length() / maxForce);
|
||||
float noise = MathHelper.Lerp(aiTarget.MinSoundRange, aiTarget.MaxSoundRange, Math.Min(currForce.Length() * forceMultiplier / maxForce, 1.0f));
|
||||
aiTarget.SoundRange = Math.Max(noise, aiTarget.SoundRange);
|
||||
}
|
||||
#if CLIENT
|
||||
|
||||
@@ -79,7 +79,14 @@ namespace Barotrauma.Items.Components
|
||||
public float Range
|
||||
{
|
||||
get { return range; }
|
||||
set { range = MathHelper.Clamp(value, 0.0f, 100000.0f); }
|
||||
set
|
||||
{
|
||||
range = MathHelper.Clamp(value, 0.0f, 100000.0f);
|
||||
if (item?.AiTarget != null && item.AiTarget.MaxSoundRange <= 0)
|
||||
{
|
||||
item.AiTarget.MaxSoundRange = range;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Serialize(false, false, description: "Should the sonar display the walls of the submarine it is inside.")]
|
||||
|
||||
@@ -84,13 +84,10 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
if (sender == null || sender.channel != channel) { return false; }
|
||||
|
||||
if (sender.TeamID != Character.TeamType.None && TeamID != Character.TeamType.None)
|
||||
if (sender.TeamID != TeamID)
|
||||
{
|
||||
if (sender.TeamID != TeamID)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Vector2.DistanceSquared(item.WorldPosition, sender.item.WorldPosition) > sender.range * sender.range) { return false; }
|
||||
|
||||
|
||||
@@ -264,7 +264,7 @@ namespace Barotrauma.Items.Components
|
||||
Character user = item.ParentInventory?.Owner as Character;
|
||||
removeNodeDelay = (user?.SelectedConstruction == null) ? removeNodeDelay - deltaTime : 0.5f;
|
||||
|
||||
Submarine sub = null;
|
||||
Submarine sub = item.Submarine;
|
||||
if (connections[0] != null && connections[0].Item.Submarine != null) { sub = connections[0].Item.Submarine; }
|
||||
if (connections[1] != null && connections[1].Item.Submarine != null) { sub = connections[1].Item.Submarine; }
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@ namespace Barotrauma
|
||||
protected readonly int capacity;
|
||||
|
||||
public Item[] Items;
|
||||
protected bool[] hideEmptySlot;
|
||||
|
||||
public bool Locked;
|
||||
|
||||
@@ -32,21 +31,16 @@ namespace Barotrauma
|
||||
this.Owner = owner;
|
||||
|
||||
Items = new Item[capacity];
|
||||
hideEmptySlot = new bool[capacity];
|
||||
|
||||
#if CLIENT
|
||||
this.slotsPerRow = slotsPerRow;
|
||||
|
||||
if (SlotSpriteSmall == null)
|
||||
if (DraggableIndicator == null)
|
||||
{
|
||||
//TODO: define these in xml
|
||||
SlotSpriteSmall = new Sprite("Content/UI/InventoryUIAtlas.png", new Rectangle(0, 0, 128, 128), null, 0);
|
||||
// Adjustment to match the old size of 75,71
|
||||
SlotSpriteSmall.size = new Vector2(SlotSpriteSmall.SourceRect.Width * 0.5859375f, SlotSpriteSmall.SourceRect.Height * 0.5546875f);
|
||||
DraggableIndicator = GUI.Style.GetComponentStyle("GUIDragIndicator").Sprites[GUIComponent.ComponentState.None][0].Sprite;
|
||||
|
||||
slotHotkeySprite = new Sprite("Content/UI/InventoryUIAtlas.png", new Rectangle(128, 0, 128, 128), null, 0);
|
||||
EquipIndicator = new Sprite("Content/UI/inventoryAtlas.png", new Rectangle(673, 182, 73, 27), new Vector2(0.5f, 0.5f), 0);
|
||||
EquipIndicatorHighlight = new Sprite("Content/UI/inventoryAtlas.png", new Rectangle(679, 108, 67, 21), new Vector2(0.5f, 0.5f), 0);
|
||||
EquipIndicator = new Sprite("Content/UI/InventoryUIAtlas.png", new Rectangle(137, 10, 112, 25), new Vector2(0.5f, 1f), 0);
|
||||
EquipIndicator.size = new Vector2(EquipIndicator.SourceRect.Width * 0.682f, EquipIndicator.SourceRect.Height * 0.682f);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -108,7 +102,7 @@ namespace Barotrauma
|
||||
/// <summary>
|
||||
/// If there is room, puts the item in the inventory and returns true, otherwise returns false
|
||||
/// </summary>
|
||||
public virtual bool TryPutItem(Item item, Character user, List<InvSlotType> allowedSlots = null, bool createNetworkEvent = true)
|
||||
public virtual bool TryPutItem(Item item, Character user, List<InvSlotType> allowedSlots = null, bool createNetworkEvent = true, bool avoidHotkeys = false)
|
||||
{
|
||||
int slot = FindAllowedSlot(item);
|
||||
if (slot < 0) return false;
|
||||
@@ -117,7 +111,7 @@ namespace Barotrauma
|
||||
return true;
|
||||
}
|
||||
|
||||
public virtual bool TryPutItem(Item item, int i, bool allowSwapping, bool allowCombine, Character user, bool createNetworkEvent = true)
|
||||
public virtual bool TryPutItem(Item item, int i, bool allowSwapping, bool allowCombine, Character user, bool createNetworkEvent = true, bool avoidHotkeys = false)
|
||||
{
|
||||
if (i < 0 || i >= Items.Length)
|
||||
{
|
||||
|
||||
@@ -47,9 +47,9 @@ namespace Barotrauma
|
||||
return (item != null && Items[i] == null && container.CanBeContained(item));
|
||||
}
|
||||
|
||||
public override bool TryPutItem(Item item, Character user, List<InvSlotType> allowedSlots = null, bool createNetworkEvent = true)
|
||||
public override bool TryPutItem(Item item, Character user, List<InvSlotType> allowedSlots = null, bool createNetworkEvent = true, bool preferNonHotkeys = false)
|
||||
{
|
||||
bool wasPut = base.TryPutItem(item, user, allowedSlots, createNetworkEvent);
|
||||
bool wasPut = base.TryPutItem(item, user, allowedSlots, createNetworkEvent, preferNonHotkeys);
|
||||
|
||||
if (wasPut)
|
||||
{
|
||||
@@ -68,9 +68,9 @@ namespace Barotrauma
|
||||
return wasPut;
|
||||
}
|
||||
|
||||
public override bool TryPutItem(Item item, int i, bool allowSwapping, bool allowCombine, Character user, bool createNetworkEvent = true)
|
||||
public override bool TryPutItem(Item item, int i, bool allowSwapping, bool allowCombine, Character user, bool createNetworkEvent = true, bool preferNonHotkeys = false)
|
||||
{
|
||||
bool wasPut = base.TryPutItem(item, i, allowSwapping, allowCombine, user, createNetworkEvent);
|
||||
bool wasPut = base.TryPutItem(item, i, allowSwapping, allowCombine, user, createNetworkEvent, preferNonHotkeys);
|
||||
|
||||
if (wasPut)
|
||||
{
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
@@ -283,16 +284,23 @@ namespace Barotrauma
|
||||
Removed = true;
|
||||
}
|
||||
|
||||
public static void DumpIds(int count)
|
||||
public static void DumpIds(int count, string filename)
|
||||
{
|
||||
List<Entity> entities = dictionary.Values.OrderByDescending(e => e.id).ToList();
|
||||
|
||||
count = Math.Min(entities.Count, count);
|
||||
|
||||
List<string> lines = new List<string>();
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
lines.Add(entities[i].id + ": " + entities[i].ToString());
|
||||
DebugConsole.ThrowError(entities[i].id + ": " + entities[i].ToString());
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(filename))
|
||||
{
|
||||
File.WriteAllLines(filename, lines);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ namespace Barotrauma
|
||||
return false;
|
||||
}
|
||||
|
||||
public void SaveToCache(string filename, long? time=null)
|
||||
public void SaveToCache(string filename, long? time = null)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(filename))
|
||||
{
|
||||
@@ -191,9 +191,26 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
public static string GetShortHash(string fullHash)
|
||||
{
|
||||
{
|
||||
if (string.IsNullOrEmpty(fullHash)) { return ""; }
|
||||
return fullHash.Length < 7 ? fullHash : fullHash.Substring(0, 7);
|
||||
}
|
||||
|
||||
public static bool RemoveFromCache(string filename)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(filename))
|
||||
{
|
||||
filename = filename.CleanUpPath();
|
||||
lock (cache)
|
||||
{
|
||||
if (cache.ContainsKey(filename))
|
||||
{
|
||||
cache.Remove(filename);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,6 +173,7 @@ namespace Barotrauma
|
||||
XDocument doc = OpenFile(filePath);
|
||||
StartHashDocTask(doc);
|
||||
hashTask.Wait();
|
||||
hashTask = null;
|
||||
}
|
||||
|
||||
return hash;
|
||||
@@ -343,7 +344,10 @@ namespace Barotrauma
|
||||
public Submarine(string filePath, string hash = "", bool tryLoad = true) : base(null)
|
||||
{
|
||||
this.filePath = filePath;
|
||||
LastModifiedTime = File.GetLastWriteTime(filePath);
|
||||
if (!string.IsNullOrEmpty(filePath) && File.Exists(filePath))
|
||||
{
|
||||
LastModifiedTime = File.GetLastWriteTime(filePath);
|
||||
}
|
||||
try
|
||||
{
|
||||
name = displayName = Path.GetFileNameWithoutExtension(filePath);
|
||||
@@ -1631,6 +1635,10 @@ namespace Barotrauma
|
||||
return false;
|
||||
}
|
||||
|
||||
hash = null;
|
||||
hashTask = null;
|
||||
Md5Hash.RemoveFromCache(filePath);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.IO.Pipes;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
@@ -81,43 +82,67 @@ namespace Barotrauma.Networking
|
||||
readCancellationToken = null;
|
||||
readStream?.Dispose(); readStream = null;
|
||||
writeStream?.Dispose(); writeStream = null;
|
||||
msgsToRead?.Clear(); msgsToWrite?.Clear();
|
||||
}
|
||||
|
||||
|
||||
private static int ReadIncomingMsgs()
|
||||
{
|
||||
Task<int> readTask = readStream?.ReadAsync(tempBytes, 0, tempBytes.Length, readCancellationToken.Token);
|
||||
TimeSpan ts = TimeSpan.FromMilliseconds(100);
|
||||
for (int i = 0; i < 150; i++)
|
||||
{
|
||||
if (shutDown)
|
||||
{
|
||||
readCancellationToken?.Cancel();
|
||||
shutDown = true;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((readTask?.IsCompleted ?? true) || (readTask?.Wait(ts) ?? true))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (readTask == null || !readTask.IsCompleted)
|
||||
{
|
||||
readCancellationToken?.Cancel();
|
||||
shutDown = true;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (readTask.Status != TaskStatus.RanToCompletion)
|
||||
{
|
||||
shutDown = true;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return readTask.Result;
|
||||
}
|
||||
|
||||
|
||||
private static void UpdateRead()
|
||||
{
|
||||
while (!shutDown)
|
||||
{
|
||||
Task<int> readTask = readStream?.ReadAsync(tempBytes, 0, tempBytes.Length, readCancellationToken.Token);
|
||||
TimeSpan ts = TimeSpan.FromMilliseconds(100);
|
||||
for (int i=0;i<150;i++)
|
||||
{
|
||||
if (shutDown)
|
||||
{
|
||||
readCancellationToken?.Cancel();
|
||||
shutDown = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if ((readTask?.IsCompleted ?? true) || (readTask?.Wait(ts) ?? true))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (readTask == null || !readTask.IsCompleted)
|
||||
{
|
||||
readCancellationToken?.Cancel();
|
||||
shutDown = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (readTask.Status != TaskStatus.RanToCompletion)
|
||||
#if SERVER
|
||||
if (!((readStream as AnonymousPipeClientStream)?.IsConnected ?? false))
|
||||
{
|
||||
shutDown = true;
|
||||
return;
|
||||
}
|
||||
#else
|
||||
if (!((readStream as AnonymousPipeServerStream)?.IsConnected ?? false))
|
||||
{
|
||||
shutDown = true;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
int readLen = readTask.Result;
|
||||
int readLen = ReadIncomingMsgs();
|
||||
|
||||
if (readLen < 0) { shutDown = true; return; }
|
||||
|
||||
int procIndex = 0;
|
||||
|
||||
@@ -125,8 +150,20 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
if (readState == ReadState.WaitingForPacketStart)
|
||||
{
|
||||
readIncTotal = tempBytes[procIndex] | (tempBytes[procIndex + 1] << 8);
|
||||
procIndex += 2;
|
||||
readIncTotal = tempBytes[procIndex];
|
||||
procIndex++;
|
||||
|
||||
if (procIndex >= readLen)
|
||||
{
|
||||
readLen = ReadIncomingMsgs();
|
||||
|
||||
if (readLen < 0) { shutDown = true; return; }
|
||||
|
||||
procIndex = 0;
|
||||
}
|
||||
|
||||
readIncTotal |= (tempBytes[procIndex] << 8);
|
||||
procIndex++;
|
||||
|
||||
if (readIncTotal <= 0) { continue; }
|
||||
|
||||
@@ -166,6 +203,19 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
while (!shutDown)
|
||||
{
|
||||
#if SERVER
|
||||
if (!((writeStream as AnonymousPipeClientStream)?.IsConnected ?? false))
|
||||
{
|
||||
shutDown = true;
|
||||
return;
|
||||
}
|
||||
#else
|
||||
if (!((writeStream as AnonymousPipeServerStream)?.IsConnected ?? false))
|
||||
{
|
||||
shutDown = true;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
bool msgAvailable; byte[] msg;
|
||||
lock (msgsToWrite)
|
||||
{
|
||||
@@ -176,9 +226,11 @@ namespace Barotrauma.Networking
|
||||
byte[] lengthBytes = new byte[2];
|
||||
lengthBytes[0] = (byte)(msg.Length & 0xFF);
|
||||
lengthBytes[1] = (byte)((msg.Length >> 8) & 0xFF);
|
||||
|
||||
msg = lengthBytes.Concat(msg).ToArray();
|
||||
|
||||
try
|
||||
{
|
||||
writeStream?.Write(lengthBytes, 0, 2);
|
||||
writeStream?.Write(msg, 0, msg.Length);
|
||||
}
|
||||
catch (IOException e)
|
||||
@@ -199,11 +251,23 @@ namespace Barotrauma.Networking
|
||||
writeManualResetEvent.Reset();
|
||||
if (!writeManualResetEvent.WaitOne(1000))
|
||||
{
|
||||
//heartbeat to keep the other end alive
|
||||
byte[] lengthBytes = new byte[2];
|
||||
lengthBytes[0] = (byte)0;
|
||||
lengthBytes[1] = (byte)0;
|
||||
writeStream?.Write(lengthBytes, 0, 2);
|
||||
if (shutDown)
|
||||
{
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
//heartbeat to keep the other end alive
|
||||
byte[] lengthBytes = new byte[2];
|
||||
lengthBytes[0] = (byte)0;
|
||||
lengthBytes[1] = (byte)0;
|
||||
writeStream?.Write(lengthBytes, 0, 2);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
shutDown = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
public OrderChatMessage(Order order, string orderOption, Entity targetEntity, Character targetCharacter, Character sender)
|
||||
: this(order, orderOption,
|
||||
order.GetChatMessage(targetCharacter?.Name, sender?.CurrentHull?.DisplayName, givingOrderToSelf: targetCharacter == sender, orderOption: orderOption),
|
||||
order?.GetChatMessage(targetCharacter?.Name, sender?.CurrentHull?.DisplayName, givingOrderToSelf: targetCharacter == sender, orderOption: orderOption),
|
||||
targetEntity, targetCharacter, sender)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -30,10 +30,11 @@ namespace Barotrauma
|
||||
Init(columnCount, rowCount);
|
||||
}
|
||||
|
||||
public SpriteSheet(string filePath, int columnCount, int rowCount, Vector2 origin)
|
||||
public SpriteSheet(string filePath, int columnCount, int rowCount, Vector2 origin, Rectangle? sourceRect = null)
|
||||
: base(filePath, origin)
|
||||
{
|
||||
this.origin = origin;
|
||||
if (sourceRect.HasValue) { SourceRect = sourceRect.Value; }
|
||||
Init(columnCount, rowCount);
|
||||
}
|
||||
|
||||
|
||||
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user