v0.10.5.1
This commit is contained in:
@@ -7,11 +7,18 @@ assignees: ''
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
**QA**
|
||||||
|
- [ ] Play through tutorials and verify that they are working.
|
||||||
|
- [ ] Do a smoketest on all game modes
|
||||||
|
- [ ] Smoketest server hosting (dedicated and client)
|
||||||
|
- [ ] Install Trick or Trauma and check you can start a round with no obvious issues/errors (to make sure we didn't unintentionally break compatibility with older mods).
|
||||||
|
- [ ] Play through one single player campaign round.
|
||||||
|
- [ ] Do a smoketest in a language other than English.
|
||||||
|
|
||||||
**Code:**
|
**Code:**
|
||||||
- [ ] Build and upload dedicated server
|
- [ ] Build and upload dedicated server
|
||||||
- [ ] Verify that Vanilla content package hashes match between Windows/Mac/Linux
|
- [ ] Verify that Vanilla content package hashes match between Windows/Mac/Linux
|
||||||
- [ ] Run "checkmissingloca" command to make sure localization files are up-to-date.
|
- [ ] Run "checkmissingloca" command to make sure localization files are up-to-date.
|
||||||
- [ ] Install Trick or Trauma and check you can start a round with no obvious issues/errors (to make sure we didn't unintentionally break compatibility with older mods).
|
|
||||||
- [ ] Prepare new main menu content (changelog)
|
- [ ] Prepare new main menu content (changelog)
|
||||||
- [ ] Prepare public github repo for pushing the new changes
|
- [ ] Prepare public github repo for pushing the new changes
|
||||||
|
|
||||||
|
|||||||
@@ -261,7 +261,7 @@ namespace Barotrauma
|
|||||||
if (targetPos == Vector2.Zero)
|
if (targetPos == Vector2.Zero)
|
||||||
{
|
{
|
||||||
Vector2 moveInput = Vector2.Zero;
|
Vector2 moveInput = Vector2.Zero;
|
||||||
if (allowMove)
|
if (allowMove && !Freeze)
|
||||||
{
|
{
|
||||||
if (GUI.KeyboardDispatcher.Subscriber == null)
|
if (GUI.KeyboardDispatcher.Subscriber == null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using FarseerPhysics;
|
using FarseerPhysics;
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
@@ -64,6 +63,27 @@ namespace Barotrauma
|
|||||||
GUI.DrawString(spriteBatch, pos + textOffset + new Vector2(0, 60 + offset), $"ACTIVE OBJECTIVE: {activeObjective.DebugTag} ({activeObjective.Priority.FormatZeroDecimal()})", Color.White, Color.Black);
|
GUI.DrawString(spriteBatch, pos + textOffset + new Vector2(0, 60 + offset), $"ACTIVE OBJECTIVE: {activeObjective.DebugTag} ({activeObjective.Priority.FormatZeroDecimal()})", Color.White, Color.Black);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (int i = 0; i < ObjectiveManager.Objectives.Count; i++)
|
||||||
|
{
|
||||||
|
var objective = ObjectiveManager.Objectives[i];
|
||||||
|
int offsetMultiplier;
|
||||||
|
if (ObjectiveManager.CurrentOrder == null)
|
||||||
|
{
|
||||||
|
if (i == 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
offsetMultiplier = i - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
offsetMultiplier = i + 1;
|
||||||
|
}
|
||||||
|
GUI.DrawString(spriteBatch, pos + textOffset + new Vector2(120, offsetMultiplier * 18 + 100), $"{objective.DebugTag} ({objective.Priority.FormatZeroDecimal()})", Color.White, Color.Black * 0.5f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (steeringManager is IndoorsSteeringManager pathSteering)
|
if (steeringManager is IndoorsSteeringManager pathSteering)
|
||||||
|
|||||||
@@ -409,11 +409,6 @@ namespace Barotrauma
|
|||||||
|
|
||||||
emitter.Emit(1.0f, limb.WorldPosition, character.CurrentHull, amountMultiplier: gibParticleAmount);
|
emitter.Emit(1.0f, limb.WorldPosition, character.CurrentHull, amountMultiplier: gibParticleAmount);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(character.BloodDecalName))
|
|
||||||
{
|
|
||||||
character.CurrentHull?.AddDecal(character.BloodDecalName, limb.WorldPosition, MathHelper.Clamp(limb.Mass, 0.5f, 2.0f));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (playSound)
|
if (playSound)
|
||||||
|
|||||||
@@ -97,8 +97,6 @@ namespace Barotrauma
|
|||||||
set { chromaticAberrationStrength = MathHelper.Clamp(value, 0.0f, 100.0f); }
|
set { chromaticAberrationStrength = MathHelper.Clamp(value, 0.0f, 100.0f); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public string BloodDecalName => Params.BloodDecal;
|
|
||||||
|
|
||||||
private readonly List<ParticleEmitter> bloodEmitters = new List<ParticleEmitter>();
|
private readonly List<ParticleEmitter> bloodEmitters = new List<ParticleEmitter>();
|
||||||
public IEnumerable<ParticleEmitter> BloodEmitters
|
public IEnumerable<ParticleEmitter> BloodEmitters
|
||||||
{
|
{
|
||||||
@@ -617,7 +615,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
partial void SetOrderProjSpecific(Order order, string orderOption)
|
partial void SetOrderProjSpecific(Order order, string orderOption)
|
||||||
{
|
{
|
||||||
GameMain.GameSession?.CrewManager?.DisplayCharacterOrder(this, order, orderOption);
|
GameMain.GameSession?.CrewManager?.AddCurrentOrderIcon(this, order, orderOption);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void AddAllToGUIUpdateList()
|
public static void AddAllToGUIUpdateList()
|
||||||
@@ -786,7 +784,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
if (CampaignInteractionType != CampaignMode.InteractionType.None && AllowCustomInteract)
|
if (CampaignInteractionType != CampaignMode.InteractionType.None && AllowCustomInteract)
|
||||||
{
|
{
|
||||||
var iconStyle = GUI.Style.GetComponentStyle("CampaignInteractionIcon." + CampaignInteractionType);
|
var iconStyle = GUI.Style.GetComponentStyle("CampaignInteractionBubble." + CampaignInteractionType);
|
||||||
if (iconStyle != null)
|
if (iconStyle != null)
|
||||||
{
|
{
|
||||||
Vector2 headPos = AnimController.GetLimb(LimbType.Head)?.WorldPosition ?? WorldPosition + Vector2.UnitY * 100.0f;
|
Vector2 headPos = AnimController.GetLimb(LimbType.Head)?.WorldPosition ?? WorldPosition + Vector2.UnitY * 100.0f;
|
||||||
@@ -825,15 +823,19 @@ namespace Barotrauma
|
|||||||
/// Creates a progress bar that's "linked" to the specified object (or updates an existing one if there's one already linked to the object)
|
/// Creates a progress bar that's "linked" to the specified object (or updates an existing one if there's one already linked to the object)
|
||||||
/// The progress bar will automatically fade out after 1 sec if the method hasn't been called during that time
|
/// The progress bar will automatically fade out after 1 sec if the method hasn't been called during that time
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public HUDProgressBar UpdateHUDProgressBar(object linkedObject, Vector2 worldPosition, float progress, Color emptyColor, Color fullColor)
|
public HUDProgressBar UpdateHUDProgressBar(object linkedObject, Vector2 worldPosition, float progress, Color emptyColor, Color fullColor, string textTag = "")
|
||||||
{
|
{
|
||||||
if (controlled != this) return null;
|
if (controlled != this) { return null; }
|
||||||
|
|
||||||
if (!hudProgressBars.TryGetValue(linkedObject, out HUDProgressBar progressBar))
|
if (!hudProgressBars.TryGetValue(linkedObject, out HUDProgressBar progressBar))
|
||||||
{
|
{
|
||||||
progressBar = new HUDProgressBar(worldPosition, Submarine, emptyColor, fullColor);
|
progressBar = new HUDProgressBar(worldPosition, Submarine, emptyColor, fullColor, textTag);
|
||||||
hudProgressBars.Add(linkedObject, progressBar);
|
hudProgressBars.Add(linkedObject, progressBar);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
progressBar.TextTag = textTag;
|
||||||
|
}
|
||||||
|
|
||||||
progressBar.WorldPosition = worldPosition;
|
progressBar.WorldPosition = worldPosition;
|
||||||
progressBar.FadeTimer = Math.Max(progressBar.FadeTimer, 1.0f);
|
progressBar.FadeTimer = Math.Max(progressBar.FadeTimer, 1.0f);
|
||||||
@@ -859,7 +861,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
var selectedSound = matchingSounds.GetRandom();
|
var selectedSound = matchingSounds.GetRandom();
|
||||||
if (selectedSound?.Sound == null) { return; }
|
if (selectedSound?.Sound == null) { return; }
|
||||||
soundChannel = SoundPlayer.PlaySound(selectedSound.Sound, AnimController.WorldPosition, selectedSound.Volume, selectedSound.Range, CurrentHull);
|
soundChannel = SoundPlayer.PlaySound(selectedSound.Sound, AnimController.WorldPosition, selectedSound.Volume, selectedSound.Range, hullGuess: CurrentHull);
|
||||||
soundTimer = soundInterval;
|
soundTimer = soundInterval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -52,7 +52,6 @@ namespace Barotrauma
|
|||||||
return
|
return
|
||||||
character?.Inventory != null &&
|
character?.Inventory != null &&
|
||||||
character.AllowInput &&
|
character.AllowInput &&
|
||||||
!character.LockHands &&
|
|
||||||
(controller?.User != character || !controller.HideHUD) &&
|
(controller?.User != character || !controller.HideHUD) &&
|
||||||
!IsCampaignInterfaceOpen &&
|
!IsCampaignInterfaceOpen &&
|
||||||
!ConversationAction.FadeScreenToBlack;
|
!ConversationAction.FadeScreenToBlack;
|
||||||
@@ -227,7 +226,7 @@ namespace Barotrauma
|
|||||||
Color.Lerp(GUI.Style.Red, GUI.Style.Orange * 0.5f, brokenItem.Condition / brokenItem.MaxCondition) * alpha);
|
Color.Lerp(GUI.Style.Red, GUI.Style.Orange * 0.5f, brokenItem.Condition / brokenItem.MaxCondition) * alpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!character.IsIncapacitated && character.Stun <= 0.0f && !IsCampaignInterfaceOpen)
|
if (!character.IsIncapacitated && character.Stun <= 0.0f && !IsCampaignInterfaceOpen && (!character.IsKeyDown(InputType.Aim) || character.SelectedItems.Any(it => it?.GetComponent<Sprayer>() == null)))
|
||||||
{
|
{
|
||||||
if (character.FocusedCharacter != null && character.FocusedCharacter.CanBeSelected)
|
if (character.FocusedCharacter != null && character.FocusedCharacter.CanBeSelected)
|
||||||
{
|
{
|
||||||
@@ -307,6 +306,14 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
progressBar.Draw(spriteBatch, cam);
|
progressBar.Draw(spriteBatch, cam);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach (Character npc in Character.CharacterList)
|
||||||
|
{
|
||||||
|
if (npc.CampaignInteractionType == CampaignMode.InteractionType.None || npc.Submarine != character.Submarine || npc.IsDead || npc.IsIncapacitated) { continue; }
|
||||||
|
|
||||||
|
var iconStyle = GUI.Style.GetComponentStyle("CampaignInteractionIcon." + npc.CampaignInteractionType);
|
||||||
|
GUI.DrawIndicator(spriteBatch, npc.WorldPosition, cam, 500.0f, iconStyle.GetDefaultSprite(), iconStyle.Color);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (character.SelectedConstruction != null &&
|
if (character.SelectedConstruction != null &&
|
||||||
@@ -355,7 +362,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
if (ShouldDrawInventory(character))
|
if (ShouldDrawInventory(character))
|
||||||
{
|
{
|
||||||
character.Inventory.Locked = LockInventory(character);
|
character.Inventory.Locked = character == Character.Controlled && LockInventory(character);
|
||||||
character.Inventory.DrawOwn(spriteBatch);
|
character.Inventory.DrawOwn(spriteBatch);
|
||||||
character.Inventory.CurrentLayout = CharacterHealth.OpenHealthWindow == null && character.SelectedCharacter == null ?
|
character.Inventory.CurrentLayout = CharacterHealth.OpenHealthWindow == null && character.SelectedCharacter == null ?
|
||||||
CharacterInventory.Layout.Default :
|
CharacterInventory.Layout.Default :
|
||||||
@@ -369,14 +376,10 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (character.SelectedCharacter.CanInventoryBeAccessed)
|
if (character.SelectedCharacter.CanInventoryBeAccessed)
|
||||||
{
|
{
|
||||||
///character.Inventory.CurrentLayout = Alignment.Left;
|
character.SelectedCharacter.Inventory.Locked = false;
|
||||||
character.SelectedCharacter.Inventory.CurrentLayout = CharacterInventory.Layout.Left;
|
character.SelectedCharacter.Inventory.CurrentLayout = CharacterInventory.Layout.Left;
|
||||||
character.SelectedCharacter.Inventory.DrawOwn(spriteBatch);
|
character.SelectedCharacter.Inventory.DrawOwn(spriteBatch);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
//character.Inventory.CurrentLayout = (CharacterHealth.OpenHealthWindow == null) ? Alignment.Center : Alignment.Left;
|
|
||||||
}
|
|
||||||
if (CharacterHealth.OpenHealthWindow == character.SelectedCharacter.CharacterHealth)
|
if (CharacterHealth.OpenHealthWindow == character.SelectedCharacter.CharacterHealth)
|
||||||
{
|
{
|
||||||
character.SelectedCharacter.CharacterHealth.Alignment = Alignment.Left;
|
character.SelectedCharacter.CharacterHealth.Alignment = Alignment.Left;
|
||||||
@@ -450,7 +453,6 @@ namespace Barotrauma
|
|||||||
private static bool LockInventory(Character character)
|
private static bool LockInventory(Character character)
|
||||||
{
|
{
|
||||||
if (character?.Inventory == null || !character.AllowInput || character.LockHands || IsCampaignInterfaceOpen) { return true; }
|
if (character?.Inventory == null || !character.AllowInput || character.LockHands || IsCampaignInterfaceOpen) { return true; }
|
||||||
|
|
||||||
return character.ShouldLockHud();
|
return character.ShouldLockHud();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,8 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (this != Controlled)
|
if (this != Controlled)
|
||||||
{
|
{
|
||||||
if (GameMain.Client.EndCinematic != null) // Freezes the characters during the ending cinematic
|
if (GameMain.Client.EndCinematic != null &&
|
||||||
|
GameMain.Client.EndCinematic.Running) // Freezes the characters during the ending cinematic
|
||||||
{
|
{
|
||||||
AnimController.Frozen = true;
|
AnimController.Frozen = true;
|
||||||
memState.Clear();
|
memState.Clear();
|
||||||
|
|||||||
@@ -38,25 +38,43 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public Vector2 Size;
|
public Vector2 Size;
|
||||||
|
|
||||||
private Submarine parentSub;
|
private readonly Submarine parentSub;
|
||||||
|
public string Text
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
private set;
|
||||||
|
}
|
||||||
|
|
||||||
public HUDProgressBar(Vector2 worldPosition, Submarine parentSubmarine = null)
|
private string textTag;
|
||||||
: this(worldPosition, parentSubmarine, GUI.Style.Red, GUI.Style.Green)
|
public string TextTag
|
||||||
|
{
|
||||||
|
get { return textTag; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (textTag == value) { return; }
|
||||||
|
textTag = value;
|
||||||
|
Text = string.IsNullOrEmpty(textTag) ? string.Empty : TextManager.Get(textTag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public HUDProgressBar(Vector2 worldPosition, string textTag, Submarine parentSubmarine = null)
|
||||||
|
: this(worldPosition, parentSubmarine, GUI.Style.Red, GUI.Style.Green, textTag)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public HUDProgressBar(Vector2 worldPosition, Submarine parentSubmarine, Color emptyColor, Color fullColor)
|
public HUDProgressBar(Vector2 worldPosition, Submarine parentSubmarine, Color emptyColor, Color fullColor, string textTag)
|
||||||
{
|
{
|
||||||
this.emptyColor = emptyColor;
|
this.emptyColor = emptyColor;
|
||||||
this.fullColor = fullColor;
|
this.fullColor = fullColor;
|
||||||
|
|
||||||
parentSub = parentSubmarine;
|
parentSub = parentSubmarine;
|
||||||
|
|
||||||
WorldPosition = worldPosition;
|
WorldPosition = worldPosition;
|
||||||
|
|
||||||
Size = new Vector2(100.0f, 20.0f);
|
Size = new Vector2(100.0f, 20.0f);
|
||||||
|
|
||||||
FadeTimer = 1.0f;
|
FadeTimer = 1.0f;
|
||||||
|
if (!string.IsNullOrEmpty(textTag))
|
||||||
|
{
|
||||||
|
textTag = textTag;
|
||||||
|
Text = TextManager.Get(textTag);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Update(float deltatime)
|
public void Update(float deltatime)
|
||||||
@@ -76,12 +94,21 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
pos = cam.WorldToScreen(pos);
|
pos = cam.WorldToScreen(pos);
|
||||||
|
Color color = Color.Lerp(emptyColor, fullColor, progress);
|
||||||
GUI.DrawProgressBar(spriteBatch,
|
GUI.DrawProgressBar(spriteBatch,
|
||||||
new Vector2(pos.X, -pos.Y),
|
new Vector2(pos.X, -pos.Y),
|
||||||
Size, progress,
|
Size, progress,
|
||||||
Color.Lerp(emptyColor, fullColor, progress) * a,
|
color * a,
|
||||||
Color.White * a * 0.8f);
|
Color.White * a * 0.8f);
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(Text))
|
||||||
|
{
|
||||||
|
Vector2 textSize = GUI.SmallFont.MeasureString(Text);
|
||||||
|
Vector2 textPos = new Vector2(pos.X + (Size.X - textSize.X) / 2, pos.Y - textSize.Y * 1.2f);
|
||||||
|
GUI.DrawString(spriteBatch, textPos - Vector2.One, Text, Color.Black * a, font: GUI.SmallFont);
|
||||||
|
GUI.DrawString(spriteBatch, textPos, Text, Color.White * a, font: GUI.SmallFont);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private GUIButton suicideButton;
|
public GUIButton SuicideButton { get; private set; }
|
||||||
|
|
||||||
// healthbars
|
// healthbars
|
||||||
private GUIProgressBar healthBar;
|
private GUIProgressBar healthBar;
|
||||||
@@ -247,22 +247,6 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private GUIFrame healthBarHolder;
|
private GUIFrame healthBarHolder;
|
||||||
|
|
||||||
private Point healthBarOffset
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return new Point(Math.Max(2, GUI.IntScaleCeiling(1.5f)), Math.Min(GUI.IntScaleFloor(18f), 19));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Point healthBarSize
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return new Point(healthBarHolder.Rect.Width - Math.Min(GUI.IntScale(45f), 47), GUI.IntScale(15f));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
partial void InitProjSpecific(XElement element, Character character)
|
partial void InitProjSpecific(XElement element, Character character)
|
||||||
{
|
{
|
||||||
DisplayedVitality = MaxVitality;
|
DisplayedVitality = MaxVitality;
|
||||||
@@ -290,29 +274,22 @@ namespace Barotrauma
|
|||||||
healthBarHolder.RectTransform.NonScaledSize = HUDLayoutSettings.HealthBarArea.Size;
|
healthBarHolder.RectTransform.NonScaledSize = HUDLayoutSettings.HealthBarArea.Size;
|
||||||
healthBarHolder.RectTransform.RelativeOffset = Vector2.Zero;
|
healthBarHolder.RectTransform.RelativeOffset = Vector2.Zero;
|
||||||
|
|
||||||
GUIFrame healthBarBG = new GUIFrame(new RectTransform(Vector2.One, healthBarHolder.RectTransform), style: "CharacterHealthBarBG")
|
healthBarShadow = new GUIProgressBar(new RectTransform(Vector2.One, healthBarHolder.RectTransform, Anchor.BottomRight),
|
||||||
{
|
barSize: 1.0f, color: Color.Green, style: horizontal ? "CharacterHealthBar" : "GUIProgressBarVertical", showFrame: false)
|
||||||
CanBeFocused = false
|
|
||||||
};
|
|
||||||
|
|
||||||
healthBarShadow = new GUIProgressBar(new RectTransform(healthBarSize, healthBarHolder.RectTransform, Anchor.BottomRight),
|
|
||||||
barSize: 1.0f, color: Color.Green, style: horizontal ? "CharacterHealthBarSlider" : "GUIProgressBarVertical", showFrame: false)
|
|
||||||
{
|
{
|
||||||
IsHorizontal = horizontal
|
IsHorizontal = horizontal
|
||||||
};
|
};
|
||||||
healthBarShadow.Visible = false;
|
healthBarShadow.Visible = false;
|
||||||
healthShadowSize = 1.0f;
|
healthShadowSize = 1.0f;
|
||||||
|
|
||||||
healthBar = new GUIProgressBar(new RectTransform(healthBarSize, healthBarHolder.RectTransform, Anchor.BottomRight),
|
healthBar = new GUIProgressBar(new RectTransform(Vector2.One, healthBarHolder.RectTransform, Anchor.BottomRight),
|
||||||
barSize: 1.0f, color: GUI.Style.HealthBarColorHigh, style: horizontal ? "CharacterHealthBarSlider" : "GUIProgressBarVertical", showFrame: false)
|
barSize: 1.0f, color: GUI.Style.HealthBarColorHigh, style: horizontal ? "CharacterHealthBar" : "GUIProgressBarVertical")
|
||||||
{
|
{
|
||||||
HoverCursor = CursorState.Hand,
|
HoverCursor = CursorState.Hand,
|
||||||
Enabled = true,
|
Enabled = true,
|
||||||
IsHorizontal = horizontal
|
IsHorizontal = horizontal
|
||||||
};
|
};
|
||||||
|
|
||||||
healthBar.RectTransform.AbsoluteOffset = healthBarShadow.RectTransform.AbsoluteOffset = healthBarOffset;
|
|
||||||
|
|
||||||
healthInterfaceFrame = new GUIFrame(new RectTransform(new Vector2(0.7f, 0.55f), GUI.Canvas, anchor: Anchor.Center, scaleBasis: ScaleBasis.Smallest), style: "ItemUI");
|
healthInterfaceFrame = new GUIFrame(new RectTransform(new Vector2(0.7f, 0.55f), GUI.Canvas, anchor: Anchor.Center, scaleBasis: ScaleBasis.Smallest), style: "ItemUI");
|
||||||
|
|
||||||
var healthInterfaceLayout = new GUILayoutGroup(new RectTransform(Vector2.One / 1.05f, healthInterfaceFrame.RectTransform, anchor: Anchor.Center), true);
|
var healthInterfaceLayout = new GUILayoutGroup(new RectTransform(Vector2.One / 1.05f, healthInterfaceFrame.RectTransform, anchor: Anchor.Center), true);
|
||||||
@@ -519,7 +496,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
UpdateAlignment();
|
UpdateAlignment();
|
||||||
|
|
||||||
suicideButton = new GUIButton(new RectTransform(new Vector2(0.1f, 0.02f), GUI.Canvas, Anchor.TopCenter)
|
SuicideButton = new GUIButton(new RectTransform(new Vector2(0.1f, 0.02f), GUI.Canvas, Anchor.TopCenter)
|
||||||
{
|
{
|
||||||
MinSize = new Point(150, 20), RelativeOffset = new Vector2(0.0f, 0.01f)
|
MinSize = new Point(150, 20), RelativeOffset = new Vector2(0.0f, 0.01f)
|
||||||
},
|
},
|
||||||
@@ -546,7 +523,7 @@ namespace Barotrauma
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
suicideButton.TextBlock.AutoScaleHorizontal = true;
|
SuicideButton.TextBlock.AutoScaleHorizontal = true;
|
||||||
|
|
||||||
if (element != null)
|
if (element != null)
|
||||||
{
|
{
|
||||||
@@ -591,9 +568,6 @@ namespace Barotrauma
|
|||||||
healthBarHolder.RectTransform.NonScaledSize = HUDLayoutSettings.HealthBarArea.Size;
|
healthBarHolder.RectTransform.NonScaledSize = HUDLayoutSettings.HealthBarArea.Size;
|
||||||
healthBarHolder.RectTransform.RelativeOffset = Vector2.Zero;
|
healthBarHolder.RectTransform.RelativeOffset = Vector2.Zero;
|
||||||
|
|
||||||
healthBar.RectTransform.NonScaledSize = healthBarShadow.RectTransform.NonScaledSize = healthBarSize;
|
|
||||||
healthBar.RectTransform.AbsoluteOffset = healthBarShadow.RectTransform.AbsoluteOffset = healthBarOffset;
|
|
||||||
|
|
||||||
switch (alignment)
|
switch (alignment)
|
||||||
{
|
{
|
||||||
case Alignment.Left:
|
case Alignment.Left:
|
||||||
@@ -943,23 +917,7 @@ namespace Barotrauma
|
|||||||
healthBar.State = GUIComponent.ComponentState.None;
|
healthBar.State = GUIComponent.ComponentState.None;
|
||||||
}
|
}
|
||||||
|
|
||||||
suicideButton.Visible = Character == Character.Controlled && !Character.IsDead && Character.IsIncapacitated;
|
SuicideButton.Visible = Character == Character.Controlled && !Character.IsDead && Character.IsIncapacitated;
|
||||||
|
|
||||||
if (GameMain.GameSession?.Campaign is { } campaign)
|
|
||||||
{
|
|
||||||
RectTransform endRoundButton = campaign?.EndRoundButton.RectTransform;
|
|
||||||
if (endRoundButton != null)
|
|
||||||
{
|
|
||||||
if (suicideButton.Visible)
|
|
||||||
{
|
|
||||||
endRoundButton.ScreenSpaceOffset = new Point(0, suicideButton.Rect.Height);
|
|
||||||
}
|
|
||||||
else if (endRoundButton.ScreenSpaceOffset != Point.Zero)
|
|
||||||
{
|
|
||||||
endRoundButton.ScreenSpaceOffset = Point.Zero;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cprButton.Visible =
|
cprButton.Visible =
|
||||||
Character == Character.Controlled?.SelectedCharacter
|
Character == Character.Controlled?.SelectedCharacter
|
||||||
@@ -992,9 +950,9 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
healthBarHolder.AddToGUIUpdateList();
|
healthBarHolder.AddToGUIUpdateList();
|
||||||
}
|
}
|
||||||
if (suicideButton.Visible && Character == Character.Controlled)
|
if (SuicideButton.Visible && Character == Character.Controlled)
|
||||||
{
|
{
|
||||||
suicideButton.AddToGUIUpdateList();
|
SuicideButton.AddToGUIUpdateList();
|
||||||
}
|
}
|
||||||
if (cprButton != null && cprButton.Visible)
|
if (cprButton != null && cprButton.Visible)
|
||||||
{
|
{
|
||||||
@@ -1907,6 +1865,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private readonly List<Pair<AfflictionPrefab, float>> newAfflictions = new List<Pair<AfflictionPrefab, float>>();
|
private readonly List<Pair<AfflictionPrefab, float>> newAfflictions = new List<Pair<AfflictionPrefab, float>>();
|
||||||
private readonly List<Triplet<LimbHealth, AfflictionPrefab, float>> newLimbAfflictions = new List<Triplet<LimbHealth, AfflictionPrefab, float>>();
|
private readonly List<Triplet<LimbHealth, AfflictionPrefab, float>> newLimbAfflictions = new List<Triplet<LimbHealth, AfflictionPrefab, float>>();
|
||||||
|
private readonly List<Pair<AfflictionPrefab.PeriodicEffect, float>> newPeriodicEffects = new List<Pair<AfflictionPrefab.PeriodicEffect, float>>();
|
||||||
|
|
||||||
public void ClientRead(IReadMessage inc)
|
public void ClientRead(IReadMessage inc)
|
||||||
{
|
{
|
||||||
newAfflictions.Clear();
|
newAfflictions.Clear();
|
||||||
@@ -1920,9 +1880,20 @@ namespace Barotrauma
|
|||||||
DebugConsole.ThrowError("Error while reading character health data: affliction with the uint ID " + afflictionID + " not found.");
|
DebugConsole.ThrowError("Error while reading character health data: affliction with the uint ID " + afflictionID + " not found.");
|
||||||
//read the 8 bytes for affliction strength anyway to prevent messing up reading rest of the message
|
//read the 8 bytes for affliction strength anyway to prevent messing up reading rest of the message
|
||||||
_ = inc.ReadRangedSingle(0.0f, 100.0f, 8);
|
_ = inc.ReadRangedSingle(0.0f, 100.0f, 8);
|
||||||
|
int _periodicAfflictionCount = inc.ReadByte();
|
||||||
|
for (int j = 0; j < _periodicAfflictionCount; j++)
|
||||||
|
{
|
||||||
|
_ = inc.ReadByte();
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
float afflictionStrength = inc.ReadRangedSingle(0.0f, afflictionPrefab.MaxStrength, 8);
|
float afflictionStrength = inc.ReadRangedSingle(0.0f, afflictionPrefab.MaxStrength, 8);
|
||||||
|
int periodicAfflictionCount = inc.ReadByte();
|
||||||
|
for (int j = 0; j < periodicAfflictionCount; j++)
|
||||||
|
{
|
||||||
|
float periodicAfflictionTimer = inc.ReadRangedSingle(afflictionPrefab.PeriodicEffects[j].MinInterval, afflictionPrefab.PeriodicEffects[j].MaxInterval, 8);
|
||||||
|
newPeriodicEffects.Add(new Pair<AfflictionPrefab.PeriodicEffect, float>(afflictionPrefab.PeriodicEffects[j], periodicAfflictionTimer));
|
||||||
|
}
|
||||||
newAfflictions.Add(new Pair<AfflictionPrefab, float>(afflictionPrefab, afflictionStrength));
|
newAfflictions.Add(new Pair<AfflictionPrefab, float>(afflictionPrefab, afflictionStrength));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1940,12 +1911,26 @@ namespace Barotrauma
|
|||||||
Affliction existingAffliction = afflictions.Find(a => a.Prefab == newAffliction.First);
|
Affliction existingAffliction = afflictions.Find(a => a.Prefab == newAffliction.First);
|
||||||
if (existingAffliction == null)
|
if (existingAffliction == null)
|
||||||
{
|
{
|
||||||
afflictions.Add(newAffliction.First.Instantiate(newAffliction.Second));
|
existingAffliction = newAffliction.First.Instantiate(newAffliction.Second);
|
||||||
|
afflictions.Add(existingAffliction);
|
||||||
}
|
}
|
||||||
else
|
existingAffliction.SetStrength(newAffliction.Second);
|
||||||
|
if (existingAffliction == stunAffliction)
|
||||||
{
|
{
|
||||||
existingAffliction.Strength = newAffliction.Second;
|
Character.SetStun(existingAffliction.Strength, true, true);
|
||||||
if (existingAffliction == stunAffliction) Character.SetStun(existingAffliction.Strength, true, true);
|
}
|
||||||
|
foreach (var periodicEffect in newPeriodicEffects)
|
||||||
|
{
|
||||||
|
if (!existingAffliction.Prefab.PeriodicEffects.Contains(periodicEffect.First)) { continue; }
|
||||||
|
//timer has wrapped around, apply the effect
|
||||||
|
if (periodicEffect.Second - existingAffliction.PeriodicEffectTimers[periodicEffect.First] > periodicEffect.First.MinInterval / 2)
|
||||||
|
{
|
||||||
|
existingAffliction.PeriodicEffectTimers[periodicEffect.First] = periodicEffect.Second;
|
||||||
|
foreach (StatusEffect effect in periodicEffect.First.StatusEffects)
|
||||||
|
{
|
||||||
|
existingAffliction.ApplyStatusEffect(effect, deltaTime: 1.0f, this, targetLimb: null);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1961,9 +1946,20 @@ namespace Barotrauma
|
|||||||
DebugConsole.ThrowError("Error while reading character health data: affliction with the uint ID " + afflictionID + " not found.");
|
DebugConsole.ThrowError("Error while reading character health data: affliction with the uint ID " + afflictionID + " not found.");
|
||||||
//read the 8 bytes for affliction strength anyway to prevent messing up reading rest of the message
|
//read the 8 bytes for affliction strength anyway to prevent messing up reading rest of the message
|
||||||
_ = inc.ReadRangedSingle(0.0f, 100.0f, 8);
|
_ = inc.ReadRangedSingle(0.0f, 100.0f, 8);
|
||||||
|
int _periodicAfflictionCount = inc.ReadByte();
|
||||||
|
for (int j = 0; j < _periodicAfflictionCount; j++)
|
||||||
|
{
|
||||||
|
_ = inc.ReadByte();
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
float afflictionStrength = inc.ReadRangedSingle(0.0f, afflictionPrefab.MaxStrength, 8);
|
float afflictionStrength = inc.ReadRangedSingle(0.0f, afflictionPrefab.MaxStrength, 8);
|
||||||
|
int periodicAfflictionCount = inc.ReadByte();
|
||||||
|
for (int j = 0; j < periodicAfflictionCount; j++)
|
||||||
|
{
|
||||||
|
float periodicAfflictionTimer = inc.ReadRangedSingle(afflictionPrefab.PeriodicEffects[j].MinInterval, afflictionPrefab.PeriodicEffects[j].MaxInterval, 8);
|
||||||
|
newPeriodicEffects.Add(new Pair<AfflictionPrefab.PeriodicEffect, float>(afflictionPrefab.PeriodicEffects[j], periodicAfflictionTimer));
|
||||||
|
}
|
||||||
newLimbAfflictions.Add(new Triplet<LimbHealth, AfflictionPrefab, float>(limbHealths[limbIndex], afflictionPrefab, afflictionStrength));
|
newLimbAfflictions.Add(new Triplet<LimbHealth, AfflictionPrefab, float>(limbHealths[limbIndex], afflictionPrefab, afflictionStrength));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1980,15 +1976,28 @@ namespace Barotrauma
|
|||||||
|
|
||||||
foreach (Triplet<LimbHealth, AfflictionPrefab, float> newAffliction in newLimbAfflictions)
|
foreach (Triplet<LimbHealth, AfflictionPrefab, float> newAffliction in newLimbAfflictions)
|
||||||
{
|
{
|
||||||
if (newAffliction.First != limbHealth) continue;
|
if (newAffliction.First != limbHealth) { continue; }
|
||||||
Affliction existingAffliction = limbHealth.Afflictions.Find(a => a.Prefab == newAffliction.Second);
|
Affliction existingAffliction = limbHealth.Afflictions.Find(a => a.Prefab == newAffliction.Second);
|
||||||
if (existingAffliction == null)
|
if (existingAffliction == null)
|
||||||
{
|
{
|
||||||
limbHealth.Afflictions.Add(newAffliction.Second.Instantiate(newAffliction.Third));
|
existingAffliction = newAffliction.Second.Instantiate(newAffliction.Third);
|
||||||
|
limbHealth.Afflictions.Add(existingAffliction);
|
||||||
}
|
}
|
||||||
else
|
existingAffliction.SetStrength(newAffliction.Third);
|
||||||
|
|
||||||
|
foreach (var periodicEffect in newPeriodicEffects)
|
||||||
{
|
{
|
||||||
existingAffliction.Strength = newAffliction.Third;
|
if (!existingAffliction.Prefab.PeriodicEffects.Contains(periodicEffect.First)) { continue; }
|
||||||
|
//timer has wrapped around, apply the effect
|
||||||
|
if (periodicEffect.Second - existingAffliction.PeriodicEffectTimers[periodicEffect.First] > periodicEffect.First.MinInterval / 2)
|
||||||
|
{
|
||||||
|
existingAffliction.PeriodicEffectTimers[periodicEffect.First] = periodicEffect.Second;
|
||||||
|
foreach (StatusEffect effect in periodicEffect.First.StatusEffects)
|
||||||
|
{
|
||||||
|
Limb targetLimb = Character.AnimController.Limbs.FirstOrDefault(l => l.HealthIndex == limbHealths.IndexOf(newAffliction.First));
|
||||||
|
existingAffliction.ApplyStatusEffect(effect, deltaTime: 1.0f, this, targetLimb: targetLimb);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -446,7 +446,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (affliction is AfflictionBleeding)
|
if (affliction is AfflictionBleeding)
|
||||||
{
|
{
|
||||||
bleedingDamage += affliction.GetVitalityDecrease(character.CharacterHealth);
|
bleedingDamage += affliction.GetVitalityDecrease(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -455,7 +455,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (affliction.Prefab.AfflictionType == "damage")
|
if (affliction.Prefab.AfflictionType == "damage")
|
||||||
{
|
{
|
||||||
damage += affliction.GetVitalityDecrease(character.CharacterHealth);
|
damage += affliction.GetVitalityDecrease(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
float damageMultiplier = 1;
|
float damageMultiplier = 1;
|
||||||
@@ -488,7 +488,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
// spawn damage particles
|
// spawn damage particles
|
||||||
float damageParticleAmount = Math.Min(damage / 10, 1.0f) * damageMultiplier;
|
float damageParticleAmount = Math.Min(damage / 5, 1.0f) * damageMultiplier;
|
||||||
if (damageParticleAmount > 0.001f)
|
if (damageParticleAmount > 0.001f)
|
||||||
{
|
{
|
||||||
foreach (ParticleEmitter emitter in character.DamageEmitters)
|
foreach (ParticleEmitter emitter in character.DamageEmitters)
|
||||||
@@ -510,11 +510,6 @@ namespace Barotrauma
|
|||||||
if (!inWater && emitter.Prefab.ParticlePrefab.DrawTarget == ParticlePrefab.DrawTargetType.Water) { continue; }
|
if (!inWater && emitter.Prefab.ParticlePrefab.DrawTarget == ParticlePrefab.DrawTargetType.Water) { continue; }
|
||||||
emitter.Emit(1.0f, WorldPosition, character.CurrentHull, sizeMultiplier: bloodParticleSize, amountMultiplier: bloodParticleAmount);
|
emitter.Emit(1.0f, WorldPosition, character.CurrentHull, sizeMultiplier: bloodParticleSize, amountMultiplier: bloodParticleAmount);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bloodParticleAmount > 0 && character.CurrentHull != null && !string.IsNullOrEmpty(character.BloodDecalName))
|
|
||||||
{
|
|
||||||
character.CurrentHull.AddDecal(character.BloodDecalName, WorldPosition, MathHelper.Clamp(bloodParticleSize, 0.5f, 1.0f));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1086,17 +1086,6 @@ namespace Barotrauma
|
|||||||
AssignRelayToServer("water|editwater", false);
|
AssignRelayToServer("water|editwater", false);
|
||||||
AssignRelayToServer("fire|editfire", false);
|
AssignRelayToServer("fire|editfire", false);
|
||||||
|
|
||||||
commands.Add(new Command("togglecampaignteleport", "togglecampaignteleport: Toggle on/off teleportation between campaign locations by double clicking on the campaign map.", (string[] args) =>
|
|
||||||
{
|
|
||||||
if (GameMain.GameSession?.Campaign == null)
|
|
||||||
{
|
|
||||||
ThrowError("No campaign active.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
GameMain.GameSession.Map.AllowDebugTeleport = !GameMain.GameSession.Map.AllowDebugTeleport;
|
|
||||||
NewMessage((GameMain.GameSession.Map.AllowDebugTeleport ? "Enabled" : "Disabled") + " teleportation on the campaign map.", Color.White);
|
|
||||||
}, isCheat: true));
|
|
||||||
|
|
||||||
commands.Add(new Command("mute", "mute [name]: Prevent the client from speaking to anyone through the voice chat. Using this command requires a permission from the server host.",
|
commands.Add(new Command("mute", "mute [name]: Prevent the client from speaking to anyone through the voice chat. Using this command requires a permission from the server host.",
|
||||||
null,
|
null,
|
||||||
() =>
|
() =>
|
||||||
@@ -1136,7 +1125,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
foreach (var ingredient in fabricationRecipe.RequiredItems)
|
foreach (var ingredient in fabricationRecipe.RequiredItems)
|
||||||
{
|
{
|
||||||
int? ingredientPrice = ingredient.ItemPrefab.GetMinPrice();
|
int? ingredientPrice = ingredient.ItemPrefabs.Min(ip => ip.GetMinPrice());
|
||||||
if (ingredientPrice.HasValue)
|
if (ingredientPrice.HasValue)
|
||||||
{
|
{
|
||||||
if (!fabricationCost.HasValue) { fabricationCost = 0; }
|
if (!fabricationCost.HasValue) { fabricationCost = 0; }
|
||||||
@@ -1163,14 +1152,14 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (fabricationRecipe != null)
|
if (fabricationRecipe != null)
|
||||||
{
|
{
|
||||||
var ingredient = fabricationRecipe.RequiredItems.Find(r => r.ItemPrefab == targetItem);
|
var ingredient = fabricationRecipe.RequiredItems.Find(r => r.ItemPrefabs.Contains(targetItem));
|
||||||
if (ingredient == null)
|
if (ingredient == null)
|
||||||
{
|
{
|
||||||
NewMessage("Deconstructing \"" + itemPrefab.Name + "\" produces \"" + deconstructItem.ItemIdentifier + "\", which isn't required in the fabrication recipe of the item.", Color.Red);
|
NewMessage("Deconstructing \"" + itemPrefab.Name + "\" produces \"" + deconstructItem.ItemIdentifier + "\", which isn't required in the fabrication recipe of the item.", Color.Red);
|
||||||
}
|
}
|
||||||
else if (ingredient.UseCondition && ingredient.MinCondition < deconstructItem.OutCondition)
|
else if (ingredient.UseCondition && ingredient.MinCondition < deconstructItem.OutCondition)
|
||||||
{
|
{
|
||||||
NewMessage($"Deconstructing \"{itemPrefab.Name}\" produces more \"{deconstructItem.ItemIdentifier}\", than what's required to fabricate the item (required: {ingredient.ItemPrefab.Name} {(int)(ingredient.MinCondition * 100)}%, output: {deconstructItem.ItemIdentifier} {(int)(deconstructItem.OutCondition * 100)}%)", Color.Red);
|
NewMessage($"Deconstructing \"{itemPrefab.Name}\" produces more \"{deconstructItem.ItemIdentifier}\", than what's required to fabricate the item (required: {targetItem.Name} {(int)(ingredient.MinCondition * 100)}%, output: {deconstructItem.ItemIdentifier} {(int)(deconstructItem.OutCondition * 100)}%)", Color.Red);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1389,6 +1378,39 @@ namespace Barotrauma
|
|||||||
ToolBox.OpenFileWithShell(Path.GetFullPath(filePath));
|
ToolBox.OpenFileWithShell(Path.GetFullPath(filePath));
|
||||||
}));
|
}));
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
|
commands.Add(new Command("setplanthealth", "setplanthealth [value]: Sets the health of the selected plant in sub editor.", (string[] args) =>
|
||||||
|
{
|
||||||
|
if (1 > args.Length || Screen.Selected != GameMain.SubEditorScreen) { return; }
|
||||||
|
|
||||||
|
string arg = args[0];
|
||||||
|
|
||||||
|
if (!float.TryParse(arg, out float value))
|
||||||
|
{
|
||||||
|
ThrowError($"{arg} is not a valid value.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (MapEntity me in MapEntity.SelectedList)
|
||||||
|
{
|
||||||
|
if (me is Item it)
|
||||||
|
{
|
||||||
|
if (it.GetComponent<Planter>() is { } planter)
|
||||||
|
{
|
||||||
|
foreach (Growable seed in planter.GrowableSeeds.Where(s => s != null))
|
||||||
|
{
|
||||||
|
NewMessage($"Set the health of {seed.Name} to {value} (from {seed.Health})");
|
||||||
|
seed.Health = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (it.GetComponent<Growable>() is { } seed)
|
||||||
|
{
|
||||||
|
NewMessage($"Set the health of {seed.Name} to {value} (from {seed.Health})");
|
||||||
|
seed.Health = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
commands.Add(new Command("printreceivertransfers", "", (string[] args) =>
|
commands.Add(new Command("printreceivertransfers", "", (string[] args) =>
|
||||||
{
|
{
|
||||||
GameMain.Client.PrintReceiverTransters();
|
GameMain.Client.PrintReceiverTransters();
|
||||||
@@ -2012,7 +2034,7 @@ namespace Barotrauma
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
GameMain.Config.SelectCorePackage(GameMain.Config.SelectedContentPackages.First(cp => cp.CorePackage), true);
|
GameMain.Config.SelectCorePackage(GameMain.Config.CurrentCorePackage, true);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
commands.Add(new Command("ingamemodswap", "", (string[] args) =>
|
commands.Add(new Command("ingamemodswap", "", (string[] args) =>
|
||||||
@@ -2041,7 +2063,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
ShowQuestionPrompt("Permission to grant to client " + args[0] + "?", (perm) =>
|
ShowQuestionPrompt("Permission to grant to client " + args[0] + "?", (perm) =>
|
||||||
{
|
{
|
||||||
GameMain.Client?.SendConsoleCommand("giveperm " + args[0] + " " + perm);
|
GameMain.Client?.SendConsoleCommand("giveperm \"" + args[0] + "\" " + perm);
|
||||||
}, args, 1);
|
}, args, 1);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -2060,7 +2082,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
ShowQuestionPrompt("Permission to revoke from client " + args[0] + "?", (perm) =>
|
ShowQuestionPrompt("Permission to revoke from client " + args[0] + "?", (perm) =>
|
||||||
{
|
{
|
||||||
GameMain.Client?.SendConsoleCommand("revokeperm " + args[0] + " " + perm);
|
GameMain.Client?.SendConsoleCommand("revokeperm \"" + args[0] + "\" " + perm);
|
||||||
}, args, 1);
|
}, args, 1);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -2078,7 +2100,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
ShowQuestionPrompt("Rank to grant to client " + args[0] + "?", (rank) =>
|
ShowQuestionPrompt("Rank to grant to client " + args[0] + "?", (rank) =>
|
||||||
{
|
{
|
||||||
GameMain.Client?.SendConsoleCommand("giverank " + args[0] + " " + rank);
|
GameMain.Client?.SendConsoleCommand("giverank \"" + args[0] + "\" " + rank);
|
||||||
}, args, 1);
|
}, args, 1);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -2091,7 +2113,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
ShowQuestionPrompt("Console command permissions to grant to client " + args[0] + "? You may enter multiple commands separated with a space or use \"all\" to give the permission to use all console commands.", (commandNames) =>
|
ShowQuestionPrompt("Console command permissions to grant to client " + args[0] + "? You may enter multiple commands separated with a space or use \"all\" to give the permission to use all console commands.", (commandNames) =>
|
||||||
{
|
{
|
||||||
GameMain.Client?.SendConsoleCommand("givecommandperm " + args[0] + " " + commandNames);
|
GameMain.Client?.SendConsoleCommand("givecommandperm \"" + args[0] + "\" " + commandNames);
|
||||||
}, args, 1);
|
}, args, 1);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -2104,7 +2126,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
ShowQuestionPrompt("Console command permissions to revoke from client " + args[0] + "? You may enter multiple commands separated with a space or use \"all\" to revoke the permission to use any console commands.", (commandNames) =>
|
ShowQuestionPrompt("Console command permissions to revoke from client " + args[0] + "? You may enter multiple commands separated with a space or use \"all\" to revoke the permission to use any console commands.", (commandNames) =>
|
||||||
{
|
{
|
||||||
GameMain.Client?.SendConsoleCommand("revokecommandperm " + args[0] + " " + commandNames);
|
GameMain.Client?.SendConsoleCommand("revokecommandperm \"" + args[0] + "\" " + commandNames);
|
||||||
}, args, 1);
|
}, args, 1);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -2505,7 +2527,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}, isCheat: true));
|
}, isCheat: true));
|
||||||
|
|
||||||
commands.Add(new Command("spawnsub", "spawnsub [subname]: Spawn a submarine at the position of the cursor", (string[] args) =>
|
commands.Add(new Command("spawnsub", "spawnsub [subname] [is thalamus]: Spawn a submarine at the position of the cursor", (string[] args) =>
|
||||||
{
|
{
|
||||||
if (GameMain.NetworkMember != null)
|
if (GameMain.NetworkMember != null)
|
||||||
{
|
{
|
||||||
@@ -2528,6 +2550,25 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
Submarine spawnedSub = Submarine.Load(subInfo, false);
|
Submarine spawnedSub = Submarine.Load(subInfo, false);
|
||||||
spawnedSub.SetPosition(GameMain.GameScreen.Cam.ScreenToWorld(PlayerInput.MousePosition));
|
spawnedSub.SetPosition(GameMain.GameScreen.Cam.ScreenToWorld(PlayerInput.MousePosition));
|
||||||
|
if (subInfo.Type == SubmarineType.Wreck)
|
||||||
|
{
|
||||||
|
spawnedSub.MakeWreck();
|
||||||
|
if (args.Length > 1 && bool.TryParse(args[1], out bool isThalamus))
|
||||||
|
{
|
||||||
|
if (isThalamus)
|
||||||
|
{
|
||||||
|
spawnedSub.CreateWreckAI();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
spawnedSub.DisableWreckAI();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
spawnedSub.DisableWreckAI();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Barotrauma
|
||||||
|
{
|
||||||
|
partial class Decal
|
||||||
|
{
|
||||||
|
|
||||||
|
public void Draw(SpriteBatch spriteBatch, Hull hull, float depth)
|
||||||
|
{
|
||||||
|
Vector2 drawPos = position + hull.Rect.Location.ToVector2();
|
||||||
|
if (hull.Submarine != null) { drawPos += hull.Submarine.DrawPosition; }
|
||||||
|
drawPos.Y = -drawPos.Y;
|
||||||
|
|
||||||
|
spriteBatch.Draw(Sprite.Texture, drawPos, clippedSourceRect, Color * GetAlpha(), 0, Vector2.Zero, Scale, SpriteEffects.None, depth);
|
||||||
|
|
||||||
|
if (GameMain.DebugDraw && affectedSections != null && affectedSections.Count > 0)
|
||||||
|
{
|
||||||
|
Vector2 drawOffset = hull.Submarine == null ? Vector2.Zero : hull.Submarine.DrawPosition;
|
||||||
|
Point sectionSize = affectedSections.First().Rect.Size;
|
||||||
|
Rectangle drawPositionRect = new Rectangle((int)(drawOffset.X + hull.Rect.X), (int)(drawOffset.Y + hull.Rect.Y), sectionSize.X, sectionSize.Y);
|
||||||
|
|
||||||
|
foreach (var section in affectedSections)
|
||||||
|
{
|
||||||
|
// Draw colors
|
||||||
|
GUI.DrawRectangle(spriteBatch, new Vector2(drawPositionRect.X + section.Rect.X, -(drawPositionRect.Y + section.Rect.Y)), new Vector2(sectionSize.X, sectionSize.Y), Color.Red, false, 0.0f, (int)Math.Max(1.5f / Screen.Selected.Cam.Zoom, 1.0f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -67,7 +67,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
GUIListBox conversationList = lastMessageBox.FindChild("conversationlist", true) as GUIListBox;
|
GUIListBox conversationList = lastMessageBox.FindChild("conversationlist", true) as GUIListBox;
|
||||||
Debug.Assert(conversationList != null);
|
Debug.Assert(conversationList != null);
|
||||||
|
|
||||||
// gray out the last text block
|
// gray out the last text block
|
||||||
if (conversationList.Content.Children.LastOrDefault() is GUILayoutGroup lastElement)
|
if (conversationList.Content.Children.LastOrDefault() is GUILayoutGroup lastElement)
|
||||||
{
|
{
|
||||||
@@ -132,17 +132,19 @@ namespace Barotrauma
|
|||||||
};
|
};
|
||||||
shadow.SetAsFirstChild();
|
shadow.SetAsFirstChild();
|
||||||
|
|
||||||
void RecalculateLastMessage(GUIListBox conversationList, bool append)
|
static void RecalculateLastMessage(GUIListBox conversationList, bool append)
|
||||||
{
|
{
|
||||||
if (conversationList.Content.Children.LastOrDefault() is GUILayoutGroup lastElement)
|
if (conversationList.Content.Children.LastOrDefault() is GUILayoutGroup lastElement)
|
||||||
{
|
{
|
||||||
GUILayoutGroup textLayout = lastElement.GetChild<GUILayoutGroup>();
|
GUILayoutGroup textLayout = lastElement.GetChild<GUILayoutGroup>();
|
||||||
if (lastElement.Rect.Size.Y < textLayout.Rect.Size.Y && !append)
|
|
||||||
{
|
|
||||||
lastElement.RectTransform.MinSize = textLayout.Rect.Size;
|
|
||||||
}
|
|
||||||
if (textLayout != null)
|
if (textLayout != null)
|
||||||
{
|
{
|
||||||
|
if (lastElement.Rect.Size.Y < textLayout.Rect.Size.Y && !append)
|
||||||
|
{
|
||||||
|
lastElement.RectTransform.MinSize = textLayout.Rect.Size;
|
||||||
|
}
|
||||||
|
|
||||||
int textHeight = textLayout.Children.Sum(c => c.Rect.Height);
|
int textHeight = textLayout.Children.Sum(c => c.Rect.Height);
|
||||||
textLayout.RectTransform.MaxSize = new Point(lastElement.RectTransform.MaxSize.X, textHeight);
|
textLayout.RectTransform.MaxSize = new Point(lastElement.RectTransform.MaxSize.X, textHeight);
|
||||||
textLayout.Recalculate();
|
textLayout.Recalculate();
|
||||||
@@ -323,7 +325,10 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
textContent.RectTransform.MinSize = new Point(0, textContent.Children.Sum(c => c.Rect.Height + textContent.AbsoluteSpacing) + GUI.IntScale(16));
|
textContent.RectTransform.MinSize = new Point(0, textContent.Children.Sum(c => c.Rect.Height + textContent.AbsoluteSpacing) + GUI.IntScale(16));
|
||||||
// content.RectTransform.MinSize = new Point(0, textContent.Rect.Height);
|
|
||||||
|
// Recalculate the text size as it is scaled up and no longer matching the text height due to the textContent's minSize increasing
|
||||||
|
textBlock.CalculateHeightFromText();
|
||||||
|
//content.RectTransform.MinSize = new Point(0, textContent.Rect.Height);
|
||||||
|
|
||||||
return buttons;
|
return buttons;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,10 +17,11 @@ namespace Barotrauma
|
|||||||
private float intensityGraphUpdateInterval;
|
private float intensityGraphUpdateInterval;
|
||||||
private float lastIntensityUpdate;
|
private float lastIntensityUpdate;
|
||||||
|
|
||||||
private Event? pinnedEvent;
|
|
||||||
private Vector2 pinnedPosition = new Vector2(256, 128);
|
private Vector2 pinnedPosition = new Vector2(256, 128);
|
||||||
private bool isDragging;
|
private bool isDragging;
|
||||||
|
|
||||||
|
public Event? PinnedEvent { get; set; }
|
||||||
|
|
||||||
public void DebugDraw(SpriteBatch spriteBatch)
|
public void DebugDraw(SpriteBatch spriteBatch)
|
||||||
{
|
{
|
||||||
foreach (Event ev in activeEvents)
|
foreach (Event ev in activeEvents)
|
||||||
@@ -104,12 +105,21 @@ namespace Barotrauma
|
|||||||
GUI.DrawString(spriteBatch, new Vector2(graphRect.X, y), "New event (ID " + eventSet.DebugIdentifier + ") after: ", Color.Orange * 0.8f, null, 0, GUI.SmallFont);
|
GUI.DrawString(spriteBatch, new Vector2(graphRect.X, y), "New event (ID " + eventSet.DebugIdentifier + ") after: ", Color.Orange * 0.8f, null, 0, GUI.SmallFont);
|
||||||
y += 12;
|
y += 12;
|
||||||
|
|
||||||
if ((Submarine.MainSub == null || distanceTraveled < eventSet.MinDistanceTraveled) &&
|
if (eventSet.PerWreck)
|
||||||
roundDuration < eventSet.MinMissionTime)
|
{
|
||||||
|
GUI.DrawString(spriteBatch, new Vector2(graphRect.X, y), " submarine near the wreck", Color.Orange * 0.8f, null, 0, GUI.SmallFont);
|
||||||
|
y += 12;
|
||||||
|
}
|
||||||
|
if (eventSet.PerRuin)
|
||||||
|
{
|
||||||
|
GUI.DrawString(spriteBatch, new Vector2(graphRect.X, y), " submarine near the ruins", Color.Orange * 0.8f, null, 0, GUI.SmallFont);
|
||||||
|
y += 12;
|
||||||
|
}
|
||||||
|
if (roundDuration < eventSet.MinMissionTime)
|
||||||
{
|
{
|
||||||
GUI.DrawString(spriteBatch, new Vector2(graphRect.X, y),
|
GUI.DrawString(spriteBatch, new Vector2(graphRect.X, y),
|
||||||
" " + (int) (eventSet.MinDistanceTraveled * 100.0f) + "% travelled (current: " + (int) (distanceTraveled * 100.0f) + " %)",
|
" " + (int) (eventSet.MinDistanceTraveled * 100.0f) + "% travelled (current: " + (int) (distanceTraveled * 100.0f) + " %)",
|
||||||
Color.Orange * 0.8f, null, 0, GUI.SmallFont);
|
((Submarine.MainSub == null || distanceTraveled < eventSet.MinDistanceTraveled) ? Color.Lerp(GUI.Style.Yellow, GUI.Style.Red, eventSet.MinDistanceTraveled - distanceTraveled) : GUI.Style.Green) * 0.8f, null, 0, GUI.SmallFont);
|
||||||
y += 12;
|
y += 12;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,7 +135,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
GUI.DrawString(spriteBatch, new Vector2(graphRect.X, y),
|
GUI.DrawString(spriteBatch, new Vector2(graphRect.X, y),
|
||||||
" " + (int) (eventSet.MinMissionTime - roundDuration) + " s",
|
" " + (int) (eventSet.MinMissionTime - roundDuration) + " s",
|
||||||
Color.Orange * 0.8f, null, 0, GUI.SmallFont);
|
Color.Lerp(GUI.Style.Yellow, GUI.Style.Red, (eventSet.MinMissionTime - roundDuration)), null, 0, GUI.SmallFont);
|
||||||
}
|
}
|
||||||
|
|
||||||
y += 15;
|
y += 15;
|
||||||
@@ -143,25 +153,25 @@ namespace Barotrauma
|
|||||||
Rectangle outlineRect = new Rectangle(rect.Location, rect.Size);
|
Rectangle outlineRect = new Rectangle(rect.Location, rect.Size);
|
||||||
outlineRect.Inflate(4, 4);
|
outlineRect.Inflate(4, 4);
|
||||||
|
|
||||||
if (pinnedEvent == ev) { GUI.DrawRectangle(spriteBatch, outlineRect, Color.White); }
|
if (PinnedEvent == ev) { GUI.DrawRectangle(spriteBatch, outlineRect, Color.White); }
|
||||||
|
|
||||||
if (rect.Contains(PlayerInput.MousePosition))
|
if (rect.Contains(PlayerInput.MousePosition))
|
||||||
{
|
{
|
||||||
GUI.MouseCursor = CursorState.Hand;
|
GUI.MouseCursor = CursorState.Hand;
|
||||||
GUI.DrawRectangle(spriteBatch, outlineRect, Color.White);
|
GUI.DrawRectangle(spriteBatch, outlineRect, Color.White);
|
||||||
|
|
||||||
if (ev != pinnedEvent)
|
if (ev != PinnedEvent)
|
||||||
{
|
{
|
||||||
DrawEvent(spriteBatch, ev, rect);
|
DrawEvent(spriteBatch, ev, rect);
|
||||||
}
|
}
|
||||||
else if (PlayerInput.SecondaryMouseButtonHeld() || PlayerInput.SecondaryMouseButtonDown())
|
else if (PlayerInput.SecondaryMouseButtonHeld() || PlayerInput.SecondaryMouseButtonDown())
|
||||||
{
|
{
|
||||||
pinnedEvent = null;
|
PinnedEvent = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PlayerInput.PrimaryMouseButtonHeld() || PlayerInput.PrimaryMouseButtonDown())
|
if (PlayerInput.PrimaryMouseButtonHeld() || PlayerInput.PrimaryMouseButtonDown())
|
||||||
{
|
{
|
||||||
pinnedEvent = ev;
|
PinnedEvent = ev;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,9 +181,9 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public void DrawPinnedEvent(SpriteBatch spriteBatch)
|
public void DrawPinnedEvent(SpriteBatch spriteBatch)
|
||||||
{
|
{
|
||||||
if (pinnedEvent != null)
|
if (PinnedEvent != null)
|
||||||
{
|
{
|
||||||
Rectangle rect = DrawEvent(spriteBatch, pinnedEvent, null);
|
Rectangle rect = DrawEvent(spriteBatch, PinnedEvent, null);
|
||||||
|
|
||||||
if (rect != Rectangle.Empty)
|
if (rect != Rectangle.Empty)
|
||||||
{
|
{
|
||||||
@@ -187,7 +197,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (PlayerInput.SecondaryMouseButtonClicked() || PlayerInput.SecondaryMouseButtonHeld())
|
if (PlayerInput.SecondaryMouseButtonClicked() || PlayerInput.SecondaryMouseButtonHeld())
|
||||||
{
|
{
|
||||||
pinnedEvent = null;
|
PinnedEvent = null;
|
||||||
isDragging = false;
|
isDragging = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,11 +2,9 @@
|
|||||||
using Barotrauma.Items.Components;
|
using Barotrauma.Items.Components;
|
||||||
using Barotrauma.Networking;
|
using Barotrauma.Networking;
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Microsoft.Xna.Framework.Input;
|
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
@@ -14,7 +12,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
public const string RadioChatString = "r; ";
|
public const string RadioChatString = "r; ";
|
||||||
|
|
||||||
private GUIListBox chatBox;
|
private readonly GUIListBox chatBox;
|
||||||
private Point screenResolution;
|
private Point screenResolution;
|
||||||
|
|
||||||
public readonly ChatManager ChatManager = new ChatManager();
|
public readonly ChatManager ChatManager = new ChatManager();
|
||||||
@@ -37,10 +35,17 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private float prevUIScale;
|
private float prevUIScale;
|
||||||
|
|
||||||
|
private readonly GUIFrame channelSettingsFrame;
|
||||||
|
private readonly GUITextBox channelText;
|
||||||
|
private readonly GUILayoutGroup channelPickerContent;
|
||||||
|
private readonly GUIButton memButton;
|
||||||
|
private WifiComponent prevRadio;
|
||||||
|
|
||||||
|
private bool channelMemPending;
|
||||||
|
|
||||||
//individual message texts that pop up when the chatbox is hidden
|
//individual message texts that pop up when the chatbox is hidden
|
||||||
const float PopupMessageDuration = 5.0f;
|
const float PopupMessageDuration = 5.0f;
|
||||||
private float popupMessageTimer;
|
private readonly List<GUIComponent> popupMessages = new List<GUIComponent>();
|
||||||
private Queue<GUIComponent> popupMessages = new Queue<GUIComponent>();
|
|
||||||
|
|
||||||
public GUITextBox.OnEnterHandler OnEnterMessage
|
public GUITextBox.OnEnterHandler OnEnterMessage
|
||||||
{
|
{
|
||||||
@@ -67,9 +72,9 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private GUIButton showNewMessagesButton;
|
private readonly GUIButton showNewMessagesButton;
|
||||||
|
|
||||||
private GUIFrame hideableElements;
|
private readonly GUIFrame hideableElements;
|
||||||
|
|
||||||
public const int ToggleButtonWidthRaw = 30;
|
public const int ToggleButtonWidthRaw = 30;
|
||||||
private int popupMessageOffset;
|
private int popupMessageOffset;
|
||||||
@@ -88,6 +93,133 @@ namespace Barotrauma
|
|||||||
var chatBoxHolder = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.875f), hideableElements.RectTransform), style: "ChatBox");
|
var chatBoxHolder = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.875f), hideableElements.RectTransform), style: "ChatBox");
|
||||||
chatBox = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.95f), chatBoxHolder.RectTransform, Anchor.CenterRight), style: null);
|
chatBox = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.95f), chatBoxHolder.RectTransform, Anchor.CenterRight), style: null);
|
||||||
|
|
||||||
|
// channel settings -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
channelSettingsFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.2f), chatBoxHolder.RectTransform, Anchor.TopCenter, Pivot.BottomCenter) { MinSize = new Point(0, 25) }, style: "GUIFrameBottom");
|
||||||
|
var channelSettingsContent = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.9f), channelSettingsFrame.RectTransform, Anchor.Center), isHorizontal: true, childAnchor: Anchor.CenterLeft)
|
||||||
|
{
|
||||||
|
Stretch = true,
|
||||||
|
RelativeSpacing = 0.01f
|
||||||
|
};
|
||||||
|
|
||||||
|
var buttonLeft = new GUIButton(new RectTransform(new Vector2(0.1f, 0.8f), channelSettingsContent.RectTransform), style: "DeviceButton")
|
||||||
|
{
|
||||||
|
OnClicked = (btn, userdata) =>
|
||||||
|
{
|
||||||
|
if (Character.Controlled != null && ChatMessage.CanUseRadio(Character.Controlled, out WifiComponent radio))
|
||||||
|
{
|
||||||
|
SetChannel(radio.Channel - 1, setText: true);
|
||||||
|
GUI.PlayUISound(GUISoundType.PopupMenu);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var arrowIcon = new GUIImage(new RectTransform(new Vector2(0.4f), buttonLeft.RectTransform, Anchor.Center), style: "GUIButtonHorizontalArrow", scaleToFit: true)
|
||||||
|
{
|
||||||
|
Color = new Color(51, 59, 46),
|
||||||
|
SpriteEffects = Microsoft.Xna.Framework.Graphics.SpriteEffects.FlipHorizontally
|
||||||
|
};
|
||||||
|
arrowIcon.HoverColor = arrowIcon.PressedColor = arrowIcon.PressedColor = arrowIcon.Color;
|
||||||
|
|
||||||
|
channelText = new GUITextBox(new RectTransform(new Vector2(0.25f, 0.8f), channelSettingsContent.RectTransform), style: "DigitalFrameLight", textAlignment: Alignment.Center, font: GUI.DigitalFont)
|
||||||
|
{
|
||||||
|
textFilterFunction = text =>
|
||||||
|
{
|
||||||
|
var str = new string(text.Where(c => char.IsNumber(c)).ToArray());
|
||||||
|
if (str.Length > 4) { str = str.Substring(0, 4); }
|
||||||
|
return str;
|
||||||
|
},
|
||||||
|
OnEnterPressed = (tb, text) =>
|
||||||
|
{
|
||||||
|
tb.Deselect();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Vector2 textSize = channelText.Font.MeasureString("0000");
|
||||||
|
channelText.TextBlock.ToolTip = TextManager.Get("currentradiochannel");
|
||||||
|
channelText.TextBlock.TextScale = Math.Min(channelText.Rect.Height / textSize.Y * 0.9f, 1.0f);
|
||||||
|
channelText.OnDeselected += (sender, key) =>
|
||||||
|
{
|
||||||
|
int.TryParse(channelText.Text, out int newChannel);
|
||||||
|
SetChannel(newChannel, setText: true);
|
||||||
|
GUI.PlayUISound(GUISoundType.PopupMenu);
|
||||||
|
};
|
||||||
|
|
||||||
|
var buttonRight = new GUIButton(new RectTransform(new Vector2(0.1f, 0.8f), channelSettingsContent.RectTransform), style: "DeviceButton")
|
||||||
|
{
|
||||||
|
OnClicked = (btn, userdata) =>
|
||||||
|
{
|
||||||
|
if (Character.Controlled != null && ChatMessage.CanUseRadio(Character.Controlled, out WifiComponent radio))
|
||||||
|
{
|
||||||
|
SetChannel(radio.Channel + 1, setText: true);
|
||||||
|
GUI.PlayUISound(GUISoundType.PopupMenu);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
arrowIcon = new GUIImage(new RectTransform(new Vector2(0.4f), buttonRight.RectTransform, Anchor.Center), style: "GUIButtonHorizontalArrow", scaleToFit: true)
|
||||||
|
{
|
||||||
|
Color = new Color(51, 59, 46)
|
||||||
|
};
|
||||||
|
arrowIcon.HoverColor = arrowIcon.PressedColor = arrowIcon.PressedColor = arrowIcon.Color;
|
||||||
|
|
||||||
|
var channelPicker = new GUIFrame(new RectTransform(new Vector2(0.4f, 0.6f), channelSettingsContent.RectTransform), "InnerFrame");
|
||||||
|
channelPickerContent = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.9f), channelPicker.RectTransform, Anchor.Center), isHorizontal: true, childAnchor: Anchor.CenterLeft)
|
||||||
|
{
|
||||||
|
Stretch = true
|
||||||
|
};
|
||||||
|
for (int i = 0; i < 10; i++)
|
||||||
|
{
|
||||||
|
new GUIButton(new RectTransform(new Vector2(0.1f, 1.0f), channelPickerContent.RectTransform), i.ToString(), style: "GUITextBlock")
|
||||||
|
{
|
||||||
|
TextColor = new Color(51, 59, 46),
|
||||||
|
SelectedTextColor = GUI.Style.Green,
|
||||||
|
UserData = i,
|
||||||
|
OnClicked = (btn, userdata) =>
|
||||||
|
{
|
||||||
|
if (Character.Controlled != null && ChatMessage.CanUseRadio(Character.Controlled, out WifiComponent radio))
|
||||||
|
{
|
||||||
|
int index = (int)userdata;
|
||||||
|
if (channelMemPending)
|
||||||
|
{
|
||||||
|
int.TryParse(channelText.Text, out int newChannel);
|
||||||
|
radio.SetChannelMemory(index, newChannel);
|
||||||
|
btn.ToolTip = TextManager.GetWithVariables("radiochannelpreset",
|
||||||
|
new string[] { "[index]", "[channel]" },
|
||||||
|
new string[] { index.ToString(), radio.GetChannelMemory(index).ToString() });
|
||||||
|
channelMemPending = false;
|
||||||
|
channelPickerContent.Children.First().CanBeFocused = true;
|
||||||
|
memButton.Enabled = true;
|
||||||
|
channelPickerContent.Flash(GUI.Style.Green);
|
||||||
|
channelText.Flash(GUI.Style.Green);
|
||||||
|
}
|
||||||
|
SetChannel(radio.GetChannelMemory(index), setText: true);
|
||||||
|
GUI.PlayUISound(GUISoundType.PopupMenu);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
memButton = new GUIButton(new RectTransform(new Vector2(0.2f, 0.9f), channelSettingsContent.RectTransform), style: "DeviceButton", text: TextManager.Get("saveradiochannelbutton"))
|
||||||
|
{
|
||||||
|
ToolTip = TextManager.Get("saveradiochannelbuttontooltip"),
|
||||||
|
OnClicked = (btn, userdata) =>
|
||||||
|
{
|
||||||
|
channelMemPending = true;
|
||||||
|
//don't allow storing a value in the first preset
|
||||||
|
channelPickerContent.Children.First().CanBeFocused = false;
|
||||||
|
foreach (GUIComponent channelButton in channelPickerContent.Children)
|
||||||
|
{
|
||||||
|
channelButton.Selected = false;
|
||||||
|
}
|
||||||
|
btn.Enabled = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
InputBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.125f), hideableElements.RectTransform, Anchor.BottomLeft),
|
InputBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.125f), hideableElements.RectTransform, Anchor.BottomLeft),
|
||||||
style: "ChatTextBox")
|
style: "ChatTextBox")
|
||||||
{
|
{
|
||||||
@@ -148,7 +280,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Color textColor = textBox.Color;
|
Color textColor;
|
||||||
switch (command)
|
switch (command)
|
||||||
{
|
{
|
||||||
case "r":
|
case "r":
|
||||||
@@ -235,7 +367,7 @@ namespace Barotrauma
|
|||||||
},
|
},
|
||||||
Text = senderName
|
Text = senderName
|
||||||
};
|
};
|
||||||
|
|
||||||
senderNameBlock.RectTransform.NonScaledSize = senderNameBlock.TextBlock.TextSize.ToPoint();
|
senderNameBlock.RectTransform.NonScaledSize = senderNameBlock.TextBlock.TextSize.ToPoint();
|
||||||
senderNameBlock.TextBlock.OverrideTextColor(senderColor);
|
senderNameBlock.TextBlock.OverrideTextColor(senderColor);
|
||||||
if (senderNameBlock.UserData != null)
|
if (senderNameBlock.UserData != null)
|
||||||
@@ -244,7 +376,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var msgText =new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), msgHolder.RectTransform)
|
var msgText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), msgHolder.RectTransform)
|
||||||
{ AbsoluteOffset = new Point((int)(10 * GUI.Scale), senderNameTimestamp == null ? 0 : senderNameTimestamp.Rect.Height) },
|
{ AbsoluteOffset = new Point((int)(10 * GUI.Scale), senderNameTimestamp == null ? 0 : senderNameTimestamp.Rect.Height) },
|
||||||
displayedText, textColor: message.Color, font: GUI.SmallFont, textAlignment: Alignment.TopLeft, style: null, wrap: true,
|
displayedText, textColor: message.Color, font: GUI.SmallFont, textAlignment: Alignment.TopLeft, style: null, wrap: true,
|
||||||
color: ((chatBox.Content.CountChildren % 2) == 0) ? Color.Transparent : Color.Black * 0.1f)
|
color: ((chatBox.Content.CountChildren % 2) == 0) ? Color.Transparent : Color.Black * 0.1f)
|
||||||
@@ -296,7 +428,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
var popupMsg = new GUIFrame(new RectTransform(Vector2.One, GUIFrame.RectTransform), style: "GUIToolTip")
|
var popupMsg = new GUIFrame(new RectTransform(Vector2.One, GUIFrame.RectTransform), style: "GUIToolTip")
|
||||||
{
|
{
|
||||||
Visible = false,
|
UserData = 0.0f,
|
||||||
CanBeFocused = false
|
CanBeFocused = false
|
||||||
};
|
};
|
||||||
var content = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.9f), popupMsg.RectTransform, Anchor.Center));
|
var content = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.9f), popupMsg.RectTransform, Anchor.Center));
|
||||||
@@ -322,10 +454,10 @@ namespace Barotrauma
|
|||||||
popupMsg.RectTransform.Resize(new Point((int)(textWidth / content.RectTransform.RelativeSize.X) , (int)((senderTextSize.Y + msgSize.Y) / content.RectTransform.RelativeSize.Y)), resizeChildren: true);
|
popupMsg.RectTransform.Resize(new Point((int)(textWidth / content.RectTransform.RelativeSize.X) , (int)((senderTextSize.Y + msgSize.Y) / content.RectTransform.RelativeSize.Y)), resizeChildren: true);
|
||||||
popupMsg.RectTransform.IsFixedSize = true;
|
popupMsg.RectTransform.IsFixedSize = true;
|
||||||
content.Recalculate();
|
content.Recalculate();
|
||||||
popupMessages.Enqueue(popupMsg);
|
popupMessages.Add(popupMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((prevSize == 1.0f && chatBox.BarScroll == 0.0f) || (prevSize < 1.0f && chatBox.BarScroll == 1.0f)) chatBox.BarScroll = 1.0f;
|
if ((prevSize == 1.0f && chatBox.BarScroll == 0.0f) || (prevSize < 1.0f && chatBox.BarScroll == 1.0f)) { chatBox.BarScroll = 1.0f; }
|
||||||
|
|
||||||
GUISoundType soundType = GUISoundType.ChatMessage;
|
GUISoundType soundType = GUISoundType.ChatMessage;
|
||||||
if (message.Type == ChatMessageType.Radio)
|
if (message.Type == ChatMessageType.Radio)
|
||||||
@@ -372,7 +504,7 @@ namespace Barotrauma
|
|||||||
GUIFrame.RectTransform.NonScaledSize -= new Point(toggleButtonWidth, 0);
|
GUIFrame.RectTransform.NonScaledSize -= new Point(toggleButtonWidth, 0);
|
||||||
GUIFrame.RectTransform.AbsoluteOffset += new Point(toggleButtonWidth, 0);
|
GUIFrame.RectTransform.AbsoluteOffset += new Point(toggleButtonWidth, 0);
|
||||||
|
|
||||||
popupMessageOffset = GameMain.GameSession.CrewManager.ReportButtonFrame.Rect.Width + GUIFrame.Rect.Width + (int)(20 * GUI.Scale);
|
popupMessageOffset = GameMain.GameSession.CrewManager.ReportButtonFrame.Rect.Width + GUIFrame.Rect.Width + (int)(35 * GUI.Scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Update(float deltaTime)
|
public void Update(float deltaTime)
|
||||||
@@ -394,22 +526,93 @@ namespace Barotrauma
|
|||||||
ToggleButton.RectTransform.AbsoluteOffset = new Point(GUIFrame.Rect.Right, GUIFrame.Rect.Y + HUDLayoutSettings.ChatBoxArea.Height - ToggleButton.Rect.Height);
|
ToggleButton.RectTransform.AbsoluteOffset = new Point(GUIFrame.Rect.Right, GUIFrame.Rect.Y + HUDLayoutSettings.ChatBoxArea.Height - ToggleButton.Rect.Height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Character.Controlled != null && ChatMessage.CanUseRadio(Character.Controlled, out WifiComponent radio))
|
||||||
|
{
|
||||||
|
if (prevRadio != radio)
|
||||||
|
{
|
||||||
|
foreach (GUIComponent presetButton in channelPickerContent.Children)
|
||||||
|
{
|
||||||
|
int index = (int)presetButton.UserData;
|
||||||
|
presetButton.ToolTip = TextManager.GetWithVariables("radiochannelpreset",
|
||||||
|
new string[] { "[index]", "[channel]" },
|
||||||
|
new string[] { index.ToString(), radio.GetChannelMemory(index).ToString() });
|
||||||
|
}
|
||||||
|
SetChannel(radio.Channel, setText: true);
|
||||||
|
prevRadio = radio;
|
||||||
|
}
|
||||||
|
if (channelMemPending)
|
||||||
|
{
|
||||||
|
if (channelPickerContent.FlashTimer <= 0)
|
||||||
|
{
|
||||||
|
channelPickerContent.Flash(GUI.Style.Green, flashRectInflate: new Vector2(GUI.Scale * 5.0f));
|
||||||
|
}
|
||||||
|
if (PlayerInput.PrimaryMouseButtonClicked() && !GUI.IsMouseOn(channelPickerContent))
|
||||||
|
{
|
||||||
|
channelPickerContent.Children.First().CanBeFocused = true;
|
||||||
|
channelMemPending = false;
|
||||||
|
memButton.Enabled = true;
|
||||||
|
SetChannel(radio.Channel, setText: true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
channelSettingsFrame.Visible = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
channelSettingsFrame.Visible = false;
|
||||||
|
channelPickerContent.Children.First().CanBeFocused = true;
|
||||||
|
channelMemPending = false;
|
||||||
|
memButton.Enabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (ToggleOpen)
|
if (ToggleOpen)
|
||||||
{
|
{
|
||||||
openState += deltaTime * 5.0f;
|
openState += deltaTime * 5.0f;
|
||||||
//delete all popup messages when the chatbox is open
|
//delete all popup messages when the chatbox is open
|
||||||
while (popupMessages.Count > 0)
|
foreach (var popupMsg in popupMessages)
|
||||||
{
|
{
|
||||||
var popupMsg = popupMessages.Dequeue();
|
|
||||||
popupMsg.Parent.RemoveChild(popupMsg);
|
popupMsg.Parent.RemoveChild(popupMsg);
|
||||||
}
|
}
|
||||||
|
popupMessages.Clear();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
openState -= deltaTime * 5.0f;
|
openState -= deltaTime * 5.0f;
|
||||||
|
|
||||||
|
int yOffset = 0;
|
||||||
|
foreach (var popupMsg in popupMessages)
|
||||||
|
{
|
||||||
|
float msgTimer = (float)popupMsg.UserData;
|
||||||
|
|
||||||
|
int targetYOffset = (int)MathHelper.Lerp(popupMsg.RectTransform.ScreenSpaceOffset.Y, yOffset, deltaTime * 10.0f);
|
||||||
|
|
||||||
|
if (popupMsg == popupMessages.First())
|
||||||
|
{
|
||||||
|
popupMsg.UserData = msgTimer + deltaTime * Math.Max(popupMessages.Count / 2, 1);
|
||||||
|
if (msgTimer > PopupMessageDuration)
|
||||||
|
{
|
||||||
|
//move the message out of the screen and delete it
|
||||||
|
popupMsg.RectTransform.ScreenSpaceOffset =
|
||||||
|
new Point((int)MathHelper.SmoothStep(popupMessageOffset, 10, (msgTimer - PopupMessageDuration) * 5.0f), targetYOffset);
|
||||||
|
if (msgTimer > PopupMessageDuration + 0.2f)
|
||||||
|
{
|
||||||
|
popupMsg.Parent?.RemoveChild(popupMsg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (msgTimer < PopupMessageDuration)
|
||||||
|
{
|
||||||
|
if (popupMsg != popupMessages.First()) { popupMsg.UserData = Math.Min(msgTimer + deltaTime, 1.0f); }
|
||||||
|
//move the message on the screen
|
||||||
|
popupMsg.RectTransform.ScreenSpaceOffset = new Point(
|
||||||
|
(int)MathHelper.SmoothStep(0, popupMessageOffset, msgTimer * 5.0f), targetYOffset);
|
||||||
|
}
|
||||||
|
yOffset += popupMsg.Rect.Height + GUI.IntScale(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
popupMessages.RemoveAll(p => p.Parent == null);
|
||||||
|
|
||||||
//make the first popup message visible
|
//make the first popup message visible
|
||||||
var popupMsg = popupMessages.Count > 0 ? popupMessages.Peek() : null;
|
/*var popupMsg = popupMessages.Count > 0 ? popupMessages.Peek() : null;
|
||||||
if (popupMsg != null)
|
if (popupMsg != null)
|
||||||
{
|
{
|
||||||
popupMsg.Visible = true;
|
popupMsg.Visible = true;
|
||||||
@@ -433,7 +636,7 @@ namespace Barotrauma
|
|||||||
popupMsg.RectTransform.ScreenSpaceOffset = new Point(
|
popupMsg.RectTransform.ScreenSpaceOffset = new Point(
|
||||||
(int)MathHelper.SmoothStep(0, popupMessageOffset, popupMessageTimer * 5.0f), 0);
|
(int)MathHelper.SmoothStep(0, popupMessageOffset, popupMessageTimer * 5.0f), 0);
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
openState = MathHelper.Clamp(openState, 0.0f, 1.0f);
|
openState = MathHelper.Clamp(openState, 0.0f, 1.0f);
|
||||||
int hiddenBoxOffset = -(GUIFrame.Rect.Width);
|
int hiddenBoxOffset = -(GUIFrame.Rect.Width);
|
||||||
@@ -441,5 +644,27 @@ namespace Barotrauma
|
|||||||
new Point((int)MathHelper.SmoothStep(hiddenBoxOffset, 0, openState), 0);
|
new Point((int)MathHelper.SmoothStep(hiddenBoxOffset, 0, openState), 0);
|
||||||
hideableElements.Visible = openState > 0.0f;
|
hideableElements.Visible = openState > 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void SetChannel(int channel, bool setText)
|
||||||
|
{
|
||||||
|
if (Character.Controlled != null && ChatMessage.CanUseRadio(Character.Controlled, out WifiComponent radio))
|
||||||
|
{
|
||||||
|
radio.Channel = channel;
|
||||||
|
if (setText)
|
||||||
|
{
|
||||||
|
string text = radio.Channel.ToString().PadLeft(4, '0');
|
||||||
|
if (channelText.Text != text) { channelText.Text = text; }
|
||||||
|
|
||||||
|
}
|
||||||
|
if (!channelMemPending)
|
||||||
|
{
|
||||||
|
foreach (GUIComponent channelButton in channelPickerContent.Children)
|
||||||
|
{
|
||||||
|
int buttonIndex = (int)channelButton.UserData;
|
||||||
|
channelButton.Selected = radio.GetChannelMemory(buttonIndex) == channel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -323,7 +323,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (Screen.Selected == GameMain.GameScreen)
|
if (Screen.Selected == GameMain.GameScreen)
|
||||||
{
|
{
|
||||||
yOffset = -HUDLayoutSettings.ChatBoxArea.Height;
|
yOffset = (int)(-HUDLayoutSettings.ChatBoxArea.Height * 1.2f);
|
||||||
watermarkRect.Y += yOffset;
|
watermarkRect.Y += yOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -609,7 +609,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (Character.Controlled?.Inventory != null)
|
if (Character.Controlled?.Inventory != null)
|
||||||
{
|
{
|
||||||
if (!Character.Controlled.LockHands && Character.Controlled.Stun < 0.1f && !Character.Controlled.IsDead)
|
if (Character.Controlled.Stun < 0.1f && !Character.Controlled.IsDead)
|
||||||
{
|
{
|
||||||
Inventory.DrawFront(spriteBatch);
|
Inventory.DrawFront(spriteBatch);
|
||||||
}
|
}
|
||||||
@@ -1267,7 +1267,7 @@ namespace Barotrauma
|
|||||||
Vector2 diff = worldPosition - cam.WorldViewCenter;
|
Vector2 diff = worldPosition - cam.WorldViewCenter;
|
||||||
float dist = diff.Length();
|
float dist = diff.Length();
|
||||||
|
|
||||||
float symbolScale = 64.0f / sprite.size.X;
|
float symbolScale = Math.Min(64.0f / sprite.size.X, 1.0f);
|
||||||
|
|
||||||
if (dist > hideDist)
|
if (dist > hideDist)
|
||||||
{
|
{
|
||||||
@@ -2089,8 +2089,8 @@ namespace Barotrauma
|
|||||||
Stretch = true,
|
Stretch = true,
|
||||||
RelativeSpacing = 0.05f
|
RelativeSpacing = 0.05f
|
||||||
};
|
};
|
||||||
|
|
||||||
var button = new GUIButton(new RectTransform(new Vector2(0.1f, 0.1f), pauseMenuInner.RectTransform, Anchor.TopRight) { AbsoluteOffset = new Point((int)(15 * GUI.Scale)) },
|
new GUIButton(new RectTransform(new Vector2(0.1f, 0.1f), pauseMenuInner.RectTransform, Anchor.TopRight) { AbsoluteOffset = new Point((int)(15 * GUI.Scale)) },
|
||||||
"", style: "GUIBugButton")
|
"", style: "GUIBugButton")
|
||||||
{
|
{
|
||||||
IgnoreLayoutGroups = true,
|
IgnoreLayoutGroups = true,
|
||||||
@@ -2098,12 +2098,12 @@ namespace Barotrauma
|
|||||||
OnClicked = (btn, userdata) => { GameMain.Instance.ShowBugReporter(); return true; }
|
OnClicked = (btn, userdata) => { GameMain.Instance.ShowBugReporter(); return true; }
|
||||||
};
|
};
|
||||||
|
|
||||||
button = new GUIButton(new RectTransform(new Vector2(1.0f, 0.1f), buttonContainer.RectTransform), TextManager.Get("PauseMenuResume"))
|
new GUIButton(new RectTransform(new Vector2(1.0f, 0.1f), buttonContainer.RectTransform), TextManager.Get("PauseMenuResume"))
|
||||||
{
|
{
|
||||||
OnClicked = TogglePauseMenu
|
OnClicked = TogglePauseMenu
|
||||||
};
|
};
|
||||||
|
|
||||||
button = new GUIButton(new RectTransform(new Vector2(1.0f, 0.1f), buttonContainer.RectTransform), TextManager.Get("PauseMenuSettings"))
|
new GUIButton(new RectTransform(new Vector2(1.0f, 0.1f), buttonContainer.RectTransform), TextManager.Get("PauseMenuSettings"))
|
||||||
{
|
{
|
||||||
OnClicked = (btn, userData) =>
|
OnClicked = (btn, userData) =>
|
||||||
{
|
{
|
||||||
@@ -2117,8 +2117,8 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (GameMain.GameSession.GameMode is SinglePlayerCampaign spMode)
|
if (GameMain.GameSession.GameMode is SinglePlayerCampaign spMode)
|
||||||
{
|
{
|
||||||
button = new GUIButton(new RectTransform(new Vector2(1.0f, 0.1f), buttonContainer.RectTransform), TextManager.Get("PauseMenuRetry"));
|
var retryButton = new GUIButton(new RectTransform(new Vector2(1.0f, 0.1f), buttonContainer.RectTransform), TextManager.Get("PauseMenuRetry"));
|
||||||
button.OnClicked += (btn, userData) =>
|
retryButton.OnClicked += (btn, userData) =>
|
||||||
{
|
{
|
||||||
var msgBox = new GUIMessageBox("", TextManager.Get("PauseMenuRetryVerification"), new string[] { TextManager.Get("Yes"), TextManager.Get("Cancel") })
|
var msgBox = new GUIMessageBox("", TextManager.Get("PauseMenuRetryVerification"), new string[] { TextManager.Get("Yes"), TextManager.Get("Cancel") })
|
||||||
{
|
{
|
||||||
@@ -2131,6 +2131,7 @@ namespace Barotrauma
|
|||||||
GUIMessageBox.MessageBoxes.Remove(GameMain.GameSession.RoundSummary.Frame);
|
GUIMessageBox.MessageBoxes.Remove(GameMain.GameSession.RoundSummary.Frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GUIMessageBox.MessageBoxes.RemoveAll(mb => mb.UserData as string == "ConversationAction");
|
||||||
TogglePauseMenu(btn, userData);
|
TogglePauseMenu(btn, userData);
|
||||||
GameMain.GameSession.LoadPreviousSave();
|
GameMain.GameSession.LoadPreviousSave();
|
||||||
return true;
|
return true;
|
||||||
@@ -2144,24 +2145,57 @@ namespace Barotrauma
|
|||||||
};
|
};
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
button = new GUIButton(new RectTransform(new Vector2(1.0f, 0.1f), buttonContainer.RectTransform), TextManager.Get("PauseMenuSaveQuit"))
|
var saveAndQuitButton = new GUIButton(new RectTransform(new Vector2(1.0f, 0.1f), buttonContainer.RectTransform), TextManager.Get("PauseMenuSaveQuit"))
|
||||||
{
|
{
|
||||||
UserData = "save"
|
UserData = "save"
|
||||||
};
|
};
|
||||||
button.OnClicked += QuitClicked;
|
saveAndQuitButton.OnClicked += (btn, userdata) =>
|
||||||
button.OnClicked += TogglePauseMenu;
|
{
|
||||||
|
//Only allow saving mid-round in outpost levels. Quitting in the middle of a mission reset progress to the start of the round.
|
||||||
|
if (GameMain.GameSession == null)
|
||||||
|
{
|
||||||
|
pauseMenuOpen = false;
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (GameMain.GameSession?.Campaign == null || Level.IsLoadedOutpost)
|
||||||
|
{
|
||||||
|
pauseMenuOpen = false;
|
||||||
|
GameMain.QuitToMainMenu(save: true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var msgBox = new GUIMessageBox("", TextManager.Get("PauseMenuSaveAndQuitVerification", fallBackTag: "pausemenuquitverification"), new string[] { TextManager.Get("Yes"), TextManager.Get("Cancel") })
|
||||||
|
{
|
||||||
|
UserData = "verificationprompt"
|
||||||
|
};
|
||||||
|
msgBox.Buttons[0].OnClicked = (_, userdata) =>
|
||||||
|
{
|
||||||
|
pauseMenuOpen = false;
|
||||||
|
GameMain.QuitToMainMenu(save: false);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
msgBox.Buttons[0].OnClicked += msgBox.Close;
|
||||||
|
msgBox.Buttons[1].OnClicked = (_, userdata) =>
|
||||||
|
{
|
||||||
|
pauseMenuOpen = false;
|
||||||
|
msgBox.Close();
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
else if (GameMain.GameSession.GameMode is TestGameMode)
|
else if (GameMain.GameSession.GameMode is TestGameMode)
|
||||||
{
|
{
|
||||||
button = new GUIButton(new RectTransform(new Vector2(1.0f, 0.1f), buttonContainer.RectTransform), text: TextManager.Get("PauseMenuReturnToEditor"))
|
new GUIButton(new RectTransform(new Vector2(1.0f, 0.1f), buttonContainer.RectTransform), text: TextManager.Get("PauseMenuReturnToEditor"))
|
||||||
{
|
{
|
||||||
OnClicked = (btn, userdata) =>
|
OnClicked = (btn, userdata) =>
|
||||||
{
|
{
|
||||||
GameMain.GameSession.EndRound("");
|
GameMain.GameSession.EndRound("");
|
||||||
|
pauseMenuOpen = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
button.OnClicked += TogglePauseMenu;
|
|
||||||
}
|
}
|
||||||
else if (!GameMain.GameSession.GameMode.IsSinglePlayer && GameMain.Client != null && GameMain.Client.HasPermission(ClientPermissions.ManageRound))
|
else if (!GameMain.GameSession.GameMode.IsSinglePlayer && GameMain.Client != null && GameMain.Client.HasPermission(ClientPermissions.ManageRound))
|
||||||
{
|
{
|
||||||
@@ -2181,7 +2215,7 @@ namespace Barotrauma
|
|||||||
};
|
};
|
||||||
msgBox.Buttons[0].OnClicked = (_, __) =>
|
msgBox.Buttons[0].OnClicked = (_, __) =>
|
||||||
{
|
{
|
||||||
TogglePauseMenu(btn, userdata);
|
pauseMenuOpen = false;
|
||||||
GameMain.Client.RequestRoundEnd();
|
GameMain.Client.RequestRoundEnd();
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
@@ -2190,7 +2224,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TogglePauseMenu(btn, userdata);
|
pauseMenuOpen = false;
|
||||||
GameMain.Client.RequestRoundEnd();
|
GameMain.Client.RequestRoundEnd();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -2199,10 +2233,9 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
button = new GUIButton(new RectTransform(new Vector2(1.0f, 0.1f), buttonContainer.RectTransform), TextManager.Get("PauseMenuQuit"));
|
var quitButton = new GUIButton(new RectTransform(new Vector2(1.0f, 0.1f), buttonContainer.RectTransform), TextManager.Get("PauseMenuQuit"));
|
||||||
button.OnClicked += (btn, userData) =>
|
quitButton.OnClicked += (btn, userData) =>
|
||||||
{
|
{
|
||||||
var quitButton = button;
|
|
||||||
if (GameMain.GameSession != null || (Screen.Selected is CharacterEditorScreen || Screen.Selected is SubEditorScreen))
|
if (GameMain.GameSession != null || (Screen.Selected is CharacterEditorScreen || Screen.Selected is SubEditorScreen))
|
||||||
{
|
{
|
||||||
string text = GameMain.GameSession == null ? "PauseMenuQuitVerificationEditor" : "PauseMenuQuitVerification";
|
string text = GameMain.GameSession == null ? "PauseMenuQuitVerificationEditor" : "PauseMenuQuitVerification";
|
||||||
@@ -2212,21 +2245,21 @@ namespace Barotrauma
|
|||||||
};
|
};
|
||||||
msgBox.Buttons[0].OnClicked = (yesBtn, userdata) =>
|
msgBox.Buttons[0].OnClicked = (yesBtn, userdata) =>
|
||||||
{
|
{
|
||||||
QuitClicked(quitButton, quitButton.UserData);
|
GameMain.QuitToMainMenu(save: false);
|
||||||
pauseMenuOpen = false;
|
pauseMenuOpen = false;
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
msgBox.Buttons[0].OnClicked += msgBox.Close;
|
msgBox.Buttons[0].OnClicked += msgBox.Close;
|
||||||
msgBox.Buttons[1].OnClicked = (_, userdata) =>
|
msgBox.Buttons[1].OnClicked = (_, userdata) =>
|
||||||
{
|
{
|
||||||
TogglePauseMenu(btn, userData);
|
pauseMenuOpen = false;
|
||||||
msgBox.Close();
|
msgBox.Close();
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
QuitClicked(quitButton, quitButton.UserData);
|
GameMain.QuitToMainMenu(save: false);
|
||||||
pauseMenuOpen = false;
|
pauseMenuOpen = false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -2242,12 +2275,6 @@ namespace Barotrauma
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool QuitClicked(GUIButton button, object obj)
|
|
||||||
{
|
|
||||||
GameMain.QuitToMainMenu(button.UserData as string == "save");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Displays a message at the center of the screen, automatically preventing overlapping with other centered messages. TODO: Allow to show messages at the middle of the screen (instead of the top center).
|
/// Displays a message at the center of the screen, automatically preventing overlapping with other centered messages. TODO: Allow to show messages at the middle of the screen (instead of the top center).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -104,6 +104,12 @@ namespace Barotrauma
|
|||||||
set { textBlock.HoverTextColor = value; }
|
set { textBlock.HoverTextColor = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Color SelectedTextColor
|
||||||
|
{
|
||||||
|
get { return textBlock.SelectedTextColor; }
|
||||||
|
set { textBlock.SelectedTextColor = value; }
|
||||||
|
}
|
||||||
|
|
||||||
public override float FlashTimer
|
public override float FlashTimer
|
||||||
{
|
{
|
||||||
get { return Frame.FlashTimer; }
|
get { return Frame.FlashTimer; }
|
||||||
|
|||||||
@@ -756,9 +756,9 @@ namespace Barotrauma
|
|||||||
flashColor = (color == null) ? GUI.Style.Red : (Color)color;
|
flashColor = (color == null) ? GUI.Style.Red : (Color)color;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void FadeOut(float duration, bool removeAfter)
|
public void FadeOut(float duration, bool removeAfter, float wait = 0.0f)
|
||||||
{
|
{
|
||||||
CoroutineManager.StartCoroutine(LerpAlpha(0.0f, duration, removeAfter));
|
CoroutineManager.StartCoroutine(LerpAlpha(0.0f, duration, removeAfter, wait));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void FadeIn(float wait, float duration)
|
public void FadeIn(float wait, float duration)
|
||||||
|
|||||||
@@ -239,7 +239,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
activeTextureLoads.Add(Sprite.FullPath);
|
activeTextureLoads.Add(Sprite.FullPath);
|
||||||
}
|
}
|
||||||
Sprite.EnsureLazyLoaded();
|
await Sprite.LazyLoadAsync();
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -446,7 +446,7 @@ namespace Barotrauma
|
|||||||
//dragging
|
//dragging
|
||||||
if (CanDragElements && draggedElement != null)
|
if (CanDragElements && draggedElement != null)
|
||||||
{
|
{
|
||||||
if (!PlayerInput.LeftButtonHeld())
|
if (!PlayerInput.PrimaryMouseButtonHeld())
|
||||||
{
|
{
|
||||||
OnRearranged?.Invoke(this, draggedElement.UserData);
|
OnRearranged?.Invoke(this, draggedElement.UserData);
|
||||||
draggedElement = null;
|
draggedElement = null;
|
||||||
@@ -533,7 +533,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CanDragElements && PlayerInput.LeftButtonDown() && GUI.MouseOn == child)
|
if (CanDragElements && PlayerInput.PrimaryMouseButtonDown() && GUI.MouseOn == child)
|
||||||
{
|
{
|
||||||
draggedElement = child;
|
draggedElement = child;
|
||||||
draggedReferenceRectangle = child.Rect;
|
draggedReferenceRectangle = child.Rect;
|
||||||
@@ -970,7 +970,6 @@ namespace Barotrauma
|
|||||||
spriteBatch.Begin(SpriteSortMode.Deferred, samplerState: GUI.SamplerState, rasterizerState: GameMain.ScissorTestEnable);
|
spriteBatch.Begin(SpriteSortMode.Deferred, samplerState: GUI.SamplerState, rasterizerState: GameMain.ScissorTestEnable);
|
||||||
}
|
}
|
||||||
|
|
||||||
var children = Content.Children;
|
|
||||||
int lastVisible = 0;
|
int lastVisible = 0;
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|||||||
@@ -180,13 +180,13 @@ namespace Barotrauma
|
|||||||
Icon = new GUIImage(new RectTransform(new Vector2(0.2f, 0.95f), horizontalLayoutGroup.RectTransform), iconStyle, scaleToFit: true);
|
Icon = new GUIImage(new RectTransform(new Vector2(0.2f, 0.95f), horizontalLayoutGroup.RectTransform), iconStyle, scaleToFit: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Content = new GUILayoutGroup(new RectTransform(new Vector2(icon != null ? 0.65f : 0.85f, 1.0f), horizontalLayoutGroup.RectTransform));
|
Content = new GUILayoutGroup(new RectTransform(new Vector2(Icon != null ? 0.65f : 0.85f, 1.0f), horizontalLayoutGroup.RectTransform));
|
||||||
|
|
||||||
var buttonContainer = new GUIFrame(new RectTransform(new Vector2(0.15f, 1.0f), horizontalLayoutGroup.RectTransform), style: null);
|
var buttonContainer = new GUIFrame(new RectTransform(new Vector2(0.15f, 1.0f), horizontalLayoutGroup.RectTransform), style: null);
|
||||||
Buttons = new List<GUIButton>(1)
|
Buttons = new List<GUIButton>(1)
|
||||||
{
|
{
|
||||||
new GUIButton(new RectTransform(new Vector2(0.5f, 0.5f), buttonContainer.RectTransform, Anchor.Center),
|
new GUIButton(new RectTransform(new Vector2(0.3f, 0.5f), buttonContainer.RectTransform, Anchor.Center),
|
||||||
style: "GUIButtonHorizontalArrow")
|
style: "UIToggleButton")
|
||||||
{
|
{
|
||||||
OnClicked = Close
|
OnClicked = Close
|
||||||
}
|
}
|
||||||
@@ -221,7 +221,7 @@ namespace Barotrauma
|
|||||||
Content.RectTransform.NonScaledSize =
|
Content.RectTransform.NonScaledSize =
|
||||||
new Point(Content.Rect.Width, height);
|
new Point(Content.Rect.Width, height);
|
||||||
}
|
}
|
||||||
Buttons[0].RectTransform.MaxSize = new Point(Math.Min(Buttons[0].Rect.Width, Buttons[0].Rect.Height));
|
Buttons[0].RectTransform.MaxSize = new Point((int)(0.4f * Buttons[0].Rect.Y), Buttons[0].Rect.Y);
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageBoxes.Add(this);
|
MessageBoxes.Add(this);
|
||||||
@@ -271,99 +271,92 @@ namespace Barotrauma
|
|||||||
|
|
||||||
protected override void Update(float deltaTime)
|
protected override void Update(float deltaTime)
|
||||||
{
|
{
|
||||||
if (type == Type.InGame)
|
if (type != Type.InGame) { return; }
|
||||||
|
|
||||||
|
Vector2 initialPos = new Vector2(0.0f, GameMain.GraphicsHeight);
|
||||||
|
Vector2 defaultPos = new Vector2(0.0f, HUDLayoutSettings.InventoryAreaLower.Y - InnerFrame.Rect.Height - 20 * GUI.Scale);
|
||||||
|
Vector2 endPos = new Vector2(GameMain.GraphicsWidth, defaultPos.Y);
|
||||||
|
|
||||||
|
if (!closing)
|
||||||
{
|
{
|
||||||
Vector2 initialPos = new Vector2(0.0f, GameMain.GraphicsHeight);
|
Point step = Vector2.SmoothStep(initialPos, defaultPos, openState).ToPoint();
|
||||||
Vector2 defaultPos = new Vector2(0.0f, HUDLayoutSettings.InventoryAreaLower.Y - InnerFrame.Rect.Height - 20 * GUI.Scale);
|
InnerFrame.RectTransform.AbsoluteOffset = step;
|
||||||
Vector2 endPos = new Vector2(GameMain.GraphicsWidth, defaultPos.Y);
|
if (BackgroundIcon != null)
|
||||||
|
|
||||||
/*for (int i = MessageBoxes.IndexOf(this); i >= 0; i--)
|
|
||||||
{
|
{
|
||||||
if (MessageBoxes[i] is GUIMessageBox otherMsgBox && otherMsgBox != this && otherMsgBox.type == type && !otherMsgBox.closing)
|
BackgroundIcon.RectTransform.AbsoluteOffset = new Point(InnerFrame.Rect.Location.X - (int) (BackgroundIcon.Rect.Size.X / 1.25f), (int)defaultPos.Y - BackgroundIcon.Rect.Size.Y / 2);
|
||||||
|
if (!MathUtils.NearlyEqual(openState, 1.0f))
|
||||||
{
|
{
|
||||||
defaultPos = new Vector2(
|
BackgroundIcon.Color = ToolBox.GradientLerp(openState, Color.Transparent, Color.White);
|
||||||
Math.Max(otherMsgBox.InnerFrame.RectTransform.AbsoluteOffset.X + 10 * GUI.Scale, defaultPos.X),
|
|
||||||
Math.Max(otherMsgBox.InnerFrame.RectTransform.AbsoluteOffset.Y + 10 * GUI.Scale, defaultPos.Y));
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
if (!closing)
|
|
||||||
{
|
|
||||||
Point step = Vector2.SmoothStep(initialPos, defaultPos, openState).ToPoint();
|
|
||||||
InnerFrame.RectTransform.AbsoluteOffset = step;
|
|
||||||
if (BackgroundIcon != null)
|
|
||||||
{
|
|
||||||
BackgroundIcon.RectTransform.AbsoluteOffset = new Point(InnerFrame.Rect.Location.X - (int) (BackgroundIcon.Rect.Size.X / 1.25f), (int)defaultPos.Y - BackgroundIcon.Rect.Size.Y / 2);
|
|
||||||
if (!MathUtils.NearlyEqual(openState, 1.0f))
|
|
||||||
{
|
|
||||||
BackgroundIcon.Color = ToolBox.GradientLerp(openState, Color.Transparent, Color.White);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
openState = Math.Min(openState + deltaTime * 2.0f, 1.0f);
|
|
||||||
|
|
||||||
if (GUI.MouseOn != InnerFrame && !InnerFrame.IsParentOf(GUI.MouseOn) && AutoClose)
|
|
||||||
{
|
|
||||||
inGameCloseTimer += deltaTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (inGameCloseTimer >= inGameCloseTime)
|
|
||||||
{
|
|
||||||
Close();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
if (!(Screen.Selected is RoundSummaryScreen) && !MessageBoxes.Any(mb => mb.UserData is RoundSummary))
|
||||||
|
{
|
||||||
|
openState = Math.Min(openState + deltaTime * 2.0f, 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GUI.MouseOn != InnerFrame && !InnerFrame.IsParentOf(GUI.MouseOn) && AutoClose)
|
||||||
|
{
|
||||||
|
inGameCloseTimer += deltaTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inGameCloseTimer >= inGameCloseTime)
|
||||||
|
{
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
openState += deltaTime * 2.0f;
|
||||||
|
Point step = Vector2.SmoothStep(defaultPos, endPos, openState - 1.0f).ToPoint();
|
||||||
|
InnerFrame.RectTransform.AbsoluteOffset = step;
|
||||||
|
if (BackgroundIcon != null)
|
||||||
|
{
|
||||||
|
BackgroundIcon.Color *= 0.9f;
|
||||||
|
}
|
||||||
|
if (openState >= 2.0f)
|
||||||
|
{
|
||||||
|
if (Parent != null) { Parent.RemoveChild(this); }
|
||||||
|
if (MessageBoxes.Contains(this)) { MessageBoxes.Remove(this); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newBackgroundIcon != null)
|
||||||
|
{
|
||||||
|
if (!iconSwitching)
|
||||||
{
|
{
|
||||||
openState += deltaTime * 2.0f;
|
|
||||||
Point step = Vector2.SmoothStep(defaultPos, endPos, openState - 1.0f).ToPoint();
|
|
||||||
InnerFrame.RectTransform.AbsoluteOffset = step;
|
|
||||||
if (BackgroundIcon != null)
|
if (BackgroundIcon != null)
|
||||||
{
|
{
|
||||||
BackgroundIcon.Color *= 0.9f;
|
BackgroundIcon.Color *= 0.9f;
|
||||||
}
|
if (BackgroundIcon.Color.A == 0)
|
||||||
if (openState >= 2.0f)
|
|
||||||
{
|
|
||||||
if (Parent != null) { Parent.RemoveChild(this); }
|
|
||||||
if (MessageBoxes.Contains(this)) { MessageBoxes.Remove(this); }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newBackgroundIcon != null)
|
|
||||||
{
|
|
||||||
if (!iconSwitching)
|
|
||||||
{
|
|
||||||
if (BackgroundIcon != null)
|
|
||||||
{
|
|
||||||
BackgroundIcon.Color *= 0.9f;
|
|
||||||
if (BackgroundIcon.Color.A == 0)
|
|
||||||
{
|
|
||||||
BackgroundIcon = null;
|
|
||||||
iconSwitching = true;
|
|
||||||
RemoveChild(BackgroundIcon);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
|
BackgroundIcon = null;
|
||||||
iconSwitching = true;
|
iconSwitching = true;
|
||||||
|
RemoveChild(BackgroundIcon);
|
||||||
}
|
}
|
||||||
iconState = 0;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
newBackgroundIcon.SetAsFirstChild();
|
iconSwitching = true;
|
||||||
newBackgroundIcon.RectTransform.AbsoluteOffset = new Point(InnerFrame.Rect.Location.X - (int) (newBackgroundIcon.Rect.Size.X / 1.25f), (int)defaultPos.Y - newBackgroundIcon.Rect.Size.Y / 2);
|
|
||||||
newBackgroundIcon.Color = ToolBox.GradientLerp(iconState, Color.Transparent, Color.White);
|
|
||||||
if (newBackgroundIcon.Color.A == 255)
|
|
||||||
{
|
|
||||||
BackgroundIcon = newBackgroundIcon;
|
|
||||||
BackgroundIcon.SetAsFirstChild();
|
|
||||||
newBackgroundIcon = null;
|
|
||||||
iconSwitching = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
iconState = Math.Min(iconState + deltaTime * 2.0f, 1.0f);
|
|
||||||
}
|
}
|
||||||
|
iconState = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
newBackgroundIcon.SetAsFirstChild();
|
||||||
|
newBackgroundIcon.RectTransform.AbsoluteOffset = new Point(InnerFrame.Rect.Location.X - (int) (newBackgroundIcon.Rect.Size.X / 1.25f), (int)defaultPos.Y - newBackgroundIcon.Rect.Size.Y / 2);
|
||||||
|
newBackgroundIcon.Color = ToolBox.GradientLerp(iconState, Color.Transparent, Color.White);
|
||||||
|
if (newBackgroundIcon.Color.A == 255)
|
||||||
|
{
|
||||||
|
BackgroundIcon = newBackgroundIcon;
|
||||||
|
BackgroundIcon.SetAsFirstChild();
|
||||||
|
newBackgroundIcon = null;
|
||||||
|
iconSwitching = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
iconState = Math.Min(iconState + deltaTime * 2.0f, 1.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -380,16 +380,18 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private void ClampIntValue()
|
private void ClampIntValue()
|
||||||
{
|
{
|
||||||
if (MinValueInt != null)
|
if (MinValueInt != null && intValue < MinValueInt.Value)
|
||||||
{
|
{
|
||||||
intValue = Math.Max(intValue, MinValueInt.Value);
|
intValue = Math.Max(intValue, MinValueInt.Value);
|
||||||
minusButton.Enabled = intValue > MinValueInt;
|
UpdateText();
|
||||||
}
|
}
|
||||||
if (MaxValueInt != null)
|
if (MaxValueInt != null && intValue > MaxValueInt.Value)
|
||||||
{
|
{
|
||||||
intValue = Math.Min(intValue, MaxValueInt.Value);
|
intValue = Math.Min(intValue, MaxValueInt.Value);
|
||||||
plusButton.Enabled = intValue < MaxValueInt;
|
UpdateText();
|
||||||
}
|
}
|
||||||
|
plusButton.Enabled = intValue < MaxValueInt;
|
||||||
|
minusButton.Enabled = intValue > MinValueInt;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateText()
|
private void UpdateText()
|
||||||
|
|||||||
@@ -462,7 +462,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
protected List<Tuple<Vector2, int>> GetAllPositions()
|
protected List<Tuple<Vector2, int>> GetAllPositions()
|
||||||
{
|
{
|
||||||
float halfHeight = Font.MeasureString("T").Y * 0.5f;
|
float halfHeight = Font.MeasureString("T").Y * 0.5f * textScale;
|
||||||
string textDrawn = Censor ? CensoredText : WrappedText;
|
string textDrawn = Censor ? CensoredText : WrappedText;
|
||||||
var positions = new List<Tuple<Vector2, int>>();
|
var positions = new List<Tuple<Vector2, int>>();
|
||||||
if (textDrawn.Contains("\n"))
|
if (textDrawn.Contains("\n"))
|
||||||
@@ -474,10 +474,10 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
string line = lines[i];
|
string line = lines[i];
|
||||||
totalIndex += line.Length;
|
totalIndex += line.Length;
|
||||||
float totalTextHeight = Font.MeasureString(textDrawn.Substring(0, totalIndex)).Y;
|
float totalTextHeight = Font.MeasureString(textDrawn.Substring(0, totalIndex)).Y * textScale;
|
||||||
for (int j = 0; j <= line.Length; j++)
|
for (int j = 0; j <= line.Length; j++)
|
||||||
{
|
{
|
||||||
Vector2 lineTextSize = Font.MeasureString(line.Substring(0, j));
|
Vector2 lineTextSize = Font.MeasureString(line.Substring(0, j)) * textScale;
|
||||||
Vector2 indexPos = new Vector2(lineTextSize.X + Padding.X, totalTextHeight + Padding.Y - halfHeight);
|
Vector2 indexPos = new Vector2(lineTextSize.X + Padding.X, totalTextHeight + Padding.Y - halfHeight);
|
||||||
//DebugConsole.NewMessage($"index: {index}, pos: {indexPos}", Color.AliceBlue);
|
//DebugConsole.NewMessage($"index: {index}, pos: {indexPos}", Color.AliceBlue);
|
||||||
positions.Add(new Tuple<Vector2, int>(indexPos, index + j));
|
positions.Add(new Tuple<Vector2, int>(indexPos, index + j));
|
||||||
@@ -490,8 +490,8 @@ namespace Barotrauma
|
|||||||
textDrawn = Censor ? CensoredText : Text;
|
textDrawn = Censor ? CensoredText : Text;
|
||||||
for (int i = 0; i <= Text.Length; i++)
|
for (int i = 0; i <= Text.Length; i++)
|
||||||
{
|
{
|
||||||
Vector2 textSize = Font.MeasureString(textDrawn.Substring(0, i));
|
Vector2 textSize = Font.MeasureString(textDrawn.Substring(0, i)) * textScale;
|
||||||
Vector2 indexPos = new Vector2(textSize.X + Padding.X, textSize.Y + Padding.Y - halfHeight) + TextPos - Origin;
|
Vector2 indexPos = new Vector2(textSize.X + Padding.X, textSize.Y + Padding.Y - halfHeight) + TextPos - Origin * textScale;
|
||||||
//DebugConsole.NewMessage($"index: {i}, pos: {indexPos}", Color.WhiteSmoke);
|
//DebugConsole.NewMessage($"index: {i}, pos: {indexPos}", Color.WhiteSmoke);
|
||||||
positions.Add(new Tuple<Vector2, int>(indexPos, i));
|
positions.Add(new Tuple<Vector2, int>(indexPos, i));
|
||||||
}
|
}
|
||||||
@@ -508,7 +508,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
var positions = GetAllPositions();
|
var positions = GetAllPositions();
|
||||||
if (positions.Count == 0) { return 0; }
|
if (positions.Count == 0) { return 0; }
|
||||||
float halfHeight = Font.MeasureString("T").Y * 0.5f;
|
float halfHeight = Font.MeasureString("T").Y * 0.5f * textScale;
|
||||||
|
|
||||||
var currPosition = positions[0];
|
var currPosition = positions[0];
|
||||||
|
|
||||||
@@ -522,7 +522,8 @@ namespace Barotrauma
|
|||||||
float diffY = Math.Abs(p1.Item1.Y - pos.Y) - Math.Abs(p2.Item1.Y - pos.Y);
|
float diffY = Math.Abs(p1.Item1.Y - pos.Y) - Math.Abs(p2.Item1.Y - pos.Y);
|
||||||
if (diffY < -3.0f)
|
if (diffY < -3.0f)
|
||||||
{
|
{
|
||||||
currPosition = p1; continue;
|
currPosition = p1;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
else if (diffY > 3.0f)
|
else if (diffY > 3.0f)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -325,7 +325,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
while (ClampText && textBlock.Text.Length>0 && Font.MeasureString(textBlock.Text).X > (int)(textBlock.Rect.Width - textBlock.Padding.X - textBlock.Padding.Z))
|
while (ClampText && textBlock.Text.Length > 0 && Font.MeasureString(textBlock.Text).X * TextBlock.TextScale > (int)(textBlock.Rect.Width - textBlock.Padding.X - textBlock.Padding.Z))
|
||||||
{
|
{
|
||||||
textBlock.Text = textBlock.Text.Substring(0, textBlock.Text.Length - 1);
|
textBlock.Text = textBlock.Text.Substring(0, textBlock.Text.Length - 1);
|
||||||
}
|
}
|
||||||
@@ -354,10 +354,10 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
int diff = totalIndex - CaretIndex;
|
int diff = totalIndex - CaretIndex;
|
||||||
int index = currentLineLength - diff;
|
int index = currentLineLength - diff;
|
||||||
Vector2 lineTextSize = Font.MeasureString(lines[i].Substring(0, index));
|
Vector2 lineTextSize = Font.MeasureString(lines[i].Substring(0, index)) * TextBlock.TextScale;
|
||||||
Vector2 lastLineSize = Font.MeasureString(lines[i]);
|
Vector2 lastLineSize = Font.MeasureString(lines[i]) * TextBlock.TextScale;
|
||||||
float totalTextHeight = Font.MeasureString(textDrawn.Substring(0, totalIndex)).Y;
|
float totalTextHeight = Font.MeasureString(textDrawn.Substring(0, totalIndex)).Y * TextBlock.TextScale;
|
||||||
caretPos = new Vector2(lineTextSize.X, totalTextHeight - lastLineSize.Y) + textBlock.TextPos - textBlock.Origin;
|
caretPos = new Vector2(lineTextSize.X, totalTextHeight - lastLineSize.Y) + textBlock.TextPos - textBlock.Origin * TextBlock.TextScale;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -366,8 +366,8 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
CaretIndex = Math.Min(CaretIndex, textDrawn.Length);
|
CaretIndex = Math.Min(CaretIndex, textDrawn.Length);
|
||||||
textDrawn = Censor ? textBlock.CensoredText : textBlock.Text;
|
textDrawn = Censor ? textBlock.CensoredText : textBlock.Text;
|
||||||
Vector2 textSize = Font.MeasureString(textDrawn.Substring(0, CaretIndex));
|
Vector2 textSize = Font.MeasureString(textDrawn.Substring(0, CaretIndex)) * TextBlock.TextScale;
|
||||||
caretPos = new Vector2(textSize.X, 0) + textBlock.TextPos - textBlock.Origin;
|
caretPos = new Vector2(textSize.X, 0) + textBlock.TextPos - textBlock.Origin * TextBlock.TextScale;
|
||||||
}
|
}
|
||||||
caretPosDirty = false;
|
caretPosDirty = false;
|
||||||
}
|
}
|
||||||
@@ -506,7 +506,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
GUI.DrawLine(spriteBatch,
|
GUI.DrawLine(spriteBatch,
|
||||||
new Vector2(Rect.X + (int)caretPos.X + 2, Rect.Y + caretPos.Y + 3),
|
new Vector2(Rect.X + (int)caretPos.X + 2, Rect.Y + caretPos.Y + 3),
|
||||||
new Vector2(Rect.X + (int)caretPos.X + 2, Rect.Y + caretPos.Y + Font.MeasureString("I").Y - 3),
|
new Vector2(Rect.X + (int)caretPos.X + 2, Rect.Y + caretPos.Y + Font.MeasureString("I").Y * textBlock.TextScale - 3),
|
||||||
CaretColor ?? textBlock.TextColor * (textBlock.TextColor.A / 255.0f));
|
CaretColor ?? textBlock.TextColor * (textBlock.TextColor.A / 255.0f));
|
||||||
}
|
}
|
||||||
if (selectedCharacters > 0)
|
if (selectedCharacters > 0)
|
||||||
@@ -544,7 +544,7 @@ namespace Barotrauma
|
|||||||
: selectionEndIndex < totalIndex && selectionStartIndex > previousCharacters;
|
: selectionEndIndex < totalIndex && selectionStartIndex > previousCharacters;
|
||||||
if (containsSelection)
|
if (containsSelection)
|
||||||
{
|
{
|
||||||
Vector2 currentLineSize = Font.MeasureString(currentLine);
|
Vector2 currentLineSize = Font.MeasureString(currentLine) * TextBlock.TextScale;
|
||||||
if ((IsLeftToRight && selectionStartIndex < previousCharacters && selectionEndIndex > totalIndex)
|
if ((IsLeftToRight && selectionStartIndex < previousCharacters && selectionEndIndex > totalIndex)
|
||||||
|| !IsLeftToRight && selectionEndIndex < previousCharacters && selectionStartIndex > totalIndex)
|
|| !IsLeftToRight && selectionEndIndex < previousCharacters && selectionStartIndex > totalIndex)
|
||||||
{
|
{
|
||||||
@@ -560,7 +560,7 @@ namespace Barotrauma
|
|||||||
int startIndex = selectFromTheBeginning ? 0 : Math.Abs(selectionStartIndex - previousCharacters);
|
int startIndex = selectFromTheBeginning ? 0 : Math.Abs(selectionStartIndex - previousCharacters);
|
||||||
int endIndex = Math.Abs(selectionEndIndex - previousCharacters);
|
int endIndex = Math.Abs(selectionEndIndex - previousCharacters);
|
||||||
int characters = Math.Min(endIndex - startIndex, currentLineLength - startIndex);
|
int characters = Math.Min(endIndex - startIndex, currentLineLength - startIndex);
|
||||||
Vector2 selectedTextSize = Font.MeasureString(currentLine.Substring(startIndex, characters));
|
Vector2 selectedTextSize = Font.MeasureString(currentLine.Substring(startIndex, characters)) * TextBlock.TextScale;
|
||||||
Vector2 topLeft = selectFromTheBeginning
|
Vector2 topLeft = selectFromTheBeginning
|
||||||
? new Vector2(offset.X, offset.Y + currentLineSize.Y * i)
|
? new Vector2(offset.X, offset.Y + currentLineSize.Y * i)
|
||||||
: new Vector2(selectionStartPos.X, offset.Y + currentLineSize.Y * i);
|
: new Vector2(selectionStartPos.X, offset.Y + currentLineSize.Y * i);
|
||||||
@@ -573,7 +573,7 @@ namespace Barotrauma
|
|||||||
int startIndex = selectFromTheBeginning ? currentLineLength : Math.Abs(selectionStartIndex - previousCharacters);
|
int startIndex = selectFromTheBeginning ? currentLineLength : Math.Abs(selectionStartIndex - previousCharacters);
|
||||||
int endIndex = selectFromTheStart ? 0 : Math.Abs(selectionEndIndex - previousCharacters);
|
int endIndex = selectFromTheStart ? 0 : Math.Abs(selectionEndIndex - previousCharacters);
|
||||||
int characters = Math.Min(Math.Abs(endIndex - startIndex), currentLineLength);
|
int characters = Math.Min(Math.Abs(endIndex - startIndex), currentLineLength);
|
||||||
Vector2 selectedTextSize = Font.MeasureString(currentLine.Substring(endIndex, characters));
|
Vector2 selectedTextSize = Font.MeasureString(currentLine.Substring(endIndex, characters)) * TextBlock.TextScale;
|
||||||
Vector2 topLeft = selectFromTheBeginning
|
Vector2 topLeft = selectFromTheBeginning
|
||||||
? new Vector2(offset.X + currentLineSize.X - selectedTextSize.X, offset.Y + currentLineSize.Y * i)
|
? new Vector2(offset.X + currentLineSize.X - selectedTextSize.X, offset.Y + currentLineSize.Y * i)
|
||||||
: new Vector2(selectionStartPos.X - selectedTextSize.X, offset.Y + currentLineSize.Y * i);
|
: new Vector2(selectionStartPos.X - selectedTextSize.X, offset.Y + currentLineSize.Y * i);
|
||||||
@@ -612,7 +612,7 @@ namespace Barotrauma
|
|||||||
OnTextChanged?.Invoke(this, Text);
|
OnTextChanged?.Invoke(this, Text);
|
||||||
if (textBlock.OverflowClipActive && wasOverflowClipActive && !MathUtils.NearlyEqual(textBlock.TextPos, textPos))
|
if (textBlock.OverflowClipActive && wasOverflowClipActive && !MathUtils.NearlyEqual(textBlock.TextPos, textPos))
|
||||||
{
|
{
|
||||||
textBlock.TextPos = textPos + Vector2.UnitX * Font.MeasureString(input).X;
|
textBlock.TextPos = textPos + Vector2.UnitX * Font.MeasureString(input).X * TextBlock.TextScale;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -714,8 +714,8 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
InitSelectionStart();
|
InitSelectionStart();
|
||||||
}
|
}
|
||||||
float lineHeight = Font.MeasureString("T").Y;
|
float lineHeight = Font.MeasureString("T").Y * TextBlock.TextScale;
|
||||||
int newIndex = textBlock.GetCaretIndexFromLocalPos(new Vector2(caretPos.X, caretPos.Y-lineHeight));
|
int newIndex = textBlock.GetCaretIndexFromLocalPos(new Vector2(caretPos.X, caretPos.Y - lineHeight));
|
||||||
CaretIndex = newIndex;
|
CaretIndex = newIndex;
|
||||||
caretTimer = 0;
|
caretTimer = 0;
|
||||||
HandleSelection();
|
HandleSelection();
|
||||||
@@ -725,8 +725,8 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
InitSelectionStart();
|
InitSelectionStart();
|
||||||
}
|
}
|
||||||
lineHeight = Font.MeasureString("T").Y;
|
lineHeight = Font.MeasureString("T").Y * TextBlock.TextScale;
|
||||||
newIndex = textBlock.GetCaretIndexFromLocalPos(new Vector2(caretPos.X, caretPos.Y+lineHeight));
|
newIndex = textBlock.GetCaretIndexFromLocalPos(new Vector2(caretPos.X, caretPos.Y + lineHeight));
|
||||||
CaretIndex = newIndex;
|
CaretIndex = newIndex;
|
||||||
caretTimer = 0;
|
caretTimer = 0;
|
||||||
HandleSelection();
|
HandleSelection();
|
||||||
@@ -865,18 +865,18 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
string textDrawn = Censor ? textBlock.CensoredText : textBlock.WrappedText;
|
string textDrawn = Censor ? textBlock.CensoredText : textBlock.WrappedText;
|
||||||
InitSelectionStart();
|
InitSelectionStart();
|
||||||
selectionEndIndex = CaretIndex;
|
selectionEndIndex = Math.Min(CaretIndex, textDrawn.Length);
|
||||||
selectionEndPos = caretPos;
|
selectionEndPos = caretPos;
|
||||||
selectedCharacters = Math.Abs(selectionStartIndex - selectionEndIndex);
|
selectedCharacters = Math.Abs(selectionStartIndex - selectionEndIndex);
|
||||||
if (IsLeftToRight)
|
if (IsLeftToRight)
|
||||||
{
|
{
|
||||||
selectedText = Text.Substring(selectionStartIndex, selectedCharacters);
|
selectedText = Text.Substring(selectionStartIndex, selectedCharacters);
|
||||||
selectionRectSize = Font.MeasureString(textDrawn.Substring(selectionStartIndex, selectedCharacters));
|
selectionRectSize = Font.MeasureString(textDrawn.Substring(selectionStartIndex, selectedCharacters)) * TextBlock.TextScale;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
selectedText = Text.Substring(selectionEndIndex, selectedCharacters);
|
selectedText = Text.Substring(selectionEndIndex, Math.Min(selectedCharacters, textDrawn.Length - selectionEndIndex));
|
||||||
selectionRectSize = Font.MeasureString(textDrawn.Substring(selectionEndIndex, selectedCharacters));
|
selectionRectSize = Font.MeasureString(textDrawn.Substring(selectionEndIndex, selectedCharacters)) * TextBlock.TextScale;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,6 +68,10 @@ namespace Barotrauma
|
|||||||
CreateUI();
|
CreateUI();
|
||||||
|
|
||||||
campaignUI.Campaign.Map.OnLocationChanged += UpdateLocation;
|
campaignUI.Campaign.Map.OnLocationChanged += UpdateLocation;
|
||||||
|
if (CurrentLocation?.Reputation != null)
|
||||||
|
{
|
||||||
|
CurrentLocation.Reputation.OnReputationValueChanged += Refresh;
|
||||||
|
}
|
||||||
campaignUI.Campaign.CargoManager.OnItemsInBuyCrateChanged += RefreshBuying;
|
campaignUI.Campaign.CargoManager.OnItemsInBuyCrateChanged += RefreshBuying;
|
||||||
campaignUI.Campaign.CargoManager.OnPurchasedItemsChanged += RefreshBuying;
|
campaignUI.Campaign.CargoManager.OnPurchasedItemsChanged += RefreshBuying;
|
||||||
campaignUI.Campaign.CargoManager.OnItemsInSellCrateChanged += RefreshSelling;
|
campaignUI.Campaign.CargoManager.OnItemsInSellCrateChanged += RefreshSelling;
|
||||||
@@ -378,9 +382,13 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
Stretch = true
|
Stretch = true
|
||||||
};
|
};
|
||||||
new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), totalContainer.RectTransform), TextManager.Get("campaignstore.total"), font: GUI.Font);
|
new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), totalContainer.RectTransform), TextManager.Get("campaignstore.total"), font: GUI.Font)
|
||||||
|
{
|
||||||
|
CanBeFocused = false
|
||||||
|
};
|
||||||
shoppingCrateTotal = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), totalContainer.RectTransform), "", font: GUI.SubHeadingFont, textAlignment: Alignment.Right)
|
shoppingCrateTotal = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), totalContainer.RectTransform), "", font: GUI.SubHeadingFont, textAlignment: Alignment.Right)
|
||||||
{
|
{
|
||||||
|
CanBeFocused = false,
|
||||||
TextScale = 1.1f
|
TextScale = 1.1f
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -412,11 +420,20 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (prevLocation == newLocation) { return; }
|
if (prevLocation == newLocation) { return; }
|
||||||
|
|
||||||
|
if (prevLocation?.Reputation != null)
|
||||||
|
{
|
||||||
|
prevLocation.Reputation.OnReputationValueChanged -= Refresh;
|
||||||
|
}
|
||||||
|
|
||||||
foreach (ItemPrefab itemPrefab in ItemPrefab.Prefabs)
|
foreach (ItemPrefab itemPrefab in ItemPrefab.Prefabs)
|
||||||
{
|
{
|
||||||
if (itemPrefab.CanBeBoughtAtLocation(CurrentLocation, out PriceInfo _))
|
if (itemPrefab.CanBeBoughtAtLocation(CurrentLocation, out PriceInfo _))
|
||||||
{
|
{
|
||||||
ChangeStoreTab(StoreTab.Buy);
|
ChangeStoreTab(StoreTab.Buy);
|
||||||
|
if (newLocation?.Reputation != null)
|
||||||
|
{
|
||||||
|
newLocation.Reputation.OnReputationValueChanged += Refresh;
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -717,9 +734,15 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private GUIComponent CreateItemFrame(PurchasedItem pi, PriceInfo priceInfo, GUIListBox listBox, bool forceDisable = false)
|
private GUIComponent CreateItemFrame(PurchasedItem pi, PriceInfo priceInfo, GUIListBox listBox, bool forceDisable = false)
|
||||||
{
|
{
|
||||||
|
var tooltip = pi.ItemPrefab.Name;
|
||||||
|
if (!string.IsNullOrWhiteSpace(pi.ItemPrefab.Description))
|
||||||
|
{
|
||||||
|
tooltip += "\n" + pi.ItemPrefab.Description;
|
||||||
|
}
|
||||||
|
|
||||||
GUIFrame frame = new GUIFrame(new RectTransform(new Point(listBox.Content.Rect.Width, (int)(GUI.yScale * 60)), parent: listBox.Content.RectTransform), style: "ListBoxElement")
|
GUIFrame frame = new GUIFrame(new RectTransform(new Point(listBox.Content.Rect.Width, (int)(GUI.yScale * 60)), parent: listBox.Content.RectTransform), style: "ListBoxElement")
|
||||||
{
|
{
|
||||||
ToolTip = pi.ItemPrefab.Description,
|
ToolTip = tooltip,
|
||||||
UserData = pi
|
UserData = pi
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -740,6 +763,7 @@ namespace Barotrauma
|
|||||||
iconRelativeWidth = (0.9f * mainGroup.Rect.Height) / mainGroup.Rect.Width;
|
iconRelativeWidth = (0.9f * mainGroup.Rect.Height) / mainGroup.Rect.Width;
|
||||||
GUIImage img = new GUIImage(new RectTransform(new Vector2(iconRelativeWidth, 0.9f), mainGroup.RectTransform), itemIcon, scaleToFit: true)
|
GUIImage img = new GUIImage(new RectTransform(new Vector2(iconRelativeWidth, 0.9f), mainGroup.RectTransform), itemIcon, scaleToFit: true)
|
||||||
{
|
{
|
||||||
|
CanBeFocused = false,
|
||||||
Color = (itemIcon == pi.ItemPrefab.InventoryIcon ? pi.ItemPrefab.InventoryIconColor : pi.ItemPrefab.SpriteColor) * (forceDisable ? 0.5f : 1.0f),
|
Color = (itemIcon == pi.ItemPrefab.InventoryIcon ? pi.ItemPrefab.InventoryIconColor : pi.ItemPrefab.SpriteColor) * (forceDisable ? 0.5f : 1.0f),
|
||||||
UserData = "icon"
|
UserData = "icon"
|
||||||
};
|
};
|
||||||
@@ -748,8 +772,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
GUILayoutGroup nameAndQuantityGroup = new GUILayoutGroup(new RectTransform(new Vector2(nameAndIconRelativeWidth - iconRelativeWidth, 1.0f), mainGroup.RectTransform))
|
GUILayoutGroup nameAndQuantityGroup = new GUILayoutGroup(new RectTransform(new Vector2(nameAndIconRelativeWidth - iconRelativeWidth, 1.0f), mainGroup.RectTransform))
|
||||||
{
|
{
|
||||||
Stretch = true,
|
CanBeFocused = false,
|
||||||
ToolTip = pi.ItemPrefab.Description
|
Stretch = true
|
||||||
};
|
};
|
||||||
GUITextBlock nameBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), nameAndQuantityGroup.RectTransform),
|
GUITextBlock nameBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), nameAndQuantityGroup.RectTransform),
|
||||||
pi.ItemPrefab.Name, font: GUI.SubHeadingFont, textAlignment: Alignment.BottomLeft)
|
pi.ItemPrefab.Name, font: GUI.SubHeadingFont, textAlignment: Alignment.BottomLeft)
|
||||||
@@ -801,8 +825,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
var priceBlock = new GUITextBlock(new RectTransform(new Vector2(priceAndButtonRelativeWidth - buttonRelativeWidth, 1.0f), mainGroup.RectTransform), "", font: GUI.SubHeadingFont, textAlignment: Alignment.Right)
|
var priceBlock = new GUITextBlock(new RectTransform(new Vector2(priceAndButtonRelativeWidth - buttonRelativeWidth, 1.0f), mainGroup.RectTransform), "", font: GUI.SubHeadingFont, textAlignment: Alignment.Right)
|
||||||
{
|
{
|
||||||
|
CanBeFocused = false,
|
||||||
TextColor = Color.White * (forceDisable ? 0.5f : 1.0f),
|
TextColor = Color.White * (forceDisable ? 0.5f : 1.0f),
|
||||||
ToolTip = pi.ItemPrefab.Description,
|
|
||||||
UserData = "price"
|
UserData = "price"
|
||||||
};
|
};
|
||||||
if(listBox == storeSellList || listBox == shoppingCrateSellList)
|
if(listBox == storeSellList || listBox == shoppingCrateSellList)
|
||||||
|
|||||||
@@ -788,17 +788,12 @@ namespace Barotrauma
|
|||||||
string msg = ChatMessage.GetTimeStamp() + message.TextWithSender;
|
string msg = ChatMessage.GetTimeStamp() + message.TextWithSender;
|
||||||
storedMessages.Add(new Pair<string, PlayerConnectionChangeType>(msg, message.ChangeType));
|
storedMessages.Add(new Pair<string, PlayerConnectionChangeType>(msg, message.ChangeType));
|
||||||
|
|
||||||
if (GameSession.IsTabMenuOpen)
|
if (GameSession.IsTabMenuOpen && selectedTab == InfoFrameTab.Crew)
|
||||||
{
|
{
|
||||||
TabMenu instance = GameSession.TabMenuInstance;
|
TabMenu instance = GameSession.TabMenuInstance;
|
||||||
instance.AddLineToLog(msg, message.ChangeType);
|
instance.AddLineToLog(msg, message.ChangeType);
|
||||||
|
instance.RemoveCurrentElements();
|
||||||
// Update crew
|
instance.CreateMultiPlayerList(true);
|
||||||
if (selectedTab == InfoFrameTab.Crew)
|
|
||||||
{
|
|
||||||
instance.RemoveCurrentElements();
|
|
||||||
instance.CreateMultiPlayerList(true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -835,14 +830,15 @@ namespace Barotrauma
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), logList.Content.RectTransform), line, wrap: true, font: GUI.SmallFont)
|
if (logList != null)
|
||||||
{
|
{
|
||||||
TextColor = textColor,
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), logList.Content.RectTransform), line, wrap: true, font: GUI.SmallFont)
|
||||||
CanBeFocused = false,
|
{
|
||||||
UserData = line
|
TextColor = textColor,
|
||||||
}.CalculateHeightFromText();
|
CanBeFocused = false,
|
||||||
|
UserData = line
|
||||||
//if ((prevSize == 1.0f && listBox.BarScroll == 0.0f) || (prevSize < 1.0f && listBox.BarScroll == 1.0f)) listBox.BarScroll = 1.0f;
|
}.CalculateHeightFromText();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CreateMissionInfo(GUIFrame infoFrame)
|
private void CreateMissionInfo(GUIFrame infoFrame)
|
||||||
|
|||||||
@@ -56,11 +56,6 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public static Thread MainThread { get; private set; }
|
public static Thread MainThread { get; private set; }
|
||||||
|
|
||||||
public static IEnumerable<ContentPackage> SelectedPackages
|
|
||||||
{
|
|
||||||
get { return Config?.SelectedContentPackages; }
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ContentPackage vanillaContent;
|
private static ContentPackage vanillaContent;
|
||||||
public static ContentPackage VanillaContent
|
public static ContentPackage VanillaContent
|
||||||
{
|
{
|
||||||
@@ -69,7 +64,7 @@ namespace Barotrauma
|
|||||||
if (vanillaContent == null)
|
if (vanillaContent == null)
|
||||||
{
|
{
|
||||||
// TODO: Dynamic method for defining and finding the vanilla content package.
|
// TODO: Dynamic method for defining and finding the vanilla content package.
|
||||||
vanillaContent = ContentPackage.List.SingleOrDefault(cp => Path.GetFileName(cp.Path).Equals("vanilla 0.9.xml", StringComparison.OrdinalIgnoreCase));
|
vanillaContent = ContentPackage.CorePackages.SingleOrDefault(cp => Path.GetFileName(cp.Path).Equals("vanilla 0.9.xml", StringComparison.OrdinalIgnoreCase));
|
||||||
}
|
}
|
||||||
return vanillaContent;
|
return vanillaContent;
|
||||||
}
|
}
|
||||||
@@ -454,40 +449,31 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GUI.Init(Window, Config.SelectedContentPackages, GraphicsDevice);
|
GUI.Init(Window, Config.AllEnabledPackages, GraphicsDevice);
|
||||||
DebugConsole.Init();
|
DebugConsole.Init();
|
||||||
|
|
||||||
if (Config.AutoUpdateWorkshopItems)
|
if (Config.AutoUpdateWorkshopItems)
|
||||||
{
|
{
|
||||||
bool waitingForWorkshopUpdates = true;
|
Config.WaitingForAutoUpdate = true;
|
||||||
bool result = false;
|
|
||||||
TaskPool.Add("AutoUpdateWorkshopItemsAsync",
|
TaskPool.Add("AutoUpdateWorkshopItemsAsync",
|
||||||
SteamManager.AutoUpdateWorkshopItemsAsync(), (task) =>
|
SteamManager.AutoUpdateWorkshopItemsAsync(), (task) =>
|
||||||
{
|
{
|
||||||
result = ((Task<bool>)task).Result;
|
bool result = ((Task<bool>)task).Result;
|
||||||
waitingForWorkshopUpdates = false;
|
|
||||||
|
Config.WaitingForAutoUpdate = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
while (waitingForWorkshopUpdates) { yield return CoroutineStatus.Running; }
|
while (Config.WaitingForAutoUpdate) { yield return CoroutineStatus.Running; }
|
||||||
|
|
||||||
if (result)
|
|
||||||
{
|
|
||||||
CrossThread.RequestExecutionOnMainThread(() =>
|
|
||||||
{
|
|
||||||
ContentPackage.LoadAll();
|
|
||||||
Config.ReloadContentPackages();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (SelectedPackages.None())
|
if (Config.AllEnabledPackages.None())
|
||||||
{
|
{
|
||||||
DebugConsole.Log("No content packages selected");
|
DebugConsole.Log("No content packages selected");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DebugConsole.Log("Selected content packages: " + string.Join(", ", SelectedPackages.Select(cp => cp.Name)));
|
DebugConsole.Log("Selected content packages: " + string.Join(", ", Config.AllEnabledPackages.Select(cp => cp.Name)));
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
@@ -542,6 +528,7 @@ namespace Barotrauma
|
|||||||
OutpostGenerationParams.LoadPresets();
|
OutpostGenerationParams.LoadPresets();
|
||||||
WreckAIConfig.LoadAll();
|
WreckAIConfig.LoadAll();
|
||||||
EventSet.LoadPrefabs();
|
EventSet.LoadPrefabs();
|
||||||
|
ItemPrefab.LoadAll(GetFilesOfType(ContentType.Item));
|
||||||
AfflictionPrefab.LoadAll(GetFilesOfType(ContentType.Afflictions));
|
AfflictionPrefab.LoadAll(GetFilesOfType(ContentType.Afflictions));
|
||||||
SkillSettings.Load(GetFilesOfType(ContentType.SkillSettings));
|
SkillSettings.Load(GetFilesOfType(ContentType.SkillSettings));
|
||||||
Order.Init();
|
Order.Init();
|
||||||
@@ -550,10 +537,6 @@ namespace Barotrauma
|
|||||||
yield return CoroutineStatus.Running;
|
yield return CoroutineStatus.Running;
|
||||||
|
|
||||||
StructurePrefab.LoadAll(GetFilesOfType(ContentType.Structure));
|
StructurePrefab.LoadAll(GetFilesOfType(ContentType.Structure));
|
||||||
TitleScreen.LoadState = 53.0f;
|
|
||||||
yield return CoroutineStatus.Running;
|
|
||||||
|
|
||||||
ItemPrefab.LoadAll(GetFilesOfType(ContentType.Item));
|
|
||||||
TitleScreen.LoadState = 55.0f;
|
TitleScreen.LoadState = 55.0f;
|
||||||
yield return CoroutineStatus.Running;
|
yield return CoroutineStatus.Running;
|
||||||
|
|
||||||
@@ -628,8 +611,6 @@ namespace Barotrauma
|
|||||||
LocationType.Init();
|
LocationType.Init();
|
||||||
MainMenuScreen.Select();
|
MainMenuScreen.Select();
|
||||||
|
|
||||||
CheckContentPackage();
|
|
||||||
|
|
||||||
foreach (string steamError in SteamManager.InitializationErrors)
|
foreach (string steamError in SteamManager.InitializationErrors)
|
||||||
{
|
{
|
||||||
new GUIMessageBox(TextManager.Get("Error"), TextManager.Get(steamError));
|
new GUIMessageBox(TextManager.Get("Error"), TextManager.Get(steamError));
|
||||||
@@ -645,29 +626,6 @@ namespace Barotrauma
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CheckContentPackage()
|
|
||||||
{
|
|
||||||
foreach (ContentPackage contentPackage in Config.SelectedContentPackages)
|
|
||||||
{
|
|
||||||
var exePaths = contentPackage.GetFilesOfType(ContentType.Executable);
|
|
||||||
if (exePaths.Any() && AppDomain.CurrentDomain.FriendlyName != Path.GetFileNameWithoutExtension(exePaths.First()))
|
|
||||||
{
|
|
||||||
var msgBox = new GUIMessageBox(TextManager.Get("Error"), TextManager.GetWithVariables("IncorrectExe",
|
|
||||||
new string[2] { "[selectedpackage]", "[exename]" }, new string[2] { contentPackage.Name, exePaths.First() }),
|
|
||||||
new string[] { TextManager.Get("Yes"), TextManager.Get("No") });
|
|
||||||
msgBox.Buttons[0].OnClicked += (_, userdata) =>
|
|
||||||
{
|
|
||||||
string fullPath = Path.GetFullPath(exePaths.First());
|
|
||||||
ToolBox.OpenFileWithShell(fullPath);
|
|
||||||
Exit();
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
msgBox.Buttons[1].OnClicked = msgBox.Close;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// UnloadContent will be called once per game and is the place to unload
|
/// UnloadContent will be called once per game and is the place to unload
|
||||||
/// all content.
|
/// all content.
|
||||||
@@ -690,11 +648,11 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (searchAllContentPackages)
|
if (searchAllContentPackages)
|
||||||
{
|
{
|
||||||
return ContentPackage.GetFilesOfType(ContentPackage.List, type);
|
return ContentPackage.GetFilesOfType(ContentPackage.AllPackages, type);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return ContentPackage.GetFilesOfType(SelectedPackages, type);
|
return ContentPackage.GetFilesOfType(Config.AllEnabledPackages, type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -938,6 +896,7 @@ namespace Barotrauma
|
|||||||
if (GameSession?.GameMode != null && GameSession.GameMode.Paused)
|
if (GameSession?.GameMode != null && GameSession.GameMode.Paused)
|
||||||
{
|
{
|
||||||
Paused = true;
|
Paused = true;
|
||||||
|
GameSession.GameMode.UpdateWhilePaused((float)Timing.Step);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !DEBUG
|
#if !DEBUG
|
||||||
@@ -960,7 +919,6 @@ namespace Barotrauma
|
|||||||
DebugConsole.AddToGUIUpdateList();
|
DebugConsole.AddToGUIUpdateList();
|
||||||
|
|
||||||
DebugConsole.Update((float)Timing.Step);
|
DebugConsole.Update((float)Timing.Step);
|
||||||
Paused = Paused || (DebugConsole.IsOpen && (NetworkMember == null || !NetworkMember.GameStarted));
|
|
||||||
|
|
||||||
if (!Paused)
|
if (!Paused)
|
||||||
{
|
{
|
||||||
@@ -1088,11 +1046,11 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update store stock when saving and quitting in an outpost (normally updated when CampaignMode.End() is called)
|
// Update store stock when saving and quitting in an outpost (normally updated when CampaignMode.End() is called)
|
||||||
if (GameSession?.Campaign is SinglePlayerCampaign campaign && Level.IsLoadedOutpost && campaign.Map?.CurrentLocation != null && campaign.CargoManager != null)
|
if (GameSession?.Campaign is SinglePlayerCampaign spCampaign && Level.IsLoadedOutpost && spCampaign.Map?.CurrentLocation != null && spCampaign.CargoManager != null)
|
||||||
{
|
{
|
||||||
campaign.Map.CurrentLocation.AddToStock(campaign.CargoManager.SoldItems);
|
spCampaign.Map.CurrentLocation.AddToStock(spCampaign.CargoManager.SoldItems);
|
||||||
campaign.CargoManager.ClearSoldItemsProjSpecific();
|
spCampaign.CargoManager.ClearSoldItemsProjSpecific();
|
||||||
campaign.Map.CurrentLocation.RemoveFromStock(campaign.CargoManager.PurchasedItems);
|
spCampaign.Map.CurrentLocation.RemoveFromStock(spCampaign.CargoManager.PurchasedItems);
|
||||||
}
|
}
|
||||||
|
|
||||||
SaveUtil.SaveGame(GameSession.SavePath);
|
SaveUtil.SaveGame(GameSession.SavePath);
|
||||||
|
|||||||
@@ -10,8 +10,17 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
public enum SellStatus
|
public enum SellStatus
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Entity sold in SP. Or, entity sold by client and confirmed by server in MP.
|
||||||
|
/// </summary>
|
||||||
Confirmed,
|
Confirmed,
|
||||||
|
/// <summary>
|
||||||
|
/// Entity sold by client in MP. Client has received at least one update from server after selling, but this entity wasn't yet confirmed.
|
||||||
|
/// </summary>
|
||||||
Unconfirmed,
|
Unconfirmed,
|
||||||
|
/// <summary>
|
||||||
|
/// Entity sold by client in MP. Client hasn't yet received an update from server after selling.
|
||||||
|
/// </summary>
|
||||||
Local
|
Local
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,28 +45,41 @@ namespace Barotrauma
|
|||||||
|
|
||||||
// Only consider items which have been:
|
// Only consider items which have been:
|
||||||
// a) sold in singleplayer or confirmed by server (SellStatus.Confirmed); or
|
// a) sold in singleplayer or confirmed by server (SellStatus.Confirmed); or
|
||||||
// b) sold locally in multiplier (SellStatus.Local), but the client has not received a campaing state update yet after selling them
|
// b) sold locally in multiplayer (SellStatus.Local), but the client has not received a campaing state update yet after selling them
|
||||||
var soldEntities = SoldEntities.Where(se => se.Status != SoldEntity.SellStatus.Unconfirmed);
|
var soldEntities = SoldEntities.Where(se => se.Status != SoldEntity.SellStatus.Unconfirmed);
|
||||||
|
|
||||||
var sellables = Item.ItemList.FindAll(i => i?.Prefab != null && !i.Removed &&
|
var sellables = Item.ItemList.FindAll(i => i?.Prefab != null && !i.Removed &&
|
||||||
i.GetRootInventoryOwner() == character &&
|
i.GetRootInventoryOwner() == character &&
|
||||||
!i.SpawnedInOutpost &&
|
!i.SpawnedInOutpost &&
|
||||||
(i.ContainedItems == null || i.ContainedItems.None() || i.ContainedItems.All(ci => soldEntities.Any(se => se.Item == ci))) &&
|
(i.ContainedItems == null || i.ContainedItems.None() || i.ContainedItems.All(ci => soldEntities.Any(se => se.Item == ci))) &&
|
||||||
i.IsFullCondition && soldEntities.None(se => se.Item == i));
|
i.Condition >= 0.9f * i.MaxCondition && soldEntities.None(se => se.Item == i));
|
||||||
|
|
||||||
// Prevent selling things like battery cells from headsets and oxygen tanks from diving masks
|
// Prevent selling items in equipment slots
|
||||||
var slots = new List<InvSlotType>() { InvSlotType.Head, InvSlotType.OuterClothes, InvSlotType.Headset };
|
var slots = new List<InvSlotType>() { InvSlotType.Head, InvSlotType.InnerClothes, InvSlotType.OuterClothes, InvSlotType.Headset, InvSlotType.Card };
|
||||||
foreach (InvSlotType slot in slots)
|
foreach (InvSlotType slot in slots)
|
||||||
{
|
{
|
||||||
var index = character.Inventory.FindLimbSlot(slot);
|
var index = character.Inventory.FindLimbSlot(slot);
|
||||||
if (character.Inventory.Items[index] is Item item && item.ContainedItems != null)
|
if (character.Inventory.Items[index] is Item item)
|
||||||
|
{
|
||||||
|
// Don't prevent selling of items which can only be put in equipment slots (like diving suits)
|
||||||
|
if (item.AllowedSlots.Contains(InvSlotType.Any))
|
||||||
|
{
|
||||||
|
sellables.Remove(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prevent selling items contained in certain equipped items (like battery cell in equipped headset or oxygen tank in equipped diving mask)
|
||||||
|
slots = new List<InvSlotType>() { InvSlotType.Head, InvSlotType.OuterClothes, InvSlotType.Headset };
|
||||||
|
foreach (InvSlotType slot in slots)
|
||||||
|
{
|
||||||
|
var index = character.Inventory.FindLimbSlot(slot);
|
||||||
|
if (character.Inventory.Items[index] is Item item &&
|
||||||
|
item.ContainedItems != null && item.AllowedSlots.Contains(InvSlotType.Any))
|
||||||
{
|
{
|
||||||
foreach (Item containedItem in item.ContainedItems)
|
foreach (Item containedItem in item.ContainedItems)
|
||||||
{
|
{
|
||||||
if (containedItem != null)
|
sellables.Remove(containedItem);
|
||||||
{
|
|
||||||
sellables.Remove(containedItem);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -123,7 +145,7 @@ namespace Barotrauma
|
|||||||
var itemValue = GetSellValueAtCurrentLocation(item.ItemPrefab, quantity: item.Quantity);
|
var itemValue = GetSellValueAtCurrentLocation(item.ItemPrefab, quantity: item.Quantity);
|
||||||
|
|
||||||
// check if the store can afford the item
|
// check if the store can afford the item
|
||||||
if (location.StoreCurrentBalance < itemValue) { continue; }
|
if (Location.StoreCurrentBalance < itemValue) { continue; }
|
||||||
|
|
||||||
var matchingItems = itemsInInventory.FindAll(i => i.Prefab == item.ItemPrefab);
|
var matchingItems = itemsInInventory.FindAll(i => i.Prefab == item.ItemPrefab);
|
||||||
if (matchingItems.Count <= item.Quantity)
|
if (matchingItems.Count <= item.Quantity)
|
||||||
@@ -147,7 +169,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Exchange money
|
// Exchange money
|
||||||
campaign.Map.CurrentLocation.StoreCurrentBalance -= itemValue;
|
Location.StoreCurrentBalance -= itemValue;
|
||||||
campaign.Money += itemValue;
|
campaign.Money += itemValue;
|
||||||
|
|
||||||
// Remove from the sell crate
|
// Remove from the sell crate
|
||||||
|
|||||||
@@ -15,11 +15,6 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
partial class CrewManager
|
partial class CrewManager
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// How long the previously selected character waits doing nothing when switching to another character. Only affects idling.
|
|
||||||
/// </summary>
|
|
||||||
const float CharacterWaitOnSwitch = 10.0f;
|
|
||||||
|
|
||||||
private Point screenResolution;
|
private Point screenResolution;
|
||||||
|
|
||||||
#region UI
|
#region UI
|
||||||
@@ -63,6 +58,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private Sprite jobIndicatorBackground, previousOrderArrow, cancelIcon;
|
private Sprite jobIndicatorBackground, previousOrderArrow, cancelIcon;
|
||||||
|
|
||||||
|
private const int MaxOrderIcons = 3;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Constructors
|
#region Constructors
|
||||||
@@ -363,9 +360,10 @@ namespace Barotrauma
|
|||||||
UserData = character
|
UserData = character
|
||||||
};
|
};
|
||||||
|
|
||||||
// "Padding" to prevent member-specific command button from overlapping job indicator
|
|
||||||
var commandButtonAbsoluteHeight = Math.Min(40.0f, 0.67f * background.Rect.Height);
|
var commandButtonAbsoluteHeight = Math.Min(40.0f, 0.67f * background.Rect.Height);
|
||||||
var paddingRelativeWidth = 0.35f * commandButtonAbsoluteHeight / background.Rect.Width;
|
var paddingRelativeWidth = 0.35f * commandButtonAbsoluteHeight / background.Rect.Width;
|
||||||
|
|
||||||
|
// "Padding" to prevent member-specific command button from overlapping job indicator
|
||||||
new GUIFrame(new RectTransform(new Vector2(paddingRelativeWidth, 1.0f), layoutGroup.RectTransform), style: null);
|
new GUIFrame(new RectTransform(new Vector2(paddingRelativeWidth, 1.0f), layoutGroup.RectTransform), style: null);
|
||||||
|
|
||||||
var jobIconBackground = new GUIImage(
|
var jobIconBackground = new GUIImage(
|
||||||
@@ -392,7 +390,16 @@ namespace Barotrauma
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
var nameRelativeWidth = 1.0f - paddingRelativeWidth - 3.7f * iconRelativeWidth;
|
var nameRelativeWidth = 1.0f
|
||||||
|
// Start padding
|
||||||
|
- paddingRelativeWidth
|
||||||
|
// 5 icons (job, 3 orders, sound)
|
||||||
|
- (5 * 0.8f * iconRelativeWidth)
|
||||||
|
// Vertical line
|
||||||
|
- (0.1f * iconRelativeWidth)
|
||||||
|
// Spacing
|
||||||
|
- (7 * layoutGroup.RelativeSpacing);
|
||||||
|
|
||||||
var font = layoutGroup.Rect.Width < 150 ? GUI.SmallFont : GUI.Font;
|
var font = layoutGroup.Rect.Width < 150 ? GUI.SmallFont : GUI.Font;
|
||||||
var nameBlock = new GUITextBlock(
|
var nameBlock = new GUITextBlock(
|
||||||
new RectTransform(
|
new RectTransform(
|
||||||
@@ -417,6 +424,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
UserData = character
|
UserData = character
|
||||||
};
|
};
|
||||||
|
|
||||||
// Only create a tooltip if the name doesn't fit the name block
|
// Only create a tooltip if the name doesn't fit the name block
|
||||||
if (nameBlock.Text.EndsWith("..."))
|
if (nameBlock.Text.EndsWith("..."))
|
||||||
{
|
{
|
||||||
@@ -432,6 +440,7 @@ namespace Barotrauma
|
|||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsSinglePlayer)
|
if (IsSinglePlayer)
|
||||||
{
|
{
|
||||||
characterButton.OnClicked = CharacterClicked;
|
characterButton.OnClicked = CharacterClicked;
|
||||||
@@ -443,7 +452,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
new GUIImage(
|
new GUIImage(
|
||||||
new RectTransform(new Vector2(0.5f * iconRelativeWidth, 0.5f), layoutGroup.RectTransform),
|
new RectTransform(new Vector2(0.1f * iconRelativeWidth, 0.5f), layoutGroup.RectTransform),
|
||||||
style: "VerticalLine")
|
style: "VerticalLine")
|
||||||
{
|
{
|
||||||
CanBeFocused = false
|
CanBeFocused = false
|
||||||
@@ -697,7 +706,7 @@ namespace Barotrauma
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Displays the specified order in the crew UI next to the character.
|
/// Displays the specified order in the crew UI next to the character.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void DisplayCharacterOrder(Character character, Order order, string option)
|
public void AddCurrentOrderIcon(Character character, Order order, string option)
|
||||||
{
|
{
|
||||||
if (character == null) { return; }
|
if (character == null) { return; }
|
||||||
|
|
||||||
@@ -706,34 +715,44 @@ namespace Barotrauma
|
|||||||
if (characterFrame == null) { return; }
|
if (characterFrame == null) { return; }
|
||||||
|
|
||||||
GUILayoutGroup layoutGroup = (GUILayoutGroup)characterFrame.FindChild(c => c is GUILayoutGroup);
|
GUILayoutGroup layoutGroup = (GUILayoutGroup)characterFrame.FindChild(c => c is GUILayoutGroup);
|
||||||
var currentOrderComponent = GetCurrentOrderComponent(layoutGroup);
|
|
||||||
|
|
||||||
if (order != null)
|
// Get the OrderInfo from the current order icon
|
||||||
|
var currentOrderIcon = GetCurrentOrderIcon(layoutGroup);
|
||||||
|
OrderInfo? currentOrderInfo = null;
|
||||||
|
if (currentOrderIcon?.UserData is OrderInfo)
|
||||||
{
|
{
|
||||||
var prevOrderComponent = GetPreviousOrderComponent(layoutGroup);
|
currentOrderInfo = (OrderInfo)currentOrderIcon.UserData;
|
||||||
if (currentOrderComponent?.UserData is OrderInfo currentOrderInfo)
|
// No need to recreate icons if the current order matches the new order
|
||||||
{
|
if (currentOrderInfo.Value.MatchesOrder(order, option)) { return; }
|
||||||
if (order.Identifier == currentOrderInfo.Order.Identifier &&
|
}
|
||||||
option == currentOrderInfo.OrderOption &&
|
|
||||||
order.TargetEntity == currentOrderInfo.Order.TargetEntity) { return; }
|
|
||||||
|
|
||||||
layoutGroup.RemoveChild(prevOrderComponent);
|
// Remove the current order icon
|
||||||
DisplayPreviousCharacterOrder(character, layoutGroup, currentOrderInfo);
|
layoutGroup.RemoveChild(currentOrderIcon);
|
||||||
}
|
|
||||||
else if (order.Identifier != dismissedOrderPrefab.Identifier &&
|
// Remove a previous order icon if it matches the new order
|
||||||
prevOrderComponent?.UserData is OrderInfo prevOrderInfo &&
|
// We don't want the same order as both a current order and a previous order
|
||||||
order.Identifier == prevOrderInfo.Order.Identifier &&
|
foreach (GUIComponent icon in GetPreviousOrderIcons(layoutGroup))
|
||||||
option == prevOrderInfo.OrderOption &&
|
{
|
||||||
order.TargetEntity == prevOrderInfo.Order.TargetEntity)
|
if (icon?.UserData is OrderInfo info && info.MatchesOrder(order, option))
|
||||||
{
|
{
|
||||||
layoutGroup.RemoveChild(prevOrderComponent);
|
layoutGroup.RemoveChild(icon);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
layoutGroup.RemoveChild(currentOrderComponent);
|
// Create a new previous order icon from the current order icon's OrderInfo
|
||||||
|
if (currentOrderInfo.HasValue)
|
||||||
|
{
|
||||||
|
AddPreviousOrderIcon(character, layoutGroup, currentOrderInfo.Value);
|
||||||
|
}
|
||||||
|
|
||||||
if (order == null || order.Identifier == dismissedOrderPrefab.Identifier) { return; }
|
if (order == null || order.Identifier == dismissedOrderPrefab.Identifier) { return; }
|
||||||
|
|
||||||
|
if (GetPreviousOrderIcons(layoutGroup).Count() >= MaxOrderIcons)
|
||||||
|
{
|
||||||
|
RemoveLastPreviousOrderIcon(layoutGroup);
|
||||||
|
}
|
||||||
|
|
||||||
var orderFrame = new GUIButton(
|
var orderFrame = new GUIButton(
|
||||||
new RectTransform(
|
new RectTransform(
|
||||||
layoutGroup.GetChildByUserData("job").RectTransform.RelativeSize,
|
layoutGroup.GetChildByUserData("job").RectTransform.RelativeSize,
|
||||||
@@ -748,25 +767,31 @@ namespace Barotrauma
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
CreateNodeIcon(orderFrame.RectTransform, order.SymbolSprite, order.Color, tooltip: order.Name);
|
CreateNodeIcon(orderFrame.RectTransform, order.SymbolSprite, order.Color, tooltip: order.Name);
|
||||||
new GUIImage(
|
|
||||||
new RectTransform(Vector2.One, orderFrame.RectTransform),
|
new GUIImage(new RectTransform(Vector2.One, orderFrame.RectTransform), cancelIcon, scaleToFit: true)
|
||||||
cancelIcon,
|
|
||||||
scaleToFit: true)
|
|
||||||
{
|
{
|
||||||
CanBeFocused = false,
|
CanBeFocused = false,
|
||||||
UserData = "cancel",
|
UserData = "cancel",
|
||||||
Visible = false
|
Visible = false
|
||||||
};
|
};
|
||||||
|
|
||||||
orderFrame.RectTransform.RepositionChildInHierarchy(4);
|
orderFrame.RectTransform.RepositionChildInHierarchy(4);
|
||||||
characterFrame.SetAsFirstChild();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DisplayPreviousCharacterOrder(Character character, GUILayoutGroup characterComponent, OrderInfo orderInfo)
|
private void AddPreviousOrderIcon(Character character, GUILayoutGroup characterComponent, OrderInfo orderInfo)
|
||||||
{
|
{
|
||||||
if (orderInfo.Order == null || orderInfo.Order.Identifier == dismissedOrderPrefab.Identifier) { return; }
|
if (orderInfo.Order == null || orderInfo.Order.Identifier == dismissedOrderPrefab.Identifier) { return; }
|
||||||
|
|
||||||
|
var maxPreviousOrderIcons = GetCurrentOrderIcon(characterComponent) != null ? MaxOrderIcons - 1 : MaxOrderIcons;
|
||||||
|
if (GetPreviousOrderIcons(characterComponent).Count() >= maxPreviousOrderIcons)
|
||||||
|
{
|
||||||
|
RemoveLastPreviousOrderIcon(characterComponent);
|
||||||
|
}
|
||||||
|
|
||||||
var previousOrderInfo = new OrderInfo(orderInfo);
|
var previousOrderInfo = new OrderInfo(orderInfo);
|
||||||
|
|
||||||
var prevOrderFrame = new GUIButton(
|
var prevOrderFrame = new GUIButton(
|
||||||
new RectTransform(
|
new RectTransform(
|
||||||
characterComponent.GetChildByUserData("job").RectTransform.RelativeSize,
|
characterComponent.GetChildByUserData("job").RectTransform.RelativeSize,
|
||||||
@@ -786,17 +811,20 @@ namespace Barotrauma
|
|||||||
var prevOrderIconFrame = new GUIFrame(
|
var prevOrderIconFrame = new GUIFrame(
|
||||||
new RectTransform(new Vector2(0.8f), prevOrderFrame.RectTransform, anchor: Anchor.BottomLeft),
|
new RectTransform(new Vector2(0.8f), prevOrderFrame.RectTransform, anchor: Anchor.BottomLeft),
|
||||||
style: null);
|
style: null);
|
||||||
|
|
||||||
CreateNodeIcon(
|
CreateNodeIcon(
|
||||||
prevOrderIconFrame.RectTransform,
|
prevOrderIconFrame.RectTransform,
|
||||||
previousOrderInfo.Order.SymbolSprite,
|
previousOrderInfo.Order.SymbolSprite,
|
||||||
previousOrderInfo.Order.Color,
|
previousOrderInfo.Order.Color,
|
||||||
tooltip: previousOrderInfo.Order.Name);
|
tooltip: previousOrderInfo.Order.Name);
|
||||||
|
|
||||||
foreach (GUIComponent c in prevOrderIconFrame.Children)
|
foreach (GUIComponent c in prevOrderIconFrame.Children)
|
||||||
{
|
{
|
||||||
c.HoverColor = c.Color;
|
c.HoverColor = c.Color;
|
||||||
c.PressedColor = c.Color;
|
c.PressedColor = c.Color;
|
||||||
c.SelectedColor = c.Color;
|
c.SelectedColor = c.Color;
|
||||||
}
|
}
|
||||||
|
|
||||||
new GUIImage(
|
new GUIImage(
|
||||||
new RectTransform(new Vector2(0.8f), prevOrderFrame.RectTransform, anchor: Anchor.TopRight),
|
new RectTransform(new Vector2(0.8f), prevOrderFrame.RectTransform, anchor: Anchor.TopRight),
|
||||||
previousOrderArrow,
|
previousOrderArrow,
|
||||||
@@ -804,19 +832,63 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
CanBeFocused = false
|
CanBeFocused = false
|
||||||
};
|
};
|
||||||
prevOrderFrame.RectTransform.RepositionChildInHierarchy(GetCurrentOrderComponent(characterComponent) != null ? 5 : 4);
|
|
||||||
|
var positionInHierarchy = GetCurrentOrderIcon(characterComponent) != null ? 5 : 4;
|
||||||
|
prevOrderFrame.RectTransform.RepositionChildInHierarchy(positionInHierarchy);
|
||||||
}
|
}
|
||||||
|
|
||||||
private GUIComponent GetCurrentOrderComponent(GUILayoutGroup characterComponent)
|
private void AddOldPreviousOrderIcons(Character character, GUILayoutGroup oldCharacterComponent)
|
||||||
{
|
{
|
||||||
return characterComponent?.FindChild(c => c?.UserData is OrderInfo orderInfo && orderInfo.ComponentIdentifier == "currentorder");
|
var prevOrderIcons = GetPreviousOrderIcons(oldCharacterComponent).ToList();
|
||||||
|
if (prevOrderIcons.None()) { return; }
|
||||||
|
if (prevOrderIcons.Count() > 1)
|
||||||
|
{
|
||||||
|
prevOrderIcons.Sort((x, y) => oldCharacterComponent.GetChildIndex(x).CompareTo(oldCharacterComponent.GetChildIndex(y)));
|
||||||
|
prevOrderIcons.Reverse();
|
||||||
|
}
|
||||||
|
if (crewList.Content.Children.FirstOrDefault(c => c?.UserData == character)?.GetChild<GUILayoutGroup>() is GUILayoutGroup newCharacterComponent)
|
||||||
|
{
|
||||||
|
foreach (GUIComponent icon in prevOrderIcons)
|
||||||
|
{
|
||||||
|
if (icon.UserData is OrderInfo orderInfo)
|
||||||
|
{
|
||||||
|
AddPreviousOrderIcon(character, newCharacterComponent, orderInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private GUIComponent GetPreviousOrderComponent(GUILayoutGroup characterComponent)
|
private void RemoveLastPreviousOrderIcon(GUILayoutGroup characterComponent)
|
||||||
{
|
{
|
||||||
return characterComponent?.FindChild(c => c?.UserData is OrderInfo orderInfo && orderInfo.ComponentIdentifier == "previousorder");
|
var prevOrderIcons = GetPreviousOrderIcons(characterComponent);
|
||||||
|
if (prevOrderIcons.None()) { return; }
|
||||||
|
if (prevOrderIcons.Count() == 1)
|
||||||
|
{
|
||||||
|
characterComponent.RemoveChild(prevOrderIcons.First());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int highestIndex = 0;
|
||||||
|
GUIComponent oldestPreviousOrderIcon = null;
|
||||||
|
foreach (GUIComponent icon in prevOrderIcons)
|
||||||
|
{
|
||||||
|
int i = characterComponent.GetChildIndex(icon);
|
||||||
|
if (i > highestIndex || oldestPreviousOrderIcon == null)
|
||||||
|
{
|
||||||
|
highestIndex = i;
|
||||||
|
oldestPreviousOrderIcon = icon;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
characterComponent.RemoveChild(oldestPreviousOrderIcon);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private GUIComponent GetCurrentOrderIcon(GUILayoutGroup characterComponent) =>
|
||||||
|
characterComponent?.FindChild(c => c?.UserData is OrderInfo orderInfo && orderInfo.ComponentIdentifier == "currentorder");
|
||||||
|
|
||||||
|
private IEnumerable<GUIComponent> GetPreviousOrderIcons(GUILayoutGroup characterComponent) =>
|
||||||
|
characterComponent?.FindChildren(c => c?.UserData is OrderInfo orderInfo && orderInfo.ComponentIdentifier == "previousorder");
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Updating and drawing the UI
|
#region Updating and drawing the UI
|
||||||
@@ -854,7 +926,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (IsSinglePlayer || client == null || (GameMain.NetworkMember?.ConnectedClients?.All(match => match != client) ?? true)) { return; }
|
if (IsSinglePlayer || client == null || (GameMain.NetworkMember?.ConnectedClients?.All(match => match != client) ?? true)) { return; }
|
||||||
|
|
||||||
contextMenu = new GUIFrame(new RectTransform(new Vector2(0.1f, 0.12f), GUI.Canvas) { ScreenSpaceOffset = mousePos }, style: "GUIToolTip") { UserData = client };
|
contextMenu = new GUIFrame(new RectTransform(new Vector2(0.1f, 0.15f), GUI.Canvas) { ScreenSpaceOffset = mousePos }, style: "GUIToolTip") { UserData = client };
|
||||||
|
|
||||||
var nameLabel = new GUITextBlock(new RectTransform(new Vector2(1f, 0.2f), contextMenu.RectTransform), client.Name, font: GUI.SubHeadingFont)
|
var nameLabel = new GUITextBlock(new RectTransform(new Vector2(1f, 0.2f), contextMenu.RectTransform), client.Name, font: GUI.SubHeadingFont)
|
||||||
{
|
{
|
||||||
@@ -864,7 +936,9 @@ namespace Barotrauma
|
|||||||
|
|
||||||
var optionsList = new GUIListBox(new RectTransform(new Vector2(1f, 0.8f), contextMenu.RectTransform, Anchor.BottomLeft), style: null)
|
var optionsList = new GUIListBox(new RectTransform(new Vector2(1f, 0.8f), contextMenu.RectTransform, Anchor.BottomLeft), style: null)
|
||||||
{
|
{
|
||||||
Padding = new Vector4(4, 0, 4, 4)
|
Padding = new Vector4(4, 0, 4, 4),
|
||||||
|
AutoHideScrollBar = false,
|
||||||
|
ScrollBarVisible = false
|
||||||
};
|
};
|
||||||
|
|
||||||
bool hasSteam = client.SteamID > 0 && SteamManager.IsInitialized,
|
bool hasSteam = client.SteamID > 0 && SteamManager.IsInitialized,
|
||||||
@@ -886,6 +960,13 @@ namespace Barotrauma
|
|||||||
UserData = "steam"
|
UserData = "steam"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
new GUITextBlock(new RectTransform(Point.Zero, parent), TextManager.Get("moderationmenu.userdetails"), font: GUI.SmallFont)
|
||||||
|
{
|
||||||
|
Padding = new Vector4(4),
|
||||||
|
Enabled = true,
|
||||||
|
UserData = "user"
|
||||||
|
};
|
||||||
|
|
||||||
new GUITextBlock(new RectTransform(Point.Zero, parent), TextManager.Get("permissions"), font: GUI.SmallFont)
|
new GUITextBlock(new RectTransform(Point.Zero, parent), TextManager.Get("permissions"), font: GUI.SmallFont)
|
||||||
{
|
{
|
||||||
Padding = new Vector4(4),
|
Padding = new Vector4(4),
|
||||||
@@ -971,6 +1052,9 @@ namespace Barotrauma
|
|||||||
case "ban":
|
case "ban":
|
||||||
GameMain.Client?.CreateKickReasonPrompt(client.Name, true);
|
GameMain.Client?.CreateKickReasonPrompt(client.Name, true);
|
||||||
break;
|
break;
|
||||||
|
case "user":
|
||||||
|
GameMain.NetLobbyScreen?.SelectPlayer(client);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
contextMenu = null;
|
contextMenu = null;
|
||||||
return true;
|
return true;
|
||||||
@@ -983,7 +1067,11 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (client == null ) { return; }
|
if (client == null ) { return; }
|
||||||
|
|
||||||
subContextMenu = new GUIListBox(new RectTransform(new Vector2(0.1f, 0.1f), GUI.Canvas) { ScreenSpaceOffset = pos }, style: "GUIToolTip");
|
subContextMenu = new GUIListBox(new RectTransform(new Vector2(0.1f, 0.1f), GUI.Canvas) { ScreenSpaceOffset = pos }, style: "GUIToolTip")
|
||||||
|
{
|
||||||
|
AutoHideScrollBar = false,
|
||||||
|
ScrollBarVisible = false
|
||||||
|
};
|
||||||
|
|
||||||
foreach (var rank in PermissionPreset.List)
|
foreach (var rank in PermissionPreset.List)
|
||||||
{
|
{
|
||||||
@@ -1073,11 +1161,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (!(c.UserData is Character character) || character.IsDead || character.Removed) { continue; }
|
if (!(c.UserData is Character character) || character.IsDead || character.Removed) { continue; }
|
||||||
AddCharacter(character);
|
AddCharacter(character);
|
||||||
if (GetPreviousOrderComponent(c.GetChild<GUILayoutGroup>())?.UserData is OrderInfo prevInfo &&
|
AddOldPreviousOrderIcons(character, c.GetChild<GUILayoutGroup>());
|
||||||
crewList.Content.Children.FirstOrDefault(c => c?.UserData == character)?.GetChild<GUILayoutGroup>() is GUILayoutGroup newLayoutGroup)
|
|
||||||
{
|
|
||||||
DisplayPreviousCharacterOrder(character, newLayoutGroup, prevInfo);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1112,9 +1196,10 @@ namespace Barotrauma
|
|||||||
if (!AllowCharacterSwitch) { return; }
|
if (!AllowCharacterSwitch) { return; }
|
||||||
//make the previously selected character wait in place for some time
|
//make the previously selected character wait in place for some time
|
||||||
//(so they don't immediately start idling and walking away from their station)
|
//(so they don't immediately start idling and walking away from their station)
|
||||||
if (Character.Controlled?.AIController?.ObjectiveManager != null)
|
var aiController = Character.Controlled?.AIController;
|
||||||
|
if (aiController != null)
|
||||||
{
|
{
|
||||||
Character.Controlled.AIController.ObjectiveManager.WaitTimer = CharacterWaitOnSwitch;
|
aiController.Reset();
|
||||||
}
|
}
|
||||||
DisableCommandUI();
|
DisableCommandUI();
|
||||||
Character.Controlled = character;
|
Character.Controlled = character;
|
||||||
@@ -1419,7 +1504,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
if (child.FindChild(c => c is GUILayoutGroup) is GUILayoutGroup layoutGroup)
|
if (child.FindChild(c => c is GUILayoutGroup) is GUILayoutGroup layoutGroup)
|
||||||
{
|
{
|
||||||
if (GetCurrentOrderComponent(layoutGroup) is GUIComponent orderButton &&
|
if (GetCurrentOrderIcon(layoutGroup) is GUIComponent orderButton &&
|
||||||
orderButton.GetChildByUserData("colorsource") is GUIComponent orderIcon &&
|
orderButton.GetChildByUserData("colorsource") is GUIComponent orderIcon &&
|
||||||
orderButton.GetChildByUserData("cancel") is GUIComponent cancelIcon)
|
orderButton.GetChildByUserData("cancel") is GUIComponent cancelIcon)
|
||||||
{
|
{
|
||||||
@@ -1504,8 +1589,8 @@ namespace Barotrauma
|
|||||||
private Hull hullContext;
|
private Hull hullContext;
|
||||||
private bool isContextual;
|
private bool isContextual;
|
||||||
private readonly List<Order> contextualOrders = new List<Order>();
|
private readonly List<Order> contextualOrders = new List<Order>();
|
||||||
private Point shorcutCenterNodeOffset;
|
private Point shortcutCenterNodeOffset;
|
||||||
private const int maxShorcutNodeCount = 4;
|
private const int maxShortcutNodeCount = 4;
|
||||||
|
|
||||||
private bool WasCommandInterfaceDisabledThisUpdate { get; set; }
|
private bool WasCommandInterfaceDisabledThisUpdate { get; set; }
|
||||||
private bool CanIssueOrders
|
private bool CanIssueOrders
|
||||||
@@ -1688,7 +1773,7 @@ namespace Barotrauma
|
|||||||
returnNodeMargin = returnNodeSize.X * 0.5f;
|
returnNodeMargin = returnNodeSize.X * 0.5f;
|
||||||
|
|
||||||
nodeDistance = (int)(150 * GUI.Scale);
|
nodeDistance = (int)(150 * GUI.Scale);
|
||||||
shorcutCenterNodeOffset = new Point(0, (int)(1.25f * nodeDistance));
|
shortcutCenterNodeOffset = new Point(0, (int)(1.25f * nodeDistance));
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<OrderCategory> GetAvailableCategories()
|
private List<OrderCategory> GetAvailableCategories()
|
||||||
@@ -1972,7 +2057,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
shortcutNodes.Clear();
|
shortcutNodes.Clear();
|
||||||
|
|
||||||
if (shortcutNodes.Count < maxShorcutNodeCount && sub.GetItems(false).Find(i => i.HasTag("reactor") && !i.NonInteractable)?.GetComponent<Reactor>() is Reactor reactor)
|
if (shortcutNodes.Count < maxShortcutNodeCount && sub.GetItems(false).Find(i => i.HasTag("reactor") && !i.NonInteractable)?.GetComponent<Reactor>() is Reactor reactor)
|
||||||
{
|
{
|
||||||
var reactorOutput = -reactor.CurrPowerConsumption;
|
var reactorOutput = -reactor.CurrPowerConsumption;
|
||||||
// If player is not an engineer AND the reactor is not powered up AND nobody is using the reactor
|
// If player is not an engineer AND the reactor is not powered up AND nobody is using the reactor
|
||||||
@@ -1990,7 +2075,7 @@ namespace Barotrauma
|
|||||||
// TODO: Reconsider the conditions as bot captain can have the nav term selected without operating it
|
// TODO: Reconsider the conditions as bot captain can have the nav term selected without operating it
|
||||||
// If player is not a captain AND nobody is using the nav terminal AND the nav terminal is powered up
|
// If player is not a captain AND nobody is using the nav terminal AND the nav terminal is powered up
|
||||||
// --> Create shortcut node for Steer order
|
// --> Create shortcut node for Steer order
|
||||||
if (shortcutNodes.Count < maxShorcutNodeCount && (Character.Controlled == null || Character.Controlled.Info?.Job?.Prefab != JobPrefab.Get("captain")) &&
|
if (shortcutNodes.Count < maxShortcutNodeCount && (Character.Controlled == null || Character.Controlled.Info?.Job?.Prefab != JobPrefab.Get("captain")) &&
|
||||||
sub.GetItems(false).Find(i => i.HasTag("navterminal") && !i.NonInteractable) is Item nav && characters.None(c => c.SelectedConstruction == nav) &&
|
sub.GetItems(false).Find(i => i.HasTag("navterminal") && !i.NonInteractable) is Item nav && characters.None(c => c.SelectedConstruction == nav) &&
|
||||||
nav.GetComponent<Steering>() is Steering steering && steering.Voltage > steering.MinVoltage)
|
nav.GetComponent<Steering>() is Steering steering && steering.Voltage > steering.MinVoltage)
|
||||||
{
|
{
|
||||||
@@ -2000,7 +2085,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
// If player is not a security officer AND invaders are reported
|
// If player is not a security officer AND invaders are reported
|
||||||
// --> Create shorcut node for Fight Intruders order
|
// --> Create shorcut node for Fight Intruders order
|
||||||
if (shortcutNodes.Count < maxShorcutNodeCount && (Character.Controlled == null || Character.Controlled.Info?.Job?.Prefab != JobPrefab.Get("securityofficer")) &&
|
if (shortcutNodes.Count < maxShortcutNodeCount && (Character.Controlled == null || Character.Controlled.Info?.Job?.Prefab != JobPrefab.Get("securityofficer")) &&
|
||||||
(Order.GetPrefab("reportintruders") is Order reportIntruders && ActiveOrders.Any(o => o.First.Prefab == reportIntruders)))
|
(Order.GetPrefab("reportintruders") is Order reportIntruders && ActiveOrders.Any(o => o.First.Prefab == reportIntruders)))
|
||||||
{
|
{
|
||||||
shortcutNodes.Add(
|
shortcutNodes.Add(
|
||||||
@@ -2009,7 +2094,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
// If player is not a mechanic AND a breach has been reported
|
// If player is not a mechanic AND a breach has been reported
|
||||||
// --> Create shorcut node for Fix Leaks order
|
// --> Create shorcut node for Fix Leaks order
|
||||||
if (shortcutNodes.Count < maxShorcutNodeCount && (Character.Controlled == null || Character.Controlled.Info?.Job?.Prefab != JobPrefab.Get("mechanic")) &&
|
if (shortcutNodes.Count < maxShortcutNodeCount && (Character.Controlled == null || Character.Controlled.Info?.Job?.Prefab != JobPrefab.Get("mechanic")) &&
|
||||||
(Order.GetPrefab("reportbreach") is Order reportBreach && ActiveOrders.Any(o => o.First.Prefab == reportBreach)))
|
(Order.GetPrefab("reportbreach") is Order reportBreach && ActiveOrders.Any(o => o.First.Prefab == reportBreach)))
|
||||||
{
|
{
|
||||||
shortcutNodes.Add(
|
shortcutNodes.Add(
|
||||||
@@ -2018,7 +2103,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
// If player is not an engineer AND broken devices have been reported
|
// If player is not an engineer AND broken devices have been reported
|
||||||
// --> Create shortcut node for Repair Damaged Systems order
|
// --> Create shortcut node for Repair Damaged Systems order
|
||||||
if (shortcutNodes.Count < maxShorcutNodeCount && (Character.Controlled == null || Character.Controlled.Info?.Job?.Prefab != JobPrefab.Get("engineer")) &&
|
if (shortcutNodes.Count < maxShortcutNodeCount && (Character.Controlled == null || Character.Controlled.Info?.Job?.Prefab != JobPrefab.Get("engineer")) &&
|
||||||
(Order.GetPrefab("reportbrokendevices") is Order reportBrokenDevices && ActiveOrders.Any(o => o.First.Prefab == reportBrokenDevices)))
|
(Order.GetPrefab("reportbrokendevices") is Order reportBrokenDevices && ActiveOrders.Any(o => o.First.Prefab == reportBrokenDevices)))
|
||||||
{
|
{
|
||||||
shortcutNodes.Add(
|
shortcutNodes.Add(
|
||||||
@@ -2027,13 +2112,13 @@ namespace Barotrauma
|
|||||||
|
|
||||||
// If fire is reported
|
// If fire is reported
|
||||||
// --> Create shortcut node for Extinguish Fires order
|
// --> Create shortcut node for Extinguish Fires order
|
||||||
if (shortcutNodes.Count < maxShorcutNodeCount && ActiveOrders.Any(o=> o.First.Prefab == Order.GetPrefab("reportfire")))
|
if (shortcutNodes.Count < maxShortcutNodeCount && ActiveOrders.Any(o=> o.First.Prefab == Order.GetPrefab("reportfire")))
|
||||||
{
|
{
|
||||||
shortcutNodes.Add(
|
shortcutNodes.Add(
|
||||||
CreateOrderNode(shortcutNodeSize, null, Point.Zero, Order.GetPrefab("extinguishfires"), -1));
|
CreateOrderNode(shortcutNodeSize, null, Point.Zero, Order.GetPrefab("extinguishfires"), -1));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shortcutNodes.Count < maxShorcutNodeCount && characterContext?.Info?.Job?.Prefab?.AppropriateOrders != null)
|
if (shortcutNodes.Count < maxShortcutNodeCount && characterContext?.Info?.Job?.Prefab?.AppropriateOrders != null)
|
||||||
{
|
{
|
||||||
foreach (string orderIdentifier in characterContext.Info.Job.Prefab.AppropriateOrders)
|
foreach (string orderIdentifier in characterContext.Info.Job.Prefab.AppropriateOrders)
|
||||||
{
|
{
|
||||||
@@ -2046,7 +2131,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
shortcutNodes.Add(CreateOrderNode(shortcutNodeSize, null, Point.Zero, orderPrefab, -1));
|
shortcutNodes.Add(CreateOrderNode(shortcutNodeSize, null, Point.Zero, orderPrefab, -1));
|
||||||
}
|
}
|
||||||
if (shortcutNodes.Count >= maxShorcutNodeCount) { break; }
|
if (shortcutNodes.Count >= maxShortcutNodeCount) { break; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2063,7 +2148,7 @@ namespace Barotrauma
|
|||||||
c.PressedColor = c.Color;
|
c.PressedColor = c.Color;
|
||||||
c.SelectedColor = c.Color;
|
c.SelectedColor = c.Color;
|
||||||
}
|
}
|
||||||
shortcutCenterNode.RectTransform.MoveOverTime(shorcutCenterNodeOffset, CommandNodeAnimDuration);
|
shortcutCenterNode.RectTransform.MoveOverTime(shortcutCenterNodeOffset, CommandNodeAnimDuration);
|
||||||
|
|
||||||
var nodeCountForCalculations = shortcutNodes.Count * 2 + 2;
|
var nodeCountForCalculations = shortcutNodes.Count * 2 + 2;
|
||||||
var offsets = MathUtils.GetPointsOnCircumference(Vector2.Zero, 0.75f * nodeDistance, nodeCountForCalculations);
|
var offsets = MathUtils.GetPointsOnCircumference(Vector2.Zero, 0.75f * nodeDistance, nodeCountForCalculations);
|
||||||
@@ -2071,7 +2156,7 @@ namespace Barotrauma
|
|||||||
for (int i = 0; i < shortcutNodes.Count; i++)
|
for (int i = 0; i < shortcutNodes.Count; i++)
|
||||||
{
|
{
|
||||||
shortcutNodes[i].RectTransform.Parent = commandFrame.RectTransform;
|
shortcutNodes[i].RectTransform.Parent = commandFrame.RectTransform;
|
||||||
shortcutNodes[i].RectTransform.MoveOverTime(shorcutCenterNodeOffset + offsets[firstOffsetIndex - i].ToPoint(), CommandNodeAnimDuration);
|
shortcutNodes[i].RectTransform.MoveOverTime(shortcutCenterNodeOffset + offsets[firstOffsetIndex - i].ToPoint(), CommandNodeAnimDuration);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2100,6 +2185,8 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (contextualOrders.None())
|
if (contextualOrders.None())
|
||||||
{
|
{
|
||||||
|
string orderIdentifier;
|
||||||
|
|
||||||
// Check if targeting an item or a hull
|
// Check if targeting an item or a hull
|
||||||
if (itemContext != null && !itemContext.NonInteractable)
|
if (itemContext != null && !itemContext.NonInteractable)
|
||||||
{
|
{
|
||||||
@@ -2114,7 +2201,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If targeting a periscope connected to a turret, show the 'operateweapons' order
|
// If targeting a periscope connected to a turret, show the 'operateweapons' order
|
||||||
var orderIdentifier = "operateweapons";
|
orderIdentifier = "operateweapons";
|
||||||
var operateWeaponsPrefab = Order.GetPrefab(orderIdentifier);
|
var operateWeaponsPrefab = Order.GetPrefab(orderIdentifier);
|
||||||
if (contextualOrders.None(o => o.Identifier.Equals(orderIdentifier)) && itemContext.Components.Any(c => c is Controller))
|
if (contextualOrders.None(o => o.Identifier.Equals(orderIdentifier)) && itemContext.Components.Any(c => c is Controller))
|
||||||
{
|
{
|
||||||
@@ -2123,9 +2210,9 @@ namespace Barotrauma
|
|||||||
if (turret != null) { contextualOrders.Add(new Order(operateWeaponsPrefab, turret.Item, turret, Character.Controlled)); }
|
if (turret != null) { contextualOrders.Add(new Order(operateWeaponsPrefab, turret.Item, turret, Character.Controlled)); }
|
||||||
}
|
}
|
||||||
|
|
||||||
// If targeting a repairable item, show the 'repairsystems' order
|
// If targeting a repairable item with condition below the repair threshold, show the 'repairsystems' order
|
||||||
orderIdentifier = "repairsystems";
|
orderIdentifier = "repairsystems";
|
||||||
if (contextualOrders.None(o => o.Identifier.Equals(orderIdentifier)) && itemContext.Repairables.Any())
|
if (contextualOrders.None(o => o.Identifier.Equals(orderIdentifier)) && itemContext.Repairables.Any(r => itemContext.ConditionPercentage < r.RepairThreshold))
|
||||||
{
|
{
|
||||||
contextualOrders.Add(new Order(Order.GetPrefab(orderIdentifier), itemContext, null, Character.Controlled));
|
contextualOrders.Add(new Order(Order.GetPrefab(orderIdentifier), itemContext, null, Character.Controlled));
|
||||||
if (itemContext.Repairables.Any(r => r != null && r.requiredSkills.Any(s => s != null && s.Identifier.Equals("electrical"))))
|
if (itemContext.Repairables.Any(r => r != null && r.requiredSkills.Any(s => s != null && s.Identifier.Equals("electrical"))))
|
||||||
@@ -2138,13 +2225,6 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Always show the 'wait' order if there are other crew members alive
|
|
||||||
orderIdentifier = "wait";
|
|
||||||
if (contextualOrders.None(o => o.Identifier.Equals(orderIdentifier)) && characters.Any(c => c != Character.Controlled))
|
|
||||||
{
|
|
||||||
contextualOrders.Add(new Order(Order.GetPrefab(orderIdentifier), itemContext, null, Character.Controlled));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove the 'pumpwater' order if the target pump is auto-controlled (as it will immediately overwrite the work done by the bot)
|
// Remove the 'pumpwater' order if the target pump is auto-controlled (as it will immediately overwrite the work done by the bot)
|
||||||
orderIdentifier = "pumpwater";
|
orderIdentifier = "pumpwater";
|
||||||
if (contextualOrders.FirstOrDefault(o => o.Identifier.Equals(orderIdentifier)) is Order o &&
|
if (contextualOrders.FirstOrDefault(o => o.Identifier.Equals(orderIdentifier)) is Order o &&
|
||||||
@@ -2152,20 +2232,34 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (pump.IsAutoControlled) { contextualOrders.Remove(o); }
|
if (pump.IsAutoControlled) { contextualOrders.Remove(o); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (contextualOrders.None())
|
||||||
|
{
|
||||||
|
// If there are other crew members alive and there are no other contextual orders available, show the 'wait' order
|
||||||
|
orderIdentifier = "wait";
|
||||||
|
if (contextualOrders.None(o => o.Identifier.Equals(orderIdentifier)) && characters.Any(c => c != Character.Controlled))
|
||||||
|
{
|
||||||
|
contextualOrders.Add(new Order(Order.GetPrefab(orderIdentifier), itemContext, null, Character.Controlled));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if(hullContext != null)
|
else if(hullContext != null)
|
||||||
{
|
{
|
||||||
contextualOrders.Add(new Order(Order.GetPrefab("fixleaks"), hullContext, null, Character.Controlled));
|
contextualOrders.Add(new Order(Order.GetPrefab("fixleaks"), hullContext, null, Character.Controlled));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show the 'follow' and 'dismissed' orders if there are other crew members alive
|
|
||||||
if (characters.Any(c => c != Character.Controlled))
|
if (characters.Any(c => c != Character.Controlled))
|
||||||
{
|
{
|
||||||
var orderIdentifier = "follow";
|
// Show 'follow' order only when there are no orders of other categories available
|
||||||
if (contextualOrders.None(o => o.Identifier.Equals(orderIdentifier)))
|
if (contextualOrders.None(o => o.Category != OrderCategory.Movement))
|
||||||
{
|
{
|
||||||
contextualOrders.Add(Order.GetPrefab(orderIdentifier));
|
orderIdentifier = "follow";
|
||||||
|
if (contextualOrders.None(o => o.Identifier.Equals(orderIdentifier)))
|
||||||
|
{
|
||||||
|
contextualOrders.Add(Order.GetPrefab(orderIdentifier));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show 'dismissed' order only when there are crew members with active orders
|
// Show 'dismissed' order only when there are crew members with active orders
|
||||||
orderIdentifier = "dismissed";
|
orderIdentifier = "dismissed";
|
||||||
if (contextualOrders.None(o => o.Identifier.Equals(orderIdentifier)) &&
|
if (contextualOrders.None(o => o.Identifier.Equals(orderIdentifier)) &&
|
||||||
@@ -2192,7 +2286,7 @@ namespace Barotrauma
|
|||||||
if (Order.PrefabList.Any(o => item.HasTag(o.ItemIdentifiers))) { return true; }
|
if (Order.PrefabList.Any(o => item.HasTag(o.ItemIdentifiers))) { return true; }
|
||||||
if (Order.PrefabList.Any(o => o.ItemComponentType != null && item.Components.Any(c => c?.GetType() == o.ItemComponentType))) { return true; }
|
if (Order.PrefabList.Any(o => o.ItemComponentType != null && item.Components.Any(c => c?.GetType() == o.ItemComponentType))) { return true; }
|
||||||
|
|
||||||
if (item.Repairables.Any()) { return true; }
|
if (item.Repairables.Any(r => item.ConditionPercentage < r.RepairThreshold)) { return true; }
|
||||||
var operateWeaponsPrefab = Order.GetPrefab("operateweapons");
|
var operateWeaponsPrefab = Order.GetPrefab("operateweapons");
|
||||||
return item.Components.Any(c => c is Controller) &&
|
return item.Components.Any(c => c is Controller) &&
|
||||||
(item.GetConnectedComponents<Turret>().Any(c => operateWeaponsPrefab.ItemIdentifiers.Contains(c.Item.Prefab.Identifier)) ||
|
(item.GetConnectedComponents<Turret>().Any(c => operateWeaponsPrefab.ItemIdentifiers.Contains(c.Item.Prefab.Identifier)) ||
|
||||||
@@ -2209,8 +2303,30 @@ namespace Barotrauma
|
|||||||
|
|
||||||
node.RectTransform.MoveOverTime(offset, CommandNodeAnimDuration);
|
node.RectTransform.MoveOverTime(offset, CommandNodeAnimDuration);
|
||||||
|
|
||||||
if (checkIfOrderCanBeHeard && !disableNode) { disableNode = !CanSomeoneHearCharacter(); }
|
if (checkIfOrderCanBeHeard && !disableNode)
|
||||||
var mustSetOptionOrTarget = order.HasOptions || (order.MustSetTarget && itemContext == null);
|
{
|
||||||
|
disableNode = !CanSomeoneHearCharacter();
|
||||||
|
}
|
||||||
|
|
||||||
|
var mustSetOptionOrTarget = order.HasOptions;
|
||||||
|
Item orderTargetEntity = null;
|
||||||
|
|
||||||
|
// If the order doesn't have options, but must set a target,
|
||||||
|
// we have to check if there's only one possible target available
|
||||||
|
// so we know to directly target that with the order
|
||||||
|
if (!mustSetOptionOrTarget && order.MustSetTarget && itemContext == null)
|
||||||
|
{
|
||||||
|
var matchingItems = order.GetMatchingItems(GetTargetSubmarine(), true);
|
||||||
|
if (matchingItems.Count > 1)
|
||||||
|
{
|
||||||
|
mustSetOptionOrTarget = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
orderTargetEntity = matchingItems.FirstOrDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
node.OnClicked = (button, userData) =>
|
node.OnClicked = (button, userData) =>
|
||||||
{
|
{
|
||||||
if (disableNode || !CanIssueOrders) { return false; }
|
if (disableNode || !CanIssueOrders) { return false; }
|
||||||
@@ -2224,7 +2340,11 @@ namespace Barotrauma
|
|||||||
NavigateForward(button, userData);
|
NavigateForward(button, userData);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (orderTargetEntity != null)
|
||||||
|
{
|
||||||
|
o = new Order(o.Prefab, orderTargetEntity, orderTargetEntity.Components.FirstOrDefault(ic => ic.GetType() == order.ItemComponentType), orderGiver: order.OrderGiver);
|
||||||
|
}
|
||||||
SetCharacterOrder(characterContext ?? GetCharacterForQuickAssignment(o), o, null, Character.Controlled);
|
SetCharacterOrder(characterContext ?? GetCharacterForQuickAssignment(o), o, null, Character.Controlled);
|
||||||
DisableCommandUI();
|
DisableCommandUI();
|
||||||
}
|
}
|
||||||
@@ -2382,6 +2502,10 @@ namespace Barotrauma
|
|||||||
|
|
||||||
Sprite icon = null;
|
Sprite icon = null;
|
||||||
order.MinimapIcons?.TryGetValue(item.Prefab.Identifier, out icon);
|
order.MinimapIcons?.TryGetValue(item.Prefab.Identifier, out icon);
|
||||||
|
if (item.Prefab.MinimapIcon != null)
|
||||||
|
{
|
||||||
|
icon = item.Prefab.MinimapIcon;
|
||||||
|
}
|
||||||
var colorMultiplier = characters.Any(c => c.CurrentOrder != null &&
|
var colorMultiplier = characters.Any(c => c.CurrentOrder != null &&
|
||||||
c.CurrentOrder.Identifier == userData.Item1.Identifier &&
|
c.CurrentOrder.Identifier == userData.Item1.Identifier &&
|
||||||
c.CurrentOrder.TargetEntity == userData.Item1.TargetEntity) ? 0.5f : 1f;
|
c.CurrentOrder.TargetEntity == userData.Item1.TargetEntity) ? 0.5f : 1f;
|
||||||
@@ -2601,7 +2725,7 @@ namespace Barotrauma
|
|||||||
var availableNodePositions = 20;
|
var availableNodePositions = 20;
|
||||||
var offsets = MathUtils.GetPointsOnCircumference(Vector2.Zero, 2.7f * this.nodeDistance, availableNodePositions,
|
var offsets = MathUtils.GetPointsOnCircumference(Vector2.Zero, 2.7f * this.nodeDistance, availableNodePositions,
|
||||||
firstAngle: MathHelper.ToRadians(-90f - ((extraOptionCharacters.Count - 1) * 0.5f * (360f / availableNodePositions))));
|
firstAngle: MathHelper.ToRadians(-90f - ((extraOptionCharacters.Count - 1) * 0.5f * (360f / availableNodePositions))));
|
||||||
for (int i = 0; i < extraOptionCharacters.Count; i++)
|
for (int i = 0; i < extraOptionCharacters.Count && i < availableNodePositions; i++)
|
||||||
{
|
{
|
||||||
CreateAssignmentNode(userData as Tuple<Order, string>, extraOptionCharacters[i], offsets[i].ToPoint(), -1, nameLabelScale: 1.15f);
|
CreateAssignmentNode(userData as Tuple<Order, string>, extraOptionCharacters[i], offsets[i].ToPoint(), -1, nameLabelScale: 1.15f);
|
||||||
}
|
}
|
||||||
@@ -2786,7 +2910,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
bearing = GetBearing(
|
bearing = GetBearing(
|
||||||
centerNode.RectTransform.AnimTargetPos.ToVector2(),
|
centerNode.RectTransform.AnimTargetPos.ToVector2(),
|
||||||
shorcutCenterNodeOffset.ToVector2());
|
shortcutCenterNodeOffset.ToVector2());
|
||||||
}
|
}
|
||||||
return nodeCount % 2 > 0 ?
|
return nodeCount % 2 > 0 ?
|
||||||
MathHelper.ToRadians(bearing + 360.0f / nodeCount / 2) :
|
MathHelper.ToRadians(bearing + 360.0f / nodeCount / 2) :
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Barotrauma.Extensions;
|
using Barotrauma.Extensions;
|
||||||
|
using Barotrauma.Items.Components;
|
||||||
using Barotrauma.Networking;
|
using Barotrauma.Networking;
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
@@ -30,11 +31,6 @@ namespace Barotrauma
|
|||||||
protected set;
|
protected set;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Paused
|
|
||||||
{
|
|
||||||
get { return ForceMapUI || CoroutineManager.IsCoroutineRunning("LevelTransition"); }
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool showCampaignUI;
|
private bool showCampaignUI;
|
||||||
private bool wasChatBoxOpen;
|
private bool wasChatBoxOpen;
|
||||||
public bool ShowCampaignUI
|
public bool ShowCampaignUI
|
||||||
@@ -165,7 +161,6 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TransitionType.LeaveLocation:
|
case TransitionType.LeaveLocation:
|
||||||
// not sure why this can happen at an outpost but it apparently can in multiplayer
|
|
||||||
buttonText = TextManager.GetWithVariable("LeaveLocation", "[locationname]", Level.Loaded.StartLocation?.Name ?? "[ERROR]");
|
buttonText = TextManager.GetWithVariable("LeaveLocation", "[locationname]", Level.Loaded.StartLocation?.Name ?? "[ERROR]");
|
||||||
endRoundButton.Visible = !ForceMapUI && !ShowCampaignUI;
|
endRoundButton.Visible = !ForceMapUI && !ShowCampaignUI;
|
||||||
break;
|
break;
|
||||||
@@ -195,14 +190,26 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (endRoundButton.Visible)
|
if (endRoundButton.Visible)
|
||||||
{
|
{
|
||||||
|
if (!AllowedToEndRound()) { buttonText = TextManager.Get("map"); }
|
||||||
endRoundButton.Text = ToolBox.LimitString(buttonText, endRoundButton.Font, endRoundButton.Rect.Width - 5);
|
endRoundButton.Text = ToolBox.LimitString(buttonText, endRoundButton.Font, endRoundButton.Rect.Width - 5);
|
||||||
if (endRoundButton.Text != buttonText)
|
if (endRoundButton.Text != buttonText)
|
||||||
{
|
{
|
||||||
endRoundButton.ToolTip = buttonText;
|
endRoundButton.ToolTip = buttonText;
|
||||||
}
|
}
|
||||||
endRoundButton.Enabled = AllowedToEndRound();
|
if (Character.Controlled?.ViewTarget is Item item)
|
||||||
|
{
|
||||||
|
Turret turret = item.GetComponent<Turret>();
|
||||||
|
endRoundButton.RectTransform.ScreenSpaceOffset = turret == null ? Point.Zero : new Point(0, (int)(turret.UIElementHeight * 1.25f));
|
||||||
|
}
|
||||||
|
else if (Character.Controlled?.CharacterHealth?.SuicideButton?.Visible ?? false)
|
||||||
|
{
|
||||||
|
endRoundButton.RectTransform.ScreenSpaceOffset = new Point(0, Character.Controlled.CharacterHealth.SuicideButton.Rect.Height);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
endRoundButton.RectTransform.ScreenSpaceOffset = Point.Zero;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
endRoundButton.DrawManually(spriteBatch);
|
endRoundButton.DrawManually(spriteBatch);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -216,7 +223,14 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
await Task.Yield();
|
await Task.Yield();
|
||||||
Rand.ThreadId = System.Threading.Thread.CurrentThread.ManagedThreadId;
|
Rand.ThreadId = System.Threading.Thread.CurrentThread.ManagedThreadId;
|
||||||
GameMain.GameSession.StartRound(newLevel, mirrorLevel: mirror);
|
try
|
||||||
|
{
|
||||||
|
GameMain.GameSession.StartRound(newLevel, mirrorLevel: mirror);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
roundSummaryScreen.LoadException = e;
|
||||||
|
}
|
||||||
Rand.ThreadId = 0;
|
Rand.ThreadId = 0;
|
||||||
});
|
});
|
||||||
TaskPool.Add("AsyncCampaignStartRound", loadTask, (t) =>
|
TaskPool.Add("AsyncCampaignStartRound", loadTask, (t) =>
|
||||||
|
|||||||
+19
-3
@@ -3,7 +3,7 @@ using Barotrauma.Networking;
|
|||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using Barotrauma.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
|
|
||||||
@@ -13,6 +13,11 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
public bool SuppressStateSending = false;
|
public bool SuppressStateSending = false;
|
||||||
|
|
||||||
|
public override bool Paused
|
||||||
|
{
|
||||||
|
get { return ForceMapUI || CoroutineManager.IsCoroutineRunning("LevelTransition"); }
|
||||||
|
}
|
||||||
|
|
||||||
private UInt16 pendingSaveID = 1;
|
private UInt16 pendingSaveID = 1;
|
||||||
public UInt16 PendingSaveID
|
public UInt16 PendingSaveID
|
||||||
{
|
{
|
||||||
@@ -100,7 +105,7 @@ namespace Barotrauma
|
|||||||
};
|
};
|
||||||
|
|
||||||
int buttonHeight = (int)(GUI.Scale * 40);
|
int buttonHeight = (int)(GUI.Scale * 40);
|
||||||
int buttonWidth = GUI.IntScale(200);
|
int buttonWidth = GUI.IntScale(450);
|
||||||
|
|
||||||
endRoundButton = new GUIButton(HUDLayoutSettings.ToRectTransform(new Rectangle((GameMain.GraphicsWidth / 2) - (buttonWidth / 2), HUDLayoutSettings.ButtonAreaTop.Center.Y - (buttonHeight / 2), buttonWidth, buttonHeight), GUICanvas.Instance),
|
endRoundButton = new GUIButton(HUDLayoutSettings.ToRectTransform(new Rectangle((GameMain.GraphicsWidth / 2) - (buttonWidth / 2), HUDLayoutSettings.ButtonAreaTop.Center.Y - (buttonHeight / 2), buttonWidth, buttonHeight), GUICanvas.Instance),
|
||||||
TextManager.Get("EndRound"), textAlignment: Alignment.Center, style: "EndRoundButton")
|
TextManager.Get("EndRound"), textAlignment: Alignment.Center, style: "EndRoundButton")
|
||||||
@@ -209,6 +214,7 @@ namespace Barotrauma
|
|||||||
Character.Controlled = null;
|
Character.Controlled = null;
|
||||||
prevControlled.ClearInputs();
|
prevControlled.ClearInputs();
|
||||||
}
|
}
|
||||||
|
GameMain.GameScreen.Cam.Freeze = true;
|
||||||
overlayTextColor = Color.Lerp(Color.Transparent, Color.White, (timer - 1.0f) / fadeInDuration);
|
overlayTextColor = Color.Lerp(Color.Transparent, Color.White, (timer - 1.0f) / fadeInDuration);
|
||||||
timer = Math.Min(timer + CoroutineManager.DeltaTime, textDuration);
|
timer = Math.Min(timer + CoroutineManager.DeltaTime, textDuration);
|
||||||
yield return CoroutineStatus.Running;
|
yield return CoroutineStatus.Running;
|
||||||
@@ -357,7 +363,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
base.Update(deltaTime);
|
base.Update(deltaTime);
|
||||||
|
|
||||||
if (PlayerInput.RightButtonClicked() ||
|
if (PlayerInput.SecondaryMouseButtonClicked() ||
|
||||||
PlayerInput.KeyHit(Microsoft.Xna.Framework.Input.Keys.Escape))
|
PlayerInput.KeyHit(Microsoft.Xna.Framework.Input.Keys.Escape))
|
||||||
{
|
{
|
||||||
ShowCampaignUI = false;
|
ShowCampaignUI = false;
|
||||||
@@ -403,6 +409,14 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (CampaignUI == null) { InitCampaignUI(); }
|
if (CampaignUI == null) { InitCampaignUI(); }
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var transitionType = GetAvailableTransition(out _, out _);
|
||||||
|
if (transitionType == TransitionType.None && CampaignUI?.SelectedTab == InteractionType.Map)
|
||||||
|
{
|
||||||
|
ShowCampaignUI = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
public override void End(TransitionType transitionType = TransitionType.None)
|
public override void End(TransitionType transitionType = TransitionType.None)
|
||||||
{
|
{
|
||||||
@@ -528,6 +542,7 @@ namespace Barotrauma
|
|||||||
UInt16 currentLocIndex = msg.ReadUInt16();
|
UInt16 currentLocIndex = msg.ReadUInt16();
|
||||||
UInt16 selectedLocIndex = msg.ReadUInt16();
|
UInt16 selectedLocIndex = msg.ReadUInt16();
|
||||||
byte selectedMissionIndex = msg.ReadByte();
|
byte selectedMissionIndex = msg.ReadByte();
|
||||||
|
bool allowDebugTeleport = msg.ReadBoolean();
|
||||||
float? reputation = null;
|
float? reputation = null;
|
||||||
if (msg.ReadBoolean()) { reputation = msg.ReadSingle(); }
|
if (msg.ReadBoolean()) { reputation = msg.ReadSingle(); }
|
||||||
|
|
||||||
@@ -640,6 +655,7 @@ namespace Barotrauma
|
|||||||
campaign.Map.SetLocation(currentLocIndex == UInt16.MaxValue ? -1 : currentLocIndex);
|
campaign.Map.SetLocation(currentLocIndex == UInt16.MaxValue ? -1 : currentLocIndex);
|
||||||
campaign.Map.SelectLocation(selectedLocIndex == UInt16.MaxValue ? -1 : selectedLocIndex);
|
campaign.Map.SelectLocation(selectedLocIndex == UInt16.MaxValue ? -1 : selectedLocIndex);
|
||||||
campaign.Map.SelectMission(selectedMissionIndex);
|
campaign.Map.SelectMission(selectedMissionIndex);
|
||||||
|
campaign.Map.AllowDebugTeleport = allowDebugTeleport;
|
||||||
campaign.CargoManager.SetItemsInBuyCrate(buyCrateItems);
|
campaign.CargoManager.SetItemsInBuyCrate(buyCrateItems);
|
||||||
campaign.CargoManager.SetPurchasedItems(purchasedItems);
|
campaign.CargoManager.SetPurchasedItems(purchasedItems);
|
||||||
campaign.CargoManager.SetSoldItems(soldItems);
|
campaign.CargoManager.SetSoldItems(soldItems);
|
||||||
|
|||||||
+54
-10
@@ -11,6 +11,35 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
class SinglePlayerCampaign : CampaignMode
|
class SinglePlayerCampaign : CampaignMode
|
||||||
{
|
{
|
||||||
|
public override bool Paused
|
||||||
|
{
|
||||||
|
get { return ForceMapUI || CoroutineManager.IsCoroutineRunning("LevelTransition") || ShowCampaignUI && CampaignUI.SelectedTab == InteractionType.Map; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void UpdateWhilePaused(float deltaTime)
|
||||||
|
{
|
||||||
|
if (CoroutineManager.IsCoroutineRunning("LevelTransition") || CoroutineManager.IsCoroutineRunning("SubmarineTransition") || gameOver) { return; }
|
||||||
|
|
||||||
|
if (PlayerInput.RightButtonClicked() ||
|
||||||
|
PlayerInput.KeyHit(Microsoft.Xna.Framework.Input.Keys.Escape))
|
||||||
|
{
|
||||||
|
ShowCampaignUI = false;
|
||||||
|
if (GUIMessageBox.VisibleBox?.UserData is RoundSummary roundSummary &&
|
||||||
|
roundSummary.ContinueButton != null &&
|
||||||
|
roundSummary.ContinueButton.Visible)
|
||||||
|
{
|
||||||
|
GUIMessageBox.MessageBoxes.Remove(GUIMessageBox.VisibleBox);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CrewManager.ChatBox != null)
|
||||||
|
{
|
||||||
|
CrewManager.ChatBox.Update(deltaTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
CrewManager.UpdateReports();
|
||||||
|
}
|
||||||
|
|
||||||
private float endTimer;
|
private float endTimer;
|
||||||
|
|
||||||
private bool savedOnStart;
|
private bool savedOnStart;
|
||||||
@@ -124,7 +153,7 @@ namespace Barotrauma
|
|||||||
private void InitUI()
|
private void InitUI()
|
||||||
{
|
{
|
||||||
int buttonHeight = (int)(GUI.Scale * 40);
|
int buttonHeight = (int)(GUI.Scale * 40);
|
||||||
int buttonWidth = GUI.IntScale(200);
|
int buttonWidth = GUI.IntScale(450);
|
||||||
|
|
||||||
endRoundButton = new GUIButton(HUDLayoutSettings.ToRectTransform(new Rectangle((GameMain.GraphicsWidth / 2) - (buttonWidth / 2), HUDLayoutSettings.ButtonAreaTop.Center.Y - (buttonHeight / 2), buttonWidth, buttonHeight), GUICanvas.Instance),
|
endRoundButton = new GUIButton(HUDLayoutSettings.ToRectTransform(new Rectangle((GameMain.GraphicsWidth / 2) - (buttonWidth / 2), HUDLayoutSettings.ButtonAreaTop.Center.Y - (buttonHeight / 2), buttonWidth, buttonHeight), GUICanvas.Instance),
|
||||||
TextManager.Get("EndRound"), textAlignment: Alignment.Center, style: "EndRoundButton")
|
TextManager.Get("EndRound"), textAlignment: Alignment.Center, style: "EndRoundButton")
|
||||||
@@ -357,10 +386,11 @@ namespace Barotrauma
|
|||||||
break;
|
break;
|
||||||
case TransitionType.ProgressToNextLocation:
|
case TransitionType.ProgressToNextLocation:
|
||||||
Map.MoveToNextLocation();
|
Map.MoveToNextLocation();
|
||||||
Map.ProgressWorld();
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Map.ProgressWorld(transitionType, (float)(Timing.TotalTime - GameMain.GameSession.RoundStartTime));
|
||||||
|
|
||||||
var endTransition = new CameraTransition(Submarine.MainSub, GameMain.GameScreen.Cam, null,
|
var endTransition = new CameraTransition(Submarine.MainSub, GameMain.GameScreen.Cam, null,
|
||||||
transitionType == TransitionType.LeaveLocation ? Alignment.BottomCenter : Alignment.Center,
|
transitionType == TransitionType.LeaveLocation ? Alignment.BottomCenter : Alignment.Center,
|
||||||
fadeOut: false,
|
fadeOut: false,
|
||||||
@@ -383,6 +413,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
//--------------------------------------
|
//--------------------------------------
|
||||||
|
|
||||||
|
bool save = false;
|
||||||
|
|
||||||
if (success)
|
if (success)
|
||||||
{
|
{
|
||||||
if (leavingSub != Submarine.MainSub && !leavingSub.DockedTo.Contains(Submarine.MainSub))
|
if (leavingSub != Submarine.MainSub && !leavingSub.DockedTo.Contains(Submarine.MainSub))
|
||||||
@@ -398,21 +430,33 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
GameMain.GameSession.SubmarineInfo = new SubmarineInfo(GameMain.GameSession.Submarine);
|
GameMain.GameSession.SubmarineInfo = new SubmarineInfo(GameMain.GameSession.Submarine);
|
||||||
|
|
||||||
|
if (PendingSubmarineSwitch != null)
|
||||||
|
{
|
||||||
|
SubmarineInfo previousSub = GameMain.GameSession.SubmarineInfo;
|
||||||
|
GameMain.GameSession.SubmarineInfo = PendingSubmarineSwitch;
|
||||||
|
PendingSubmarineSwitch = null;
|
||||||
|
|
||||||
|
for (int i = 0; i < GameMain.GameSession.OwnedSubmarines.Count; i++)
|
||||||
|
{
|
||||||
|
if (GameMain.GameSession.OwnedSubmarines[i].Name == previousSub.Name)
|
||||||
|
{
|
||||||
|
GameMain.GameSession.OwnedSubmarines[i] = previousSub;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SaveUtil.SaveGame(GameMain.GameSession.SavePath);
|
SaveUtil.SaveGame(GameMain.GameSession.SavePath);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
PendingSubmarineSwitch = null;
|
||||||
EnableRoundSummaryGameOverState();
|
EnableRoundSummaryGameOverState();
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------
|
//--------------------------------------
|
||||||
|
|
||||||
if (PendingSubmarineSwitch != null)
|
|
||||||
{
|
|
||||||
GameMain.GameSession.SubmarineInfo = PendingSubmarineSwitch;
|
|
||||||
PendingSubmarineSwitch = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
SelectSummaryScreen(roundSummary, newLevel, mirror, () =>
|
SelectSummaryScreen(roundSummary, newLevel, mirror, () =>
|
||||||
{
|
{
|
||||||
GameMain.GameScreen.Select();
|
GameMain.GameScreen.Select();
|
||||||
@@ -473,7 +517,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
base.Update(deltaTime);
|
base.Update(deltaTime);
|
||||||
|
|
||||||
if (PlayerInput.RightButtonClicked() ||
|
if (PlayerInput.SecondaryMouseButtonClicked() ||
|
||||||
PlayerInput.KeyHit(Microsoft.Xna.Framework.Input.Keys.Escape))
|
PlayerInput.KeyHit(Microsoft.Xna.Framework.Input.Keys.Escape))
|
||||||
{
|
{
|
||||||
ShowCampaignUI = false;
|
ShowCampaignUI = false;
|
||||||
@@ -581,7 +625,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else if (transitionType == TransitionType.ProgressToNextEmptyLocation)
|
else if (transitionType == TransitionType.ProgressToNextEmptyLocation)
|
||||||
{
|
{
|
||||||
Map.SetLocation(Map.Locations.IndexOf(Level.Loaded.EndLocation));
|
Map.SetLocation(Map.Locations.IndexOf(Level.Loaded.EndLocation ?? Map.CurrentLocation));
|
||||||
}
|
}
|
||||||
|
|
||||||
var subsToLeaveBehind = GetSubsToLeaveBehind(leavingSub);
|
var subsToLeaveBehind = GetSubsToLeaveBehind(leavingSub);
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Barotrauma.Extensions;
|
||||||
|
using Barotrauma.Items.Components;
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
@@ -7,6 +11,17 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
public Action OnRoundEnd;
|
public Action OnRoundEnd;
|
||||||
|
|
||||||
|
public bool SpawnOutpost;
|
||||||
|
|
||||||
|
public OutpostGenerationParams OutpostParams;
|
||||||
|
public LocationType OutpostType;
|
||||||
|
|
||||||
|
public EventPrefab TriggeredEvent;
|
||||||
|
|
||||||
|
private List<Event> scriptedEvent;
|
||||||
|
|
||||||
|
private GUIButton createEventButton;
|
||||||
|
|
||||||
public TestGameMode(GameModePreset preset) : base(preset)
|
public TestGameMode(GameModePreset preset) : base(preset)
|
||||||
{
|
{
|
||||||
foreach (JobPrefab jobPrefab in JobPrefab.Prefabs)
|
foreach (JobPrefab jobPrefab in JobPrefab.Prefabs)
|
||||||
@@ -24,11 +39,96 @@ namespace Barotrauma
|
|||||||
base.Start();
|
base.Start();
|
||||||
|
|
||||||
CrewManager.InitSinglePlayerRound();
|
CrewManager.InitSinglePlayerRound();
|
||||||
|
|
||||||
|
if (SpawnOutpost)
|
||||||
|
{
|
||||||
|
GenerateOutpost(Submarine.MainSub);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TriggeredEvent != null)
|
||||||
|
{
|
||||||
|
scriptedEvent = new List<Event> { TriggeredEvent.CreateInstance() };
|
||||||
|
GameMain.GameSession.EventManager.PinnedEvent = scriptedEvent.Last();
|
||||||
|
|
||||||
|
createEventButton = new GUIButton(new RectTransform(new Point(128, 64), GUI.Canvas, Anchor.TopCenter) { ScreenSpaceOffset = new Point(0, 32) }, TextManager.Get("create"))
|
||||||
|
{
|
||||||
|
OnClicked = delegate
|
||||||
|
{
|
||||||
|
scriptedEvent.Add(TriggeredEvent.CreateInstance());
|
||||||
|
GameMain.GameSession.EventManager.PinnedEvent = scriptedEvent.Last();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void AddToGUIUpdateList()
|
||||||
|
{
|
||||||
|
base.AddToGUIUpdateList();
|
||||||
|
createEventButton?.AddToGUIUpdateList();
|
||||||
|
}
|
||||||
|
|
||||||
public override void End(CampaignMode.TransitionType transitionType = CampaignMode.TransitionType.None)
|
public override void End(CampaignMode.TransitionType transitionType = CampaignMode.TransitionType.None)
|
||||||
{
|
{
|
||||||
|
GameMain.GameSession.EventManager.PinnedEvent = null;
|
||||||
OnRoundEnd?.Invoke();
|
OnRoundEnd?.Invoke();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void Update(float deltaTime)
|
||||||
|
{
|
||||||
|
base.Update(deltaTime);
|
||||||
|
|
||||||
|
if (scriptedEvent != null)
|
||||||
|
{
|
||||||
|
foreach (Event sEvent in scriptedEvent.Where(sEvent => !sEvent.IsFinished))
|
||||||
|
{
|
||||||
|
sEvent.Update(deltaTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GenerateOutpost(Submarine submarine)
|
||||||
|
{
|
||||||
|
Submarine outpost = OutpostGenerator.Generate(OutpostParams ?? OutpostGenerationParams.Params.GetRandom(), OutpostType ?? LocationType.List.GetRandom());
|
||||||
|
outpost.SetPosition(Vector2.Zero);
|
||||||
|
|
||||||
|
float closestDistance = 0.0f;
|
||||||
|
DockingPort myPort = null, outPostPort = null;
|
||||||
|
foreach (DockingPort port in DockingPort.List)
|
||||||
|
{
|
||||||
|
if (port.IsHorizontal || port.Docked) { continue; }
|
||||||
|
if (port.Item.Submarine == outpost)
|
||||||
|
{
|
||||||
|
outPostPort = port;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (port.Item.Submarine != submarine) { continue; }
|
||||||
|
|
||||||
|
//the submarine port has to be at the top of the sub
|
||||||
|
if (port.Item.WorldPosition.Y < submarine.WorldPosition.Y) { continue; }
|
||||||
|
|
||||||
|
float dist = Vector2.DistanceSquared(port.Item.WorldPosition, outpost.WorldPosition);
|
||||||
|
if ((myPort == null || dist < closestDistance || port.MainDockingPort) && !(myPort?.MainDockingPort ?? false))
|
||||||
|
{
|
||||||
|
myPort = port;
|
||||||
|
closestDistance = dist;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (myPort != null && outPostPort != null)
|
||||||
|
{
|
||||||
|
Vector2 portDiff = myPort.Item.WorldPosition - submarine.WorldPosition;
|
||||||
|
Vector2 spawnPos = (outPostPort.Item.WorldPosition - portDiff) - Vector2.UnitY * outPostPort.DockedDistance;
|
||||||
|
|
||||||
|
submarine.SetPosition(spawnPos);
|
||||||
|
myPort.Dock(outPostPort);
|
||||||
|
myPort.Lock(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Character.Controlled != null)
|
||||||
|
{
|
||||||
|
Character.Controlled.TeleportTo(outpost.GetWaypoints(false).GetRandom(point => point.SpawnType == SpawnType.Human).WorldPosition);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-1
@@ -293,7 +293,9 @@ namespace Barotrauma.Tutorials
|
|||||||
|
|
||||||
// Room 4
|
// Room 4
|
||||||
do { yield return null; } while (!officer_somethingBigSensor.MotionDetected);
|
do { yield return null; } while (!officer_somethingBigSensor.MotionDetected);
|
||||||
TriggerTutorialSegment(3); // Arm railgun
|
GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Officer.Radio.SomethingBig"), ChatMessageType.Radio, null);
|
||||||
|
yield return new WaitForSeconds(2f, false);
|
||||||
|
TriggerTutorialSegment(3); // Arm coilgun
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
SetHighlight(officer_coilgunLoader.Item, officer_coilgunLoader.Inventory.Items[0] == null || officer_coilgunLoader.Inventory.Items[0].Condition == 0);
|
SetHighlight(officer_coilgunLoader.Item, officer_coilgunLoader.Inventory.Items[0] == null || officer_coilgunLoader.Inventory.Items[0].Condition == 0);
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
@@ -373,15 +374,6 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(gameSession.GameMode is CampaignMode))
|
|
||||||
{
|
|
||||||
var shadow = new GUIFrame(new RectTransform(new Point((int)(totalWidth * 1.2f), GameMain.GraphicsHeight * 2), background.RectTransform, Anchor.Center), style: "OuterGlow")
|
|
||||||
{
|
|
||||||
Color = Color.Black
|
|
||||||
};
|
|
||||||
shadow.RectTransform.SetAsFirstChild();
|
|
||||||
}
|
|
||||||
|
|
||||||
Frame = background;
|
Frame = background;
|
||||||
return background;
|
return background;
|
||||||
}
|
}
|
||||||
@@ -511,7 +503,7 @@ namespace Barotrauma
|
|||||||
Character character = characterInfo.Character;
|
Character character = characterInfo.Character;
|
||||||
if (character == null || character.IsDead)
|
if (character == null || character.IsDead)
|
||||||
{
|
{
|
||||||
if (characterInfo.IsNewHire)
|
if (character == null && characterInfo.IsNewHire)
|
||||||
{
|
{
|
||||||
statusText = TextManager.Get("CampaignCrew.NewHire");
|
statusText = TextManager.Get("CampaignCrew.NewHire");
|
||||||
statusColor = GUI.Style.Blue;
|
statusColor = GUI.Style.Blue;
|
||||||
@@ -616,21 +608,8 @@ namespace Barotrauma
|
|||||||
sliderHolder.RectTransform.MaxSize = new Point(int.MaxValue, GUI.IntScale(25.0f));
|
sliderHolder.RectTransform.MaxSize = new Point(int.MaxValue, GUI.IntScale(25.0f));
|
||||||
factionTextContent.Recalculate();
|
factionTextContent.Recalculate();
|
||||||
|
|
||||||
new GUICustomComponent(new RectTransform(new Vector2(0.8f, 1.0f), sliderHolder.RectTransform), onDraw: (sb, customComponent) =>
|
new GUICustomComponent(new RectTransform(new Vector2(0.8f, 1.0f), sliderHolder.RectTransform),
|
||||||
{
|
onDraw: (sb, customComponent) => DrawReputationBar(sb, customComponent.Rect, normalizedReputation));
|
||||||
GUI.DrawRectangle(sb, customComponent.Rect, GUI.Style.ColorInventoryBackground, isFilled: true);
|
|
||||||
if (normalizedReputation < 0.5f)
|
|
||||||
{
|
|
||||||
int barWidth = (int)((0.5f - normalizedReputation) * customComponent.Rect.Width);
|
|
||||||
GUI.DrawRectangle(sb, new Rectangle(customComponent.Rect.Center.X - barWidth, customComponent.Rect.Y, barWidth, customComponent.Rect.Height), GUI.Style.Red, isFilled: true);
|
|
||||||
}
|
|
||||||
else if (normalizedReputation > 0.5f)
|
|
||||||
{
|
|
||||||
int barWidth = (int)((normalizedReputation - 0.5f) * customComponent.Rect.Width);
|
|
||||||
GUI.DrawRectangle(sb, new Rectangle(customComponent.Rect.Center.X, customComponent.Rect.Y, barWidth, customComponent.Rect.Height), GUI.Style.Green, isFilled: true);
|
|
||||||
}
|
|
||||||
GUI.DrawLine(sb, new Vector2(customComponent.Rect.Center.X, customComponent.Rect.Y - 2), new Vector2(customComponent.Rect.Center.X, customComponent.Rect.Bottom + 2), factionDescription.TextColor, width: 1);
|
|
||||||
});
|
|
||||||
|
|
||||||
string reputationText = ((int)Math.Round(reputation)).ToString();
|
string reputationText = ((int)Math.Round(reputation)).ToString();
|
||||||
int reputationChange = (int)Math.Round( reputation - initialReputation);
|
int reputationChange = (int)Math.Round( reputation - initialReputation);
|
||||||
@@ -650,5 +629,21 @@ namespace Barotrauma
|
|||||||
textAlignment: Alignment.CenterLeft, font: GUI.SubHeadingFont);
|
textAlignment: Alignment.CenterLeft, font: GUI.SubHeadingFont);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void DrawReputationBar(SpriteBatch sb, Rectangle rect, float normalizedReputation)
|
||||||
|
{
|
||||||
|
GUI.DrawRectangle(sb, rect, GUI.Style.ColorInventoryBackground, isFilled: true);
|
||||||
|
if (normalizedReputation < 0.5f)
|
||||||
|
{
|
||||||
|
int barWidth = (int)((0.5f - normalizedReputation) * rect.Width);
|
||||||
|
GUI.DrawRectangle(sb, new Rectangle(rect.Center.X - barWidth, rect.Y, barWidth, rect.Height), GUI.Style.Red, isFilled: true);
|
||||||
|
}
|
||||||
|
else if (normalizedReputation > 0.5f)
|
||||||
|
{
|
||||||
|
int barWidth = (int)((normalizedReputation - 0.5f) * rect.Width);
|
||||||
|
GUI.DrawRectangle(sb, new Rectangle(rect.Center.X, rect.Y, barWidth, rect.Height), GUI.Style.Green, isFilled: true);
|
||||||
|
}
|
||||||
|
GUI.DrawLine(sb, new Vector2(rect.Center.X, rect.Y - 2), new Vector2(rect.Center.X, rect.Bottom + 2), GUI.Style.TextColor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,6 +65,10 @@ namespace Barotrauma
|
|||||||
keyMapping[(int)InputType.Voice] = new KeyOrMouse(Keys.V);
|
keyMapping[(int)InputType.Voice] = new KeyOrMouse(Keys.V);
|
||||||
keyMapping[(int)InputType.LocalVoice] = new KeyOrMouse(Keys.B);
|
keyMapping[(int)InputType.LocalVoice] = new KeyOrMouse(Keys.B);
|
||||||
keyMapping[(int)InputType.Command] = new KeyOrMouse(MouseButton.MiddleMouse);
|
keyMapping[(int)InputType.Command] = new KeyOrMouse(MouseButton.MiddleMouse);
|
||||||
|
#if DEBUG
|
||||||
|
keyMapping[(int)InputType.PreviousFireMode] = new KeyOrMouse(MouseButton.MouseWheelDown);
|
||||||
|
keyMapping[(int)InputType.NextFireMode] = new KeyOrMouse(MouseButton.MouseWheelUp);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (Language == "French")
|
if (Language == "French")
|
||||||
{
|
{
|
||||||
@@ -314,7 +318,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
var corePackageDropdown = new GUIDropDown(new RectTransform(new Vector2(1.0f, 0.05f), leftPanel.RectTransform))
|
var corePackageDropdown = new GUIDropDown(new RectTransform(new Vector2(1.0f, 0.05f), leftPanel.RectTransform))
|
||||||
{
|
{
|
||||||
ButtonEnabled = ContentPackage.List.Count(cp => cp.CorePackage) > 1
|
ButtonEnabled = ContentPackage.CorePackages.Count > 1
|
||||||
};
|
};
|
||||||
|
|
||||||
var filterContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), leftPanel.RectTransform), isHorizontal: true)
|
var filterContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), leftPanel.RectTransform), isHorizontal: true)
|
||||||
@@ -342,7 +346,7 @@ namespace Barotrauma
|
|||||||
ScrollBarVisible = true
|
ScrollBarVisible = true
|
||||||
};
|
};
|
||||||
|
|
||||||
foreach (ContentPackage contentPackage in ContentPackage.List.Where(cp => cp.CorePackage))
|
foreach (ContentPackage contentPackage in ContentPackage.CorePackages)
|
||||||
{
|
{
|
||||||
var frame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.2f), corePackageDropdown.ListBox.Content.RectTransform), style: "ListBoxElement")
|
var frame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.2f), corePackageDropdown.ListBox.Content.RectTransform), style: "ListBoxElement")
|
||||||
{
|
{
|
||||||
@@ -358,7 +362,7 @@ namespace Barotrauma
|
|||||||
TextManager.GetWithVariables(contentPackage.GameVersion <= new Version(0, 0, 0, 0) ? "IncompatibleContentPackageUnknownVersion" : "IncompatibleContentPackage",
|
TextManager.GetWithVariables(contentPackage.GameVersion <= new Version(0, 0, 0, 0) ? "IncompatibleContentPackageUnknownVersion" : "IncompatibleContentPackage",
|
||||||
new string[3] { "[packagename]", "[packageversion]", "[gameversion]" }, new string[3] { contentPackage.Name, contentPackage.GameVersion.ToString(), GameMain.Version.ToString() });
|
new string[3] { "[packagename]", "[packageversion]", "[gameversion]" }, new string[3] { contentPackage.Name, contentPackage.GameVersion.ToString(), GameMain.Version.ToString() });
|
||||||
}
|
}
|
||||||
else if (contentPackage.CorePackage && !contentPackage.ContainsRequiredCorePackageFiles(out List<ContentType> missingContentTypes))
|
else if (!contentPackage.ContainsRequiredCorePackageFiles(out List<ContentType> missingContentTypes))
|
||||||
{
|
{
|
||||||
frame.UserData = null;
|
frame.UserData = null;
|
||||||
text.TextColor = GUI.Style.Red * 0.6f;
|
text.TextColor = GUI.Style.Red * 0.6f;
|
||||||
@@ -374,7 +378,7 @@ namespace Barotrauma
|
|||||||
"\n" + string.Join("\n", contentPackage.ErrorMessages);
|
"\n" + string.Join("\n", contentPackage.ErrorMessages);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SelectedContentPackages.Contains(contentPackage))
|
if (contentPackage == CurrentCorePackage)
|
||||||
{
|
{
|
||||||
corePackageDropdown.Select(corePackageDropdown.ListBox.Content.GetChildIndex(frame));
|
corePackageDropdown.Select(corePackageDropdown.ListBox.Content.GetChildIndex(frame));
|
||||||
}
|
}
|
||||||
@@ -382,10 +386,7 @@ namespace Barotrauma
|
|||||||
corePackageDropdown.OnSelected = SelectCorePackage;
|
corePackageDropdown.OnSelected = SelectCorePackage;
|
||||||
corePackageDropdown.ListBox.CanBeFocused = CanHotswapPackages(true);
|
corePackageDropdown.ListBox.CanBeFocused = CanHotswapPackages(true);
|
||||||
|
|
||||||
foreach (ContentPackage contentPackage in ContentPackage.List
|
foreach (ContentPackage contentPackage in ContentPackage.RegularPackages)
|
||||||
.Where(cp => !cp.CorePackage)
|
|
||||||
.OrderBy(cp => !SelectedContentPackages.Contains(cp))
|
|
||||||
.ThenBy(cp => -SelectedContentPackages.IndexOf(cp)))
|
|
||||||
{
|
{
|
||||||
var frame = new GUIFrame(new RectTransform(new Vector2(1.0f, tickBoxScale.Y), contentPackageList.Content.RectTransform), style: "ListBoxElement")
|
var frame = new GUIFrame(new RectTransform(new Vector2(1.0f, tickBoxScale.Y), contentPackageList.Content.RectTransform), style: "ListBoxElement")
|
||||||
{
|
{
|
||||||
@@ -407,7 +408,7 @@ namespace Barotrauma
|
|||||||
style: "GUITickBox")
|
style: "GUITickBox")
|
||||||
{
|
{
|
||||||
UserData = contentPackage,
|
UserData = contentPackage,
|
||||||
Selected = SelectedContentPackages.Contains(contentPackage),
|
Selected = EnabledRegularPackages.Contains(contentPackage),
|
||||||
OnSelected = SelectContentPackage,
|
OnSelected = SelectContentPackage,
|
||||||
Enabled = CanHotswapPackages(false)
|
Enabled = CanHotswapPackages(false)
|
||||||
};
|
};
|
||||||
@@ -1595,10 +1596,10 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (userData is ContentPackage contentPackage)
|
if (userData is ContentPackage contentPackage)
|
||||||
{
|
{
|
||||||
if (!SelectedContentPackages.Contains(contentPackage)) { return; }
|
if (!EnabledRegularPackages.Contains(contentPackage)) { return; }
|
||||||
}
|
}
|
||||||
|
|
||||||
ReorderSelectedContentPackages(cp => -listBox.Content.GetChildIndex(listBox.Content.GetChildByUserData(cp)));
|
ContentPackage.SortContentPackages(cp => listBox.Content.GetChildIndex(listBox.Content.GetChildByUserData(cp)), true);
|
||||||
|
|
||||||
UnsavedSettings = true;
|
UnsavedSettings = true;
|
||||||
}
|
}
|
||||||
@@ -1609,18 +1610,13 @@ namespace Barotrauma
|
|||||||
|
|
||||||
var contentPackage = tickBox.UserData as ContentPackage;
|
var contentPackage = tickBox.UserData as ContentPackage;
|
||||||
|
|
||||||
ContentPackage.List = ContentPackage.List
|
|
||||||
.OrderByDescending(p => p.CorePackage)
|
|
||||||
.ThenBy(cp => -contentPackageList.Content.GetChildIndex(contentPackageList.Content.GetChildByUserData(cp)))
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
if (tickBox.Selected)
|
if (tickBox.Selected)
|
||||||
{
|
{
|
||||||
SelectContentPackage(contentPackage);
|
EnableRegularPackage(contentPackage);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DeselectContentPackage(contentPackage);
|
DisableRegularPackage(contentPackage);
|
||||||
}
|
}
|
||||||
|
|
||||||
UnsavedSettings = true;
|
UnsavedSettings = true;
|
||||||
|
|||||||
@@ -717,7 +717,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
slot.QuickUseButtonToolTip = quickUseAction == QuickUseAction.None ?
|
slot.QuickUseButtonToolTip = quickUseAction == QuickUseAction.None ?
|
||||||
"" : TextManager.GetWithVariable("QuickUseAction." + quickUseAction.ToString(), "[equippeditem]", character.SelectedItems.FirstOrDefault(i => i != null)?.Name);
|
"" : TextManager.GetWithVariable("QuickUseAction." + quickUseAction.ToString(), "[equippeditem]", character.SelectedItems.FirstOrDefault(i => i != null)?.Name);
|
||||||
if (PlayerInput.PrimaryMouseButtonDown()) slot.EquipButtonState = GUIComponent.ComponentState.Pressed;
|
if (PlayerInput.PrimaryMouseButtonDown()) { slot.EquipButtonState = GUIComponent.ComponentState.Pressed; }
|
||||||
if (PlayerInput.PrimaryMouseButtonClicked())
|
if (PlayerInput.PrimaryMouseButtonClicked())
|
||||||
{
|
{
|
||||||
QuickUseItem(item, allowEquip: true, allowInventorySwap: false, allowApplyTreatment: false);
|
QuickUseItem(item, allowEquip: true, allowInventorySwap: false, allowApplyTreatment: false);
|
||||||
@@ -937,28 +937,52 @@ namespace Barotrauma
|
|||||||
switch (quickUseAction)
|
switch (quickUseAction)
|
||||||
{
|
{
|
||||||
case QuickUseAction.Equip:
|
case QuickUseAction.Equip:
|
||||||
//attempt to put in a free slot first
|
if (string.IsNullOrEmpty(item.Prefab.EquipConfirmationText) || character != Character.Controlled)
|
||||||
for (int i = capacity - 1; i >= 0; i--)
|
|
||||||
{
|
{
|
||||||
if (Items[i] != null) { continue; }
|
Equip();
|
||||||
if (SlotTypes[i] == InvSlotType.Any || !item.AllowedSlots.Any(a => a.HasFlag(SlotTypes[i]))) { continue; }
|
}
|
||||||
success = TryPutItem(item, i, true, false, Character.Controlled, true);
|
else
|
||||||
if (success) { break; }
|
{
|
||||||
|
if (GUIMessageBox.MessageBoxes.Any(mb => mb.UserData as string == "equipconfirmation")) { return; }
|
||||||
|
var equipConfirmation = new GUIMessageBox(string.Empty, TextManager.Get(item.Prefab.EquipConfirmationText),
|
||||||
|
new string[] { TextManager.Get("yes"), TextManager.Get("no") })
|
||||||
|
{
|
||||||
|
UserData = "equipconfirmation"
|
||||||
|
};
|
||||||
|
equipConfirmation.Buttons[0].OnClicked = (btn, userdata) =>
|
||||||
|
{
|
||||||
|
Equip();
|
||||||
|
equipConfirmation.Close();
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
equipConfirmation.Buttons[1].OnClicked = equipConfirmation.Close;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!success)
|
void Equip()
|
||||||
{
|
{
|
||||||
|
//attempt to put in a free slot first
|
||||||
for (int i = capacity - 1; i >= 0; i--)
|
for (int i = capacity - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
|
if (Items[i] != null) { continue; }
|
||||||
if (SlotTypes[i] == InvSlotType.Any || !item.AllowedSlots.Any(a => a.HasFlag(SlotTypes[i]))) { continue; }
|
if (SlotTypes[i] == InvSlotType.Any || !item.AllowedSlots.Any(a => a.HasFlag(SlotTypes[i]))) { continue; }
|
||||||
// something else already equipped in a hand slot, attempt to unequip it so items aren't unnecessarily swapped to it
|
|
||||||
if (Items[i] != null && Items[i].AllowedSlots.Contains(InvSlotType.Any) && (SlotTypes[i] == InvSlotType.LeftHand || SlotTypes[i] == InvSlotType.RightHand))
|
|
||||||
{
|
|
||||||
TryPutItem(Items[i], Character.Controlled, new List<InvSlotType>() { InvSlotType.Any }, true);
|
|
||||||
}
|
|
||||||
success = TryPutItem(item, i, true, false, Character.Controlled, true);
|
success = TryPutItem(item, i, true, false, Character.Controlled, true);
|
||||||
if (success) { break; }
|
if (success) { break; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!success)
|
||||||
|
{
|
||||||
|
for (int i = capacity - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
if (SlotTypes[i] == InvSlotType.Any || !item.AllowedSlots.Any(a => a.HasFlag(SlotTypes[i]))) { continue; }
|
||||||
|
// something else already equipped in a hand slot, attempt to unequip it so items aren't unnecessarily swapped to it
|
||||||
|
if (Items[i] != null && Items[i].AllowedSlots.Contains(InvSlotType.Any) && (SlotTypes[i] == InvSlotType.LeftHand || SlotTypes[i] == InvSlotType.RightHand))
|
||||||
|
{
|
||||||
|
TryPutItem(Items[i], Character.Controlled, new List<InvSlotType>() { InvSlotType.Any }, true);
|
||||||
|
}
|
||||||
|
success = TryPutItem(item, i, true, false, Character.Controlled, true);
|
||||||
|
if (success) { break; }
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case QuickUseAction.Unequip:
|
case QuickUseAction.Unequip:
|
||||||
@@ -1046,8 +1070,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public void DrawOwn(SpriteBatch spriteBatch)
|
public void DrawOwn(SpriteBatch spriteBatch)
|
||||||
{
|
{
|
||||||
if (!AccessibleWhenAlive && !character.IsDead) return;
|
if (!AccessibleWhenAlive && !character.IsDead) { return; }
|
||||||
if (slots == null) CreateSlots();
|
if (slots == null) { CreateSlots(); }
|
||||||
if (GameMain.GraphicsWidth != screenResolution.X ||
|
if (GameMain.GraphicsWidth != screenResolution.X ||
|
||||||
GameMain.GraphicsHeight != screenResolution.Y ||
|
GameMain.GraphicsHeight != screenResolution.Y ||
|
||||||
prevUIScale != UIScale ||
|
prevUIScale != UIScale ||
|
||||||
@@ -1070,7 +1094,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
for (int i = 0; i < capacity; i++)
|
for (int i = 0; i < capacity; i++)
|
||||||
{
|
{
|
||||||
if (HideSlot(i)) continue;
|
if (HideSlot(i)) { continue; }
|
||||||
|
|
||||||
Rectangle interactRect = slots[i].InteractRect;
|
Rectangle interactRect = slots[i].InteractRect;
|
||||||
interactRect.Location += slots[i].DrawOffset.ToPoint();
|
interactRect.Location += slots[i].DrawOffset.ToPoint();
|
||||||
@@ -1086,9 +1110,13 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
InventorySlot highlightedQuickUseSlot = null;
|
InventorySlot highlightedQuickUseSlot = null;
|
||||||
|
Rectangle inventoryArea = Rectangle.Empty;
|
||||||
|
|
||||||
for (int i = 0; i < capacity; i++)
|
for (int i = 0; i < capacity; i++)
|
||||||
{
|
{
|
||||||
if (HideSlot(i)) continue;
|
if (HideSlot(i)) { continue; }
|
||||||
|
|
||||||
|
inventoryArea = inventoryArea == Rectangle.Empty ? slots[i].InteractRect : Rectangle.Union(inventoryArea, slots[i].InteractRect);
|
||||||
|
|
||||||
if (Items[i] == null ||
|
if (Items[i] == null ||
|
||||||
(draggingItem == Items[i] && !slots[i].InteractRect.Contains(PlayerInput.MousePosition)) ||
|
(draggingItem == Items[i] && !slots[i].InteractRect.Contains(PlayerInput.MousePosition)) ||
|
||||||
@@ -1102,7 +1130,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (draggingItem == Items[i] && !slots[i].IsHighlighted) continue;
|
if (draggingItem == Items[i] && !slots[i].IsHighlighted) { continue; }
|
||||||
|
|
||||||
//draw hand icons if the item is equipped in a hand slot
|
//draw hand icons if the item is equipped in a hand slot
|
||||||
if (IsInLimbSlot(Items[i], InvSlotType.LeftHand))
|
if (IsInLimbSlot(Items[i], InvSlotType.LeftHand))
|
||||||
@@ -1169,7 +1197,17 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (highlightedQuickUseSlot != null && !string.IsNullOrEmpty(highlightedQuickUseSlot.QuickUseButtonToolTip))
|
if (Locked)
|
||||||
|
{
|
||||||
|
GUI.DrawRectangle(spriteBatch, inventoryArea, new Color(30,30,30,100), isFilled: true);
|
||||||
|
var lockIcon = GUI.Style.GetComponentStyle("LockIcon")?.GetDefaultSprite();
|
||||||
|
lockIcon?.Draw(spriteBatch, inventoryArea.Center.ToVector2(), scale: Math.Min(inventoryArea.Height / lockIcon.size.Y * 0.7f, 1.0f));
|
||||||
|
if (inventoryArea.Contains(PlayerInput.MousePosition))
|
||||||
|
{
|
||||||
|
GUIComponent.DrawToolTip(spriteBatch, TextManager.Get("handcuffed"), new Rectangle(inventoryArea.Center - new Point(inventoryArea.Height / 2), new Point(inventoryArea.Height)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (highlightedQuickUseSlot != null && !string.IsNullOrEmpty(highlightedQuickUseSlot.QuickUseButtonToolTip))
|
||||||
{
|
{
|
||||||
GUIComponent.DrawToolTip(spriteBatch, highlightedQuickUseSlot.QuickUseButtonToolTip, highlightedQuickUseSlot.EquipButtonRect);
|
GUIComponent.DrawToolTip(spriteBatch, highlightedQuickUseSlot.QuickUseButtonToolTip, highlightedQuickUseSlot.EquipButtonRect);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,29 +68,52 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
if (Window.Height > 0 && Window.Width > 0)
|
if (Window.Height > 0 && Window.Width > 0)
|
||||||
{
|
{
|
||||||
rect.Height = -(int)(Window.Y * item.Scale);
|
if (IsHorizontal)
|
||||||
|
|
||||||
rect.Y += (int)(doorRect.Height * openState);
|
|
||||||
rect.Height = Math.Max(rect.Height - (rect.Y - doorRect.Y), 0);
|
|
||||||
rect.Y = Math.Min(doorRect.Y, rect.Y);
|
|
||||||
|
|
||||||
if (convexHull2 != null)
|
|
||||||
{
|
{
|
||||||
Rectangle rect2 = doorRect;
|
rect.Width = (int)(Window.X * item.Scale);
|
||||||
rect2.Y += (int)(Window.Y * item.Scale - Window.Height * item.Scale);
|
rect.X -= (int)(doorRect.Width * openState);
|
||||||
|
rect.Width = Math.Max(rect.Width - (doorRect.X - rect.X), 0);
|
||||||
rect2.Y += (int)(doorRect.Height * openState);
|
rect.X = Math.Max(doorRect.X, rect.X);
|
||||||
rect2.Y = Math.Min(doorRect.Y, rect2.Y);
|
if (convexHull2 != null)
|
||||||
rect2.Height = rect2.Y - (doorRect.Y - (int)(doorRect.Height * (1.0f - openState)));
|
|
||||||
|
|
||||||
if (rect2.Height == 0)
|
|
||||||
{
|
{
|
||||||
convexHull2.Enabled = false;
|
Rectangle rect2 = doorRect;
|
||||||
|
rect2.X += (int)(Window.Right * item.Scale);
|
||||||
|
rect2.X -= (int)(doorRect.Width * openState);
|
||||||
|
rect2.X = Math.Max(doorRect.X, rect2.X);
|
||||||
|
rect2.Width = doorRect.Right - (int)(doorRect.Width * openState) - rect2.X;
|
||||||
|
if (rect2.Width == 0)
|
||||||
|
{
|
||||||
|
convexHull2.Enabled = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
convexHull2.Enabled = true;
|
||||||
|
convexHull2.SetVertices(GetConvexHullCorners(rect2));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rect.Height = -(int)(Window.Y * item.Scale);
|
||||||
|
rect.Y += (int)(doorRect.Height * openState);
|
||||||
|
rect.Height = Math.Max(rect.Height - (rect.Y - doorRect.Y), 0);
|
||||||
|
rect.Y = Math.Min(doorRect.Y, rect.Y);
|
||||||
|
if (convexHull2 != null)
|
||||||
{
|
{
|
||||||
convexHull2.Enabled = true;
|
Rectangle rect2 = doorRect;
|
||||||
convexHull2.SetVertices(GetConvexHullCorners(rect2));
|
rect2.Y += (int)(Window.Y * item.Scale - Window.Height * item.Scale);
|
||||||
|
rect2.Y += (int)(doorRect.Height * openState);
|
||||||
|
rect2.Y = Math.Min(doorRect.Y, rect2.Y);
|
||||||
|
rect2.Height = rect2.Y - (doorRect.Y - (int)(doorRect.Height * (1.0f - openState)));
|
||||||
|
if (rect2.Height == 0)
|
||||||
|
{
|
||||||
|
convexHull2.Enabled = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
convexHull2.Enabled = true;
|
||||||
|
convexHull2.SetVertices(GetConvexHullCorners(rect2));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -251,8 +274,9 @@ namespace Barotrauma.Items.Components
|
|||||||
bool open = msg.ReadBoolean();
|
bool open = msg.ReadBoolean();
|
||||||
bool broken = msg.ReadBoolean();
|
bool broken = msg.ReadBoolean();
|
||||||
bool forcedOpen = msg.ReadBoolean();
|
bool forcedOpen = msg.ReadBoolean();
|
||||||
|
bool isStuck = msg.ReadBoolean();
|
||||||
SetState(open, isNetworkMessage: true, sendNetworkMessage: false, forcedOpen: forcedOpen);
|
SetState(open, isNetworkMessage: true, sendNetworkMessage: false, forcedOpen: forcedOpen);
|
||||||
Stuck = msg.ReadRangedSingle(0.0f, 100.0f, 8);
|
stuck = msg.ReadRangedSingle(0.0f, 100.0f, 8);
|
||||||
UInt16 lastUserID = msg.ReadUInt16();
|
UInt16 lastUserID = msg.ReadUInt16();
|
||||||
Character user = lastUserID == 0 ? null : Entity.FindEntityByID(lastUserID) as Character;
|
Character user = lastUserID == 0 ? null : Entity.FindEntityByID(lastUserID) as Character;
|
||||||
if (user != lastUser)
|
if (user != lastUser)
|
||||||
@@ -260,7 +284,7 @@ namespace Barotrauma.Items.Components
|
|||||||
lastUser = user;
|
lastUser = user;
|
||||||
toggleCooldownTimer = ToggleCoolDown;
|
toggleCooldownTimer = ToggleCoolDown;
|
||||||
}
|
}
|
||||||
|
this.isStuck = isStuck;
|
||||||
if (isStuck) { OpenState = 0.0f; }
|
if (isStuck) { OpenState = 0.0f; }
|
||||||
IsBroken = broken;
|
IsBroken = broken;
|
||||||
PredictedState = null;
|
PredictedState = null;
|
||||||
|
|||||||
@@ -0,0 +1,360 @@
|
|||||||
|
#nullable enable
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Xml.Linq;
|
||||||
|
using Barotrauma.Networking;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
|
||||||
|
namespace Barotrauma.Items.Components
|
||||||
|
{
|
||||||
|
internal partial class VineTile
|
||||||
|
{
|
||||||
|
public void Draw(SpriteBatch spriteBatch, Vector2 position, float depth, float leafDepth)
|
||||||
|
{
|
||||||
|
Vector2 pos = position + Position;
|
||||||
|
pos.Y = -pos.Y;
|
||||||
|
|
||||||
|
VineSprite vineSprite = Parent.VineSprites[Type];
|
||||||
|
Color color = Parent.Decayed ? Parent.DeadTint : Parent.VineTint;
|
||||||
|
|
||||||
|
float layer1 = depth + 0.01f, // flowers
|
||||||
|
layer2 = depth + 0.02f, // decay atlas
|
||||||
|
layer3 = depth + 0.03f; // branches and leaves
|
||||||
|
|
||||||
|
float scale = Parent.VineScale * VineStep;
|
||||||
|
|
||||||
|
if (Parent.VineAtlas != null)
|
||||||
|
{
|
||||||
|
spriteBatch.Draw(Parent.VineAtlas.Texture, pos + offset, vineSprite.SourceRect, color, 0f, vineSprite.AbsoluteOrigin, scale, SpriteEffects.None, layer3);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Parent.DecayAtlas != null)
|
||||||
|
{
|
||||||
|
spriteBatch.Draw(Parent.DecayAtlas.Texture, pos, vineSprite.SourceRect, HealthColor, 0f, vineSprite.AbsoluteOrigin, scale, SpriteEffects.None, layer2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FlowerConfig.Variant >= 0 && !Parent.Decayed)
|
||||||
|
{
|
||||||
|
Sprite flowerSprite = Parent.FlowerSprites[FlowerConfig.Variant];
|
||||||
|
flowerSprite.Draw(spriteBatch, pos, Parent.FlowerTint, flowerSprite.Origin, scale: Parent.BaseFlowerScale * FlowerConfig.Scale * FlowerStep, rotate: FlowerConfig.Rotation, depth: layer1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (LeafConfig.Variant >= 0)
|
||||||
|
{
|
||||||
|
Sprite leafSprite = Parent.LeafSprites[LeafConfig.Variant];
|
||||||
|
leafSprite.Draw(spriteBatch, pos, Parent.Decayed ? Parent.DeadTint : Parent.LeafTint, leafSprite.Origin, scale: Parent.BaseLeafScale * LeafConfig.Scale * FlowerStep, rotate: LeafConfig.Rotation, depth: layer3 + leafDepth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class VineSprite
|
||||||
|
{
|
||||||
|
[Serialize("0,0,0,0", false)]
|
||||||
|
public Rectangle SourceRect { get; private set; }
|
||||||
|
|
||||||
|
[Serialize("0.5,0.5", false)]
|
||||||
|
public Vector2 Origin { get; private set; }
|
||||||
|
|
||||||
|
public Vector2 AbsoluteOrigin;
|
||||||
|
|
||||||
|
public VineSprite(XElement element)
|
||||||
|
{
|
||||||
|
SerializableProperty.DeserializeProperties(this, element);
|
||||||
|
AbsoluteOrigin = new Vector2(SourceRect.Width * Origin.X, SourceRect.Height * Origin.Y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal partial class Growable
|
||||||
|
{
|
||||||
|
public readonly Dictionary<VineTileType, VineSprite> VineSprites = new Dictionary<VineTileType, VineSprite>();
|
||||||
|
public readonly List<Sprite> FlowerSprites = new List<Sprite>();
|
||||||
|
public readonly List<Sprite> LeafSprites = new List<Sprite>();
|
||||||
|
|
||||||
|
public Sprite? VineAtlas, DecayAtlas;
|
||||||
|
|
||||||
|
protected override void RemoveComponentSpecific()
|
||||||
|
{
|
||||||
|
VineAtlas?.Remove();
|
||||||
|
DecayAtlas?.Remove();
|
||||||
|
|
||||||
|
foreach (Sprite sprite in FlowerSprites)
|
||||||
|
{
|
||||||
|
sprite.Remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (Sprite sprite in LeafSprites)
|
||||||
|
{
|
||||||
|
sprite.Remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Draw(SpriteBatch spriteBatch, Planter planter, Vector2 offset, float depth)
|
||||||
|
{
|
||||||
|
const float zStep = 0.0001f;
|
||||||
|
float leafDepth = 0f;
|
||||||
|
|
||||||
|
foreach (VineTile vine in Vines)
|
||||||
|
{
|
||||||
|
leafDepth += zStep;
|
||||||
|
vine.Draw(spriteBatch, planter.Item.DrawPosition + offset, depth, leafDepth);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GameMain.DebugDraw)
|
||||||
|
{
|
||||||
|
foreach (Rectangle rect in FailedRectangles)
|
||||||
|
{
|
||||||
|
Rectangle wRect = rect;
|
||||||
|
wRect.Y = -wRect.Y;
|
||||||
|
wRect.Y -= wRect.Height;
|
||||||
|
GUI.DrawRectangle(spriteBatch, wRect, Color.Red);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
partial void LoadVines(XElement element)
|
||||||
|
{
|
||||||
|
string? vineAtlasPath = element.GetAttributeString("vineatlas", null);
|
||||||
|
string? decayAtlasPath = element.GetAttributeString("decayatlas", null);
|
||||||
|
|
||||||
|
if (vineAtlasPath != null)
|
||||||
|
{
|
||||||
|
VineAtlas = new Sprite(vineAtlasPath, Rectangle.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (decayAtlasPath != null)
|
||||||
|
{
|
||||||
|
DecayAtlas = new Sprite(decayAtlasPath, Rectangle.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (XElement subElement in element.Elements())
|
||||||
|
{
|
||||||
|
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||||
|
{
|
||||||
|
case "vinesprite":
|
||||||
|
var tileType = subElement.GetAttributeString("type", null);
|
||||||
|
VineTileType type = Enum.Parse<VineTileType>(tileType);
|
||||||
|
VineSprites.Add(type, new VineSprite(subElement));
|
||||||
|
break;
|
||||||
|
case "flowersprite":
|
||||||
|
FlowerSprites.Add(new Sprite(subElement));
|
||||||
|
break;
|
||||||
|
case "leafsprite":
|
||||||
|
LeafSprites.Add(new Sprite(subElement));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
flowerVariants = FlowerSprites.Count;
|
||||||
|
leafVariants = LeafSprites.Count;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (VineTileType type in Enum.GetValues(typeof(VineTileType)))
|
||||||
|
{
|
||||||
|
if (!VineSprites.ContainsKey(type))
|
||||||
|
{
|
||||||
|
DebugConsole.ThrowError($"Vine sprite missing from {item.prefab.Identifier}: {type}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly object mutex = new object();
|
||||||
|
|
||||||
|
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
||||||
|
{
|
||||||
|
Health = msg.ReadRangedSingle(0, MaxHealth, 8);
|
||||||
|
int startOffset = msg.ReadRangedInteger(-1, MaximumVines);
|
||||||
|
if (startOffset > -1)
|
||||||
|
{
|
||||||
|
int vineCount = msg.ReadRangedInteger(0, VineChunkSize);
|
||||||
|
List<VineTile> tiles = new List<VineTile>();
|
||||||
|
for (int i = 0; i < vineCount; i++)
|
||||||
|
{
|
||||||
|
VineTileType vineType = (VineTileType) msg.ReadRangedInteger(0b0000, 0b1111);
|
||||||
|
int flowerConfig = msg.ReadRangedInteger(0, 0xFFF);
|
||||||
|
int leafConfig = msg.ReadRangedInteger(0, 0xFFF);
|
||||||
|
sbyte posX = (sbyte) msg.ReadByte(), posY = (sbyte) msg.ReadByte();
|
||||||
|
Vector2 pos = new Vector2(posX * VineTile.Size, posY * VineTile.Size);
|
||||||
|
|
||||||
|
tiles.Add(new VineTile(this, pos, vineType, FoliageConfig.Deserialize(flowerConfig), FoliageConfig.Deserialize(leafConfig)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// is this even needed??
|
||||||
|
lock (mutex)
|
||||||
|
{
|
||||||
|
for (var i = 0; i < vineCount; i++)
|
||||||
|
{
|
||||||
|
int index = i + startOffset;
|
||||||
|
if (index >= Vines.Count)
|
||||||
|
{
|
||||||
|
Vines.Add(tiles[i]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
VineTile oldVine = Vines[index];
|
||||||
|
VineTile newVine = tiles[i];
|
||||||
|
newVine.GrowthStep = oldVine.GrowthStep;
|
||||||
|
Vines[index] = newVine;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateBranchHealth();
|
||||||
|
ResetPlanterSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ResetPlanterSize()
|
||||||
|
{
|
||||||
|
if (item.ParentInventory is ItemInventory itemInventory && itemInventory.Owner is Item parentItem)
|
||||||
|
{
|
||||||
|
if (parentItem.GetComponent<Planter>() is { } planter)
|
||||||
|
{
|
||||||
|
planter.Item.ResetCachedVisibleSize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
private int seed;
|
||||||
|
|
||||||
|
// Huge bowl of spaghetti
|
||||||
|
public void CreateDebugHUD(Planter planter, PlantSlot slot)
|
||||||
|
{
|
||||||
|
Vector2 relativeSize = new Vector2(0.3f, 0.6f);
|
||||||
|
GUIMessageBox msgBox = new GUIMessageBox(item.Name, "", new[] { TextManager.Get("applysettingsbutton") }, relativeSize);
|
||||||
|
|
||||||
|
GUILayoutGroup content = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.85f), msgBox.Content.RectTransform)) { Stretch = true };
|
||||||
|
GUINumberInput seedInput = CreateIntEntry("Random Seed", seed, content.RectTransform);
|
||||||
|
GUINumberInput vineTileSizeInput = CreateIntEntry("Vine Tile Size (Global)", VineTile.Size, content.RectTransform);
|
||||||
|
GUINumberInput[] leafScaleRangeInput = CreateMinMaxEntry("Leaf Scale Range (Global)", new []{ MinLeafScale, MaxLeafScale }, 1.5f, content.RectTransform);
|
||||||
|
GUINumberInput[] flowerScaleRangeInput = CreateMinMaxEntry("Flower Scale Range (Global)", new []{ MinFlowerScale, MaxFlowerScale }, 1.5f, content.RectTransform);
|
||||||
|
GUINumberInput vineCountInput = CreateIntEntry("Vine Count", MaximumVines, content.RectTransform);
|
||||||
|
GUINumberInput vineScaleInput = CreateFloatEntry("Vine Scale", VineScale, content.RectTransform);
|
||||||
|
GUINumberInput flowerInput = CreateIntEntry("Flower Quantity", FlowerQuantity, content.RectTransform);
|
||||||
|
GUINumberInput flowerScaleInput = CreateFloatEntry("Flower Scale", BaseFlowerScale, content.RectTransform);
|
||||||
|
GUINumberInput leafScaleInput = CreateFloatEntry("Leaf Scale", BaseLeafScale, content.RectTransform);
|
||||||
|
GUINumberInput leafProbabilityInput = CreateFloatEntry("Leaf Probability", LeafProbability, content.RectTransform);
|
||||||
|
GUINumberInput[] leafTintInputs = CreateMinMaxEntry("Leaf Tint", new []{ LeafTint.R / 255f, LeafTint.G / 255f, LeafTint.B / 255f }, 1.0f, content.RectTransform);
|
||||||
|
GUINumberInput[] flowerTintInputs = CreateMinMaxEntry("Flower Tint", new []{ FlowerTint.R / 255f, FlowerTint.G / 255f, FlowerTint.B / 255f }, 1.0f, content.RectTransform);
|
||||||
|
GUINumberInput[] vineTintInputs = CreateMinMaxEntry("Branch Tint", new []{ VineTint.R / 255f, VineTint.G / 255f, VineTint.B / 255f }, 1.0f, content.RectTransform);
|
||||||
|
|
||||||
|
// Apply
|
||||||
|
msgBox.Buttons[0].OnClicked = (button, o) =>
|
||||||
|
{
|
||||||
|
seed = seedInput.IntValue;
|
||||||
|
MaximumVines = vineCountInput.IntValue;
|
||||||
|
FlowerQuantity = flowerInput.IntValue;
|
||||||
|
BaseFlowerScale = flowerScaleInput.FloatValue;
|
||||||
|
VineScale = vineScaleInput.FloatValue;
|
||||||
|
BaseLeafScale = leafScaleInput.FloatValue;
|
||||||
|
LeafProbability = leafProbabilityInput.FloatValue;
|
||||||
|
VineTile.Size = vineTileSizeInput.IntValue;
|
||||||
|
|
||||||
|
MinFlowerScale = flowerScaleRangeInput[0].FloatValue;
|
||||||
|
MaxFlowerScale = flowerScaleRangeInput[1].FloatValue;
|
||||||
|
MinLeafScale = leafScaleRangeInput[0].FloatValue;
|
||||||
|
MaxLeafScale = leafScaleRangeInput[1].FloatValue;
|
||||||
|
|
||||||
|
LeafTint = new Color(leafTintInputs[0].FloatValue, leafTintInputs[1].FloatValue, leafTintInputs[2].FloatValue);
|
||||||
|
FlowerTint = new Color(flowerTintInputs[0].FloatValue, flowerTintInputs[1].FloatValue, flowerTintInputs[2].FloatValue);
|
||||||
|
VineTint = new Color(vineTintInputs[0].FloatValue, vineTintInputs[1].FloatValue, vineTintInputs[2].FloatValue);
|
||||||
|
|
||||||
|
if (FlowerQuantity >= MaximumVines - 1)
|
||||||
|
{
|
||||||
|
vineCountInput.Flash(Color.Red);
|
||||||
|
flowerInput.Flash(Color.Red);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MinFlowerScale > MaxFlowerScale)
|
||||||
|
{
|
||||||
|
foreach (GUINumberInput input in flowerScaleRangeInput)
|
||||||
|
{
|
||||||
|
input.Flash(Color.Red);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MinLeafScale > MaxLeafScale)
|
||||||
|
{
|
||||||
|
foreach (GUINumberInput input in leafScaleRangeInput)
|
||||||
|
{
|
||||||
|
input.Flash(Color.Red);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
msgBox.Close();
|
||||||
|
|
||||||
|
Random random = new Random(seed);
|
||||||
|
Random flowerRandom = new Random(seed);
|
||||||
|
Vines.Clear();
|
||||||
|
GenerateFlowerTiles(flowerRandom);
|
||||||
|
GenerateStem();
|
||||||
|
|
||||||
|
Decayed = false;
|
||||||
|
FullyGrown = false;
|
||||||
|
while (MaximumVines > Vines.Count)
|
||||||
|
{
|
||||||
|
if (!CanGrowMore())
|
||||||
|
{
|
||||||
|
Decayed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
TryGenerateBranches(planter, slot, random, flowerRandom);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Decayed)
|
||||||
|
{
|
||||||
|
FullyGrown = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (VineTile vineTile in Vines)
|
||||||
|
{
|
||||||
|
vineTile.GrowthStep = 2.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static GUINumberInput CreateIntEntry(string label, int defaultValue, RectTransform parent)
|
||||||
|
{
|
||||||
|
GUILayoutGroup layout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.08f), parent), isHorizontal: true);
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(0.5f, 1f), layout.RectTransform), label);
|
||||||
|
GUINumberInput input = new GUINumberInput(new RectTransform(new Vector2(0.5f, 1f), layout.RectTransform), GUINumberInput.NumberType.Int) { IntValue = defaultValue };
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static GUINumberInput CreateFloatEntry(string label, float defaultValue, RectTransform parent)
|
||||||
|
{
|
||||||
|
GUILayoutGroup layout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.08f), parent), isHorizontal: true);
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(0.5f, 1f), layout.RectTransform), label);
|
||||||
|
GUINumberInput input = new GUINumberInput(new RectTransform(new Vector2(0.5f, 1f), layout.RectTransform), GUINumberInput.NumberType.Float) { FloatValue = defaultValue, DecimalsToDisplay = 2 };
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static GUINumberInput[] CreateMinMaxEntry(string label, float[] values, float max, RectTransform parent, float min = 0f)
|
||||||
|
{
|
||||||
|
GUILayoutGroup layout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.08f), parent), isHorizontal: true);
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(0.5f, 1f), layout.RectTransform), label);
|
||||||
|
GUINumberInput[] inputs = new GUINumberInput[values.Length];
|
||||||
|
for (var i = 0; i < values.Length; i++)
|
||||||
|
{
|
||||||
|
float value = values[i];
|
||||||
|
GUINumberInput input = new GUINumberInput(new RectTransform(new Vector2(0.5f / values.Length, 1f), layout.RectTransform), GUINumberInput.NumberType.Float)
|
||||||
|
{
|
||||||
|
FloatValue = value, DecimalsToDisplay = 2,
|
||||||
|
MinValueFloat = min,
|
||||||
|
MaxValueFloat = max
|
||||||
|
};
|
||||||
|
inputs[i] = input;
|
||||||
|
}
|
||||||
|
|
||||||
|
return inputs;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -12,11 +12,11 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
partial class RangedWeapon : ItemComponent
|
partial class RangedWeapon : ItemComponent
|
||||||
{
|
{
|
||||||
private Sprite crosshairSprite, crosshairPointerSprite;
|
protected Sprite crosshairSprite, crosshairPointerSprite;
|
||||||
|
|
||||||
private Vector2 crosshairPos, crosshairPointerPos;
|
protected Vector2 crosshairPos, crosshairPointerPos;
|
||||||
|
|
||||||
private float currentCrossHairScale, currentCrossHairPointerScale;
|
protected float currentCrossHairScale, currentCrossHairPointerScale;
|
||||||
|
|
||||||
private readonly List<ParticleEmitter> particleEmitters = new List<ParticleEmitter>();
|
private readonly List<ParticleEmitter> particleEmitters = new List<ParticleEmitter>();
|
||||||
|
|
||||||
@@ -86,7 +86,6 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
|
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
|
||||||
{
|
{
|
||||||
if (crosshairSprite == null) { return; }
|
|
||||||
if (character == null || !character.IsKeyDown(InputType.Aim)) { return; }
|
if (character == null || !character.IsKeyDown(InputType.Aim)) { return; }
|
||||||
|
|
||||||
//camera focused on some other item/device, don't draw the crosshair
|
//camera focused on some other item/device, don't draw the crosshair
|
||||||
|
|||||||
@@ -0,0 +1,338 @@
|
|||||||
|
using Barotrauma.Networking;
|
||||||
|
using Barotrauma.Particles;
|
||||||
|
using FarseerPhysics;
|
||||||
|
using FarseerPhysics.Dynamics;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Xml.Linq;
|
||||||
|
|
||||||
|
namespace Barotrauma.Items.Components
|
||||||
|
{
|
||||||
|
|
||||||
|
partial class Sprayer : RangedWeapon, IDrawableComponent
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
private Vector2 debugRayStartPos, debugRayEndPos;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
public Vector2 DrawSize
|
||||||
|
{
|
||||||
|
get { return Vector2.Zero; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly List<ParticleEmitter> particleEmitters = new List<ParticleEmitter>();
|
||||||
|
private Hull targetHull;
|
||||||
|
|
||||||
|
private Vector2 rayStartWorldPosition;
|
||||||
|
|
||||||
|
private Color color;
|
||||||
|
|
||||||
|
partial void InitProjSpecific(XElement element)
|
||||||
|
{
|
||||||
|
currentCrossHairPointerScale = element.GetAttributeFloat("crosshairscale", 0.1f);
|
||||||
|
|
||||||
|
foreach (XElement subElement in element.Elements())
|
||||||
|
{
|
||||||
|
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||||
|
{
|
||||||
|
case "particleemitter":
|
||||||
|
particleEmitters.Add(new ParticleEmitter(subElement));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly List<BackgroundSection> targetSections = new List<BackgroundSection>();
|
||||||
|
|
||||||
|
// 0 = 1x1, 1 = 2x2, 2 = 3x3
|
||||||
|
private int spraySetting = 0;
|
||||||
|
private readonly Point[] sprayArray = new Point[8];
|
||||||
|
|
||||||
|
public override void UpdateHUD(Character character, float deltaTime, Camera cam)
|
||||||
|
{
|
||||||
|
if (character == null || !character.IsKeyDown(InputType.Aim)) return;
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
if (PlayerInput.KeyHit(InputType.PreviousFireMode))
|
||||||
|
#else
|
||||||
|
if (PlayerInput.MouseWheelDownClicked())
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
|
||||||
|
if (spraySetting > 0)
|
||||||
|
{
|
||||||
|
spraySetting--;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
spraySetting = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
targetSections.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
if (PlayerInput.KeyHit(InputType.NextFireMode))
|
||||||
|
#else
|
||||||
|
if (PlayerInput.MouseWheelUpClicked())
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
if (spraySetting < 2)
|
||||||
|
{
|
||||||
|
spraySetting++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
spraySetting = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
targetSections.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
crosshairPointerPos = PlayerInput.MousePosition;
|
||||||
|
|
||||||
|
Vector2 rayStart;
|
||||||
|
Vector2 sourcePos = character?.AnimController == null ? item.SimPosition : character.AnimController.AimSourceSimPos;
|
||||||
|
Vector2 barrelPos = item.SimPosition + TransformedBarrelPos;
|
||||||
|
//make sure there's no obstacles between the base of the item (or the shoulder of the character) and the end of the barrel
|
||||||
|
if (Submarine.PickBody(sourcePos, barrelPos, collisionCategory: Physics.CollisionItem | Physics.CollisionItemBlocking | Physics.CollisionWall) == null)
|
||||||
|
{
|
||||||
|
//no obstacles -> we start the raycast at the end of the barrel
|
||||||
|
rayStart = ConvertUnits.ToSimUnits(item.WorldPosition) + TransformedBarrelPos;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
targetHull = null;
|
||||||
|
targetSections.Clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2 pos = character.CursorWorldPosition;
|
||||||
|
Vector2 rayEnd = ConvertUnits.ToSimUnits(pos);
|
||||||
|
rayStartWorldPosition = ConvertUnits.ToDisplayUnits(rayStart);
|
||||||
|
|
||||||
|
if (Vector2.Distance(rayStartWorldPosition, pos) > Range)
|
||||||
|
{
|
||||||
|
targetHull = null;
|
||||||
|
targetSections.Clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
debugRayStartPos = ConvertUnits.ToDisplayUnits(rayStart);
|
||||||
|
debugRayEndPos = ConvertUnits.ToDisplayUnits(rayEnd);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Submarine parentSub = character.Submarine ?? item.Submarine;
|
||||||
|
if (parentSub != null)
|
||||||
|
{
|
||||||
|
rayStart -= parentSub.SimPosition;
|
||||||
|
rayEnd -= parentSub.SimPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
var obstacles = Submarine.PickBodies(rayStart, rayEnd, collisionCategory: Physics.CollisionItem | Physics.CollisionItemBlocking | Physics.CollisionWall);
|
||||||
|
foreach (var body in obstacles)
|
||||||
|
{
|
||||||
|
if (body.UserData is Item item)
|
||||||
|
{
|
||||||
|
var door = item.GetComponent<Door>();
|
||||||
|
if (door != null && door.IsOpen || door.IsBroken) continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
targetHull = null;
|
||||||
|
targetSections.Clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
targetHull = Hull.GetCleanTarget(pos);
|
||||||
|
if (targetHull == null)
|
||||||
|
{
|
||||||
|
targetSections.Clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BackgroundSection mousedOverSection = targetHull.GetBackgroundSection(pos);
|
||||||
|
|
||||||
|
if (mousedOverSection == null)
|
||||||
|
{
|
||||||
|
targetSections.Clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No need to refresh
|
||||||
|
if (targetSections.Count > 0 && mousedOverSection == targetSections[0])
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
targetSections.Clear();
|
||||||
|
|
||||||
|
targetSections.Add(mousedOverSection);
|
||||||
|
int mousedOverIndex = mousedOverSection.Index;
|
||||||
|
|
||||||
|
// Start with 2x2
|
||||||
|
if (spraySetting > 0)
|
||||||
|
{
|
||||||
|
sprayArray[0].X = mousedOverIndex + 1;
|
||||||
|
sprayArray[0].Y = mousedOverSection.RowIndex;
|
||||||
|
|
||||||
|
sprayArray[1].X = mousedOverIndex + targetHull.xBackgroundMax;
|
||||||
|
sprayArray[1].Y = mousedOverSection.RowIndex + 1;
|
||||||
|
|
||||||
|
sprayArray[2].X = sprayArray[1].X + 1;
|
||||||
|
sprayArray[2].Y = sprayArray[1].Y;
|
||||||
|
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
if (targetHull.DoesSectionMatch(sprayArray[i].X, sprayArray[i].Y))
|
||||||
|
{
|
||||||
|
targetSections.Add(targetHull.BackgroundSections[sprayArray[i].X]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add more if it's 3x3
|
||||||
|
if (spraySetting == 2)
|
||||||
|
{
|
||||||
|
sprayArray[3].X = mousedOverIndex - 1;
|
||||||
|
sprayArray[3].Y = mousedOverSection.RowIndex;
|
||||||
|
|
||||||
|
sprayArray[4].X = sprayArray[1].X - 1;
|
||||||
|
sprayArray[4].Y = sprayArray[1].Y;
|
||||||
|
|
||||||
|
sprayArray[5].X = sprayArray[3].X - targetHull.xBackgroundMax;
|
||||||
|
sprayArray[5].Y = sprayArray[3].Y - 1;
|
||||||
|
|
||||||
|
sprayArray[6].X = sprayArray[5].X + 1;
|
||||||
|
sprayArray[6].Y = sprayArray[5].Y;
|
||||||
|
|
||||||
|
sprayArray[7].X = sprayArray[6].X + 1;
|
||||||
|
sprayArray[7].Y = sprayArray[6].Y;
|
||||||
|
|
||||||
|
for (int i = 3; i < sprayArray.Length; i++)
|
||||||
|
{
|
||||||
|
if (targetHull.DoesSectionMatch(sprayArray[i].X, sprayArray[i].Y))
|
||||||
|
{
|
||||||
|
targetSections.Add(targetHull.BackgroundSections[sprayArray[i].X]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
|
||||||
|
{
|
||||||
|
if (character == null || !character.IsKeyDown(InputType.Aim)) { return; }
|
||||||
|
GUI.HideCursor = targetSections.Count > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Use(float deltaTime, Character character = null)
|
||||||
|
{
|
||||||
|
if (character == null) { return false; }
|
||||||
|
if (character == Character.Controlled)
|
||||||
|
{
|
||||||
|
if (targetSections.Count == 0) { return false; }
|
||||||
|
Spray(deltaTime);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//allow remote players to use the sprayer, but don't actually color the walls (we'll receive the data from the server)
|
||||||
|
return character.IsRemotePlayer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Spray(float deltaTime)
|
||||||
|
{
|
||||||
|
if (targetSections.Count == 0) { return; }
|
||||||
|
|
||||||
|
Item liquidItem = liquidContainer?.Inventory.Items[0];
|
||||||
|
if (liquidItem == null) { return; }
|
||||||
|
|
||||||
|
bool isCleaning = false;
|
||||||
|
liquidColors.TryGetValue(liquidItem.prefab.Identifier, out color);
|
||||||
|
|
||||||
|
// Ethanol or other cleaning solvent
|
||||||
|
if (color.A == 0) { isCleaning = true; }
|
||||||
|
|
||||||
|
float sizeAdjustedSprayStrength = SprayStrength / targetSections.Count;
|
||||||
|
|
||||||
|
if (!isCleaning)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < targetSections.Count; i++)
|
||||||
|
{
|
||||||
|
targetHull.SetSectionColorOrStrength(targetSections[i], color, sizeAdjustedSprayStrength * deltaTime, true, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int i = 0; i < targetSections.Count; i++)
|
||||||
|
{
|
||||||
|
targetHull.CleanSection(targetSections[i], -sizeAdjustedSprayStrength * deltaTime, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2 particleStartPos = item.WorldPosition + ConvertUnits.ToDisplayUnits(TransformedBarrelPos);
|
||||||
|
Vector2 particleEndPos = Vector2.Zero;
|
||||||
|
for (int i = 0; i < targetSections.Count; i++)
|
||||||
|
{
|
||||||
|
particleEndPos += new Vector2(targetSections[i].Rect.Center.X, targetSections[i].Rect.Y - targetSections[i].Rect.Height / 2) + targetHull.Rect.Location.ToVector2();
|
||||||
|
}
|
||||||
|
particleEndPos /= targetSections.Count;
|
||||||
|
if (targetHull?.Submarine != null)
|
||||||
|
{
|
||||||
|
particleEndPos += targetHull.Submarine.Position;
|
||||||
|
}
|
||||||
|
float dist = Vector2.Distance(particleStartPos, particleEndPos);
|
||||||
|
|
||||||
|
foreach (ParticleEmitter particleEmitter in particleEmitters)
|
||||||
|
{
|
||||||
|
float particleAngle = item.body.Rotation + ((item.body.Dir > 0.0f) ? 0.0f : MathHelper.Pi);
|
||||||
|
float particleRange = particleEmitter.Prefab.VelocityMax * particleEmitter.Prefab.ParticlePrefab.LifeTime;
|
||||||
|
particleEmitter.Emit(
|
||||||
|
deltaTime, particleStartPos,
|
||||||
|
item.CurrentHull, particleAngle, particleEmitter.Prefab.CopyEntityAngle ? -particleAngle : 0, velocityMultiplier: dist / particleRange * 1.5f,
|
||||||
|
colorMultiplier: new Color(color.R, color.G, color.B, (byte)255));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Draw(SpriteBatch spriteBatch, bool editing, float itemDepth = -1)
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
if (GameMain.DebugDraw && Character.Controlled != null && Character.Controlled.IsKeyDown(InputType.Aim))
|
||||||
|
{
|
||||||
|
GUI.DrawLine(spriteBatch,
|
||||||
|
new Vector2(debugRayStartPos.X, -debugRayStartPos.Y),
|
||||||
|
new Vector2(debugRayEndPos.X, -debugRayEndPos.Y),
|
||||||
|
Color.Yellow);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (Character.Controlled == null || !Character.Controlled.HasEquippedItem(item) || !Character.Controlled.IsKeyDown(InputType.Aim) || targetHull == null || targetSections.Count == 0) return;
|
||||||
|
|
||||||
|
Vector2 drawOffset = targetHull.Submarine == null ? Vector2.Zero : targetHull.Submarine.DrawPosition;
|
||||||
|
Point sectionSize = targetSections[0].Rect.Size;
|
||||||
|
Rectangle drawPositionRect = new Rectangle((int)(drawOffset.X + targetHull.Rect.X), (int)(drawOffset.Y + targetHull.Rect.Y), sectionSize.X, sectionSize.Y);
|
||||||
|
|
||||||
|
if (crosshairSprite == null && crosshairPointerSprite == null)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < targetSections.Count; i++)
|
||||||
|
{
|
||||||
|
GUI.DrawRectangle(spriteBatch, new Vector2(drawPositionRect.X + targetSections[i].Rect.X, -(drawPositionRect.Y + targetSections[i].Rect.Y)), new Vector2(sectionSize.X, sectionSize.Y), Color.White, false, 0.0f, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (targetSections.Count > 0)
|
||||||
|
{
|
||||||
|
Vector2 drawPos = Vector2.Zero;
|
||||||
|
for (int i = 0; i < targetSections.Count; i++)
|
||||||
|
{
|
||||||
|
drawPos += new Vector2(drawPositionRect.X + targetSections[i].Rect.X + sectionSize.X / 2, -(drawPositionRect.Y + targetSections[i].Rect.Y - sectionSize.Y / 2));
|
||||||
|
}
|
||||||
|
drawPos /= targetSections.Count;
|
||||||
|
crosshairSprite?.Draw(spriteBatch, drawPos, scale: sectionSize.X * 3 / crosshairSprite.size.X);
|
||||||
|
crosshairPointerSprite?.Draw(spriteBatch, drawPos, scale: sectionSize.X * (spraySetting + 1) / crosshairPointerSprite.size.X);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -256,6 +256,7 @@ namespace Barotrauma.Items.Components
|
|||||||
loopingSoundChannel = loopingSound.RoundSound.Sound.Play(
|
loopingSoundChannel = loopingSound.RoundSound.Sound.Play(
|
||||||
new Vector3(item.WorldPosition, 0.0f),
|
new Vector3(item.WorldPosition, 0.0f),
|
||||||
0.01f,
|
0.01f,
|
||||||
|
loopingSound.RoundSound.GetRandomFrequencyMultiplier(),
|
||||||
SoundPlayer.ShouldMuffleSound(Character.Controlled, item.WorldPosition, loopingSound.Range, Character.Controlled?.CurrentHull));
|
SoundPlayer.ShouldMuffleSound(Character.Controlled, item.WorldPosition, loopingSound.Range, Character.Controlled?.CurrentHull));
|
||||||
loopingSoundChannel.Looping = true;
|
loopingSoundChannel.Looping = true;
|
||||||
//TODO: tweak
|
//TODO: tweak
|
||||||
@@ -326,7 +327,7 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
float volume = GetSoundVolume(itemSound);
|
float volume = GetSoundVolume(itemSound);
|
||||||
if (volume <= 0.0001f) { return; }
|
if (volume <= 0.0001f) { return; }
|
||||||
var channel = SoundPlayer.PlaySound(itemSound.RoundSound.Sound, position, volume, itemSound.Range, item.CurrentHull);
|
var channel = SoundPlayer.PlaySound(itemSound.RoundSound.Sound, position, volume, itemSound.Range, itemSound.RoundSound.GetRandomFrequencyMultiplier(), item.CurrentHull);
|
||||||
if (channel != null) { playingOneshotSoundChannels.Add(channel); }
|
if (channel != null) { playingOneshotSoundChannels.Add(channel); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -172,6 +172,8 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
Vector2 transformedItemPos = ItemPos * item.Scale;
|
Vector2 transformedItemPos = ItemPos * item.Scale;
|
||||||
Vector2 transformedItemInterval = ItemInterval * item.Scale;
|
Vector2 transformedItemInterval = ItemInterval * item.Scale;
|
||||||
|
Vector2 transformedItemIntervalHorizontal = new Vector2(transformedItemInterval.X, 0.0f);
|
||||||
|
Vector2 transformedItemIntervalVertical = new Vector2(0.0f, transformedItemInterval.Y);
|
||||||
|
|
||||||
if (item.body == null)
|
if (item.body == null)
|
||||||
{
|
{
|
||||||
@@ -180,15 +182,26 @@ namespace Barotrauma.Items.Components
|
|||||||
transformedItemPos.X = -transformedItemPos.X;
|
transformedItemPos.X = -transformedItemPos.X;
|
||||||
transformedItemPos.X += item.Rect.Width;
|
transformedItemPos.X += item.Rect.Width;
|
||||||
transformedItemInterval.X = -transformedItemInterval.X;
|
transformedItemInterval.X = -transformedItemInterval.X;
|
||||||
|
transformedItemIntervalHorizontal.X = -transformedItemIntervalHorizontal.X;
|
||||||
}
|
}
|
||||||
if (item.FlippedY)
|
if (item.FlippedY)
|
||||||
{
|
{
|
||||||
transformedItemPos.Y = -transformedItemPos.Y;
|
transformedItemPos.Y = -transformedItemPos.Y;
|
||||||
transformedItemPos.Y -= item.Rect.Height;
|
transformedItemPos.Y -= item.Rect.Height;
|
||||||
transformedItemInterval.Y = -transformedItemInterval.Y;
|
transformedItemInterval.Y = -transformedItemInterval.Y;
|
||||||
|
transformedItemIntervalVertical.Y = -transformedItemIntervalVertical.Y;
|
||||||
}
|
}
|
||||||
transformedItemPos += new Vector2(item.Rect.X, item.Rect.Y);
|
transformedItemPos += new Vector2(item.Rect.X, item.Rect.Y);
|
||||||
if (item.Submarine != null) { transformedItemPos += item.Submarine.DrawPosition; }
|
if (item.Submarine != null) { transformedItemPos += item.Submarine.DrawPosition; }
|
||||||
|
|
||||||
|
if (Math.Abs(item.Rotation) > 0.01f)
|
||||||
|
{
|
||||||
|
Matrix transform = Matrix.CreateRotationZ(MathHelper.ToRadians(-item.Rotation));
|
||||||
|
transformedItemPos = Vector2.Transform(transformedItemPos - item.DrawPosition, transform) + item.DrawPosition;
|
||||||
|
transformedItemInterval = Vector2.Transform(transformedItemInterval, transform);
|
||||||
|
transformedItemIntervalHorizontal = Vector2.Transform(transformedItemIntervalHorizontal, transform);
|
||||||
|
transformedItemIntervalVertical = Vector2.Transform(transformedItemIntervalVertical, transform);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -197,9 +210,12 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
transformedItemPos.X = -transformedItemPos.X;
|
transformedItemPos.X = -transformedItemPos.X;
|
||||||
transformedItemInterval.X = -transformedItemInterval.X;
|
transformedItemInterval.X = -transformedItemInterval.X;
|
||||||
|
transformedItemIntervalHorizontal.X = -transformedItemIntervalHorizontal.X;
|
||||||
}
|
}
|
||||||
|
|
||||||
transformedItemPos = Vector2.Transform(transformedItemPos, transform);
|
transformedItemPos = Vector2.Transform(transformedItemPos, transform);
|
||||||
transformedItemInterval = Vector2.Transform(transformedItemInterval, transform);
|
transformedItemInterval = Vector2.Transform(transformedItemInterval, transform);
|
||||||
|
transformedItemIntervalHorizontal = Vector2.Transform(transformedItemIntervalHorizontal, transform);
|
||||||
|
|
||||||
transformedItemPos += item.DrawPosition;
|
transformedItemPos += item.DrawPosition;
|
||||||
}
|
}
|
||||||
@@ -207,8 +223,14 @@ namespace Barotrauma.Items.Components
|
|||||||
Vector2 currentItemPos = transformedItemPos;
|
Vector2 currentItemPos = transformedItemPos;
|
||||||
|
|
||||||
SpriteEffects spriteEffects = SpriteEffects.None;
|
SpriteEffects spriteEffects = SpriteEffects.None;
|
||||||
if ((item.body != null && item.body.Dir == -1) || item.FlippedX) { spriteEffects |= SpriteEffects.FlipHorizontally; }
|
if ((item.body != null && item.body.Dir == -1) || item.FlippedX)
|
||||||
if (item.FlippedY) { spriteEffects |= SpriteEffects.FlipVertically; }
|
{
|
||||||
|
spriteEffects |= MathUtils.NearlyEqual(ItemRotation % 180, 90.0f) ? SpriteEffects.FlipVertically : SpriteEffects.FlipHorizontally;
|
||||||
|
}
|
||||||
|
if (item.FlippedY)
|
||||||
|
{
|
||||||
|
spriteEffects |= MathUtils.NearlyEqual(ItemRotation % 180, 90.0f) ? SpriteEffects.FlipHorizontally : SpriteEffects.FlipVertically;
|
||||||
|
}
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
foreach (Item containedItem in Inventory.Items)
|
foreach (Item containedItem in Inventory.Items)
|
||||||
@@ -233,7 +255,7 @@ namespace Barotrauma.Items.Components
|
|||||||
new Vector2(currentItemPos.X, -currentItemPos.Y),
|
new Vector2(currentItemPos.X, -currentItemPos.Y),
|
||||||
containedItem.GetSpriteColor(),
|
containedItem.GetSpriteColor(),
|
||||||
origin,
|
origin,
|
||||||
-(containedItem.body == null ? 0.0f : containedItem.body.DrawRotation),
|
-(containedItem.body == null ? 0.0f : containedItem.body.DrawRotation + MathHelper.ToRadians(-item.Rotation)),
|
||||||
containedItem.Scale,
|
containedItem.Scale,
|
||||||
spriteEffects,
|
spriteEffects,
|
||||||
depth: containedSpriteDepth);
|
depth: containedSpriteDepth);
|
||||||
@@ -248,11 +270,11 @@ namespace Barotrauma.Items.Components
|
|||||||
if (Math.Abs(ItemInterval.X) > 0.001f && Math.Abs(ItemInterval.Y) > 0.001f)
|
if (Math.Abs(ItemInterval.X) > 0.001f && Math.Abs(ItemInterval.Y) > 0.001f)
|
||||||
{
|
{
|
||||||
//interval set on both axes -> use a grid layout
|
//interval set on both axes -> use a grid layout
|
||||||
currentItemPos.X += transformedItemInterval.X;
|
currentItemPos += transformedItemIntervalHorizontal;
|
||||||
if (i % ItemsPerRow == 0)
|
if (i % ItemsPerRow == 0)
|
||||||
{
|
{
|
||||||
currentItemPos.X = transformedItemPos.X;
|
currentItemPos = transformedItemPos;
|
||||||
currentItemPos.Y += transformedItemInterval.Y;
|
currentItemPos += transformedItemIntervalVertical * (i / ItemsPerRow);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -264,6 +286,7 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
public override void UpdateHUD(Character character, float deltaTime, Camera cam)
|
public override void UpdateHUD(Character character, float deltaTime, Camera cam)
|
||||||
{
|
{
|
||||||
|
if (item.NonInteractable) { return; }
|
||||||
if (Inventory.RectTransform != null)
|
if (Inventory.RectTransform != null)
|
||||||
{
|
{
|
||||||
guiCustomComponent.RectTransform.Parent = Inventory.RectTransform;
|
guiCustomComponent.RectTransform.Parent = Inventory.RectTransform;
|
||||||
@@ -272,7 +295,7 @@ namespace Barotrauma.Items.Components
|
|||||||
//if the item is in the character's inventory, no need to update the item's inventory
|
//if the item is in the character's inventory, no need to update the item's inventory
|
||||||
//because the player can see it by hovering the cursor over the item
|
//because the player can see it by hovering the cursor over the item
|
||||||
guiCustomComponent.Visible = item.ParentInventory?.Owner != character && DrawInventory;
|
guiCustomComponent.Visible = item.ParentInventory?.Owner != character && DrawInventory;
|
||||||
if (!guiCustomComponent.Visible) return;
|
if (!guiCustomComponent.Visible) { return; }
|
||||||
|
|
||||||
Inventory.Update(deltaTime, cam);
|
Inventory.Update(deltaTime, cam);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Microsoft.Xna.Framework;
|
using Barotrauma.Networking;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
using System;
|
using System;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
@@ -225,5 +226,10 @@ namespace Barotrauma.Items.Components
|
|||||||
textBlock.TextOffset = drawPos - textBlock.Rect.Location.ToVector2() + new Vector2(scrollAmount + scrollPadding, 0.0f);
|
textBlock.TextOffset = drawPos - textBlock.Rect.Location.ToVector2() + new Vector2(scrollAmount + scrollPadding, 0.0f);
|
||||||
textBlock.DrawManually(spriteBatch);
|
textBlock.DrawManually(spriteBatch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
||||||
|
{
|
||||||
|
Text = msg.ReadString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,8 +49,8 @@ namespace Barotrauma.Items.Components
|
|||||||
if (light.LightSprite != null && (item.body == null || item.body.Enabled) && lightBrightness > 0.0f && IsOn)
|
if (light.LightSprite != null && (item.body == null || item.body.Enabled) && lightBrightness > 0.0f && IsOn)
|
||||||
{
|
{
|
||||||
Vector2 origin = light.LightSprite.Origin;
|
Vector2 origin = light.LightSprite.Origin;
|
||||||
if (light.LightSpriteEffect == SpriteEffects.FlipHorizontally) { origin.X = light.LightSprite.SourceRect.Width - origin.X; }
|
if ((light.LightSpriteEffect & SpriteEffects.FlipHorizontally) == SpriteEffects.FlipHorizontally) { origin.X = light.LightSprite.SourceRect.Width - origin.X; }
|
||||||
if (light.LightSpriteEffect == SpriteEffects.FlipVertically) { origin.Y = light.LightSprite.SourceRect.Height - origin.Y; }
|
if ((light.LightSpriteEffect & SpriteEffects.FlipVertically) == SpriteEffects.FlipVertically) { origin.Y = light.LightSprite.SourceRect.Height - origin.Y; }
|
||||||
light.LightSprite.Draw(spriteBatch, new Vector2(item.DrawPosition.X, -item.DrawPosition.Y), lightColor * lightBrightness, origin, -light.Rotation, item.Scale, light.LightSpriteEffect, item.SpriteDepth - 0.0001f);
|
light.LightSprite.Draw(spriteBatch, new Vector2(item.DrawPosition.X, -item.DrawPosition.Y), lightColor * lightBrightness, origin, -light.Rotation, item.Scale, light.LightSpriteEffect, item.SpriteDepth - 0.0001f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,7 +52,9 @@ namespace Barotrauma.Items.Components
|
|||||||
RelativeOffset = new Vector2(0.05f, 0)
|
RelativeOffset = new Vector2(0.05f, 0)
|
||||||
}, TextManager.Get("PumpAutoControl", fallBackTag: "ReactorAutoControl"), font: GUI.SubHeadingFont, style: "IndicatorLightYellow")
|
}, TextManager.Get("PumpAutoControl", fallBackTag: "ReactorAutoControl"), font: GUI.SubHeadingFont, style: "IndicatorLightYellow")
|
||||||
{
|
{
|
||||||
CanBeFocused = false
|
Selected = false,
|
||||||
|
Enabled = false,
|
||||||
|
ToolTip = TextManager.Get("AutoControlTip")
|
||||||
};
|
};
|
||||||
powerIndicator.TextBlock.Wrap = autoControlIndicator.TextBlock.Wrap = true;
|
powerIndicator.TextBlock.Wrap = autoControlIndicator.TextBlock.Wrap = true;
|
||||||
powerIndicator.TextBlock.OverrideTextColor(GUI.Style.TextColor);
|
powerIndicator.TextBlock.OverrideTextColor(GUI.Style.TextColor);
|
||||||
@@ -75,6 +77,7 @@ namespace Barotrauma.Items.Components
|
|||||||
if (Math.Abs(newTargetForce - targetForce) < 0.01) { return false; }
|
if (Math.Abs(newTargetForce - targetForce) < 0.01) { return false; }
|
||||||
|
|
||||||
targetForce = newTargetForce;
|
targetForce = newTargetForce;
|
||||||
|
User = Character.Controlled;
|
||||||
|
|
||||||
if (GameMain.Client != null)
|
if (GameMain.Client != null)
|
||||||
{
|
{
|
||||||
@@ -145,7 +148,7 @@ namespace Barotrauma.Items.Components
|
|||||||
propellerSprite.Draw(spriteBatch, (int)Math.Floor(spriteIndex), drawPos, Color.White, propellerSprite.Origin, 0.0f, Vector2.One);
|
propellerSprite.Draw(spriteBatch, (int)Math.Floor(spriteIndex), drawPos, Color.White, propellerSprite.Origin, 0.0f, Vector2.One);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (editing)
|
if (editing && !GUI.DisableHUD)
|
||||||
{
|
{
|
||||||
Vector2 drawPos = item.DrawPosition;
|
Vector2 drawPos = item.DrawPosition;
|
||||||
drawPos += PropellerPos;
|
drawPos += PropellerPos;
|
||||||
@@ -164,11 +167,16 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
if (correctionTimer > 0.0f)
|
if (correctionTimer > 0.0f)
|
||||||
{
|
{
|
||||||
StartDelayedCorrection(type, msg.ExtractBits(5), sendingTime);
|
StartDelayedCorrection(type, msg.ExtractBits(5 + 16), sendingTime);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
targetForce = msg.ReadRangedInteger(-10, 10) * 10.0f;
|
targetForce = msg.ReadRangedInteger(-10, 10) * 10.0f;
|
||||||
|
UInt16 userID = msg.ReadUInt16();
|
||||||
|
if (userID != Entity.NullEntityID)
|
||||||
|
{
|
||||||
|
User = Entity.FindEntityByID(userID) as Character;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ namespace Barotrauma.Items.Components
|
|||||||
OnSelected = (component, userdata) =>
|
OnSelected = (component, userdata) =>
|
||||||
{
|
{
|
||||||
selectedItem = userdata as FabricationRecipe;
|
selectedItem = userdata as FabricationRecipe;
|
||||||
if (selectedItem != null) SelectItem(Character.Controlled, selectedItem);
|
if (selectedItem != null) { SelectItem(Character.Controlled, selectedItem); }
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -292,7 +292,7 @@ namespace Barotrauma.Items.Components
|
|||||||
foreach (Item item in inputContainer.Inventory.Items)
|
foreach (Item item in inputContainer.Inventory.Items)
|
||||||
{
|
{
|
||||||
if (item == null) { continue; }
|
if (item == null) { continue; }
|
||||||
missingItems.Remove(missingItems.FirstOrDefault(mi => mi.ItemPrefab == item.prefab));
|
missingItems.Remove(missingItems.FirstOrDefault(mi => mi.ItemPrefabs.Contains(item.prefab)));
|
||||||
}
|
}
|
||||||
|
|
||||||
var availableIngredients = GetAvailableIngredients();
|
var availableIngredients = GetAvailableIngredients();
|
||||||
@@ -328,12 +328,12 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
if (slotIndex >= inputContainer.Capacity) { break; }
|
if (slotIndex >= inputContainer.Capacity) { break; }
|
||||||
|
|
||||||
var itemIcon = requiredItem.ItemPrefab.InventoryIcon ?? requiredItem.ItemPrefab.sprite;
|
var itemIcon = requiredItem.ItemPrefabs.First().InventoryIcon ?? requiredItem.ItemPrefabs.First().sprite;
|
||||||
Rectangle slotRect = inputContainer.Inventory.slots[slotIndex].Rect;
|
Rectangle slotRect = inputContainer.Inventory.slots[slotIndex].Rect;
|
||||||
itemIcon.Draw(
|
itemIcon.Draw(
|
||||||
spriteBatch,
|
spriteBatch,
|
||||||
slotRect.Center.ToVector2(),
|
slotRect.Center.ToVector2(),
|
||||||
color: requiredItem.ItemPrefab.InventoryIconColor * 0.3f,
|
color: requiredItem.ItemPrefabs.First().InventoryIconColor * 0.3f,
|
||||||
scale: Math.Min(slotRect.Width / itemIcon.size.X, slotRect.Height / itemIcon.size.Y));
|
scale: Math.Min(slotRect.Width / itemIcon.size.X, slotRect.Height / itemIcon.size.Y));
|
||||||
|
|
||||||
if (requiredItem.UseCondition && requiredItem.MinCondition < 1.0f)
|
if (requiredItem.UseCondition && requiredItem.MinCondition < 1.0f)
|
||||||
@@ -346,14 +346,16 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
if (slotRect.Contains(PlayerInput.MousePosition))
|
if (slotRect.Contains(PlayerInput.MousePosition))
|
||||||
{
|
{
|
||||||
string toolTipText = requiredItem.ItemPrefab.Name;
|
var suitableIngredients = requiredItem.ItemPrefabs.Select(ip => ip.Name);
|
||||||
|
string toolTipText = string.Join(", ", suitableIngredients.Count() > 3 ? suitableIngredients.SkipLast(suitableIngredients.Count() - 3) : suitableIngredients);
|
||||||
|
if (suitableIngredients.Count() > 3) { toolTipText += "..."; }
|
||||||
if (requiredItem.UseCondition && requiredItem.MinCondition < 1.0f)
|
if (requiredItem.UseCondition && requiredItem.MinCondition < 1.0f)
|
||||||
{
|
{
|
||||||
toolTipText += " " + (int)Math.Round(requiredItem.MinCondition * 100) + "%";
|
toolTipText += " " + (int)Math.Round(requiredItem.MinCondition * 100) + "%";
|
||||||
}
|
}
|
||||||
if (!string.IsNullOrEmpty(requiredItem.ItemPrefab.Description))
|
if (!string.IsNullOrEmpty(requiredItem.ItemPrefabs.First().Description))
|
||||||
{
|
{
|
||||||
toolTipText += '\n' + requiredItem.ItemPrefab.Description;
|
toolTipText += '\n' + requiredItem.ItemPrefabs.First().Description;
|
||||||
}
|
}
|
||||||
tooltip = new Pair<Rectangle, string>(slotRect, toolTipText);
|
tooltip = new Pair<Rectangle, string>(slotRect, toolTipText);
|
||||||
}
|
}
|
||||||
@@ -378,10 +380,11 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
if (fabricatedItem != null)
|
if (fabricatedItem != null)
|
||||||
{
|
{
|
||||||
|
float clampedProgressState = Math.Clamp(progressState, 0f, 1f);
|
||||||
GUI.DrawRectangle(spriteBatch,
|
GUI.DrawRectangle(spriteBatch,
|
||||||
new Rectangle(
|
new Rectangle(
|
||||||
slotRect.X, slotRect.Y + (int)(slotRect.Height * (1.0f - progressState)),
|
slotRect.X, slotRect.Y + (int)(slotRect.Height * (1.0f - clampedProgressState)),
|
||||||
slotRect.Width, (int)(slotRect.Height * progressState)),
|
slotRect.Width, (int)(slotRect.Height * clampedProgressState)),
|
||||||
GUI.Style.Green * 0.5f, isFilled: true);
|
GUI.Style.Green * 0.5f, isFilled: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -429,8 +432,10 @@ namespace Barotrauma.Items.Components
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool SelectItem(Character user, FabricationRecipe selectedItem)
|
private bool SelectItem(Character user, FabricationRecipe selectedItem, float? overrideRequiredTime = null)
|
||||||
{
|
{
|
||||||
|
this.selectedItem = selectedItem;
|
||||||
|
|
||||||
selectedItemFrame.ClearChildren();
|
selectedItemFrame.ClearChildren();
|
||||||
selectedItemReqsFrame.ClearChildren();
|
selectedItemReqsFrame.ClearChildren();
|
||||||
|
|
||||||
@@ -496,7 +501,8 @@ namespace Barotrauma.Items.Components
|
|||||||
float degreeOfSuccess = user == null ? 0.0f : FabricationDegreeOfSuccess(user, selectedItem.RequiredSkills);
|
float degreeOfSuccess = user == null ? 0.0f : FabricationDegreeOfSuccess(user, selectedItem.RequiredSkills);
|
||||||
if (degreeOfSuccess > 0.5f) { degreeOfSuccess = 1.0f; }
|
if (degreeOfSuccess > 0.5f) { degreeOfSuccess = 1.0f; }
|
||||||
|
|
||||||
float requiredTime = user == null ? selectedItem.RequiredTime : GetRequiredTime(selectedItem, user);
|
float requiredTime = overrideRequiredTime ??
|
||||||
|
(user == null ? selectedItem.RequiredTime : GetRequiredTime(selectedItem, user));
|
||||||
|
|
||||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedReqFrame.RectTransform),
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedReqFrame.RectTransform),
|
||||||
TextManager.Get("FabricatorRequiredTime") , textColor: ToolBox.GradientLerp(degreeOfSuccess, GUI.Style.Red, Color.Yellow, GUI.Style.Green), font: GUI.SubHeadingFont)
|
TextManager.Get("FabricatorRequiredTime") , textColor: ToolBox.GradientLerp(degreeOfSuccess, GUI.Style.Red, Color.Yellow, GUI.Style.Green), font: GUI.SubHeadingFont)
|
||||||
@@ -605,7 +611,7 @@ namespace Barotrauma.Items.Components
|
|||||||
State = newState;
|
State = newState;
|
||||||
timeUntilReady = newTimeUntilReady;
|
timeUntilReady = newTimeUntilReady;
|
||||||
|
|
||||||
if (newState == FabricatorState.Stopped || itemIndex == -1 || user == null)
|
if (newState == FabricatorState.Stopped || itemIndex == -1)
|
||||||
{
|
{
|
||||||
CancelFabricating();
|
CancelFabricating();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,7 +81,9 @@ namespace Barotrauma.Items.Components
|
|||||||
autoControlIndicator = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.25f), rightArea.RectTransform, Anchor.TopLeft),
|
autoControlIndicator = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.25f), rightArea.RectTransform, Anchor.TopLeft),
|
||||||
TextManager.Get("PumpAutoControl", fallBackTag: "ReactorAutoControl"), font: GUI.SubHeadingFont, style: "IndicatorLightYellow")
|
TextManager.Get("PumpAutoControl", fallBackTag: "ReactorAutoControl"), font: GUI.SubHeadingFont, style: "IndicatorLightYellow")
|
||||||
{
|
{
|
||||||
CanBeFocused = false
|
Selected = false,
|
||||||
|
Enabled = false,
|
||||||
|
ToolTip = TextManager.Get("AutoControlTip")
|
||||||
};
|
};
|
||||||
autoControlIndicator.TextBlock.AutoScaleHorizontal = true;
|
autoControlIndicator.TextBlock.AutoScaleHorizontal = true;
|
||||||
autoControlIndicator.TextBlock.OverrideTextColor(GUI.Style.TextColor);
|
autoControlIndicator.TextBlock.OverrideTextColor(GUI.Style.TextColor);
|
||||||
|
|||||||
@@ -131,17 +131,23 @@ namespace Barotrauma.Items.Components
|
|||||||
criticalHeatWarning = new GUITickBox(new RectTransform(new Vector2(0.33f, 1.0f), topLeftArea.RectTransform) { MaxSize = maxIndicatorSize },
|
criticalHeatWarning = new GUITickBox(new RectTransform(new Vector2(0.33f, 1.0f), topLeftArea.RectTransform) { MaxSize = maxIndicatorSize },
|
||||||
TextManager.Get("ReactorWarningCriticalTemp"), font: GUI.SubHeadingFont, style: "IndicatorLightRed")
|
TextManager.Get("ReactorWarningCriticalTemp"), font: GUI.SubHeadingFont, style: "IndicatorLightRed")
|
||||||
{
|
{
|
||||||
CanBeFocused = false
|
Selected = false,
|
||||||
|
Enabled = false,
|
||||||
|
ToolTip = TextManager.Get("ReactorHeatTip")
|
||||||
};
|
};
|
||||||
lowTemperatureWarning = new GUITickBox(new RectTransform(new Vector2(0.33f, 1.0f), topLeftArea.RectTransform) { MaxSize = maxIndicatorSize },
|
lowTemperatureWarning = new GUITickBox(new RectTransform(new Vector2(0.33f, 1.0f), topLeftArea.RectTransform) { MaxSize = maxIndicatorSize },
|
||||||
TextManager.Get("ReactorWarningCriticalLowTemp"), font: GUI.SubHeadingFont, style: "IndicatorLightRed")
|
TextManager.Get("ReactorWarningCriticalLowTemp"), font: GUI.SubHeadingFont, style: "IndicatorLightRed")
|
||||||
{
|
{
|
||||||
CanBeFocused = false
|
Selected = false,
|
||||||
|
Enabled = false,
|
||||||
|
ToolTip = TextManager.Get("ReactorTempTip")
|
||||||
};
|
};
|
||||||
criticalOutputWarning = new GUITickBox(new RectTransform(new Vector2(0.33f, 1.0f), topLeftArea.RectTransform) { MaxSize = maxIndicatorSize },
|
criticalOutputWarning = new GUITickBox(new RectTransform(new Vector2(0.33f, 1.0f), topLeftArea.RectTransform) { MaxSize = maxIndicatorSize },
|
||||||
TextManager.Get("ReactorWarningCriticalOutput"), font: GUI.SubHeadingFont, style: "IndicatorLightRed")
|
TextManager.Get("ReactorWarningCriticalOutput"), font: GUI.SubHeadingFont, style: "IndicatorLightRed")
|
||||||
{
|
{
|
||||||
CanBeFocused = false
|
Selected = false,
|
||||||
|
Enabled = false,
|
||||||
|
ToolTip = TextManager.Get("ReactorOutputTip")
|
||||||
};
|
};
|
||||||
List<GUITickBox> indicatorLights = new List<GUITickBox>() { criticalHeatWarning, lowTemperatureWarning, criticalOutputWarning };
|
List<GUITickBox> indicatorLights = new List<GUITickBox>() { criticalHeatWarning, lowTemperatureWarning, criticalOutputWarning };
|
||||||
indicatorLights.ForEach(l => l.TextBlock.OverrideTextColor(GUI.Style.TextColor));
|
indicatorLights.ForEach(l => l.TextBlock.OverrideTextColor(GUI.Style.TextColor));
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
using Barotrauma.Extensions;
|
|
||||||
|
|
||||||
namespace Barotrauma.Items.Components
|
namespace Barotrauma.Items.Components
|
||||||
{
|
{
|
||||||
@@ -20,7 +19,7 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
private PathFinder pathFinder;
|
private PathFinder pathFinder;
|
||||||
|
|
||||||
private bool dynamicDockingIndicator = true;
|
private readonly bool dynamicDockingIndicator = true;
|
||||||
|
|
||||||
private bool unsentChanges;
|
private bool unsentChanges;
|
||||||
private float networkUpdateTimer;
|
private float networkUpdateTimer;
|
||||||
@@ -378,7 +377,6 @@ namespace Barotrauma.Items.Components
|
|||||||
float edgeDist = Rand.Range(0.0f, 1.0f);
|
float edgeDist = Rand.Range(0.0f, 1.0f);
|
||||||
Vector2 blipPos = trigger.WorldPosition + Rand.Vector(trigger.ColliderRadius * edgeDist);
|
Vector2 blipPos = trigger.WorldPosition + Rand.Vector(trigger.ColliderRadius * edgeDist);
|
||||||
Vector2 blipVel = flow;
|
Vector2 blipVel = flow;
|
||||||
if (trigger.ForceFalloff) flow *= (1.0f - edgeDist);
|
|
||||||
|
|
||||||
//go through other triggers in range and add the flows of the ones that the blip is inside
|
//go through other triggers in range and add the flows of the ones that the blip is inside
|
||||||
foreach (KeyValuePair<LevelTrigger, Vector2> triggerFlow2 in levelTriggerFlows)
|
foreach (KeyValuePair<LevelTrigger, Vector2> triggerFlow2 in levelTriggerFlows)
|
||||||
@@ -387,7 +385,7 @@ namespace Barotrauma.Items.Components
|
|||||||
if (trigger2 != trigger && Vector2.DistanceSquared(blipPos, trigger2.WorldPosition) < trigger2.ColliderRadius * trigger2.ColliderRadius)
|
if (trigger2 != trigger && Vector2.DistanceSquared(blipPos, trigger2.WorldPosition) < trigger2.ColliderRadius * trigger2.ColliderRadius)
|
||||||
{
|
{
|
||||||
Vector2 trigger2flow = triggerFlow2.Value;
|
Vector2 trigger2flow = triggerFlow2.Value;
|
||||||
if (trigger2.ForceFalloff) trigger2flow *= (1.0f - Vector2.Distance(blipPos, trigger2.WorldPosition) / trigger2.ColliderRadius);
|
if (trigger2.ForceFalloff) trigger2flow *= 1.0f - Vector2.Distance(blipPos, trigger2.WorldPosition) / trigger2.ColliderRadius;
|
||||||
blipVel += trigger2flow;
|
blipVel += trigger2flow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -507,7 +505,7 @@ namespace Barotrauma.Items.Components
|
|||||||
float passivePingRadius = (float)(Timing.TotalTime % 1.0f);
|
float passivePingRadius = (float)(Timing.TotalTime % 1.0f);
|
||||||
if (passivePingRadius > 0.0f)
|
if (passivePingRadius > 0.0f)
|
||||||
{
|
{
|
||||||
disruptedDirections.Clear();
|
if (activePingsCount == 0) { disruptedDirections.Clear(); }
|
||||||
foreach (AITarget t in AITarget.List)
|
foreach (AITarget t in AITarget.List)
|
||||||
{
|
{
|
||||||
if (t.Entity is Character c && c.Params.HideInSonar) { continue; }
|
if (t.Entity is Character c && c.Params.HideInSonar) { continue; }
|
||||||
@@ -581,14 +579,14 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentMode == Mode.Active && currentPingIndex != -1)
|
if (currentPingIndex != -1)
|
||||||
{
|
{
|
||||||
var activePing = activePings[currentPingIndex];
|
var activePing = activePings[currentPingIndex];
|
||||||
if (activePing.IsDirectional && directionalPingCircle != null)
|
if (activePing.IsDirectional && directionalPingCircle != null)
|
||||||
{
|
{
|
||||||
directionalPingCircle.Draw(spriteBatch, center, Color.White * (1.0f - activePing.State),
|
directionalPingCircle.Draw(spriteBatch, center, Color.White * (1.0f - activePing.State),
|
||||||
rotate: MathUtils.VectorToAngle(activePing.Direction),
|
rotate: MathUtils.VectorToAngle(activePing.Direction),
|
||||||
scale: (DisplayRadius / directionalPingCircle.size.X) * activePing.State);
|
scale: DisplayRadius / directionalPingCircle.size.X * activePing.State);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -611,13 +609,13 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
if (sonarBlips.Count > 0)
|
if (sonarBlips.Count > 0)
|
||||||
{
|
{
|
||||||
zoomSqrt = (float)Math.Sqrt(zoom);
|
float blipScale = 0.08f * (float)Math.Sqrt(zoom) * (rect.Width / 700.0f);
|
||||||
spriteBatch.End();
|
spriteBatch.End();
|
||||||
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Additive);
|
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Additive);
|
||||||
|
|
||||||
foreach (SonarBlip sonarBlip in sonarBlips)
|
foreach (SonarBlip sonarBlip in sonarBlips)
|
||||||
{
|
{
|
||||||
DrawBlip(spriteBatch, sonarBlip, transducerCenter, center, sonarBlip.FadeTimer / 2.0f * signalStrength);
|
DrawBlip(spriteBatch, sonarBlip, transducerCenter, center, sonarBlip.FadeTimer / 2.0f * signalStrength, blipScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
spriteBatch.End();
|
spriteBatch.End();
|
||||||
@@ -1297,7 +1295,7 @@ namespace Barotrauma.Items.Components
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawBlip(SpriteBatch spriteBatch, SonarBlip blip, Vector2 transducerPos, Vector2 center, float strength)
|
private void DrawBlip(SpriteBatch spriteBatch, SonarBlip blip, Vector2 transducerPos, Vector2 center, float strength, float blipScale)
|
||||||
{
|
{
|
||||||
strength = MathHelper.Clamp(strength, 0.0f, 1.0f);
|
strength = MathHelper.Clamp(strength, 0.0f, 1.0f);
|
||||||
|
|
||||||
@@ -1306,8 +1304,8 @@ namespace Barotrauma.Items.Components
|
|||||||
Vector2 pos = (blip.Position - transducerPos) * displayScale * zoom;
|
Vector2 pos = (blip.Position - transducerPos) * displayScale * zoom;
|
||||||
pos.Y = -pos.Y;
|
pos.Y = -pos.Y;
|
||||||
|
|
||||||
if (Rand.Range(0.5f, 2.0f) < distort) pos.X = -pos.X;
|
if (Rand.Range(0.5f, 2.0f) < distort) { pos.X = -pos.X; }
|
||||||
if (Rand.Range(0.5f, 2.0f) < distort) pos.Y = -pos.Y;
|
if (Rand.Range(0.5f, 2.0f) < distort) { pos.Y = -pos.Y; }
|
||||||
|
|
||||||
float posDistSqr = pos.LengthSquared();
|
float posDistSqr = pos.LengthSquared();
|
||||||
if (posDistSqr > DisplayRadius * DisplayRadius)
|
if (posDistSqr > DisplayRadius * DisplayRadius)
|
||||||
@@ -1324,15 +1322,15 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
Vector2 dir = pos / (float)Math.Sqrt(posDistSqr);
|
Vector2 dir = pos / (float)Math.Sqrt(posDistSqr);
|
||||||
Vector2 normal = new Vector2(dir.Y, -dir.X);
|
Vector2 normal = new Vector2(dir.Y, -dir.X);
|
||||||
float scale = (strength + 3.0f) * blip.Scale * zoomSqrt;
|
float scale = (strength + 3.0f) * blip.Scale * blipScale;
|
||||||
Color color = ToolBox.GradientLerp(strength, blipColorGradient[blip.BlipType]);
|
Color color = ToolBox.GradientLerp(strength, blipColorGradient[blip.BlipType]);
|
||||||
|
|
||||||
sonarBlip.Draw(spriteBatch, center + pos, color, sonarBlip.Origin, blip.Rotation ?? MathUtils.VectorToAngle(pos),
|
sonarBlip.Draw(spriteBatch, center + pos, color, sonarBlip.Origin, blip.Rotation ?? MathUtils.VectorToAngle(pos),
|
||||||
blip.Size * scale * 0.04f, SpriteEffects.None, 0);
|
blip.Size * scale * 0.5f, SpriteEffects.None, 0);
|
||||||
|
|
||||||
pos += Rand.Range(0.0f, 1.0f) * dir + Rand.Range(-scale, scale) * normal;
|
pos += Rand.Range(0.0f, 1.0f) * dir + Rand.Range(-scale, scale) * normal;
|
||||||
|
|
||||||
sonarBlip.Draw(spriteBatch, center + pos, color * 0.5f, sonarBlip.Origin, 0, scale * 0.08f, SpriteEffects.None, 0);
|
sonarBlip.Draw(spriteBatch, center + pos, color * 0.5f, sonarBlip.Origin, 0, scale, SpriteEffects.None, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawMarker(SpriteBatch spriteBatch, string label, string iconIdentifier, object targetIdentifier, Vector2 worldPosition, Vector2 transducerPosition, float scale, Vector2 center, float radius)
|
private void DrawMarker(SpriteBatch spriteBatch, string label, string iconIdentifier, object targetIdentifier, Vector2 worldPosition, Vector2 transducerPosition, float scale, Vector2 center, float radius)
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ namespace Barotrauma.Items.Components
|
|||||||
LevelEnd,
|
LevelEnd,
|
||||||
LevelStart
|
LevelStart
|
||||||
};
|
};
|
||||||
|
|
||||||
private GUITickBox maintainPosTickBox, levelEndTickBox, levelStartTickBox;
|
private GUITickBox maintainPosTickBox, levelEndTickBox, levelStartTickBox;
|
||||||
|
|
||||||
private GUIComponent statusContainer, dockingContainer, controlContainer;
|
private GUIComponent statusContainer, dockingContainer, controlContainer;
|
||||||
@@ -349,20 +350,34 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
OnClicked = (btn, userdata) =>
|
OnClicked = (btn, userdata) =>
|
||||||
{
|
{
|
||||||
|
if (GameMain.GameSession?.Campaign is CampaignMode campaign)
|
||||||
if (GameMain.GameSession?.Campaign != null)
|
|
||||||
{
|
{
|
||||||
if (Level.IsLoadedOutpost &&
|
if (Level.IsLoadedOutpost &&
|
||||||
DockingSources.Any(d => d.Docked && (d.DockingTarget?.Item.Submarine?.Info?.IsOutpost ?? false)))
|
DockingSources.Any(d => d.Docked && (d.DockingTarget?.Item.Submarine?.Info?.IsOutpost ?? false)))
|
||||||
{
|
{
|
||||||
GameMain.GameSession.Campaign.CampaignUI.SelectTab(CampaignMode.InteractionType.Map);
|
// Undocking from an outpost
|
||||||
GameMain.GameSession.Campaign.ShowCampaignUI = true;
|
campaign.CampaignUI.SelectTab(CampaignMode.InteractionType.Map);
|
||||||
|
campaign.ShowCampaignUI = true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (!Level.IsLoadedOutpost && DockingModeEnabled && ActiveDockingSource != null &&
|
else if (!Level.IsLoadedOutpost && DockingModeEnabled && ActiveDockingSource != null &&
|
||||||
!ActiveDockingSource.Docked && (DockingTarget?.Item?.Submarine?.Info.IsOutpost ?? false))
|
!ActiveDockingSource.Docked && DockingTarget?.Item?.Submarine == Level.Loaded.StartOutpost && (DockingTarget?.Item?.Submarine?.Info.IsOutpost ?? false))
|
||||||
{
|
{
|
||||||
enterOutpostPrompt = new GUIMessageBox("", TextManager.GetWithVariable("campaignenteroutpostprompt", "[locationname]", DockingTarget.Item.Submarine.Info.Name), new string[] { TextManager.Get("yes"), TextManager.Get("no") });
|
// Docking to an outpost
|
||||||
|
var subsToLeaveBehind = campaign.GetSubsToLeaveBehind(Item.Submarine);
|
||||||
|
if (subsToLeaveBehind.Any())
|
||||||
|
{
|
||||||
|
enterOutpostPrompt = new GUIMessageBox(
|
||||||
|
TextManager.GetWithVariable("enterlocation", "[locationname]", DockingTarget.Item.Submarine.Info.Name),
|
||||||
|
TextManager.Get(subsToLeaveBehind.Count == 1 ? "LeaveSubBehind" : "LeaveSubsBehind"),
|
||||||
|
new string[] { TextManager.Get("yes"), TextManager.Get("no") });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
enterOutpostPrompt = new GUIMessageBox("",
|
||||||
|
TextManager.GetWithVariable("campaignenteroutpostprompt", "[locationname]", DockingTarget.Item.Submarine.Info.Name),
|
||||||
|
new string[] { TextManager.Get("yes"), TextManager.Get("no") });
|
||||||
|
}
|
||||||
enterOutpostPrompt.Buttons[0].OnClicked += (btn, userdata) =>
|
enterOutpostPrompt.Buttons[0].OnClicked += (btn, userdata) =>
|
||||||
{
|
{
|
||||||
SendDockingSignal();
|
SendDockingSignal();
|
||||||
@@ -780,10 +795,16 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
checkConnectedPortsTimer = CheckConnectedPortsInterval;
|
checkConnectedPortsTimer = CheckConnectedPortsInterval;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
checkConnectedPortsTimer -= deltaTime;
|
||||||
|
}
|
||||||
|
|
||||||
float closestDist = DockingAssistThreshold * DockingAssistThreshold;
|
|
||||||
DockingModeEnabled = false;
|
DockingModeEnabled = false;
|
||||||
|
|
||||||
|
if (connectedPorts.None()) { return; }
|
||||||
|
|
||||||
|
float closestDist = DockingAssistThreshold * DockingAssistThreshold;
|
||||||
foreach (DockingPort sourcePort in connectedPorts)
|
foreach (DockingPort sourcePort in connectedPorts)
|
||||||
{
|
{
|
||||||
if (sourcePort.Docked || sourcePort.Item.Submarine == null) { continue; }
|
if (sourcePort.Docked || sourcePort.Item.Submarine == null) { continue; }
|
||||||
@@ -795,15 +816,14 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
if (targetPort.Docked || targetPort.Item.Submarine == null) { continue; }
|
if (targetPort.Docked || targetPort.Item.Submarine == null) { continue; }
|
||||||
if (targetPort.Item.Submarine == controlledSub || targetPort.IsHorizontal != sourcePort.IsHorizontal) { continue; }
|
if (targetPort.Item.Submarine == controlledSub || targetPort.IsHorizontal != sourcePort.IsHorizontal) { continue; }
|
||||||
|
if (targetPort.Item.Submarine.DockedTo?.Contains(sourcePort.Item.Submarine) ?? false) { continue; }
|
||||||
if (Level.Loaded != null && targetPort.Item.Submarine.WorldPosition.Y > Level.Loaded.Size.Y) { continue; }
|
if (Level.Loaded != null && targetPort.Item.Submarine.WorldPosition.Y > Level.Loaded.Size.Y) { continue; }
|
||||||
|
if (sourceDir == targetPort.GetDir()) { continue; }
|
||||||
int targetDir = targetPort.GetDir();
|
|
||||||
|
|
||||||
if (sourceDir == targetDir) { continue; }
|
|
||||||
|
|
||||||
float dist = Vector2.DistanceSquared(sourcePort.Item.WorldPosition, targetPort.Item.WorldPosition);
|
float dist = Vector2.DistanceSquared(sourcePort.Item.WorldPosition, targetPort.Item.WorldPosition);
|
||||||
if (dist < closestDist)
|
if (dist < closestDist)
|
||||||
{
|
{
|
||||||
|
closestDist = dist;
|
||||||
DockingModeEnabled = true;
|
DockingModeEnabled = true;
|
||||||
ActiveDockingSource = sourcePort;
|
ActiveDockingSource = sourcePort;
|
||||||
DockingTarget = targetPort;
|
DockingTarget = targetPort;
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
|
||||||
|
namespace Barotrauma.Items.Components
|
||||||
|
{
|
||||||
|
internal partial class Planter
|
||||||
|
{
|
||||||
|
public Vector2 DrawSize => CalculateSize();
|
||||||
|
|
||||||
|
private Vector2 CalculateSize()
|
||||||
|
{
|
||||||
|
if (GrowableSeeds.All(s => s == null)) { return Vector2.Zero; }
|
||||||
|
|
||||||
|
Point pos = item.DrawPosition.ToPoint();
|
||||||
|
Rectangle rect = new Rectangle(pos, Point.Zero);
|
||||||
|
|
||||||
|
for (int i = 0; i < GrowableSeeds.Length; i++)
|
||||||
|
{
|
||||||
|
Growable seed = GrowableSeeds[i];
|
||||||
|
PlantSlot slot = PlantSlots.ContainsKey(i) ? PlantSlots[i] : NullSlot;
|
||||||
|
if (seed == null) { continue; }
|
||||||
|
|
||||||
|
foreach (VineTile vine in seed.Vines)
|
||||||
|
{
|
||||||
|
Rectangle worldRect = vine.Rect;
|
||||||
|
worldRect.Location += slot.Offset.ToPoint();
|
||||||
|
worldRect.Location += pos;
|
||||||
|
rect = Rectangle.Union(rect, worldRect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2 result = new Vector2(MaxDistance(pos.X, rect.Left, rect.Right) * 2, MaxDistance(pos.Y, rect.Top, rect.Bottom) * 2);
|
||||||
|
return result;
|
||||||
|
|
||||||
|
static float MaxDistance(float origin, float x, float y)
|
||||||
|
{
|
||||||
|
return Math.Max(Math.Abs(origin - x), Math.Abs(origin - y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private LightComponent lightComponent;
|
||||||
|
|
||||||
|
public void Draw(SpriteBatch spriteBatch, bool editing, float itemDepth = -1)
|
||||||
|
{
|
||||||
|
for (var i = 0; i < GrowableSeeds.Length; i++)
|
||||||
|
{
|
||||||
|
Growable growable = GrowableSeeds[i];
|
||||||
|
PlantSlot slot = PlantSlots.ContainsKey(i) ? PlantSlots[i] : NullSlot;
|
||||||
|
growable?.Draw(spriteBatch, this, slot.Offset, itemDepth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -29,6 +29,7 @@ namespace Barotrauma.Items.Components
|
|||||||
private List<Pair<RelatedItem, ParticleEmitter>> particleEmitterHitItem = new List<Pair<RelatedItem, ParticleEmitter>>();
|
private List<Pair<RelatedItem, ParticleEmitter>> particleEmitterHitItem = new List<Pair<RelatedItem, ParticleEmitter>>();
|
||||||
|
|
||||||
private float prevProgressBarState;
|
private float prevProgressBarState;
|
||||||
|
private Item prevProgressBarTarget = null;
|
||||||
|
|
||||||
partial void InitProjSpecific(XElement element)
|
partial void InitProjSpecific(XElement element)
|
||||||
{
|
{
|
||||||
@@ -65,7 +66,7 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
foreach (ParticleEmitter particleEmitter in particleEmitters)
|
foreach (ParticleEmitter particleEmitter in particleEmitters)
|
||||||
{
|
{
|
||||||
float particleAngle = item.body.Rotation + ((item.body.Dir > 0.0f) ? 0.0f : MathHelper.Pi);
|
float particleAngle = item.body.Rotation + MathHelper.ToRadians(BarrelRotation) + ((item.body.Dir > 0.0f) ? 0.0f : MathHelper.Pi);
|
||||||
particleEmitter.Emit(
|
particleEmitter.Emit(
|
||||||
deltaTime, ConvertUnits.ToDisplayUnits(raystart),
|
deltaTime, ConvertUnits.ToDisplayUnits(raystart),
|
||||||
item.CurrentHull, particleAngle, particleEmitter.Prefab.CopyEntityAngle ? -particleAngle : 0);
|
item.CurrentHull, particleAngle, particleEmitter.Prefab.CopyEntityAngle ? -particleAngle : 0);
|
||||||
@@ -92,7 +93,7 @@ namespace Barotrauma.Items.Components
|
|||||||
if (targetStructure.Submarine != null) particlePos += targetStructure.Submarine.DrawPosition;
|
if (targetStructure.Submarine != null) particlePos += targetStructure.Submarine.DrawPosition;
|
||||||
foreach (var emitter in particleEmitterHitStructure)
|
foreach (var emitter in particleEmitterHitStructure)
|
||||||
{
|
{
|
||||||
float particleAngle = item.body.Rotation + ((item.body.Dir > 0.0f) ? 0.0f : MathHelper.Pi);
|
float particleAngle = item.body.Rotation + MathHelper.ToRadians(BarrelRotation) + ((item.body.Dir > 0.0f) ? 0.0f : MathHelper.Pi);
|
||||||
emitter.Emit(deltaTime, particlePos, item.CurrentHull, particleAngle + MathHelper.Pi, -particleAngle + MathHelper.Pi);
|
emitter.Emit(deltaTime, particlePos, item.CurrentHull, particleAngle + MathHelper.Pi, -particleAngle + MathHelper.Pi);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -103,7 +104,7 @@ namespace Barotrauma.Items.Components
|
|||||||
if (targetCharacter.Submarine != null) particlePos += targetCharacter.Submarine.DrawPosition;
|
if (targetCharacter.Submarine != null) particlePos += targetCharacter.Submarine.DrawPosition;
|
||||||
foreach (var emitter in particleEmitterHitCharacter)
|
foreach (var emitter in particleEmitterHitCharacter)
|
||||||
{
|
{
|
||||||
float particleAngle = item.body.Rotation + ((item.body.Dir > 0.0f) ? 0.0f : MathHelper.Pi);
|
float particleAngle = item.body.Rotation + MathHelper.ToRadians(BarrelRotation) + ((item.body.Dir > 0.0f) ? 0.0f : MathHelper.Pi);
|
||||||
emitter.Emit(deltaTime, particlePos, item.CurrentHull, particleAngle + MathHelper.Pi, -particleAngle + MathHelper.Pi);
|
emitter.Emit(deltaTime, particlePos, item.CurrentHull, particleAngle + MathHelper.Pi, -particleAngle + MathHelper.Pi);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -111,7 +112,7 @@ namespace Barotrauma.Items.Components
|
|||||||
partial void FixItemProjSpecific(Character user, float deltaTime, Item targetItem)
|
partial void FixItemProjSpecific(Character user, float deltaTime, Item targetItem)
|
||||||
{
|
{
|
||||||
float progressBarState = targetItem.ConditionPercentage / 100.0f;
|
float progressBarState = targetItem.ConditionPercentage / 100.0f;
|
||||||
if (!MathUtils.NearlyEqual(progressBarState, prevProgressBarState))
|
if (!MathUtils.NearlyEqual(progressBarState, prevProgressBarState) || prevProgressBarTarget != targetItem)
|
||||||
{
|
{
|
||||||
var door = targetItem.GetComponent<Door>();
|
var door = targetItem.GetComponent<Door>();
|
||||||
if (door == null || door.Stuck <= 0)
|
if (door == null || door.Stuck <= 0)
|
||||||
@@ -121,18 +122,20 @@ namespace Barotrauma.Items.Components
|
|||||||
targetItem,
|
targetItem,
|
||||||
progressBarPos,
|
progressBarPos,
|
||||||
progressBarState,
|
progressBarState,
|
||||||
GUI.Style.Red, GUI.Style.Green);
|
GUI.Style.Red, GUI.Style.Green,
|
||||||
|
progressBarState < prevProgressBarState ? "progressbar.cutting" : "");
|
||||||
if (progressBar != null) { progressBar.Size = new Vector2(60.0f, 20.0f); }
|
if (progressBar != null) { progressBar.Size = new Vector2(60.0f, 20.0f); }
|
||||||
}
|
}
|
||||||
prevProgressBarState = progressBarState;
|
prevProgressBarState = progressBarState;
|
||||||
|
prevProgressBarTarget = targetItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector2 particlePos = ConvertUnits.ToDisplayUnits(pickedPosition);
|
Vector2 particlePos = ConvertUnits.ToDisplayUnits(pickedPosition);
|
||||||
if (targetItem.Submarine != null) particlePos += targetItem.Submarine.DrawPosition;
|
if (targetItem.Submarine != null) particlePos += targetItem.Submarine.DrawPosition;
|
||||||
foreach (var emitter in particleEmitterHitItem)
|
foreach (var emitter in particleEmitterHitItem)
|
||||||
{
|
{
|
||||||
if (!emitter.First.MatchesItem(targetItem)) continue;
|
if (!emitter.First.MatchesItem(targetItem)) { continue; }
|
||||||
float particleAngle = item.body.Rotation + ((item.body.Dir > 0.0f) ? 0.0f : MathHelper.Pi);
|
float particleAngle = item.body.Rotation + MathHelper.ToRadians(BarrelRotation) + ((item.body.Dir > 0.0f) ? 0.0f : MathHelper.Pi);
|
||||||
emitter.Second.Emit(deltaTime, particlePos, item.CurrentHull, particleAngle + MathHelper.Pi, -particleAngle + MathHelper.Pi);
|
emitter.Second.Emit(deltaTime, particlePos, item.CurrentHull, particleAngle + MathHelper.Pi, -particleAngle + MathHelper.Pi);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -192,6 +192,7 @@ namespace Barotrauma.Items.Components
|
|||||||
foreach (Wire wire in panel.DisconnectedWires)
|
foreach (Wire wire in panel.DisconnectedWires)
|
||||||
{
|
{
|
||||||
if (wire == DraggingConnected && mouseInRect) { continue; }
|
if (wire == DraggingConnected && mouseInRect) { continue; }
|
||||||
|
if (wire.HiddenInGame && Screen.Selected == GameMain.GameScreen) { continue; }
|
||||||
|
|
||||||
Connection recipient = wire.OtherConnection(null);
|
Connection recipient = wire.OtherConnection(null);
|
||||||
string label = recipient == null ? "" : recipient.item.Name + $" ({recipient.DisplayName})";
|
string label = recipient == null ? "" : recipient.item.Name + $" ({recipient.DisplayName})";
|
||||||
@@ -238,6 +239,7 @@ namespace Barotrauma.Items.Components
|
|||||||
for (int i = 0; i < MaxLinked; i++)
|
for (int i = 0; i < MaxLinked; i++)
|
||||||
{
|
{
|
||||||
if (wires[i] == null || wires[i].Hidden || (DraggingConnected == wires[i] && (mouseIn || Screen.Selected == GameMain.SubEditorScreen))) { continue; }
|
if (wires[i] == null || wires[i].Hidden || (DraggingConnected == wires[i] && (mouseIn || Screen.Selected == GameMain.SubEditorScreen))) { continue; }
|
||||||
|
if (wires[i].HiddenInGame && Screen.Selected == GameMain.GameScreen) { continue; }
|
||||||
|
|
||||||
Connection recipient = wires[i].OtherConnection(this);
|
Connection recipient = wires[i].OtherConnection(this);
|
||||||
string label = recipient == null ? "" : recipient.item.Name + $" ({recipient.DisplayName})";
|
string label = recipient == null ? "" : recipient.item.Name + $" ({recipient.DisplayName})";
|
||||||
@@ -289,7 +291,7 @@ namespace Barotrauma.Items.Components
|
|||||||
flashColor * (float)Math.Sin(FlashTimer % flashCycleDuration / flashCycleDuration * MathHelper.Pi * 0.8f), scale: connectorSpriteScale);
|
flashColor * (float)Math.Sin(FlashTimer % flashCycleDuration / flashCycleDuration * MathHelper.Pi * 0.8f), scale: connectorSpriteScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Wires.Any(w => w != null && w != DraggingConnected && !w.Hidden))
|
if (Wires.Any(w => w != null && w != DraggingConnected && !w.Hidden && (!w.HiddenInGame || Screen.Selected != GameMain.GameScreen)))
|
||||||
{
|
{
|
||||||
int screwIndex = (int)Math.Floor(position.Y / 30.0f) % screwSprites.Count;
|
int screwIndex = (int)Math.Floor(position.Y / 30.0f) % screwSprites.Count;
|
||||||
screwSprites[screwIndex].Draw(spriteBatch, position, scale: connectorSpriteScale);
|
screwSprites[screwIndex].Draw(spriteBatch, position, scale: connectorSpriteScale);
|
||||||
@@ -325,7 +327,7 @@ namespace Barotrauma.Items.Components
|
|||||||
canDrag &&
|
canDrag &&
|
||||||
((PlayerInput.MousePosition.X > Math.Min(start.X, end.X) &&
|
((PlayerInput.MousePosition.X > Math.Min(start.X, end.X) &&
|
||||||
PlayerInput.MousePosition.X < Math.Max(start.X, end.X) &&
|
PlayerInput.MousePosition.X < Math.Max(start.X, end.X) &&
|
||||||
MathUtils.LineToPointDistance(start, end, PlayerInput.MousePosition) < 6) ||
|
MathUtils.LineToPointDistanceSquared(start, end, PlayerInput.MousePosition) < 36) ||
|
||||||
Vector2.Distance(end, PlayerInput.MousePosition) < 20.0f ||
|
Vector2.Distance(end, PlayerInput.MousePosition) < 20.0f ||
|
||||||
new Rectangle((start.X < end.X) ? textX - 100 : textX, (int)start.Y - 5, 100, 14).Contains(PlayerInput.MousePosition));
|
new Rectangle((start.X < end.X) ? textX - 100 : textX, (int)start.Y - 5, 100, 14).Contains(PlayerInput.MousePosition));
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
using Barotrauma.Networking;
|
||||||
|
|
||||||
|
namespace Barotrauma.Items.Components
|
||||||
|
{
|
||||||
|
partial class MemoryComponent : ItemComponent
|
||||||
|
{
|
||||||
|
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
||||||
|
{
|
||||||
|
Value = msg.ReadString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -165,6 +165,12 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (!string.IsNullOrEmpty(target.customInteractHUDText) && target.AllowCustomInteract)
|
||||||
|
{
|
||||||
|
texts.Add(target.customInteractHUDText);
|
||||||
|
textColors.Add(GUI.Style.Green);
|
||||||
|
}
|
||||||
|
|
||||||
if (target.IsUnconscious)
|
if (target.IsUnconscious)
|
||||||
{
|
{
|
||||||
texts.Add(TextManager.Get("Unconscious"));
|
texts.Add(TextManager.Get("Unconscious"));
|
||||||
|
|||||||
@@ -17,6 +17,17 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
private GUIProgressBar powerIndicator;
|
private GUIProgressBar powerIndicator;
|
||||||
|
|
||||||
|
public int UIElementHeight
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
int height = 0;
|
||||||
|
if (ShowChargeIndicator) { height += powerIndicator.Rect.Height; }
|
||||||
|
if (ShowProjectileIndicator) { height += (int)(Inventory.SlotSpriteSmall.size.Y * Inventory.UIScale) + 5; }
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private float recoilTimer;
|
private float recoilTimer;
|
||||||
|
|
||||||
private float RetractionTime => Math.Max(Reload * RetractionDurationMultiplier, RecoilTime);
|
private float RetractionTime => Math.Max(Reload * RetractionDurationMultiplier, RecoilTime);
|
||||||
@@ -235,12 +246,11 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
public void Draw(SpriteBatch spriteBatch, bool editing = false, float itemDepth = -1)
|
public void Draw(SpriteBatch spriteBatch, bool editing = false, float itemDepth = -1)
|
||||||
{
|
{
|
||||||
Vector2 drawPos = new Vector2(item.Rect.X + transformedBarrelPos.X, item.Rect.Y - transformedBarrelPos.Y);
|
if (!MathUtils.NearlyEqual(item.Rotation, prevBaseRotation))
|
||||||
if (item.Submarine != null)
|
|
||||||
{
|
{
|
||||||
drawPos += item.Submarine.DrawPosition;
|
UpdateTransformedBarrelPos();
|
||||||
}
|
}
|
||||||
drawPos.Y = -drawPos.Y;
|
Vector2 drawPos = GetDrawPos();
|
||||||
|
|
||||||
float recoilOffset = 0.0f;
|
float recoilOffset = 0.0f;
|
||||||
if (Math.Abs(RecoilDistance) > 0.0f && recoilTimer > 0.0f)
|
if (Math.Abs(RecoilDistance) > 0.0f && recoilTimer > 0.0f)
|
||||||
@@ -275,7 +285,7 @@ namespace Barotrauma.Items.Components
|
|||||||
rotation + MathHelper.PiOver2, item.Scale,
|
rotation + MathHelper.PiOver2, item.Scale,
|
||||||
SpriteEffects.None, item.SpriteDepth + (barrelSprite.Depth - item.Sprite.Depth));
|
SpriteEffects.None, item.SpriteDepth + (barrelSprite.Depth - item.Sprite.Depth));
|
||||||
|
|
||||||
if (!editing) { return; }
|
if (!editing || GUI.DisableHUD) { return; }
|
||||||
|
|
||||||
float widgetRadius = 60.0f;
|
float widgetRadius = 60.0f;
|
||||||
|
|
||||||
@@ -310,7 +320,7 @@ namespace Barotrauma.Items.Components
|
|||||||
};
|
};
|
||||||
widget.MouseHeld += (deltaTime) =>
|
widget.MouseHeld += (deltaTime) =>
|
||||||
{
|
{
|
||||||
minRotation = GetRotationAngle(drawPos);
|
minRotation = GetRotationAngle(GetDrawPos());
|
||||||
if (minRotation > maxRotation)
|
if (minRotation > maxRotation)
|
||||||
{
|
{
|
||||||
float temp = minRotation;
|
float temp = minRotation;
|
||||||
@@ -332,7 +342,7 @@ namespace Barotrauma.Items.Components
|
|||||||
widget.PreDraw += (sprtBtch, deltaTime) =>
|
widget.PreDraw += (sprtBtch, deltaTime) =>
|
||||||
{
|
{
|
||||||
widget.tooltip = "Min: " + (int)MathHelper.ToDegrees(minRotation);
|
widget.tooltip = "Min: " + (int)MathHelper.ToDegrees(minRotation);
|
||||||
widget.DrawPos = drawPos + new Vector2((float)Math.Cos(minRotation), (float)Math.Sin(minRotation)) * widgetRadius;
|
widget.DrawPos = GetDrawPos() + new Vector2((float)Math.Cos(minRotation), (float)Math.Sin(minRotation)) * widgetRadius;
|
||||||
widget.Update(deltaTime);
|
widget.Update(deltaTime);
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
@@ -351,7 +361,7 @@ namespace Barotrauma.Items.Components
|
|||||||
};
|
};
|
||||||
widget.MouseHeld += (deltaTime) =>
|
widget.MouseHeld += (deltaTime) =>
|
||||||
{
|
{
|
||||||
maxRotation = GetRotationAngle(drawPos);
|
maxRotation = GetRotationAngle(GetDrawPos());
|
||||||
if (minRotation > maxRotation)
|
if (minRotation > maxRotation)
|
||||||
{
|
{
|
||||||
float temp = minRotation;
|
float temp = minRotation;
|
||||||
@@ -373,12 +383,20 @@ namespace Barotrauma.Items.Components
|
|||||||
widget.PreDraw += (sprtBtch, deltaTime) =>
|
widget.PreDraw += (sprtBtch, deltaTime) =>
|
||||||
{
|
{
|
||||||
widget.tooltip = "Max: " + (int)MathHelper.ToDegrees(maxRotation);
|
widget.tooltip = "Max: " + (int)MathHelper.ToDegrees(maxRotation);
|
||||||
widget.DrawPos = drawPos + new Vector2((float)Math.Cos(maxRotation), (float)Math.Sin(maxRotation)) * widgetRadius;
|
widget.DrawPos = GetDrawPos() + new Vector2((float)Math.Cos(maxRotation), (float)Math.Sin(maxRotation)) * widgetRadius;
|
||||||
widget.Update(deltaTime);
|
widget.Update(deltaTime);
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
minRotationWidget.Draw(spriteBatch, (float)Timing.Step);
|
minRotationWidget.Draw(spriteBatch, (float)Timing.Step);
|
||||||
maxRotationWidget.Draw(spriteBatch, (float)Timing.Step);
|
maxRotationWidget.Draw(spriteBatch, (float)Timing.Step);
|
||||||
|
|
||||||
|
Vector2 GetDrawPos()
|
||||||
|
{
|
||||||
|
Vector2 drawPos = new Vector2(item.Rect.X + transformedBarrelPos.X, item.Rect.Y - transformedBarrelPos.Y);
|
||||||
|
if (item.Submarine != null) { drawPos += item.Submarine.DrawPosition; }
|
||||||
|
drawPos.Y = -drawPos.Y;
|
||||||
|
return drawPos;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Widget GetWidget(string id, SpriteBatch spriteBatch, int size = 5, Action<Widget> initMethod = null)
|
private Widget GetWidget(string id, SpriteBatch spriteBatch, int size = 5, Action<Widget> initMethod = null)
|
||||||
|
|||||||
@@ -715,7 +715,12 @@ namespace Barotrauma
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static bool IsMouseOnInventory(bool ignoreDraggedItem = false)
|
public static bool IsMouseOnInventory(bool ignoreDraggedItem = false)
|
||||||
{
|
{
|
||||||
var isSubEditor = Screen.Selected is SubEditorScreen editor && !editor.WiringMode;
|
if (GameMain.GameSession?.Campaign != null &&
|
||||||
|
(GameMain.GameSession.Campaign.ShowCampaignUI || GameMain.GameSession.Campaign.ForceMapUI))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (Character.Controlled == null) { return false; }
|
if (Character.Controlled == null) { return false; }
|
||||||
|
|
||||||
if (!ignoreDraggedItem)
|
if (!ignoreDraggedItem)
|
||||||
@@ -723,6 +728,8 @@ namespace Barotrauma
|
|||||||
if (draggingItem != null || DraggingInventory != null) { return true; }
|
if (draggingItem != null || DraggingInventory != null) { return true; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var isSubEditor = Screen.Selected is SubEditorScreen editor && !editor.WiringMode;
|
||||||
|
|
||||||
if (Character.Controlled.Inventory != null && !isSubEditor)
|
if (Character.Controlled.Inventory != null && !isSubEditor)
|
||||||
{
|
{
|
||||||
var inv = Character.Controlled.Inventory;
|
var inv = Character.Controlled.Inventory;
|
||||||
@@ -840,7 +847,8 @@ namespace Barotrauma
|
|||||||
foreach (var ic in character.SelectedConstruction.ActiveHUDs)
|
foreach (var ic in character.SelectedConstruction.ActiveHUDs)
|
||||||
{
|
{
|
||||||
var itemContainer = ic as ItemContainer;
|
var itemContainer = ic as ItemContainer;
|
||||||
if (itemContainer?.Inventory?.slots == null) continue;
|
if (itemContainer?.Inventory?.slots == null) { continue; }
|
||||||
|
if (ic.Item.NonInteractable) { continue; }
|
||||||
|
|
||||||
foreach (var slot in itemContainer.Inventory.slots)
|
foreach (var slot in itemContainer.Inventory.slots)
|
||||||
{
|
{
|
||||||
@@ -1127,7 +1135,6 @@ namespace Barotrauma
|
|||||||
return hoverArea;
|
return hoverArea;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static void DrawFront(SpriteBatch spriteBatch)
|
public static void DrawFront(SpriteBatch spriteBatch)
|
||||||
{
|
{
|
||||||
if (GUI.PauseMenuOpen || GUI.SettingsMenuOpen) { return; }
|
if (GUI.PauseMenuOpen || GUI.SettingsMenuOpen) { return; }
|
||||||
@@ -1202,6 +1209,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
Color slotColor = Color.White;
|
Color slotColor = Color.White;
|
||||||
|
if ((inventory?.Owner as Item)?.NonInteractable ?? false) { slotColor = Color.Gray; }
|
||||||
var itemContainer = item?.GetComponent<ItemContainer>();
|
var itemContainer = item?.GetComponent<ItemContainer>();
|
||||||
if (itemContainer != null && (itemContainer.InventoryTopSprite != null || itemContainer.InventoryBottomSprite != null))
|
if (itemContainer != null && (itemContainer.InventoryTopSprite != null || itemContainer.InventoryBottomSprite != null))
|
||||||
{
|
{
|
||||||
@@ -1470,18 +1478,19 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (receivedItemIDs[i] == 0 || (Entity.FindEntityByID(receivedItemIDs[i]) as Item != Items[i]))
|
if (receivedItemIDs[i] == 0 || (Entity.FindEntityByID(receivedItemIDs[i]) as Item != Items[i]))
|
||||||
{
|
{
|
||||||
if (Items[i] != null) Items[i].Drop(null);
|
Items[i]?.Drop(null);
|
||||||
System.Diagnostics.Debug.Assert(Items[i] == null);
|
System.Diagnostics.Debug.Assert(Items[i] == null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < capacity; i++)
|
//iterate backwards to get the item to the Any slots first
|
||||||
|
for (int i = capacity - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
if (receivedItemIDs[i] > 0)
|
if (receivedItemIDs[i] > 0)
|
||||||
{
|
{
|
||||||
if (!(Entity.FindEntityByID(receivedItemIDs[i]) is Item item) || Items[i] == item) { continue; }
|
if (!(Entity.FindEntityByID(receivedItemIDs[i]) is Item item) || Items[i] == item) { continue; }
|
||||||
|
|
||||||
TryPutItem(item, i, true, true, null, false);
|
TryPutItem(item, i, false, false, null, false);
|
||||||
for (int j = 0; j < capacity; j++)
|
for (int j = 0; j < capacity; j++)
|
||||||
{
|
{
|
||||||
if (Items[j] == item && receivedItemIDs[j] != item.ID)
|
if (Items[j] == item && receivedItemIDs[j] != item.ID)
|
||||||
|
|||||||
@@ -92,8 +92,6 @@ namespace Barotrauma
|
|||||||
return parentInventory == null && (body == null || body.Enabled) && ShowItems;
|
return parentInventory == null && (body == null || body.Enabled) && ShowItems;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public float SpriteRotation;
|
|
||||||
|
|
||||||
public Color GetSpriteColor()
|
public Color GetSpriteColor()
|
||||||
{
|
{
|
||||||
@@ -297,7 +295,7 @@ namespace Barotrauma
|
|||||||
foreach (var decorativeSprite in Prefab.DecorativeSprites)
|
foreach (var decorativeSprite in Prefab.DecorativeSprites)
|
||||||
{
|
{
|
||||||
if (!spriteAnimState[decorativeSprite].IsActive) { continue; }
|
if (!spriteAnimState[decorativeSprite].IsActive) { continue; }
|
||||||
Vector2 offset = decorativeSprite.GetOffset(ref spriteAnimState[decorativeSprite].OffsetState) * Scale;
|
Vector2 offset = decorativeSprite.GetOffset(ref spriteAnimState[decorativeSprite].OffsetState, -rotationRad) * Scale;
|
||||||
decorativeSprite.Sprite.DrawTiled(spriteBatch,
|
decorativeSprite.Sprite.DrawTiled(spriteBatch,
|
||||||
new Vector2(DrawPosition.X + offset.X - rect.Width / 2, -(DrawPosition.Y + offset.Y + rect.Height / 2)),
|
new Vector2(DrawPosition.X + offset.X - rect.Width / 2, -(DrawPosition.Y + offset.Y + rect.Height / 2)),
|
||||||
size, color: color,
|
size, color: color,
|
||||||
@@ -307,15 +305,24 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
activeSprite.Draw(spriteBatch, new Vector2(DrawPosition.X, -DrawPosition.Y) + drawOffset, color, SpriteRotation + rotation, Scale, activeSprite.effects, depth);
|
Vector2 origin = activeSprite.Origin;
|
||||||
fadeInBrokenSprite?.Sprite.Draw(spriteBatch, new Vector2(DrawPosition.X, -DrawPosition.Y) + fadeInBrokenSprite.Offset.ToVector2() * Scale, color * fadeInBrokenSpriteAlpha, SpriteRotation + rotation, Scale, activeSprite.effects, depth - 0.000001f);
|
if ((activeSprite.effects & SpriteEffects.FlipHorizontally) == SpriteEffects.FlipHorizontally)
|
||||||
|
{
|
||||||
|
origin.X = activeSprite.SourceRect.Width - origin.X;
|
||||||
|
}
|
||||||
|
if ((activeSprite.effects & SpriteEffects.FlipVertically) == SpriteEffects.FlipVertically)
|
||||||
|
{
|
||||||
|
origin.Y = activeSprite.SourceRect.Height - origin.Y;
|
||||||
|
}
|
||||||
|
activeSprite.Draw(spriteBatch, new Vector2(DrawPosition.X, -DrawPosition.Y) + drawOffset, color, origin, rotationRad, Scale, activeSprite.effects, depth);
|
||||||
|
fadeInBrokenSprite?.Sprite.Draw(spriteBatch, new Vector2(DrawPosition.X, -DrawPosition.Y) + fadeInBrokenSprite.Offset.ToVector2() * Scale, color * fadeInBrokenSpriteAlpha, origin, rotationRad, Scale, activeSprite.effects, depth - 0.000001f);
|
||||||
foreach (var decorativeSprite in Prefab.DecorativeSprites)
|
foreach (var decorativeSprite in Prefab.DecorativeSprites)
|
||||||
{
|
{
|
||||||
if (!spriteAnimState[decorativeSprite].IsActive) { continue; }
|
if (!spriteAnimState[decorativeSprite].IsActive) { continue; }
|
||||||
float rot = decorativeSprite.GetRotation(ref spriteAnimState[decorativeSprite].RotationState);
|
float rot = decorativeSprite.GetRotation(ref spriteAnimState[decorativeSprite].RotationState);
|
||||||
Vector2 offset = decorativeSprite.GetOffset(ref spriteAnimState[decorativeSprite].OffsetState) * Scale;
|
Vector2 offset = decorativeSprite.GetOffset(ref spriteAnimState[decorativeSprite].OffsetState, -rotationRad) * Scale;
|
||||||
decorativeSprite.Sprite.Draw(spriteBatch, new Vector2(DrawPosition.X + offset.X, -(DrawPosition.Y + offset.Y)), color,
|
decorativeSprite.Sprite.Draw(spriteBatch, new Vector2(DrawPosition.X + offset.X, -(DrawPosition.Y + offset.Y)), color,
|
||||||
SpriteRotation + rotation + rot, decorativeSprite.Scale * Scale, activeSprite.effects,
|
rotationRad + rot, decorativeSprite.Scale * Scale, activeSprite.effects,
|
||||||
depth: Math.Min(depth + (decorativeSprite.Sprite.Depth - activeSprite.Depth), 0.999f));
|
depth: Math.Min(depth + (decorativeSprite.Sprite.Depth - activeSprite.Depth), 0.999f));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -358,7 +365,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (!spriteAnimState[decorativeSprite].IsActive) { continue; }
|
if (!spriteAnimState[decorativeSprite].IsActive) { continue; }
|
||||||
float rotation = decorativeSprite.GetRotation(ref spriteAnimState[decorativeSprite].RotationState);
|
float rotation = decorativeSprite.GetRotation(ref spriteAnimState[decorativeSprite].RotationState);
|
||||||
Vector2 offset = decorativeSprite.GetOffset(ref spriteAnimState[decorativeSprite].OffsetState) * Scale;
|
Vector2 offset = decorativeSprite.GetOffset(ref spriteAnimState[decorativeSprite].OffsetState, -rotationRad) * Scale;
|
||||||
|
|
||||||
var ca = (float)Math.Cos(-body.Rotation);
|
var ca = (float)Math.Cos(-body.Rotation);
|
||||||
var sa = (float)Math.Sin(-body.Rotation);
|
var sa = (float)Math.Sin(-body.Rotation);
|
||||||
@@ -378,7 +385,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (!spriteAnimState[decorativeSprite].IsActive) { continue; }
|
if (!spriteAnimState[decorativeSprite].IsActive) { continue; }
|
||||||
float rotation = decorativeSprite.GetRotation(ref spriteAnimState[decorativeSprite].RotationState);
|
float rotation = decorativeSprite.GetRotation(ref spriteAnimState[decorativeSprite].RotationState);
|
||||||
var (xOff, yOff) = decorativeSprite.GetOffset(ref spriteAnimState[decorativeSprite].OffsetState) * Scale;
|
var (xOff, yOff) = decorativeSprite.GetOffset(ref spriteAnimState[decorativeSprite].OffsetState, -rotationRad) * Scale;
|
||||||
|
|
||||||
decorativeSprite.Sprite.Draw(spriteBatch, new Vector2(DrawPosition.X + xOff, -(DrawPosition.Y + yOff)), color,
|
decorativeSprite.Sprite.Draw(spriteBatch, new Vector2(DrawPosition.X + xOff, -(DrawPosition.Y + yOff)), color,
|
||||||
rotation, decorativeSprite.Scale * Scale, activeSprite.effects,
|
rotation, decorativeSprite.Scale * Scale, activeSprite.effects,
|
||||||
@@ -437,7 +444,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ShowLinks) return;
|
if (!ShowLinks || GUI.DisableHUD) { return; }
|
||||||
|
|
||||||
foreach (MapEntity e in linkedTo)
|
foreach (MapEntity e in linkedTo)
|
||||||
{
|
{
|
||||||
@@ -455,21 +462,6 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawDecorativeSprite(SpriteBatch spriteBatch, DecorativeSprite decorativeSprite, Color color, float depth)
|
|
||||||
{
|
|
||||||
if (!spriteAnimState[decorativeSprite].IsActive) { return; }
|
|
||||||
float rotation = decorativeSprite.GetRotation(ref spriteAnimState[decorativeSprite].RotationState);
|
|
||||||
Vector2 offset = decorativeSprite.GetOffset(ref spriteAnimState[decorativeSprite].OffsetState) * Scale;
|
|
||||||
|
|
||||||
var ca = (float)Math.Cos(-body.Rotation);
|
|
||||||
var sa = (float)Math.Sin(-body.Rotation);
|
|
||||||
Vector2 transformedOffset = new Vector2(ca * offset.X + sa * offset.Y, -sa * offset.X + ca * offset.Y);
|
|
||||||
|
|
||||||
decorativeSprite.Sprite.Draw(spriteBatch, new Vector2(DrawPosition.X + transformedOffset.X, -(DrawPosition.Y + transformedOffset.Y)), color,
|
|
||||||
-body.Rotation + rotation, decorativeSprite.Scale * Scale, activeSprite.effects,
|
|
||||||
depth: depth + (decorativeSprite.Sprite.Depth - activeSprite.Depth));
|
|
||||||
}
|
|
||||||
|
|
||||||
partial void OnCollisionProjSpecific(float impact)
|
partial void OnCollisionProjSpecific(float impact)
|
||||||
{
|
{
|
||||||
if (impact > 1.0f &&
|
if (impact > 1.0f &&
|
||||||
@@ -512,7 +504,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (Screen.Selected != GameMain.SubEditorScreen) { return; }
|
if (Screen.Selected != GameMain.SubEditorScreen) { return; }
|
||||||
|
|
||||||
if (Character.Controlled == null) { activeHUDs.Clear(); }
|
if (Character.Controlled == null) { activeHUDs.Clear(); }
|
||||||
|
|
||||||
if (!Linkable) { return; }
|
if (!Linkable) { return; }
|
||||||
@@ -1154,7 +1146,6 @@ namespace Barotrauma
|
|||||||
editingHUDRefreshPending = true;
|
editingHUDRefreshPending = true;
|
||||||
break;
|
break;
|
||||||
case NetEntityEvent.Type.Upgrade:
|
case NetEntityEvent.Type.Upgrade:
|
||||||
{
|
|
||||||
string identifier = msg.ReadString();
|
string identifier = msg.ReadString();
|
||||||
byte level = msg.ReadByte();
|
byte level = msg.ReadByte();
|
||||||
if (UpgradePrefab.Find(identifier) is { } upgradePrefab)
|
if (UpgradePrefab.Find(identifier) is { } upgradePrefab)
|
||||||
@@ -1174,8 +1165,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
AddUpgrade(upgrade, false);
|
AddUpgrade(upgrade, false);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case NetEntityEvent.Type.Invalid:
|
case NetEntityEvent.Type.Invalid:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1391,7 +1381,7 @@ namespace Barotrauma
|
|||||||
if (itemPrefab == null)
|
if (itemPrefab == null)
|
||||||
{
|
{
|
||||||
string errorMsg = "Failed to spawn item, prefab not found (name: " + (itemName ?? "null") + ", identifier: " + (itemIdentifier ?? "null") + ")";
|
string errorMsg = "Failed to spawn item, prefab not found (name: " + (itemName ?? "null") + ", identifier: " + (itemIdentifier ?? "null") + ")";
|
||||||
errorMsg += "\n" + string.Join(", ", GameMain.Config.SelectedContentPackages.Select(cp => cp.Name));
|
errorMsg += "\n" + string.Join(", ", GameMain.Config.AllEnabledPackages.Select(cp => cp.Name));
|
||||||
GameAnalyticsManager.AddErrorEventOnce("Item.ReadSpawnData:PrefabNotFound" + (itemName ?? "null") + (itemIdentifier ?? "null"),
|
GameAnalyticsManager.AddErrorEventOnce("Item.ReadSpawnData:PrefabNotFound" + (itemName ?? "null") + (itemIdentifier ?? "null"),
|
||||||
GameAnalyticsSDK.Net.EGAErrorSeverity.Critical,
|
GameAnalyticsSDK.Net.EGAErrorSeverity.Critical,
|
||||||
errorMsg);
|
errorMsg);
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ namespace Barotrauma
|
|||||||
public List<ContainedItemSprite> ContainedSprites = new List<ContainedItemSprite>();
|
public List<ContainedItemSprite> ContainedSprites = new List<ContainedItemSprite>();
|
||||||
public Dictionary<int, List<DecorativeSprite>> DecorativeSpriteGroups = new Dictionary<int, List<DecorativeSprite>>();
|
public Dictionary<int, List<DecorativeSprite>> DecorativeSpriteGroups = new Dictionary<int, List<DecorativeSprite>>();
|
||||||
public Sprite InventoryIcon;
|
public Sprite InventoryIcon;
|
||||||
|
public Sprite MinimapIcon;
|
||||||
|
|
||||||
//only used to display correct color in the sub editor, item instances have their own property that can be edited on a per-item basis
|
//only used to display correct color in the sub editor, item instances have their own property that can be edited on a per-item basis
|
||||||
[Serialize("1.0,1.0,1.0,1.0", false)]
|
[Serialize("1.0,1.0,1.0,1.0", false)]
|
||||||
@@ -90,6 +91,7 @@ namespace Barotrauma
|
|||||||
};
|
};
|
||||||
item.SetTransform(ConvertUnits.ToSimUnits(Submarine.MainSub == null ? item.Position : item.Position - Submarine.MainSub.Position), 0.0f);
|
item.SetTransform(ConvertUnits.ToSimUnits(Submarine.MainSub == null ? item.Position : item.Position - Submarine.MainSub.Position), 0.0f);
|
||||||
item.FindHull();
|
item.FindHull();
|
||||||
|
item.Submarine = Submarine.MainSub;
|
||||||
|
|
||||||
if (PlayerInput.IsShiftDown())
|
if (PlayerInput.IsShiftDown())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ namespace Barotrauma
|
|||||||
Vector2.Zero, 0.0f, hull);
|
Vector2.Zero, 0.0f, hull);
|
||||||
}
|
}
|
||||||
|
|
||||||
hull = hull ?? Hull.FindHull(worldPosition, useWorldCoordinates: true);
|
hull ??= Hull.FindHull(worldPosition, useWorldCoordinates: true);
|
||||||
bool underwater = hull == null || worldPosition.Y < hull.WorldSurface;
|
bool underwater = hull == null || worldPosition.Y < hull.WorldSurface;
|
||||||
|
|
||||||
if (underwater && underwaterBubble)
|
if (underwater && underwaterBubble)
|
||||||
@@ -44,7 +44,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
if (smoke)
|
if (smoke)
|
||||||
{
|
{
|
||||||
var smokeParticle = GameMain.ParticleManager.CreateParticle(Rand.Range(0.0f, 1.0f) < 0.5f ? "explosionsmoke" : "smoke",
|
GameMain.ParticleManager.CreateParticle(Rand.Range(0.0f, 1.0f) < 0.5f ? "explosionsmoke" : "smoke",
|
||||||
ClampParticlePos(worldPosition + Rand.Vector((float)System.Math.Sqrt(Rand.Range(0.0f, attack.Range))), hull),
|
ClampParticlePos(worldPosition + Rand.Vector((float)System.Math.Sqrt(Rand.Range(0.0f, attack.Range))), hull),
|
||||||
Rand.Vector(Rand.Range(0.0f, particleSpeed)), 0.0f, hull);
|
Rand.Vector(Rand.Range(0.0f, particleSpeed)), 0.0f, hull);
|
||||||
}
|
}
|
||||||
@@ -75,11 +75,6 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hull != null && !string.IsNullOrWhiteSpace(decal) && decalSize > 0.0f)
|
|
||||||
{
|
|
||||||
hull.AddDecal(decal, worldPosition, decalSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flash)
|
if (flash)
|
||||||
{
|
{
|
||||||
float displayRange = flashRange.HasValue ? flashRange.Value : attack.Range;
|
float displayRange = flashRange.HasValue ? flashRange.Value : attack.Range;
|
||||||
|
|||||||
@@ -12,35 +12,10 @@ namespace Barotrauma
|
|||||||
partial void UpdateProjSpecific(float growModifier)
|
partial void UpdateProjSpecific(float growModifier)
|
||||||
{
|
{
|
||||||
EmitParticles(size, WorldPosition, hull, growModifier, OnChangeHull);
|
EmitParticles(size, WorldPosition, hull, growModifier, OnChangeHull);
|
||||||
|
|
||||||
lightSource.Color = new Color(1.0f, 0.45f, 0.3f) * Rand.Range(0.8f, 1.0f);
|
lightSource.Color = new Color(1.0f, 0.45f, 0.3f) * Rand.Range(0.8f, 1.0f);
|
||||||
if (Math.Abs((lightSource.Range * 0.2f) - Math.Max(size.X, size.Y)) > 1.0f) lightSource.Range = Math.Max(size.X, size.Y) * 5.0f;
|
if (Math.Abs((lightSource.Range * 0.2f) - Math.Max(size.X, size.Y)) > 1.0f) lightSource.Range = Math.Max(size.X, size.Y) * 5.0f;
|
||||||
if (Vector2.DistanceSquared(lightSource.Position,position) > 5.0f) lightSource.Position = position + Vector2.UnitY * 30.0f;
|
if (Vector2.DistanceSquared(lightSource.Position, position) > 5.0f) lightSource.Position = position + Vector2.UnitY * 30.0f;
|
||||||
|
|
||||||
if (size.X > 256.0f)
|
|
||||||
{
|
|
||||||
if (burnDecals.Count == 0)
|
|
||||||
{
|
|
||||||
var newDecal = hull.AddDecal("burnt", WorldPosition + size/2);
|
|
||||||
if (newDecal != null) burnDecals.Add(newDecal);
|
|
||||||
}
|
|
||||||
else if (WorldPosition.X < burnDecals[0].WorldPosition.X - 256.0f)
|
|
||||||
{
|
|
||||||
var newDecal = hull.AddDecal("burnt", WorldPosition);
|
|
||||||
if (newDecal != null) burnDecals.Insert(0, newDecal);
|
|
||||||
}
|
|
||||||
else if (WorldPosition.X + size.X > burnDecals[burnDecals.Count-1].WorldPosition.X + 256.0f)
|
|
||||||
{
|
|
||||||
var newDecal = hull.AddDecal("burnt", WorldPosition + Vector2.UnitX * size.X);
|
|
||||||
if (newDecal != null) burnDecals.Add(newDecal);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (Decal d in burnDecals)
|
|
||||||
{
|
|
||||||
//prevent the decals from fading out as long as the firesource is alive
|
|
||||||
d.FadeTimer = Math.Min(d.FadeTimer, d.FadeInTime);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void EmitParticles(Vector2 size, Vector2 worldPosition, Hull hull, float growModifier, Particle.OnChangeHullHandler onChangeHull = null)
|
public static void EmitParticles(Vector2 size, Vector2 worldPosition, Hull hull, float growModifier, Particle.OnChangeHullHandler onChangeHull = null)
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
using Barotrauma.Networking;
|
using Barotrauma.Networking;
|
||||||
using Barotrauma.Particles;
|
|
||||||
using Barotrauma.Sounds;
|
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
using Microsoft.Xna.Framework.Input;
|
using Microsoft.Xna.Framework.Input;
|
||||||
@@ -12,16 +10,10 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
partial class Hull : MapEntity, ISerializableEntity, IServerSerializable, IClientSerializable
|
partial class Hull : MapEntity, ISerializableEntity, IServerSerializable, IClientSerializable
|
||||||
{
|
{
|
||||||
public const int MaxDecalsPerHull = 10;
|
|
||||||
|
|
||||||
private readonly List<Decal> decals = new List<Decal>();
|
|
||||||
|
|
||||||
private float serverUpdateDelay;
|
private float serverUpdateDelay;
|
||||||
private float remoteWaterVolume, remoteOxygenPercentage;
|
private float remoteWaterVolume, remoteOxygenPercentage;
|
||||||
private List<Vector3> remoteFireSources;
|
private List<Vector3> remoteFireSources;
|
||||||
|
private readonly List<BackgroundSection> remoteBackgroundSections = new List<BackgroundSection>();
|
||||||
private bool networkUpdatePending;
|
|
||||||
private float networkUpdateTimer;
|
|
||||||
|
|
||||||
private double lastAmbientLightEditTime;
|
private double lastAmbientLightEditTime;
|
||||||
|
|
||||||
@@ -49,11 +41,14 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private float paintAmount = 0.0f;
|
||||||
|
private float minimumPaintAmountToDraw;
|
||||||
|
|
||||||
public override bool IsVisible(Rectangle worldView)
|
public override bool IsVisible(Rectangle worldView)
|
||||||
{
|
{
|
||||||
if (Screen.Selected != GameMain.SubEditorScreen && !GameMain.DebugDraw)
|
if (Screen.Selected != GameMain.SubEditorScreen && !GameMain.DebugDraw)
|
||||||
{
|
{
|
||||||
if (decals.Count == 0) { return false; }
|
if (decals.Count == 0 && paintAmount < minimumPaintAmountToDraw) { return false; }
|
||||||
|
|
||||||
Rectangle worldRect = WorldRect;
|
Rectangle worldRect = WorldRect;
|
||||||
if (worldRect.X > worldView.Right || worldRect.Right < worldView.X) { return false; }
|
if (worldRect.X > worldView.Right || worldRect.Right < worldView.X) { return false; }
|
||||||
@@ -70,20 +65,6 @@ namespace Barotrauma
|
|||||||
!Submarine.RectContains(MathUtils.ExpandRect(WorldRect, -8), position));
|
!Submarine.RectContains(MathUtils.ExpandRect(WorldRect, -8), position));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Decal AddDecal(string decalName, Vector2 worldPosition, float scale = 1.0f)
|
|
||||||
{
|
|
||||||
if (decals.Count >= MaxDecalsPerHull) return null;
|
|
||||||
|
|
||||||
var decal = GameMain.DecalManager.CreateDecal(decalName, scale, worldPosition, this);
|
|
||||||
|
|
||||||
if (decal != null)
|
|
||||||
{
|
|
||||||
decals.Add(decal);
|
|
||||||
}
|
|
||||||
|
|
||||||
return decal;
|
|
||||||
}
|
|
||||||
|
|
||||||
private GUIComponent CreateEditingHUD(bool inGame = false)
|
private GUIComponent CreateEditingHUD(bool inGame = false)
|
||||||
{
|
{
|
||||||
editingHUD = new GUIFrame(new RectTransform(new Vector2(0.3f, 0.25f), GUI.Canvas, Anchor.CenterRight) { MinSize = new Point(400, 0) }) { UserData = this };
|
editingHUD = new GUIFrame(new RectTransform(new Vector2(0.3f, 0.25f), GUI.Canvas, Anchor.CenterRight) { MinSize = new Point(400, 0) }) { UserData = this };
|
||||||
@@ -101,39 +82,32 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
editingHUD = CreateEditingHUD(Screen.Selected != GameMain.SubEditorScreen);
|
editingHUD = CreateEditingHUD(Screen.Selected != GameMain.SubEditorScreen);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!PlayerInput.KeyDown(Keys.Space)) return;
|
if (!PlayerInput.KeyDown(Keys.Space)) { return; }
|
||||||
bool lClick = PlayerInput.PrimaryMouseButtonClicked();
|
bool lClick = PlayerInput.PrimaryMouseButtonClicked();
|
||||||
bool rClick = PlayerInput.SecondaryMouseButtonClicked();
|
bool rClick = PlayerInput.SecondaryMouseButtonClicked();
|
||||||
if (!lClick && !rClick) return;
|
if (!lClick && !rClick) { return; }
|
||||||
|
|
||||||
Vector2 position = cam.ScreenToWorld(PlayerInput.MousePosition);
|
Vector2 position = cam.ScreenToWorld(PlayerInput.MousePosition);
|
||||||
|
|
||||||
if (lClick)
|
foreach (MapEntity entity in mapEntityList)
|
||||||
{
|
{
|
||||||
foreach (MapEntity entity in mapEntityList)
|
if (entity == this || !entity.IsHighlighted) { continue; }
|
||||||
|
if (!entity.IsMouseOn(position)) { continue; }
|
||||||
|
if (entity.linkedTo != null && entity.linkedTo.Contains(this))
|
||||||
{
|
{
|
||||||
if (entity == this || !entity.IsHighlighted) continue;
|
if (entity == this || !entity.IsHighlighted) continue;
|
||||||
if (!entity.IsMouseOn(position)) continue;
|
if (!entity.IsMouseOn(position)) continue;
|
||||||
if (entity.Linkable && entity.linkedTo != null)
|
if (entity.Linkable && entity.linkedTo != null && !entity.linkedTo.Contains(this))
|
||||||
{
|
{
|
||||||
entity.linkedTo.Add(this);
|
entity.linkedTo.Add(this);
|
||||||
linkedTo.Add(entity);
|
linkedTo.Add(entity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
else if (entity.Linkable && entity.linkedTo != null)
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach (MapEntity entity in mapEntityList)
|
|
||||||
{
|
{
|
||||||
if (entity == this || !entity.IsHighlighted) continue;
|
entity.linkedTo.Add(this);
|
||||||
if (!entity.IsMouseOn(position)) continue;
|
linkedTo.Add(entity);
|
||||||
if (entity.linkedTo != null && entity.linkedTo.Contains(this))
|
|
||||||
{
|
|
||||||
entity.linkedTo.Remove(this);
|
|
||||||
linkedTo.Remove(entity);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -151,7 +125,15 @@ namespace Barotrauma
|
|||||||
networkUpdateTimer += deltaTime;
|
networkUpdateTimer += deltaTime;
|
||||||
if (networkUpdateTimer > 0.2f)
|
if (networkUpdateTimer > 0.2f)
|
||||||
{
|
{
|
||||||
GameMain.NetworkMember?.CreateEntityEvent(this);
|
if (!pendingSectionUpdates.Any())
|
||||||
|
{
|
||||||
|
GameMain.NetworkMember?.CreateEntityEvent(this);
|
||||||
|
}
|
||||||
|
foreach (int pendingSectionUpdate in pendingSectionUpdates)
|
||||||
|
{
|
||||||
|
GameMain.NetworkMember?.CreateEntityEvent(this, new object[] { pendingSectionUpdate });
|
||||||
|
}
|
||||||
|
pendingSectionUpdates.Clear();
|
||||||
networkUpdatePending = false;
|
networkUpdatePending = false;
|
||||||
networkUpdateTimer = 0.0f;
|
networkUpdateTimer = 0.0f;
|
||||||
}
|
}
|
||||||
@@ -189,14 +171,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (Decal decal in decals)
|
|
||||||
{
|
|
||||||
decal.Update(deltaTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
decals.RemoveAll(d => d.FadeTimer >= d.LifeTime);
|
|
||||||
|
|
||||||
if (waterVolume < 1.0f) return;
|
if (waterVolume < 1.0f) return;
|
||||||
for (int i = 1; i < waveY.Length - 1; i++)
|
for (int i = 1; i < waveY.Length - 1; i++)
|
||||||
{
|
{
|
||||||
@@ -324,6 +299,35 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void DrawSectionColors(SpriteBatch spriteBatch)
|
||||||
|
{
|
||||||
|
Vector2 drawOffset = Submarine == null ? Vector2.Zero : Submarine.DrawPosition;
|
||||||
|
Point sectionSize = BackgroundSections[0].Rect.Size;
|
||||||
|
Vector2 drawPos = drawOffset + new Vector2(rect.Location.X + sectionSize.X / 2, rect.Location.Y - sectionSize.Y / 2);
|
||||||
|
|
||||||
|
for (int i = 0; i < BackgroundSections.Count; i++)
|
||||||
|
{
|
||||||
|
BackgroundSection section = BackgroundSections[i];
|
||||||
|
|
||||||
|
if (section.ColorStrength < 0.01f || section.Color.A < 1) { continue; }
|
||||||
|
|
||||||
|
if (GameMain.DecalManager.GrimeSprites.Count == 0)
|
||||||
|
{
|
||||||
|
GUI.DrawRectangle(spriteBatch,
|
||||||
|
new Vector2(drawOffset.X + rect.X + section.Rect.X, -(drawOffset.Y + rect.Y + section.Rect.Y)),
|
||||||
|
new Vector2(sectionSize.X, sectionSize.Y),
|
||||||
|
section.GetStrengthAdjustedColor(), true, 0.0f, (int)Math.Max(1.5f / Screen.Selected.Cam.Zoom, 1.0f));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Vector2 sectionPos = new Vector2(drawPos.X + section.Rect.Location.X, -(drawPos.Y + section.Rect.Location.Y));
|
||||||
|
Vector2 randomOffset = new Vector2(section.Noise.X - 0.5f, section.Noise.Y - 0.5f) * 15.0f;
|
||||||
|
var sprite = GameMain.DecalManager.GrimeSprites[i % GameMain.DecalManager.GrimeSprites.Count];
|
||||||
|
sprite.Draw(spriteBatch, sectionPos + randomOffset, section.GetStrengthAdjustedColor(), scale: 1.25f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static void UpdateVertices(Camera cam, WaterRenderer renderer)
|
public static void UpdateVertices(Camera cam, WaterRenderer renderer)
|
||||||
{
|
{
|
||||||
foreach (EntityGrid entityGrid in EntityGrids)
|
foreach (EntityGrid entityGrid in EntityGrids)
|
||||||
@@ -526,22 +530,38 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public void ClientWrite(IWriteMessage msg, object[] extraData = null)
|
public void ClientWrite(IWriteMessage msg, object[] extraData = null)
|
||||||
{
|
{
|
||||||
msg.WriteRangedSingle(MathHelper.Clamp(waterVolume / Volume, 0.0f, 1.5f), 0.0f, 1.5f, 8);
|
msg.Write(extraData != null);
|
||||||
|
if (extraData == null)
|
||||||
msg.Write(FireSources.Count > 0);
|
|
||||||
if (FireSources.Count > 0)
|
|
||||||
{
|
{
|
||||||
msg.WriteRangedInteger(Math.Min(FireSources.Count, 16), 0, 16);
|
msg.WriteRangedSingle(MathHelper.Clamp(waterVolume / Volume, 0.0f, 1.5f), 0.0f, 1.5f, 8);
|
||||||
for (int i = 0; i < Math.Min(FireSources.Count, 16); i++)
|
|
||||||
{
|
|
||||||
var fireSource = FireSources[i];
|
|
||||||
Vector2 normalizedPos = new Vector2(
|
|
||||||
(fireSource.Position.X - rect.X) / rect.Width,
|
|
||||||
(fireSource.Position.Y - (rect.Y - rect.Height)) / rect.Height);
|
|
||||||
|
|
||||||
msg.WriteRangedSingle(MathHelper.Clamp(normalizedPos.X, 0.0f, 1.0f), 0.0f, 1.0f, 8);
|
msg.Write(FireSources.Count > 0);
|
||||||
msg.WriteRangedSingle(MathHelper.Clamp(normalizedPos.Y, 0.0f, 1.0f), 0.0f, 1.0f, 8);
|
if (FireSources.Count > 0)
|
||||||
msg.WriteRangedSingle(MathHelper.Clamp(fireSource.Size.X / rect.Width, 0.0f, 1.0f), 0, 1.0f, 8);
|
{
|
||||||
|
msg.WriteRangedInteger(Math.Min(FireSources.Count, 16), 0, 16);
|
||||||
|
for (int i = 0; i < Math.Min(FireSources.Count, 16); i++)
|
||||||
|
{
|
||||||
|
var fireSource = FireSources[i];
|
||||||
|
Vector2 normalizedPos = new Vector2(
|
||||||
|
(fireSource.Position.X - rect.X) / rect.Width,
|
||||||
|
(fireSource.Position.Y - (rect.Y - rect.Height)) / rect.Height);
|
||||||
|
|
||||||
|
msg.WriteRangedSingle(MathHelper.Clamp(normalizedPos.X, 0.0f, 1.0f), 0.0f, 1.0f, 8);
|
||||||
|
msg.WriteRangedSingle(MathHelper.Clamp(normalizedPos.Y, 0.0f, 1.0f), 0.0f, 1.0f, 8);
|
||||||
|
msg.WriteRangedSingle(MathHelper.Clamp(fireSource.Size.X / rect.Width, 0.0f, 1.0f), 0, 1.0f, 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int sectorToUpdate = (int)extraData[0];
|
||||||
|
int start = sectorToUpdate * BackgroundSectionsPerNetworkEvent;
|
||||||
|
int end = Math.Min((sectorToUpdate + 1) * BackgroundSectionsPerNetworkEvent, BackgroundSections.Count - 1);
|
||||||
|
msg.WriteRangedInteger(sectorToUpdate, 0, BackgroundSections.Count - 1);
|
||||||
|
for (int i = start; i < end; i++)
|
||||||
|
{
|
||||||
|
msg.WriteRangedSingle(BackgroundSections[i].ColorStrength, 0.0f, 1.0f, 8);
|
||||||
|
msg.Write(BackgroundSections[i].Color.PackedValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -565,6 +585,54 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool hasExtraData = message.ReadBoolean();
|
||||||
|
if (hasExtraData)
|
||||||
|
{
|
||||||
|
bool hasSectionUpdate = message.ReadBoolean();
|
||||||
|
if (hasSectionUpdate)
|
||||||
|
{
|
||||||
|
int sectorToUpdate = message.ReadRangedInteger(0, BackgroundSections.Count - 1);
|
||||||
|
int start = sectorToUpdate * BackgroundSectionsPerNetworkEvent;
|
||||||
|
int end = Math.Min((sectorToUpdate + 1) * BackgroundSectionsPerNetworkEvent, BackgroundSections.Count - 1);
|
||||||
|
for (int i = start; i < end; i++)
|
||||||
|
{
|
||||||
|
float colorStrength = message.ReadRangedSingle(0.0f, 1.0f, 8);
|
||||||
|
Color color = new Color(message.ReadUInt32());
|
||||||
|
float prevColorStrength = BackgroundSections[i].ColorStrength;
|
||||||
|
BackgroundSections[i].SetColorStrength(colorStrength);
|
||||||
|
BackgroundSections[i].SetColor(color);
|
||||||
|
paintAmount = Math.Max(0, paintAmount + (BackgroundSections[i].ColorStrength - prevColorStrength) / BackgroundSections.Count);
|
||||||
|
|
||||||
|
var remoteBackgroundSection = remoteBackgroundSections.Find(s => s.Index == i);
|
||||||
|
if (remoteBackgroundSection != null)
|
||||||
|
{
|
||||||
|
remoteBackgroundSection.SetColorStrength(colorStrength);
|
||||||
|
remoteBackgroundSection.SetColor(color);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
remoteBackgroundSections.Add(new BackgroundSection(new Rectangle(0, 0, 1, 1), i, colorStrength, color, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
paintAmount = BackgroundSections.Sum(s => s.ColorStrength);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int decalCount = message.ReadRangedInteger(0, MaxDecalsPerHull);
|
||||||
|
decals.Clear();
|
||||||
|
for (int i = 0; i < decalCount; i++)
|
||||||
|
{
|
||||||
|
UInt32 decalId = message.ReadUInt32();
|
||||||
|
float normalizedXPos = message.ReadRangedSingle(0.0f, 1.0f, 8);
|
||||||
|
float normalizedYPos = message.ReadRangedSingle(0.0f, 1.0f, 8);
|
||||||
|
float decalPosX = MathHelper.Lerp(rect.X, rect.Right, normalizedXPos);
|
||||||
|
float decalPosY = MathHelper.Lerp(rect.Y - rect.Height, rect.Y, normalizedYPos);
|
||||||
|
float decalScale = message.ReadRangedSingle(0.0f, 2.0f, 12);
|
||||||
|
AddDecal(decalId, new Vector2(decalPosX, decalPosY), decalScale, isNetworkEvent: true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (serverUpdateDelay > 0.0f) { return; }
|
if (serverUpdateDelay > 0.0f) { return; }
|
||||||
|
|
||||||
ApplyRemoteState();
|
ApplyRemoteState();
|
||||||
@@ -572,10 +640,14 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private void ApplyRemoteState()
|
private void ApplyRemoteState()
|
||||||
{
|
{
|
||||||
if (remoteFireSources == null)
|
foreach (BackgroundSection remoteBackgroundSection in remoteBackgroundSections)
|
||||||
{
|
{
|
||||||
return;
|
BackgroundSections[remoteBackgroundSection.Index].SetColor(remoteBackgroundSection.Color);
|
||||||
|
BackgroundSections[remoteBackgroundSection.Index].SetColorStrength(remoteBackgroundSection.ColorStrength);
|
||||||
}
|
}
|
||||||
|
remoteBackgroundSections.Clear();
|
||||||
|
|
||||||
|
if (remoteFireSources == null) { return; }
|
||||||
|
|
||||||
WaterVolume = remoteWaterVolume;
|
WaterVolume = remoteWaterVolume;
|
||||||
OxygenPercentage = remoteOxygenPercentage;
|
OxygenPercentage = remoteOxygenPercentage;
|
||||||
@@ -609,7 +681,6 @@ namespace Barotrauma
|
|||||||
FireSources.RemoveAt(i);
|
FireSources.RemoveAt(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
remoteFireSources = null;
|
remoteFireSources = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,8 +34,8 @@ namespace Barotrauma
|
|||||||
public const int DefaultBufferSize = 2000;
|
public const int DefaultBufferSize = 2000;
|
||||||
public const int DefaultIndoorsBufferSize = 3000;
|
public const int DefaultIndoorsBufferSize = 3000;
|
||||||
|
|
||||||
public static Vector2 DistortionScale = new Vector2(2f, 2f);
|
public static Vector2 DistortionScale = new Vector2(2f, 1.5f);
|
||||||
public static Vector2 DistortionStrength = new Vector2(0.25f, 0.25f);
|
public static Vector2 DistortionStrength = new Vector2(0.01f, 0.33f);
|
||||||
public static float BlurAmount = 0.0f;
|
public static float BlurAmount = 0.0f;
|
||||||
|
|
||||||
public Vector2 WavePos
|
public Vector2 WavePos
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
using Barotrauma.Items.Components;
|
using Barotrauma.Items.Components;
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
using SharpFont;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
@@ -87,6 +88,12 @@ namespace Barotrauma.Lights
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class VectorPair
|
||||||
|
{
|
||||||
|
public Vector2? A = null;
|
||||||
|
public Vector2? B = null;
|
||||||
|
}
|
||||||
|
|
||||||
class ConvexHull
|
class ConvexHull
|
||||||
{
|
{
|
||||||
public static List<ConvexHullList> HullLists = new List<ConvexHullList>();
|
public static List<ConvexHullList> HullLists = new List<ConvexHullList>();
|
||||||
@@ -96,6 +103,7 @@ namespace Barotrauma.Lights
|
|||||||
private readonly Segment[] segments = new Segment[4];
|
private readonly Segment[] segments = new Segment[4];
|
||||||
private readonly SegmentPoint[] vertices = new SegmentPoint[4];
|
private readonly SegmentPoint[] vertices = new SegmentPoint[4];
|
||||||
private readonly SegmentPoint[] losVertices = new SegmentPoint[4];
|
private readonly SegmentPoint[] losVertices = new SegmentPoint[4];
|
||||||
|
private readonly VectorPair[] losOffsets = new VectorPair[4];
|
||||||
|
|
||||||
private readonly bool[] backFacing;
|
private readonly bool[] backFacing;
|
||||||
private readonly bool[] ignoreEdge;
|
private readonly bool[] ignoreEdge;
|
||||||
@@ -105,6 +113,7 @@ namespace Barotrauma.Lights
|
|||||||
public VertexPositionColor[] ShadowVertices { get; private set; }
|
public VertexPositionColor[] ShadowVertices { get; private set; }
|
||||||
public VertexPositionTexture[] PenumbraVertices { get; private set; }
|
public VertexPositionTexture[] PenumbraVertices { get; private set; }
|
||||||
public int ShadowVertexCount { get; private set; }
|
public int ShadowVertexCount { get; private set; }
|
||||||
|
public int PenumbraVertexCount { get; private set; }
|
||||||
|
|
||||||
private readonly HashSet<ConvexHull> overlappingHulls = new HashSet<ConvexHull>();
|
private readonly HashSet<ConvexHull> overlappingHulls = new HashSet<ConvexHull>();
|
||||||
|
|
||||||
@@ -157,15 +166,24 @@ namespace Barotrauma.Lights
|
|||||||
|
|
||||||
ParentEntity = parent;
|
ParentEntity = parent;
|
||||||
|
|
||||||
ShadowVertices = new VertexPositionColor[6 * 2];
|
ShadowVertices = new VertexPositionColor[6 * 4];
|
||||||
PenumbraVertices = new VertexPositionTexture[6];
|
PenumbraVertices = new VertexPositionTexture[6 * 4];
|
||||||
|
|
||||||
backFacing = new bool[4];
|
backFacing = new bool[4];
|
||||||
ignoreEdge = new bool[4];
|
ignoreEdge = new bool[4];
|
||||||
|
|
||||||
SetVertices(points);
|
float minX = points[0].X, minY = points[0].Y, maxX = points[0].X, maxY = points[0].Y;
|
||||||
|
|
||||||
Enabled = true;
|
for (int i = 1; i < vertices.Length; i++)
|
||||||
|
{
|
||||||
|
if (points[i].X < minX) minX = points[i].X;
|
||||||
|
if (points[i].Y < minY) minY = points[i].Y;
|
||||||
|
|
||||||
|
if (points[i].X > maxX) maxX = points[i].X;
|
||||||
|
if (points[i].Y > minY) maxY = points[i].Y;
|
||||||
|
}
|
||||||
|
|
||||||
|
BoundingBox = new Rectangle((int)minX, (int)minY, (int)(maxX - minX), (int)(maxY - minY));
|
||||||
|
|
||||||
isHorizontal = BoundingBox.Width > BoundingBox.Height;
|
isHorizontal = BoundingBox.Width > BoundingBox.Height;
|
||||||
if (ParentEntity is Structure structure)
|
if (ParentEntity is Structure structure)
|
||||||
@@ -180,6 +198,10 @@ namespace Barotrauma.Lights
|
|||||||
if (door != null) { isHorizontal = door.IsHorizontal; }
|
if (door != null) { isHorizontal = door.IsHorizontal; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SetVertices(points);
|
||||||
|
|
||||||
|
Enabled = true;
|
||||||
|
|
||||||
var chList = HullLists.Find(h => h.Submarine == parent.Submarine);
|
var chList = HullLists.Find(h => h.Submarine == parent.Submarine);
|
||||||
if (chList == null)
|
if (chList == null)
|
||||||
{
|
{
|
||||||
@@ -202,11 +224,17 @@ namespace Barotrauma.Lights
|
|||||||
|
|
||||||
if (isHorizontal == ch.isHorizontal)
|
if (isHorizontal == ch.isHorizontal)
|
||||||
{
|
{
|
||||||
if (BoundingBox == ch.BoundingBox) { return; }
|
|
||||||
|
|
||||||
//hide segments that are roughly at the some position as some other segment (e.g. the ends of two adjacent wall pieces)
|
//hide segments that are roughly at the some position as some other segment (e.g. the ends of two adjacent wall pieces)
|
||||||
float mergeDist = 32;
|
float mergeDist = 16;
|
||||||
float mergeDistSqr = mergeDist * mergeDist;
|
float mergeDistSqr = mergeDist * mergeDist;
|
||||||
|
|
||||||
|
Rectangle intersection = Rectangle.Intersect(BoundingBox, ch.BoundingBox);
|
||||||
|
int intersectionArea = intersection.Width * intersection.Height;
|
||||||
|
int bboxArea = BoundingBox.Width * BoundingBox.Height;
|
||||||
|
int otherBboxArea = ch.BoundingBox.Width * ch.BoundingBox.Height;
|
||||||
|
if (Math.Abs(intersectionArea - bboxArea) < mergeDistSqr) { return; }
|
||||||
|
if (Math.Abs(intersectionArea - otherBboxArea) < mergeDistSqr) { return; }
|
||||||
|
|
||||||
for (int i = 0; i < segments.Length; i++)
|
for (int i = 0; i < segments.Length; i++)
|
||||||
{
|
{
|
||||||
for (int j = 0; j < ch.segments.Length; j++)
|
for (int j = 0; j < ch.segments.Length; j++)
|
||||||
@@ -237,21 +265,67 @@ namespace Barotrauma.Lights
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
for (int i = 0; i < segments.Length; i++)
|
||||||
{
|
{
|
||||||
//TODO: do something to corner areas where a vertical wall meets a horizontal one
|
if (ignoreEdge[i]) { continue; }
|
||||||
|
if (Vector2.DistanceSquared(segments[i].Start.Pos, segments[i].End.Pos) < 1.0f) { continue; }
|
||||||
|
for (int j = 0; j < ch.segments.Length; j++)
|
||||||
|
{
|
||||||
|
if (ch.ignoreEdge[j]) { continue; }
|
||||||
|
if (Vector2.DistanceSquared(ch.segments[j].Start.Pos, ch.segments[j].End.Pos) < 1.0f) { continue; }
|
||||||
|
if (IsSegmentAInB(segments[i], ch.segments[j]))
|
||||||
|
{
|
||||||
|
ignoreEdge[i] = true;
|
||||||
|
if (Vector2.DistanceSquared(ch.segments[j].Start.Pos, segments[i].Start.Pos) < 4.0f)
|
||||||
|
{
|
||||||
|
ch.ShiftSegmentPoint(j, false, segments[i].End.Pos);
|
||||||
|
}
|
||||||
|
else if (Vector2.DistanceSquared(ch.segments[j].Start.Pos, segments[i].End.Pos) < 4.0f)
|
||||||
|
{
|
||||||
|
ch.ShiftSegmentPoint(j, false, segments[i].Start.Pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Vector2.DistanceSquared(ch.segments[j].End.Pos, segments[i].Start.Pos) < 4.0f)
|
||||||
|
{
|
||||||
|
ch.ShiftSegmentPoint(j, true, segments[i].End.Pos);
|
||||||
|
}
|
||||||
|
else if (Vector2.DistanceSquared(ch.segments[j].End.Pos, segments[i].End.Pos) < 4.0f)
|
||||||
|
{
|
||||||
|
ch.ShiftSegmentPoint(j, true, segments[i].Start.Pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (IsSegmentAInB(ch.segments[j], segments[i]))
|
||||||
|
{
|
||||||
|
ch.ignoreEdge[j] = true;
|
||||||
|
|
||||||
|
if (Vector2.DistanceSquared(segments[i].Start.Pos, ch.segments[j].Start.Pos) < 4.0f)
|
||||||
|
{
|
||||||
|
ShiftSegmentPoint(i, false, ch.segments[j].End.Pos);
|
||||||
|
}
|
||||||
|
else if (Vector2.DistanceSquared(segments[i].Start.Pos, ch.segments[j].End.Pos) < 4.0f)
|
||||||
|
{
|
||||||
|
ShiftSegmentPoint(i, false, ch.segments[j].Start.Pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Vector2.DistanceSquared(segments[i].End.Pos, ch.segments[j].Start.Pos) < 4.0f)
|
||||||
|
{
|
||||||
|
ShiftSegmentPoint(i, true, ch.segments[j].End.Pos);
|
||||||
|
}
|
||||||
|
else if (Vector2.DistanceSquared(segments[i].End.Pos, ch.segments[j].End.Pos) < 4.0f)
|
||||||
|
{
|
||||||
|
ShiftSegmentPoint(i, true, ch.segments[j].Start.Pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//ignore edges that are inside some other convex hull
|
//ignore edges that are inside some other convex hull
|
||||||
for (int i = 0; i < vertices.Length; i++)
|
for (int i = 0; i < vertices.Length; i++)
|
||||||
{
|
{
|
||||||
if (vertices[i].Pos.X >= ch.BoundingBox.X && vertices[i].Pos.X <= ch.BoundingBox.Right &&
|
if (ch.IsPointInside(vertices[i].Pos))
|
||||||
vertices[i].Pos.Y >= ch.BoundingBox.Y && vertices[i].Pos.Y <= ch.BoundingBox.Bottom)
|
|
||||||
{
|
{
|
||||||
Vector2 p = vertices[(i + 1) % vertices.Length].Pos;
|
if (ch.IsPointInside(vertices[(i + 1) % vertices.Length].Pos))
|
||||||
|
|
||||||
if (p.X >= ch.BoundingBox.X && p.X <= ch.BoundingBox.Right &&
|
|
||||||
p.Y >= ch.BoundingBox.Y && p.Y <= ch.BoundingBox.Bottom)
|
|
||||||
{
|
{
|
||||||
ignoreEdge[i] = true;
|
ignoreEdge[i] = true;
|
||||||
overlappingHulls.Add(ch);
|
overlappingHulls.Add(ch);
|
||||||
@@ -260,6 +334,75 @@ namespace Barotrauma.Lights
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ShiftSegmentPoint(int segmentIndex, bool end, Vector2 newPos)
|
||||||
|
{
|
||||||
|
var segment = segments[segmentIndex];
|
||||||
|
|
||||||
|
losOffsets[segmentIndex] ??= new VectorPair();
|
||||||
|
bool flipped = false;
|
||||||
|
if (Vector2.DistanceSquared(vertices[segmentIndex].Pos, segment.Start.Pos) > Vector2.DistanceSquared(vertices[segmentIndex].Pos, segment.End.Pos))
|
||||||
|
{
|
||||||
|
flipped = true;
|
||||||
|
}
|
||||||
|
if (end == !flipped)
|
||||||
|
{
|
||||||
|
losOffsets[segmentIndex].B = newPos;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
losOffsets[segmentIndex].A = newPos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsSegmentAInB(Segment a, Segment b)
|
||||||
|
{
|
||||||
|
if (Vector2.DistanceSquared(a.Start.Pos, a.End.Pos) > Vector2.DistanceSquared(b.Start.Pos, b.End.Pos))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2 min = new Vector2(Math.Min(b.Start.Pos.X, b.End.Pos.X), Math.Min(b.Start.Pos.Y, b.End.Pos.Y));
|
||||||
|
Vector2 max = new Vector2(Math.Max(b.Start.Pos.X, b.End.Pos.X), Math.Max(b.Start.Pos.Y, b.End.Pos.Y));
|
||||||
|
min.X -= 1.0f; min.Y -= 1.0f;
|
||||||
|
max.X += 1.0f; max.Y += 1.0f;
|
||||||
|
|
||||||
|
if (a.Start.Pos.X < min.X) { return false; }
|
||||||
|
if (a.Start.Pos.Y < min.Y) { return false; }
|
||||||
|
if (a.End.Pos.X < min.X) { return false; }
|
||||||
|
if (a.End.Pos.Y < min.Y) { return false; }
|
||||||
|
|
||||||
|
if (a.Start.Pos.X > max.X) { return false; }
|
||||||
|
if (a.Start.Pos.Y > max.Y) { return false; }
|
||||||
|
if (a.End.Pos.X > max.X) { return false; }
|
||||||
|
if (a.End.Pos.Y > max.Y) { return false; }
|
||||||
|
|
||||||
|
float startDist = MathUtils.LineToPointDistanceSquared(b.Start.Pos, b.End.Pos, a.Start.Pos);
|
||||||
|
if (startDist > 1.0f) { return false; }
|
||||||
|
float endDist = MathUtils.LineToPointDistanceSquared(b.Start.Pos, b.End.Pos, a.End.Pos);
|
||||||
|
if (endDist > 1.0f) { return false; }
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsPointInside(Vector2 point)
|
||||||
|
{
|
||||||
|
if (!BoundingBox.Contains(point)) { return false; }
|
||||||
|
|
||||||
|
Vector2 center = (vertices[0].Pos + vertices[1].Pos + vertices[2].Pos + vertices[3].Pos) * 0.25f;
|
||||||
|
for (int i=0;i<4;i++)
|
||||||
|
{
|
||||||
|
Vector2 segmentVector = vertices[(i + 1) % 4].Pos - vertices[i].Pos;
|
||||||
|
Vector2 centerToVertex = center - vertices[i].Pos;
|
||||||
|
Vector2 pointToVertex = point - vertices[i].Pos;
|
||||||
|
|
||||||
|
float dotCenter = Vector2.Dot(centerToVertex, segmentVector);
|
||||||
|
float dotPoint = Vector2.Dot(pointToVertex, segmentVector);
|
||||||
|
|
||||||
|
if ((dotCenter > 0f && dotPoint < 0f) || (dotCenter < 0f && dotPoint > 0f)) { return false; }
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private void MergeSegments(Segment segment1, Segment segment2, bool startPointsMatch)
|
private void MergeSegments(Segment segment1, Segment segment2, bool startPointsMatch)
|
||||||
{
|
{
|
||||||
int startPointIndex = -1, endPointIndex = -1;
|
int startPointIndex = -1, endPointIndex = -1;
|
||||||
@@ -344,6 +487,8 @@ namespace Barotrauma.Lights
|
|||||||
vertices[i].Pos += amount;
|
vertices[i].Pos += amount;
|
||||||
losVertices[i].Pos += amount;
|
losVertices[i].Pos += amount;
|
||||||
|
|
||||||
|
losOffsets[i] = null;
|
||||||
|
|
||||||
segments[i].Start.Pos += amount;
|
segments[i].Start.Pos += amount;
|
||||||
segments[i].End.Pos += amount;
|
segments[i].End.Pos += amount;
|
||||||
}
|
}
|
||||||
@@ -406,6 +551,7 @@ namespace Barotrauma.Lights
|
|||||||
{
|
{
|
||||||
vertices[i] = new SegmentPoint(points[i], this);
|
vertices[i] = new SegmentPoint(points[i], this);
|
||||||
losVertices[i] = new SegmentPoint(points[i], this);
|
losVertices[i] = new SegmentPoint(points[i], this);
|
||||||
|
losOffsets[i] = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
@@ -517,7 +663,7 @@ namespace Barotrauma.Lights
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CalculateShadowVertices(Vector2 lightSourcePos, bool los = true)
|
public void CalculateLosVertices(Vector2 lightSourcePos)
|
||||||
{
|
{
|
||||||
Vector3 offset = Vector3.Zero;
|
Vector3 offset = Vector3.Zero;
|
||||||
if (ParentEntity != null && ParentEntity.Submarine != null)
|
if (ParentEntity != null && ParentEntity.Submarine != null)
|
||||||
@@ -527,8 +673,6 @@ namespace Barotrauma.Lights
|
|||||||
|
|
||||||
ShadowVertexCount = 0;
|
ShadowVertexCount = 0;
|
||||||
|
|
||||||
var vertices = los ? losVertices : this.vertices;
|
|
||||||
|
|
||||||
//compute facing of each edge, using N*L
|
//compute facing of each edge, using N*L
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
@@ -538,8 +682,8 @@ namespace Barotrauma.Lights
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector2 firstVertex = vertices[i].Pos;
|
Vector2 firstVertex = losVertices[i].Pos;
|
||||||
Vector2 secondVertex = vertices[(i+1) % 4].Pos;
|
Vector2 secondVertex = losVertices[(i+1) % 4].Pos;
|
||||||
|
|
||||||
Vector2 L = lightSourcePos - ((firstVertex + secondVertex) / 2.0f);
|
Vector2 L = lightSourcePos - ((firstVertex + secondVertex) / 2.0f);
|
||||||
|
|
||||||
@@ -547,121 +691,144 @@ namespace Barotrauma.Lights
|
|||||||
-(secondVertex.Y - firstVertex.Y),
|
-(secondVertex.Y - firstVertex.Y),
|
||||||
secondVertex.X - firstVertex.X);
|
secondVertex.X - firstVertex.X);
|
||||||
|
|
||||||
backFacing[i] = (Vector2.Dot(N, L) < 0) == los;
|
backFacing[i] = (Vector2.Dot(N, L) < 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
//find beginning and ending vertices which
|
ShadowVertexCount = 0;
|
||||||
//belong to the shadow
|
for (int i=0;i<4;i++)
|
||||||
int startingIndex = -1;
|
|
||||||
int endingIndex = -1;
|
|
||||||
for (int i = 0; i < 4; i++)
|
|
||||||
{
|
{
|
||||||
int currentEdge = i;
|
if (!backFacing[i]) { continue; }
|
||||||
int nextEdge = (i + 1) % 4;
|
int currentIndex = i;
|
||||||
|
Vector3 vertexPos0 = new Vector3(losOffsets[currentIndex]?.A ?? losVertices[currentIndex].Pos, 0.0f);
|
||||||
|
Vector3 vertexPos1 = new Vector3(losOffsets[currentIndex]?.B ?? losVertices[(currentIndex + 1) % 4].Pos, 0.0f);
|
||||||
|
|
||||||
if (backFacing[currentEdge] && !backFacing[nextEdge])
|
if (Vector3.DistanceSquared(vertexPos0, vertexPos1) < 1.0f) { continue; }
|
||||||
endingIndex = nextEdge;
|
|
||||||
|
|
||||||
if (!backFacing[currentEdge] && backFacing[nextEdge])
|
Vector3 L2P0 = vertexPos0 - new Vector3(lightSourcePos, 0);
|
||||||
startingIndex = nextEdge;
|
L2P0.Normalize();
|
||||||
}
|
Vector3 extruded0 = new Vector3(lightSourcePos, 0) + L2P0 * 9000;
|
||||||
|
|
||||||
if (startingIndex == -1 || endingIndex == -1) { return; }
|
Vector3 L2P1 = vertexPos1 - new Vector3(lightSourcePos, 0);
|
||||||
|
L2P1.Normalize();
|
||||||
|
Vector3 extruded1 = new Vector3(lightSourcePos, 0) + L2P1 * 9000;
|
||||||
|
|
||||||
//nr of vertices that are in the shadow
|
ShadowVertices[ShadowVertexCount + 0] = new VertexPositionColor
|
||||||
if (endingIndex > startingIndex)
|
|
||||||
ShadowVertexCount = endingIndex - startingIndex + 1;
|
|
||||||
else
|
|
||||||
ShadowVertexCount = 4 + 1 - startingIndex + endingIndex;
|
|
||||||
|
|
||||||
//shadowVertices = new VertexPositionColor[shadowVertexCount * 2];
|
|
||||||
|
|
||||||
//create a triangle strip that has the shape of the shadow
|
|
||||||
int currentIndex = startingIndex;
|
|
||||||
int svCount = 0;
|
|
||||||
while (svCount != ShadowVertexCount * 2)
|
|
||||||
{
|
|
||||||
Vector3 vertexPos = new Vector3(vertices[currentIndex].Pos, 0.0f);
|
|
||||||
|
|
||||||
int i = los ? svCount : svCount + 1;
|
|
||||||
int j = los ? svCount + 1 : svCount;
|
|
||||||
|
|
||||||
//one vertex on the hull
|
|
||||||
ShadowVertices[i] = new VertexPositionColor
|
|
||||||
{
|
{
|
||||||
Color = los ? Color.Black : Color.Transparent,
|
Color = Color.Black,
|
||||||
Position = vertexPos + offset
|
Position = vertexPos1 + offset
|
||||||
};
|
};
|
||||||
|
|
||||||
//one extruded by the light direction
|
ShadowVertices[ShadowVertexCount + 1] = new VertexPositionColor
|
||||||
ShadowVertices[j] = new VertexPositionColor
|
|
||||||
{
|
{
|
||||||
Color = ShadowVertices[i].Color
|
Color = Color.Black,
|
||||||
|
Position = vertexPos0 + offset
|
||||||
};
|
};
|
||||||
|
|
||||||
Vector3 L2P = vertexPos - new Vector3(lightSourcePos, 0);
|
ShadowVertices[ShadowVertexCount + 2] = new VertexPositionColor
|
||||||
L2P.Normalize();
|
{
|
||||||
|
Color = Color.Black,
|
||||||
ShadowVertices[j].Position = new Vector3(lightSourcePos, 0) + L2P * 9000 + offset;
|
Position = extruded0 + offset
|
||||||
|
};
|
||||||
|
|
||||||
svCount += 2;
|
ShadowVertices[ShadowVertexCount + 3] = new VertexPositionColor
|
||||||
currentIndex = (currentIndex + 1) % 4;
|
{
|
||||||
|
Color = Color.Black,
|
||||||
|
Position = vertexPos1 + offset
|
||||||
|
};
|
||||||
|
|
||||||
|
ShadowVertices[ShadowVertexCount + 4] = new VertexPositionColor
|
||||||
|
{
|
||||||
|
Color = Color.Black,
|
||||||
|
Position = extruded0 + offset
|
||||||
|
};
|
||||||
|
|
||||||
|
ShadowVertices[ShadowVertexCount + 5] = new VertexPositionColor
|
||||||
|
{
|
||||||
|
Color = Color.Black,
|
||||||
|
Position = extruded1 + offset
|
||||||
|
};
|
||||||
|
|
||||||
|
ShadowVertexCount += 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (los)
|
CalculateLosPenumbraVertices(lightSourcePos);
|
||||||
{
|
|
||||||
CalculatePenumbraVertices(startingIndex, endingIndex, lightSourcePos, los);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CalculatePenumbraVertices(int startingIndex, int endingIndex, Vector2 lightSourcePos, bool los)
|
private void CalculateLosPenumbraVertices(Vector2 lightSourcePos)
|
||||||
{
|
{
|
||||||
var vertices = los ? losVertices : this.vertices;
|
|
||||||
|
|
||||||
Vector3 offset = Vector3.Zero;
|
Vector3 offset = Vector3.Zero;
|
||||||
if (ParentEntity != null && ParentEntity.Submarine != null)
|
if (ParentEntity != null && ParentEntity.Submarine != null)
|
||||||
{
|
{
|
||||||
offset = new Vector3(ParentEntity.Submarine.DrawPosition.X, ParentEntity.Submarine.DrawPosition.Y, 0.0f);
|
offset = new Vector3(ParentEntity.Submarine.DrawPosition.X, ParentEntity.Submarine.DrawPosition.Y, 0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int n = 0; n < 4; n += 3)
|
PenumbraVertexCount = 0;
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
Vector3 penumbraStart = new Vector3((n == 0) ? vertices[startingIndex].Pos : vertices[endingIndex].Pos, 0.0f);
|
int currentIndex = i;
|
||||||
|
int prevIndex = (i + 3) % 4;
|
||||||
|
int nextIndex = (i + 1) % 4;
|
||||||
|
bool disjointed = losOffsets[i]?.A != null;
|
||||||
|
Vector2 vertexPos0 = losOffsets[currentIndex]?.A ?? losVertices[currentIndex].Pos;
|
||||||
|
Vector2 vertexPos1 = losOffsets[currentIndex]?.B ?? losVertices[nextIndex].Pos;
|
||||||
|
|
||||||
PenumbraVertices[n] = new VertexPositionTexture
|
if (Vector2.DistanceSquared(vertexPos0, vertexPos1) < 1.0f) { continue; }
|
||||||
|
|
||||||
|
if (backFacing[currentIndex] && (disjointed || (!backFacing[prevIndex])))
|
||||||
{
|
{
|
||||||
Position = penumbraStart + offset,
|
Vector3 penumbraStart = new Vector3(vertexPos0, 0.0f);
|
||||||
TextureCoordinate = new Vector2(0.0f, 1.0f)
|
|
||||||
};
|
|
||||||
|
|
||||||
for (int i = 0; i < 2; i++)
|
PenumbraVertices[PenumbraVertexCount] = new VertexPositionTexture
|
||||||
{
|
|
||||||
PenumbraVertices[n + i + 1] = new VertexPositionTexture();
|
|
||||||
Vector3 vertexDir = penumbraStart - new Vector3(lightSourcePos, 0);
|
|
||||||
vertexDir.Normalize();
|
|
||||||
|
|
||||||
Vector3 normal = (i == 0) ? new Vector3(-vertexDir.Y, vertexDir.X, 0.0f) : new Vector3(vertexDir.Y, -vertexDir.X, 0.0f) * 0.05f;
|
|
||||||
if (n > 0) normal = -normal;
|
|
||||||
|
|
||||||
vertexDir = penumbraStart - (new Vector3(lightSourcePos, 0) - normal * 20.0f);
|
|
||||||
vertexDir.Normalize();
|
|
||||||
PenumbraVertices[n + i + 1].Position = new Vector3(lightSourcePos, 0) + vertexDir * 9000 + offset;
|
|
||||||
|
|
||||||
if (los)
|
|
||||||
{
|
{
|
||||||
PenumbraVertices[n + i + 1].TextureCoordinate = (i == 0) ? new Vector2(0.05f, 0.0f) : new Vector2(1.0f, 0.0f);
|
Position = penumbraStart + offset,
|
||||||
}
|
TextureCoordinate = new Vector2(0.0f, 1.0f)
|
||||||
else
|
};
|
||||||
|
|
||||||
|
for (int j = 0; j < 2; j++)
|
||||||
{
|
{
|
||||||
PenumbraVertices[n + i + 1].TextureCoordinate = (i == 0) ? new Vector2(1.0f, 0.0f) : Vector2.Zero;
|
PenumbraVertices[PenumbraVertexCount + j + 1] = new VertexPositionTexture();
|
||||||
|
Vector3 vertexDir = penumbraStart - new Vector3(lightSourcePos, 0);
|
||||||
|
vertexDir.Normalize();
|
||||||
|
|
||||||
|
Vector3 normal = (j == 0) ? new Vector3(-vertexDir.Y, vertexDir.X, 0.0f) : new Vector3(vertexDir.Y, -vertexDir.X, 0.0f) * 0.05f;
|
||||||
|
|
||||||
|
vertexDir = penumbraStart - (new Vector3(lightSourcePos, 0) - normal * 20.0f);
|
||||||
|
vertexDir.Normalize();
|
||||||
|
PenumbraVertices[PenumbraVertexCount + j + 1].Position = new Vector3(lightSourcePos, 0) + vertexDir * 9000 + offset;
|
||||||
|
|
||||||
|
PenumbraVertices[PenumbraVertexCount + j + 1].TextureCoordinate = (j == 0) ? new Vector2(0.05f, 0.0f) : new Vector2(1.0f, 0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PenumbraVertexCount += 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n > 0)
|
disjointed = losOffsets[i]?.B != null;
|
||||||
|
if (backFacing[currentIndex] && (disjointed || (!backFacing[nextIndex])))
|
||||||
{
|
{
|
||||||
var temp = PenumbraVertices[4];
|
Vector3 penumbraStart = new Vector3(vertexPos1, 0.0f);
|
||||||
PenumbraVertices[4] = PenumbraVertices[5];
|
|
||||||
PenumbraVertices[5] = temp;
|
PenumbraVertices[PenumbraVertexCount] = new VertexPositionTexture
|
||||||
|
{
|
||||||
|
Position = penumbraStart + offset,
|
||||||
|
TextureCoordinate = new Vector2(0.0f, 1.0f)
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int j = 0; j < 2; j++)
|
||||||
|
{
|
||||||
|
PenumbraVertices[PenumbraVertexCount + (1 - j) + 1] = new VertexPositionTexture();
|
||||||
|
Vector3 vertexDir = penumbraStart - new Vector3(lightSourcePos, 0);
|
||||||
|
vertexDir.Normalize();
|
||||||
|
|
||||||
|
Vector3 normal = (j == 0) ? new Vector3(-vertexDir.Y, vertexDir.X, 0.0f) : new Vector3(vertexDir.Y, -vertexDir.X, 0.0f) * 0.05f;
|
||||||
|
|
||||||
|
vertexDir = penumbraStart - (new Vector3(lightSourcePos, 0) + normal * 20.0f);
|
||||||
|
vertexDir.Normalize();
|
||||||
|
PenumbraVertices[PenumbraVertexCount + (1 - j) + 1].Position = new Vector3(lightSourcePos, 0) + vertexDir * 9000 + offset;
|
||||||
|
|
||||||
|
PenumbraVertices[PenumbraVertexCount + (1 - j) + 1].TextureCoordinate = (j == 0) ? new Vector2(0.05f, 0.0f) : new Vector2(1.0f, 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
PenumbraVertexCount += 3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -381,7 +381,7 @@ namespace Barotrauma.Lights
|
|||||||
if (GUI.DisableItemHighlights) { return false; }
|
if (GUI.DisableItemHighlights) { return false; }
|
||||||
|
|
||||||
highlightedEntities.Clear();
|
highlightedEntities.Clear();
|
||||||
if (Character.Controlled != null)
|
if (Character.Controlled != null && (!Character.Controlled.IsKeyDown(InputType.Aim) || Character.Controlled.SelectedItems.Any(it => it?.GetComponent<Sprayer>() == null)))
|
||||||
{
|
{
|
||||||
if (Character.Controlled.FocusedItem != null)
|
if (Character.Controlled.FocusedItem != null)
|
||||||
{
|
{
|
||||||
@@ -532,28 +532,16 @@ namespace Barotrauma.Lights
|
|||||||
Vector2 relativeLightPos = pos;
|
Vector2 relativeLightPos = pos;
|
||||||
if (convexHull.ParentEntity?.Submarine != null) relativeLightPos -= convexHull.ParentEntity.Submarine.Position;
|
if (convexHull.ParentEntity?.Submarine != null) relativeLightPos -= convexHull.ParentEntity.Submarine.Position;
|
||||||
|
|
||||||
convexHull.CalculateShadowVertices(relativeLightPos, true);
|
convexHull.CalculateLosVertices(relativeLightPos);
|
||||||
|
|
||||||
//convert triangle strips to a triangle list
|
for (int i = 0; i < convexHull.ShadowVertexCount; i++)
|
||||||
for (int i = 0; i < convexHull.ShadowVertexCount * 2 - 2; i++)
|
|
||||||
{
|
{
|
||||||
if (i % 2 == 0)
|
shadowVerts.Add(convexHull.ShadowVertices[i]);
|
||||||
{
|
|
||||||
shadowVerts.Add(convexHull.ShadowVertices[i]);
|
|
||||||
shadowVerts.Add(convexHull.ShadowVertices[i + 1]);
|
|
||||||
shadowVerts.Add(convexHull.ShadowVertices[i + 2]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
shadowVerts.Add(convexHull.ShadowVertices[i]);
|
|
||||||
shadowVerts.Add(convexHull.ShadowVertices[i + 2]);
|
|
||||||
shadowVerts.Add(convexHull.ShadowVertices[i + 1]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (convexHull.ShadowVertexCount > 0)
|
for (int i = 0; i < convexHull.PenumbraVertexCount; i++)
|
||||||
{
|
{
|
||||||
penumbraVerts.AddRange(convexHull.PenumbraVertices);
|
penumbraVerts.Add(convexHull.PenumbraVertices[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ namespace Barotrauma.Lights
|
|||||||
private short[] indices;
|
private short[] indices;
|
||||||
|
|
||||||
private List<ConvexHullList> hullsInRange;
|
private List<ConvexHullList> hullsInRange;
|
||||||
|
|
||||||
public Texture2D texture;
|
public Texture2D texture;
|
||||||
|
|
||||||
public SpriteEffects LightSpriteEffect;
|
public SpriteEffects LightSpriteEffect;
|
||||||
@@ -300,6 +300,14 @@ namespace Barotrauma.Lights
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public float TextureRange
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return lightSourceParams.TextureRange;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Background lights are drawn behind submarines and they don't cast shadows.
|
/// Background lights are drawn behind submarines and they don't cast shadows.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -366,7 +374,7 @@ namespace Barotrauma.Lights
|
|||||||
var fullChList = ConvexHull.HullLists.Find(x => x.Submarine == sub);
|
var fullChList = ConvexHull.HullLists.Find(x => x.Submarine == sub);
|
||||||
if (fullChList == null) return;
|
if (fullChList == null) return;
|
||||||
|
|
||||||
chList.List = fullChList.List.FindAll(ch => ch.Enabled && MathUtils.CircleIntersectsRectangle(lightPos, Range, ch.BoundingBox));
|
chList.List = fullChList.List.FindAll(ch => ch.Enabled && MathUtils.CircleIntersectsRectangle(lightPos, TextureRange, ch.BoundingBox));
|
||||||
|
|
||||||
NeedsHullCheck = true;
|
NeedsHullCheck = true;
|
||||||
}
|
}
|
||||||
@@ -418,7 +426,7 @@ namespace Barotrauma.Lights
|
|||||||
subBorders.Location += sub.HiddenSubPosition.ToPoint() - new Point(0, sub.Borders.Height);
|
subBorders.Location += sub.HiddenSubPosition.ToPoint() - new Point(0, sub.Borders.Height);
|
||||||
|
|
||||||
//only draw if the light overlaps with the sub
|
//only draw if the light overlaps with the sub
|
||||||
if (!MathUtils.CircleIntersectsRectangle(lightPos, Range, subBorders))
|
if (!MathUtils.CircleIntersectsRectangle(lightPos, TextureRange, subBorders))
|
||||||
{
|
{
|
||||||
if (chList.List.Count > 0) NeedsRecalculation = true;
|
if (chList.List.Count > 0) NeedsRecalculation = true;
|
||||||
chList.List.Clear();
|
chList.List.Clear();
|
||||||
@@ -452,7 +460,7 @@ namespace Barotrauma.Lights
|
|||||||
subBorders.Location += sub.HiddenSubPosition.ToPoint() - new Point(0, sub.Borders.Height);
|
subBorders.Location += sub.HiddenSubPosition.ToPoint() - new Point(0, sub.Borders.Height);
|
||||||
|
|
||||||
//don't draw any shadows if the light doesn't overlap with the borders of the sub
|
//don't draw any shadows if the light doesn't overlap with the borders of the sub
|
||||||
if (!MathUtils.CircleIntersectsRectangle(lightPos, Range, subBorders))
|
if (!MathUtils.CircleIntersectsRectangle(lightPos, TextureRange, subBorders))
|
||||||
{
|
{
|
||||||
if (chList.List.Count > 0) NeedsRecalculation = true;
|
if (chList.List.Count > 0) NeedsRecalculation = true;
|
||||||
chList.List.Clear();
|
chList.List.Clear();
|
||||||
@@ -495,7 +503,7 @@ namespace Barotrauma.Lights
|
|||||||
{
|
{
|
||||||
foreach (ConvexHull hull in chList.List)
|
foreach (ConvexHull hull in chList.List)
|
||||||
{
|
{
|
||||||
if (!chList.IsHidden.Contains(hull)) hulls.Add(hull);
|
if (!chList.IsHidden.Contains(hull)) { hulls.Add(hull); }
|
||||||
}
|
}
|
||||||
foreach (ConvexHull hull in chList.List)
|
foreach (ConvexHull hull in chList.List)
|
||||||
{
|
{
|
||||||
@@ -503,7 +511,7 @@ namespace Barotrauma.Lights
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float bounds = Range * 2;
|
float bounds = TextureRange;
|
||||||
//find convexhull segments that are close enough and facing towards the light source
|
//find convexhull segments that are close enough and facing towards the light source
|
||||||
List<Segment> visibleSegments = new List<Segment>();
|
List<Segment> visibleSegments = new List<Segment>();
|
||||||
List<SegmentPoint> points = new List<SegmentPoint>();
|
List<SegmentPoint> points = new List<SegmentPoint>();
|
||||||
@@ -513,6 +521,49 @@ namespace Barotrauma.Lights
|
|||||||
hull.GetVisibleSegments(drawPos, visibleSegments, ignoreEdges: false);
|
hull.GetVisibleSegments(drawPos, visibleSegments, ignoreEdges: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//add a square-shaped boundary to make sure we've got something to construct the triangles from
|
||||||
|
//even if there aren't enough hull segments around the light source
|
||||||
|
|
||||||
|
//(might be more effective to calculate if we actually need these extra points)
|
||||||
|
|
||||||
|
Vector2 drawOffset = Vector2.Zero;
|
||||||
|
float boundsExtended = bounds;
|
||||||
|
if (OverrideLightTexture != null)
|
||||||
|
{
|
||||||
|
float cosAngle = (float)Math.Cos(Rotation);
|
||||||
|
float sinAngle = -(float)Math.Sin(Rotation);
|
||||||
|
|
||||||
|
var overrideTextureDims = new Vector2(OverrideLightTexture.SourceRect.Width, OverrideLightTexture.SourceRect.Height);
|
||||||
|
|
||||||
|
Vector2 origin = OverrideLightTexture.Origin;
|
||||||
|
|
||||||
|
origin /= Math.Max(overrideTextureDims.X, overrideTextureDims.Y);
|
||||||
|
origin -= Vector2.One * 0.5f;
|
||||||
|
|
||||||
|
if (Math.Abs(origin.X) >= 0.45f || Math.Abs(origin.Y) >= 0.45f)
|
||||||
|
{
|
||||||
|
boundsExtended += 5.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
origin *= TextureRange;
|
||||||
|
|
||||||
|
drawOffset.X = -origin.X * cosAngle - origin.Y * sinAngle;
|
||||||
|
drawOffset.Y = origin.X * sinAngle + origin.Y * cosAngle;
|
||||||
|
}
|
||||||
|
|
||||||
|
var boundaryCorners = new SegmentPoint[] {
|
||||||
|
new SegmentPoint(new Vector2(drawPos.X + drawOffset.X + boundsExtended, drawPos.Y + drawOffset.Y + boundsExtended), null),
|
||||||
|
new SegmentPoint(new Vector2(drawPos.X + drawOffset.X + boundsExtended, drawPos.Y + drawOffset.Y - boundsExtended), null),
|
||||||
|
new SegmentPoint(new Vector2(drawPos.X + drawOffset.X - boundsExtended, drawPos.Y + drawOffset.Y - boundsExtended), null),
|
||||||
|
new SegmentPoint(new Vector2(drawPos.X + drawOffset.X - boundsExtended, drawPos.Y + drawOffset.Y + boundsExtended), null)
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
var s = new Segment(boundaryCorners[i], boundaryCorners[(i + 1) % 4], null);
|
||||||
|
visibleSegments.Add(s);
|
||||||
|
}
|
||||||
|
|
||||||
//Generate new points at the intersections between segments
|
//Generate new points at the intersections between segments
|
||||||
//This is necessary for the light volume to generate properly on some subs
|
//This is necessary for the light volume to generate properly on some subs
|
||||||
for (int i = 0; i < visibleSegments.Count; i++)
|
for (int i = 0; i < visibleSegments.Count; i++)
|
||||||
@@ -532,10 +583,10 @@ namespace Barotrauma.Lights
|
|||||||
Vector2 p2a = visibleSegments[j].Start.WorldPos;
|
Vector2 p2a = visibleSegments[j].Start.WorldPos;
|
||||||
Vector2 p2b = visibleSegments[j].End.WorldPos;
|
Vector2 p2b = visibleSegments[j].End.WorldPos;
|
||||||
|
|
||||||
if (Vector2.DistanceSquared(p1a, p2a) < 25.0f ||
|
if (Vector2.DistanceSquared(p1a, p2a) < 5.0f ||
|
||||||
Vector2.DistanceSquared(p1a, p2b) < 25.0f ||
|
Vector2.DistanceSquared(p1a, p2b) < 5.0f ||
|
||||||
Vector2.DistanceSquared(p1b, p2a) < 25.0f ||
|
Vector2.DistanceSquared(p1b, p2a) < 5.0f ||
|
||||||
Vector2.DistanceSquared(p1b, p2b) < 25.0f)
|
Vector2.DistanceSquared(p1b, p2b) < 5.0f)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -565,8 +616,8 @@ namespace Barotrauma.Lights
|
|||||||
mid.Pos -= visibleSegments[i].ConvexHull.ParentEntity.Submarine.DrawPosition;
|
mid.Pos -= visibleSegments[i].ConvexHull.ParentEntity.Submarine.DrawPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Vector2.DistanceSquared(start.WorldPos, mid.WorldPos) < 25.0f ||
|
if (Vector2.DistanceSquared(start.WorldPos, mid.WorldPos) < 5.0f ||
|
||||||
Vector2.DistanceSquared(end.WorldPos, mid.WorldPos) < 25.0f)
|
Vector2.DistanceSquared(end.WorldPos, mid.WorldPos) < 5.0f)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -580,6 +631,7 @@ namespace Barotrauma.Lights
|
|||||||
{
|
{
|
||||||
IsHorizontal = visibleSegments[i].IsHorizontal
|
IsHorizontal = visibleSegments[i].IsHorizontal
|
||||||
};
|
};
|
||||||
|
|
||||||
visibleSegments[i] = seg1;
|
visibleSegments[i] = seg1;
|
||||||
visibleSegments.Insert(i + 1, seg2);
|
visibleSegments.Insert(i + 1, seg2);
|
||||||
i--;
|
i--;
|
||||||
@@ -588,34 +640,27 @@ namespace Barotrauma.Lights
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (Segment s in visibleSegments)
|
//remove segments that fall out of bounds
|
||||||
|
for (int i = 0; i < visibleSegments.Count; i++)
|
||||||
{
|
{
|
||||||
points.Add(s.Start);
|
Segment s = visibleSegments[i];
|
||||||
points.Add(s.End);
|
if (Math.Abs(s.Start.WorldPos.X - drawPos.X - drawOffset.X) > boundsExtended + 1.0f ||
|
||||||
if (Math.Abs(s.Start.WorldPos.X - drawPos.X) > bounds) bounds = Math.Abs(s.Start.WorldPos.X - drawPos.X);
|
Math.Abs(s.Start.WorldPos.Y - drawPos.Y - drawOffset.Y) > boundsExtended + 1.0f ||
|
||||||
if (Math.Abs(s.Start.WorldPos.Y - drawPos.Y) > bounds) bounds = Math.Abs(s.Start.WorldPos.Y - drawPos.Y);
|
Math.Abs(s.End.WorldPos.X - drawPos.X - drawOffset.X) > boundsExtended + 1.0f ||
|
||||||
if (Math.Abs(s.End.WorldPos.X - drawPos.X) > bounds) bounds = Math.Abs(s.End.WorldPos.X - drawPos.X);
|
Math.Abs(s.End.WorldPos.Y - drawPos.Y - drawOffset.Y) > boundsExtended + 1.0f)
|
||||||
if (Math.Abs(s.End.WorldPos.Y - drawPos.Y) > bounds) bounds = Math.Abs(s.End.WorldPos.Y - drawPos.Y);
|
{
|
||||||
|
visibleSegments.RemoveAt(i);
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
points.Add(s.Start);
|
||||||
|
points.Add(s.End);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//add a square-shaped boundary to make sure we've got something to construct the triangles from
|
visibleSegments = visibleSegments.OrderBy(s => MathUtils.LineToPointDistanceSquared(s.Start.WorldPos, s.End.WorldPos, drawPos)).ToList();
|
||||||
//even if there aren't enough hull segments around the light source
|
|
||||||
|
|
||||||
//(might be more effective to calculate if we actually need these extra points)
|
|
||||||
var boundaryCorners = new List<SegmentPoint> {
|
|
||||||
new SegmentPoint(new Vector2(drawPos.X + bounds, drawPos.Y + bounds), null),
|
|
||||||
new SegmentPoint(new Vector2(drawPos.X + bounds, drawPos.Y - bounds), null),
|
|
||||||
new SegmentPoint(new Vector2(drawPos.X - bounds, drawPos.Y - bounds), null),
|
|
||||||
new SegmentPoint(new Vector2(drawPos.X - bounds, drawPos.Y + bounds), null)
|
|
||||||
};
|
|
||||||
|
|
||||||
points.AddRange(boundaryCorners);
|
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++)
|
|
||||||
{
|
|
||||||
visibleSegments.Add(new Segment(boundaryCorners[i], boundaryCorners[(i + 1) % 4], null));
|
|
||||||
}
|
|
||||||
|
|
||||||
var compareCCW = new CompareSegmentPointCW(drawPos);
|
var compareCCW = new CompareSegmentPointCW(drawPos);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -635,13 +680,15 @@ namespace Barotrauma.Lights
|
|||||||
//List<Pair<int, Vector2>> preOutput = new List<Pair<int, Vector2>>();
|
//List<Pair<int, Vector2>> preOutput = new List<Pair<int, Vector2>>();
|
||||||
|
|
||||||
//remove points that are very close to each other
|
//remove points that are very close to each other
|
||||||
for (int i = 0; i < points.Count - 1; i++)
|
for (int i = 0; i < points.Count; i++)
|
||||||
{
|
{
|
||||||
if (Math.Abs(points[i].WorldPos.X - points[i + 1].WorldPos.X) < 6 &&
|
for (int j = Math.Min(i + 4, points.Count-1); j > i; j--)
|
||||||
Math.Abs(points[i].WorldPos.Y - points[i + 1].WorldPos.Y) < 6)
|
|
||||||
{
|
{
|
||||||
points.RemoveAt(i + 1);
|
if (Math.Abs(points[i].WorldPos.X - points[j].WorldPos.X) < 6 &&
|
||||||
i--;
|
Math.Abs(points[i].WorldPos.Y - points[j].WorldPos.Y) < 6)
|
||||||
|
{
|
||||||
|
points.RemoveAt(j);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -651,16 +698,16 @@ namespace Barotrauma.Lights
|
|||||||
Vector2 dirNormal = new Vector2(-dir.Y, dir.X) * 3;
|
Vector2 dirNormal = new Vector2(-dir.Y, dir.X) * 3;
|
||||||
|
|
||||||
//do two slightly offset raycasts to hit the segment itself and whatever's behind it
|
//do two slightly offset raycasts to hit the segment itself and whatever's behind it
|
||||||
Pair<int,Vector2> intersection1 = RayCast(drawPos, drawPos + dir * bounds * 2 - dirNormal, visibleSegments);
|
Pair<int,Vector2> intersection1 = RayCast(drawPos, drawPos + dir * boundsExtended * 2 - dirNormal, visibleSegments);
|
||||||
Pair<int,Vector2> intersection2 = RayCast(drawPos, drawPos + dir * bounds * 2 + dirNormal, visibleSegments);
|
Pair<int,Vector2> intersection2 = RayCast(drawPos, drawPos + dir * boundsExtended * 2 + dirNormal, visibleSegments);
|
||||||
|
|
||||||
if (intersection1.First < 0) return new List<Vector2>();
|
if (intersection1.First < 0) return null;
|
||||||
if (intersection2.First < 0) return new List<Vector2>();
|
if (intersection2.First < 0) return null;
|
||||||
Segment seg1 = visibleSegments[intersection1.First];
|
Segment seg1 = visibleSegments[intersection1.First];
|
||||||
Segment seg2 = visibleSegments[intersection2.First];
|
Segment seg2 = visibleSegments[intersection2.First];
|
||||||
|
|
||||||
bool isPoint1 = MathUtils.LineToPointDistance(seg1.Start.WorldPos, seg1.End.WorldPos, p.WorldPos) < 5.0f;
|
bool isPoint1 = MathUtils.LineToPointDistanceSquared(seg1.Start.WorldPos, seg1.End.WorldPos, p.WorldPos) < 25.0f;
|
||||||
bool isPoint2 = MathUtils.LineToPointDistance(seg2.Start.WorldPos, seg2.End.WorldPos, p.WorldPos) < 5.0f;
|
bool isPoint2 = MathUtils.LineToPointDistanceSquared(seg2.Start.WorldPos, seg2.End.WorldPos, p.WorldPos) < 25.0f;
|
||||||
|
|
||||||
if (isPoint1 && isPoint2)
|
if (isPoint1 && isPoint2)
|
||||||
{
|
{
|
||||||
@@ -696,11 +743,13 @@ namespace Barotrauma.Lights
|
|||||||
//remove points that are very close to each other
|
//remove points that are very close to each other
|
||||||
for (int i = 0; i < output.Count - 1; i++)
|
for (int i = 0; i < output.Count - 1; i++)
|
||||||
{
|
{
|
||||||
if (Math.Abs(output[i].X - output[i + 1].X) < 6 &&
|
for (int j = Math.Min(i + 4, output.Count - 1); j > i; j--)
|
||||||
Math.Abs(output[i].Y - output[i + 1].Y) < 6)
|
|
||||||
{
|
{
|
||||||
output.RemoveAt(i + 1);
|
if (Math.Abs(output[i].X - output[j].X) < 6 &&
|
||||||
i--;
|
Math.Abs(output[i].Y - output[j].Y) < 6)
|
||||||
|
{
|
||||||
|
output.RemoveAt(j);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -709,7 +758,6 @@ namespace Barotrauma.Lights
|
|||||||
|
|
||||||
private Pair<int, Vector2> RayCast(Vector2 rayStart, Vector2 rayEnd, List<Segment> segments)
|
private Pair<int, Vector2> RayCast(Vector2 rayStart, Vector2 rayEnd, List<Segment> segments)
|
||||||
{
|
{
|
||||||
float closestDist = float.PositiveInfinity;
|
|
||||||
Vector2? closestIntersection = null;
|
Vector2? closestIntersection = null;
|
||||||
int segment = -1;
|
int segment = -1;
|
||||||
|
|
||||||
@@ -724,11 +772,11 @@ namespace Barotrauma.Lights
|
|||||||
|
|
||||||
//segment's end position always has a higher or equal y coordinate than the start position
|
//segment's end position always has a higher or equal y coordinate than the start position
|
||||||
//so we can do this comparison and skip segments that are at the wrong side of the ray
|
//so we can do this comparison and skip segments that are at the wrong side of the ray
|
||||||
if (s.End.WorldPos.Y < s.Start.WorldPos.Y)
|
/*if (s.End.WorldPos.Y < s.Start.WorldPos.Y)
|
||||||
{
|
{
|
||||||
System.Diagnostics.Debug.Assert(s.End.WorldPos.Y >= s.Start.WorldPos.Y,
|
System.Diagnostics.Debug.Assert(s.End.WorldPos.Y >= s.Start.WorldPos.Y,
|
||||||
"LightSource raycast failed. Segment's end positions should never be below the start position. Parent entity: " + (s.ConvexHull?.ParentEntity == null ? "null" : s.ConvexHull.ParentEntity.ToString()));
|
"LightSource raycast failed. Segment's end positions should never be below the start position. Parent entity: " + (s.ConvexHull?.ParentEntity == null ? "null" : s.ConvexHull.ParentEntity.ToString()));
|
||||||
}
|
}*/
|
||||||
if (s.Start.WorldPos.Y > maxY || s.End.WorldPos.Y < minY) { continue; }
|
if (s.Start.WorldPos.Y > maxY || s.End.WorldPos.Y < minY) { continue; }
|
||||||
//same for the x-axis
|
//same for the x-axis
|
||||||
if (s.Start.WorldPos.X > s.End.WorldPos.X)
|
if (s.Start.WorldPos.X > s.End.WorldPos.X)
|
||||||
@@ -741,18 +789,29 @@ namespace Barotrauma.Lights
|
|||||||
if (s.End.WorldPos.X < minX) continue;
|
if (s.End.WorldPos.X < minX) continue;
|
||||||
if (s.Start.WorldPos.X > maxX) continue;
|
if (s.Start.WorldPos.X > maxX) continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s.IsAxisAligned ?
|
bool intersects;
|
||||||
MathUtils.GetAxisAlignedLineIntersection(rayStart, rayEnd, s.Start.WorldPos, s.End.WorldPos, s.IsHorizontal, out Vector2 intersection) :
|
Vector2 intersection;
|
||||||
MathUtils.GetLineIntersection(rayStart, rayEnd, s.Start.WorldPos, s.End.WorldPos, out intersection))
|
if (s.IsAxisAligned)
|
||||||
{
|
{
|
||||||
float dist = Vector2.DistanceSquared(intersection, rayStart);
|
intersects = MathUtils.GetAxisAlignedLineIntersection(rayStart, rayEnd, s.Start.WorldPos, s.End.WorldPos, s.IsHorizontal, out intersection);
|
||||||
if (dist < closestDist)
|
}
|
||||||
{
|
else
|
||||||
closestDist = dist;
|
{
|
||||||
closestIntersection = intersection;
|
intersects = MathUtils.GetLineIntersection(rayStart, rayEnd, s.Start.WorldPos, s.End.WorldPos, out intersection);
|
||||||
segment = i;
|
}
|
||||||
}
|
|
||||||
|
if (intersects)
|
||||||
|
{
|
||||||
|
closestIntersection = intersection;
|
||||||
|
|
||||||
|
rayEnd = intersection;
|
||||||
|
minX = Math.Min(rayStart.X, rayEnd.X);
|
||||||
|
maxX = Math.Max(rayStart.X, rayEnd.X);
|
||||||
|
minY = Math.Min(rayStart.Y, rayEnd.Y);
|
||||||
|
maxY = Math.Max(rayStart.Y, rayEnd.Y);
|
||||||
|
|
||||||
|
segment = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -797,7 +856,7 @@ namespace Barotrauma.Lights
|
|||||||
|
|
||||||
//hacky fix to exc excessively large light volumes (they used to be up to 4x the range of the light if there was nothing to block the rays).
|
//hacky fix to exc excessively large light volumes (they used to be up to 4x the range of the light if there was nothing to block the rays).
|
||||||
//might want to tweak the raycast logic in a way that this isn't necessary
|
//might want to tweak the raycast logic in a way that this isn't necessary
|
||||||
float boundRadius = Range * 1.1f / (1.0f - Math.Max(Math.Abs(uvOffset.X), Math.Abs(uvOffset.Y)));
|
/*float boundRadius = Range * 1.1f / (1.0f - Math.Max(Math.Abs(uvOffset.X), Math.Abs(uvOffset.Y)));
|
||||||
Rectangle boundArea = new Rectangle((int)(drawPos.X - boundRadius), (int)(drawPos.Y + boundRadius), (int)(boundRadius * 2), (int)(boundRadius * 2));
|
Rectangle boundArea = new Rectangle((int)(drawPos.X - boundRadius), (int)(drawPos.Y + boundRadius), (int)(boundRadius * 2), (int)(boundRadius * 2));
|
||||||
for (int i = 0; i < rayCastHits.Count; i++)
|
for (int i = 0; i < rayCastHits.Count; i++)
|
||||||
{
|
{
|
||||||
@@ -805,7 +864,7 @@ namespace Barotrauma.Lights
|
|||||||
{
|
{
|
||||||
rayCastHits[i] = intersection;
|
rayCastHits[i] = intersection;
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
// Add all the other encounter points as vertices
|
// Add all the other encounter points as vertices
|
||||||
// storing their world position as UV coordinates
|
// storing their world position as UV coordinates
|
||||||
@@ -818,7 +877,7 @@ namespace Barotrauma.Lights
|
|||||||
//so we can add new vertices based on these normals
|
//so we can add new vertices based on these normals
|
||||||
Vector2 prevVertex = rayCastHits[i > 0 ? i - 1 : rayCastHits.Count - 1];
|
Vector2 prevVertex = rayCastHits[i > 0 ? i - 1 : rayCastHits.Count - 1];
|
||||||
Vector2 nextVertex = rayCastHits[i < rayCastHits.Count - 1 ? i + 1 : 0];
|
Vector2 nextVertex = rayCastHits[i < rayCastHits.Count - 1 ? i + 1 : 0];
|
||||||
|
|
||||||
Vector2 rawDiff = vertex - drawPos;
|
Vector2 rawDiff = vertex - drawPos;
|
||||||
|
|
||||||
//calculate normal of first segment
|
//calculate normal of first segment
|
||||||
@@ -836,12 +895,18 @@ namespace Barotrauma.Lights
|
|||||||
//if the normal is pointing towards the light origin
|
//if the normal is pointing towards the light origin
|
||||||
//rather than away from it, invert it
|
//rather than away from it, invert it
|
||||||
if (Vector2.DistanceSquared(nDiff2, rawDiff) > Vector2.DistanceSquared(-nDiff2, rawDiff)) nDiff2 = -nDiff2;
|
if (Vector2.DistanceSquared(nDiff2, rawDiff) > Vector2.DistanceSquared(-nDiff2, rawDiff)) nDiff2 = -nDiff2;
|
||||||
|
|
||||||
//add the normals together and use some magic numbers to create
|
//add the normals together and use some magic numbers to create
|
||||||
//a somewhat useful/good-looking blur
|
//a somewhat useful/good-looking blur
|
||||||
Vector2 nDiff = nDiff1 + nDiff2;
|
Vector2 nDiff = nDiff1 * 40.0f;
|
||||||
nDiff /= Math.Max(Math.Abs(nDiff.X), Math.Abs(nDiff.Y));
|
if (MathUtils.GetLineIntersection(vertex + (nDiff1 * 40.0f), nextVertex + (nDiff1 * 40.0f), vertex + (nDiff2 * 40.0f), prevVertex + (nDiff2 * 40.0f), true, out Vector2 intersection))
|
||||||
nDiff *= 50.0f;
|
{
|
||||||
|
nDiff = intersection - vertex;
|
||||||
|
if (nDiff.LengthSquared() > 10000.0f)
|
||||||
|
{
|
||||||
|
nDiff /= Math.Max(Math.Abs(nDiff.X), Math.Abs(nDiff.Y)); nDiff *= 100.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Vector2 diff = rawDiff;
|
Vector2 diff = rawDiff;
|
||||||
diff /= Range * 2.0f;
|
diff /= Range * 2.0f;
|
||||||
@@ -948,6 +1013,50 @@ namespace Barotrauma.Lights
|
|||||||
/// <param name="spriteBatch"></param>
|
/// <param name="spriteBatch"></param>
|
||||||
public void DrawSprite(SpriteBatch spriteBatch, Camera cam)
|
public void DrawSprite(SpriteBatch spriteBatch, Camera cam)
|
||||||
{
|
{
|
||||||
|
if (GameMain.DebugDraw)
|
||||||
|
{
|
||||||
|
Vector2 drawPos = position;
|
||||||
|
if (ParentSub != null)
|
||||||
|
{
|
||||||
|
drawPos += ParentSub.DrawPosition;
|
||||||
|
}
|
||||||
|
drawPos.Y = -drawPos.Y;
|
||||||
|
|
||||||
|
float cosAngle = (float)Math.Cos(Rotation);
|
||||||
|
float sinAngle = -(float)Math.Sin(Rotation);
|
||||||
|
|
||||||
|
float bounds = TextureRange;
|
||||||
|
|
||||||
|
if (OverrideLightTexture != null)
|
||||||
|
{
|
||||||
|
var overrideTextureDims = new Vector2(OverrideLightTexture.SourceRect.Width, OverrideLightTexture.SourceRect.Height);
|
||||||
|
|
||||||
|
Vector2 origin = OverrideLightTexture.Origin;
|
||||||
|
|
||||||
|
origin /= Math.Max(overrideTextureDims.X, overrideTextureDims.Y);
|
||||||
|
origin *= TextureRange;
|
||||||
|
|
||||||
|
drawPos.X += origin.X * sinAngle + origin.Y * cosAngle;
|
||||||
|
drawPos.Y += origin.X * cosAngle + origin.Y * sinAngle;
|
||||||
|
}
|
||||||
|
|
||||||
|
//add a square-shaped boundary to make sure we've got something to construct the triangles from
|
||||||
|
//even if there aren't enough hull segments around the light source
|
||||||
|
|
||||||
|
//(might be more effective to calculate if we actually need these extra points)
|
||||||
|
var boundaryCorners = new SegmentPoint[] {
|
||||||
|
new SegmentPoint(new Vector2(drawPos.X + bounds, drawPos.Y + bounds), null),
|
||||||
|
new SegmentPoint(new Vector2(drawPos.X + bounds, drawPos.Y - bounds), null),
|
||||||
|
new SegmentPoint(new Vector2(drawPos.X - bounds, drawPos.Y - bounds), null),
|
||||||
|
new SegmentPoint(new Vector2(drawPos.X - bounds, drawPos.Y + bounds), null)
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int i=0;i<4;i++)
|
||||||
|
{
|
||||||
|
GUI.DrawLine(spriteBatch, boundaryCorners[i].Pos, boundaryCorners[(i + 1) % 4].Pos, Color.White, 0, 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (DeformableLightSprite != null)
|
if (DeformableLightSprite != null)
|
||||||
{
|
{
|
||||||
Vector2 origin = DeformableLightSprite.Origin;
|
Vector2 origin = DeformableLightSprite.Origin;
|
||||||
@@ -976,11 +1085,11 @@ namespace Barotrauma.Lights
|
|||||||
if (LightSprite != null)
|
if (LightSprite != null)
|
||||||
{
|
{
|
||||||
Vector2 origin = LightSprite.Origin;
|
Vector2 origin = LightSprite.Origin;
|
||||||
if (LightSpriteEffect == SpriteEffects.FlipHorizontally)
|
if ((LightSpriteEffect & SpriteEffects.FlipHorizontally) == SpriteEffects.FlipHorizontally)
|
||||||
{
|
{
|
||||||
origin.X = LightSprite.SourceRect.Width - origin.X;
|
origin.X = LightSprite.SourceRect.Width - origin.X;
|
||||||
}
|
}
|
||||||
if (LightSpriteEffect == SpriteEffects.FlipVertically)
|
if ((LightSpriteEffect & SpriteEffects.FlipVertically) == SpriteEffects.FlipVertically)
|
||||||
{
|
{
|
||||||
origin.Y = LightSprite.SourceRect.Height - origin.Y;
|
origin.Y = LightSprite.SourceRect.Height - origin.Y;
|
||||||
}
|
}
|
||||||
@@ -1088,7 +1197,7 @@ namespace Barotrauma.Lights
|
|||||||
PrimitiveType.TriangleList, 0, 0, indexCount / 3
|
PrimitiveType.TriangleList, 0, 0, indexCount / 3
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Reset()
|
public void Reset()
|
||||||
{
|
{
|
||||||
hullsInRange.Clear();
|
hullsInRange.Clear();
|
||||||
|
|||||||
@@ -9,8 +9,6 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
partial class Map
|
partial class Map
|
||||||
{
|
{
|
||||||
public bool AllowDebugTeleport;
|
|
||||||
|
|
||||||
class MapAnim
|
class MapAnim
|
||||||
{
|
{
|
||||||
public Location StartLocation;
|
public Location StartLocation;
|
||||||
@@ -380,6 +378,7 @@ namespace Barotrauma
|
|||||||
Location prevLocation = CurrentDisplayLocation;
|
Location prevLocation = CurrentDisplayLocation;
|
||||||
CurrentLocation = HighlightedLocation;
|
CurrentLocation = HighlightedLocation;
|
||||||
Level.Loaded.DebugSetStartLocation(CurrentLocation);
|
Level.Loaded.DebugSetStartLocation(CurrentLocation);
|
||||||
|
Level.Loaded.DebugSetEndLocation(null);
|
||||||
|
|
||||||
CurrentLocation.Discovered = true;
|
CurrentLocation.Discovered = true;
|
||||||
CurrentLocation.CreateStore();
|
CurrentLocation.CreateStore();
|
||||||
@@ -573,7 +572,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GameMain.DebugDraw && location == HighlightedLocation)
|
if (GameMain.DebugDraw && location == HighlightedLocation && (!location.Discovered || !location.Type.HasOutpost))
|
||||||
{
|
{
|
||||||
if (location.Reputation != null)
|
if (location.Reputation != null)
|
||||||
{
|
{
|
||||||
@@ -589,7 +588,7 @@ namespace Barotrauma
|
|||||||
Color barColor = ToolBox.GradientLerp(location.Reputation.NormalizedValue, Color.Red, Color.Yellow, Color.LightGreen);
|
Color barColor = ToolBox.GradientLerp(location.Reputation.NormalizedValue, Color.Red, Color.Yellow, Color.LightGreen);
|
||||||
GUI.DrawRectangle(spriteBatch, bgRect, Color.Black * 0.8f, isFilled: true);
|
GUI.DrawRectangle(spriteBatch, bgRect, Color.Black * 0.8f, isFilled: true);
|
||||||
GUI.DrawRectangle(spriteBatch, new Rectangle((int)dPos.X, (int)dPos.Y, (int)(location.Reputation.NormalizedValue * 255), 32), barColor, isFilled: true);
|
GUI.DrawRectangle(spriteBatch, new Rectangle((int)dPos.X, (int)dPos.Y, (int)(location.Reputation.NormalizedValue * 255), 32), barColor, isFilled: true);
|
||||||
string reputationValue = location.Reputation.Value.ToString(CultureInfo.InvariantCulture);
|
string reputationValue = ((int)location.Reputation.Value).ToString();
|
||||||
Vector2 repValueSize = GUI.SubHeadingFont.MeasureString(reputationValue);
|
Vector2 repValueSize = GUI.SubHeadingFont.MeasureString(reputationValue);
|
||||||
GUI.DrawString(spriteBatch, dPos + (new Vector2(256, 32) / 2) - (repValueSize / 2), reputationValue, Color.White, Color.Black, font: GUI.SubHeadingFont);
|
GUI.DrawString(spriteBatch, dPos + (new Vector2(256, 32) / 2) - (repValueSize / 2), reputationValue, Color.White, Color.Black, font: GUI.SubHeadingFont);
|
||||||
GUI.DrawRectangle(spriteBatch, new Rectangle((int)dPos.X, (int)dPos.Y, 256, 32), Color.White);
|
GUI.DrawRectangle(spriteBatch, new Rectangle((int)dPos.X, (int)dPos.Y, 256, 32), Color.White);
|
||||||
@@ -607,12 +606,34 @@ namespace Barotrauma
|
|||||||
Vector2 nameSize = GUI.LargeFont.MeasureString(HighlightedLocation.Name);
|
Vector2 nameSize = GUI.LargeFont.MeasureString(HighlightedLocation.Name);
|
||||||
Vector2 typeSize = GUI.Font.MeasureString(HighlightedLocation.Type.Name);
|
Vector2 typeSize = GUI.Font.MeasureString(HighlightedLocation.Type.Name);
|
||||||
Vector2 size = new Vector2(Math.Max(nameSize.X, typeSize.X), nameSize.Y + typeSize.Y);
|
Vector2 size = new Vector2(Math.Max(nameSize.X, typeSize.X), nameSize.Y + typeSize.Y);
|
||||||
|
bool showReputation = HighlightedLocation.Discovered && HighlightedLocation.Type.HasOutpost && HighlightedLocation.Reputation != null;
|
||||||
|
string repLabelText = null, repValueText = null;
|
||||||
|
Vector2 repLabelSize = Vector2.Zero, repBarSize = Vector2.Zero;
|
||||||
|
if (showReputation)
|
||||||
|
{
|
||||||
|
repLabelText = TextManager.Get("reputation");
|
||||||
|
repLabelSize = GUI.Font.MeasureString(repLabelText);
|
||||||
|
size.X = Math.Max(size.X, repLabelSize.X);
|
||||||
|
repBarSize = new Vector2(Math.Max(0.75f * size.X, 100), repLabelSize.Y);
|
||||||
|
size.X = Math.Max(size.X, (4.0f / 3.0f) * repBarSize.X);
|
||||||
|
size.Y += 2 * repLabelSize.Y + 4 + repBarSize.Y;
|
||||||
|
repValueText = ((int)HighlightedLocation.Reputation.Value).ToString();
|
||||||
|
}
|
||||||
GUI.Style.GetComponentStyle("OuterGlow").Sprites[GUIComponent.ComponentState.None][0].Draw(
|
GUI.Style.GetComponentStyle("OuterGlow").Sprites[GUIComponent.ComponentState.None][0].Draw(
|
||||||
spriteBatch, new Rectangle((int)(pos.X - 60 * GUI.Scale), (int)(pos.Y - size.Y), (int)(size.X + 120 * GUI.Scale), (int)(size.Y * 2.2f)), Color.Black * hudVisibility);
|
spriteBatch, new Rectangle((int)(pos.X - 60 * GUI.Scale), (int)(pos.Y - size.Y), (int)(size.X + 120 * GUI.Scale), (int)(size.Y * 2.2f)), Color.Black * hudVisibility);
|
||||||
GUI.DrawString(spriteBatch, pos - new Vector2(0.0f, size.Y / 2),
|
var topLeftPos = pos - new Vector2(0.0f, size.Y / 2);
|
||||||
HighlightedLocation.Name, GUI.Style.TextColor * hudVisibility * 1.5f, font: GUI.LargeFont);
|
GUI.DrawString(spriteBatch, topLeftPos, HighlightedLocation.Name, GUI.Style.TextColor * hudVisibility * 1.5f, font: GUI.LargeFont);
|
||||||
GUI.DrawString(spriteBatch, pos + new Vector2(0.0f, size.Y / 2 - GUI.Font.MeasureString(HighlightedLocation.Type.Name).Y),
|
topLeftPos += new Vector2(0.0f, nameSize.Y);
|
||||||
HighlightedLocation.Type.Name, GUI.Style.TextColor * hudVisibility * 1.5f);
|
GUI.DrawString(spriteBatch, topLeftPos, HighlightedLocation.Type.Name, GUI.Style.TextColor * hudVisibility * 1.5f);
|
||||||
|
if (showReputation)
|
||||||
|
{
|
||||||
|
topLeftPos += new Vector2(0.0f, typeSize.Y + repLabelSize.Y);
|
||||||
|
GUI.DrawString(spriteBatch, topLeftPos, repLabelText, GUI.Style.TextColor * hudVisibility * 1.5f);
|
||||||
|
topLeftPos += new Vector2(0.0f, repLabelSize.Y + 4);
|
||||||
|
Rectangle repBarRect = new Rectangle(new Point((int)topLeftPos.X, (int)topLeftPos.Y), new Point((int)repBarSize.X, (int)repBarSize.Y));
|
||||||
|
RoundSummary.DrawReputationBar(spriteBatch, repBarRect, HighlightedLocation.Reputation.NormalizedValue);
|
||||||
|
GUI.DrawString(spriteBatch, new Vector2(repBarRect.Right + 4, repBarRect.Top), repValueText, GUI.Style.TextColor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (tooltip != null)
|
if (tooltip != null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -159,6 +159,31 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (PlayerInput.IsCtrlDown())
|
if (PlayerInput.IsCtrlDown())
|
||||||
{
|
{
|
||||||
|
#if DEBUG
|
||||||
|
if (PlayerInput.KeyHit(Keys.D))
|
||||||
|
{
|
||||||
|
bool terminate = false;
|
||||||
|
foreach (MapEntity entity in selectedList)
|
||||||
|
{
|
||||||
|
if (entity is Item item && item.GetComponent<Planter>() is { } planter)
|
||||||
|
{
|
||||||
|
planter.Update(1.0f, cam);
|
||||||
|
for (var i = 0; i < planter.GrowableSeeds.Length; i++)
|
||||||
|
{
|
||||||
|
Growable seed = planter.GrowableSeeds[i];
|
||||||
|
PlantSlot slot = planter.PlantSlots.ContainsKey(i) ? planter.PlantSlots[i] : Planter.NullSlot;
|
||||||
|
if (seed == null) { continue; }
|
||||||
|
|
||||||
|
seed.CreateDebugHUD(planter, slot);
|
||||||
|
terminate = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (terminate) { break; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
if (PlayerInput.KeyHit(Keys.C))
|
if (PlayerInput.KeyHit(Keys.C))
|
||||||
{
|
{
|
||||||
Copy(selectedList);
|
Copy(selectedList);
|
||||||
@@ -897,8 +922,9 @@ namespace Barotrauma
|
|||||||
Clone(copiedList);
|
Clone(copiedList);
|
||||||
|
|
||||||
var clones = mapEntityList.Except(prevEntities).ToList();
|
var clones = mapEntityList.Except(prevEntities).ToList();
|
||||||
|
|
||||||
var nonWireClones = clones.Where(c => !(c is Item item) || item.GetComponent<Wire>() == null);
|
var nonWireClones = clones.Where(c => !(c is Item item) || item.GetComponent<Wire>() == null);
|
||||||
|
if (!nonWireClones.Any()) { nonWireClones = clones; }
|
||||||
|
|
||||||
Vector2 center = Vector2.Zero;
|
Vector2 center = Vector2.Zero;
|
||||||
nonWireClones.ForEach(c => center += c.WorldPosition);
|
nonWireClones.ForEach(c => center += c.WorldPosition);
|
||||||
center = Submarine.VectorToWorldGrid(center / nonWireClones.Count());
|
center = Submarine.VectorToWorldGrid(center / nonWireClones.Count());
|
||||||
|
|||||||
@@ -185,9 +185,20 @@ namespace Barotrauma
|
|||||||
public override bool IsVisible(Rectangle worldView)
|
public override bool IsVisible(Rectangle worldView)
|
||||||
{
|
{
|
||||||
Rectangle worldRect = WorldRect;
|
Rectangle worldRect = WorldRect;
|
||||||
|
Vector2 worldPos = WorldPosition;
|
||||||
|
|
||||||
if (worldRect.X > worldView.Right || worldRect.Right < worldView.X) { return false; }
|
Vector2 min = new Vector2(worldRect.X, worldRect.Y - worldRect.Height);
|
||||||
if (worldRect.Y < worldView.Y - worldView.Height || worldRect.Y - worldRect.Height > worldView.Y) { return false; }
|
Vector2 max = new Vector2(worldRect.Right, worldRect.Y);
|
||||||
|
foreach (DecorativeSprite decorativeSprite in Prefab.DecorativeSprites)
|
||||||
|
{
|
||||||
|
min.X = Math.Min(worldPos.X - decorativeSprite.Sprite.size.X * decorativeSprite.Sprite.RelativeOrigin.X * decorativeSprite.Scale * Scale, min.X);
|
||||||
|
max.X = Math.Max(worldPos.X + decorativeSprite.Sprite.size.X * (1.0f - decorativeSprite.Sprite.RelativeOrigin.X) * decorativeSprite.Scale * Scale, max.X);
|
||||||
|
min.Y = Math.Min(worldPos.Y - decorativeSprite.Sprite.size.Y * (1.0f - decorativeSprite.Sprite.RelativeOrigin.Y) * decorativeSprite.Scale * Scale, min.Y);
|
||||||
|
max.Y = Math.Max(worldPos.Y + decorativeSprite.Sprite.size.Y * decorativeSprite.Sprite.RelativeOrigin.Y * decorativeSprite.Scale * Scale, max.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (min.X > worldView.Right || max.X < worldView.X) { return false; }
|
||||||
|
if ( min.Y > worldView.Y || max.Y < worldView.Y - worldView.Height) { return false; }
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -455,8 +466,16 @@ namespace Barotrauma
|
|||||||
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
||||||
{
|
{
|
||||||
byte sectionCount = msg.ReadByte();
|
byte sectionCount = msg.ReadByte();
|
||||||
if (sectionCount != Sections.Length)
|
|
||||||
|
bool invalidMessage = false;
|
||||||
|
if (type != ServerNetObject.ENTITY_EVENT && type != ServerNetObject.ENTITY_EVENT_INITIAL)
|
||||||
{
|
{
|
||||||
|
DebugConsole.NewMessage($"Error while reading a network event for the structure \"{Name} ({ID})\". Invalid event type ({type}).", Color.Red);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (sectionCount != Sections.Length)
|
||||||
|
{
|
||||||
|
invalidMessage = true;
|
||||||
string errorMsg = $"Error while reading a network event for the structure \"{Name} ({ID})\". Section count does not match (server: {sectionCount} client: {Sections.Length})";
|
string errorMsg = $"Error while reading a network event for the structure \"{Name} ({ID})\". Section count does not match (server: {sectionCount} client: {Sections.Length})";
|
||||||
DebugConsole.NewMessage(errorMsg, Color.Red);
|
DebugConsole.NewMessage(errorMsg, Color.Red);
|
||||||
GameAnalyticsManager.AddErrorEventOnce("Structure.ClientRead:SectionCountMismatch", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
GameAnalyticsManager.AddErrorEventOnce("Structure.ClientRead:SectionCountMismatch", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||||
@@ -465,7 +484,7 @@ namespace Barotrauma
|
|||||||
for (int i = 0; i < sectionCount; i++)
|
for (int i = 0; i < sectionCount; i++)
|
||||||
{
|
{
|
||||||
float damage = msg.ReadRangedSingle(0.0f, 1.0f, 8) * MaxHealth;
|
float damage = msg.ReadRangedSingle(0.0f, 1.0f, 8) * MaxHealth;
|
||||||
if (i < Sections.Length)
|
if (!invalidMessage && i < Sections.Length)
|
||||||
{
|
{
|
||||||
SetDamage(i, damage);
|
SetDamage(i, damage);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ using Barotrauma.IO;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
using Barotrauma.Items.Components;
|
using Barotrauma.Items.Components;
|
||||||
|
using System.Globalization;
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
@@ -19,6 +20,7 @@ namespace Barotrauma
|
|||||||
public Sound Sound;
|
public Sound Sound;
|
||||||
public readonly float Volume;
|
public readonly float Volume;
|
||||||
public readonly float Range;
|
public readonly float Range;
|
||||||
|
public readonly Vector2 FrequencyMultiplierRange;
|
||||||
public readonly bool Stream;
|
public readonly bool Stream;
|
||||||
|
|
||||||
public string Filename
|
public string Filename
|
||||||
@@ -32,8 +34,34 @@ namespace Barotrauma
|
|||||||
Stream = sound.Stream;
|
Stream = sound.Stream;
|
||||||
Range = element.GetAttributeFloat("range", 1000.0f);
|
Range = element.GetAttributeFloat("range", 1000.0f);
|
||||||
Volume = element.GetAttributeFloat("volume", 1.0f);
|
Volume = element.GetAttributeFloat("volume", 1.0f);
|
||||||
|
FrequencyMultiplierRange = new Vector2(1.0f);
|
||||||
|
string freqMultAttr = element.GetAttributeString("frequencymultiplier", element.GetAttributeString("frequency", "1.0"));
|
||||||
|
if (!freqMultAttr.Contains(','))
|
||||||
|
{
|
||||||
|
if (float.TryParse(freqMultAttr, NumberStyles.Any, CultureInfo.InvariantCulture, out float freqMult))
|
||||||
|
{
|
||||||
|
FrequencyMultiplierRange = new Vector2(freqMult);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var freqMult = XMLExtensions.ParseVector2(freqMultAttr, false);
|
||||||
|
if (freqMult.Y >= 0.25f)
|
||||||
|
{
|
||||||
|
FrequencyMultiplierRange = freqMult;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (FrequencyMultiplierRange.Y > 4.0f)
|
||||||
|
{
|
||||||
|
DebugConsole.ThrowError($"Loaded frequency range exceeds max value: {FrequencyMultiplierRange} (original string was \"{freqMultAttr}\")");
|
||||||
|
}
|
||||||
sound.IgnoreMuffling = element.GetAttributeBool("dontmuffle", false);
|
sound.IgnoreMuffling = element.GetAttributeBool("dontmuffle", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public float GetRandomFrequencyMultiplier()
|
||||||
|
{
|
||||||
|
return Rand.Range(FrequencyMultiplierRange.X, FrequencyMultiplierRange.Y);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
partial class Submarine : Entity, IServerSerializable
|
partial class Submarine : Entity, IServerSerializable
|
||||||
@@ -288,6 +316,27 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void DrawPaintedColors(SpriteBatch spriteBatch, bool editing = false, Predicate<MapEntity> predicate = null)
|
||||||
|
{
|
||||||
|
var entitiesToRender = !editing && visibleEntities != null ? visibleEntities : MapEntity.mapEntityList;
|
||||||
|
|
||||||
|
foreach (MapEntity e in entitiesToRender)
|
||||||
|
{
|
||||||
|
if (e is Hull hull)
|
||||||
|
{
|
||||||
|
if (hull.SupportsPaintedColors)
|
||||||
|
{
|
||||||
|
if (predicate != null)
|
||||||
|
{
|
||||||
|
if (!predicate(e)) continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
hull.DrawSectionColors(spriteBatch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static void DrawBack(SpriteBatch spriteBatch, bool editing = false, Predicate<MapEntity> predicate = null)
|
public static void DrawBack(SpriteBatch spriteBatch, bool editing = false, Predicate<MapEntity> predicate = null)
|
||||||
{
|
{
|
||||||
var entitiesToRender = !editing && visibleEntities != null ? visibleEntities : MapEntity.mapEntityList;
|
var entitiesToRender = !editing && visibleEntities != null ? visibleEntities : MapEntity.mapEntityList;
|
||||||
@@ -511,6 +560,11 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
||||||
{
|
{
|
||||||
|
if (type != ServerNetObject.ENTITY_POSITION)
|
||||||
|
{
|
||||||
|
DebugConsole.NewMessage($"Error while reading a network event for the submarine \"{Info.Name} ({ID})\". Invalid event type ({type}).", Color.Red);
|
||||||
|
}
|
||||||
|
|
||||||
var posInfo = PhysicsBody.ClientRead(type, msg, sendingTime, parentDebugName: Info.Name);
|
var posInfo = PhysicsBody.ClientRead(type, msg, sendingTime, parentDebugName: Info.Name);
|
||||||
msg.ReadPadBits();
|
msg.ReadPadBits();
|
||||||
|
|
||||||
|
|||||||
@@ -238,42 +238,7 @@ namespace Barotrauma
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool EnterIDCardDesc(GUITextBox textBox, string text)
|
private GUIComponent CreateEditingHUD()
|
||||||
{
|
|
||||||
IdCardDesc = text;
|
|
||||||
textBox.Text = text;
|
|
||||||
textBox.Color = GUI.Style.Green;
|
|
||||||
|
|
||||||
textBox.Deselect();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
private bool EnterIDCardTags(GUITextBox textBox, string text)
|
|
||||||
{
|
|
||||||
IdCardTags = text.Split(',');
|
|
||||||
textBox.Text = string.Join(",", IdCardTags);
|
|
||||||
textBox.Flash(GUI.Style.Green);
|
|
||||||
textBox.Deselect();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool EnterTags(GUITextBox textBox, string text)
|
|
||||||
{
|
|
||||||
tags = text.Split(',').ToList();
|
|
||||||
textBox.Text = string.Join(",", Tags);
|
|
||||||
textBox.Flash(GUI.Style.Green);
|
|
||||||
textBox.Deselect();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool TextBoxChanged(GUITextBox textBox, string text)
|
|
||||||
{
|
|
||||||
textBox.Color = GUI.Style.Red;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private GUIComponent CreateEditingHUD(bool inGame = false)
|
|
||||||
{
|
{
|
||||||
int width = 500;
|
int width = 500;
|
||||||
int height = spawnType == SpawnType.Path ? 80 : 200;
|
int height = spawnType == SpawnType.Path ? 80 : 200;
|
||||||
@@ -326,21 +291,48 @@ namespace Barotrauma
|
|||||||
GUITextBox propertyBox = new GUITextBox(new RectTransform(new Vector2(0.5f, 1.0f), descText.RectTransform, Anchor.CenterRight), IdCardDesc)
|
GUITextBox propertyBox = new GUITextBox(new RectTransform(new Vector2(0.5f, 1.0f), descText.RectTransform, Anchor.CenterRight), IdCardDesc)
|
||||||
{
|
{
|
||||||
MaxTextLength = 150,
|
MaxTextLength = 150,
|
||||||
OnEnterPressed = EnterIDCardDesc,
|
|
||||||
ToolTip = TextManager.Get("IDCardDescriptionTooltip")
|
ToolTip = TextManager.Get("IDCardDescriptionTooltip")
|
||||||
};
|
};
|
||||||
propertyBox.OnTextChanged += TextBoxChanged;
|
propertyBox.OnTextChanged += (textBox, text) =>
|
||||||
|
{
|
||||||
|
IdCardDesc = text;
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
propertyBox.OnEnterPressed += (textBox, text) =>
|
||||||
|
{
|
||||||
|
IdCardDesc = text;
|
||||||
|
textBox.Flash(GUI.Style.Green);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
propertyBox.OnDeselected += (textBox, keys) =>
|
||||||
|
{
|
||||||
|
IdCardDesc = textBox.Text;
|
||||||
|
textBox.Flash(GUI.Style.Green);
|
||||||
|
};
|
||||||
|
|
||||||
var idCardTagsText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.2f), paddedFrame.RectTransform),
|
var idCardTagsText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.2f), paddedFrame.RectTransform),
|
||||||
TextManager.Get("IDCardTags"), font: GUI.SmallFont);
|
TextManager.Get("IDCardTags"), font: GUI.SmallFont);
|
||||||
propertyBox = new GUITextBox(new RectTransform(new Vector2(0.5f, 1.0f), idCardTagsText.RectTransform, Anchor.CenterRight), string.Join(", ", idCardTags))
|
propertyBox = new GUITextBox(new RectTransform(new Vector2(0.5f, 1.0f), idCardTagsText.RectTransform, Anchor.CenterRight), string.Join(", ", idCardTags))
|
||||||
{
|
{
|
||||||
MaxTextLength = 60,
|
MaxTextLength = 60,
|
||||||
OnEnterPressed = EnterIDCardTags,
|
|
||||||
ToolTip = TextManager.Get("IDCardTagsTooltip")
|
ToolTip = TextManager.Get("IDCardTagsTooltip")
|
||||||
};
|
};
|
||||||
propertyBox.OnTextChanged += TextBoxChanged;
|
propertyBox.OnTextChanged += (textBox, text) =>
|
||||||
|
{
|
||||||
|
IdCardTags = text.Split(',');
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
propertyBox.OnEnterPressed += (textBox, text) =>
|
||||||
|
{
|
||||||
|
textBox.Text = string.Join(",", IdCardTags);
|
||||||
|
textBox.Flash(GUI.Style.Green);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
propertyBox.OnDeselected += (textBox, keys) =>
|
||||||
|
{
|
||||||
|
textBox.Text = string.Join(",", IdCardTags);
|
||||||
|
textBox.Flash(GUI.Style.Green);
|
||||||
|
};
|
||||||
|
|
||||||
var jobsText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.2f), paddedFrame.RectTransform),
|
var jobsText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.2f), paddedFrame.RectTransform),
|
||||||
TextManager.Get("SpawnpointJobs"), font: GUI.SmallFont)
|
TextManager.Get("SpawnpointJobs"), font: GUI.SmallFont)
|
||||||
@@ -368,12 +360,26 @@ namespace Barotrauma
|
|||||||
propertyBox = new GUITextBox(new RectTransform(new Vector2(0.5f, 1.0f), tagsText.RectTransform, Anchor.CenterRight), string.Join(", ", tags))
|
propertyBox = new GUITextBox(new RectTransform(new Vector2(0.5f, 1.0f), tagsText.RectTransform, Anchor.CenterRight), string.Join(", ", tags))
|
||||||
{
|
{
|
||||||
MaxTextLength = 60,
|
MaxTextLength = 60,
|
||||||
OnEnterPressed = EnterTags,
|
|
||||||
ToolTip = TextManager.Get("spawnpointtagstooltip")
|
ToolTip = TextManager.Get("spawnpointtagstooltip")
|
||||||
};
|
};
|
||||||
propertyBox.OnTextChanged += TextBoxChanged;
|
propertyBox.OnTextChanged += (textBox, text) =>
|
||||||
|
{
|
||||||
|
tags = text.Split(',').ToList();
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
propertyBox.OnEnterPressed += (textBox, text) =>
|
||||||
|
{
|
||||||
|
textBox.Text = string.Join(",", tags);
|
||||||
|
textBox.Flash(GUI.Style.Green);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
propertyBox.OnDeselected += (textBox, keys) =>
|
||||||
|
{
|
||||||
|
textBox.Text = string.Join(",", tags);
|
||||||
|
textBox.Flash(GUI.Style.Green);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
PositionEditingHUD();
|
PositionEditingHUD();
|
||||||
|
|
||||||
return editingHUD;
|
return editingHUD;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Microsoft.Xna.Framework;
|
using Barotrauma.Steam;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -7,12 +8,13 @@ namespace Barotrauma.Networking
|
|||||||
{
|
{
|
||||||
partial class BannedPlayer
|
partial class BannedPlayer
|
||||||
{
|
{
|
||||||
public BannedPlayer(string name, UInt16 uniqueIdentifier, bool isRangeBan, string ip, ulong steamID)
|
public BannedPlayer(string name, UInt16 uniqueIdentifier, bool isRangeBan, string endPoint, ulong steamID)
|
||||||
{
|
{
|
||||||
this.Name = name;
|
this.Name = name;
|
||||||
|
this.EndPoint = endPoint;
|
||||||
this.SteamID = steamID;
|
this.SteamID = steamID;
|
||||||
|
ParseEndPointAsSteamId();
|
||||||
this.IsRangeBan = isRangeBan;
|
this.IsRangeBan = isRangeBan;
|
||||||
this.IP = ip;
|
|
||||||
this.UniqueIdentifier = uniqueIdentifier;
|
this.UniqueIdentifier = uniqueIdentifier;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -66,13 +68,13 @@ namespace Barotrauma.Networking
|
|||||||
RelativeSpacing = 0.02f
|
RelativeSpacing = 0.02f
|
||||||
};
|
};
|
||||||
|
|
||||||
string ip = bannedPlayer.IP;
|
string endPoint = bannedPlayer.EndPoint;
|
||||||
if (localRangeBans.Contains(bannedPlayer.UniqueIdentifier)) ip = ToRange(ip);
|
if (localRangeBans.Contains(bannedPlayer.UniqueIdentifier)) endPoint = ToRange(endPoint);
|
||||||
GUITextBlock textBlock = new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.0f), topArea.RectTransform),
|
GUITextBlock textBlock = new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.0f), topArea.RectTransform),
|
||||||
bannedPlayer.Name + " (" + ip + ")");
|
bannedPlayer.Name + " (" + endPoint + ")");
|
||||||
textBlock.RectTransform.MinSize = new Point(textBlock.Rect.Width, 0);
|
textBlock.RectTransform.MinSize = new Point(textBlock.Rect.Width, 0);
|
||||||
|
|
||||||
if (bannedPlayer.IP.IndexOf(".x") <= -1)
|
if (bannedPlayer.EndPoint.IndexOf(".x") <= -1)
|
||||||
{
|
{
|
||||||
var rangeBanButton = new GUIButton(new RectTransform(new Vector2(0.25f, 0.4f), topArea.RectTransform),
|
var rangeBanButton = new GUIButton(new RectTransform(new Vector2(0.25f, 0.4f), topArea.RectTransform),
|
||||||
TextManager.Get("BanRange"), style: "GUIButtonSmall")
|
TextManager.Get("BanRange"), style: "GUIButtonSmall")
|
||||||
@@ -156,19 +158,19 @@ namespace Barotrauma.Networking
|
|||||||
UInt16 uniqueIdentifier = incMsg.ReadUInt16();
|
UInt16 uniqueIdentifier = incMsg.ReadUInt16();
|
||||||
bool isRangeBan = incMsg.ReadBoolean(); incMsg.ReadPadBits();
|
bool isRangeBan = incMsg.ReadBoolean(); incMsg.ReadPadBits();
|
||||||
|
|
||||||
string ip = "";
|
string endPoint = "";
|
||||||
UInt64 steamID = 0;
|
UInt64 steamID = 0;
|
||||||
if (isOwner)
|
if (isOwner)
|
||||||
{
|
{
|
||||||
ip = incMsg.ReadString();
|
endPoint = incMsg.ReadString();
|
||||||
steamID = incMsg.ReadUInt64();
|
steamID = incMsg.ReadUInt64();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ip = "IP concealed by host";
|
endPoint = "Endpoint concealed by host";
|
||||||
steamID = 0;
|
steamID = 0;
|
||||||
}
|
}
|
||||||
bannedPlayers.Add(new BannedPlayer(name, uniqueIdentifier, isRangeBan, ip, steamID));
|
bannedPlayers.Add(new BannedPlayer(name, uniqueIdentifier, isRangeBan, endPoint, steamID));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (banFrame != null)
|
if (banFrame != null)
|
||||||
|
|||||||
@@ -520,11 +520,13 @@ namespace Barotrauma.Networking
|
|||||||
msgBox.Content.Parent.RectTransform.MinSize = new Point(0, (int)(msgBox.Content.RectTransform.MinSize.Y / msgBox.Content.RectTransform.RelativeSize.Y));
|
msgBox.Content.Parent.RectTransform.MinSize = new Point(0, (int)(msgBox.Content.RectTransform.MinSize.Y / msgBox.Content.RectTransform.RelativeSize.Y));
|
||||||
|
|
||||||
var okButton = msgBox.Buttons[0];
|
var okButton = msgBox.Buttons[0];
|
||||||
|
okButton.OnClicked += msgBox.Close;
|
||||||
var cancelButton = msgBox.Buttons[1];
|
var cancelButton = msgBox.Buttons[1];
|
||||||
|
cancelButton.OnClicked += msgBox.Close;
|
||||||
|
|
||||||
okButton.OnClicked += (GUIButton button, object obj) =>
|
okButton.OnClicked += (GUIButton button, object obj) =>
|
||||||
{
|
{
|
||||||
clientPeer.SendPassword(passwordBox.Text);
|
clientPeer?.SendPassword(passwordBox.Text);
|
||||||
requiresPw = false;
|
requiresPw = false;
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
@@ -855,22 +857,6 @@ namespace Barotrauma.Networking
|
|||||||
traitorResults.Add(new TraitorMissionResult(inc));
|
traitorResults.Add(new TraitorMissionResult(inc));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GameMain.GameSession?.GameMode is CampaignMode mpCampaign)
|
|
||||||
{
|
|
||||||
if (inc.ReadBoolean())
|
|
||||||
{
|
|
||||||
Dictionary<string, int> clientUpgrades = UpgradeManager.GetMetadataLevels(mpCampaign.CampaignMetadata);
|
|
||||||
Dictionary<string, int> serverUpgrades = new Dictionary<string, int>();
|
|
||||||
|
|
||||||
int length = inc.ReadUInt16();
|
|
||||||
for (int i = 0; i < length; i++)
|
|
||||||
{
|
|
||||||
serverUpgrades.Add(inc.ReadString(), inc.ReadByte());
|
|
||||||
}
|
|
||||||
UpgradeManager.CompareUpgrades(clientUpgrades, serverUpgrades);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
roundInitStatus = RoundInitStatus.Interrupted;
|
roundInitStatus = RoundInitStatus.Interrupted;
|
||||||
CoroutineManager.StartCoroutine(EndGame(endMessage, traitorResults, transitionType), "EndGame");
|
CoroutineManager.StartCoroutine(EndGame(endMessage, traitorResults, transitionType), "EndGame");
|
||||||
break;
|
break;
|
||||||
@@ -934,7 +920,7 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
private void ReadStartGameFinalize(IReadMessage inc)
|
private void ReadStartGameFinalize(IReadMessage inc)
|
||||||
{
|
{
|
||||||
TaskPool.ListTasks(null);
|
TaskPool.ListTasks();
|
||||||
ushort contentToPreloadCount = inc.ReadUInt16();
|
ushort contentToPreloadCount = inc.ReadUInt16();
|
||||||
List<ContentFile> contentToPreload = new List<ContentFile>();
|
List<ContentFile> contentToPreload = new List<ContentFile>();
|
||||||
for (int i = 0; i < contentToPreloadCount; i++)
|
for (int i = 0; i < contentToPreloadCount; i++)
|
||||||
@@ -1006,8 +992,19 @@ namespace Barotrauma.Networking
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void OnDisconnect()
|
private void OnDisconnect(bool disableReconnect)
|
||||||
{
|
{
|
||||||
|
CoroutineManager.StopCoroutines("WaitForStartingInfo");
|
||||||
|
reconnectBox?.Close();
|
||||||
|
reconnectBox = null;
|
||||||
|
|
||||||
|
GameMain.Config.RestoreBackupPackages();
|
||||||
|
|
||||||
|
GUI.ClearCursorWait();
|
||||||
|
|
||||||
|
if (disableReconnect) { allowReconnect = false; }
|
||||||
|
if (!this.allowReconnect) { CancelConnect(); }
|
||||||
|
|
||||||
if (SteamManager.IsInitialized)
|
if (SteamManager.IsInitialized)
|
||||||
{
|
{
|
||||||
Steamworks.SteamFriends.ClearRichPresence();
|
Steamworks.SteamFriends.ClearRichPresence();
|
||||||
@@ -1107,8 +1104,9 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
reconnectBox?.Close();
|
reconnectBox?.Close();
|
||||||
reconnectBox = new GUIMessageBox(
|
reconnectBox = new GUIMessageBox(
|
||||||
TextManager.Get("ConnectionLost"),
|
TextManager.Get("ConnectionLost"), msg,
|
||||||
msg, new string[0]);
|
new string[] { TextManager.Get("Cancel") });
|
||||||
|
reconnectBox.Buttons[0].OnClicked += (btn, userdata) => { CancelConnect(); return true; };
|
||||||
connected = false;
|
connected = false;
|
||||||
ConnectToServer(serverEndpoint, serverName);
|
ConnectToServer(serverEndpoint, serverName);
|
||||||
}
|
}
|
||||||
@@ -1385,6 +1383,7 @@ namespace Barotrauma.Networking
|
|||||||
if (gameMode == null)
|
if (gameMode == null)
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError("Game mode \"" + modeIdentifier + "\" not found!");
|
DebugConsole.ThrowError("Game mode \"" + modeIdentifier + "\" not found!");
|
||||||
|
roundInitStatus = RoundInitStatus.Interrupted;
|
||||||
yield return CoroutineStatus.Failure;
|
yield return CoroutineStatus.Failure;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1415,11 +1414,13 @@ namespace Barotrauma.Networking
|
|||||||
int missionIndex = inc.ReadInt16();
|
int missionIndex = inc.ReadInt16();
|
||||||
if (!GameMain.NetLobbyScreen.TrySelectSub(subName, subHash, GameMain.NetLobbyScreen.SubList))
|
if (!GameMain.NetLobbyScreen.TrySelectSub(subName, subHash, GameMain.NetLobbyScreen.SubList))
|
||||||
{
|
{
|
||||||
|
roundInitStatus = RoundInitStatus.Interrupted;
|
||||||
yield return CoroutineStatus.Success;
|
yield return CoroutineStatus.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!GameMain.NetLobbyScreen.TrySelectSub(shuttleName, shuttleHash, GameMain.NetLobbyScreen.ShuttleList.ListBox))
|
if (!GameMain.NetLobbyScreen.TrySelectSub(shuttleName, shuttleHash, GameMain.NetLobbyScreen.ShuttleList.ListBox))
|
||||||
{
|
{
|
||||||
|
roundInitStatus = RoundInitStatus.Interrupted;
|
||||||
yield return CoroutineStatus.Success;
|
yield return CoroutineStatus.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1448,6 +1449,7 @@ namespace Barotrauma.Networking
|
|||||||
GameMain.NetLobbyScreen.Select();
|
GameMain.NetLobbyScreen.Select();
|
||||||
DebugConsole.ThrowError(errorMsg);
|
DebugConsole.ThrowError(errorMsg);
|
||||||
GameAnalyticsManager.AddErrorEventOnce("GameClient.StartGame:FailedToSelectSub" + subName, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
GameAnalyticsManager.AddErrorEventOnce("GameClient.StartGame:FailedToSelectSub" + subName, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||||
|
roundInitStatus = RoundInitStatus.Interrupted;
|
||||||
yield return CoroutineStatus.Failure;
|
yield return CoroutineStatus.Failure;
|
||||||
}
|
}
|
||||||
if (GameMain.NetLobbyScreen.SelectedShuttle == null ||
|
if (GameMain.NetLobbyScreen.SelectedShuttle == null ||
|
||||||
@@ -1459,6 +1461,7 @@ namespace Barotrauma.Networking
|
|||||||
string errorMsg = "Failed to select shuttle \"" + shuttleName + "\" (hash: " + shuttleHash + ").";
|
string errorMsg = "Failed to select shuttle \"" + shuttleName + "\" (hash: " + shuttleHash + ").";
|
||||||
DebugConsole.ThrowError(errorMsg);
|
DebugConsole.ThrowError(errorMsg);
|
||||||
GameAnalyticsManager.AddErrorEventOnce("GameClient.StartGame:FailedToSelectShuttle" + shuttleName, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
GameAnalyticsManager.AddErrorEventOnce("GameClient.StartGame:FailedToSelectShuttle" + shuttleName, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||||
|
roundInitStatus = RoundInitStatus.Interrupted;
|
||||||
yield return CoroutineStatus.Failure;
|
yield return CoroutineStatus.Failure;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1487,6 +1490,7 @@ namespace Barotrauma.Networking
|
|||||||
gameStarted = true;
|
gameStarted = true;
|
||||||
DebugConsole.ThrowError(errorMsg);
|
DebugConsole.ThrowError(errorMsg);
|
||||||
GameMain.NetLobbyScreen.Select();
|
GameMain.NetLobbyScreen.Select();
|
||||||
|
roundInitStatus = RoundInitStatus.Interrupted;
|
||||||
yield return CoroutineStatus.Failure;
|
yield return CoroutineStatus.Failure;
|
||||||
}
|
}
|
||||||
else if (campaign.Map == null)
|
else if (campaign.Map == null)
|
||||||
@@ -1495,6 +1499,7 @@ namespace Barotrauma.Networking
|
|||||||
gameStarted = true;
|
gameStarted = true;
|
||||||
DebugConsole.ThrowError(errorMsg);
|
DebugConsole.ThrowError(errorMsg);
|
||||||
GameMain.NetLobbyScreen.Select();
|
GameMain.NetLobbyScreen.Select();
|
||||||
|
roundInitStatus = RoundInitStatus.Interrupted;
|
||||||
yield return CoroutineStatus.Failure;
|
yield return CoroutineStatus.Failure;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1515,6 +1520,11 @@ namespace Barotrauma.Networking
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (GameMain.Client?.ServerSettings?.Voting != null)
|
||||||
|
{
|
||||||
|
GameMain.Client.ServerSettings.Voting.ResetVotes(GameMain.Client.ConnectedClients);
|
||||||
|
}
|
||||||
|
|
||||||
if (loadTask != null)
|
if (loadTask != null)
|
||||||
{
|
{
|
||||||
while (!loadTask.IsCompleted && !loadTask.IsFaulted && !loadTask.IsCanceled)
|
while (!loadTask.IsCompleted && !loadTask.IsFaulted && !loadTask.IsCanceled)
|
||||||
@@ -1626,7 +1636,10 @@ namespace Barotrauma.Networking
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (respawnAllowed) { respawnManager = new RespawnManager(this, GameMain.NetLobbyScreen.UsingShuttle ? GameMain.NetLobbyScreen.SelectedShuttle : null); }
|
if (respawnAllowed)
|
||||||
|
{
|
||||||
|
respawnManager = new RespawnManager(this, GameMain.NetLobbyScreen.UsingShuttle && gameMode != GameModePreset.MultiPlayerCampaign ? GameMain.NetLobbyScreen.SelectedShuttle : null);
|
||||||
|
}
|
||||||
|
|
||||||
gameStarted = true;
|
gameStarted = true;
|
||||||
ServerSettings.ServerDetailsChanged = true;
|
ServerSettings.ServerDetailsChanged = true;
|
||||||
@@ -1645,6 +1658,17 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
public IEnumerable<object> EndGame(string endMessage, List<TraitorMissionResult> traitorResults = null, CampaignMode.TransitionType transitionType = CampaignMode.TransitionType.None)
|
public IEnumerable<object> EndGame(string endMessage, List<TraitorMissionResult> traitorResults = null, CampaignMode.TransitionType transitionType = CampaignMode.TransitionType.None)
|
||||||
{
|
{
|
||||||
|
//round starting up, wait for it to finish
|
||||||
|
DateTime timeOut = DateTime.Now + new TimeSpan(0, 0, 60);
|
||||||
|
while (TaskPool.IsTaskRunning("AsyncCampaignStartRound"))
|
||||||
|
{
|
||||||
|
if (DateTime.Now > timeOut)
|
||||||
|
{
|
||||||
|
throw new Exception("Failed to end a round (async campaign round start timed out).");
|
||||||
|
}
|
||||||
|
yield return new WaitForSeconds(1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
if (!gameStarted)
|
if (!gameStarted)
|
||||||
{
|
{
|
||||||
GameMain.NetLobbyScreen.Select();
|
GameMain.NetLobbyScreen.Select();
|
||||||
@@ -2086,7 +2110,6 @@ namespace Barotrauma.Networking
|
|||||||
{
|
{
|
||||||
while ((objHeader = (ServerNetObject)inc.ReadByte()) != ServerNetObject.END_OF_MESSAGE)
|
while ((objHeader = (ServerNetObject)inc.ReadByte()) != ServerNetObject.END_OF_MESSAGE)
|
||||||
{
|
{
|
||||||
bool eventReadFailed = false;
|
|
||||||
switch (objHeader)
|
switch (objHeader)
|
||||||
{
|
{
|
||||||
case ServerNetObject.SYNC_IDS:
|
case ServerNetObject.SYNC_IDS:
|
||||||
@@ -2110,7 +2133,13 @@ namespace Barotrauma.Networking
|
|||||||
int msgEndPos = (int)(inc.BitPosition + msgLength * 8);
|
int msgEndPos = (int)(inc.BitPosition + msgLength * 8);
|
||||||
|
|
||||||
var entity = Entity.FindEntityByID(id) as IServerSerializable;
|
var entity = Entity.FindEntityByID(id) as IServerSerializable;
|
||||||
if (entity != null)
|
if (msgEndPos > inc.LengthBits)
|
||||||
|
{
|
||||||
|
DebugConsole.ThrowError($"Error while reading a position update for the entity \"({entity?.ToString() ?? "null"})\". Message length exceeds the size of the buffer.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entity != null && (entity is Item || entity is Character || entity is Submarine))
|
||||||
{
|
{
|
||||||
entity.ClientRead(objHeader.Value, inc, sendingTime);
|
entity.ClientRead(objHeader.Value, inc, sendingTime);
|
||||||
}
|
}
|
||||||
@@ -2127,8 +2156,7 @@ namespace Barotrauma.Networking
|
|||||||
case ServerNetObject.ENTITY_EVENT_INITIAL:
|
case ServerNetObject.ENTITY_EVENT_INITIAL:
|
||||||
if (!entityEventManager.Read(objHeader.Value, inc, sendingTime, entities))
|
if (!entityEventManager.Read(objHeader.Value, inc, sendingTime, entities))
|
||||||
{
|
{
|
||||||
eventReadFailed = true;
|
return;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ServerNetObject.CHAT_MESSAGE:
|
case ServerNetObject.CHAT_MESSAGE:
|
||||||
@@ -2138,16 +2166,11 @@ namespace Barotrauma.Networking
|
|||||||
throw new Exception($"Unknown object header \"{objHeader}\"!)");
|
throw new Exception($"Unknown object header \"{objHeader}\"!)");
|
||||||
}
|
}
|
||||||
prevBitLength = inc.BitPosition - prevBitPos;
|
prevBitLength = inc.BitPosition - prevBitPos;
|
||||||
prevByteLength = inc.BytePosition - prevByteLength;
|
prevByteLength = inc.BytePosition - prevBytePos;
|
||||||
|
|
||||||
prevObjHeader = objHeader;
|
prevObjHeader = objHeader;
|
||||||
prevBitPos = inc.BitPosition;
|
prevBitPos = inc.BitPosition;
|
||||||
prevBytePos = inc.BytePosition;
|
prevBytePos = inc.BytePosition;
|
||||||
|
|
||||||
if (eventReadFailed)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2618,7 +2641,7 @@ namespace Barotrauma.Networking
|
|||||||
public void VoteForKick(Client votedClient)
|
public void VoteForKick(Client votedClient)
|
||||||
{
|
{
|
||||||
if (votedClient == null) { return; }
|
if (votedClient == null) { return; }
|
||||||
votedClient.AddKickVote(ConnectedClients.First(c => c.ID == ID));
|
votedClient.AddKickVote(ConnectedClients.FirstOrDefault(c => c.ID == myID));
|
||||||
Vote(VoteType.Kick, votedClient);
|
Vote(VoteType.Kick, votedClient);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+16
-5
@@ -164,6 +164,19 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
for (int i = 0; i < eventCount; i++)
|
for (int i = 0; i < eventCount; i++)
|
||||||
{
|
{
|
||||||
|
//16 = entity ID, 8 = msg length
|
||||||
|
if (msg.BitPosition + 16 + 8 > msg.LengthBits)
|
||||||
|
{
|
||||||
|
string errorMsg = $"Error while reading a message from the server. Entity event data exceeds the size of the buffer (current position: {msg.BitPosition}, length: {msg.LengthBits}).";
|
||||||
|
errorMsg += "\nPrevious entities:";
|
||||||
|
for (int j = entities.Count - 1; j >= 0; j--)
|
||||||
|
{
|
||||||
|
errorMsg += "\n" + (entities[j] == null ? "NULL" : entities[j].ToString());
|
||||||
|
}
|
||||||
|
DebugConsole.ThrowError(errorMsg);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
UInt16 thisEventID = (UInt16)(firstEventID + (UInt16)i);
|
UInt16 thisEventID = (UInt16)(firstEventID + (UInt16)i);
|
||||||
UInt16 entityID = msg.ReadUInt16();
|
UInt16 entityID = msg.ReadUInt16();
|
||||||
|
|
||||||
@@ -176,7 +189,7 @@ namespace Barotrauma.Networking
|
|||||||
}
|
}
|
||||||
msg.ReadPadBits();
|
msg.ReadPadBits();
|
||||||
entities.Add(null);
|
entities.Add(null);
|
||||||
if (thisEventID == (UInt16)(lastReceivedID + 1)) lastReceivedID++;
|
if (thisEventID == (UInt16)(lastReceivedID + 1)) { lastReceivedID++; }
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -248,10 +261,8 @@ namespace Barotrauma.Networking
|
|||||||
errorMsg += "\n" + (entities[j] == null ? "NULL" : entities[j].ToString());
|
errorMsg += "\n" + (entities[j] == null ? "NULL" : entities[j].ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GameSettings.VerboseLogging)
|
DebugConsole.ThrowError("Failed to read event for entity \"" + entity.ToString() + "\"!", e);
|
||||||
{
|
|
||||||
DebugConsole.ThrowError("Failed to read event for entity \"" + entity.ToString() + "\"!", e);
|
|
||||||
}
|
|
||||||
GameAnalyticsManager.AddErrorEventOnce("ClientEntityEventManager.Read:ReadFailed" + entity.ToString(),
|
GameAnalyticsManager.AddErrorEventOnce("ClientEntityEventManager.Read:ReadFailed" + entity.ToString(),
|
||||||
GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||||
msg.BitPosition = (int)(msgPosition + msgLength * 8);
|
msg.BitPosition = (int)(msgPosition + msgLength * 8);
|
||||||
|
|||||||
+185
-3
@@ -1,13 +1,56 @@
|
|||||||
using System;
|
using Barotrauma.Extensions;
|
||||||
|
using Barotrauma.Steam;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace Barotrauma.Networking
|
namespace Barotrauma.Networking
|
||||||
{
|
{
|
||||||
abstract class ClientPeer
|
abstract class ClientPeer
|
||||||
{
|
{
|
||||||
|
protected class ServerContentPackage
|
||||||
|
{
|
||||||
|
public string Name;
|
||||||
|
public string Hash;
|
||||||
|
public UInt64 WorkshopId;
|
||||||
|
|
||||||
|
public ContentPackage RegularPackage
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return ContentPackage.RegularPackages.Find(p => p.MD5hash.Hash.Equals(Hash));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ContentPackage CorePackage
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return ContentPackage.CorePackages.Find(p => p.MD5hash.Hash.Equals(Hash));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ServerContentPackage(string name, string hash, UInt64 workshopId)
|
||||||
|
{
|
||||||
|
Name = name;
|
||||||
|
Hash = hash;
|
||||||
|
WorkshopId = workshopId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected string GetPackageStr(ContentPackage contentPackage)
|
||||||
|
{
|
||||||
|
return "\"" + contentPackage.Name + "\" (hash " + contentPackage.MD5hash.ShortHash + ")";
|
||||||
|
}
|
||||||
|
protected string GetPackageStr(ServerContentPackage contentPackage)
|
||||||
|
{
|
||||||
|
return "\"" + contentPackage.Name + "\" (hash " + Md5Hash.GetShortHash(contentPackage.Hash) + ")";
|
||||||
|
}
|
||||||
|
|
||||||
public delegate void MessageCallback(IReadMessage message);
|
public delegate void MessageCallback(IReadMessage message);
|
||||||
public delegate void DisconnectCallback();
|
public delegate void DisconnectCallback(bool disableReconnect);
|
||||||
public delegate void DisconnectMessageCallback(string message);
|
public delegate void DisconnectMessageCallback(string message);
|
||||||
public delegate void PasswordCallback(int salt, int retries);
|
public delegate void PasswordCallback(int salt, int retries);
|
||||||
public delegate void InitializationCompleteCallback();
|
public delegate void InitializationCompleteCallback();
|
||||||
@@ -25,11 +68,150 @@ namespace Barotrauma.Networking
|
|||||||
public NetworkConnection ServerConnection { get; protected set; }
|
public NetworkConnection ServerConnection { get; protected set; }
|
||||||
|
|
||||||
public abstract void Start(object endPoint, int ownerKey);
|
public abstract void Start(object endPoint, int ownerKey);
|
||||||
public abstract void Close(string msg = null);
|
public abstract void Close(string msg = null, bool disableReconnect = false);
|
||||||
public abstract void Update(float deltaTime);
|
public abstract void Update(float deltaTime);
|
||||||
public abstract void Send(IWriteMessage msg, DeliveryMethod deliveryMethod);
|
public abstract void Send(IWriteMessage msg, DeliveryMethod deliveryMethod);
|
||||||
public abstract void SendPassword(string password);
|
public abstract void SendPassword(string password);
|
||||||
|
|
||||||
|
protected abstract void SendMsgInternal(DeliveryMethod deliveryMethod, IWriteMessage msg);
|
||||||
|
|
||||||
|
protected ConnectionInitialization initializationStep;
|
||||||
|
protected bool contentPackageOrderReceived;
|
||||||
|
protected int ownerKey = 0;
|
||||||
|
protected int passwordSalt;
|
||||||
|
protected Steamworks.AuthTicket steamAuthTicket;
|
||||||
|
protected void ReadConnectionInitializationStep(IReadMessage inc)
|
||||||
|
{
|
||||||
|
ConnectionInitialization step = (ConnectionInitialization)inc.ReadByte();
|
||||||
|
|
||||||
|
IWriteMessage outMsg;
|
||||||
|
|
||||||
|
switch (step)
|
||||||
|
{
|
||||||
|
case ConnectionInitialization.SteamTicketAndVersion:
|
||||||
|
if (initializationStep != ConnectionInitialization.SteamTicketAndVersion) { return; }
|
||||||
|
outMsg = new WriteOnlyMessage();
|
||||||
|
outMsg.Write((byte)PacketHeader.IsConnectionInitializationStep);
|
||||||
|
outMsg.Write((byte)ConnectionInitialization.SteamTicketAndVersion);
|
||||||
|
outMsg.Write(Name);
|
||||||
|
outMsg.Write(ownerKey);
|
||||||
|
outMsg.Write(SteamManager.GetSteamID());
|
||||||
|
if (steamAuthTicket == null)
|
||||||
|
{
|
||||||
|
outMsg.Write((UInt16)0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
outMsg.Write((UInt16)steamAuthTicket.Data.Length);
|
||||||
|
outMsg.Write(steamAuthTicket.Data, 0, steamAuthTicket.Data.Length);
|
||||||
|
}
|
||||||
|
outMsg.Write(GameMain.Version.ToString());
|
||||||
|
outMsg.Write(GameMain.Config.Language);
|
||||||
|
|
||||||
|
SendMsgInternal(DeliveryMethod.Reliable, outMsg);
|
||||||
|
break;
|
||||||
|
case ConnectionInitialization.ContentPackageOrder:
|
||||||
|
if (initializationStep == ConnectionInitialization.SteamTicketAndVersion ||
|
||||||
|
initializationStep == ConnectionInitialization.Password) { initializationStep = ConnectionInitialization.ContentPackageOrder; }
|
||||||
|
if (initializationStep != ConnectionInitialization.ContentPackageOrder) { return; }
|
||||||
|
outMsg = new WriteOnlyMessage();
|
||||||
|
outMsg.Write((byte)PacketHeader.IsConnectionInitializationStep);
|
||||||
|
outMsg.Write((byte)ConnectionInitialization.ContentPackageOrder);
|
||||||
|
|
||||||
|
string serverName = inc.ReadString();
|
||||||
|
|
||||||
|
UInt32 cpCount = inc.ReadVariableUInt32();
|
||||||
|
ServerContentPackage corePackage = null;
|
||||||
|
List<ServerContentPackage> regularPackages = new List<ServerContentPackage>();
|
||||||
|
List<ServerContentPackage> missingPackages = new List<ServerContentPackage>();
|
||||||
|
for (int i = 0; i < cpCount; i++)
|
||||||
|
{
|
||||||
|
string name = inc.ReadString();
|
||||||
|
string hash = inc.ReadString();
|
||||||
|
UInt64 workshopId = inc.ReadUInt64();
|
||||||
|
var pkg = new ServerContentPackage(name, hash, workshopId);
|
||||||
|
if (pkg.CorePackage != null)
|
||||||
|
{
|
||||||
|
corePackage = pkg;
|
||||||
|
}
|
||||||
|
else if (pkg.RegularPackage != null)
|
||||||
|
{
|
||||||
|
regularPackages.Add(pkg);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
missingPackages.Add(pkg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (missingPackages.Count > 0)
|
||||||
|
{
|
||||||
|
var nonDownloadable = missingPackages.Where(p => p.WorkshopId == 0);
|
||||||
|
|
||||||
|
if (nonDownloadable.Any())
|
||||||
|
{
|
||||||
|
string disconnectMsg;
|
||||||
|
if (nonDownloadable.Count() == 1)
|
||||||
|
{
|
||||||
|
disconnectMsg = $"DisconnectMessage.MissingContentPackage~[missingcontentpackage]={GetPackageStr(missingPackages[0])}";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
List<string> packageStrs = new List<string>();
|
||||||
|
nonDownloadable.ForEach(cp => packageStrs.Add(GetPackageStr(cp)));
|
||||||
|
disconnectMsg = $"DisconnectMessage.MissingContentPackages~[missingcontentpackages]={string.Join(", ", packageStrs)}";
|
||||||
|
}
|
||||||
|
Close(disconnectMsg, disableReconnect: true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Close(disableReconnect: true);
|
||||||
|
|
||||||
|
string missingModNames = "\n- " + string.Join("\n\n- ", missingPackages.Select(p => GetPackageStr(p))) + "\n\n";
|
||||||
|
|
||||||
|
var msgBox = new GUIMessageBox(
|
||||||
|
TextManager.Get("WorkshopItemDownloadTitle"),
|
||||||
|
TextManager.GetWithVariable("WorkshopItemDownloadPrompt", "[items]", missingModNames),
|
||||||
|
new string[] { TextManager.Get("Yes"), TextManager.Get("No") });
|
||||||
|
msgBox.Buttons[0].OnClicked = (yesBtn, userdata) =>
|
||||||
|
{
|
||||||
|
GameMain.ServerListScreen.Select();
|
||||||
|
GameMain.ServerListScreen.DownloadWorkshopItems(missingPackages.Select(p => p.WorkshopId), serverName, ServerConnection.EndPointString);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
msgBox.Buttons[0].OnClicked += msgBox.Close;
|
||||||
|
msgBox.Buttons[1].OnClicked = msgBox.Close;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!contentPackageOrderReceived)
|
||||||
|
{
|
||||||
|
GameMain.Config.SwapPackages(corePackage.CorePackage, regularPackages.Select(p => p.RegularPackage).ToList());
|
||||||
|
contentPackageOrderReceived = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
SendMsgInternal(DeliveryMethod.Reliable, outMsg);
|
||||||
|
break;
|
||||||
|
case ConnectionInitialization.Password:
|
||||||
|
if (initializationStep == ConnectionInitialization.SteamTicketAndVersion) { initializationStep = ConnectionInitialization.Password; }
|
||||||
|
if (initializationStep != ConnectionInitialization.Password) { return; }
|
||||||
|
bool incomingSalt = inc.ReadBoolean(); inc.ReadPadBits();
|
||||||
|
int retries = 0;
|
||||||
|
if (incomingSalt)
|
||||||
|
{
|
||||||
|
passwordSalt = inc.ReadInt32();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
retries = inc.ReadInt32();
|
||||||
|
}
|
||||||
|
OnRequestPassword?.Invoke(passwordSalt, retries);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
public abstract void ForceTimeOut();
|
public abstract void ForceTimeOut();
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+15
-101
@@ -14,11 +14,6 @@ namespace Barotrauma.Networking
|
|||||||
private NetClient netClient;
|
private NetClient netClient;
|
||||||
private NetPeerConfiguration netPeerConfiguration;
|
private NetPeerConfiguration netPeerConfiguration;
|
||||||
|
|
||||||
private ConnectionInitialization initializationStep;
|
|
||||||
private bool contentPackageOrderReceived;
|
|
||||||
private int ownerKey;
|
|
||||||
private int passwordSalt;
|
|
||||||
private Steamworks.AuthTicket steamAuthTicket;
|
|
||||||
List<NetIncomingMessage> incomingLidgrenMessages;
|
List<NetIncomingMessage> incomingLidgrenMessages;
|
||||||
|
|
||||||
public LidgrenClientPeer(string name)
|
public LidgrenClientPeer(string name)
|
||||||
@@ -128,7 +123,7 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
if (isConnectionInitializationStep && initializationStep != ConnectionInitialization.Success)
|
if (isConnectionInitializationStep && initializationStep != ConnectionInitialization.Success)
|
||||||
{
|
{
|
||||||
ReadConnectionInitializationStep(inc);
|
ReadConnectionInitializationStep(new ReadWriteMessage(inc.Data, (int)inc.Position, inc.LengthBits, false));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -158,99 +153,6 @@ namespace Barotrauma.Networking
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ReadConnectionInitializationStep(NetIncomingMessage inc)
|
|
||||||
{
|
|
||||||
if (!isActive) { return; }
|
|
||||||
|
|
||||||
ConnectionInitialization step = (ConnectionInitialization)inc.ReadByte();
|
|
||||||
//Console.WriteLine(step + " " + initializationStep);
|
|
||||||
NetOutgoingMessage outMsg; NetSendResult result;
|
|
||||||
|
|
||||||
switch (step)
|
|
||||||
{
|
|
||||||
case ConnectionInitialization.SteamTicketAndVersion:
|
|
||||||
if (initializationStep != ConnectionInitialization.SteamTicketAndVersion) { return; }
|
|
||||||
outMsg = netClient.CreateMessage();
|
|
||||||
outMsg.Write((byte)PacketHeader.IsConnectionInitializationStep);
|
|
||||||
outMsg.Write((byte)ConnectionInitialization.SteamTicketAndVersion);
|
|
||||||
outMsg.Write(Name);
|
|
||||||
outMsg.Write(ownerKey);
|
|
||||||
outMsg.Write(SteamManager.GetSteamID());
|
|
||||||
if (steamAuthTicket == null)
|
|
||||||
{
|
|
||||||
outMsg.Write((UInt16)0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
outMsg.Write((UInt16)steamAuthTicket.Data.Length);
|
|
||||||
outMsg.Write(steamAuthTicket.Data, 0, steamAuthTicket.Data.Length);
|
|
||||||
}
|
|
||||||
|
|
||||||
outMsg.Write(GameMain.Version.ToString());
|
|
||||||
|
|
||||||
IEnumerable<ContentPackage> mpContentPackages = GameMain.SelectedPackages.Where(cp => cp.HasMultiplayerIncompatibleContent);
|
|
||||||
outMsg.WriteVariableInt32(mpContentPackages.Count());
|
|
||||||
foreach (ContentPackage contentPackage in mpContentPackages)
|
|
||||||
{
|
|
||||||
outMsg.Write(contentPackage.Name);
|
|
||||||
outMsg.Write(contentPackage.MD5hash.Hash);
|
|
||||||
}
|
|
||||||
|
|
||||||
result = netClient.SendMessage(outMsg, NetDeliveryMethod.ReliableUnordered);
|
|
||||||
if (result != NetSendResult.Queued && result != NetSendResult.Sent)
|
|
||||||
{
|
|
||||||
DebugConsole.NewMessage("Failed to send "+initializationStep.ToString()+" message to host: " + result);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ConnectionInitialization.ContentPackageOrder:
|
|
||||||
if (initializationStep == ConnectionInitialization.SteamTicketAndVersion ||
|
|
||||||
initializationStep == ConnectionInitialization.Password) { initializationStep = ConnectionInitialization.ContentPackageOrder; }
|
|
||||||
if (initializationStep != ConnectionInitialization.ContentPackageOrder) { return; }
|
|
||||||
outMsg = netClient.CreateMessage();
|
|
||||||
outMsg.Write((byte)PacketHeader.IsConnectionInitializationStep);
|
|
||||||
outMsg.Write((byte)ConnectionInitialization.ContentPackageOrder);
|
|
||||||
|
|
||||||
Int32 cpCount = inc.ReadVariableInt32();
|
|
||||||
List<ContentPackage> serverContentPackages = new List<ContentPackage>();
|
|
||||||
for (int i = 0; i < cpCount; i++)
|
|
||||||
{
|
|
||||||
string hash = inc.ReadString();
|
|
||||||
serverContentPackages.Add(GameMain.Config.SelectedContentPackages.Find(cp => cp.MD5hash.Hash == hash));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!contentPackageOrderReceived)
|
|
||||||
{
|
|
||||||
GameMain.Config.ReorderSelectedContentPackages(cp => serverContentPackages.Contains(cp) ?
|
|
||||||
serverContentPackages.IndexOf(cp) :
|
|
||||||
serverContentPackages.Count + GameMain.Config.SelectedContentPackages.IndexOf(cp));
|
|
||||||
contentPackageOrderReceived = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
result = netClient.SendMessage(outMsg, NetDeliveryMethod.ReliableUnordered);
|
|
||||||
if (result != NetSendResult.Queued && result != NetSendResult.Sent)
|
|
||||||
{
|
|
||||||
DebugConsole.NewMessage("Failed to send " + initializationStep.ToString() + " message to host: " + result);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
case ConnectionInitialization.Password:
|
|
||||||
if (initializationStep == ConnectionInitialization.SteamTicketAndVersion) { initializationStep = ConnectionInitialization.Password; }
|
|
||||||
if (initializationStep != ConnectionInitialization.Password) { return; }
|
|
||||||
bool incomingSalt = inc.ReadBoolean(); inc.ReadPadBits();
|
|
||||||
int retries = 0;
|
|
||||||
if (incomingSalt)
|
|
||||||
{
|
|
||||||
passwordSalt = inc.ReadInt32();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
retries = inc.ReadInt32();
|
|
||||||
}
|
|
||||||
OnRequestPassword?.Invoke(passwordSalt, retries);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void SendPassword(string password)
|
public override void SendPassword(string password)
|
||||||
{
|
{
|
||||||
if (!isActive) { return; }
|
if (!isActive) { return; }
|
||||||
@@ -269,7 +171,7 @@ namespace Barotrauma.Networking
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Close(string msg = null)
|
public override void Close(string msg = null, bool disableReconnect = false)
|
||||||
{
|
{
|
||||||
if (!isActive) { return; }
|
if (!isActive) { return; }
|
||||||
|
|
||||||
@@ -278,7 +180,7 @@ namespace Barotrauma.Networking
|
|||||||
netClient.Shutdown(msg ?? TextManager.Get("Disconnecting"));
|
netClient.Shutdown(msg ?? TextManager.Get("Disconnecting"));
|
||||||
netClient = null;
|
netClient = null;
|
||||||
steamAuthTicket?.Cancel(); steamAuthTicket = null;
|
steamAuthTicket?.Cancel(); steamAuthTicket = null;
|
||||||
OnDisconnect?.Invoke();
|
OnDisconnect?.Invoke(disableReconnect);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Send(IWriteMessage msg, DeliveryMethod deliveryMethod)
|
public override void Send(IWriteMessage msg, DeliveryMethod deliveryMethod)
|
||||||
@@ -320,6 +222,18 @@ namespace Barotrauma.Networking
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void SendMsgInternal(DeliveryMethod deliveryMethod, IWriteMessage msg)
|
||||||
|
{
|
||||||
|
NetOutgoingMessage lidgrenMsg = netClient.CreateMessage();
|
||||||
|
lidgrenMsg.Write(msg.Buffer, 0, msg.LengthBytes);
|
||||||
|
|
||||||
|
NetSendResult result = netClient.SendMessage(lidgrenMsg, NetDeliveryMethod.ReliableUnordered);
|
||||||
|
if (result != NetSendResult.Queued && result != NetSendResult.Sent)
|
||||||
|
{
|
||||||
|
DebugConsole.NewMessage("Failed to send message to host: " + result + "\n" + Environment.StackTrace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
public override void ForceTimeOut()
|
public override void ForceTimeOut()
|
||||||
{
|
{
|
||||||
|
|||||||
+32
-92
@@ -12,10 +12,6 @@ namespace Barotrauma.Networking
|
|||||||
{
|
{
|
||||||
private bool isActive;
|
private bool isActive;
|
||||||
private UInt64 hostSteamId;
|
private UInt64 hostSteamId;
|
||||||
private ConnectionInitialization initializationStep;
|
|
||||||
private bool contentPackageOrderReceived;
|
|
||||||
private int passwordSalt;
|
|
||||||
private Steamworks.AuthTicket steamAuthTicket;
|
|
||||||
private double timeout;
|
private double timeout;
|
||||||
private double heartbeatTimer;
|
private double heartbeatTimer;
|
||||||
private double connectionStatusTimer;
|
private double connectionStatusTimer;
|
||||||
@@ -89,6 +85,7 @@ namespace Barotrauma.Networking
|
|||||||
Steamworks.SteamNetworking.AcceptP2PSessionWithUser(steamId);
|
Steamworks.SteamNetworking.AcceptP2PSessionWithUser(steamId);
|
||||||
}
|
}
|
||||||
else if (initializationStep != ConnectionInitialization.Password &&
|
else if (initializationStep != ConnectionInitialization.Password &&
|
||||||
|
initializationStep != ConnectionInitialization.ContentPackageOrder &&
|
||||||
initializationStep != ConnectionInitialization.Success)
|
initializationStep != ConnectionInitialization.Success)
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError($"Connection from incorrect SteamID was rejected: "+
|
DebugConsole.ThrowError($"Connection from incorrect SteamID was rejected: "+
|
||||||
@@ -105,7 +102,7 @@ namespace Barotrauma.Networking
|
|||||||
OnDisconnectMessageReceived?.Invoke($"SteamP2P connection failed: {error}");
|
OnDisconnectMessageReceived?.Invoke($"SteamP2P connection failed: {error}");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnP2PData(ulong steamId, byte[] data, int dataLength, int channel)
|
private void OnP2PData(ulong steamId, byte[] data, int dataLength)
|
||||||
{
|
{
|
||||||
if (!isActive) { return; }
|
if (!isActive) { return; }
|
||||||
if (steamId != hostSteamId) { return; }
|
if (steamId != hostSteamId) { return; }
|
||||||
@@ -165,6 +162,7 @@ namespace Barotrauma.Networking
|
|||||||
heartbeatTimer -= deltaTime;
|
heartbeatTimer -= deltaTime;
|
||||||
|
|
||||||
if (initializationStep != ConnectionInitialization.Password &&
|
if (initializationStep != ConnectionInitialization.Password &&
|
||||||
|
initializationStep != ConnectionInitialization.ContentPackageOrder &&
|
||||||
initializationStep != ConnectionInitialization.Success)
|
initializationStep != ConnectionInitialization.Success)
|
||||||
{
|
{
|
||||||
connectionStatusTimer -= deltaTime;
|
connectionStatusTimer -= deltaTime;
|
||||||
@@ -194,7 +192,7 @@ namespace Barotrauma.Networking
|
|||||||
var packet = Steamworks.SteamNetworking.ReadP2PPacket();
|
var packet = Steamworks.SteamNetworking.ReadP2PPacket();
|
||||||
if (packet.HasValue)
|
if (packet.HasValue)
|
||||||
{
|
{
|
||||||
OnP2PData(packet?.SteamId ?? 0, packet?.Data, packet?.Data.Length ?? 0, 0);
|
OnP2PData(packet?.SteamId ?? 0, packet?.Data, packet?.Data.Length ?? 0);
|
||||||
receivedBytes += packet?.Data.Length ?? 0;
|
receivedBytes += packet?.Data.Length ?? 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -249,88 +247,6 @@ namespace Barotrauma.Networking
|
|||||||
incomingDataMessages.Clear();
|
incomingDataMessages.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ReadConnectionInitializationStep(IReadMessage inc)
|
|
||||||
{
|
|
||||||
if (!isActive) { return; }
|
|
||||||
|
|
||||||
ConnectionInitialization step = (ConnectionInitialization)inc.ReadByte();
|
|
||||||
|
|
||||||
IWriteMessage outMsg;
|
|
||||||
|
|
||||||
//DebugConsole.NewMessage(step + " " + initializationStep);
|
|
||||||
switch (step)
|
|
||||||
{
|
|
||||||
case ConnectionInitialization.SteamTicketAndVersion:
|
|
||||||
if (initializationStep != ConnectionInitialization.SteamTicketAndVersion) { return; }
|
|
||||||
outMsg = new WriteOnlyMessage();
|
|
||||||
outMsg.Write((byte)DeliveryMethod.Reliable);
|
|
||||||
outMsg.Write((byte)PacketHeader.IsConnectionInitializationStep);
|
|
||||||
outMsg.Write((byte)ConnectionInitialization.SteamTicketAndVersion);
|
|
||||||
outMsg.Write(Name);
|
|
||||||
outMsg.Write(SteamManager.GetSteamID());
|
|
||||||
outMsg.Write((UInt16)steamAuthTicket.Data.Length);
|
|
||||||
outMsg.Write(steamAuthTicket.Data, 0, steamAuthTicket.Data.Length);
|
|
||||||
|
|
||||||
outMsg.Write(GameMain.Version.ToString());
|
|
||||||
|
|
||||||
IEnumerable<ContentPackage> mpContentPackages = GameMain.SelectedPackages.Where(cp => cp.HasMultiplayerIncompatibleContent);
|
|
||||||
outMsg.WriteVariableUInt32((UInt32)mpContentPackages.Count());
|
|
||||||
foreach (ContentPackage contentPackage in mpContentPackages)
|
|
||||||
{
|
|
||||||
outMsg.Write(contentPackage.Name);
|
|
||||||
outMsg.Write(contentPackage.MD5hash.Hash);
|
|
||||||
}
|
|
||||||
|
|
||||||
heartbeatTimer = 5.0;
|
|
||||||
Steamworks.SteamNetworking.SendP2PPacket(hostSteamId, outMsg.Buffer, outMsg.LengthBytes, 0, Steamworks.P2PSend.Reliable);
|
|
||||||
sentBytes += outMsg.LengthBytes;
|
|
||||||
break;
|
|
||||||
case ConnectionInitialization.ContentPackageOrder:
|
|
||||||
if (initializationStep == ConnectionInitialization.SteamTicketAndVersion ||
|
|
||||||
initializationStep == ConnectionInitialization.Password) { initializationStep = ConnectionInitialization.ContentPackageOrder; }
|
|
||||||
if (initializationStep != ConnectionInitialization.ContentPackageOrder) { return; }
|
|
||||||
outMsg = new WriteOnlyMessage();
|
|
||||||
outMsg.Write((byte)DeliveryMethod.Reliable);
|
|
||||||
outMsg.Write((byte)PacketHeader.IsConnectionInitializationStep);
|
|
||||||
outMsg.Write((byte)ConnectionInitialization.ContentPackageOrder);
|
|
||||||
|
|
||||||
UInt32 cpCount = inc.ReadVariableUInt32();
|
|
||||||
List<ContentPackage> serverContentPackages = new List<ContentPackage>();
|
|
||||||
for (int i = 0; i < cpCount; i++)
|
|
||||||
{
|
|
||||||
string hash = inc.ReadString();
|
|
||||||
serverContentPackages.Add(GameMain.Config.SelectedContentPackages.Find(cp => cp.MD5hash.Hash == hash));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!contentPackageOrderReceived)
|
|
||||||
{
|
|
||||||
GameMain.Config.ReorderSelectedContentPackages(cp => serverContentPackages.Contains(cp) ?
|
|
||||||
serverContentPackages.IndexOf(cp) :
|
|
||||||
serverContentPackages.Count + GameMain.Config.SelectedContentPackages.IndexOf(cp));
|
|
||||||
contentPackageOrderReceived = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Steamworks.SteamNetworking.SendP2PPacket(hostSteamId, outMsg.Buffer, outMsg.LengthBytes, 0, Steamworks.P2PSend.Reliable);
|
|
||||||
sentBytes += outMsg.LengthBytes;
|
|
||||||
break;
|
|
||||||
case ConnectionInitialization.Password:
|
|
||||||
if (initializationStep == ConnectionInitialization.SteamTicketAndVersion) { initializationStep = ConnectionInitialization.Password; }
|
|
||||||
if (initializationStep != ConnectionInitialization.Password) { return; }
|
|
||||||
bool incomingSalt = inc.ReadBoolean(); inc.ReadPadBits();
|
|
||||||
int retries = 0;
|
|
||||||
if (incomingSalt)
|
|
||||||
{
|
|
||||||
passwordSalt = inc.ReadInt32();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
retries = inc.ReadInt32();
|
|
||||||
}
|
|
||||||
OnRequestPassword?.Invoke(passwordSalt, retries);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Send(IWriteMessage msg, DeliveryMethod deliveryMethod)
|
public override void Send(IWriteMessage msg, DeliveryMethod deliveryMethod)
|
||||||
{
|
{
|
||||||
if (!isActive) { return; }
|
if (!isActive) { return; }
|
||||||
@@ -339,8 +255,7 @@ namespace Barotrauma.Networking
|
|||||||
buf[0] = (byte)deliveryMethod;
|
buf[0] = (byte)deliveryMethod;
|
||||||
|
|
||||||
byte[] bufAux = new byte[msg.LengthBytes];
|
byte[] bufAux = new byte[msg.LengthBytes];
|
||||||
bool isCompressed; int length;
|
msg.PrepareForSending(ref bufAux, out bool isCompressed, out int length);
|
||||||
msg.PrepareForSending(ref bufAux, out isCompressed, out length);
|
|
||||||
|
|
||||||
buf[1] = (byte)(isCompressed ? PacketHeader.IsCompressed : PacketHeader.None);
|
buf[1] = (byte)(isCompressed ? PacketHeader.IsCompressed : PacketHeader.None);
|
||||||
|
|
||||||
@@ -426,7 +341,7 @@ namespace Barotrauma.Networking
|
|||||||
sentBytes += outMsg.LengthBytes;
|
sentBytes += outMsg.LengthBytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Close(string msg = null)
|
public override void Close(string msg = null, bool disableReconnect = false)
|
||||||
{
|
{
|
||||||
if (!isActive) { return; }
|
if (!isActive) { return; }
|
||||||
|
|
||||||
@@ -451,7 +366,7 @@ namespace Barotrauma.Networking
|
|||||||
steamAuthTicket?.Cancel(); steamAuthTicket = null;
|
steamAuthTicket?.Cancel(); steamAuthTicket = null;
|
||||||
hostSteamId = 0;
|
hostSteamId = 0;
|
||||||
|
|
||||||
OnDisconnect?.Invoke();
|
OnDisconnect?.Invoke(disableReconnect);
|
||||||
}
|
}
|
||||||
|
|
||||||
~SteamP2PClientPeer()
|
~SteamP2PClientPeer()
|
||||||
@@ -460,6 +375,31 @@ namespace Barotrauma.Networking
|
|||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void SendMsgInternal(DeliveryMethod deliveryMethod, IWriteMessage msg)
|
||||||
|
{
|
||||||
|
Steamworks.P2PSend sendType;
|
||||||
|
switch (deliveryMethod)
|
||||||
|
{
|
||||||
|
case DeliveryMethod.Reliable:
|
||||||
|
case DeliveryMethod.ReliableOrdered:
|
||||||
|
//the documentation seems to suggest that the Reliable send type
|
||||||
|
//enforces packet order (TODO: verify)
|
||||||
|
sendType = Steamworks.P2PSend.Reliable;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
sendType = Steamworks.P2PSend.Unreliable;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
IWriteMessage msgToSend = new WriteOnlyMessage();
|
||||||
|
msgToSend.Write((byte)deliveryMethod);
|
||||||
|
msgToSend.Write(msg.Buffer, 0, msg.LengthBytes);
|
||||||
|
|
||||||
|
heartbeatTimer = 5.0;
|
||||||
|
Steamworks.SteamNetworking.SendP2PPacket(hostSteamId, msgToSend.Buffer, msgToSend.LengthBytes, 0, sendType);
|
||||||
|
sentBytes += msg.LengthBytes;
|
||||||
|
}
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
public override void ForceTimeOut()
|
public override void ForceTimeOut()
|
||||||
{
|
{
|
||||||
|
|||||||
+12
-8
@@ -1,8 +1,6 @@
|
|||||||
using System;
|
using Barotrauma.Steam;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Net;
|
|
||||||
using System.Text;
|
|
||||||
using Barotrauma.Steam;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
@@ -12,7 +10,6 @@ namespace Barotrauma.Networking
|
|||||||
{
|
{
|
||||||
private bool isActive;
|
private bool isActive;
|
||||||
|
|
||||||
private ConnectionInitialization initializationStep;
|
|
||||||
private readonly UInt64 selfSteamID;
|
private readonly UInt64 selfSteamID;
|
||||||
|
|
||||||
private long sentBytes, receivedBytes;
|
private long sentBytes, receivedBytes;
|
||||||
@@ -61,7 +58,7 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
initializationStep = ConnectionInitialization.SteamTicketAndVersion;
|
initializationStep = ConnectionInitialization.SteamTicketAndVersion;
|
||||||
|
|
||||||
ServerConnection = new PipeConnection();
|
ServerConnection = new PipeConnection(selfSteamID);
|
||||||
ServerConnection.Status = NetworkConnectionStatus.Connected;
|
ServerConnection.Status = NetworkConnectionStatus.Connected;
|
||||||
|
|
||||||
remotePeers = new List<RemotePeer>();
|
remotePeers = new List<RemotePeer>();
|
||||||
@@ -161,6 +158,7 @@ namespace Barotrauma.Networking
|
|||||||
remotePeer.Authenticating = true;
|
remotePeer.Authenticating = true;
|
||||||
|
|
||||||
authMsg.ReadString(); //skip name
|
authMsg.ReadString(); //skip name
|
||||||
|
authMsg.ReadInt32(); //skip owner key
|
||||||
authMsg.ReadUInt64(); //skip steamid
|
authMsg.ReadUInt64(); //skip steamid
|
||||||
UInt16 ticketLength = authMsg.ReadUInt16();
|
UInt16 ticketLength = authMsg.ReadUInt16();
|
||||||
byte[] ticket = authMsg.ReadBytes(ticketLength);
|
byte[] ticket = authMsg.ReadBytes(ticketLength);
|
||||||
@@ -395,7 +393,7 @@ namespace Barotrauma.Networking
|
|||||||
return; //owner doesn't send passwords
|
return; //owner doesn't send passwords
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Close(string msg = null)
|
public override void Close(string msg = null, bool disableReconnect = false)
|
||||||
{
|
{
|
||||||
if (!isActive) { return; }
|
if (!isActive) { return; }
|
||||||
|
|
||||||
@@ -415,7 +413,7 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
ChildServerRelay.ClosePipes();
|
ChildServerRelay.ClosePipes();
|
||||||
|
|
||||||
OnDisconnect?.Invoke();
|
OnDisconnect?.Invoke(disableReconnect);
|
||||||
|
|
||||||
SteamManager.LeaveLobby();
|
SteamManager.LeaveLobby();
|
||||||
Steamworks.SteamNetworking.ResetActions();
|
Steamworks.SteamNetworking.ResetActions();
|
||||||
@@ -445,6 +443,12 @@ namespace Barotrauma.Networking
|
|||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void SendMsgInternal(DeliveryMethod deliveryMethod, IWriteMessage msg)
|
||||||
|
{
|
||||||
|
//not currently used by SteamP2POwnerPeer
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
public override void ForceTimeOut()
|
public override void ForceTimeOut()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -73,26 +73,25 @@ namespace Barotrauma.Networking
|
|||||||
get;
|
get;
|
||||||
private set;
|
private set;
|
||||||
} = new List<string>();
|
} = new List<string>();
|
||||||
public List<string> ContentPackageWorkshopUrls
|
public List<ulong> ContentPackageWorkshopIds
|
||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
private set;
|
private set;
|
||||||
} = new List<string>();
|
} = new List<ulong>();
|
||||||
|
|
||||||
public bool ContentPackagesMatch(IEnumerable<ContentPackage> myContentPackages)
|
public bool ContentPackagesMatch()
|
||||||
{
|
{
|
||||||
|
var myContentPackages = ContentPackage.AllPackages;
|
||||||
//make sure we have all the packages the server requires
|
//make sure we have all the packages the server requires
|
||||||
foreach (string hash in ContentPackageHashes)
|
if (ContentPackageHashes.Count != ContentPackageWorkshopIds.Count) { return false; }
|
||||||
|
for (int i = 0; i < ContentPackageWorkshopIds.Count; i++)
|
||||||
{
|
{
|
||||||
if (!myContentPackages.Any(myPackage => myPackage.MD5hash.Hash == hash)) { return false; }
|
string hash = ContentPackageHashes[i];
|
||||||
}
|
UInt64 id = ContentPackageWorkshopIds[i];
|
||||||
|
if (!myContentPackages.Any(myPackage => myPackage.MD5hash.Hash == hash))
|
||||||
//make sure the server isn't missing any of our packages that cause multiplayer incompatibility
|
|
||||||
foreach (ContentPackage myPackage in myContentPackages)
|
|
||||||
{
|
|
||||||
if (myPackage.HasMultiplayerIncompatibleContent)
|
|
||||||
{
|
{
|
||||||
if (!ContentPackageHashes.Any(hash => hash == myPackage.MD5hash.Hash)) { return false; }
|
if (myContentPackages.Any(p => p.SteamWorkshopId == id)) { return false; }
|
||||||
|
if (id == 0) { return false; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,19 +144,22 @@ namespace Barotrauma.Networking
|
|||||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), previewContainer.RectTransform),
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), previewContainer.RectTransform),
|
||||||
TextManager.AddPunctuation(':', TextManager.Get("ServerListVersion"), string.IsNullOrEmpty(GameVersion) ? TextManager.Get("Unknown") : GameVersion));
|
TextManager.AddPunctuation(':', TextManager.Get("ServerListVersion"), string.IsNullOrEmpty(GameVersion) ? TextManager.Get("Unknown") : GameVersion));
|
||||||
|
|
||||||
PlayStyle playStyle = PlayStyle ?? Networking.PlayStyle.Serious;
|
bool hidePlaystyleBanner = previewContainer.Rect.Height < 380 || !PlayStyle.HasValue;
|
||||||
|
if (!hidePlaystyleBanner)
|
||||||
|
{
|
||||||
|
PlayStyle playStyle = PlayStyle ?? Networking.PlayStyle.Serious;
|
||||||
|
Sprite playStyleBannerSprite = ServerListScreen.PlayStyleBanners[(int)playStyle];
|
||||||
|
float playStyleBannerAspectRatio = playStyleBannerSprite.SourceRect.Width / playStyleBannerSprite.SourceRect.Height;
|
||||||
|
var playStyleBanner = new GUIImage(new RectTransform(new Point(previewContainer.Rect.Width, (int)(previewContainer.Rect.Width / playStyleBannerAspectRatio)), previewContainer.RectTransform),
|
||||||
|
playStyleBannerSprite, null, true);
|
||||||
|
|
||||||
Sprite playStyleBannerSprite = ServerListScreen.PlayStyleBanners[(int)playStyle];
|
var playStyleName = new GUITextBlock(new RectTransform(new Vector2(0.15f, 0.0f), playStyleBanner.RectTransform) { RelativeOffset = new Vector2(0.01f, 0.06f) },
|
||||||
float playStyleBannerAspectRatio = playStyleBannerSprite.SourceRect.Width / playStyleBannerSprite.SourceRect.Height;
|
TextManager.AddPunctuation(':', TextManager.Get("serverplaystyle"), TextManager.Get("servertag."+ playStyle)), textColor: Color.White,
|
||||||
var playStyleBanner = new GUIImage(new RectTransform(new Point(previewContainer.Rect.Width, (int)(previewContainer.Rect.Width / playStyleBannerAspectRatio)), previewContainer.RectTransform),
|
font: GUI.SmallFont, textAlignment: Alignment.Center,
|
||||||
playStyleBannerSprite, null, true);
|
color: ServerListScreen.PlayStyleColors[(int)playStyle], style: "GUISlopedHeader");
|
||||||
|
playStyleName.RectTransform.NonScaledSize = (playStyleName.Font.MeasureString(playStyleName.Text) + new Vector2(20, 5) * GUI.Scale).ToPoint();
|
||||||
var playStyleName = new GUITextBlock(new RectTransform(new Vector2(0.15f, 0.0f), playStyleBanner.RectTransform) { RelativeOffset = new Vector2(0.01f, 0.06f) },
|
playStyleName.RectTransform.IsFixedSize = true;
|
||||||
TextManager.AddPunctuation(':', TextManager.Get("serverplaystyle"), TextManager.Get("servertag."+ playStyle)), textColor: Color.White,
|
}
|
||||||
font: GUI.SmallFont, textAlignment: Alignment.Center,
|
|
||||||
color: ServerListScreen.PlayStyleColors[(int)playStyle], style: "GUISlopedHeader");
|
|
||||||
playStyleName.RectTransform.NonScaledSize = (playStyleName.Font.MeasureString(playStyleName.Text) + new Vector2(20, 5) * GUI.Scale).ToPoint();
|
|
||||||
playStyleName.RectTransform.IsFixedSize = true;
|
|
||||||
|
|
||||||
var content = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.6f), previewContainer.RectTransform))
|
var content = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.6f), previewContainer.RectTransform))
|
||||||
{
|
{
|
||||||
@@ -207,8 +209,13 @@ namespace Barotrauma.Networking
|
|||||||
TextManager.Get(string.IsNullOrEmpty(GameMode) ? "Unknown" : "GameMode." + GameMode, returnNull: true) ?? GameMode,
|
TextManager.Get(string.IsNullOrEmpty(GameMode) ? "Unknown" : "GameMode." + GameMode, returnNull: true) ?? GameMode,
|
||||||
textAlignment: Alignment.Right);
|
textAlignment: Alignment.Right);
|
||||||
|
|
||||||
/*var traitors = new GUITextBlock(new RectTransform(new Vector2(1.0f, elementHeight), bodyContainer.RectTransform), TextManager.Get("Traitors"));
|
GUITextBlock playStyleText = null;
|
||||||
new GUITextBlock(new RectTransform(Vector2.One, traitors.RectTransform), TextManager.Get(!TraitorsEnabled.HasValue ? "Unknown" : TraitorsEnabled.Value.ToString()), textAlignment: Alignment.Right);*/
|
if (hidePlaystyleBanner && PlayStyle.HasValue)
|
||||||
|
{
|
||||||
|
PlayStyle playStyle = PlayStyle.Value;
|
||||||
|
playStyleText = new GUITextBlock(new RectTransform(new Vector2(1.0f, elementHeight), content.RectTransform), TextManager.Get("serverplaystyle"));
|
||||||
|
new GUITextBlock(new RectTransform(Vector2.One, playStyleText.RectTransform), TextManager.Get("servertag." + playStyle), textAlignment: Alignment.Right);
|
||||||
|
}
|
||||||
|
|
||||||
var subSelection = new GUITextBlock(new RectTransform(new Vector2(1.0f, elementHeight), content.RectTransform), TextManager.Get("ServerListSubSelection"));
|
var subSelection = new GUITextBlock(new RectTransform(new Vector2(1.0f, elementHeight), content.RectTransform), TextManager.Get("ServerListSubSelection"));
|
||||||
new GUITextBlock(new RectTransform(Vector2.One, subSelection.RectTransform), TextManager.Get(!SubSelectionMode.HasValue ? "Unknown" : SubSelectionMode.Value.ToString()), textAlignment: Alignment.Right);
|
new GUITextBlock(new RectTransform(Vector2.One, subSelection.RectTransform), TextManager.Get(!SubSelectionMode.HasValue ? "Unknown" : SubSelectionMode.Value.ToString()), textAlignment: Alignment.Right);
|
||||||
@@ -222,6 +229,10 @@ namespace Barotrauma.Networking
|
|||||||
{
|
{
|
||||||
gameMode.Font = subSelection.Font = modeSelection.Font = GUI.SmallFont;
|
gameMode.Font = subSelection.Font = modeSelection.Font = GUI.SmallFont;
|
||||||
gameMode.GetChild<GUITextBlock>().Font = subSelection.GetChild<GUITextBlock>().Font = modeSelection.GetChild<GUITextBlock>().Font = GUI.SmallFont;
|
gameMode.GetChild<GUITextBlock>().Font = subSelection.GetChild<GUITextBlock>().Font = modeSelection.GetChild<GUITextBlock>().Font = GUI.SmallFont;
|
||||||
|
if (playStyleText != null)
|
||||||
|
{
|
||||||
|
playStyleText.Font = playStyleText.GetChild<GUITextBlock>().Font = GUI.SmallFont;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var allowSpectating = new GUITickBox(new RectTransform(new Vector2(1, elementHeight), content.RectTransform), TextManager.Get("ServerListAllowSpectating"))
|
var allowSpectating = new GUITickBox(new RectTransform(new Vector2(1, elementHeight), content.RectTransform), TextManager.Get("ServerListAllowSpectating"))
|
||||||
@@ -279,7 +290,6 @@ namespace Barotrauma.Networking
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
List<string> availableWorkshopUrls = new List<string>();
|
|
||||||
for (int i = 0; i < ContentPackageNames.Count; i++)
|
for (int i = 0; i < ContentPackageNames.Count; i++)
|
||||||
{
|
{
|
||||||
var packageText = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.15f), contentPackageList.Content.RectTransform) { MinSize = new Point(0, 15) },
|
var packageText = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.15f), contentPackageList.Content.RectTransform) { MinSize = new Point(0, 15) },
|
||||||
@@ -289,22 +299,15 @@ namespace Barotrauma.Networking
|
|||||||
};
|
};
|
||||||
if (i < ContentPackageHashes.Count)
|
if (i < ContentPackageHashes.Count)
|
||||||
{
|
{
|
||||||
if (GameMain.Config.SelectedContentPackages.Any(cp => cp.MD5hash.Hash == ContentPackageHashes[i]))
|
if (ContentPackage.AllPackages.Any(cp => cp.MD5hash.Hash == ContentPackageHashes[i]))
|
||||||
{
|
{
|
||||||
packageText.Selected = true;
|
packageText.Selected = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
//matching content package found, but it hasn't been enabled
|
|
||||||
if (ContentPackage.List.Any(cp => cp.MD5hash.Hash == ContentPackageHashes[i]))
|
|
||||||
{
|
|
||||||
packageText.TextColor = GUI.Style.Orange;
|
|
||||||
packageText.ToolTip = TextManager.GetWithVariable("ServerListContentPackageNotEnabled", "[contentpackage]", ContentPackageNames[i]);
|
|
||||||
}
|
|
||||||
//workshop download link found
|
//workshop download link found
|
||||||
else if (i < ContentPackageWorkshopUrls.Count && !string.IsNullOrEmpty(ContentPackageWorkshopUrls[i]))
|
if (i < ContentPackageWorkshopIds.Count && ContentPackageWorkshopIds[i] != 0)
|
||||||
{
|
{
|
||||||
availableWorkshopUrls.Add(ContentPackageWorkshopUrls[i]);
|
|
||||||
packageText.TextColor = Color.Yellow;
|
packageText.TextColor = Color.Yellow;
|
||||||
packageText.ToolTip = TextManager.GetWithVariable("ServerListIncompatibleContentPackageWorkshopAvailable", "[contentpackage]", ContentPackageNames[i]);
|
packageText.ToolTip = TextManager.GetWithVariable("ServerListIncompatibleContentPackageWorkshopAvailable", "[contentpackage]", ContentPackageNames[i]);
|
||||||
}
|
}
|
||||||
@@ -316,21 +319,6 @@ namespace Barotrauma.Networking
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (availableWorkshopUrls.Count > 0)
|
|
||||||
{
|
|
||||||
var workshopBtn = new GUIButton(new RectTransform(new Vector2(1.0f, 0.1f), content.RectTransform), TextManager.Get("ServerListSubscribeMissingPackages"))
|
|
||||||
{
|
|
||||||
ToolTip = TextManager.Get(SteamManager.IsInitialized ? "ServerListSubscribeMissingPackagesTooltip" : "ServerListSubscribeMissingPackagesTooltipNoSteam"),
|
|
||||||
Enabled = SteamManager.IsInitialized,
|
|
||||||
OnClicked = (btn, userdata) =>
|
|
||||||
{
|
|
||||||
GameMain.SteamWorkshopScreen.SubscribeToPackages(availableWorkshopUrls);
|
|
||||||
GameMain.SteamWorkshopScreen.Select();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
workshopBtn.TextBlock.AutoScaleHorizontal = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
@@ -391,7 +379,7 @@ namespace Barotrauma.Networking
|
|||||||
if (bool.TryParse(element.GetAttributeString("UsingWhiteList", ""), out bool whitelistTemp)) { info.UsingWhiteList = whitelistTemp; }
|
if (bool.TryParse(element.GetAttributeString("UsingWhiteList", ""), out bool whitelistTemp)) { info.UsingWhiteList = whitelistTemp; }
|
||||||
if (Enum.TryParse(element.GetAttributeString("TraitorsEnabled", ""), out YesNoMaybe traitorsTemp)) { info.TraitorsEnabled = traitorsTemp; }
|
if (Enum.TryParse(element.GetAttributeString("TraitorsEnabled", ""), out YesNoMaybe traitorsTemp)) { info.TraitorsEnabled = traitorsTemp; }
|
||||||
if (Enum.TryParse(element.GetAttributeString("SubSelectionMode", ""), out SelectionMode subSelectionTemp)) { info.SubSelectionMode = subSelectionTemp; }
|
if (Enum.TryParse(element.GetAttributeString("SubSelectionMode", ""), out SelectionMode subSelectionTemp)) { info.SubSelectionMode = subSelectionTemp; }
|
||||||
if (Enum.TryParse(element.GetAttributeString("ModeSelectionMode", ""), out SelectionMode modeSelectionTemp)) { info.ModeSelectionMode = subSelectionTemp; }
|
if (Enum.TryParse(element.GetAttributeString("ModeSelectionMode", ""), out SelectionMode modeSelectionTemp)) { info.ModeSelectionMode = modeSelectionTemp; }
|
||||||
if (bool.TryParse(element.GetAttributeString("VoipEnabled", ""), out bool voipTemp)) { info.VoipEnabled = voipTemp; }
|
if (bool.TryParse(element.GetAttributeString("VoipEnabled", ""), out bool voipTemp)) { info.VoipEnabled = voipTemp; }
|
||||||
if (bool.TryParse(element.GetAttributeString("KarmaEnabled", ""), out bool karmaTemp)) { info.KarmaEnabled = karmaTemp; }
|
if (bool.TryParse(element.GetAttributeString("KarmaEnabled", ""), out bool karmaTemp)) { info.KarmaEnabled = karmaTemp; }
|
||||||
if (bool.TryParse(element.GetAttributeString("FriendlyFireEnabled", ""), out bool friendlyFireTemp)) { info.FriendlyFireEnabled = friendlyFireTemp; }
|
if (bool.TryParse(element.GetAttributeString("FriendlyFireEnabled", ""), out bool friendlyFireTemp)) { info.FriendlyFireEnabled = friendlyFireTemp; }
|
||||||
|
|||||||
@@ -477,10 +477,6 @@ namespace Barotrauma.Networking
|
|||||||
GUITextBlock.AutoScaleAndNormalize(playStyleTickBoxes.Select(t => t.TextBlock));
|
GUITextBlock.AutoScaleAndNormalize(playStyleTickBoxes.Select(t => t.TextBlock));
|
||||||
playstyleList.RectTransform.MinSize = new Point(0, (int)(playstyleList.Content.Children.First().Rect.Height * 2.0f + playstyleList.Padding.Y + playstyleList.Padding.W));
|
playstyleList.RectTransform.MinSize = new Point(0, (int)(playstyleList.Content.Children.First().Rect.Height * 2.0f + playstyleList.Padding.Y + playstyleList.Padding.W));
|
||||||
|
|
||||||
var endBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), roundsTab.RectTransform),
|
|
||||||
TextManager.Get("ServerSettingsEndRoundWhenDestReached"));
|
|
||||||
GetPropertyData("EndRoundAtLevelEnd").AssignGUIComponent(endBox);
|
|
||||||
|
|
||||||
var endVoteBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), roundsTab.RectTransform),
|
var endVoteBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), roundsTab.RectTransform),
|
||||||
TextManager.Get("ServerSettingsEndRoundVoting"));
|
TextManager.Get("ServerSettingsEndRoundVoting"));
|
||||||
GetPropertyData("AllowEndVoting").AssignGUIComponent(endVoteBox);
|
GetPropertyData("AllowEndVoting").AssignGUIComponent(endVoteBox);
|
||||||
@@ -569,6 +565,8 @@ namespace Barotrauma.Networking
|
|||||||
};
|
};
|
||||||
slider.OnMoved(slider, slider.BarScroll);
|
slider.OnMoved(slider, slider.BarScroll);
|
||||||
|
|
||||||
|
var traitorsMinPlayerCount = CreateLabeledNumberInput(roundsTab, "ServerSettingsTraitorsMinPlayerCount", 1, 16, "ServerSettingsTraitorsMinPlayerCountToolTip");
|
||||||
|
GetPropertyData("TraitorsMinPlayerCount").AssignGUIComponent(traitorsMinPlayerCount);
|
||||||
|
|
||||||
var ragdollButtonBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), roundsTab.RectTransform), TextManager.Get("ServerSettingsAllowRagdollButton"));
|
var ragdollButtonBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), roundsTab.RectTransform), TextManager.Get("ServerSettingsAllowRagdollButton"));
|
||||||
GetPropertyData("AllowRagdollButton").AssignGUIComponent(ragdollButtonBox);
|
GetPropertyData("AllowRagdollButton").AssignGUIComponent(ragdollButtonBox);
|
||||||
@@ -576,53 +574,6 @@ namespace Barotrauma.Networking
|
|||||||
var disableBotConversationsBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), roundsTab.RectTransform), TextManager.Get("ServerSettingsDisableBotConversations"));
|
var disableBotConversationsBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), roundsTab.RectTransform), TextManager.Get("ServerSettingsDisableBotConversations"));
|
||||||
GetPropertyData("DisableBotConversations").AssignGUIComponent(disableBotConversationsBox);
|
GetPropertyData("DisableBotConversations").AssignGUIComponent(disableBotConversationsBox);
|
||||||
|
|
||||||
/*var traitorRatioBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), roundsTab.RectTransform), TextManager.Get("ServerSettingsUseTraitorRatio"));
|
|
||||||
|
|
||||||
CreateLabeledSlider(roundsTab, "", out slider, out sliderLabel);
|
|
||||||
var traitorRatioSlider = slider;
|
|
||||||
traitorRatioBox.OnSelected = (GUITickBox) =>
|
|
||||||
{
|
|
||||||
traitorRatioSlider.OnMoved(traitorRatioSlider, traitorRatioSlider.BarScroll);
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
if (TraitorUseRatio)
|
|
||||||
{
|
|
||||||
traitorRatioSlider.Range = new Vector2(0.1f, 1.0f);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
traitorRatioSlider.Range = new Vector2(1.0f, maxPlayers);
|
|
||||||
}
|
|
||||||
|
|
||||||
string traitorRatioLabel = TextManager.Get("ServerSettingsTraitorRatio") + " ";
|
|
||||||
string traitorCountLabel = TextManager.Get("ServerSettingsTraitorCount") + " ";
|
|
||||||
|
|
||||||
traitorRatioSlider.Range = new Vector2(0.1f, 1.0f);
|
|
||||||
traitorRatioSlider.OnMoved = (GUIScrollBar scrollBar, float barScroll) =>
|
|
||||||
{
|
|
||||||
GUITextBlock traitorText = scrollBar.UserData as GUITextBlock;
|
|
||||||
if (traitorRatioBox.Selected)
|
|
||||||
{
|
|
||||||
scrollBar.Step = 0.01f;
|
|
||||||
scrollBar.Range = new Vector2(0.1f, 1.0f);
|
|
||||||
traitorText.Text = traitorRatioLabel + (int)MathUtils.Round(scrollBar.BarScrollValue * 100.0f, 1.0f) + " %";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
scrollBar.Step = 1f / (maxPlayers - 1);
|
|
||||||
scrollBar.Range = new Vector2(1.0f, maxPlayers);
|
|
||||||
traitorText.Text = traitorCountLabel + scrollBar.BarScrollValue;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
GetPropertyData("TraitorUseRatio").AssignGUIComponent(traitorRatioBox);
|
|
||||||
GetPropertyData("TraitorRatio").AssignGUIComponent(traitorRatioSlider);
|
|
||||||
|
|
||||||
traitorRatioSlider.OnMoved(traitorRatioSlider, traitorRatioSlider.BarScroll);
|
|
||||||
traitorRatioBox.OnSelected(traitorRatioBox);*/
|
|
||||||
|
|
||||||
var buttonHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.07f), roundsTab.RectTransform), isHorizontal: true)
|
var buttonHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.07f), roundsTab.RectTransform), isHorizontal: true)
|
||||||
{
|
{
|
||||||
Stretch = true,
|
Stretch = true,
|
||||||
@@ -919,7 +870,7 @@ namespace Barotrauma.Networking
|
|||||||
slider.UserData = label;
|
slider.UserData = label;
|
||||||
}
|
}
|
||||||
|
|
||||||
private GUINumberInput CreateLabeledNumberInput(GUIComponent parent, string labelTag, int min, int max)
|
private GUINumberInput CreateLabeledNumberInput(GUIComponent parent, string labelTag, int min, int max, string toolTipTag = null)
|
||||||
{
|
{
|
||||||
var container = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.1f), parent.RectTransform), isHorizontal: true)
|
var container = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.1f), parent.RectTransform), isHorizontal: true)
|
||||||
{
|
{
|
||||||
@@ -928,11 +879,15 @@ namespace Barotrauma.Networking
|
|||||||
ToolTip = TextManager.Get(labelTag)
|
ToolTip = TextManager.Get(labelTag)
|
||||||
};
|
};
|
||||||
|
|
||||||
new GUITextBlock(new RectTransform(new Vector2(0.7f, 1.0f), container.RectTransform),
|
var label = new GUITextBlock(new RectTransform(new Vector2(0.7f, 1.0f), container.RectTransform),
|
||||||
TextManager.Get(labelTag), textAlignment: Alignment.CenterLeft, font: GUI.SmallFont)
|
TextManager.Get(labelTag), textAlignment: Alignment.CenterLeft, font: GUI.SmallFont)
|
||||||
{
|
{
|
||||||
AutoScaleHorizontal = true
|
AutoScaleHorizontal = true
|
||||||
};
|
};
|
||||||
|
if (!string.IsNullOrEmpty(toolTipTag))
|
||||||
|
{
|
||||||
|
label.ToolTip = TextManager.Get(toolTipTag);
|
||||||
|
}
|
||||||
var input = new GUINumberInput(new RectTransform(new Vector2(0.3f, 1.0f), container.RectTransform), GUINumberInput.NumberType.Int)
|
var input = new GUINumberInput(new RectTransform(new Vector2(0.3f, 1.0f), container.RectTransform), GUINumberInput.NumberType.Int)
|
||||||
{
|
{
|
||||||
MinValueInt = min,
|
MinValueInt = min,
|
||||||
|
|||||||
@@ -1,22 +1,18 @@
|
|||||||
using Barotrauma.Networking;
|
using Barotrauma.IO;
|
||||||
|
using Barotrauma.Networking;
|
||||||
using RestSharp;
|
using RestSharp;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Barotrauma.IO;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using RestSharp.Contrib;
|
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
using Color = Microsoft.Xna.Framework.Color;
|
using Color = Microsoft.Xna.Framework.Color;
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using NLog.Fluent;
|
|
||||||
|
|
||||||
namespace Barotrauma.Steam
|
namespace Barotrauma.Steam
|
||||||
{
|
{
|
||||||
static partial class SteamManager
|
static partial class SteamManager
|
||||||
{
|
{
|
||||||
private static Dictionary<Steamworks.Data.PublishedFileId, Task> modCopiesInProgress = new Dictionary<Steamworks.Data.PublishedFileId, Task>();
|
private static readonly Dictionary<Steamworks.Data.PublishedFileId, Task> modCopiesInProgress = new Dictionary<Steamworks.Data.PublishedFileId, Task>();
|
||||||
|
|
||||||
private static void InitializeProjectSpecific()
|
private static void InitializeProjectSpecific()
|
||||||
{
|
{
|
||||||
@@ -49,6 +45,9 @@ namespace Barotrauma.Steam
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
#if !DEBUG
|
||||||
|
DebugConsole.ThrowError("SteamManager initialization threw an exception", e);
|
||||||
|
#endif
|
||||||
isInitialized = false;
|
isInitialized = false;
|
||||||
initializationErrors.Add("SteamClientInitFailed");
|
initializationErrors.Add("SteamClientInitFailed");
|
||||||
}
|
}
|
||||||
@@ -85,28 +84,6 @@ namespace Barotrauma.Steam
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static void UpdateProjectSpecific(float deltaTime)
|
|
||||||
{
|
|
||||||
if (ugcSubscriptionTasks != null)
|
|
||||||
{
|
|
||||||
var ugcSubscriptionKeys = ugcSubscriptionTasks.Keys.ToList();
|
|
||||||
foreach (var key in ugcSubscriptionKeys)
|
|
||||||
{
|
|
||||||
var task = ugcSubscriptionTasks[key];
|
|
||||||
|
|
||||||
if (task.IsCompleted)
|
|
||||||
{
|
|
||||||
if (!task.IsCompletedSuccessfully)
|
|
||||||
{
|
|
||||||
DebugConsole.ThrowError("Failed to subscribe to a Steam Workshop item with id " + key.ToString() + ": TaskStatus = " + task.Status.ToString());
|
|
||||||
}
|
|
||||||
ugcSubscriptionTasks.Remove(key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async Task InitRelayNetworkAccess()
|
public static async Task InitRelayNetworkAccess()
|
||||||
{
|
{
|
||||||
if (!IsInitialized) { return; }
|
if (!IsInitialized) { return; }
|
||||||
@@ -209,13 +186,13 @@ namespace Barotrauma.Steam
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var contentPackages = GameMain.Config.SelectedContentPackages.Where(cp => cp.HasMultiplayerIncompatibleContent);
|
var contentPackages = GameMain.Config.AllEnabledPackages.Where(cp => cp.HasMultiplayerIncompatibleContent);
|
||||||
|
|
||||||
currentLobby?.SetData("name", serverSettings.ServerName);
|
currentLobby?.SetData("name", serverSettings.ServerName);
|
||||||
currentLobby?.SetData("playercount", (GameMain.Client?.ConnectedClients?.Count ?? 0).ToString());
|
currentLobby?.SetData("playercount", (GameMain.Client?.ConnectedClients?.Count ?? 0).ToString());
|
||||||
currentLobby?.SetData("maxplayernum", serverSettings.MaxPlayers.ToString());
|
currentLobby?.SetData("maxplayernum", serverSettings.MaxPlayers.ToString());
|
||||||
//currentLobby?.SetData("hostipaddress", lobbyIP);
|
//currentLobby?.SetData("hostipaddress", lobbyIP);
|
||||||
string pingLocation = Steamworks.SteamNetworkingUtils.LocalPingLocation.ToString();
|
string pingLocation = Steamworks.SteamNetworkingUtils.LocalPingLocation?.ToString();
|
||||||
currentLobby?.SetData("pinglocation", pingLocation ?? "");
|
currentLobby?.SetData("pinglocation", pingLocation ?? "");
|
||||||
currentLobby?.SetData("lobbyowner", SteamIDUInt64ToString(GetSteamID()));
|
currentLobby?.SetData("lobbyowner", SteamIDUInt64ToString(GetSteamID()));
|
||||||
currentLobby?.SetData("haspassword", serverSettings.HasPassword.ToString());
|
currentLobby?.SetData("haspassword", serverSettings.HasPassword.ToString());
|
||||||
@@ -225,7 +202,7 @@ namespace Barotrauma.Steam
|
|||||||
|
|
||||||
currentLobby?.SetData("contentpackage", string.Join(",", contentPackages.Select(cp => cp.Name)));
|
currentLobby?.SetData("contentpackage", string.Join(",", contentPackages.Select(cp => cp.Name)));
|
||||||
currentLobby?.SetData("contentpackagehash", string.Join(",", contentPackages.Select(cp => cp.MD5hash.Hash)));
|
currentLobby?.SetData("contentpackagehash", string.Join(",", contentPackages.Select(cp => cp.MD5hash.Hash)));
|
||||||
currentLobby?.SetData("contentpackageurl", string.Join(",", contentPackages.Select(cp => cp.SteamWorkshopUrl ?? "")));
|
currentLobby?.SetData("contentpackageid", string.Join(",", contentPackages.Select(cp => cp.SteamWorkshopId)));
|
||||||
currentLobby?.SetData("usingwhitelist", (serverSettings.Whitelist != null && serverSettings.Whitelist.Enabled).ToString());
|
currentLobby?.SetData("usingwhitelist", (serverSettings.Whitelist != null && serverSettings.Whitelist.Enabled).ToString());
|
||||||
currentLobby?.SetData("modeselectionmode", serverSettings.ModeSelectionMode.ToString());
|
currentLobby?.SetData("modeselectionmode", serverSettings.ModeSelectionMode.ToString());
|
||||||
currentLobby?.SetData("subselectionmode", serverSettings.SubSelectionMode.ToString());
|
currentLobby?.SetData("subselectionmode", serverSettings.SubSelectionMode.ToString());
|
||||||
@@ -280,9 +257,8 @@ namespace Barotrauma.Steam
|
|||||||
{
|
{
|
||||||
if (!isInitialized) { return false; }
|
if (!isInitialized) { return false; }
|
||||||
|
|
||||||
|
|
||||||
int doneTasks = 0;
|
int doneTasks = 0;
|
||||||
Action taskDone = () =>
|
void taskDone()
|
||||||
{
|
{
|
||||||
doneTasks++;
|
doneTasks++;
|
||||||
if (doneTasks >= 2)
|
if (doneTasks >= 2)
|
||||||
@@ -290,52 +266,64 @@ namespace Barotrauma.Steam
|
|||||||
serverQueryFinished?.Invoke();
|
serverQueryFinished?.Invoke();
|
||||||
serverQueryFinished = null;
|
serverQueryFinished = null;
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
//TODO: find a better strategy to fetch all lobbies, this is gonna take forever if we actually have 10000 lobbies
|
//TODO: find a better strategy to fetch all lobbies, this is gonna take forever if we actually have 10000 lobbies
|
||||||
Steamworks.Data.LobbyQuery lobbyQuery = Steamworks.SteamMatchmaking.CreateLobbyQuery().FilterDistanceWorldwide().WithMaxResults(10000);
|
Steamworks.Data.LobbyQuery lobbyQuery = Steamworks.SteamMatchmaking.CreateLobbyQuery().FilterDistanceWorldwide().WithMaxResults(10000);
|
||||||
|
|
||||||
|
Steamworks.Dispatch.OnDebugCallback = (callbackType, contents, isServer) =>
|
||||||
|
{
|
||||||
|
DebugConsole.NewMessage($"{callbackType}: " + contents, Color.Yellow);
|
||||||
|
};
|
||||||
TaskPool.Add("LobbyQueryRequest", lobbyQuery.RequestAsync(),
|
TaskPool.Add("LobbyQueryRequest", lobbyQuery.RequestAsync(),
|
||||||
(t) =>
|
(t) =>
|
||||||
{
|
{
|
||||||
var lobbies = ((Task<Steamworks.Data.Lobby[]>)t).Result;
|
Steamworks.Dispatch.OnDebugCallback = null;
|
||||||
foreach (var lobby in lobbies)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(lobby.GetData("name"))) { continue; }
|
|
||||||
|
|
||||||
ServerInfo serverInfo = new ServerInfo();
|
|
||||||
serverInfo.ServerName = lobby.GetData("name");
|
|
||||||
serverInfo.OwnerID = SteamIDStringToUInt64(lobby.GetData("lobbyowner"));
|
|
||||||
serverInfo.LobbyID = lobby.Id;
|
|
||||||
bool.TryParse(lobby.GetData("haspassword"), out serverInfo.HasPassword);
|
|
||||||
serverInfo.PlayerCount = int.TryParse(lobby.GetData("playercount"), out int playerCount) ? playerCount : 0;
|
|
||||||
serverInfo.MaxPlayers = int.TryParse(lobby.GetData("maxplayernum"), out int maxPlayers) ? maxPlayers : 1;
|
|
||||||
serverInfo.RespondedToSteamQuery = true;
|
|
||||||
|
|
||||||
AssignLobbyDataToServerInfo(lobby, serverInfo);
|
|
||||||
|
|
||||||
addToServerList(serverInfo);
|
|
||||||
}
|
|
||||||
taskDone();
|
|
||||||
if (t.Status == TaskStatus.Faulted)
|
if (t.Status == TaskStatus.Faulted)
|
||||||
{
|
{
|
||||||
TaskPool.PrintTaskExceptions(t, "Failed to retrieve SteamP2P lobbies");
|
TaskPool.PrintTaskExceptions(t, "Failed to retrieve SteamP2P lobbies");
|
||||||
|
taskDone();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
var lobbies = ((Task<Steamworks.Data.Lobby[]>)t).Result;
|
||||||
|
if (lobbies != null)
|
||||||
|
{
|
||||||
|
foreach (var lobby in lobbies)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(lobby.GetData("name"))) { continue; }
|
||||||
|
|
||||||
|
ServerInfo serverInfo = new ServerInfo();
|
||||||
|
serverInfo.ServerName = lobby.GetData("name");
|
||||||
|
serverInfo.OwnerID = SteamIDStringToUInt64(lobby.GetData("lobbyowner"));
|
||||||
|
serverInfo.LobbyID = lobby.Id;
|
||||||
|
bool.TryParse(lobby.GetData("haspassword"), out serverInfo.HasPassword);
|
||||||
|
serverInfo.PlayerCount = int.TryParse(lobby.GetData("playercount"), out int playerCount) ? playerCount : 0;
|
||||||
|
serverInfo.MaxPlayers = int.TryParse(lobby.GetData("maxplayernum"), out int maxPlayers) ? maxPlayers : 1;
|
||||||
|
serverInfo.RespondedToSteamQuery = true;
|
||||||
|
|
||||||
|
AssignLobbyDataToServerInfo(lobby, serverInfo);
|
||||||
|
|
||||||
|
addToServerList(serverInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
taskDone();
|
||||||
});
|
});
|
||||||
|
|
||||||
Steamworks.ServerList.Internet serverQuery = new Steamworks.ServerList.Internet();
|
Steamworks.ServerList.Internet serverQuery = new Steamworks.ServerList.Internet();
|
||||||
Action<Steamworks.Data.ServerInfo, bool> onServer = (Steamworks.Data.ServerInfo info, bool responsive) =>
|
void onServer(Steamworks.Data.ServerInfo info, bool responsive)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(info.Name)) { return; }
|
if (string.IsNullOrEmpty(info.Name)) { return; }
|
||||||
|
|
||||||
ServerInfo serverInfo = new ServerInfo();
|
ServerInfo serverInfo = new ServerInfo
|
||||||
serverInfo.ServerName = info.Name;
|
{
|
||||||
serverInfo.IP = info.Address.ToString();
|
ServerName = info.Name,
|
||||||
serverInfo.Port = info.ConnectionPort.ToString();
|
HasPassword = info.Passworded,
|
||||||
serverInfo.PlayerCount = info.Players;
|
IP = info.Address.ToString(),
|
||||||
serverInfo.MaxPlayers = info.MaxPlayers;
|
Port = info.ConnectionPort.ToString(),
|
||||||
serverInfo.RespondedToSteamQuery = responsive;
|
PlayerCount = info.Players,
|
||||||
|
MaxPlayers = info.MaxPlayers,
|
||||||
|
RespondedToSteamQuery = responsive
|
||||||
|
};
|
||||||
|
|
||||||
if (responsive)
|
if (responsive)
|
||||||
{
|
{
|
||||||
@@ -344,11 +332,11 @@ namespace Barotrauma.Steam
|
|||||||
{
|
{
|
||||||
if (t.Status == TaskStatus.Faulted)
|
if (t.Status == TaskStatus.Faulted)
|
||||||
{
|
{
|
||||||
TaskPool.PrintTaskExceptions(t, "Failed to retrieve rules for "+info.Name);
|
TaskPool.PrintTaskExceptions(t, "Failed to retrieve rules for " + info.Name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var rules = ((Task<Dictionary<string,string>>)t).Result;
|
var rules = ((Task<Dictionary<string, string>>)t).Result;
|
||||||
AssignServerRulesToServerInfo(rules, serverInfo);
|
AssignServerRulesToServerInfo(rules, serverInfo);
|
||||||
|
|
||||||
CrossThread.RequestExecutionOnMainThread(() =>
|
CrossThread.RequestExecutionOnMainThread(() =>
|
||||||
@@ -365,7 +353,7 @@ namespace Barotrauma.Steam
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
}
|
||||||
serverQuery.OnResponsiveServer += (info) => onServer(info, true);
|
serverQuery.OnResponsiveServer += (info) => onServer(info, true);
|
||||||
serverQuery.OnUnresponsiveServer += (info) => onServer(info, false);
|
serverQuery.OnUnresponsiveServer += (info) => onServer(info, false);
|
||||||
|
|
||||||
@@ -393,11 +381,20 @@ namespace Barotrauma.Steam
|
|||||||
|
|
||||||
serverInfo.ContentPackageNames.AddRange(lobby.GetData("contentpackage").Split(','));
|
serverInfo.ContentPackageNames.AddRange(lobby.GetData("contentpackage").Split(','));
|
||||||
serverInfo.ContentPackageHashes.AddRange(lobby.GetData("contentpackagehash").Split(','));
|
serverInfo.ContentPackageHashes.AddRange(lobby.GetData("contentpackagehash").Split(','));
|
||||||
serverInfo.ContentPackageWorkshopUrls.AddRange(lobby.GetData("contentpackageurl").Split(','));
|
|
||||||
|
string workshopIdData = lobby.GetData("contentpackageid");
|
||||||
|
if (!string.IsNullOrEmpty(workshopIdData))
|
||||||
|
{
|
||||||
|
serverInfo.ContentPackageWorkshopIds.AddRange(ParseWorkshopIds(workshopIdData));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string[] workshopUrls = lobby.GetData("contentpackageurl").Split(',');
|
||||||
|
serverInfo.ContentPackageWorkshopIds.AddRange(WorkshopUrlsToIds(workshopUrls));
|
||||||
|
}
|
||||||
|
|
||||||
serverInfo.UsingWhiteList = getLobbyBool("usingwhitelist");
|
serverInfo.UsingWhiteList = getLobbyBool("usingwhitelist");
|
||||||
SelectionMode selectionMode;
|
if (Enum.TryParse(lobby.GetData("modeselectionmode"), out SelectionMode selectionMode)) { serverInfo.ModeSelectionMode = selectionMode; }
|
||||||
if (Enum.TryParse(lobby.GetData("modeselectionmode"), out selectionMode)) { serverInfo.ModeSelectionMode = selectionMode; }
|
|
||||||
if (Enum.TryParse(lobby.GetData("subselectionmode"), out selectionMode)) { serverInfo.SubSelectionMode = selectionMode; }
|
if (Enum.TryParse(lobby.GetData("subselectionmode"), out selectionMode)) { serverInfo.SubSelectionMode = selectionMode; }
|
||||||
|
|
||||||
serverInfo.AllowSpectating = getLobbyBool("allowspectating");
|
serverInfo.AllowSpectating = getLobbyBool("allowspectating");
|
||||||
@@ -412,11 +409,12 @@ namespace Barotrauma.Steam
|
|||||||
if (Enum.TryParse(lobby.GetData("playstyle"), out PlayStyle playStyle)) serverInfo.PlayStyle = playStyle;
|
if (Enum.TryParse(lobby.GetData("playstyle"), out PlayStyle playStyle)) serverInfo.PlayStyle = playStyle;
|
||||||
|
|
||||||
if (serverInfo.ContentPackageNames.Count != serverInfo.ContentPackageHashes.Count ||
|
if (serverInfo.ContentPackageNames.Count != serverInfo.ContentPackageHashes.Count ||
|
||||||
serverInfo.ContentPackageHashes.Count != serverInfo.ContentPackageWorkshopUrls.Count)
|
serverInfo.ContentPackageHashes.Count != serverInfo.ContentPackageWorkshopIds.Count)
|
||||||
{
|
{
|
||||||
//invalid contentpackage info
|
//invalid contentpackage info
|
||||||
serverInfo.ContentPackageNames.Clear();
|
serverInfo.ContentPackageNames.Clear();
|
||||||
serverInfo.ContentPackageHashes.Clear();
|
serverInfo.ContentPackageHashes.Clear();
|
||||||
|
serverInfo.ContentPackageWorkshopIds.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
string pingLocation = lobby.GetData("pinglocation");
|
string pingLocation = lobby.GetData("pinglocation");
|
||||||
@@ -449,10 +447,18 @@ namespace Barotrauma.Steam
|
|||||||
|
|
||||||
serverInfo.ContentPackageNames.Clear();
|
serverInfo.ContentPackageNames.Clear();
|
||||||
serverInfo.ContentPackageHashes.Clear();
|
serverInfo.ContentPackageHashes.Clear();
|
||||||
serverInfo.ContentPackageWorkshopUrls.Clear();
|
serverInfo.ContentPackageWorkshopIds.Clear();
|
||||||
if (rules.ContainsKey("contentpackage")) serverInfo.ContentPackageNames.AddRange(rules["contentpackage"].Split(','));
|
if (rules.ContainsKey("contentpackage")) serverInfo.ContentPackageNames.AddRange(rules["contentpackage"].Split(','));
|
||||||
if (rules.ContainsKey("contentpackagehash")) serverInfo.ContentPackageHashes.AddRange(rules["contentpackagehash"].Split(','));
|
if (rules.ContainsKey("contentpackagehash")) serverInfo.ContentPackageHashes.AddRange(rules["contentpackagehash"].Split(','));
|
||||||
if (rules.ContainsKey("contentpackageurl")) serverInfo.ContentPackageWorkshopUrls.AddRange(rules["contentpackageurl"].Split(','));
|
if (rules.ContainsKey("contentpackageid"))
|
||||||
|
{
|
||||||
|
serverInfo.ContentPackageWorkshopIds.AddRange(ParseWorkshopIds(rules["contentpackageid"]));
|
||||||
|
}
|
||||||
|
else if (rules.ContainsKey("contentpackageurl"))
|
||||||
|
{
|
||||||
|
string[] workshopUrls = rules["contentpackageurl"].Split(',');
|
||||||
|
serverInfo.ContentPackageWorkshopIds.AddRange(WorkshopUrlsToIds(workshopUrls));
|
||||||
|
}
|
||||||
|
|
||||||
if (rules.ContainsKey("usingwhitelist")) serverInfo.UsingWhiteList = rules["usingwhitelist"] == "True";
|
if (rules.ContainsKey("usingwhitelist")) serverInfo.UsingWhiteList = rules["usingwhitelist"] == "True";
|
||||||
if (rules.ContainsKey("modeselectionmode"))
|
if (rules.ContainsKey("modeselectionmode"))
|
||||||
@@ -479,37 +485,16 @@ namespace Barotrauma.Steam
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (serverInfo.ContentPackageNames.Count != serverInfo.ContentPackageHashes.Count ||
|
if (serverInfo.ContentPackageNames.Count != serverInfo.ContentPackageHashes.Count ||
|
||||||
serverInfo.ContentPackageHashes.Count != serverInfo.ContentPackageWorkshopUrls.Count)
|
serverInfo.ContentPackageHashes.Count != serverInfo.ContentPackageWorkshopIds.Count)
|
||||||
{
|
{
|
||||||
//invalid contentpackage info
|
//invalid contentpackage info
|
||||||
serverInfo.ContentPackageNames.Clear();
|
serverInfo.ContentPackageNames.Clear();
|
||||||
serverInfo.ContentPackageHashes.Clear();
|
serverInfo.ContentPackageHashes.Clear();
|
||||||
|
serverInfo.ContentPackageWorkshopIds.Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ulong GetWorkshopItemIDFromUrl(string url)
|
#region Connecting to servers
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Uri uri = new Uri(url);
|
|
||||||
string idStr = HttpUtility.ParseQueryString(uri.Query).Get("id");
|
|
||||||
if (ulong.TryParse(idStr, out ulong id))
|
|
||||||
{
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
DebugConsole.ThrowError("Failed to get Workshop item ID from the url \"" + url + "\"!", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Connecting to servers
|
|
||||||
|
|
||||||
//TODO: reimplement server list queries
|
|
||||||
|
|
||||||
private static Steamworks.AuthTicket currentTicket = null;
|
private static Steamworks.AuthTicket currentTicket = null;
|
||||||
public static Steamworks.AuthTicket GetAuthSessionTicket()
|
public static Steamworks.AuthTicket GetAuthSessionTicket()
|
||||||
{
|
{
|
||||||
@@ -545,9 +530,9 @@ namespace Barotrauma.Steam
|
|||||||
Steamworks.SteamUser.EndAuthSession(clientSteamID);
|
Steamworks.SteamUser.EndAuthSession(clientSteamID);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Workshop
|
#region Workshop
|
||||||
|
|
||||||
public const string WorkshopItemPreviewImageFolder = "Workshop";
|
public const string WorkshopItemPreviewImageFolder = "Workshop";
|
||||||
public const string PreviewImageName = "PreviewImage.png";
|
public const string PreviewImageName = "PreviewImage.png";
|
||||||
@@ -620,7 +605,8 @@ namespace Barotrauma.Steam
|
|||||||
.WithLongDescription();
|
.WithLongDescription();
|
||||||
if (requireTags != null) query.WithTags(requireTags);
|
if (requireTags != null) query.WithTags(requireTags);
|
||||||
|
|
||||||
TaskPool.Add("GetPopularWorkshopItems", GetWorkshopItemsAsync(query, amount, (item) => !item.IsSubscribed), (task) => {
|
TaskPool.Add("GetPopularWorkshopItems", GetWorkshopItemsAsync(query, amount, (item) => !item.IsSubscribed), (task) =>
|
||||||
|
{
|
||||||
var entries = ((Task<List<Steamworks.Ugc.Item>>)task).Result;
|
var entries = ((Task<List<Steamworks.Ugc.Item>>)task).Result;
|
||||||
|
|
||||||
//count the number of each unique tag
|
//count the number of each unique tag
|
||||||
@@ -669,47 +655,82 @@ namespace Barotrauma.Steam
|
|||||||
TaskPool.Add("GetPublishedWorkshopItems", GetWorkshopItemsAsync(query), (task) => { onItemsFound?.Invoke(((Task<List<Steamworks.Ugc.Item>>)task).Result); });
|
TaskPool.Add("GetPublishedWorkshopItems", GetWorkshopItemsAsync(query), (task) => { onItemsFound?.Invoke(((Task<List<Steamworks.Ugc.Item>>)task).Result); });
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Dictionary<ulong, Task> ugcSubscriptionTasks;
|
private static readonly HashSet<ulong> pendingWorkshopSubscriptions = new HashSet<ulong>();
|
||||||
|
|
||||||
public static void SubscribeToWorkshopItem(string itemUrl)
|
public static void SubscribeToWorkshopItem(ulong id, Action onInstalled = null)
|
||||||
{
|
|
||||||
if (!isInitialized) return;
|
|
||||||
|
|
||||||
ulong id = GetWorkshopItemIDFromUrl(itemUrl);
|
|
||||||
|
|
||||||
SubscribeToWorkshopItem(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void SubscribeToWorkshopItem(ulong id)
|
|
||||||
{
|
{
|
||||||
if (!isInitialized) return;
|
if (!isInitialized) return;
|
||||||
|
|
||||||
if (id == 0) { return; }
|
if (id == 0) { return; }
|
||||||
|
|
||||||
if (ugcSubscriptionTasks?.ContainsKey(id) ?? false) { return; }
|
if (pendingWorkshopSubscriptions.Contains(id)) { return; }
|
||||||
|
|
||||||
ugcSubscriptionTasks ??= new Dictionary<ulong, Task>();
|
pendingWorkshopSubscriptions.Add(id);
|
||||||
ugcSubscriptionTasks.Add(id, Task.Run(async () =>
|
TaskPool.Add(
|
||||||
{
|
$"SubscribeToWorkshopItem({id})",
|
||||||
Steamworks.Ugc.Item? item = await Steamworks.SteamUGC.QueryFileAsync(id);
|
Task.Run(async () =>
|
||||||
|
{
|
||||||
|
Steamworks.Ugc.Item? item = await Steamworks.SteamUGC.QueryFileAsync(id);
|
||||||
|
|
||||||
if (!item.HasValue)
|
if (!item.HasValue)
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError("Failed to find a Steam Workshop item with the ID " + id.ToString() + ".");
|
DebugConsole.ThrowError($"Failed to find a Steam Workshop item with the ID {id}.");
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool subscribed = await item?.Subscribe();
|
if (!(item?.IsSubscribed ?? false))
|
||||||
if (!subscribed)
|
{
|
||||||
|
bool subscribed = await item?.Subscribe();
|
||||||
|
if (!subscribed)
|
||||||
|
{
|
||||||
|
DebugConsole.ThrowError($"Failed to subscribe to Steam Workshop item with the ID {id}.");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return item;
|
||||||
|
}),
|
||||||
|
(t) =>
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError("Failed to subscribe to Steam Workshop item with the ID " + id.ToString() + ".");
|
bool shouldCleanup = true;
|
||||||
}
|
if (t.IsFaulted)
|
||||||
bool downloading = item?.Download() ?? false;
|
{
|
||||||
if (!downloading)
|
TaskPool.PrintTaskExceptions(t, $"Workshop subscription task {id} faulted");
|
||||||
{
|
}
|
||||||
DebugConsole.ThrowError("Failed to start downloading Steam Workshop item with the ID " + id.ToString() + ".");
|
else
|
||||||
}
|
{
|
||||||
}));
|
var item = ((Task<Steamworks.Ugc.Item?>)t).Result;
|
||||||
|
if (item != null)
|
||||||
|
{
|
||||||
|
if (item?.IsInstalled ?? false)
|
||||||
|
{
|
||||||
|
onInstalled?.Invoke();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
void _onInstalled()
|
||||||
|
{
|
||||||
|
onInstalled?.Invoke();
|
||||||
|
pendingWorkshopSubscriptions.Remove(id);
|
||||||
|
}
|
||||||
|
bool downloading = item?.Download(_onInstalled) ?? false;
|
||||||
|
if (!downloading)
|
||||||
|
{
|
||||||
|
DebugConsole.ThrowError($"Failed to start downloading Steam Workshop item with the ID {id}.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
shouldCleanup = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldCleanup)
|
||||||
|
{
|
||||||
|
pendingWorkshopSubscriptions.Remove(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void CreateWorkshopItemStaging(ContentPackage contentPackage, out Steamworks.Ugc.Editor? itemEditor)
|
public static void CreateWorkshopItemStaging(ContentPackage contentPackage, out Steamworks.Ugc.Editor? itemEditor)
|
||||||
@@ -790,9 +811,9 @@ namespace Barotrauma.Steam
|
|||||||
itemEditor = itemEditor?.WithPrivateVisibility();
|
itemEditor = itemEditor?.WithPrivateVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!CheckWorkshopItemEnabled(existingItem))
|
if (!CheckWorkshopItemInstalled(existingItem))
|
||||||
{
|
{
|
||||||
if (!EnableWorkShopItem(existingItem, out string errorMsg))
|
if (!InstallWorkshopItem(existingItem, out string errorMsg))
|
||||||
{
|
{
|
||||||
DebugConsole.NewMessage(errorMsg, Color.Red);
|
DebugConsole.NewMessage(errorMsg, Color.Red);
|
||||||
new GUIMessageBox(
|
new GUIMessageBox(
|
||||||
@@ -804,9 +825,9 @@ namespace Barotrauma.Steam
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ContentPackage tempContentPackage = new ContentPackage(Path.Combine(existingItem?.Directory, MetadataFileName)) { SteamWorkshopUrl = existingItem.Value.Url };
|
ContentPackage tempContentPackage = new ContentPackage(Path.Combine(existingItem?.Directory, MetadataFileName)) { SteamWorkshopId = existingItem.Value.Id };
|
||||||
string installedContentPackagePath = Path.GetFullPath(GetWorkshopItemContentPackagePath(tempContentPackage));
|
string installedContentPackagePath = Path.GetFullPath(GetWorkshopItemContentPackagePath(tempContentPackage));
|
||||||
contentPackage = ContentPackage.List.Find(cp => Path.GetFullPath(cp.Path) == installedContentPackagePath);
|
contentPackage = ContentPackage.AllPackages.FirstOrDefault(cp => Path.GetFullPath(cp.Path) == installedContentPackagePath);
|
||||||
|
|
||||||
itemEditor = itemEditor?.WithContent(Path.GetDirectoryName(installedContentPackagePath));
|
itemEditor = itemEditor?.WithContent(Path.GetDirectoryName(installedContentPackagePath));
|
||||||
|
|
||||||
@@ -923,7 +944,7 @@ namespace Barotrauma.Steam
|
|||||||
workshopPublishStatus.Result = task.Result;
|
workshopPublishStatus.Result = task.Result;
|
||||||
DebugConsole.NewMessage("Published workshop item " + item?.Title + " successfully.", Microsoft.Xna.Framework.Color.LightGreen);
|
DebugConsole.NewMessage("Published workshop item " + item?.Title + " successfully.", Microsoft.Xna.Framework.Color.LightGreen);
|
||||||
|
|
||||||
contentPackage.SteamWorkshopUrl = $"http://steamcommunity.com/sharedfiles/filedetails/?source=Facepunch.Steamworks&id={task.Result.FileId.Value}";
|
contentPackage.SteamWorkshopId = task.Result.FileId.Value;
|
||||||
//NOTE: This sets InstallTime one hour into the future to guarantee
|
//NOTE: This sets InstallTime one hour into the future to guarantee
|
||||||
//that the published content package won't be autoupdated incorrectly.
|
//that the published content package won't be autoupdated incorrectly.
|
||||||
//Change if it causes issues.
|
//Change if it causes issues.
|
||||||
@@ -937,9 +958,9 @@ namespace Barotrauma.Steam
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Enables a workshop item by moving it to the game folder.
|
/// Installs a workshop item by moving it to the game folder.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static bool EnableWorkShopItem(Steamworks.Ugc.Item? item, out string errorMsg, bool selectContentPackage = false, bool suppressInstallNotif = false)
|
public static bool InstallWorkshopItem(Steamworks.Ugc.Item? item, out string errorMsg, bool enableContentPackage = false, bool suppressInstallNotif = false)
|
||||||
{
|
{
|
||||||
if (!(item?.IsInstalled ?? false))
|
if (!(item?.IsInstalled ?? false))
|
||||||
{
|
{
|
||||||
@@ -959,11 +980,11 @@ namespace Barotrauma.Steam
|
|||||||
|
|
||||||
ContentPackage contentPackage = new ContentPackage(metaDataFilePath)
|
ContentPackage contentPackage = new ContentPackage(metaDataFilePath)
|
||||||
{
|
{
|
||||||
SteamWorkshopUrl = item?.Url
|
SteamWorkshopId = item?.Id ?? 0
|
||||||
};
|
};
|
||||||
string newContentPackagePath = GetWorkshopItemContentPackagePath(contentPackage);
|
string newContentPackagePath = GetWorkshopItemContentPackagePath(contentPackage);
|
||||||
|
|
||||||
List<ContentPackage> existingPackages = ContentPackage.List.Where(cp => cp.Path.CleanUpPath() == newContentPackagePath.CleanUpPath()).ToList();
|
List<ContentPackage> existingPackages = ContentPackage.AllPackages.Where(cp => cp.Path.CleanUpPath() == newContentPackagePath.CleanUpPath()).ToList();
|
||||||
if (existingPackages.Any())
|
if (existingPackages.Any())
|
||||||
{
|
{
|
||||||
if (item?.Owner.Id != Steamworks.SteamClient.SteamId)
|
if (item?.Owner.Id != Steamworks.SteamClient.SteamId)
|
||||||
@@ -975,7 +996,7 @@ namespace Barotrauma.Steam
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
RemoveMods(cp => !string.IsNullOrWhiteSpace(cp.SteamWorkshopUrl) && cp.SteamWorkshopUrl == contentPackage.SteamWorkshopUrl,
|
RemoveMods(cp => cp.SteamWorkshopId != 0 && cp.SteamWorkshopId == contentPackage.SteamWorkshopId,
|
||||||
false);
|
false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1024,7 +1045,7 @@ namespace Barotrauma.Steam
|
|||||||
|
|
||||||
var newPackage = new ContentPackage(cp.Path, newContentPackagePath)
|
var newPackage = new ContentPackage(cp.Path, newContentPackagePath)
|
||||||
{
|
{
|
||||||
SteamWorkshopUrl = item?.Url,
|
SteamWorkshopId = item?.Id ?? 0,
|
||||||
InstallTime = item?.Updated > item?.Created ? item?.Updated : item?.Created
|
InstallTime = item?.Updated > item?.Created ? item?.Updated : item?.Created
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1045,17 +1066,17 @@ namespace Barotrauma.Steam
|
|||||||
Directory.CreateDirectory(Path.GetDirectoryName(newContentPackagePath));
|
Directory.CreateDirectory(Path.GetDirectoryName(newContentPackagePath));
|
||||||
}
|
}
|
||||||
newPackage.Save(newContentPackagePath);
|
newPackage.Save(newContentPackagePath);
|
||||||
ContentPackage.List.Add(newPackage);
|
ContentPackage.AddPackage(newPackage);
|
||||||
|
|
||||||
if (selectContentPackage)
|
if (enableContentPackage)
|
||||||
{
|
{
|
||||||
if (newPackage.CorePackage)
|
if (newPackage.IsCorePackage)
|
||||||
{
|
{
|
||||||
GameMain.Config.SelectCorePackage(newPackage);
|
GameMain.Config.SelectCorePackage(newPackage);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GameMain.Config.SelectContentPackage(newPackage);
|
GameMain.Config.EnableRegularPackage(newPackage);
|
||||||
}
|
}
|
||||||
GameMain.Config.SaveNewPlayerConfig();
|
GameMain.Config.SaveNewPlayerConfig();
|
||||||
|
|
||||||
@@ -1213,40 +1234,21 @@ namespace Barotrauma.Steam
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool CheckFileEquality(string filePath1, string filePath2)
|
|
||||||
{
|
|
||||||
if (filePath1 == filePath2)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
using (FileStream fs1 = File.OpenRead(filePath1))
|
|
||||||
using (FileStream fs2 = File.OpenRead(filePath2))
|
|
||||||
{
|
|
||||||
Md5Hash hash1 = new Md5Hash(fs1);
|
|
||||||
Md5Hash hash2 = new Md5Hash(fs2);
|
|
||||||
return hash1.Hash == hash2.Hash;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void RemoveMods(Func<ContentPackage, bool> predicate, bool delete = true)
|
private static void RemoveMods(Func<ContentPackage, bool> predicate, bool delete = true)
|
||||||
{
|
{
|
||||||
var toRemove = ContentPackage.List.Where(predicate).ToList();
|
var toRemoveCore = ContentPackage.CorePackages.Where(predicate).ToList();
|
||||||
var packagesToDeselect = GameMain.Config.SelectedContentPackages.Where(p => toRemove.Contains(p)).ToList();
|
if (toRemoveCore.Contains(GameMain.Config.CurrentCorePackage)) { GameMain.Config.AutoSelectCorePackage(toRemoveCore); }
|
||||||
|
|
||||||
|
var toRemoveRegular = ContentPackage.RegularPackages.Where(predicate).ToList();
|
||||||
|
var packagesToDeselect = GameMain.Config.EnabledRegularPackages.Where(p => toRemoveRegular.Contains(p)).ToList();
|
||||||
foreach (var cp in packagesToDeselect)
|
foreach (var cp in packagesToDeselect)
|
||||||
{
|
{
|
||||||
if (cp.CorePackage)
|
GameMain.Config.DisableRegularPackage(cp);
|
||||||
{
|
|
||||||
GameMain.Config.AutoSelectCorePackage(toRemove);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
GameMain.Config.DeselectContentPackage(cp);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (delete)
|
if (delete)
|
||||||
{
|
{
|
||||||
|
var toRemove = toRemoveCore.Concat(toRemoveRegular);
|
||||||
foreach (var cp in toRemove)
|
foreach (var cp in toRemove)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -1258,22 +1260,19 @@ namespace Barotrauma.Steam
|
|||||||
{
|
{
|
||||||
DebugConsole.ThrowError($"An error occurred while attempting to delete {Path.GetDirectoryName(cp.Path)}", e);
|
DebugConsole.ThrowError($"An error occurred while attempting to delete {Path.GetDirectoryName(cp.Path)}", e);
|
||||||
}
|
}
|
||||||
|
ContentPackage.RemovePackage(cp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ContentPackage.List.RemoveAll(cp => toRemove.Contains(cp));
|
|
||||||
GameMain.Config.SelectedContentPackages.RemoveAll(cp => !ContentPackage.List.Contains(cp));
|
|
||||||
|
|
||||||
ContentPackage.SortContentPackages();
|
|
||||||
GameMain.Config.SaveNewPlayerConfig();
|
GameMain.Config.SaveNewPlayerConfig();
|
||||||
|
|
||||||
GameMain.Config.WarnIfContentPackageSelectionDirty();
|
GameMain.Config.WarnIfContentPackageSelectionDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Disables a workshop item by removing the files from the game folder.
|
/// Uninstalls a workshop item by removing the files from the game folder.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static bool DisableWorkShopItem(Steamworks.Ugc.Item? item, bool noLog, out string errorMsg)
|
public static bool UninstallWorkshopItem(Steamworks.Ugc.Item? item, bool noLog, out string errorMsg)
|
||||||
{
|
{
|
||||||
errorMsg = null;
|
errorMsg = null;
|
||||||
if (!(item?.IsInstalled ?? false))
|
if (!(item?.IsInstalled ?? false))
|
||||||
@@ -1288,13 +1287,13 @@ namespace Barotrauma.Steam
|
|||||||
|
|
||||||
ContentPackage contentPackage = new ContentPackage(Path.Combine(item?.Directory, MetadataFileName))
|
ContentPackage contentPackage = new ContentPackage(Path.Combine(item?.Directory, MetadataFileName))
|
||||||
{
|
{
|
||||||
SteamWorkshopUrl = item?.Url
|
SteamWorkshopId = item?.Id ?? 0
|
||||||
};
|
};
|
||||||
|
|
||||||
GameMain.Config.SuppressModFolderWatcher = true;
|
GameMain.Config.SuppressModFolderWatcher = true;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
RemoveMods(cp => !string.IsNullOrWhiteSpace(cp.SteamWorkshopUrl) && cp.SteamWorkshopUrl == contentPackage.SteamWorkshopUrl);
|
RemoveMods(cp => cp.SteamWorkshopId != 0 && cp.SteamWorkshopId == contentPackage.SteamWorkshopId);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@@ -1330,7 +1329,7 @@ namespace Barotrauma.Steam
|
|||||||
return contentPackage.IsCompatible();
|
return contentPackage.IsCompatible();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool CheckWorkshopItemEnabled(Steamworks.Ugc.Item? item)
|
public static bool CheckWorkshopItemInstalled(Steamworks.Ugc.Item? item)
|
||||||
{
|
{
|
||||||
if (!(item?.IsInstalled ?? false)) { return false; }
|
if (!(item?.IsInstalled ?? false)) { return false; }
|
||||||
|
|
||||||
@@ -1359,7 +1358,7 @@ namespace Barotrauma.Steam
|
|||||||
string errorMessage = "Metadata file for the Workshop item \"" + item?.Title +
|
string errorMessage = "Metadata file for the Workshop item \"" + item?.Title +
|
||||||
"\" not found. Could not combine path (" + (item?.Directory ?? "directory name empty") + ").";
|
"\" not found. Could not combine path (" + (item?.Directory ?? "directory name empty") + ").";
|
||||||
DebugConsole.ThrowError(errorMessage);
|
DebugConsole.ThrowError(errorMessage);
|
||||||
GameAnalyticsManager.AddErrorEventOnce("SteamManager.CheckWorkshopItemEnabled:PathCombineException" + item?.Title,
|
GameAnalyticsManager.AddErrorEventOnce("SteamManager.CheckWorkshopItemInstalled:PathCombineException" + item?.Title,
|
||||||
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||||
errorMessage);
|
errorMessage);
|
||||||
return false;
|
return false;
|
||||||
@@ -1373,12 +1372,12 @@ namespace Barotrauma.Steam
|
|||||||
|
|
||||||
ContentPackage contentPackage = new ContentPackage(metaDataPath)
|
ContentPackage contentPackage = new ContentPackage(metaDataPath)
|
||||||
{
|
{
|
||||||
SteamWorkshopUrl = item?.Url
|
SteamWorkshopId = item?.Id ?? 0
|
||||||
};
|
};
|
||||||
//make sure the contentpackage file is present
|
//make sure the contentpackage file is present
|
||||||
if (!File.Exists(GetWorkshopItemContentPackagePath(contentPackage)) ||
|
if (!File.Exists(GetWorkshopItemContentPackagePath(contentPackage)) ||
|
||||||
!ContentPackage.List.Any(cp => cp.SteamWorkshopUrl == contentPackage.SteamWorkshopUrl ||
|
!ContentPackage.AllPackages.Any(cp => cp.SteamWorkshopId == contentPackage.SteamWorkshopId ||
|
||||||
(string.IsNullOrWhiteSpace(cp.SteamWorkshopUrl) && cp.Name == contentPackage.Name)))
|
(cp.SteamWorkshopId == 0 && cp.Name == contentPackage.Name)))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -1399,9 +1398,9 @@ namespace Barotrauma.Steam
|
|||||||
|
|
||||||
ContentPackage steamPackage = new ContentPackage(metaDataPath)
|
ContentPackage steamPackage = new ContentPackage(metaDataPath)
|
||||||
{
|
{
|
||||||
SteamWorkshopUrl = item?.Url
|
SteamWorkshopId = item?.Id ?? 0
|
||||||
};
|
};
|
||||||
ContentPackage myPackage = ContentPackage.List.Find(cp => cp.SteamWorkshopUrl == steamPackage.SteamWorkshopUrl);
|
ContentPackage myPackage = ContentPackage.AllPackages.FirstOrDefault(cp => cp.SteamWorkshopId == steamPackage.SteamWorkshopId);
|
||||||
|
|
||||||
if (myPackage?.InstallTime == null)
|
if (myPackage?.InstallTime == null)
|
||||||
{
|
{
|
||||||
@@ -1427,7 +1426,7 @@ namespace Barotrauma.Steam
|
|||||||
GameMain.Config.SuppressModFolderWatcher = true;
|
GameMain.Config.SuppressModFolderWatcher = true;
|
||||||
|
|
||||||
//remove mods that the player is no longer subscribed to
|
//remove mods that the player is no longer subscribed to
|
||||||
RemoveMods(cp => !string.IsNullOrWhiteSpace(cp.SteamWorkshopUrl) && !items.Any(it => it.Id == GetWorkshopItemIDFromUrl(cp.SteamWorkshopUrl)));
|
RemoveMods(cp => cp.SteamWorkshopId != 0 && !items.Any(it => it.Id == cp.SteamWorkshopId));
|
||||||
|
|
||||||
GameMain.Config.SuppressModFolderWatcher = false;
|
GameMain.Config.SuppressModFolderWatcher = false;
|
||||||
|
|
||||||
@@ -1441,9 +1440,9 @@ namespace Barotrauma.Steam
|
|||||||
|
|
||||||
bool installedSuccessfully = false;
|
bool installedSuccessfully = false;
|
||||||
string errorMsg;
|
string errorMsg;
|
||||||
if (!CheckWorkshopItemEnabled(item))
|
if (!CheckWorkshopItemInstalled(item))
|
||||||
{
|
{
|
||||||
installedSuccessfully = EnableWorkShopItem(item, out errorMsg);
|
installedSuccessfully = InstallWorkshopItem(item, out errorMsg);
|
||||||
}
|
}
|
||||||
else if (!CheckWorkshopItemUpToDate(item))
|
else if (!CheckWorkshopItemUpToDate(item))
|
||||||
{
|
{
|
||||||
@@ -1529,12 +1528,12 @@ namespace Barotrauma.Steam
|
|||||||
{
|
{
|
||||||
errorMsg = "";
|
errorMsg = "";
|
||||||
if (!(item?.IsInstalled ?? false)) { return false; }
|
if (!(item?.IsInstalled ?? false)) { return false; }
|
||||||
bool reenable = GameMain.Config.SelectedContentPackages.Any(p => !string.IsNullOrEmpty(p.SteamWorkshopUrl) && GetWorkshopItemIDFromUrl(p.SteamWorkshopUrl) == item?.Id);
|
bool reenable = GameMain.Config.AllEnabledPackages.Any(p => p.SteamWorkshopId != 0 && p.SteamWorkshopId == item?.Id);
|
||||||
if (item?.Owner.Id != Steamworks.SteamClient.SteamId)
|
if (item?.Owner.Id != Steamworks.SteamClient.SteamId)
|
||||||
{
|
{
|
||||||
if (!DisableWorkShopItem(item, false, out errorMsg)) { return false; }
|
if (!UninstallWorkshopItem(item, false, out errorMsg)) { return false; }
|
||||||
}
|
}
|
||||||
if (!EnableWorkShopItem(item, errorMsg: out errorMsg, selectContentPackage: reenable)) { return false; }
|
if (!InstallWorkshopItem(item, errorMsg: out errorMsg, enableContentPackage: reenable)) { return false; }
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1543,7 +1542,7 @@ namespace Barotrauma.Steam
|
|||||||
string packageName = contentPackage.Name.Trim();
|
string packageName = contentPackage.Name.Trim();
|
||||||
packageName = ToolBox.RemoveInvalidFileNameChars(packageName);
|
packageName = ToolBox.RemoveInvalidFileNameChars(packageName);
|
||||||
while (packageName.Last() == '.') { packageName = packageName.Substring(0, packageName.Length-1); }
|
while (packageName.Last() == '.') { packageName = packageName.Substring(0, packageName.Length-1); }
|
||||||
//packageName = packageName + "_" + GetWorkshopItemIDFromUrl(contentPackage.SteamWorkshopUrl);
|
//packageName = packageName + "_" + contentPackage.SteamWorkshopId.ToString();
|
||||||
|
|
||||||
return Path.Combine("Mods", packageName, MetadataFileName);
|
return Path.Combine("Mods", packageName, MetadataFileName);
|
||||||
}
|
}
|
||||||
@@ -1559,8 +1558,7 @@ namespace Barotrauma.Steam
|
|||||||
attr.Name.ToString() == "characterfile") &&
|
attr.Name.ToString() == "characterfile") &&
|
||||||
attr.Value.CleanUpPath().Contains("/"))
|
attr.Value.CleanUpPath().Contains("/"))
|
||||||
{
|
{
|
||||||
ContentType type = ContentType.None;
|
Enum.TryParse(attr.Name.LocalName, true, out ContentType type);
|
||||||
Enum.TryParse(attr.Name.LocalName, true, out type);
|
|
||||||
attr.Value = CorrectContentFilePath(attr.Value, type, package, true);
|
attr.Value = CorrectContentFilePath(attr.Value, type, package, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1615,8 +1613,7 @@ namespace Barotrauma.Steam
|
|||||||
if (checkIfFileExists)
|
if (checkIfFileExists)
|
||||||
{
|
{
|
||||||
bool exists = File.Exists(contentFilePath);
|
bool exists = File.Exists(contentFilePath);
|
||||||
if (type == ContentType.Executable ||
|
if (type == ContentType.ServerExecutable)
|
||||||
type == ContentType.ServerExecutable)
|
|
||||||
{
|
{
|
||||||
exists |= File.Exists(Path.GetFileNameWithoutExtension(contentFilePath) + ".dll");
|
exists |= File.Exists(Path.GetFileNameWithoutExtension(contentFilePath) + ".dll");
|
||||||
}
|
}
|
||||||
@@ -1634,7 +1631,7 @@ namespace Barotrauma.Steam
|
|||||||
{
|
{
|
||||||
if (checkIfFileExists)
|
if (checkIfFileExists)
|
||||||
{
|
{
|
||||||
ContentPackage otherContentPackage = ContentPackage.List.Find(cp => cp.Name.Equals(splitPath[1], StringComparison.OrdinalIgnoreCase));
|
ContentPackage otherContentPackage = ContentPackage.AllPackages.FirstOrDefault(cp => cp.Name.Equals(splitPath[1], StringComparison.OrdinalIgnoreCase));
|
||||||
if (otherContentPackage != null)
|
if (otherContentPackage != null)
|
||||||
{
|
{
|
||||||
string otherPackageName = Path.GetDirectoryName(otherContentPackage.Path);
|
string otherPackageName = Path.GetDirectoryName(otherContentPackage.Path);
|
||||||
|
|||||||
@@ -167,7 +167,7 @@ namespace Barotrauma.Networking
|
|||||||
bool prevCaptured = true;
|
bool prevCaptured = true;
|
||||||
int captureTimer;
|
int captureTimer;
|
||||||
|
|
||||||
void UpdateCapture()
|
private void UpdateCapture()
|
||||||
{
|
{
|
||||||
Array.Copy(uncompressedBuffer, 0, prevUncompressedBuffer, 0, VoipConfig.BUFFER_SIZE);
|
Array.Copy(uncompressedBuffer, 0, prevUncompressedBuffer, 0, VoipConfig.BUFFER_SIZE);
|
||||||
Array.Clear(uncompressedBuffer, 0, VoipConfig.BUFFER_SIZE);
|
Array.Clear(uncompressedBuffer, 0, VoipConfig.BUFFER_SIZE);
|
||||||
@@ -273,6 +273,11 @@ namespace Barotrauma.Networking
|
|||||||
if (allowEnqueue || captureTimer > 0)
|
if (allowEnqueue || captureTimer > 0)
|
||||||
{
|
{
|
||||||
LastEnqueueAudio = DateTime.Now;
|
LastEnqueueAudio = DateTime.Now;
|
||||||
|
if (GameMain.Client?.Character != null)
|
||||||
|
{
|
||||||
|
var messageType = !ForceLocal && ChatMessage.CanUseRadio(GameMain.Client.Character, out _) ? ChatMessageType.Radio : ChatMessageType.Default;
|
||||||
|
GameMain.Client.Character.ShowSpeechBubble(1.25f, ChatMessage.MessageColor[(int)messageType]);
|
||||||
|
}
|
||||||
//encode audio and enqueue it
|
//encode audio and enqueue it
|
||||||
lock (buffers)
|
lock (buffers)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -91,13 +91,13 @@ namespace Barotrauma
|
|||||||
if (userData == null) return;
|
if (userData == null) return;
|
||||||
foreach (GUIComponent comp in listBox.Content.Children)
|
foreach (GUIComponent comp in listBox.Content.Children)
|
||||||
{
|
{
|
||||||
if (comp.UserData != userData) continue;
|
if (comp.UserData != userData) { continue; }
|
||||||
GUITextBlock voteText = comp.FindChild("votes") as GUITextBlock;
|
if (!(comp.FindChild("votes") is GUITextBlock voteText))
|
||||||
if (voteText == null)
|
|
||||||
{
|
{
|
||||||
voteText = new GUITextBlock(new RectTransform(new Point(30, comp.Rect.Height), comp.RectTransform, Anchor.CenterRight),
|
voteText = new GUITextBlock(new RectTransform(new Point(30, comp.Rect.Height), comp.RectTransform, Anchor.CenterRight),
|
||||||
"", textAlignment: Alignment.CenterRight)
|
"", textAlignment: Alignment.CenterRight)
|
||||||
{
|
{
|
||||||
|
Padding = Vector4.Zero,
|
||||||
UserData = "votes"
|
UserData = "votes"
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using Microsoft.Xna.Framework;
|
|||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection.Metadata;
|
||||||
|
|
||||||
namespace Barotrauma.Particles
|
namespace Barotrauma.Particles
|
||||||
{
|
{
|
||||||
@@ -61,6 +62,8 @@ namespace Barotrauma.Particles
|
|||||||
|
|
||||||
public bool HighQualityCollisionDetection;
|
public bool HighQualityCollisionDetection;
|
||||||
|
|
||||||
|
public Vector4 ColorMultiplier;
|
||||||
|
|
||||||
public bool DrawOnTop { get; private set; }
|
public bool DrawOnTop { get; private set; }
|
||||||
|
|
||||||
public ParticlePrefab.DrawTargetType DrawTarget
|
public ParticlePrefab.DrawTargetType DrawTarget
|
||||||
@@ -141,7 +144,8 @@ namespace Barotrauma.Particles
|
|||||||
|
|
||||||
color = prefab.StartColor;
|
color = prefab.StartColor;
|
||||||
changeColor = prefab.StartColor != prefab.EndColor;
|
changeColor = prefab.StartColor != prefab.EndColor;
|
||||||
|
ColorMultiplier = Vector4.One;
|
||||||
|
|
||||||
velocityChange = prefab.VelocityChangeDisplay;
|
velocityChange = prefab.VelocityChangeDisplay;
|
||||||
velocityChangeWater = prefab.VelocityChangeWaterDisplay;
|
velocityChangeWater = prefab.VelocityChangeWaterDisplay;
|
||||||
|
|
||||||
@@ -287,22 +291,42 @@ namespace Barotrauma.Particles
|
|||||||
Vector2 collisionNormal = Vector2.Zero;
|
Vector2 collisionNormal = Vector2.Zero;
|
||||||
if (velocity.Y < 0.0f && position.Y - prefab.CollisionRadius * size.Y < hullRect.Y - hullRect.Height)
|
if (velocity.Y < 0.0f && position.Y - prefab.CollisionRadius * size.Y < hullRect.Y - hullRect.Height)
|
||||||
{
|
{
|
||||||
if (prefab.DeleteOnCollision) return false;
|
if (prefab.DeleteOnCollision) { return false; }
|
||||||
collisionNormal = new Vector2(0.0f, 1.0f);
|
collisionNormal = new Vector2(0.0f, 1.0f);
|
||||||
}
|
}
|
||||||
else if (velocity.Y > 0.0f && position.Y + prefab.CollisionRadius * size.Y > hullRect.Y)
|
else if (velocity.Y > 0.0f && position.Y + prefab.CollisionRadius * size.Y > hullRect.Y)
|
||||||
{
|
{
|
||||||
if (prefab.DeleteOnCollision) return false;
|
if (prefab.DeleteOnCollision) { return false; }
|
||||||
collisionNormal = new Vector2(0.0f, -1.0f);
|
collisionNormal = new Vector2(0.0f, -1.0f);
|
||||||
}
|
}
|
||||||
else if (velocity.X < 0.0f && position.X - prefab.CollisionRadius * size.X < hullRect.X)
|
|
||||||
|
if (collisionNormal != Vector2.Zero)
|
||||||
{
|
{
|
||||||
if (prefab.DeleteOnCollision) return false;
|
bool gapFound = false;
|
||||||
|
foreach (Gap gap in hullGaps)
|
||||||
|
{
|
||||||
|
if (gap.Open <= 0.9f || gap.IsHorizontal) { continue; }
|
||||||
|
|
||||||
|
if (gap.WorldRect.X > position.X || gap.WorldRect.Right < position.X) { continue; }
|
||||||
|
float hullCenterY = currentHull.WorldRect.Y - currentHull.WorldRect.Height / 2;
|
||||||
|
int gapDir = Math.Sign(gap.WorldRect.Y - hullCenterY);
|
||||||
|
if (Math.Sign(velocity.Y) != gapDir || Math.Sign(position.Y - hullCenterY) != gapDir) { continue; }
|
||||||
|
|
||||||
|
gapFound = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
handleCollision(gapFound, collisionNormal);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (velocity.X < 0.0f && position.X - prefab.CollisionRadius * size.X < hullRect.X)
|
||||||
|
{
|
||||||
|
if (prefab.DeleteOnCollision) { return false; }
|
||||||
collisionNormal = new Vector2(1.0f, 0.0f);
|
collisionNormal = new Vector2(1.0f, 0.0f);
|
||||||
}
|
}
|
||||||
else if (velocity.X > 0.0f && position.X + prefab.CollisionRadius * size.X > hullRect.Right)
|
else if (velocity.X > 0.0f && position.X + prefab.CollisionRadius * size.X > hullRect.Right)
|
||||||
{
|
{
|
||||||
if (prefab.DeleteOnCollision) return false;
|
if (prefab.DeleteOnCollision) { return false; }
|
||||||
collisionNormal = new Vector2(-1.0f, 0.0f);
|
collisionNormal = new Vector2(-1.0f, 0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -311,26 +335,21 @@ namespace Barotrauma.Particles
|
|||||||
bool gapFound = false;
|
bool gapFound = false;
|
||||||
foreach (Gap gap in hullGaps)
|
foreach (Gap gap in hullGaps)
|
||||||
{
|
{
|
||||||
if (gap.Open <= 0.9f || gap.IsHorizontal != (collisionNormal.X != 0.0f)) continue;
|
if (gap.Open <= 0.9f || !gap.IsHorizontal) { continue; }
|
||||||
|
|
||||||
if (gap.IsHorizontal)
|
if (gap.WorldRect.Y < position.Y || gap.WorldRect.Y - gap.WorldRect.Height > position.Y) { continue; }
|
||||||
{
|
int gapDir = Math.Sign(gap.WorldRect.Center.X - currentHull.WorldRect.Center.X);
|
||||||
if (gap.WorldRect.Y < position.Y || gap.WorldRect.Y - gap.WorldRect.Height > position.Y) continue;
|
if (Math.Sign(velocity.X) != gapDir || Math.Sign(position.X - currentHull.WorldRect.Center.X) != gapDir) { continue; }
|
||||||
int gapDir = Math.Sign(gap.WorldRect.Center.X - currentHull.WorldRect.Center.X);
|
|
||||||
if (Math.Sign(velocity.X) != gapDir || Math.Sign(position.X - currentHull.WorldRect.Center.X) != gapDir) continue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (gap.WorldRect.X > position.X || gap.WorldRect.Right < position.X) continue;
|
|
||||||
float hullCenterY = currentHull.WorldRect.Y - currentHull.WorldRect.Height / 2;
|
|
||||||
int gapDir = Math.Sign(gap.WorldRect.Y - hullCenterY);
|
|
||||||
if (Math.Sign(velocity.Y) != gapDir || Math.Sign(position.Y - hullCenterY) != gapDir) continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
gapFound = true;
|
gapFound = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleCollision(gapFound, collisionNormal);
|
||||||
|
}
|
||||||
|
|
||||||
|
void handleCollision(bool gapFound, Vector2 collisionNormal)
|
||||||
|
{
|
||||||
if (!gapFound)
|
if (!gapFound)
|
||||||
{
|
{
|
||||||
OnWallCollisionInside(currentHull, collisionNormal);
|
OnWallCollisionInside(currentHull, collisionNormal);
|
||||||
@@ -378,6 +397,8 @@ namespace Barotrauma.Particles
|
|||||||
|
|
||||||
private void OnWallCollisionInside(Hull prevHull, Vector2 collisionNormal)
|
private void OnWallCollisionInside(Hull prevHull, Vector2 collisionNormal)
|
||||||
{
|
{
|
||||||
|
if (prevHull == null) { return; }
|
||||||
|
|
||||||
Rectangle prevHullRect = prevHull.WorldRect;
|
Rectangle prevHullRect = prevHull.WorldRect;
|
||||||
|
|
||||||
Vector2 subVel = prevHull?.Submarine != null ? ConvertUnits.ToDisplayUnits(prevHull.Submarine.Velocity) : Vector2.Zero;
|
Vector2 subVel = prevHull?.Submarine != null ? ConvertUnits.ToDisplayUnits(prevHull.Submarine.Velocity) : Vector2.Zero;
|
||||||
@@ -465,12 +486,14 @@ namespace Barotrauma.Particles
|
|||||||
drawSize *= ((totalLifeTime - lifeTime) / prefab.GrowTime);
|
drawSize *= ((totalLifeTime - lifeTime) / prefab.GrowTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Color currColor = new Color(color.ToVector4() * ColorMultiplier);
|
||||||
|
|
||||||
if (prefab.Sprites[spriteIndex] is SpriteSheet)
|
if (prefab.Sprites[spriteIndex] is SpriteSheet)
|
||||||
{
|
{
|
||||||
((SpriteSheet)prefab.Sprites[spriteIndex]).Draw(
|
((SpriteSheet)prefab.Sprites[spriteIndex]).Draw(
|
||||||
spriteBatch, animFrame,
|
spriteBatch, animFrame,
|
||||||
new Vector2(drawPosition.X, -drawPosition.Y),
|
new Vector2(drawPosition.X, -drawPosition.Y),
|
||||||
color * (color.A / 255.0f),
|
currColor * (currColor.A / 255.0f),
|
||||||
prefab.Sprites[spriteIndex].Origin, drawRotation,
|
prefab.Sprites[spriteIndex].Origin, drawRotation,
|
||||||
drawSize, SpriteEffects.None, prefab.Sprites[spriteIndex].Depth);
|
drawSize, SpriteEffects.None, prefab.Sprites[spriteIndex].Depth);
|
||||||
}
|
}
|
||||||
@@ -478,7 +501,7 @@ namespace Barotrauma.Particles
|
|||||||
{
|
{
|
||||||
prefab.Sprites[spriteIndex].Draw(spriteBatch,
|
prefab.Sprites[spriteIndex].Draw(spriteBatch,
|
||||||
new Vector2(drawPosition.X, -drawPosition.Y),
|
new Vector2(drawPosition.X, -drawPosition.Y),
|
||||||
color * (color.A / 255.0f),
|
currColor * (currColor.A / 255.0f),
|
||||||
prefab.Sprites[spriteIndex].Origin, drawRotation,
|
prefab.Sprites[spriteIndex].Origin, drawRotation,
|
||||||
drawSize, SpriteEffects.None, prefab.Sprites[spriteIndex].Depth);
|
drawSize, SpriteEffects.None, prefab.Sprites[spriteIndex].Depth);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ namespace Barotrauma.Particles
|
|||||||
Prefab = prefab;
|
Prefab = prefab;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Emit(float deltaTime, Vector2 position, Hull hullGuess = null, float angle = 0.0f, float particleRotation = 0.0f, float velocityMultiplier = 1.0f, float sizeMultiplier = 1.0f, float amountMultiplier = 1.0f)
|
public void Emit(float deltaTime, Vector2 position, Hull hullGuess = null, float angle = 0.0f, float particleRotation = 0.0f, float velocityMultiplier = 1.0f, float sizeMultiplier = 1.0f, float amountMultiplier = 1.0f, Color? colorMultiplier = null)
|
||||||
{
|
{
|
||||||
emitTimer += deltaTime * amountMultiplier;
|
emitTimer += deltaTime * amountMultiplier;
|
||||||
burstEmitTimer -= deltaTime;
|
burstEmitTimer -= deltaTime;
|
||||||
@@ -33,7 +33,7 @@ namespace Barotrauma.Particles
|
|||||||
float emitInterval = 1.0f / Prefab.ParticlesPerSecond;
|
float emitInterval = 1.0f / Prefab.ParticlesPerSecond;
|
||||||
while (emitTimer > emitInterval)
|
while (emitTimer > emitInterval)
|
||||||
{
|
{
|
||||||
Emit(position, hullGuess, angle, particleRotation, velocityMultiplier, sizeMultiplier);
|
Emit(position, hullGuess, angle, particleRotation, velocityMultiplier, sizeMultiplier, colorMultiplier);
|
||||||
emitTimer -= emitInterval;
|
emitTimer -= emitInterval;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -43,11 +43,11 @@ namespace Barotrauma.Particles
|
|||||||
burstEmitTimer = Prefab.EmitInterval;
|
burstEmitTimer = Prefab.EmitInterval;
|
||||||
for (int i = 0; i < Prefab.ParticleAmount * amountMultiplier; i++)
|
for (int i = 0; i < Prefab.ParticleAmount * amountMultiplier; i++)
|
||||||
{
|
{
|
||||||
Emit(position, hullGuess, angle, particleRotation, velocityMultiplier, sizeMultiplier);
|
Emit(position, hullGuess, angle, particleRotation, velocityMultiplier, sizeMultiplier, colorMultiplier);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Emit(Vector2 position, Hull hullGuess, float angle, float particleRotation, float velocityMultiplier, float sizeMultiplier)
|
private void Emit(Vector2 position, Hull hullGuess, float angle, float particleRotation, float velocityMultiplier, float sizeMultiplier, Color? colorMultiplier = null)
|
||||||
{
|
{
|
||||||
angle += Rand.Range(Prefab.AngleMin, Prefab.AngleMax);
|
angle += Rand.Range(Prefab.AngleMin, Prefab.AngleMax);
|
||||||
|
|
||||||
@@ -61,6 +61,7 @@ namespace Barotrauma.Particles
|
|||||||
{
|
{
|
||||||
particle.Size *= Rand.Range(Prefab.ScaleMin, Prefab.ScaleMax) * sizeMultiplier;
|
particle.Size *= Rand.Range(Prefab.ScaleMin, Prefab.ScaleMax) * sizeMultiplier;
|
||||||
particle.HighQualityCollisionDetection = Prefab.HighQualityCollisionDetection;
|
particle.HighQualityCollisionDetection = Prefab.HighQualityCollisionDetection;
|
||||||
|
if (colorMultiplier.HasValue) { particle.ColorMultiplier = colorMultiplier.Value.ToVector4(); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -157,9 +157,9 @@ namespace Barotrauma
|
|||||||
sb.AppendLine("VSync " + (GameMain.Config.VSyncEnabled ? "ON" : "OFF"));
|
sb.AppendLine("VSync " + (GameMain.Config.VSyncEnabled ? "ON" : "OFF"));
|
||||||
sb.AppendLine("Language: " + (GameMain.Config.Language ?? "none"));
|
sb.AppendLine("Language: " + (GameMain.Config.Language ?? "none"));
|
||||||
}
|
}
|
||||||
if (GameMain.SelectedPackages != null)
|
if (GameMain.Config.AllEnabledPackages != null)
|
||||||
{
|
{
|
||||||
sb.AppendLine("Selected content packages: " + (!GameMain.SelectedPackages.Any() ? "None" : string.Join(", ", GameMain.SelectedPackages.Select(c => c.Name))));
|
sb.AppendLine("Selected content packages: " + (!GameMain.Config.AllEnabledPackages.Any() ? "None" : string.Join(", ", GameMain.Config.AllEnabledPackages.Select(c => c.Name))));
|
||||||
}
|
}
|
||||||
sb.AppendLine("Level seed: " + ((Level.Loaded == null) ? "no level loaded" : Level.Loaded.Seed));
|
sb.AppendLine("Level seed: " + ((Level.Loaded == null) ? "no level loaded" : Level.Loaded.Seed));
|
||||||
sb.AppendLine("Loaded submarine: " + ((Submarine.MainSub == null) ? "None" : Submarine.MainSub.Info.Name + " (" + Submarine.MainSub.Info.MD5Hash + ")"));
|
sb.AppendLine("Loaded submarine: " + ((Submarine.MainSub == null) ? "None" : Submarine.MainSub.Info.Name + " (" + Submarine.MainSub.Info.MD5Hash + ")"));
|
||||||
|
|||||||
@@ -26,6 +26,9 @@ namespace Barotrauma
|
|||||||
public Action<SubmarineInfo, string, string> StartNewGame;
|
public Action<SubmarineInfo, string, string> StartNewGame;
|
||||||
public Action<string> LoadGame;
|
public Action<string> LoadGame;
|
||||||
|
|
||||||
|
private enum CategoryFilter { All = 0, Vanilla = 1, Custom = 2 };
|
||||||
|
private CategoryFilter subFilter = CategoryFilter.All;
|
||||||
|
|
||||||
public GUIButton StartButton
|
public GUIButton StartButton
|
||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
@@ -74,6 +77,12 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.02f), leftColumn.RectTransform) { MinSize = new Point(0, 20) }, TextManager.Get("SelectedSub"), font: GUI.SubHeadingFont);
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.02f), leftColumn.RectTransform) { MinSize = new Point(0, 20) }, TextManager.Get("SelectedSub"), font: GUI.SubHeadingFont);
|
||||||
|
|
||||||
|
var moddedDropdown = new GUIDropDown(new RectTransform(new Vector2(1f, 0.02f), leftColumn.RectTransform), "", 3);
|
||||||
|
moddedDropdown.AddItem(TextManager.Get("clientpermission.all"), CategoryFilter.All);
|
||||||
|
moddedDropdown.AddItem(TextManager.Get("servertag.modded.false"), CategoryFilter.Vanilla);
|
||||||
|
moddedDropdown.AddItem(TextManager.Get("customrank"), CategoryFilter.Custom);
|
||||||
|
moddedDropdown.Select(0);
|
||||||
|
|
||||||
var filterContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform), isHorizontal: true)
|
var filterContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform), isHorizontal: true)
|
||||||
{
|
{
|
||||||
Stretch = true
|
Stretch = true
|
||||||
@@ -88,6 +97,14 @@ namespace Barotrauma
|
|||||||
searchBox.OnDeselected += (sender, userdata) => { searchTitle.Visible = true; };
|
searchBox.OnDeselected += (sender, userdata) => { searchTitle.Visible = true; };
|
||||||
searchBox.OnTextChanged += (textBox, text) => { FilterSubs(subList, text); return true; };
|
searchBox.OnTextChanged += (textBox, text) => { FilterSubs(subList, text); return true; };
|
||||||
|
|
||||||
|
moddedDropdown.OnSelected = (component, data) =>
|
||||||
|
{
|
||||||
|
searchBox.Text = string.Empty;
|
||||||
|
subFilter = (CategoryFilter)data;
|
||||||
|
UpdateSubList(SubmarineInfo.SavedSubmarines);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
subList.OnSelected = OnSubSelected;
|
subList.OnSelected = OnSubSelected;
|
||||||
}
|
}
|
||||||
else // Spacing to fix the multiplayer campaign setup layout
|
else // Spacing to fix the multiplayer campaign setup layout
|
||||||
@@ -234,7 +251,7 @@ namespace Barotrauma
|
|||||||
Stretch = true
|
Stretch = true
|
||||||
};
|
};
|
||||||
|
|
||||||
var subLabel = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.055f), subHolder.RectTransform) { MinSize = new Point(0, 25) }, TextManager.Language == "English" ? "Purchasable submarines" : TextManager.Get("workshoplabelsubmarines"), font: GUI.SubHeadingFont);
|
var subLabel = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.055f), subHolder.RectTransform) { MinSize = new Point(0, 25) }, TextManager.Get("purchasablesubmarines", fallBackTag: "workshoplabelsubmarines"), font: GUI.SubHeadingFont);
|
||||||
|
|
||||||
var filterContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), subHolder.RectTransform), isHorizontal: true)
|
var filterContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), subHolder.RectTransform), isHorizontal: true)
|
||||||
{
|
{
|
||||||
@@ -395,7 +412,16 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public void UpdateSubList(IEnumerable<SubmarineInfo> submarines)
|
public void UpdateSubList(IEnumerable<SubmarineInfo> submarines)
|
||||||
{
|
{
|
||||||
var subsToShow = submarines.Where(s => s.IsCampaignCompatibleIgnoreClass).ToList();
|
List<SubmarineInfo> subsToShow;
|
||||||
|
if (!isMultiplayer && subFilter != CategoryFilter.All)
|
||||||
|
{
|
||||||
|
subsToShow = submarines.Where(s => s.IsCampaignCompatibleIgnoreClass && s.IsVanillaSubmarine() == (subFilter == CategoryFilter.Vanilla)).ToList();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
subsToShow = submarines.Where(s => s.IsCampaignCompatibleIgnoreClass).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
subsToShow.Sort((s1, s2) =>
|
subsToShow.Sort((s1, s2) =>
|
||||||
{
|
{
|
||||||
int p1 = s1.Price > CampaignMode.MaxInitialSubmarinePrice ? 10 : 0;
|
int p1 = s1.Price > CampaignMode.MaxInitialSubmarinePrice ? 10 : 0;
|
||||||
@@ -428,18 +454,22 @@ namespace Barotrauma
|
|||||||
ToolTip = textBlock.ToolTip
|
ToolTip = textBlock.ToolTip
|
||||||
};
|
};
|
||||||
#if !DEBUG
|
#if !DEBUG
|
||||||
if (sub.Price > CampaignMode.MaxInitialSubmarinePrice && !GameMain.DebugDraw)
|
if (!GameMain.DebugDraw)
|
||||||
{
|
{
|
||||||
textBlock.CanBeFocused = false;
|
if (sub.Price > CampaignMode.MaxInitialSubmarinePrice || !sub.IsCampaignCompatible)
|
||||||
|
{
|
||||||
|
textBlock.CanBeFocused = false;
|
||||||
|
textBlock.TextColor *= 0.5f;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
if (SubmarineInfo.SavedSubmarines.Any())
|
if (SubmarineInfo.SavedSubmarines.Any())
|
||||||
{
|
{
|
||||||
var nonShuttles = subsToShow.Where(s => s.Type == SubmarineType.Player && !s.HasTag(SubmarineTag.Shuttle) && s.Price <= CampaignMode.MaxInitialSubmarinePrice).ToList();
|
var validSubs = subsToShow.Where(s => s.IsCampaignCompatible && s.Price <= CampaignMode.MaxInitialSubmarinePrice).ToList();
|
||||||
if (nonShuttles.Count > 0)
|
if (validSubs.Count > 0)
|
||||||
{
|
{
|
||||||
subList.Select(nonShuttles[Rand.Int(nonShuttles.Count)]);
|
subList.Select(validSubs[Rand.Int(validSubs.Count)]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -448,6 +478,7 @@ namespace Barotrauma
|
|||||||
public void UpdateLoadMenu(IEnumerable<string> saveFiles = null)
|
public void UpdateLoadMenu(IEnumerable<string> saveFiles = null)
|
||||||
{
|
{
|
||||||
prevSaveFiles?.Clear();
|
prevSaveFiles?.Clear();
|
||||||
|
prevSaveFiles = null;
|
||||||
loadGameContainer.ClearChildren();
|
loadGameContainer.ClearChildren();
|
||||||
|
|
||||||
if (saveFiles == null)
|
if (saveFiles == null)
|
||||||
@@ -504,6 +535,7 @@ namespace Barotrauma
|
|||||||
};
|
};
|
||||||
|
|
||||||
bool isCompatible = true;
|
bool isCompatible = true;
|
||||||
|
prevSaveFiles ??= new List<string>();
|
||||||
if (!isMultiplayer)
|
if (!isMultiplayer)
|
||||||
{
|
{
|
||||||
nameText.Text = Path.GetFileNameWithoutExtension(saveFile);
|
nameText.Text = Path.GetFileNameWithoutExtension(saveFile);
|
||||||
@@ -529,10 +561,10 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
prevSaveFiles?.Add(saveFile);
|
||||||
string[] splitSaveFile = saveFile.Split(';');
|
string[] splitSaveFile = saveFile.Split(';');
|
||||||
saveFrame.UserData = splitSaveFile[0];
|
saveFrame.UserData = splitSaveFile[0];
|
||||||
fileName = nameText.Text = Path.GetFileNameWithoutExtension(splitSaveFile[0]);
|
fileName = nameText.Text = Path.GetFileNameWithoutExtension(splitSaveFile[0]);
|
||||||
prevSaveFiles?.Add(fileName);
|
|
||||||
if (splitSaveFile.Length > 1) { subName = splitSaveFile[1]; }
|
if (splitSaveFile.Length > 1) { subName = splitSaveFile[1]; }
|
||||||
if (splitSaveFile.Length > 2) { saveTime = splitSaveFile[2]; }
|
if (splitSaveFile.Length > 2) { saveTime = splitSaveFile[2]; }
|
||||||
if (splitSaveFile.Length > 3) { contentPackageStr = splitSaveFile[3]; }
|
if (splitSaveFile.Length > 3) { contentPackageStr = splitSaveFile[3]; }
|
||||||
@@ -545,7 +577,7 @@ namespace Barotrauma
|
|||||||
if (!string.IsNullOrEmpty(contentPackageStr))
|
if (!string.IsNullOrEmpty(contentPackageStr))
|
||||||
{
|
{
|
||||||
List<string> contentPackagePaths = contentPackageStr.Split('|').ToList();
|
List<string> contentPackagePaths = contentPackageStr.Split('|').ToList();
|
||||||
if (!GameSession.IsCompatibleWithSelectedContentPackages(contentPackagePaths, out string errorMsg))
|
if (!GameSession.IsCompatibleWithEnabledContentPackages(contentPackagePaths, out string errorMsg))
|
||||||
{
|
{
|
||||||
nameText.TextColor = GUI.Style.Red;
|
nameText.TextColor = GUI.Style.Red;
|
||||||
saveFrame.ToolTip = string.Join("\n", errorMsg, TextManager.Get("campaignmode.contentpackagemismatchwarning"));
|
saveFrame.ToolTip = string.Join("\n", errorMsg, TextManager.Get("campaignmode.contentpackagemismatchwarning"));
|
||||||
@@ -696,9 +728,16 @@ namespace Barotrauma
|
|||||||
string saveFile = obj as string;
|
string saveFile = obj as string;
|
||||||
if (obj == null) { return false; }
|
if (obj == null) { return false; }
|
||||||
|
|
||||||
SaveUtil.DeleteSave(saveFile);
|
string header = TextManager.Get("deletedialoglabel");
|
||||||
prevSaveFiles?.Remove(saveFile);
|
string body = TextManager.GetWithVariable("deletedialogquestion", "[file]", Path.GetFileNameWithoutExtension(saveFile));
|
||||||
UpdateLoadMenu(prevSaveFiles);
|
|
||||||
|
EventEditorScreen.AskForConfirmation(header, body, () =>
|
||||||
|
{
|
||||||
|
SaveUtil.DeleteSave(saveFile);
|
||||||
|
prevSaveFiles?.RemoveAll(s => s.StartsWith(saveFile));
|
||||||
|
UpdateLoadMenu(prevSaveFiles.ToList());
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -497,7 +497,7 @@ namespace Barotrauma
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (Level.Loaded != null &&
|
if (Level.Loaded != null &&
|
||||||
connection.LevelData == Level.Loaded.LevelData &&
|
connection?.LevelData == Level.Loaded.LevelData &&
|
||||||
currentDisplayLocation == Campaign.Map?.CurrentLocation)
|
currentDisplayLocation == Campaign.Map?.CurrentLocation)
|
||||||
{
|
{
|
||||||
StartButton.Visible = false;
|
StartButton.Visible = false;
|
||||||
|
|||||||
+11
-6
@@ -1655,9 +1655,9 @@ namespace Barotrauma.CharacterEditor
|
|||||||
if (contentPackage == null)
|
if (contentPackage == null)
|
||||||
{
|
{
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
contentPackage = GameMain.Config.SelectedContentPackages.LastOrDefault();
|
contentPackage = GameMain.Config.AllEnabledPackages.LastOrDefault();
|
||||||
#else
|
#else
|
||||||
contentPackage = GameMain.Config.SelectedContentPackages.LastOrDefault(cp => cp != vanilla);
|
contentPackage = GameMain.Config.AllEnabledPackages.LastOrDefault(cp => cp != vanilla);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
if (contentPackage == null)
|
if (contentPackage == null)
|
||||||
@@ -1674,9 +1674,9 @@ namespace Barotrauma.CharacterEditor
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
// Content package
|
// Content package
|
||||||
if (!GameMain.Config.SelectedContentPackages.Contains(contentPackage))
|
if (!GameMain.Config.AllEnabledPackages.Contains(contentPackage))
|
||||||
{
|
{
|
||||||
GameMain.Config.SelectContentPackage(contentPackage);
|
GameMain.Config.EnableRegularPackage(contentPackage);
|
||||||
}
|
}
|
||||||
GameMain.Config.SaveNewPlayerConfig();
|
GameMain.Config.SaveNewPlayerConfig();
|
||||||
|
|
||||||
@@ -1757,9 +1757,10 @@ namespace Barotrauma.CharacterEditor
|
|||||||
#endif
|
#endif
|
||||||
// Add to the selected content package
|
// Add to the selected content package
|
||||||
contentPackage.AddFile(configFilePath, ContentType.Character);
|
contentPackage.AddFile(configFilePath, ContentType.Character);
|
||||||
|
Barotrauma.IO.Validation.DevException = true;
|
||||||
contentPackage.Save(contentPackage.Path);
|
contentPackage.Save(contentPackage.Path);
|
||||||
DebugConsole.NewMessage(GetCharacterEditorTranslation("ContentPackageSaved").Replace("[path]", contentPackage.Path));
|
Barotrauma.IO.Validation.DevException = false;
|
||||||
CharacterPrefab.LoadFromFile(configFilePath, contentPackage, forceOverride: true);
|
DebugConsole.NewMessage(GetCharacterEditorTranslation("ContentPackageSaved").Replace("[path]", contentPackage.Path));
|
||||||
|
|
||||||
// Ragdoll
|
// Ragdoll
|
||||||
RagdollParams.ClearCache();
|
RagdollParams.ClearCache();
|
||||||
@@ -1783,7 +1784,11 @@ namespace Barotrauma.CharacterEditor
|
|||||||
element.SetAttributeValue("type", name);
|
element.SetAttributeValue("type", name);
|
||||||
string fullPath = AnimationParams.GetDefaultFile(name, animation.AnimationType, contentPackage);
|
string fullPath = AnimationParams.GetDefaultFile(name, animation.AnimationType, contentPackage);
|
||||||
element.Name = AnimationParams.GetDefaultFileName(name, animation.AnimationType);
|
element.Name = AnimationParams.GetDefaultFileName(name, animation.AnimationType);
|
||||||
|
#if DEBUG
|
||||||
element.Save(fullPath);
|
element.Save(fullPath);
|
||||||
|
#else
|
||||||
|
element.SaveSafe(fullPath);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -305,7 +305,7 @@ namespace Barotrauma.CharacterEditor
|
|||||||
new GUITextBlock(new RectTransform(new Vector2(0.3f, 1), mainElement.RectTransform, Anchor.CenterLeft), TextManager.Get("ContentPackage"));
|
new GUITextBlock(new RectTransform(new Vector2(0.3f, 1), mainElement.RectTransform, Anchor.CenterLeft), TextManager.Get("ContentPackage"));
|
||||||
var rightContainer = new GUIFrame(new RectTransform(new Vector2(0.7f, 1), mainElement.RectTransform, Anchor.CenterRight), style: null);
|
var rightContainer = new GUIFrame(new RectTransform(new Vector2(0.7f, 1), mainElement.RectTransform, Anchor.CenterRight), style: null);
|
||||||
contentPackageDropDown = new GUIDropDown(new RectTransform(new Vector2(1.0f, 0.5f), rightContainer.RectTransform, Anchor.TopRight));
|
contentPackageDropDown = new GUIDropDown(new RectTransform(new Vector2(1.0f, 0.5f), rightContainer.RectTransform, Anchor.TopRight));
|
||||||
foreach (ContentPackage cp in ContentPackage.List)
|
foreach (ContentPackage cp in ContentPackage.AllPackages)
|
||||||
{
|
{
|
||||||
#if !DEBUG
|
#if !DEBUG
|
||||||
if (cp == GameMain.VanillaContent) { continue; }
|
if (cp == GameMain.VanillaContent) { continue; }
|
||||||
@@ -334,15 +334,15 @@ namespace Barotrauma.CharacterEditor
|
|||||||
contentPackageNameElement.Flash();
|
contentPackageNameElement.Flash();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (ContentPackage.List.Any(cp => cp.Name.ToLower() == contentPackageNameElement.Text.ToLower()))
|
if (ContentPackage.AllPackages.Any(cp => cp.Name.ToLower() == contentPackageNameElement.Text.ToLower()))
|
||||||
{
|
{
|
||||||
new GUIMessageBox("", TextManager.Get("charactereditor.contentpackagenameinuse", fallBackTag: "leveleditorlevelobjnametaken"));
|
new GUIMessageBox("", TextManager.Get("charactereditor.contentpackagenameinuse", fallBackTag: "leveleditorlevelobjnametaken"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
string modName = ToolBox.RemoveInvalidFileNameChars(contentPackageNameElement.Text);
|
string modName = ToolBox.RemoveInvalidFileNameChars(contentPackageNameElement.Text);
|
||||||
ContentPackage = ContentPackage.CreatePackage(contentPackageNameElement.Text, Path.Combine("Mods", modName, Steam.SteamManager.MetadataFileName), false);
|
ContentPackage = ContentPackage.CreatePackage(contentPackageNameElement.Text, Path.Combine("Mods", modName, Steam.SteamManager.MetadataFileName), false);
|
||||||
ContentPackage.List.Add(ContentPackage);
|
ContentPackage.AddPackage(ContentPackage);
|
||||||
GameMain.Config.SelectContentPackage(ContentPackage);
|
GameMain.Config.EnableRegularPackage(ContentPackage);
|
||||||
contentPackageDropDown.AddItem(ContentPackage.Name, ContentPackage, ContentPackage.Path);
|
contentPackageDropDown.AddItem(ContentPackage.Name, ContentPackage, ContentPackage.Path);
|
||||||
contentPackageDropDown.SelectItem(ContentPackage);
|
contentPackageDropDown.SelectItem(ContentPackage);
|
||||||
contentPackageNameElement.Text = "";
|
contentPackageNameElement.Text = "";
|
||||||
|
|||||||
@@ -32,10 +32,13 @@ namespace Barotrauma
|
|||||||
private EditorNode? draggedNode;
|
private EditorNode? draggedNode;
|
||||||
private Vector2 dragOffset;
|
private Vector2 dragOffset;
|
||||||
|
|
||||||
private Dictionary<EditorNode, Vector2> markedNodes = new Dictionary<EditorNode, Vector2>();
|
private readonly Dictionary<EditorNode, Vector2> markedNodes = new Dictionary<EditorNode, Vector2>();
|
||||||
|
|
||||||
private static string projectName = string.Empty;
|
private static string projectName = string.Empty;
|
||||||
|
|
||||||
|
private OutpostGenerationParams? lastTestParam;
|
||||||
|
private LocationType? lastTestType;
|
||||||
|
|
||||||
private int CreateID()
|
private int CreateID()
|
||||||
{
|
{
|
||||||
int maxId = nodeList.Any() ? nodeList.Max(node => node.ID) : 0;
|
int maxId = nodeList.Any() ? nodeList.Max(node => node.ID) : 0;
|
||||||
@@ -292,6 +295,8 @@ namespace Barotrauma
|
|||||||
string filePath = System.IO.Path.Combine(directory, $"{projectName}.sevproj");
|
string filePath = System.IO.Path.Combine(directory, $"{projectName}.sevproj");
|
||||||
File.WriteAllText(Path.Combine(directory, $"{projectName}.sevproj"), save.ToString());
|
File.WriteAllText(Path.Combine(directory, $"{projectName}.sevproj"), save.ToString());
|
||||||
GUI.AddMessage($"Project saved to {filePath}", GUI.Style.Green);
|
GUI.AddMessage($"Project saved to {filePath}", GUI.Style.Green);
|
||||||
|
|
||||||
|
AskForConfirmation(TextManager.Get("EventEditor.TestPromptHeader"), TextManager.Get("EventEditor.TestPromptBody"), CreateTestSetupMenu);
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
return true;
|
return true;
|
||||||
@@ -520,15 +525,12 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public override void Select()
|
public override void Select()
|
||||||
{
|
{
|
||||||
Cam.Position = Vector2.Zero;
|
|
||||||
nodeList.Clear();
|
|
||||||
projectName = TextManager.Get("EventEditor.Unnamed");
|
projectName = TextManager.Get("EventEditor.Unnamed");
|
||||||
base.Select();
|
base.Select();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Deselect()
|
public override void Deselect()
|
||||||
{
|
{
|
||||||
nodeList.Clear();
|
|
||||||
base.Deselect();
|
base.Deselect();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -597,9 +599,9 @@ namespace Barotrauma
|
|||||||
optionElement.Add(new XAttribute("text", text));
|
optionElement.Add(new XAttribute("text", text));
|
||||||
if (end) { optionElement.Add(new XAttribute("endconversation", true)); }
|
if (end) { optionElement.Add(new XAttribute("endconversation", true)); }
|
||||||
|
|
||||||
if (node != null)
|
if (node is EventNode eventNode)
|
||||||
{
|
{
|
||||||
ExportChildNodes((EventNode) node, optionElement);
|
ExportChildNodes(eventNode, optionElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
newElement.Add(optionElement);
|
newElement.Add(optionElement);
|
||||||
@@ -748,6 +750,57 @@ namespace Barotrauma
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool CreateTestSetupMenu()
|
||||||
|
{
|
||||||
|
var msgBox = new GUIMessageBox(TextManager.Get("EventEditor.TestPromptHeader"), "", new[] { TextManager.Get("Cancel"), TextManager.Get("OK") },
|
||||||
|
relativeSize: new Vector2(0.2f, 0.3f), minSize: new Point(300, 175));
|
||||||
|
|
||||||
|
var layout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.5f), msgBox.Content.RectTransform));
|
||||||
|
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(1, 0.25f), layout.RectTransform), TextManager.Get("EventEditor.OutpostGenParams"), font: GUI.SubHeadingFont);
|
||||||
|
GUIDropDown paramInput = new GUIDropDown(new RectTransform(new Vector2(1, 0.25f), layout.RectTransform), string.Empty, OutpostGenerationParams.Params.Count);
|
||||||
|
foreach (OutpostGenerationParams param in OutpostGenerationParams.Params)
|
||||||
|
{
|
||||||
|
paramInput.AddItem(param.Identifier, param);
|
||||||
|
}
|
||||||
|
paramInput.OnSelected = (_, param) =>
|
||||||
|
{
|
||||||
|
lastTestParam = param as OutpostGenerationParams;
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
paramInput.SelectItem(lastTestParam ?? OutpostGenerationParams.Params.FirstOrDefault());
|
||||||
|
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(1, 0.25f), layout.RectTransform), TextManager.Get("EventEditor.LocationType"), font: GUI.SubHeadingFont);
|
||||||
|
GUIDropDown typeInput = new GUIDropDown(new RectTransform(new Vector2(1, 0.25f), layout.RectTransform), string.Empty, LocationType.List.Count);
|
||||||
|
foreach (LocationType type in LocationType.List)
|
||||||
|
{
|
||||||
|
typeInput.AddItem(type.Identifier, type);
|
||||||
|
}
|
||||||
|
typeInput.OnSelected = (_, type) =>
|
||||||
|
{
|
||||||
|
lastTestType = type as LocationType;
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
typeInput.SelectItem(lastTestType ?? LocationType.List.FirstOrDefault());
|
||||||
|
|
||||||
|
// Cancel button
|
||||||
|
msgBox.Buttons[0].OnClicked = (button, o) =>
|
||||||
|
{
|
||||||
|
msgBox.Close();
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Ok button
|
||||||
|
msgBox.Buttons[1].OnClicked = (button, o) =>
|
||||||
|
{
|
||||||
|
TestEvent(lastTestParam, lastTestType);
|
||||||
|
msgBox.Close();
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private static void CreateEditMenu(ValueNode? node, NodeConnection? connection = null)
|
private static void CreateEditMenu(ValueNode? node, NodeConnection? connection = null)
|
||||||
{
|
{
|
||||||
@@ -860,6 +913,40 @@ namespace Barotrauma
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool TestEvent(OutpostGenerationParams? param, LocationType? type)
|
||||||
|
{
|
||||||
|
SubmarineInfo subInfo = SubmarineInfo.SavedSubmarines.FirstOrDefault(info => info.HasTag(SubmarineTag.Shuttle));
|
||||||
|
|
||||||
|
XElement? eventXml = ExportXML();
|
||||||
|
EventPrefab? prefab;
|
||||||
|
if (eventXml != null)
|
||||||
|
{
|
||||||
|
prefab = new EventPrefab(eventXml);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GUI.AddMessage("Unable to open test enviroment because the event contains errors.", GUI.Style.Red);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
GameSession gameSession = new GameSession(subInfo, "", GameModePreset.TestMode, null);
|
||||||
|
TestGameMode gameMode = (TestGameMode) gameSession.GameMode;
|
||||||
|
|
||||||
|
gameMode.SpawnOutpost = true;
|
||||||
|
gameMode.OutpostParams = param;
|
||||||
|
gameMode.OutpostType = type;
|
||||||
|
gameMode.TriggeredEvent = prefab;
|
||||||
|
gameMode.OnRoundEnd = () =>
|
||||||
|
{
|
||||||
|
Submarine.Unload();
|
||||||
|
GameMain.EventEditorScreen.Select();
|
||||||
|
};
|
||||||
|
|
||||||
|
GameMain.GameScreen.Select();
|
||||||
|
gameSession.StartRound(null, false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public override void Draw(double deltaTime, GraphicsDevice graphics, SpriteBatch spriteBatch)
|
public override void Draw(double deltaTime, GraphicsDevice graphics, SpriteBatch spriteBatch)
|
||||||
{
|
{
|
||||||
DrawnTooltip = string.Empty;
|
DrawnTooltip = string.Empty;
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private Effect damageEffect;
|
private Effect damageEffect;
|
||||||
private Texture2D damageStencil;
|
private Texture2D damageStencil;
|
||||||
private Texture2D distortTexture;
|
private Texture2D distortTexture;
|
||||||
|
|
||||||
private float fadeToBlackState;
|
private float fadeToBlackState;
|
||||||
|
|
||||||
@@ -171,6 +171,7 @@ namespace Barotrauma
|
|||||||
//These will be visible through the LOS effect.
|
//These will be visible through the LOS effect.
|
||||||
spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.NonPremultiplied, null, DepthStencilState.None, null, null, cam.Transform);
|
spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.NonPremultiplied, null, DepthStencilState.None, null, null, cam.Transform);
|
||||||
Submarine.DrawBack(spriteBatch, false, e => e is Structure s && (e.SpriteDepth >= 0.9f || s.Prefab.BackgroundSprite != null));
|
Submarine.DrawBack(spriteBatch, false, e => e is Structure s && (e.SpriteDepth >= 0.9f || s.Prefab.BackgroundSprite != null));
|
||||||
|
Submarine.DrawPaintedColors(spriteBatch, false);
|
||||||
spriteBatch.End();
|
spriteBatch.End();
|
||||||
|
|
||||||
graphics.SetRenderTarget(null);
|
graphics.SetRenderTarget(null);
|
||||||
|
|||||||
@@ -274,9 +274,9 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
//TODO: hacky workaround to check for wrecks and outposts, refactor SubmarineInfo and ContentType at some point
|
//TODO: hacky workaround to check for wrecks and outposts, refactor SubmarineInfo and ContentType at some point
|
||||||
var nonPlayerFiles = ContentPackage.GetFilesOfType(GameMain.Config.SelectedContentPackages, ContentType.Wreck).ToList();
|
var nonPlayerFiles = ContentPackage.GetFilesOfType(GameMain.Config.AllEnabledPackages, ContentType.Wreck).ToList();
|
||||||
nonPlayerFiles.AddRange(ContentPackage.GetFilesOfType(GameMain.Config.SelectedContentPackages, ContentType.Outpost));
|
nonPlayerFiles.AddRange(ContentPackage.GetFilesOfType(GameMain.Config.AllEnabledPackages, ContentType.Outpost));
|
||||||
nonPlayerFiles.AddRange(ContentPackage.GetFilesOfType(GameMain.Config.SelectedContentPackages, ContentType.OutpostModule));
|
nonPlayerFiles.AddRange(ContentPackage.GetFilesOfType(GameMain.Config.AllEnabledPackages, ContentType.OutpostModule));
|
||||||
SubmarineInfo subInfo = SubmarineInfo.SavedSubmarines.FirstOrDefault(s => s.Name.Equals(GameMain.Config.QuickStartSubmarineName, StringComparison.InvariantCultureIgnoreCase));
|
SubmarineInfo subInfo = SubmarineInfo.SavedSubmarines.FirstOrDefault(s => s.Name.Equals(GameMain.Config.QuickStartSubmarineName, StringComparison.InvariantCultureIgnoreCase));
|
||||||
subInfo ??= SubmarineInfo.SavedSubmarines.GetRandom(s =>
|
subInfo ??= SubmarineInfo.SavedSubmarines.GetRandom(s =>
|
||||||
s.IsPlayer && !s.HasTag(SubmarineTag.Shuttle) &&
|
s.IsPlayer && !s.HasTag(SubmarineTag.Shuttle) &&
|
||||||
|
|||||||
@@ -41,7 +41,6 @@ namespace Barotrauma
|
|||||||
private Tab selectedTab;
|
private Tab selectedTab;
|
||||||
|
|
||||||
private Sprite backgroundSprite;
|
private Sprite backgroundSprite;
|
||||||
private Sprite backgroundVignette;
|
|
||||||
|
|
||||||
private readonly GUIComponent titleText;
|
private readonly GUIComponent titleText;
|
||||||
|
|
||||||
@@ -65,8 +64,6 @@ namespace Barotrauma
|
|||||||
CreateCampaignSetupUI();
|
CreateCampaignSetupUI();
|
||||||
};
|
};
|
||||||
|
|
||||||
backgroundVignette = new Sprite("Content/UI/MainMenuVignette.png", Vector2.Zero);
|
|
||||||
|
|
||||||
new GUIImage(new RectTransform(new Vector2(0.4f, 0.25f), Frame.RectTransform, Anchor.BottomRight)
|
new GUIImage(new RectTransform(new Vector2(0.4f, 0.25f), Frame.RectTransform, Anchor.BottomRight)
|
||||||
{ RelativeOffset = new Vector2(0.08f, 0.05f), AbsoluteOffset = new Point(-8, -8) },
|
{ RelativeOffset = new Vector2(0.08f, 0.05f), AbsoluteOffset = new Point(-8, -8) },
|
||||||
style: "TitleText")
|
style: "TitleText")
|
||||||
@@ -863,7 +860,7 @@ namespace Barotrauma
|
|||||||
GameMain.NetLobbyScreen = new NetLobbyScreen();
|
GameMain.NetLobbyScreen = new NetLobbyScreen();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
string exeName = ContentPackage.GetFilesOfType(GameMain.Config.SelectedContentPackages, ContentType.ServerExecutable)?.FirstOrDefault()?.Path;
|
string exeName = ContentPackage.GetFilesOfType(GameMain.Config.AllEnabledPackages, ContentType.ServerExecutable)?.FirstOrDefault()?.Path;
|
||||||
if (string.IsNullOrEmpty(exeName))
|
if (string.IsNullOrEmpty(exeName))
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError("No server executable defined in the selected content packages. Attempting to use the default executable...");
|
DebugConsole.ThrowError("No server executable defined in the selected content packages. Attempting to use the default executable...");
|
||||||
@@ -947,14 +944,11 @@ namespace Barotrauma
|
|||||||
#if USE_STEAM
|
#if USE_STEAM
|
||||||
if (GameMain.Config.UseSteamMatchmaking)
|
if (GameMain.Config.UseSteamMatchmaking)
|
||||||
{
|
{
|
||||||
joinServerButton.Enabled = Steam.SteamManager.IsInitialized;
|
hostServerButton.Enabled = Steam.SteamManager.IsInitialized;
|
||||||
hostServerButton.Enabled = Steam.SteamManager.IsInitialized;
|
|
||||||
}
|
}
|
||||||
steamWorkshopButton.Enabled = Steam.SteamManager.IsInitialized;
|
steamWorkshopButton.Enabled = Steam.SteamManager.IsInitialized;
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
joinServerButton.Enabled = true;
|
|
||||||
hostServerButton.Enabled = true;
|
|
||||||
#if USE_STEAM
|
#if USE_STEAM
|
||||||
steamWorkshopButton.Enabled = true;
|
steamWorkshopButton.Enabled = true;
|
||||||
#endif
|
#endif
|
||||||
@@ -976,10 +970,14 @@ namespace Barotrauma
|
|||||||
aberrationStrength: 0.0f);
|
aberrationStrength: 0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
spriteBatch.Begin(blendState: BlendState.NonPremultiplied);
|
var vignette = GUI.Style.GetComponentStyle("mainmenuvignette")?.GetDefaultSprite();
|
||||||
backgroundVignette.Draw(spriteBatch, Vector2.Zero, Color.White, Vector2.Zero, 0.0f,
|
if (vignette != null)
|
||||||
new Vector2(GameMain.GraphicsWidth / backgroundVignette.size.X, GameMain.GraphicsHeight / backgroundVignette.size.Y));
|
{
|
||||||
spriteBatch.End();
|
spriteBatch.Begin(blendState: BlendState.NonPremultiplied);
|
||||||
|
vignette.Draw(spriteBatch, Vector2.Zero, Color.White, Vector2.Zero, 0.0f,
|
||||||
|
new Vector2(GameMain.GraphicsWidth / vignette.size.X, GameMain.GraphicsHeight / vignette.size.Y));
|
||||||
|
spriteBatch.End();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly string[] legalCrap = new string[]
|
readonly string[] legalCrap = new string[]
|
||||||
|
|||||||
@@ -15,20 +15,20 @@ namespace Barotrauma
|
|||||||
private readonly List<Sprite> characterSprites = new List<Sprite>();
|
private readonly List<Sprite> characterSprites = new List<Sprite>();
|
||||||
//private readonly List<Sprite> jobPreferenceSprites = new List<Sprite>();
|
//private readonly List<Sprite> jobPreferenceSprites = new List<Sprite>();
|
||||||
|
|
||||||
private GUIFrame infoFrame, modeFrame;
|
private readonly GUIFrame infoFrame, modeFrame;
|
||||||
private GUILayoutGroup infoFrameContent;
|
private readonly GUILayoutGroup infoFrameContent;
|
||||||
private GUIFrame myCharacterFrame;
|
private readonly GUIFrame myCharacterFrame;
|
||||||
|
|
||||||
private GUIListBox subList, modeList;
|
private readonly GUIListBox subList, modeList;
|
||||||
|
|
||||||
private GUIListBox chatBox, playerList;
|
private readonly GUIListBox chatBox, playerList;
|
||||||
private GUIButton serverLogReverseButton;
|
private readonly GUIButton serverLogReverseButton;
|
||||||
private GUIListBox serverLogBox, serverLogFilterTicks;
|
private readonly GUIListBox serverLogBox, serverLogFilterTicks;
|
||||||
|
|
||||||
private GUIComponent jobVariantTooltip;
|
private GUIComponent jobVariantTooltip;
|
||||||
|
|
||||||
private GUITextBox chatInput;
|
private readonly GUITextBox chatInput;
|
||||||
private GUITextBox serverLogFilter;
|
private readonly GUITextBox serverLogFilter;
|
||||||
public GUITextBox ChatInput
|
public GUITextBox ChatInput
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@@ -82,10 +82,10 @@ namespace Barotrauma
|
|||||||
private readonly GUITickBox autoRestartBox;
|
private readonly GUITickBox autoRestartBox;
|
||||||
private readonly GUITextBlock autoRestartText;
|
private readonly GUITextBlock autoRestartText;
|
||||||
|
|
||||||
private GUIDropDown shuttleList;
|
private readonly GUIDropDown shuttleList;
|
||||||
private GUITickBox shuttleTickBox;
|
private readonly GUITickBox shuttleTickBox;
|
||||||
|
|
||||||
private GUIComponent settingsBlocker;
|
private readonly GUIComponent settingsBlocker;
|
||||||
|
|
||||||
private Sprite backgroundSprite;
|
private Sprite backgroundSprite;
|
||||||
|
|
||||||
@@ -123,15 +123,6 @@ namespace Barotrauma
|
|||||||
public GUIProgressBar FileTransferProgressBar { get; private set; }
|
public GUIProgressBar FileTransferProgressBar { get; private set; }
|
||||||
public GUITextBlock FileTransferProgressText { get; private set; }
|
public GUITextBlock FileTransferProgressText { get; private set; }
|
||||||
|
|
||||||
private bool AllowSubSelection
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return GameMain.NetworkMember.ServerSettings.Voting.AllowSubVoting ||
|
|
||||||
(GameMain.Client != null && GameMain.Client.HasPermission(ClientPermissions.SelectSub));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public GUITextBox ServerName
|
public GUITextBox ServerName
|
||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
@@ -150,8 +141,8 @@ namespace Barotrauma
|
|||||||
private set;
|
private set;
|
||||||
}
|
}
|
||||||
|
|
||||||
private GUIButton showChatButton;
|
private readonly GUIButton showChatButton;
|
||||||
private GUIButton showLogButton;
|
private readonly GUIButton showLogButton;
|
||||||
|
|
||||||
public GUIListBox SubList
|
public GUIListBox SubList
|
||||||
{
|
{
|
||||||
@@ -268,9 +259,7 @@ namespace Barotrauma
|
|||||||
foreach (MissionType type in Enum.GetValues(typeof(MissionType)))
|
foreach (MissionType type in Enum.GetValues(typeof(MissionType)))
|
||||||
{
|
{
|
||||||
if (type == MissionType.None || type == MissionType.All) { continue; }
|
if (type == MissionType.None || type == MissionType.All) { continue; }
|
||||||
|
missionTypeTickBoxes[index].Selected = ((int)type & (int)value) != 0;
|
||||||
missionTypeTickBoxes[index].Selected = (((int)type & (int)value) != 0);
|
|
||||||
|
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -290,8 +279,7 @@ namespace Barotrauma
|
|||||||
List<Pair<JobPrefab, int>> jobPreferences = new List<Pair<JobPrefab, int>>();
|
List<Pair<JobPrefab, int>> jobPreferences = new List<Pair<JobPrefab, int>>();
|
||||||
foreach (GUIComponent child in JobList.Content.Children)
|
foreach (GUIComponent child in JobList.Content.Children)
|
||||||
{
|
{
|
||||||
var jobPrefab = child.UserData as Pair<JobPrefab, int>;
|
if (!(child.UserData is Pair<JobPrefab, int> jobPrefab)) { continue; }
|
||||||
if (jobPrefab == null) { continue; }
|
|
||||||
jobPreferences.Add(jobPrefab);
|
jobPreferences.Add(jobPrefab);
|
||||||
}
|
}
|
||||||
return jobPreferences;
|
return jobPreferences;
|
||||||
@@ -743,7 +731,7 @@ namespace Barotrauma
|
|||||||
foreach (GUIComponent child in subList.Content.Children)
|
foreach (GUIComponent child in subList.Content.Children)
|
||||||
{
|
{
|
||||||
if (!(child.UserData is SubmarineInfo sub)) { continue; }
|
if (!(child.UserData is SubmarineInfo sub)) { continue; }
|
||||||
child.Visible = string.IsNullOrEmpty(text) ? true : sub.DisplayName.ToLower().Contains(text.ToLower());
|
child.Visible = string.IsNullOrEmpty(text) || sub.DisplayName.ToLower().Contains(text.ToLower());
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
@@ -887,7 +875,12 @@ namespace Barotrauma
|
|||||||
ContinueCampaignButton = new GUIButton(new RectTransform(new Vector2(1.0f, 0.3f), campaignContent.RectTransform),
|
ContinueCampaignButton = new GUIButton(new RectTransform(new Vector2(1.0f, 0.3f), campaignContent.RectTransform),
|
||||||
TextManager.Get("campaigncontinue"), textAlignment: Alignment.Center)
|
TextManager.Get("campaigncontinue"), textAlignment: Alignment.Center)
|
||||||
{
|
{
|
||||||
OnClicked = (_, __) => { GameMain.Client?.RequestStartRound(true); return true; }
|
OnClicked = (_, __) =>
|
||||||
|
{
|
||||||
|
CoroutineManager.StartCoroutine(WaitForStartRound(ContinueCampaignButton), "WaitForStartRound");
|
||||||
|
GameMain.Client?.RequestStartRound(true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
QuitCampaignButton = new GUIButton(new RectTransform(new Vector2(1.0f, 0.3f), campaignContent.RectTransform),
|
QuitCampaignButton = new GUIButton(new RectTransform(new Vector2(1.0f, 0.3f), campaignContent.RectTransform),
|
||||||
TextManager.Get("pausemenusavequit"), textAlignment: Alignment.Center)
|
TextManager.Get("pausemenusavequit"), textAlignment: Alignment.Center)
|
||||||
@@ -1356,6 +1349,7 @@ namespace Barotrauma
|
|||||||
if (GameMain.Client == null) { return; }
|
if (GameMain.Client == null) { return; }
|
||||||
string newName = Client.SanitizeName(tb.Text);
|
string newName = Client.SanitizeName(tb.Text);
|
||||||
newName = newName.Replace(":", "").Replace(";", "");
|
newName = newName.Replace(":", "").Replace(";", "");
|
||||||
|
if (newName == GameMain.Client.Name) return;
|
||||||
if (string.IsNullOrWhiteSpace(newName))
|
if (string.IsNullOrWhiteSpace(newName))
|
||||||
{
|
{
|
||||||
tb.Text = GameMain.Client.Name;
|
tb.Text = GameMain.Client.Name;
|
||||||
@@ -1365,6 +1359,8 @@ namespace Barotrauma
|
|||||||
if (isGameRunning)
|
if (isGameRunning)
|
||||||
{
|
{
|
||||||
GameMain.Client.PendingName = tb.Text;
|
GameMain.Client.PendingName = tb.Text;
|
||||||
|
TabMenu.PendingChanges = true;
|
||||||
|
CreateChangesPendingText();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1603,13 +1599,13 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private void AddSubmarine(GUIComponent subList, SubmarineInfo sub)
|
private void AddSubmarine(GUIComponent subList, SubmarineInfo sub)
|
||||||
{
|
{
|
||||||
if (subList is GUIListBox)
|
if (subList is GUIListBox listBox)
|
||||||
{
|
{
|
||||||
subList = ((GUIListBox)subList).Content;
|
subList = listBox.Content;
|
||||||
}
|
}
|
||||||
else if (subList is GUIDropDown)
|
else if (subList is GUIDropDown dropDown)
|
||||||
{
|
{
|
||||||
subList = ((GUIDropDown)subList).ListBox.Content;
|
subList = dropDown.ListBox.Content;
|
||||||
}
|
}
|
||||||
|
|
||||||
var frame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.1f), subList.RectTransform) { MinSize = new Point(0, 20) },
|
var frame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.1f), subList.RectTransform) { MinSize = new Point(0, 20) },
|
||||||
@@ -1655,7 +1651,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (sub.HasTag(SubmarineTag.Shuttle))
|
if (sub.HasTag(SubmarineTag.Shuttle))
|
||||||
{
|
{
|
||||||
var shuttleText = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), frame.RectTransform, Anchor.CenterRight),
|
var shuttleText = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), frame.RectTransform, Anchor.CenterRight) { AbsoluteOffset = new Point(GUI.IntScale(20), 0) },
|
||||||
TextManager.Get("Shuttle", fallBackTag: "RespawnShuttle"), textAlignment: Alignment.CenterRight, font: GUI.SmallFont)
|
TextManager.Get("Shuttle", fallBackTag: "RespawnShuttle"), textAlignment: Alignment.CenterRight, font: GUI.SmallFont)
|
||||||
{
|
{
|
||||||
TextColor = subTextBlock.TextColor * 0.8f,
|
TextColor = subTextBlock.TextColor * 0.8f,
|
||||||
@@ -1665,16 +1661,16 @@ namespace Barotrauma
|
|||||||
//make shuttles more dim in the sub list (selecting a shuttle as the main sub is allowed but not recommended)
|
//make shuttles more dim in the sub list (selecting a shuttle as the main sub is allowed but not recommended)
|
||||||
if (subList == this.subList.Content)
|
if (subList == this.subList.Content)
|
||||||
{
|
{
|
||||||
subTextBlock.TextColor *= 0.5f;
|
subTextBlock.TextColor *= 0.8f;
|
||||||
foreach (GUIComponent child in frame.Children)
|
foreach (GUIComponent child in frame.Children)
|
||||||
{
|
{
|
||||||
child.Color *= 0.5f;
|
child.Color *= 0.8f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var classText = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), frame.RectTransform, Anchor.CenterRight),
|
var classText = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), frame.RectTransform, Anchor.CenterRight) { AbsoluteOffset = new Point(GUI.IntScale(20), 0) },
|
||||||
TextManager.Get($"submarineclass.{sub.SubmarineClass}"), textAlignment: Alignment.CenterRight, font: GUI.SmallFont)
|
TextManager.Get($"submarineclass.{sub.SubmarineClass}"), textAlignment: Alignment.CenterRight, font: GUI.SmallFont)
|
||||||
{
|
{
|
||||||
UserData = "classtext",
|
UserData = "classtext",
|
||||||
@@ -1816,20 +1812,20 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public void SetPlayerNameAndJobPreference(Client client)
|
public void SetPlayerNameAndJobPreference(Client client)
|
||||||
{
|
{
|
||||||
var PlayerFrame = (GUITextBlock)PlayerList.Content.FindChild(client);
|
var playerFrame = (GUITextBlock)PlayerList.Content.FindChild(client);
|
||||||
if (PlayerFrame == null) { return; }
|
if (playerFrame == null) { return; }
|
||||||
PlayerFrame.Text = client.Name;
|
playerFrame.Text = client.Name;
|
||||||
|
|
||||||
Color color = Color.White;
|
Color color = Color.White;
|
||||||
if (JobPrefab.Prefabs.ContainsKey(client.PreferredJob))
|
if (JobPrefab.Prefabs.ContainsKey(client.PreferredJob))
|
||||||
{
|
{
|
||||||
color = JobPrefab.Prefabs[client.PreferredJob].UIColor;
|
color = JobPrefab.Prefabs[client.PreferredJob].UIColor;
|
||||||
}
|
}
|
||||||
PlayerFrame.Color = color * 0.4f;
|
playerFrame.Color = color * 0.4f;
|
||||||
PlayerFrame.HoverColor = color * 0.6f;
|
playerFrame.HoverColor = color * 0.6f;
|
||||||
PlayerFrame.SelectedColor = color * 0.8f;
|
playerFrame.SelectedColor = color * 0.8f;
|
||||||
PlayerFrame.OutlineColor = color * 0.5f;
|
playerFrame.OutlineColor = color * 0.5f;
|
||||||
PlayerFrame.TextColor = color;
|
playerFrame.TextColor = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetPlayerVoiceIconState(Client client, bool muted, bool mutedLocally)
|
public void SetPlayerVoiceIconState(Client client, bool muted, bool mutedLocally)
|
||||||
@@ -2671,7 +2667,7 @@ namespace Barotrauma
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool SwitchJob(GUIButton button, object obj)
|
private bool SwitchJob(GUIButton _, object obj)
|
||||||
{
|
{
|
||||||
if (JobList == null) { return false; }
|
if (JobList == null) { return false; }
|
||||||
|
|
||||||
@@ -2724,7 +2720,7 @@ namespace Barotrauma
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool OpenJobSelection(GUIComponent child, object userData)
|
private bool OpenJobSelection(GUIComponent _, object __)
|
||||||
{
|
{
|
||||||
if (JobSelectionFrame != null)
|
if (JobSelectionFrame != null)
|
||||||
{
|
{
|
||||||
@@ -2870,7 +2866,9 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
Color = Color.Black,
|
Color = Color.Black,
|
||||||
HoverColor = Color.Black,
|
HoverColor = Color.Black,
|
||||||
SelectedColor = Color.Black
|
PressedColor = Color.Black,
|
||||||
|
SelectedColor = Color.Black,
|
||||||
|
CanBeFocused = false
|
||||||
};
|
};
|
||||||
|
|
||||||
var textBlock = new GUITextBlock(
|
var textBlock = new GUITextBlock(
|
||||||
@@ -2883,6 +2881,7 @@ namespace Barotrauma
|
|||||||
HoverColor = Color.Transparent,
|
HoverColor = Color.Transparent,
|
||||||
SelectedColor = Color.Transparent,
|
SelectedColor = Color.Transparent,
|
||||||
TextColor = jobPrefab.UIColor,
|
TextColor = jobPrefab.UIColor,
|
||||||
|
HoverTextColor = Color.Lerp(jobPrefab.UIColor, Color.White, 0.5f),
|
||||||
CanBeFocused = false,
|
CanBeFocused = false,
|
||||||
AutoScaleHorizontal = true
|
AutoScaleHorizontal = true
|
||||||
};
|
};
|
||||||
@@ -2938,7 +2937,7 @@ namespace Barotrauma
|
|||||||
info.Head = new CharacterInfo.HeadInfo(info.HeadSpriteId, info.Gender, info.Race, info.HairIndex, info.BeardIndex, index, info.FaceAttachmentIndex);
|
info.Head = new CharacterInfo.HeadInfo(info.HeadSpriteId, info.Gender, info.Race, info.HairIndex, info.BeardIndex, index, info.FaceAttachmentIndex);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
DebugConsole.ThrowError($"Wearable type not implemented: {type.ToString()}");
|
DebugConsole.ThrowError($"Wearable type not implemented: {type}");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
info.ReloadHeadAttachments();
|
info.ReloadHeadAttachments();
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private RectTransform prevGuiElementParent;
|
private RectTransform prevGuiElementParent;
|
||||||
|
|
||||||
|
public Exception LoadException;
|
||||||
|
|
||||||
public static RoundSummaryScreen Select(Sprite backgroundSprite, RoundSummary roundSummary)
|
public static RoundSummaryScreen Select(Sprite backgroundSprite, RoundSummary roundSummary)
|
||||||
{
|
{
|
||||||
var summaryScreen = new RoundSummaryScreen()
|
var summaryScreen = new RoundSummaryScreen()
|
||||||
@@ -51,5 +53,16 @@ namespace Barotrauma
|
|||||||
|
|
||||||
spriteBatch.End();
|
spriteBatch.End();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void Update(double deltaTime)
|
||||||
|
{
|
||||||
|
base.Update(deltaTime);
|
||||||
|
if (LoadException != null)
|
||||||
|
{
|
||||||
|
var temp = LoadException;
|
||||||
|
LoadException = null;
|
||||||
|
throw temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Barotrauma.Extensions;
|
using Barotrauma.Extensions;
|
||||||
|
using Barotrauma.IO;
|
||||||
using Barotrauma.Networking;
|
using Barotrauma.Networking;
|
||||||
using Barotrauma.Steam;
|
using Barotrauma.Steam;
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
@@ -6,13 +7,10 @@ using Microsoft.Xna.Framework.Graphics;
|
|||||||
using RestSharp;
|
using RestSharp;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Barotrauma.IO;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.NetworkInformation;
|
using System.Net.NetworkInformation;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
|
|
||||||
@@ -21,7 +19,7 @@ namespace Barotrauma
|
|||||||
class ServerListScreen : Screen
|
class ServerListScreen : Screen
|
||||||
{
|
{
|
||||||
//how often the client is allowed to refresh servers
|
//how often the client is allowed to refresh servers
|
||||||
private TimeSpan AllowedRefreshInterval = new TimeSpan(0, 0, 3);
|
private readonly TimeSpan AllowedRefreshInterval = new TimeSpan(0, 0, 3);
|
||||||
|
|
||||||
private GUIFrame menu;
|
private GUIFrame menu;
|
||||||
|
|
||||||
@@ -31,12 +29,20 @@ namespace Barotrauma
|
|||||||
private GUIButton joinButton;
|
private GUIButton joinButton;
|
||||||
private ServerInfo selectedServer;
|
private ServerInfo selectedServer;
|
||||||
|
|
||||||
|
private GUIButton scanServersButton;
|
||||||
|
|
||||||
//friends list
|
//friends list
|
||||||
private GUILayoutGroup friendsButtonHolder;
|
private GUILayoutGroup friendsButtonHolder;
|
||||||
|
|
||||||
private GUIButton friendsDropdownButton;
|
private GUIButton friendsDropdownButton;
|
||||||
private GUIListBox friendsDropdown;
|
private GUIListBox friendsDropdown;
|
||||||
|
|
||||||
|
//Workshop downloads
|
||||||
|
private GUIFrame workshopDownloadsFrame = null;
|
||||||
|
private Steamworks.Ugc.Item? currentlyDownloadingWorkshopItem = null;
|
||||||
|
private Dictionary<ulong, Steamworks.Ugc.Item?> pendingWorkshopDownloads = null;
|
||||||
|
private string autoConnectName; private string autoConnectEndpoint;
|
||||||
|
|
||||||
private class FriendInfo
|
private class FriendInfo
|
||||||
{
|
{
|
||||||
public UInt64 SteamID;
|
public UInt64 SteamID;
|
||||||
@@ -558,7 +564,7 @@ namespace Barotrauma
|
|||||||
OnClicked = GameMain.MainMenuScreen.ReturnToMainMenu
|
OnClicked = GameMain.MainMenuScreen.ReturnToMainMenu
|
||||||
};
|
};
|
||||||
|
|
||||||
new GUIButton(new RectTransform(new Vector2(0.25f, 0.9f), buttonContainer.RectTransform),
|
scanServersButton = new GUIButton(new RectTransform(new Vector2(0.25f, 0.9f), buttonContainer.RectTransform),
|
||||||
TextManager.Get("ServerListRefresh"))
|
TextManager.Get("ServerListRefresh"))
|
||||||
{
|
{
|
||||||
OnClicked = (btn, userdata) => { RefreshServers(); return true; }
|
OnClicked = (btn, userdata) => { RefreshServers(); return true; }
|
||||||
@@ -761,7 +767,7 @@ namespace Barotrauma
|
|||||||
info.GameStarted = Screen.Selected != GameMain.NetLobbyScreen;
|
info.GameStarted = Screen.Selected != GameMain.NetLobbyScreen;
|
||||||
info.GameVersion = GameMain.Version.ToString();
|
info.GameVersion = GameMain.Version.ToString();
|
||||||
info.MaxPlayers = serverSettings.MaxPlayers;
|
info.MaxPlayers = serverSettings.MaxPlayers;
|
||||||
info.PlayStyle = PlayStyle.SomethingDifferent;
|
info.PlayStyle = serverSettings.PlayStyle;
|
||||||
info.RespondedToSteamQuery = true;
|
info.RespondedToSteamQuery = true;
|
||||||
info.UsingWhiteList = serverSettings.Whitelist.Enabled;
|
info.UsingWhiteList = serverSettings.Whitelist.Enabled;
|
||||||
info.TraitorsEnabled = serverSettings.TraitorsEnabled;
|
info.TraitorsEnabled = serverSettings.TraitorsEnabled;
|
||||||
@@ -892,11 +898,11 @@ namespace Barotrauma
|
|||||||
case "ServerListCompatible":
|
case "ServerListCompatible":
|
||||||
bool? s1Compatible = NetworkMember.IsCompatible(GameMain.Version.ToString(), s1.GameVersion);
|
bool? s1Compatible = NetworkMember.IsCompatible(GameMain.Version.ToString(), s1.GameVersion);
|
||||||
if (!s1.ContentPackageHashes.Any()) { s1Compatible = null; }
|
if (!s1.ContentPackageHashes.Any()) { s1Compatible = null; }
|
||||||
if (s1Compatible.HasValue) { s1Compatible = s1Compatible.Value && s1.ContentPackagesMatch(GameMain.SelectedPackages); };
|
if (s1Compatible.HasValue) { s1Compatible = s1Compatible.Value && s1.ContentPackagesMatch(); };
|
||||||
|
|
||||||
bool? s2Compatible = NetworkMember.IsCompatible(GameMain.Version.ToString(), s2.GameVersion);
|
bool? s2Compatible = NetworkMember.IsCompatible(GameMain.Version.ToString(), s2.GameVersion);
|
||||||
if (!s2.ContentPackageHashes.Any()) { s2Compatible = null; }
|
if (!s2.ContentPackageHashes.Any()) { s2Compatible = null; }
|
||||||
if (s2Compatible.HasValue) { s2Compatible = s2Compatible.Value && s2.ContentPackagesMatch(GameMain.SelectedPackages); };
|
if (s2Compatible.HasValue) { s2Compatible = s2Compatible.Value && s2.ContentPackagesMatch(); };
|
||||||
|
|
||||||
//convert to int to make sorting easier
|
//convert to int to make sorting easier
|
||||||
//1 Compatible
|
//1 Compatible
|
||||||
@@ -946,6 +952,9 @@ namespace Barotrauma
|
|||||||
public override void Deselect()
|
public override void Deselect()
|
||||||
{
|
{
|
||||||
base.Deselect();
|
base.Deselect();
|
||||||
|
|
||||||
|
pendingWorkshopDownloads?.Clear();
|
||||||
|
workshopDownloadsFrame = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Update(double deltaTime)
|
public override void Update(double deltaTime)
|
||||||
@@ -965,6 +974,43 @@ namespace Barotrauma
|
|||||||
friendsDropdown.Visible = false;
|
friendsDropdown.Visible = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (currentlyDownloadingWorkshopItem?.IsInstalled ?? true)
|
||||||
|
{
|
||||||
|
if (pendingWorkshopDownloads?.Any() ?? false)
|
||||||
|
{
|
||||||
|
Steamworks.Ugc.Item? item = pendingWorkshopDownloads.Values.FirstOrDefault(it => it != null);
|
||||||
|
if (item != null)
|
||||||
|
{
|
||||||
|
ulong itemId = item.Value.Id;
|
||||||
|
currentlyDownloadingWorkshopItem = item;
|
||||||
|
SteamManager.SubscribeToWorkshopItem(itemId, () =>
|
||||||
|
{
|
||||||
|
pendingWorkshopDownloads.Remove(itemId);
|
||||||
|
|
||||||
|
if (SteamManager.CheckWorkshopItemInstalled(item))
|
||||||
|
{
|
||||||
|
SteamManager.UninstallWorkshopItem(item, false, out _);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SteamManager.InstallWorkshopItem(item, out string errorMsg, enableContentPackage: false, suppressInstallNotif: true))
|
||||||
|
{
|
||||||
|
workshopDownloadsFrame?.FindChild((c) => c.UserData is ulong l && l == itemId, true)?.Flash(GUI.Style.Green);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
workshopDownloadsFrame?.FindChild((c) => c.UserData is ulong l && l == itemId, true)?.Flash(GUI.Style.Red);
|
||||||
|
DebugConsole.ThrowError(errorMsg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!string.IsNullOrEmpty(autoConnectEndpoint))
|
||||||
|
{
|
||||||
|
JoinServer(autoConnectEndpoint, autoConnectName);
|
||||||
|
autoConnectEndpoint = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void FilterServers()
|
private void FilterServers()
|
||||||
@@ -992,7 +1038,7 @@ namespace Barotrauma
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
bool incompatible =
|
bool incompatible =
|
||||||
(!serverInfo.ContentPackageHashes.Any() && serverInfo.ContentPackagesMatch(GameMain.Config.SelectedContentPackages)) ||
|
(!serverInfo.ContentPackageHashes.Any() && serverInfo.ContentPackagesMatch()) ||
|
||||||
(remoteVersion != null && !NetworkMember.IsCompatible(GameMain.Version, remoteVersion));
|
(remoteVersion != null && !NetworkMember.IsCompatible(GameMain.Version, remoteVersion));
|
||||||
|
|
||||||
child.Visible =
|
child.Visible =
|
||||||
@@ -1018,7 +1064,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
var playStyle = (PlayStyle)tickBox.UserData;
|
var playStyle = (PlayStyle)tickBox.UserData;
|
||||||
|
|
||||||
if (!tickBox.Selected && serverInfo.PlayStyle == playStyle)
|
if (!tickBox.Selected && (serverInfo.PlayStyle == playStyle || !serverInfo.PlayStyle.HasValue))
|
||||||
{
|
{
|
||||||
child.Visible = false;
|
child.Visible = false;
|
||||||
break;
|
break;
|
||||||
@@ -1136,7 +1182,7 @@ namespace Barotrauma
|
|||||||
Port = port.ToString(),
|
Port = port.ToString(),
|
||||||
QueryPort = NetConfig.DefaultQueryPort.ToString(),
|
QueryPort = NetConfig.DefaultQueryPort.ToString(),
|
||||||
GameVersion = GameMain.Version.ToString(),
|
GameVersion = GameMain.Version.ToString(),
|
||||||
PlayStyle = PlayStyle.Serious
|
PlayStyle = null
|
||||||
};
|
};
|
||||||
|
|
||||||
var serverFrame = serverList.Content.FindChild(d => (d.UserData is ServerInfo info) &&
|
var serverFrame = serverList.Content.FindChild(d => (d.UserData is ServerInfo info) &&
|
||||||
@@ -1546,6 +1592,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
CanBeFocused = false
|
CanBeFocused = false
|
||||||
};
|
};
|
||||||
|
scanServersButton.Enabled = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1555,6 +1602,7 @@ namespace Barotrauma
|
|||||||
AddToServerList(info);
|
AddToServerList(info);
|
||||||
QueueInfoQuery(info);
|
QueueInfoQuery(info);
|
||||||
}
|
}
|
||||||
|
scanServersButton.Enabled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1712,7 +1760,7 @@ namespace Barotrauma
|
|||||||
CanBeFocused = false,
|
CanBeFocused = false,
|
||||||
Selected =
|
Selected =
|
||||||
(NetworkMember.IsCompatible(GameMain.Version.ToString(), serverInfo.GameVersion) ?? true) &&
|
(NetworkMember.IsCompatible(GameMain.Version.ToString(), serverInfo.GameVersion) ?? true) &&
|
||||||
serverInfo.ContentPackagesMatch(GameMain.SelectedPackages),
|
serverInfo.ContentPackagesMatch(),
|
||||||
UserData = "compatible"
|
UserData = "compatible"
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1818,19 +1866,43 @@ namespace Barotrauma
|
|||||||
|
|
||||||
for (int i = 0; i < serverInfo.ContentPackageNames.Count; i++)
|
for (int i = 0; i < serverInfo.ContentPackageNames.Count; i++)
|
||||||
{
|
{
|
||||||
if (!GameMain.SelectedPackages.Any(cp => cp.MD5hash.Hash == serverInfo.ContentPackageHashes[i]))
|
bool listAsIncompatible = false;
|
||||||
|
if (serverInfo.ContentPackageWorkshopIds[i] == 0)
|
||||||
|
{
|
||||||
|
listAsIncompatible = !GameMain.Config.AllEnabledPackages.Any(cp => cp.MD5hash.Hash == serverInfo.ContentPackageHashes[i]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
listAsIncompatible = GameMain.Config.AllEnabledPackages.Any(cp => cp.MD5hash.Hash != serverInfo.ContentPackageHashes[i] &&
|
||||||
|
cp.SteamWorkshopId == serverInfo.ContentPackageWorkshopIds[i]);
|
||||||
|
}
|
||||||
|
if (listAsIncompatible)
|
||||||
{
|
{
|
||||||
if (toolTip != "") toolTip += "\n";
|
if (toolTip != "") toolTip += "\n";
|
||||||
toolTip += TextManager.GetWithVariables("ServerListIncompatibleContentPackage", new string[2] { "[contentpackage]", "[hash]" },
|
toolTip += TextManager.GetWithVariables("ServerListIncompatibleContentPackage", new string[2] { "[contentpackage]", "[hash]" },
|
||||||
new string[2] { serverInfo.ContentPackageNames[i], Md5Hash.GetShortHash(serverInfo.ContentPackageHashes[i]) });
|
new string[2] { serverInfo.ContentPackageNames[i], Md5Hash.GetShortHash(serverInfo.ContentPackageHashes[i]) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
serverContent.Children.ForEach(c => c.ToolTip = toolTip);
|
serverContent.Children.ForEach(c => c.ToolTip = toolTip);
|
||||||
|
|
||||||
serverName.TextColor *= 0.5f;
|
serverName.TextColor *= 0.5f;
|
||||||
serverPlayers.TextColor *= 0.5f;
|
serverPlayers.TextColor *= 0.5f;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string toolTip = "";
|
||||||
|
for (int i = 0; i < serverInfo.ContentPackageNames.Count; i++)
|
||||||
|
{
|
||||||
|
if (!GameMain.Config.AllEnabledPackages.Any(cp => cp.MD5hash.Hash == serverInfo.ContentPackageHashes[i]))
|
||||||
|
{
|
||||||
|
if (toolTip != "") toolTip += "\n";
|
||||||
|
toolTip += TextManager.GetWithVariable("ServerListIncompatibleContentPackageWorkshopAvailable", "[contentpackage]", serverInfo.ContentPackageNames[i]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
serverContent.Children.ForEach(c => c.ToolTip = toolTip);
|
||||||
|
}
|
||||||
|
|
||||||
serverContent.Recalculate();
|
serverContent.Recalculate();
|
||||||
|
|
||||||
@@ -1921,17 +1993,17 @@ namespace Barotrauma
|
|||||||
serverList.ClearChildren();
|
serverList.ClearChildren();
|
||||||
new GUIMessageBox(TextManager.Get("MasterServerErrorLabel"), TextManager.GetWithVariable("MasterServerErrorException", "[error]", masterServerResponse.ErrorException.ToString()));
|
new GUIMessageBox(TextManager.Get("MasterServerErrorLabel"), TextManager.GetWithVariable("MasterServerErrorException", "[error]", masterServerResponse.ErrorException.ToString()));
|
||||||
}
|
}
|
||||||
else if (masterServerResponse.StatusCode != System.Net.HttpStatusCode.OK)
|
else if (masterServerResponse.StatusCode != HttpStatusCode.OK)
|
||||||
{
|
{
|
||||||
serverList.ClearChildren();
|
serverList.ClearChildren();
|
||||||
|
|
||||||
switch (masterServerResponse.StatusCode)
|
switch (masterServerResponse.StatusCode)
|
||||||
{
|
{
|
||||||
case System.Net.HttpStatusCode.NotFound:
|
case HttpStatusCode.NotFound:
|
||||||
new GUIMessageBox(TextManager.Get("MasterServerErrorLabel"),
|
new GUIMessageBox(TextManager.Get("MasterServerErrorLabel"),
|
||||||
TextManager.GetWithVariable("MasterServerError404", "[masterserverurl]", NetConfig.MasterServerUrl));
|
TextManager.GetWithVariable("MasterServerError404", "[masterserverurl]", NetConfig.MasterServerUrl));
|
||||||
break;
|
break;
|
||||||
case System.Net.HttpStatusCode.ServiceUnavailable:
|
case HttpStatusCode.ServiceUnavailable:
|
||||||
new GUIMessageBox(TextManager.Get("MasterServerErrorLabel"),
|
new GUIMessageBox(TextManager.Get("MasterServerErrorLabel"),
|
||||||
TextManager.Get("MasterServerErrorUnavailable"));
|
TextManager.Get("MasterServerErrorUnavailable"));
|
||||||
break;
|
break;
|
||||||
@@ -1958,6 +2030,79 @@ namespace Barotrauma
|
|||||||
masterServerResponded = true;
|
masterServerResponded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void DownloadWorkshopItems(IEnumerable<ulong> ids, string serverName, string endPointString)
|
||||||
|
{
|
||||||
|
if (workshopDownloadsFrame != null) { return; }
|
||||||
|
int rowCount = ids.Count() + 2;
|
||||||
|
|
||||||
|
autoConnectName = serverName; autoConnectEndpoint = endPointString;
|
||||||
|
|
||||||
|
workshopDownloadsFrame = new GUIFrame(new RectTransform(Vector2.One, GUI.Canvas), null, Color.Black * 0.5f);
|
||||||
|
pendingWorkshopDownloads = new Dictionary<ulong, Steamworks.Ugc.Item?>();
|
||||||
|
|
||||||
|
var innerFrame = new GUIFrame(new RectTransform(new Vector2(0.5f, 0.1f + 0.03f * rowCount), workshopDownloadsFrame.RectTransform, Anchor.Center, Pivot.Center));
|
||||||
|
var innerLayout = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, (float)rowCount / (float)(rowCount + 3)), innerFrame.RectTransform, Anchor.Center, Pivot.Center));
|
||||||
|
|
||||||
|
foreach (ulong id in ids)
|
||||||
|
{
|
||||||
|
pendingWorkshopDownloads.Add(id, null);
|
||||||
|
|
||||||
|
var itemLayout = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f / rowCount), innerLayout.RectTransform), true, Anchor.CenterLeft)
|
||||||
|
{
|
||||||
|
UserData = id
|
||||||
|
};
|
||||||
|
TaskPool.Add("RetrieveWorkshopItemData", Steamworks.SteamUGC.QueryFileAsync(id), (t) =>
|
||||||
|
{
|
||||||
|
if (t.IsFaulted)
|
||||||
|
{
|
||||||
|
TaskPool.PrintTaskExceptions(t, $"Failed to retrieve Workshop item info (ID {id})");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Steamworks.Ugc.Item? item = ((Task<Steamworks.Ugc.Item?>)t).Result;
|
||||||
|
|
||||||
|
if (!item.HasValue)
|
||||||
|
{
|
||||||
|
DebugConsole.ThrowError($"Failed to find a Steam Workshop item with the ID {id}.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pendingWorkshopDownloads.ContainsKey(id))
|
||||||
|
{
|
||||||
|
pendingWorkshopDownloads[id] = item;
|
||||||
|
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(0.4f, 0.67f), itemLayout.RectTransform, Anchor.CenterLeft, Pivot.CenterLeft), item.Value.Title);
|
||||||
|
|
||||||
|
new GUIProgressBar(new RectTransform(new Vector2(0.6f, 0.67f), itemLayout.RectTransform, Anchor.CenterLeft, Pivot.CenterLeft), 0f, Color.Lime)
|
||||||
|
{
|
||||||
|
ProgressGetter = () =>
|
||||||
|
{
|
||||||
|
if (item.Value.IsInstalled) { return 1.0f; }
|
||||||
|
else if (!item.Value.IsDownloading) { return 0.0f; }
|
||||||
|
return item.Value.DownloadAmount;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var buttonLayout = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 2.0f / rowCount), innerLayout.RectTransform), true, Anchor.CenterLeft)
|
||||||
|
{
|
||||||
|
UserData = "buttons"
|
||||||
|
};
|
||||||
|
|
||||||
|
new GUIButton(new RectTransform(new Vector2(0.3f, 0.67f), buttonLayout.RectTransform, Anchor.CenterLeft, Pivot.CenterLeft), TextManager.Get("Cancel"))
|
||||||
|
{
|
||||||
|
OnClicked = (btn, obj) =>
|
||||||
|
{
|
||||||
|
autoConnectEndpoint = null;
|
||||||
|
autoConnectName = null;
|
||||||
|
pendingWorkshopDownloads.Clear();
|
||||||
|
workshopDownloadsFrame = null;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
private bool JoinServer(string endpoint, string serverName)
|
private bool JoinServer(string endpoint, string serverName)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(ClientNameBox.Text))
|
if (string.IsNullOrWhiteSpace(ClientNameBox.Text))
|
||||||
@@ -2113,6 +2258,8 @@ namespace Barotrauma
|
|||||||
friendPopup?.AddToGUIUpdateList();
|
friendPopup?.AddToGUIUpdateList();
|
||||||
|
|
||||||
friendsDropdown?.AddToGUIUpdateList();
|
friendsDropdown?.AddToGUIUpdateList();
|
||||||
|
|
||||||
|
workshopDownloadsFrame?.AddToGUIUpdateList();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -325,7 +325,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
loadedSprites.ForEach(s => s.Remove());
|
loadedSprites.ForEach(s => s.Remove());
|
||||||
loadedSprites.Clear();
|
loadedSprites.Clear();
|
||||||
var contentPackages = GameMain.Config.SelectedContentPackages.ToList();
|
var contentPackages = GameMain.Config.AllEnabledPackages.ToList();
|
||||||
|
|
||||||
#if !DEBUG
|
#if !DEBUG
|
||||||
var vanilla = GameMain.VanillaContent;
|
var vanilla = GameMain.VanillaContent;
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
using Barotrauma.Steam;
|
using Barotrauma.IO;
|
||||||
|
using Barotrauma.Steam;
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
using RestSharp;
|
using RestSharp;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Barotrauma.IO;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
@@ -44,7 +43,7 @@ namespace Barotrauma
|
|||||||
public int PendingLoads = 1;
|
public int PendingLoads = 1;
|
||||||
}
|
}
|
||||||
private readonly Dictionary<ulong, PendingPreviewImageDownload> pendingPreviewImageDownloads = new Dictionary<ulong, PendingPreviewImageDownload>();
|
private readonly Dictionary<ulong, PendingPreviewImageDownload> pendingPreviewImageDownloads = new Dictionary<ulong, PendingPreviewImageDownload>();
|
||||||
private Dictionary<string, Sprite> itemPreviewSprites = new Dictionary<string, Sprite>();
|
private readonly Dictionary<string, Sprite> itemPreviewSprites = new Dictionary<string, Sprite>();
|
||||||
|
|
||||||
private enum Tab
|
private enum Tab
|
||||||
{
|
{
|
||||||
@@ -237,7 +236,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
SelectTab(Tab.Mods);
|
SelectTab(Tab.Mods);
|
||||||
|
|
||||||
subscribedCoroutine = CoroutineManager.StartCoroutine(PollSubscribedItems());
|
CoroutineManager.StartCoroutine(PollSubscribedItems());
|
||||||
}
|
}
|
||||||
|
|
||||||
private GUITextBox CreateFilterBox(GUIComponent parent, GUIListBox listbox)
|
private GUITextBox CreateFilterBox(GUIComponent parent, GUIListBox listbox)
|
||||||
@@ -283,7 +282,7 @@ namespace Barotrauma
|
|||||||
RefreshSubscribedItems();
|
RefreshSubscribedItems();
|
||||||
}
|
}
|
||||||
|
|
||||||
CoroutineHandle subscribedCoroutine;
|
float subscribePollAdditionalWait = 0.0f;
|
||||||
|
|
||||||
private IEnumerable<object> PollSubscribedItems()
|
private IEnumerable<object> PollSubscribedItems()
|
||||||
{
|
{
|
||||||
@@ -293,6 +292,13 @@ namespace Barotrauma
|
|||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
while (CoroutineManager.IsCoroutineRunning("Load")) { yield return new WaitForSeconds(1.0f); }
|
while (CoroutineManager.IsCoroutineRunning("Load")) { yield return new WaitForSeconds(1.0f); }
|
||||||
|
while (subscribePollAdditionalWait > 0.01f)
|
||||||
|
{
|
||||||
|
subscribePollAdditionalWait = Math.Min(subscribePollAdditionalWait, 3.0f);
|
||||||
|
float wait = subscribePollAdditionalWait;
|
||||||
|
yield return new WaitForSeconds(wait);
|
||||||
|
subscribePollAdditionalWait -= wait;
|
||||||
|
}
|
||||||
uint newNumSubscribed = Steamworks.SteamUGC.NumSubscribedItems;
|
uint newNumSubscribed = Steamworks.SteamUGC.NumSubscribedItems;
|
||||||
if (newNumSubscribed != numSubscribed)
|
if (newNumSubscribed != numSubscribed)
|
||||||
{
|
{
|
||||||
@@ -338,15 +344,6 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SubscribeToPackages(List<string> packageUrls)
|
|
||||||
{
|
|
||||||
foreach (string url in packageUrls)
|
|
||||||
{
|
|
||||||
SteamManager.SubscribeToWorkshopItem(url);
|
|
||||||
}
|
|
||||||
GameMain.SteamWorkshopScreen.Select();
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerable<object> RefreshDownloadState()
|
public IEnumerable<object> RefreshDownloadState()
|
||||||
{
|
{
|
||||||
bool isDownloading = true;
|
bool isDownloading = true;
|
||||||
@@ -420,14 +417,14 @@ namespace Barotrauma
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
//ignore subs that are part of a workshop content package
|
//ignore subs that are part of a workshop content package
|
||||||
if (ContentPackage.List.Any(cp => !string.IsNullOrEmpty(cp.SteamWorkshopUrl) &&
|
if (ContentPackage.AllPackages.Any(cp => cp.SteamWorkshopId != 0 &&
|
||||||
cp.Files.Any(f => f.Type == ContentType.Submarine && Path.GetFullPath(f.Path) == subPath)))
|
cp.Files.Any(f => f.Type == ContentType.Submarine && Path.GetFullPath(f.Path) == subPath)))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
//ignore subs that are defined in a content package with more files than just the sub
|
//ignore subs that are defined in a content package with more files than just the sub
|
||||||
//(these will be listed in the "content packages" section)
|
//(these will be listed in the "content packages" section)
|
||||||
if (ContentPackage.List.Any(cp => cp.Files.Count > 1 &&
|
if (ContentPackage.AllPackages.Any(cp => cp.Files.Count > 1 &&
|
||||||
cp.Files.Any(f => f.Type == ContentType.Submarine && Path.GetFullPath(f.Path) == subPath)))
|
cp.Files.Any(f => f.Type == ContentType.Submarine && Path.GetFullPath(f.Path) == subPath)))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
@@ -441,9 +438,9 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
CanBeFocused = false
|
CanBeFocused = false
|
||||||
};
|
};
|
||||||
foreach (ContentPackage contentPackage in ContentPackage.List)
|
foreach (ContentPackage contentPackage in ContentPackage.AllPackages)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(contentPackage.SteamWorkshopUrl) || contentPackage.HideInWorkshopMenu) { continue; }
|
if (contentPackage.SteamWorkshopId != 0 || contentPackage.HideInWorkshopMenu) { continue; }
|
||||||
if (contentPackage == GameMain.VanillaContent) { continue; }
|
if (contentPackage == GameMain.VanillaContent) { continue; }
|
||||||
//don't list content packages that only define one sub (they're visible in the "Submarines" section)
|
//don't list content packages that only define one sub (they're visible in the "Submarines" section)
|
||||||
if (contentPackage.Files.Count == 1 && contentPackage.Files[0].Type == ContentType.Submarine) { continue; }
|
if (contentPackage.Files.Count == 1 && contentPackage.Files[0].Type == ContentType.Submarine) { continue; }
|
||||||
@@ -488,7 +485,7 @@ namespace Barotrauma
|
|||||||
text = topItemFilter.Text;
|
text = topItemFilter.Text;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool visible = string.IsNullOrEmpty(text) ? true : (item?.Title?.ToLower().Contains(text.ToLower()) ?? false);
|
bool visible = string.IsNullOrEmpty(text) || (item?.Title?.ToLower().Contains(text.ToLower()) ?? false);
|
||||||
|
|
||||||
int prevIndex = -1;
|
int prevIndex = -1;
|
||||||
var existingFrame = listBox.Content.FindChild((component) => { return (component.UserData is Steamworks.Ugc.Item?) && (component.UserData as Steamworks.Ugc.Item?)?.Id == item?.Id; });
|
var existingFrame = listBox.Content.FindChild((component) => { return (component.UserData is Steamworks.Ugc.Item?) && (component.UserData as Steamworks.Ugc.Item?)?.Id == item?.Id; });
|
||||||
@@ -611,7 +608,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if ((item?.IsSubscribed ?? false) && (item?.IsInstalled ?? false) && Directory.Exists(item?.Directory))
|
if ((item?.IsSubscribed ?? false) && (item?.IsInstalled ?? false) && Directory.Exists(item?.Directory))
|
||||||
{
|
{
|
||||||
bool installed = SteamManager.CheckWorkshopItemEnabled(item);
|
bool installed = SteamManager.CheckWorkshopItemInstalled(item);
|
||||||
|
|
||||||
if (!installed)
|
if (!installed)
|
||||||
{
|
{
|
||||||
@@ -626,7 +623,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
installed = SteamManager.EnableWorkShopItem(item, out string errorMsg, Selected == this);
|
installed = SteamManager.InstallWorkshopItem(item, out string errorMsg, Selected == this);
|
||||||
if (!installed)
|
if (!installed)
|
||||||
{
|
{
|
||||||
DebugConsole.NewMessage(errorMsg, Color.Red);
|
DebugConsole.NewMessage(errorMsg, Color.Red);
|
||||||
@@ -660,7 +657,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.5f), rightColumn.RectTransform), TextManager.Get("WorkshopItemDownloadPending"));
|
new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.5f), rightColumn.RectTransform), TextManager.Get("WorkshopItemDownloadPending"));
|
||||||
}
|
}
|
||||||
else if (!(item?.IsSubscribed ?? false))
|
else if (!(item?.IsSubscribed ?? false) && (listBox != subscribedItemList))
|
||||||
{
|
{
|
||||||
var downloadBtn = new GUIButton(new RectTransform(new Point((int)(32 * GUI.Scale)), rightColumn.RectTransform), "", style: "GUIPlusButton")
|
var downloadBtn = new GUIButton(new RectTransform(new Point((int)(32 * GUI.Scale)), rightColumn.RectTransform), "", style: "GUIPlusButton")
|
||||||
{
|
{
|
||||||
@@ -684,9 +681,9 @@ namespace Barotrauma
|
|||||||
var elem = subscribedItemList.Content.GetChildByUserData(item);
|
var elem = subscribedItemList.Content.GetChildByUserData(item);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
bool reselect = GameMain.Config.SelectedContentPackages.Any(cp => !string.IsNullOrWhiteSpace(cp.SteamWorkshopUrl) && cp.SteamWorkshopUrl == item?.Url);
|
bool reselect = GameMain.Config.AllEnabledPackages.Any(cp => cp.SteamWorkshopId != 0 && cp.SteamWorkshopId == item?.Id);
|
||||||
if (!SteamManager.DisableWorkShopItem(item, false, out string errorMsg) ||
|
if (!SteamManager.UninstallWorkshopItem(item, false, out string errorMsg) ||
|
||||||
!SteamManager.EnableWorkShopItem(item, out errorMsg, reselect, true))
|
!SteamManager.InstallWorkshopItem(item, out errorMsg, reselect, true))
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError($"Failed to reinstall \"{item?.Title}\": {errorMsg}", null, true);
|
DebugConsole.ThrowError($"Failed to reinstall \"{item?.Title}\": {errorMsg}", null, true);
|
||||||
elem.Flash(GUI.Style.Red);
|
elem.Flash(GUI.Style.Red);
|
||||||
@@ -707,8 +704,9 @@ namespace Barotrauma
|
|||||||
};
|
};
|
||||||
unsubBtn.OnClicked = (btn, userdata) =>
|
unsubBtn.OnClicked = (btn, userdata) =>
|
||||||
{
|
{
|
||||||
SteamManager.DisableWorkShopItem(item, true, out _);
|
subscribePollAdditionalWait += 1.0f;
|
||||||
item?.Unsubscribe();
|
item?.Unsubscribe();
|
||||||
|
SteamManager.UninstallWorkshopItem(item, true, out _);
|
||||||
subscribedItemList.RemoveChild(subscribedItemList.Content.GetChildByUserData(item));
|
subscribedItemList.RemoveChild(subscribedItemList.Content.GetChildByUserData(item));
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
@@ -819,31 +817,34 @@ namespace Barotrauma
|
|||||||
new Tuple<Steamworks.Ugc.Item?, GUIListBox>(item, listBox),
|
new Tuple<Steamworks.Ugc.Item?, GUIListBox>(item, listBox),
|
||||||
(task, tuple) =>
|
(task, tuple) =>
|
||||||
{
|
{
|
||||||
(var it, var lb) = tuple;
|
//must be done in the main thread because creating/removing GUI elements is not thread-safe
|
||||||
var previewImage = lb.Content.FindChild(item)?.GetChildByUserData("previewimage") as GUIImage;
|
CrossThread.RequestExecutionOnMainThread(() =>
|
||||||
if (previewImage != null)
|
|
||||||
{
|
{
|
||||||
previewImage.Sprite = ((Task<Sprite>)task).Result;
|
(var it, var lb) = tuple;
|
||||||
}
|
if (lb.Content.FindChild(item)?.GetChildByUserData("previewimage") is GUIImage previewImage)
|
||||||
else
|
{
|
||||||
{
|
previewImage.Sprite = ((Task<Sprite>)task).Result;
|
||||||
CreateWorkshopItemFrame(it, lb);
|
}
|
||||||
}
|
else
|
||||||
|
{
|
||||||
|
CreateWorkshopItemFrame(it, lb);
|
||||||
|
}
|
||||||
|
|
||||||
if (modsPreviewFrame.FindChild(it) != null)
|
if (modsPreviewFrame.FindChild(it) != null)
|
||||||
{
|
{
|
||||||
ShowItemPreview(it, modsPreviewFrame);
|
ShowItemPreview(it, modsPreviewFrame);
|
||||||
}
|
}
|
||||||
if (browsePreviewFrame.FindChild(item) != null)
|
if (browsePreviewFrame.FindChild(item) != null)
|
||||||
{
|
{
|
||||||
ShowItemPreview(it, browsePreviewFrame);
|
ShowItemPreview(it, browsePreviewFrame);
|
||||||
}
|
}
|
||||||
|
|
||||||
lock (pendingPreviewImageDownloads)
|
lock (pendingPreviewImageDownloads)
|
||||||
{
|
{
|
||||||
pendingPreviewImageDownloads[it.Value.Id].PendingLoads--;
|
pendingPreviewImageDownloads[it.Value.Id].PendingLoads--;
|
||||||
if (pendingPreviewImageDownloads[it.Value.Id].PendingLoads <= 0) { pendingPreviewImageDownloads.Remove(it.Value.Id); }
|
if (pendingPreviewImageDownloads[it.Value.Id].PendingLoads <= 0) { pendingPreviewImageDownloads.Remove(it.Value.Id); }
|
||||||
}
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -872,15 +873,13 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (item == null) { return false; }
|
if (item == null) { return false; }
|
||||||
|
|
||||||
if (!(item?.IsSubscribed ?? false)) { item?.Subscribe(); }
|
|
||||||
|
|
||||||
var parentElement = downloadButton.Parent;
|
var parentElement = downloadButton.Parent;
|
||||||
parentElement.RemoveChild(downloadButton);
|
parentElement.RemoveChild(downloadButton);
|
||||||
var textBlock = new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.5f), parentElement.RectTransform), TextManager.Get("WorkshopItemDownloading"));
|
var textBlock = new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.5f), parentElement.RectTransform), TextManager.Get("WorkshopItemDownloading"));
|
||||||
|
|
||||||
item?.Download(onInstalled: () =>
|
SteamManager.SubscribeToWorkshopItem(item.Value.Id, () =>
|
||||||
{
|
{
|
||||||
if (SteamManager.EnableWorkShopItem(item, out _))
|
if (SteamManager.InstallWorkshopItem(item, out _))
|
||||||
{
|
{
|
||||||
textBlock.Text = TextManager.Get("workshopiteminstalled");
|
textBlock.Text = TextManager.Get("workshopiteminstalled");
|
||||||
frame.Flash(GUI.Style.Green);
|
frame.Flash(GUI.Style.Green);
|
||||||
@@ -1022,8 +1021,9 @@ namespace Barotrauma
|
|||||||
UserData = item,
|
UserData = item,
|
||||||
OnClicked = (btn, userdata) =>
|
OnClicked = (btn, userdata) =>
|
||||||
{
|
{
|
||||||
SteamManager.DisableWorkShopItem(item, true, out _);
|
subscribePollAdditionalWait += 1.0f;
|
||||||
item?.Unsubscribe();
|
item?.Unsubscribe();
|
||||||
|
SteamManager.UninstallWorkshopItem(item, true, out _);
|
||||||
subscribedItemList.RemoveChild(subscribedItemList.Content.GetChildByUserData(item));
|
subscribedItemList.RemoveChild(subscribedItemList.Content.GetChildByUserData(item));
|
||||||
itemPreviewFrame.ClearChildren();
|
itemPreviewFrame.ClearChildren();
|
||||||
return true;
|
return true;
|
||||||
@@ -1294,7 +1294,7 @@ namespace Barotrauma
|
|||||||
new GUITickBox(new RectTransform(new Vector2(1.0f, 0.1f), topLeftColumn.RectTransform), TextManager.Get("WorkshopItemCorePackage"))
|
new GUITickBox(new RectTransform(new Vector2(1.0f, 0.1f), topLeftColumn.RectTransform), TextManager.Get("WorkshopItemCorePackage"))
|
||||||
{
|
{
|
||||||
ToolTip = TextManager.Get("WorkshopItemCorePackageTooltip"),
|
ToolTip = TextManager.Get("WorkshopItemCorePackageTooltip"),
|
||||||
Selected = itemContentPackage.CorePackage,
|
Selected = itemContentPackage.IsCorePackage,
|
||||||
OnSelected = (tickbox) =>
|
OnSelected = (tickbox) =>
|
||||||
{
|
{
|
||||||
if (tickbox.Selected)
|
if (tickbox.Selected)
|
||||||
@@ -1309,12 +1309,12 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
itemContentPackage.CorePackage = tickbox.Selected;
|
itemContentPackage.IsCorePackage = tickbox.Selected;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
itemContentPackage.CorePackage = false;
|
itemContentPackage.IsCorePackage = false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1478,7 +1478,7 @@ namespace Barotrauma
|
|||||||
SelectTab(Tab.Browse);
|
SelectTab(Tab.Browse);
|
||||||
deleteVerification.Close();
|
deleteVerification.Close();
|
||||||
createItemFrame.ClearChildren();
|
createItemFrame.ClearChildren();
|
||||||
itemContentPackage.SteamWorkshopUrl = "";
|
itemContentPackage.SteamWorkshopId = 0;
|
||||||
itemContentPackage.Save(itemContentPackage.Path);
|
itemContentPackage.Save(itemContentPackage.Path);
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
@@ -1535,9 +1535,17 @@ namespace Barotrauma
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filePath != previewImagePath)
|
if (Path.GetFullPath(filePath) != previewImagePath)
|
||||||
{
|
{
|
||||||
File.Copy(filePath, previewImagePath, overwrite: true);
|
try
|
||||||
|
{
|
||||||
|
File.Copy(filePath, previewImagePath, overwrite: true);
|
||||||
|
}
|
||||||
|
catch (System.IO.IOException e)
|
||||||
|
{
|
||||||
|
DebugConsole.ThrowError("Failed to copy the preview image \"{previewImagePath}\" to the mod folder.", e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (itemPreviewSprites.ContainsKey(previewImagePath))
|
if (itemPreviewSprites.ContainsKey(previewImagePath))
|
||||||
@@ -1560,13 +1568,12 @@ namespace Barotrauma
|
|||||||
|
|
||||||
string modFolder = Path.GetDirectoryName(itemContentPackage.Path);
|
string modFolder = Path.GetDirectoryName(itemContentPackage.Path);
|
||||||
string filePathRelativeToModFolder = UpdaterUtil.GetRelativePath(file, Path.Combine(Environment.CurrentDirectory, modFolder));
|
string filePathRelativeToModFolder = UpdaterUtil.GetRelativePath(file, Path.Combine(Environment.CurrentDirectory, modFolder));
|
||||||
string destinationPath;
|
|
||||||
|
|
||||||
//file is not inside the mod folder, we need to move it
|
//file is not inside the mod folder, we need to move it
|
||||||
if (filePathRelativeToModFolder.StartsWith("..") ||
|
if (filePathRelativeToModFolder.StartsWith("..") ||
|
||||||
Path.GetPathRoot(Environment.CurrentDirectory) != Path.GetPathRoot(file))
|
Path.GetPathRoot(Environment.CurrentDirectory) != Path.GetPathRoot(file))
|
||||||
{
|
{
|
||||||
destinationPath = Path.Combine(modFolder, Path.GetFileName(file));
|
string destinationPath = Path.Combine(modFolder, Path.GetFileName(file));
|
||||||
//add a number to the filename if a file with the same name already exists
|
//add a number to the filename if a file with the same name already exists
|
||||||
i = 2;
|
i = 2;
|
||||||
while (File.Exists(destinationPath))
|
while (File.Exists(destinationPath))
|
||||||
@@ -1582,11 +1589,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
DebugConsole.ThrowError("Copying the file \"" + file + "\" to the mod folder failed.", e);
|
DebugConsole.ThrowError("Copying the file \"" + file + "\" to the mod folder failed.", e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
destinationPath = Path.Combine(modFolder, filePathRelativeToModFolder);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RefreshCreateItemFileList();
|
RefreshCreateItemFileList();
|
||||||
@@ -1605,7 +1608,7 @@ namespace Barotrauma
|
|||||||
if (itemContentPackage == null) return;
|
if (itemContentPackage == null) return;
|
||||||
var contentTypes = Enum.GetValues(typeof(ContentType));
|
var contentTypes = Enum.GetValues(typeof(ContentType));
|
||||||
|
|
||||||
List<ContentFile> files = itemContentPackage.Files.ToList();
|
List<ContentFile> files = itemContentPackage.FilesUnsaved.ToList();
|
||||||
|
|
||||||
for (int i = files.Count - 1; i >= 0; i--)
|
for (int i = files.Count - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
@@ -1613,15 +1616,14 @@ namespace Barotrauma
|
|||||||
|
|
||||||
bool fileExists = File.Exists(contentFile.Path);
|
bool fileExists = File.Exists(contentFile.Path);
|
||||||
|
|
||||||
if (contentFile.Type == ContentType.Executable ||
|
if (contentFile.Type == ContentType.ServerExecutable)
|
||||||
contentFile.Type == ContentType.ServerExecutable)
|
|
||||||
{
|
{
|
||||||
fileExists |= File.Exists(Path.GetFileNameWithoutExtension(contentFile.Path) + ".dll");
|
fileExists |= File.Exists(Path.GetFileNameWithoutExtension(contentFile.Path) + ".dll");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fileExists)
|
if (!fileExists)
|
||||||
{
|
{
|
||||||
itemContentPackage.Files.Remove(contentFile);
|
itemContentPackage.RemoveFile(contentFile);
|
||||||
files.RemoveAt(i);
|
files.RemoveAt(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1653,8 +1655,7 @@ namespace Barotrauma
|
|||||||
bool illegalPath = !ContentPackage.IsModFilePathAllowed(contentFile);
|
bool illegalPath = !ContentPackage.IsModFilePathAllowed(contentFile);
|
||||||
bool fileExists = File.Exists(contentFile.Path);
|
bool fileExists = File.Exists(contentFile.Path);
|
||||||
|
|
||||||
if (contentFile.Type == ContentType.Executable ||
|
if (contentFile.Type == ContentType.ServerExecutable)
|
||||||
contentFile.Type == ContentType.ServerExecutable)
|
|
||||||
{
|
{
|
||||||
fileExists |= File.Exists(Path.GetFileNameWithoutExtension(contentFile.Path) + ".dll");
|
fileExists |= File.Exists(Path.GetFileNameWithoutExtension(contentFile.Path) + ".dll");
|
||||||
}
|
}
|
||||||
@@ -1674,7 +1675,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
var tickBox = new GUITickBox(new RectTransform(Vector2.One, content.RectTransform, scaleBasis: ScaleBasis.BothHeight), "")
|
var tickBox = new GUITickBox(new RectTransform(Vector2.One, content.RectTransform, scaleBasis: ScaleBasis.BothHeight), "")
|
||||||
{
|
{
|
||||||
Selected = itemContentPackage.Files.Contains(contentFile),
|
Selected = itemContentPackage.FilesUnsaved.Contains(contentFile),
|
||||||
UserData = contentFile
|
UserData = contentFile
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1683,11 +1684,11 @@ namespace Barotrauma
|
|||||||
ContentFile f = tb.UserData as ContentFile;
|
ContentFile f = tb.UserData as ContentFile;
|
||||||
if (tb.Selected)
|
if (tb.Selected)
|
||||||
{
|
{
|
||||||
if (!itemContentPackage.Files.Contains(f)) { itemContentPackage.Files.Add(f); }
|
if (!itemContentPackage.FilesUnsaved.Contains(f)) { itemContentPackage.AddFile(f); }
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (itemContentPackage.Files.Contains(f)) { itemContentPackage.Files.Remove(f); }
|
if (itemContentPackage.FilesUnsaved.Contains(f)) { itemContentPackage.RemoveFile(f); }
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -1702,7 +1703,7 @@ namespace Barotrauma
|
|||||||
nameText.TextColor = GUI.Style.Red;
|
nameText.TextColor = GUI.Style.Red;
|
||||||
tickBox.ToolTip = TextManager.Get("WorkshopItemFileNotFound");
|
tickBox.ToolTip = TextManager.Get("WorkshopItemFileNotFound");
|
||||||
}
|
}
|
||||||
else if (illegalPath && !ContentPackage.List.Any(cp => cp.Files.Any(f => Path.GetFullPath(f.Path) == Path.GetFullPath(contentFile.Path))))
|
else if (illegalPath && !ContentPackage.AllPackages.Any(cp => cp.FilesUnsaved.Any(f => Path.GetFullPath(f.Path) == Path.GetFullPath(contentFile.Path))))
|
||||||
{
|
{
|
||||||
nameText.TextColor = GUI.Style.Red;
|
nameText.TextColor = GUI.Style.Red;
|
||||||
tickBox.ToolTip = TextManager.Get("WorkshopItemIllegalPath");
|
tickBox.ToolTip = TextManager.Get("WorkshopItemIllegalPath");
|
||||||
@@ -1839,7 +1840,10 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
new GUIMessageBox(
|
new GUIMessageBox(
|
||||||
TextManager.Get("Error"),
|
TextManager.Get("Error"),
|
||||||
TextManager.GetWithVariable("WorkshopItemPublishFailed", "[itemname]", item?.Title) + " Task ended with status "+workshopPublishStatus?.TaskStatus?.ToString());
|
TextManager.GetWithVariable("WorkshopItemPublishFailed", "[itemname]", item?.Title) +
|
||||||
|
(workshopPublishStatus?.TaskStatus != null ?
|
||||||
|
" Task ended with status " +workshopPublishStatus?.TaskStatus?.ToString() :
|
||||||
|
" Publish failed with result "+ workshopPublishStatus.Result?.Result.ToString()));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user