Unstable 0.1400.1.0

This commit is contained in:
Markus Isberg
2021-05-20 16:12:54 +03:00
parent 92f0264af2
commit 5bc850cddb
181 changed files with 2475 additions and 1588 deletions

View File

@@ -39,10 +39,7 @@ namespace Barotrauma
partial void DamageParticles(float deltaTime, Vector2 worldPosition)
{
if (particleEmitter != null)
{
particleEmitter.Emit(deltaTime, worldPosition);
}
particleEmitter?.Emit(deltaTime, worldPosition);
if (sound != null)
{

View File

@@ -201,7 +201,7 @@ namespace Barotrauma
/// </summary>
public void ControlLocalPlayer(float deltaTime, Camera cam, bool moveCam = true)
{
if (DisableControls || GUI.PauseMenuOpen || GUI.SettingsMenuOpen)
if (DisableControls || GUI.InputBlockingMenuOpen)
{
foreach (Key key in keys)
{
@@ -323,7 +323,7 @@ namespace Barotrauma
DoInteractionUpdate(deltaTime, mouseSimPos);
}
if (!GUI.PauseMenuOpen && !GUI.SettingsMenuOpen)
if (!GUI.InputBlockingMenuOpen)
{
if (SelectedConstruction != null &&
(SelectedConstruction.ActiveHUDs.Any(ic => ic.GuiFrame != null && HUD.CloseHUD(ic.GuiFrame.Rect)) ||
@@ -515,6 +515,7 @@ namespace Barotrauma
if (draggingItemToWorld)
{
if (item.OwnInventory == null ||
!item.OwnInventory.Container.AllowDragAndDrop ||
!item.OwnInventory.CanBePut(CharacterInventory.DraggingItems.First()) ||
!CanAccessInventory(item.OwnInventory))
{
@@ -679,7 +680,7 @@ namespace Barotrauma
else
{
//Ideally it shouldn't send the character entirely if we can't see them but /shrug, this isn't the most hacker-proof game atm
hudInfoVisible = controlled.CanSeeCharacter(this, controlled.ViewTarget == null ? controlled.WorldPosition : controlled.ViewTarget.WorldPosition);
hudInfoVisible = controlled.CanSeeTarget(this, controlled.ViewTarget);
}
hudInfoTimer = Rand.Range(0.5f, 1.0f);
}

View File

@@ -302,9 +302,9 @@ namespace Barotrauma
GameAnalyticsManager.AddErrorEventOnce("CharacterNetworking.ClientRead:NoInventory" + ID, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
//read anyway to prevent messing up reading the rest of the message
UInt16 lastEventID = msg.ReadUInt16();
byte itemCount = msg.ReadByte();
for (int i = 0; i < itemCount; i++)
_ = msg.ReadUInt16();
byte inventoryItemCount = msg.ReadByte();
for (int i = 0; i < inventoryItemCount; i++)
{
msg.ReadUInt16();
}
@@ -411,8 +411,11 @@ namespace Barotrauma
string option = null;
if (orderPrefab.HasOptions)
{
int optionIndex = msg.ReadRangedInteger(0, orderPrefab.Options.Length);
option = orderPrefab.Options[optionIndex];
int optionIndex = msg.ReadRangedInteger(-1, orderPrefab.AllOptions.Length);
if (optionIndex > -1)
{
option = orderPrefab.Options[optionIndex];
}
}
GameMain.GameSession?.CrewManager?.SetOrderHighlight(this, orderPrefab.Identifier, option);
}
@@ -431,9 +434,18 @@ namespace Barotrauma
break;
case 9: //NetEntityEvent.Type.AddToCrew
GameMain.GameSession.CrewManager.AddCharacter(this);
foreach (Item item in Inventory.AllItems)
CharacterTeamType teamID = (CharacterTeamType)msg.ReadByte();
ushort itemCount = msg.ReadUInt16();
for (int i = 0; i < itemCount; i++)
{
ushort itemID = msg.ReadUInt16();
if (!(Entity.FindEntityByID(itemID) is Item item)) { continue; }
item.AllowStealing = true;
var wifiComponent = item.GetComponent<Items.Components.WifiComponent>();
if (wifiComponent != null)
{
wifiComponent.TeamID = teamID;
}
}
break;
}

View File

@@ -676,8 +676,8 @@ namespace Barotrauma
bool inWater = Character.AnimController.InWater;
var drawTarget = inWater ? Particles.ParticlePrefab.DrawTargetType.Water : Particles.ParticlePrefab.DrawTargetType.Air;
var emitter = Character.BloodEmitters.FirstOrDefault(e => e.Prefab.ParticlePrefab.DrawTarget == drawTarget || e.Prefab.ParticlePrefab.DrawTarget == Particles.ParticlePrefab.DrawTargetType.Both);
float particleMinScale = emitter != null ? emitter.Prefab.ScaleMin : 0.5f;
float particleMaxScale = emitter != null ? emitter.Prefab.ScaleMax : 1;
float particleMinScale = emitter?.Prefab.Properties.ScaleMin ?? 0.5f;
float particleMaxScale = emitter?.Prefab.Properties.ScaleMax ?? 1;
float severity = Math.Min(affliction.Strength / affliction.Prefab.MaxStrength * Character.Params.BleedParticleMultiplier, 1);
float bloodParticleSize = MathHelper.Lerp(particleMinScale, particleMaxScale, severity);
if (!inWater)
@@ -1326,7 +1326,7 @@ namespace Barotrauma
child.Recalculate();
}
if (buttonToSelect != null) { buttonToSelect.OnClicked(buttonToSelect, "selectaffliction"); }
buttonToSelect?.OnClicked(buttonToSelect, "selectaffliction");
afflictionIconContainer.RecalculateChildren();

View File

@@ -1395,9 +1395,9 @@ namespace Barotrauma
// omega nesting incoming
if (fabricationRecipe != null)
{
foreach (Tuple<string, PriceInfo> itemLocationPrice in itemPrefab.GetSellPricesOver(0))
foreach (KeyValuePair<string, PriceInfo> itemLocationPrice in itemPrefab.GetSellPricesOver(0))
{
NewMessage(" If bought at " + itemLocationPrice.Item1 + " it costs " + itemLocationPrice.Item2.Price);
NewMessage(" If bought at " + itemLocationPrice.Key + " it costs " + itemLocationPrice.Value.Price);
int totalPrice = 0;
int? totalBestPrice = 0;
foreach (var ingredient in fabricationRecipe.RequiredItems)
@@ -1408,15 +1408,15 @@ namespace Barotrauma
totalPrice += ingredientItemPrefab.DefaultPrice.Price;
totalBestPrice += ingredientItemPrefab.GetMinPrice();
int basePrice = ingredientItemPrefab.DefaultPrice.Price;
foreach (Tuple<string, PriceInfo> ingredientItemLocationPrice in ingredientItemPrefab.GetBuyPricesUnder())
foreach (KeyValuePair<string, PriceInfo> ingredientItemLocationPrice in ingredientItemPrefab.GetBuyPricesUnder())
{
if (basePrice > ingredientItemLocationPrice.Item2.Price)
if (basePrice > ingredientItemLocationPrice.Value.Price)
{
NewMessage(" Location " + ingredientItemLocationPrice.Item1 + " sells ingredient " + ingredientItemPrefab.Name + " for cheaper, " + ingredientItemLocationPrice.Item2.Price, Color.Yellow);
NewMessage(" Location " + ingredientItemLocationPrice.Key + " sells ingredient " + ingredientItemPrefab.Name + " for cheaper, " + ingredientItemLocationPrice.Value.Price, Color.Yellow);
}
else
{
NewMessage(" Location " + ingredientItemLocationPrice.Item1 + " sells ingredient " + ingredientItemPrefab.Name + " for more, " + ingredientItemLocationPrice.Item2.Price, Color.Teal);
NewMessage(" Location " + ingredientItemLocationPrice.Key + " sells ingredient " + ingredientItemPrefab.Name + " for more, " + ingredientItemLocationPrice.Value.Price, Color.Teal);
}
}
}
@@ -1426,11 +1426,15 @@ namespace Barotrauma
if (totalBestPrice.HasValue)
{
int? bestDifference = itemLocationPrice.Item2.Price - totalBestPrice;
int? bestDifference = itemLocationPrice.Value.Price - totalBestPrice;
NewMessage(" Constructing the item from store-bought items provides " + bestDifference + " profit with best-case scenario values.");
}
}
}
},
() =>
{
return new string[][] { ItemPrefab.Prefabs.SelectMany(p => p.Aliases).Concat(ItemPrefab.Prefabs.Select(p => p.Identifier)).ToArray() };
}, isCheat: false));
commands.Add(new Command("checkcraftingexploits", "checkcraftingexploits: Finds outright item exploits created by buying store-bought ingredients and constructing them into sellable items.", (string[] args) =>

View File

@@ -55,6 +55,12 @@ namespace Barotrauma
{
Debug.Assert(actionInstance == null || actionId == null);
if (GUI.InputBlockingMenuOpen)
{
if (actionId.HasValue) { SendIgnore(actionId.Value); }
return;
}
shouldFadeToBlack = fadeToBlack;
if (lastMessageBox != null && !lastMessageBox.Closed && GUIMessageBox.MessageBoxes.Contains(lastMessageBox))
@@ -368,6 +374,15 @@ namespace Barotrauma
GameMain.Client?.ClientPeer?.Send(outmsg, DeliveryMethod.Reliable);
}
private static void SendIgnore(UInt16 actionId)
{
IWriteMessage outmsg = new WriteOnlyMessage();
outmsg.Write((byte)ClientPacketHeader.EVENTMANAGER_RESPONSE);
outmsg.Write(actionId);
outmsg.Write(byte.MaxValue);
GameMain.Client?.ClientPeer?.Send(outmsg, DeliveryMethod.Reliable);
}
// Too broken, left it here if I ever want to come back to it
private static List<RichTextData> GetQuoteHighlights(string text, Color color)
{

View File

@@ -22,6 +22,13 @@ namespace Barotrauma
public override void ClientReadInitial(IReadMessage msg)
{
ushort targetItemCount = msg.ReadUInt16();
for (int i = 0; i < targetItemCount; i++)
{
var item = Item.ReadSpawnData(msg);
items.Add(item);
}
byte characterCount = msg.ReadByte();
for (int i = 0; i < characterCount; i++)

View File

@@ -10,7 +10,12 @@ namespace Barotrauma
for (int i = 0; i < characterCount; i++)
{
characters.Add(Character.ReadSpawnData(msg));
Character character = Character.ReadSpawnData(msg);
characters.Add(character);
if (msg.ReadBoolean())
{
terroristCharacters.Add(character);
}
ushort itemCount = msg.ReadUInt16();
for (int j = 0; j < itemCount; j++)
{

View File

@@ -1,18 +0,0 @@
using Barotrauma.Networking;
namespace Barotrauma
{
partial class OutpostDestroyMission : AbandonedOutpostMission
{
public override void ClientReadInitial(IReadMessage msg)
{
base.ClientReadInitial(msg);
ushort itemCount = msg.ReadUInt16();
for (int i = 0; i < itemCount; i++)
{
var item = Item.ReadSpawnData(msg);
items.Add(item);
}
}
}
}

View File

@@ -208,6 +208,19 @@ namespace Barotrauma
get { return pauseMenuOpen; }
}
public static bool InputBlockingMenuOpen
{
get
{
return PauseMenuOpen ||
SettingsMenuOpen ||
DebugConsole.IsOpen ||
GameSession.IsTabMenuOpen ||
(GameMain.GameSession?.GameMode?.Paused ?? false) ||
CharacterHUD.IsCampaignInterfaceOpen;
}
}
public static bool PreventPauseMenuToggle = false;
public static Color ScreenOverlayColor
@@ -2144,7 +2157,7 @@ namespace Barotrauma
for (int j = i + 1; j < elements.Count; j++)
{
Rectangle rect2 = elements[j].Rect;
if (!rect1.Intersects(rect2)) continue;
if (!rect1.Intersects(rect2)) { continue; }
intersections = true;
Point centerDiff = rect1.Center - rect2.Center;
@@ -2173,10 +2186,10 @@ namespace Barotrauma
elements[j].RectTransform.ScreenSpaceOffset += moveAmount2.ToPoint();
}
if (disallowedAreas == null) continue;
if (disallowedAreas == null) { continue; }
foreach (Rectangle rect2 in disallowedAreas)
{
if (!rect1.Intersects(rect2)) continue;
if (!rect1.Intersects(rect2)) { continue; }
intersections = true;
Point centerDiff = rect1.Center - rect2.Center;
@@ -2194,7 +2207,7 @@ namespace Barotrauma
iterations++;
}
Vector2 ClampMoveAmount(Rectangle Rect, Rectangle clampTo, Vector2 moveAmount)
static Vector2 ClampMoveAmount(Rectangle Rect, Rectangle clampTo, Vector2 moveAmount)
{
if (Rect.Y < clampTo.Y)
{

View File

@@ -201,7 +201,7 @@ namespace Barotrauma
{
base.ApplyStyle(style);
if (frame != null) { frame.ApplyStyle(style); }
frame?.ApplyStyle(style);
}
public override void Flash(Color? color = null, float flashDuration = 1.5f, bool useRectangleFlash = false, bool useCircularFlash = false, Vector2? flashRectInflate = null)

View File

@@ -551,7 +551,7 @@ namespace Barotrauma
}
if (openState >= 2.0f)
{
if (Parent != null) { Parent.RemoveChild(this); }
Parent?.RemoveChild(this);
if (MessageBoxes.Contains(this)) { MessageBoxes.Remove(this); }
}
}
@@ -604,7 +604,7 @@ namespace Barotrauma
}
else
{
if (Parent != null) { Parent.RemoveChild(this); }
Parent?.RemoveChild(this);
if (MessageBoxes.Contains(this)) { MessageBoxes.Remove(this); }
}

View File

@@ -658,10 +658,7 @@ namespace Barotrauma
currentTextColor * (currentTextColor.A / 255.0f), 0.0f, origin, TextScale, SpriteEffects.None, textDepth, RichTextData);
}
if (Strikethrough != null)
{
Strikethrough.Draw(spriteBatch, (int)Math.Ceiling(TextSize.X / 2f), pos.X, ForceUpperCase ? pos.Y : pos.Y + GUI.Scale * 2f);
}
Strikethrough?.Draw(spriteBatch, (int)Math.Ceiling(TextSize.X / 2f), pos.X, ForceUpperCase ? pos.Y : pos.Y + GUI.Scale * 2f);
}
if (overflowClipActive)

View File

@@ -626,7 +626,6 @@ namespace Barotrauma
if (GameMain.Client == null)
{
SubmarineInfo newSub = GameMain.GameSession.SwitchSubmarine(selectedSubmarine, deliveryFee);
GameMain.GameSession.Campaign.UpgradeManager.RefundResetAndReload(newSub);
RefreshSubmarineDisplay(true);
}
else
@@ -661,7 +660,6 @@ namespace Barotrauma
{
GameMain.GameSession.PurchaseSubmarine(selectedSubmarine);
SubmarineInfo newSub = GameMain.GameSession.SwitchSubmarine(selectedSubmarine, 0);
GameMain.GameSession.Campaign.UpgradeManager.RefundResetAndReload(newSub);
RefreshSubmarineDisplay(true);
}
else

View File

@@ -228,7 +228,10 @@ namespace Barotrauma
var crewButton = createTabButton(InfoFrameTab.Crew, "crew");
var missionButton = createTabButton(InfoFrameTab.Mission, "mission");
if (!(GameMain.GameSession?.GameMode is TestGameMode))
{
createTabButton(InfoFrameTab.Mission, "mission");
}
if (GameMain.GameSession?.GameMode is CampaignMode campaignMode)
{
@@ -903,44 +906,61 @@ namespace Barotrauma
infoFrame.ClearChildren();
GUIFrame missionFrame = new GUIFrame(new RectTransform(Vector2.One, infoFrame.RectTransform, Anchor.TopCenter), style: "GUIFrameListBox");
int padding = (int)(0.0245f * missionFrame.Rect.Height);
Location location = GameMain.GameSession.EndLocation != null ? GameMain.GameSession.EndLocation : GameMain.GameSession.StartLocation;
GUIFrame missionFrameContent = new GUIFrame(new RectTransform(new Point(missionFrame.Rect.Width - padding * 2, missionFrame.Rect.Height - padding * 2), infoFrame.RectTransform, Anchor.Center), style: null);
Location location = GameMain.GameSession.EndLocation ?? GameMain.GameSession.StartLocation;
GUILayoutGroup locationInfoContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.3f), missionFrameContent.RectTransform))
{
AbsoluteSpacing = GUI.IntScale(10)
};
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), locationInfoContainer.RectTransform), location.Name, font: GUI.LargeFont);
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), locationInfoContainer.RectTransform), location.Type.Name, font: GUI.SubHeadingFont);
var biomeLabel = new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.0f), locationInfoContainer.RectTransform),
TextManager.Get("Biome", fallBackTag: "location"), font: GUI.SubHeadingFont, textAlignment: Alignment.CenterLeft);
new GUITextBlock(new RectTransform(new Vector2(1.0f, 1.0f), biomeLabel.RectTransform), Level.Loaded.LevelData.Biome.DisplayName, textAlignment: Alignment.CenterRight);
var difficultyLabel = new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.0f), locationInfoContainer.RectTransform),
TextManager.Get("LevelDifficulty"), font: GUI.SubHeadingFont, textAlignment: Alignment.CenterLeft);
new GUITextBlock(new RectTransform(new Vector2(1.0f, 1.0f), difficultyLabel.RectTransform), ((int)Level.Loaded.LevelData.Difficulty) + " %", textAlignment: Alignment.CenterRight);
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.01f), missionFrameContent.RectTransform) { AbsoluteOffset = new Point(0, locationInfoContainer.Rect.Height + padding) }, style: "HorizontalLine")
{
CanBeFocused = false
};
int locationInfoYOffset = locationInfoContainer.Rect.Height + padding * 2;
Sprite portrait = location.Type.GetPortrait(location.PortraitId);
bool hasPortrait = portrait != null && portrait.SourceRect.Width > 0 && portrait.SourceRect.Height > 0;
int contentWidth = hasPortrait ? (int)(missionFrame.Rect.Width * 0.951f) : missionFrame.Rect.Width - padding * 2;
Vector2 locationNameSize = GUI.LargeFont.MeasureString(location.Name);
Vector2 locationTypeSize = GUI.SubHeadingFont.MeasureString(location.Name);
GUITextBlock locationNameText = new GUITextBlock(new RectTransform(new Point(contentWidth, (int)locationNameSize.Y), missionFrame.RectTransform, Anchor.TopCenter) { AbsoluteOffset = new Point(0, padding) }, location.Name, font: GUI.LargeFont);
GUITextBlock locationTypeText = new GUITextBlock(new RectTransform(new Point(contentWidth, (int)locationTypeSize.Y), missionFrame.RectTransform, Anchor.TopCenter) { AbsoluteOffset = new Point(0, locationNameText.Rect.Height + padding) }, location.Type.Name, font: GUI.SubHeadingFont);
int locationInfoYOffset = locationNameText.Rect.Height + locationTypeText.Rect.Height + padding * 2;
GUIListBox missionList;
int contentWidth = missionFrameContent.Rect.Width;
if (hasPortrait)
{
GUIFrame portraitHolder = new GUIFrame(new RectTransform(new Point(contentWidth, (int)(missionFrame.Rect.Height * 0.588f)), missionFrame.RectTransform, Anchor.TopCenter) { AbsoluteOffset = new Point(0, locationInfoYOffset) });
float portraitAspectRatio = portrait.SourceRect.Width / portrait.SourceRect.Height;
GUIImage portraitImage = new GUIImage(new RectTransform(new Vector2(1.0f, 1f), portraitHolder.RectTransform), portrait, scaleToFit: true);
portraitHolder.RectTransform.NonScaledSize = new Point(portraitImage.Rect.Size.X, (int)(portraitImage.Rect.Size.X / portraitAspectRatio));
GUIImage portraitImage = new GUIImage(new RectTransform(new Vector2(0.5f, 1f), locationInfoContainer.RectTransform, Anchor.CenterRight), portrait, scaleToFit: true)
{
IgnoreLayoutGroups = true
};
locationInfoContainer.Recalculate();
portraitImage.RectTransform.NonScaledSize = new Point(Math.Min((int)(portraitImage.Rect.Size.Y * portraitAspectRatio), portraitImage.Rect.Width), portraitImage.Rect.Size.Y);
}
missionList = new GUIListBox(new RectTransform(new Point(contentWidth, missionFrame.Rect.Bottom - portraitHolder.Rect.Bottom - padding), missionFrame.RectTransform, Anchor.TopCenter) { AbsoluteOffset = new Point(0, portraitHolder.RectTransform.AbsoluteOffset.Y + portraitHolder.Rect.Height + padding) });
}
else
{
missionList = new GUIListBox(new RectTransform(new Point(contentWidth, missionFrame.Rect.Height - locationInfoYOffset - padding), missionFrame.RectTransform, Anchor.TopCenter) { AbsoluteOffset = new Point(0, locationInfoYOffset) });
}
GUIListBox missionList = new GUIListBox(new RectTransform(new Point(contentWidth, missionFrameContent.Rect.Height - locationInfoYOffset), missionFrameContent.RectTransform, Anchor.TopCenter) { AbsoluteOffset = new Point(0, locationInfoYOffset) });
missionList.ContentBackground.Color = Color.Transparent;
missionList.Spacing = GUI.IntScale(15);
if (GameMain.GameSession?.Missions != null)
{
int spacing = GUI.IntScale(5);
int iconSize = (int)(GUI.LargeFont.MeasureChar('T').Y + GUI.Font.MeasureChar('T').Y * 4 + spacing * 4);
foreach (Mission mission in GameMain.GameSession.Missions)
{
GUIFrame missionDescriptionHolder = new GUIFrame(new RectTransform(Vector2.One, missionList.Content.RectTransform), style: null);
GUILayoutGroup missionTextGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.744f, 0f), missionDescriptionHolder.RectTransform, Anchor.CenterLeft) { RelativeOffset = new Vector2(0.225f, 0f) }, false, childAnchor: Anchor.TopLeft)
GUILayoutGroup missionTextGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.744f, 0f), missionDescriptionHolder.RectTransform, Anchor.CenterLeft) { AbsoluteOffset = new Point(iconSize + spacing, 0) }, false, childAnchor: Anchor.TopLeft)
{
AbsoluteSpacing = GUI.IntScale(5)
AbsoluteSpacing = spacing
};
string descriptionText = mission.Description;
foreach (string missionMessage in mission.ShownMessages)
@@ -974,12 +994,12 @@ namespace Barotrauma
if (mission.Prefab.Icon != null)
{
float iconAspectRatio = mission.Prefab.Icon.SourceRect.Width / mission.Prefab.Icon.SourceRect.Height;
/*float iconAspectRatio = mission.Prefab.Icon.SourceRect.Width / mission.Prefab.Icon.SourceRect.Height;
int iconWidth = (int)(0.225f * missionDescriptionHolder.RectTransform.NonScaledSize.X);
int iconHeight = Math.Max(missionTextGroup.RectTransform.NonScaledSize.Y, (int)(iconWidth * iconAspectRatio));
Point iconSize = new Point(iconWidth, iconHeight);
Point iconSize = new Point(iconWidth, iconHeight);*/
new GUIImage(new RectTransform(iconSize, missionDescriptionHolder.RectTransform), mission.Prefab.Icon, null, true)
new GUIImage(new RectTransform(new Point(iconSize), missionDescriptionHolder.RectTransform), mission.Prefab.Icon, null, true)
{
Color = mission.Prefab.IconColor,
HoverColor = mission.Prefab.IconColor,

View File

@@ -43,7 +43,7 @@ namespace Barotrauma
private readonly CampaignUI campaignUI;
private CampaignMode? Campaign => campaignUI.Campaign;
private int AvailableMoney => Campaign?.Money ?? 0;
private UpgradeTab selectedUpgradTab = UpgradeTab.Upgrade;
private UpgradeTab selectedUpgradeTab = UpgradeTab.Upgrade;
private GUIMessageBox? currectConfirmation;
@@ -59,7 +59,7 @@ namespace Barotrauma
private GUIFrame? subPreviewFrame;
private Submarine? drawnSubmarine;
private readonly List<UpgradeCategory> applicableCategories = new List<UpgradeCategory>();
private Vector2[][] subHullVerticies = new Vector2[0][];
private Vector2[][] subHullVertices = new Vector2[0][];
private List<Structure> submarineWalls = new List<Structure>();
public MapEntity? HoveredItem;
@@ -110,7 +110,7 @@ namespace Barotrauma
public void RefreshAll()
{
switch (selectedUpgradTab)
switch (selectedUpgradeTab)
{
case UpgradeTab.Repairs:
SelectTab(UpgradeTab.Repairs);
@@ -215,7 +215,7 @@ namespace Barotrauma
*/
private void CreateUI(GUIComponent parent)
{
selectedUpgradTab = UpgradeTab.Upgrade;
selectedUpgradeTab = UpgradeTab.Upgrade;
parent.ClearChildren();
ItemInfoFrame.ClearChildren();
@@ -259,8 +259,8 @@ namespace Barotrauma
GUIImage submarineIcon = new GUIImage(rectT(new Point(locationLayout.Rect.Height, locationLayout.Rect.Height), locationLayout), style: "SubmarineIcon", scaleToFit: true);
new GUITextBlock(rectT(1.0f - submarineIcon.RectTransform.RelativeSize.X, 1, locationLayout), TextManager.Get("UpgradeUI.Title"), font: GUI.LargeFont);
categoryButtonLayout = new GUILayoutGroup(rectT(0.4f, 0.3f, leftLayout), isHorizontal: true) { Stretch = true };
GUIButton upgradeButton = new GUIButton(rectT(1, 1f, categoryButtonLayout), TextManager.Get("UICategory.Upgrades"), style: "GUITabButton") { UserData = UpgradeTab.Upgrade, Selected = selectedUpgradTab == UpgradeTab.Upgrade };
GUIButton repairButton = new GUIButton(rectT(1, 1f, categoryButtonLayout), TextManager.Get("UICategory.Maintenance"), style: "GUITabButton") { UserData = UpgradeTab.Repairs, Selected = selectedUpgradTab == UpgradeTab.Repairs };
GUIButton upgradeButton = new GUIButton(rectT(1, 1f, categoryButtonLayout), TextManager.Get("UICategory.Upgrades"), style: "GUITabButton") { UserData = UpgradeTab.Upgrade, Selected = selectedUpgradeTab == UpgradeTab.Upgrade };
GUIButton repairButton = new GUIButton(rectT(1, 1f, categoryButtonLayout), TextManager.Get("UICategory.Maintenance"), style: "GUITabButton") { UserData = UpgradeTab.Repairs, Selected = selectedUpgradeTab == UpgradeTab.Repairs };
/* RIGHT HEADER LAYOUT
* |---------------------------------------------------------------------------------------------------|
@@ -282,15 +282,15 @@ namespace Barotrauma
{
if (o is UpgradeTab upgradeTab)
{
if (upgradeTab != selectedUpgradTab || currentStoreLayout == null || currentStoreLayout.Parent != storeLayout)
if (upgradeTab != selectedUpgradeTab || currentStoreLayout == null || currentStoreLayout.Parent != storeLayout)
{
selectedUpgradTab = upgradeTab;
SelectTab(selectedUpgradTab);
selectedUpgradeTab = upgradeTab;
SelectTab(selectedUpgradeTab);
storeLayout?.Recalculate();
}
repairButton.Selected = (UpgradeTab) repairButton.UserData == selectedUpgradTab;
upgradeButton.Selected = (UpgradeTab) upgradeButton.UserData == selectedUpgradTab;
repairButton.Selected = (UpgradeTab) repairButton.UserData == selectedUpgradeTab;
upgradeButton.Selected = (UpgradeTab) upgradeButton.UserData == selectedUpgradeTab;
return true;
}
@@ -306,6 +306,12 @@ namespace Barotrauma
SelectTab(UpgradeTab.Upgrade);
var itemSwapPreview = new GUICustomComponent(new RectTransform(new Vector2(0.27f, 0.4f), mainStoreLayout.RectTransform, Anchor.TopLeft) { RelativeOffset = new Vector2(GUI.IsFourByThree() ? 0.5f : 0.47f, 0.0f) }, DrawItemSwapPreview)
{
IgnoreLayoutGroups = true,
CanBeFocused = true
};
#if DEBUG
// creates a button that re-creates the UI
CreateRefreshButton();
@@ -323,6 +329,35 @@ namespace Barotrauma
#endif
}
private void DrawItemSwapPreview(SpriteBatch spriteBatch, GUICustomComponent component)
{
var selectedItem = customizeTabOpen ?
activeItemSwapSlideDown?.UserData as Item ?? HoveredItem as Item :
HoveredItem as Item;
if (selectedItem?.Prefab.SwappableItem == null) { return; }
Sprite schematicsSprite = selectedItem.Prefab.SwappableItem.SchematicSprite;
if (schematicsSprite == null) { return; }
float schematicsScale = Math.Min(component.Rect.Width / 2 / schematicsSprite.size.X, component.Rect.Height / schematicsSprite.size.Y);
Vector2 center = new Vector2(component.Rect.Center.X, component.Rect.Center.Y);
schematicsSprite.Draw(spriteBatch, new Vector2(component.Rect.X, center.Y), GUI.Style.Green, new Vector2(0, schematicsSprite.size.Y / 2),
scale: schematicsScale);
var swappableItemList = selectedUpgradeCategoryLayout?.FindChild("prefablist", true) as GUIListBox;
var highlightedElement = swappableItemList?.Content.FindChild(c => c.UserData is ItemPrefab && c.IsParentOf(GUI.MouseOn)) ?? GUI.MouseOn;
ItemPrefab swapTo = highlightedElement?.UserData as ItemPrefab ?? selectedItem.PendingItemSwap;
if (swapTo?.SwappableItem == null) { return; }
Sprite? schematicsSprite2 = swapTo.SwappableItem?.SchematicSprite;
schematicsSprite2?.Draw(spriteBatch, new Vector2(component.Rect.Right, center.Y), GUI.Style.Orange, new Vector2(schematicsSprite2.size.X, schematicsSprite2.size.Y / 2),
scale: Math.Min(component.Rect.Width / 2 / schematicsSprite2.size.X, component.Rect.Height / schematicsSprite2.size.Y));
var arrowSprite = GUI.Style?.GetComponentStyle("GUIButtonToggleRight")?.GetDefaultSprite();
if (arrowSprite != null)
{
arrowSprite.Draw(spriteBatch, center, scale: GUI.Scale);
}
}
private void SelectTab(UpgradeTab tab)
{
if (currentStoreLayout != null)
@@ -672,7 +707,9 @@ namespace Barotrauma
GUIFrame paddedFrame = new GUIFrame(rectT(0.93f, 0.9f, frame, Anchor.Center), style: null);
bool hasSwappableItems = Submarine.MainSub.GetItems(true).Any(i =>
i.Prefab.SwappableItem != null && (i.Prefab.SwappableItem.CanBeBought || ItemPrefab.Prefabs.Any(ip => ip.SwappableItem?.ReplacementOnUninstall == i.Prefab.Identifier)) &&
i.Prefab.SwappableItem != null &&
!i.HiddenInGame && i.AllowSwapping &&
(i.Prefab.SwappableItem.CanBeBought || ItemPrefab.Prefabs.Any(ip => ip.SwappableItem?.ReplacementOnUninstall == i.Prefab.Identifier)) &&
Submarine.MainSub.IsEntityFoundOnThisSub(i, true) && category.ItemTags.Any(t => i.HasTag(t)));
float listHeight = hasSwappableItems ? 0.9f : 1.0f;
@@ -746,7 +783,7 @@ namespace Barotrauma
p is ItemPrefab itemPrefab &&
category.ItemTags.Any(t => itemPrefab.Tags.Contains(t)) &&
(itemPrefab.SwappableItem?.CanBeBought ?? false)).Cast<ItemPrefab>();
var entitiesOnSub = submarine.GetItems(true).Where(i => submarine.IsEntityFoundOnThisSub(i, true) && category.ItemTags.Any(t => i.HasTag(t))).ToList();
var entitiesOnSub = submarine.GetItems(true).Where(i => submarine.IsEntityFoundOnThisSub(i, true) && !i.HiddenInGame && i.AllowSwapping && category.ItemTags.Any(t => i.HasTag(t))).ToList();
int slotIndex = 0;
foreach (Item item in entitiesOnSub)
@@ -836,7 +873,7 @@ namespace Barotrauma
int price = isPurchased || replacement == item.Prefab ? 0 : replacement.SwappableItem.GetPrice(Campaign.Map?.CurrentLocation);
frames.Add(CreateUpgradeEntry(rectT(1f, 0.25f, parent.Content), replacement.UpgradePreviewSprite, replacement.Name, replacement.Description,
price, null,
price, replacement,
addBuyButton: true,
addProgressBar: false,
buttonStyle: isPurchased ? "UpgradeBuyButton" : "StoreAddToCrateButton"));
@@ -1191,7 +1228,7 @@ namespace Barotrauma
{
if (HoveredItem != item) { CreateItemTooltip(item); }
HoveredItem = item;
if (PlayerInput.PrimaryMouseButtonClicked() && selectedUpgradTab == UpgradeTab.Upgrade && currentStoreLayout != null)
if (PlayerInput.PrimaryMouseButtonClicked() && selectedUpgradeTab == UpgradeTab.Upgrade && currentStoreLayout != null)
{
if (customizeTabOpen)
{
@@ -1221,14 +1258,14 @@ namespace Barotrauma
// Every wall should have the same upgrades so we can just display the first one in the tooltip
Structure? firstStructure = submarineWalls.FirstOrDefault();
// use pnpoly algorithm to detect if our mouse is within any of the hull polygons
if (subHullVerticies.Any(hullVertex => ToolBox.PointIntersectsWithPolygon(PlayerInput.MousePosition, hullVertex)))
if (subHullVertices.Any(hullVertex => ToolBox.PointIntersectsWithPolygon(PlayerInput.MousePosition, hullVertex)))
{
if (HoveredItem != firstStructure && !(firstStructure is null)) { CreateItemTooltip(firstStructure); }
HoveredItem = firstStructure;
isMouseOnStructure = true;
GUI.MouseCursor = CursorState.Hand;
if (PlayerInput.PrimaryMouseButtonClicked() && selectedUpgradTab == UpgradeTab.Upgrade && currentStoreLayout != null)
if (PlayerInput.PrimaryMouseButtonClicked() && selectedUpgradeTab == UpgradeTab.Upgrade && currentStoreLayout != null)
{
ScrollToCategory(data => data.Category.IsWallUpgrade);
}
@@ -1353,7 +1390,7 @@ namespace Barotrauma
Vector2 offset = (sub.WorldPosition - new Vector2(dockedBorders.Center.X, dockedBorders.Y - dockedBorders.Height / 2)) * scale;
Vector2 center = parent.Rect.Center.ToVector2();
subHullVerticies = new Vector2[sub.HullVertices.Count][];
subHullVertices = new Vector2[sub.HullVertices.Count][];
for (int i = 0; i < sub.HullVertices.Count; i++)
{
@@ -1367,7 +1404,7 @@ namespace Barotrauma
float angle = (float)Math.Atan2(edge.Y, edge.X);
Matrix rotate = Matrix.CreateRotationZ(angle);
subHullVerticies[i] = new[]
subHullVertices[i] = new[]
{
center + start + Vector2.Transform(new Vector2(length, -lineWidth), rotate),
center + end + Vector2.Transform(new Vector2(-length, -lineWidth), rotate),
@@ -1379,7 +1416,7 @@ namespace Barotrauma
private void DrawSubmarine(SpriteBatch spriteBatch, GUICustomComponent component)
{
foreach (Vector2[] hullVertex in subHullVerticies)
foreach (Vector2[] hullVertex in subHullVertices)
{
// calculate the center point so we can draw a line from X to Y instead of drawing a rotated rectangle that is filled
Vector2 point1 = hullVertex[1] + (hullVertex[2] - hullVertex[1]) / 2;

View File

@@ -951,10 +951,7 @@ namespace Barotrauma
Screen.Selected.AddToGUIUpdateList();
if (Client != null)
{
Client.AddToGUIUpdateList();
}
Client?.AddToGUIUpdateList();
SubmarinePreview.AddToGUIUpdateList();
@@ -984,10 +981,7 @@ namespace Barotrauma
}
}
if (NetworkMember != null)
{
NetworkMember.Update((float)Timing.Step);
}
NetworkMember?.Update((float)Timing.Step);
GUI.Update((float)Timing.Step);
}

View File

@@ -1279,10 +1279,7 @@ namespace Barotrauma
//make the previously selected character wait in place for some time
//(so they don't immediately start idling and walking away from their station)
var aiController = Character.Controlled?.AIController;
if (aiController != null)
{
aiController.Reset();
}
aiController?.Reset();
DisableCommandUI();
Character.Controlled = character;
HintManager.OnChangeCharacter();
@@ -2009,7 +2006,10 @@ namespace Barotrauma
{
nodeConnectors = new GUICustomComponent(
new RectTransform(Vector2.One, commandFrame.RectTransform),
onDraw: DrawNodeConnectors);
onDraw: DrawNodeConnectors)
{
CanBeFocused = false
};
nodeConnectors.SetAsFirstChild();
background.SetAsFirstChild();
}
@@ -2018,10 +2018,27 @@ namespace Barotrauma
{
if (centerNode == null || optionNodes == null) { return; }
var startNodePos = centerNode.Rect.Center.ToVector2();
// Don't draw connectors for mini map options or assignment nodes
if ((targetFrame == null || !targetFrame.Visible) && !(optionNodes.FirstOrDefault()?.Item1.UserData is Character))
// Don't draw connectors for assignment nodes
if (!(optionNodes.FirstOrDefault()?.Item1.UserData is Character))
{
optionNodes.ForEach(n => DrawNodeConnector(startNodePos, centerNodeMargin, n.Item1, optionNodeMargin, spriteBatch));
// Regular option nodes
if (targetFrame == null || !targetFrame.Visible)
{
optionNodes.ForEach(n => DrawNodeConnector(startNodePos, centerNodeMargin, n.Item1, optionNodeMargin, spriteBatch));
}
// Minimap item nodes for single-option orders
else if(optionNodes.FirstOrDefault()?.Item1?.UserData is Tuple<Order, string> userData && string.IsNullOrEmpty(userData.Item2))
{
foreach (var node in optionNodes)
{
float iconRadius = 0.5f * optionNodeMargin;
Vector2 itemPosition = node.Item1.Parent.Rect.Center.ToVector2();
if (Vector2.Distance(node.Item1.Center, itemPosition) <= iconRadius) { continue; }
DrawNodeConnector(itemPosition, 0.0f, node.Item1, iconRadius, spriteBatch, widthMultiplier: 0.5f);
GUI.DrawFilledRectangle(spriteBatch, itemPosition - Vector2.One, new Vector2(3),
node.Item1.GetChildByUserData("colorsource")?.Color ?? Color.White);
}
}
}
DrawNodeConnector(startNodePos, centerNodeMargin, returnNode, returnNodeMargin, spriteBatch);
if (shortcutCenterNode == null || !shortcutCenterNode.Visible) { return; }
@@ -2030,7 +2047,7 @@ namespace Barotrauma
shortcutNodes.ForEach(n => DrawNodeConnector(startNodePos, shortcutCenterNodeMargin, n, shortcutNodeMargin, spriteBatch));
}
private void DrawNodeConnector(Vector2 startNodePos, float startNodeMargin, GUIComponent endNode, float endNodeMargin, SpriteBatch spriteBatch)
private void DrawNodeConnector(Vector2 startNodePos, float startNodeMargin, GUIComponent endNode, float endNodeMargin, SpriteBatch spriteBatch, float widthMultiplier = 1.0f)
{
if (endNode == null || !endNode.Visible) { return; }
var endNodePos = endNode.Rect.Center.ToVector2();
@@ -2041,11 +2058,11 @@ namespace Barotrauma
if ((selectedNode == null && endNode != shortcutCenterNode && GUI.IsMouseOn(endNode)) ||
(isSelectionHighlighted && (endNode == selectedNode || (endNode == shortcutCenterNode && shortcutNodes.Any(n => GUI.IsMouseOn(n))))))
{
GUI.DrawLine(spriteBatch, start, end, colorSource != null ? colorSource.HoverColor : Color.White, width: 4);
GUI.DrawLine(spriteBatch, start, end, colorSource?.HoverColor ?? Color.White, width: Math.Max(widthMultiplier * 4.0f, 1.0f));
}
else
{
GUI.DrawLine(spriteBatch, start, end, colorSource != null ? colorSource.Color : Color.White * nodeColorMultiplier, width: 2);
GUI.DrawLine(spriteBatch, start, end, colorSource?.Color ?? Color.White * nodeColorMultiplier, width: Math.Max(widthMultiplier * 2.0f, 1.0f));
}
}
@@ -2122,7 +2139,12 @@ namespace Barotrauma
{
if (commandFrame == null) { return false; }
RemoveOptionNodes();
if (targetFrame != null) { targetFrame.Visible = false; }
if (targetFrame != null)
{
targetFrame.Visible = false;
nodeConnectors.RectTransform.Parent = commandFrame.RectTransform;
nodeConnectors.RectTransform.RepositionChildInHierarchy(1);
}
// TODO: Center node could move to option node instead of being removed
commandFrame.RemoveChild(centerNode);
SetCenterNode(node);
@@ -2731,20 +2753,22 @@ namespace Barotrauma
if (itemTargetFrame == null) { continue; }
var anchor = Anchor.TopLeft;
if (itemTargetFrame.RectTransform.RelativeOffset.X < 0.5f && itemTargetFrame.RectTransform.RelativeOffset.Y < 0.5f)
if (itemTargetFrame.RectTransform.RelativeOffset.X < 0.5f)
{
anchor = Anchor.BottomRight;
if (itemTargetFrame.RectTransform.RelativeOffset.Y < 0.5f)
{
anchor = Anchor.BottomRight;
}
else
{
anchor = Anchor.TopRight;
}
}
else if (itemTargetFrame.RectTransform.RelativeOffset.X > 0.5f && itemTargetFrame.RectTransform.RelativeOffset.Y < 0.5f)
else if (itemTargetFrame.RectTransform.RelativeOffset.Y < 0.5f)
{
anchor = Anchor.BottomLeft;
}
else if (itemTargetFrame.RectTransform.RelativeOffset.X < 0.5f && itemTargetFrame.RectTransform.RelativeOffset.Y > 0.5f)
{
anchor = Anchor.TopRight;
}
GUIComponent optionElement;
if (order.Options.Length > 1)
{
@@ -2807,7 +2831,6 @@ namespace Barotrauma
{
UserData = userData,
Font = GUI.SmallFont,
ToolTip = item?.Name ?? GetOrderNameBasedOnContextuality(order),
OnClicked = (_, userData) =>
{
if (!CanIssueOrders) { return false; }
@@ -2824,12 +2847,28 @@ namespace Barotrauma
var colorMultiplier = characters.Any(c => c.CurrentOrders.Any(o => o.Order != null &&
o.Order.Identifier == userData.Item1.Identifier &&
o.Order.TargetEntity == userData.Item1.TargetEntity)) ? 0.5f : 1f;
CreateNodeIcon(Vector2.One, optionElement.RectTransform, item.Prefab.MinimapIcon ?? order.SymbolSprite, order.Color * colorMultiplier);
CreateNodeIcon(Vector2.One, optionElement.RectTransform, item.Prefab.MinimapIcon ?? order.SymbolSprite, order.Color * colorMultiplier, tooltip: item.Name);
optionNodes.Add(new Tuple<GUIComponent, Keys>(optionElement, Keys.None));
}
optionElements.Add(optionElement);
}
GUI.PreventElementOverlap(optionElements, clampArea: new Rectangle(10, 10, GameMain.GraphicsWidth - 20, GameMain.GraphicsHeight - 20));
Rectangle clampArea = new Rectangle(10, 10, GameMain.GraphicsWidth - 20, GameMain.GraphicsHeight - 20);
if (order.Identifier == "operateweapons")
{
Rectangle disallowedArea = targetFrame.GetChild<GUIFrame>().Rect;
Point originalSize = disallowedArea.Size;
disallowedArea.Size = disallowedArea.MultiplySize(0.9f);
disallowedArea.X += (originalSize.X - disallowedArea.Size.X) / 2;
disallowedArea.Y += (originalSize.Y - disallowedArea.Size.Y) / 2;
GUI.PreventElementOverlap(optionElements, new List<Rectangle>() { disallowedArea }, clampArea);
nodeConnectors.RectTransform.Parent = targetFrame.RectTransform;
nodeConnectors.RectTransform.SetAsFirstChild();
}
else
{
GUI.PreventElementOverlap(optionElements, clampArea: clampArea);
}
var shadow = new GUIFrame(
new RectTransform(targetFrame.Rect.Size + new Point((int)(200 * GUI.Scale)), targetFrame.RectTransform, anchor: Anchor.Center),
@@ -2901,6 +2940,12 @@ namespace Barotrauma
private bool CreateAssignmentNodes(GUIComponent node)
{
if (centerNode == null)
{
DisableCommandUI();
return false;
}
var order = (node.UserData is Order) ?
new Tuple<Order, string>(node.UserData as Order, null) :
node.UserData as Tuple<Order, string>;
@@ -2947,6 +2992,8 @@ namespace Barotrauma
node = null;
}
targetFrame.Visible = false;
nodeConnectors.RectTransform.Parent = commandFrame.RectTransform;
nodeConnectors.RectTransform.RepositionChildInHierarchy(1);
}
if (shortcutCenterNode != null)
{

View File

@@ -211,10 +211,7 @@ namespace Barotrauma
{
Character.Controlled = null;
if (prevControlled != null)
{
prevControlled.ClearInputs();
}
prevControlled?.ClearInputs();
overlayColor = Color.LightGray;
overlaySprite = Map.CurrentLocation.Type.GetPortrait(Map.CurrentLocation.PortraitId);
@@ -535,7 +532,13 @@ namespace Barotrauma
msg.Write(map.CurrentLocationIndex == -1 ? UInt16.MaxValue : (UInt16)map.CurrentLocationIndex);
msg.Write(map.SelectedLocationIndex == -1 ? UInt16.MaxValue : (UInt16)map.SelectedLocationIndex);
msg.Write(map.SelectedMissionIndex == -1 ? byte.MaxValue : (byte)map.SelectedMissionIndex);
var selectedMissionIndices = map.GetSelectedMissionIndices();
msg.Write((byte)selectedMissionIndices.Count());
foreach (int selectedMissionIndex in selectedMissionIndices)
{
msg.Write((byte)selectedMissionIndex);
}
msg.Write(PurchasedHullRepairs);
msg.Write(PurchasedItemRepairs);
msg.Write(PurchasedLostShuttles);
@@ -589,8 +592,15 @@ namespace Barotrauma
string mapSeed = msg.ReadString();
UInt16 currentLocIndex = msg.ReadUInt16();
UInt16 selectedLocIndex = msg.ReadUInt16();
byte selectedMissionIndex = msg.ReadByte();
bool allowDebugTeleport = msg.ReadBoolean();
byte selectedMissionCount = msg.ReadByte();
List<int> selectedMissionIndices = new List<int>();
for (int i = 0; i < selectedMissionCount; i++)
{
selectedMissionIndices.Add(msg.ReadByte());
}
bool allowDebugTeleport = msg.ReadBoolean();
float? reputation = null;
if (msg.ReadBoolean()) { reputation = msg.ReadSingle(); }
@@ -717,7 +727,7 @@ namespace Barotrauma
campaign.Map.SetLocation(currentLocIndex == UInt16.MaxValue ? -1 : currentLocIndex);
campaign.Map.SelectLocation(selectedLocIndex == UInt16.MaxValue ? -1 : selectedLocIndex);
campaign.Map.SelectMission(selectedMissionIndex);
campaign.Map.SelectMission(selectedMissionIndices);
campaign.Map.AllowDebugTeleport = allowDebugTeleport;
campaign.CargoManager.SetItemsInBuyCrate(buyCrateItems);
campaign.CargoManager.SetPurchasedItems(purchasedItems);

View File

@@ -266,10 +266,7 @@ namespace Barotrauma
prevControlled.AIController.Enabled = false;
}
Character.Controlled = null;
if (prevControlled != null)
{
prevControlled.ClearInputs();
}
prevControlled?.ClearInputs();
GUI.DisableHUD = true;
while (GameMain.Instance.LoadingScreenOpen)
@@ -305,7 +302,7 @@ namespace Barotrauma
yield return CoroutineStatus.Success;
}
overlayTextColor = Color.Lerp(Color.Transparent, Color.White, (timer - 1.0f) / fadeInDuration);
timer = Math.Min(timer + CoroutineManager.DeltaTime, textDuration);
timer = Math.Min(timer + CoroutineManager.UnscaledDeltaTime, textDuration);
yield return CoroutineStatus.Running;
}
var outpost = GameMain.GameSession.Level.StartOutpost;
@@ -333,7 +330,7 @@ namespace Barotrauma
while (timer < fadeInDuration)
{
overlayColor = Color.Lerp(Color.LightGray, Color.Transparent, timer / fadeInDuration);
timer += CoroutineManager.DeltaTime;
timer += CoroutineManager.UnscaledDeltaTime;
yield return CoroutineStatus.Running;
}
overlayColor = Color.Transparent;

View File

@@ -224,10 +224,7 @@ namespace Barotrauma.Tutorials
public virtual void Update(float deltaTime)
{
if (videoPlayer != null)
{
videoPlayer.Update();
}
videoPlayer?.Update();
if (activeObjectives != null)
{

View File

@@ -218,12 +218,15 @@ namespace Barotrauma
};
List<Mission> missionsToDisplay = new List<Mission>(selectedMissions);
if (!selectedMissions.Any() && startLocation?.SelectedMission != null)
{
if (startLocation.SelectedMission.Locations[0] == startLocation.SelectedMission.Locations[1] ||
startLocation.SelectedMission.Locations.Contains(campaignMode?.Map.SelectedLocation))
if (!selectedMissions.Any() && startLocation != null)
{
foreach (Mission mission in startLocation.SelectedMissions)
{
missionsToDisplay.Add(startLocation.SelectedMission);
if (mission.Locations[0] == mission.Locations[1] ||
mission.Locations.Contains(campaignMode?.Map.SelectedLocation))
{
missionsToDisplay.Add(mission);
}
}
}
@@ -284,10 +287,11 @@ namespace Barotrauma
new GUIImage(new RectTransform(Vector2.One, missionIcon.RectTransform), displayedMission.Completed ? "MissionCompletedIcon" : "MissionFailedIcon", scaleToFit: true);
}
var missionTextContent = new GUILayoutGroup(new RectTransform(new Vector2(0.8f, 0.8f), missionContentHorizontal.RectTransform))
var missionTextContent = new GUILayoutGroup(new RectTransform(new Vector2(0.8f, 1.0f), missionContentHorizontal.RectTransform))
{
RelativeSpacing = 0.05f
AbsoluteSpacing = GUI.IntScale(5)
};
missionContentHorizontal.Recalculate();
var missionNameTextBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform),
displayedMission.Name, font: GUI.SubHeadingFont);
if (displayedMission.Difficulty.HasValue)
@@ -309,7 +313,7 @@ namespace Barotrauma
};
}
}
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform),
var missionDescription = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform),
missionMessage, wrap: true, parseRichText: true);
int reward = displayedMission.GetReward(Submarine.MainSub);
if (selectedMissions.Contains(displayedMission) && displayedMission.Completed && reward > 0)
@@ -323,6 +327,13 @@ namespace Barotrauma
var spacing = new GUIFrame(new RectTransform(new Vector2(1.0f, 1.0f), missionList.Content.RectTransform) { MaxSize = new Point(int.MaxValue, GUI.IntScale(15)) }, style: null);
new GUIFrame(new RectTransform(new Vector2(0.8f, 1.0f), spacing.RectTransform, Anchor.Center) { RelativeOffset = new Vector2(0.1f, 0.0f) }, "HorizontalLine");
}
foreach (GUIComponent child in missionTextContent.Children)
{
child.RectTransform.IsFixedSize = true;
}
missionTextContent.RectTransform.MinSize = new Point(0, missionTextContent.Children.Sum(c => c.Rect.Height + missionTextContent.AbsoluteSpacing));
missionContentHorizontal.RectTransform.MinSize = new Point(0, (int)(missionTextContent.Rect.Height / missionTextContent.RectTransform.RelativeSize.Y));
}
if (!missionsToDisplay.Any())

View File

@@ -39,43 +39,5 @@ namespace Barotrauma
}
}
}
/// <summary>
/// Server has notified us that upgrades were reset.
/// </summary>
/// <param name="inc"></param>
/// <see cref="UpgradeManager.SendUpgradeResetMessage"/>
public void ClientRead(IReadMessage inc)
{
bool shouldReset = inc.ReadBoolean();
int money = inc.ReadInt32();
// uint length = inc.ReadUInt32();
//
// for (int i = 0; i < length; i++)
// {
// string key = inc.ReadString();
// byte value = inc.ReadByte();
// Metadata.SetValue(key, value);
// }
Campaign.Money = money;
if (shouldReset)
{
ResetUpgrades();
}
// spentMoney is local, so this message box should only appear for those who have spent money on upgrades
if (spentMoney > 0)
{
GUIMessageBox msgBox = new GUIMessageBox(TextManager.Get("UpgradeRefundTitle"), TextManager.Get("UpgradeRefundBody"), new [] { TextManager.Get("Ok") });
msgBox.Buttons[0].OnClicked += msgBox.Close;
}
spentMoney = 0;
PendingUpgrades.Clear();
PurchasedUpgrades.Clear();
CanUpgrade = false;
}
}
}

View File

@@ -1326,24 +1326,41 @@ namespace Barotrauma
}
};
GUITickBox disableInGameHintsBox = new GUITickBox(new RectTransform(tickBoxScale, gameplaySettingsGroup.RectTransform),
TextManager.Get("DisableInGameHints"))
new GUITickBox(new RectTransform(tickBoxScale, gameplaySettingsGroup.RectTransform), TextManager.Get("DisableInGameHints"))
{
Selected = DisableInGameHints,
ToolTip = TextManager.Get("DisableInGameHintsToolTip"),
OnSelected = (tickBox) =>
{
DisableInGameHints = tickBox.Selected;
if (!DisableInGameHints && GameMain.Config?.IgnoredHints != null)
{
// Reset the ignored hints when the hints are re-enabled (to-be-replaced by a separate button)
GameMain.Config.IgnoredHints.Clear();
}
UnsavedSettings = true;
return true;
}
};
new GUIButton(new RectTransform(new Vector2(1.0f, 0.05f), gameplaySettingsGroup.RectTransform),
text: TextManager.Get("ResetInGameHints"),
style: "GUIButtonSmall")
{
OnClicked = (button, userData) =>
{
var msgBox = new GUIMessageBox(TextManager.Get("ResetInGameHints"),
TextManager.Get("ResetInGameHintsTooltip"),
new string[] { TextManager.Get("Yes"), TextManager.Get("Cancel") })
{
UserData = "verificationprompt"
};
msgBox.Buttons[0].OnClicked = (button, userData) =>
{
GameMain.Config.IgnoredHints.Clear();
return true;
};
msgBox.Buttons[0].OnClicked += msgBox.Close;
msgBox.Buttons[1].OnClicked = msgBox.Close;
return false;
}
};
GUITextBlock HUDScaleText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), gameplaySettingsGroup.RectTransform), TextManager.Get("HUDScale"), font: GUI.SubHeadingFont, wrap: true);
GUIScrollBar HUDScaleScrollBar = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.05f), gameplaySettingsGroup.RectTransform),
style: "GUISlider", barSize: 0.1f)

View File

@@ -281,10 +281,10 @@ namespace Barotrauma.Items.Components
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;
float particleRange = particleEmitter.Prefab.Properties.VelocityMax * particleEmitter.Prefab.ParticlePrefab.LifeTime;
particleEmitter.Emit(
deltaTime, particleStartPos,
item.CurrentHull, particleAngle, particleEmitter.Prefab.CopyEntityAngle ? -particleAngle : 0, velocityMultiplier: dist / particleRange * 1.5f,
item.CurrentHull, particleAngle, particleEmitter.Prefab.Properties.CopyEntityAngle ? -particleAngle : 0, velocityMultiplier: dist / particleRange * 1.5f,
colorMultiplier: new Color(color.R, color.G, color.B, (byte)255));
}
}

View File

@@ -16,44 +16,43 @@ namespace Barotrauma.Items.Components
public Vector2 DrawSize
{
get { return new Vector2(light.Range * 2, light.Range * 2); }
get { return new Vector2(Light.Range * 2, Light.Range * 2); }
}
private LightSource light;
public LightSource Light
{
get { return light; }
}
public LightSource Light { get; }
public override void OnScaleChanged()
{
light.SpriteScale = Vector2.One * item.Scale;
light.Position = ParentBody != null ? ParentBody.Position : item.Position;
Light.SpriteScale = Vector2.One * item.Scale;
Light.Position = ParentBody != null ? ParentBody.Position : item.Position;
}
partial void SetLightSourceState(bool enabled, float brightness)
{
if (light == null) { return; }
light.Enabled = enabled;
light.Color = LightColor.Multiply(brightness);
if (Light == null) { return; }
Light.Enabled = enabled;
if (enabled)
{
Light.Color = LightColor.Multiply(brightness);
}
}
public void Draw(SpriteBatch spriteBatch, bool editing = false, float itemDepth = -1)
{
if (light.LightSprite != null && (item.body == null || item.body.Enabled) && lightBrightness > 0.0f && IsOn)
if (Light.LightSprite != null && (item.body == null || item.body.Enabled) && lightBrightness > 0.0f && IsOn)
{
Vector2 origin = light.LightSprite.Origin;
if ((light.LightSpriteEffect & SpriteEffects.FlipHorizontally) == SpriteEffects.FlipHorizontally) { origin.X = light.LightSprite.SourceRect.Width - origin.X; }
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, itemDepth - 0.0001f);
Vector2 origin = Light.LightSprite.Origin;
if ((Light.LightSpriteEffect & SpriteEffects.FlipHorizontally) == SpriteEffects.FlipHorizontally) { origin.X = Light.LightSprite.SourceRect.Width - origin.X; }
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, itemDepth - 0.0001f);
}
}
public override void FlipX(bool relativeToSub)
{
if (light?.LightSprite != null && item.Prefab.CanSpriteFlipX && item.body == null)
if (Light?.LightSprite != null && item.Prefab.CanSpriteFlipX && item.body == null)
{
light.LightSpriteEffect = light.LightSpriteEffect == SpriteEffects.None ?
Light.LightSpriteEffect = Light.LightSpriteEffect == SpriteEffects.None ?
SpriteEffects.FlipHorizontally : SpriteEffects.None;
}
}
@@ -93,7 +92,7 @@ namespace Barotrauma.Items.Components
protected override void RemoveComponentSpecific()
{
base.RemoveComponentSpecific();
light.Remove();
Light.Remove();
}
}
}

View File

@@ -178,26 +178,26 @@ namespace Barotrauma.Items.Components
ToolTip = fi.TargetItem.Description
};
var container = new GUILayoutGroup(new RectTransform(Vector2.One, frame.RectTransform),
childAnchor: Anchor.CenterLeft, isHorizontal: true) { RelativeSpacing = 0.02f };
var container = new GUILayoutGroup(new RectTransform(Vector2.One, frame.RectTransform),
childAnchor: Anchor.CenterLeft, isHorizontal: true) { RelativeSpacing = 0.02f };
var itemIcon = fi.TargetItem.InventoryIcon ?? fi.TargetItem.sprite;
if (itemIcon != null)
{
new GUIImage(new RectTransform(new Point(frame.Rect.Height,frame.Rect.Height), container.RectTransform),
itemIcon, scaleToFit: true)
{
Color = fi.TargetItem.InventoryIconColor,
ToolTip = fi.TargetItem.Description
};
}
var itemIcon = fi.TargetItem.InventoryIcon ?? fi.TargetItem.sprite;
if (itemIcon != null)
{
new GUIImage(new RectTransform(new Point(frame.Rect.Height,frame.Rect.Height), container.RectTransform),
itemIcon, scaleToFit: true)
{
Color = fi.TargetItem.InventoryIconColor,
ToolTip = fi.TargetItem.Description
};
}
new GUITextBlock(new RectTransform(new Vector2(0.85f, 1f), container.RectTransform), GetRecipeNameAndAmount(fi))
{
Padding = Vector4.Zero,
AutoScaleVertical = true,
ToolTip = fi.TargetItem.Description
};
new GUITextBlock(new RectTransform(new Vector2(0.85f, 1f), container.RectTransform), GetRecipeNameAndAmount(fi))
{
Padding = Vector4.Zero,
AutoScaleVertical = true,
ToolTip = fi.TargetItem.Description
};
}
}
@@ -367,6 +367,10 @@ namespace Barotrauma.Items.Components
{
toolTipText += " " + (int)Math.Round(requiredItem.MinCondition * 100) + "%";
}
else if (requiredItem.MaxCondition <= 0.0f)
{
toolTipText = TextManager.GetWithVariable("displayname.emptyitem", "[itemname]", toolTipText);
}
if (!string.IsNullOrEmpty(requiredItem.ItemPrefabs.First().Description))
{
toolTipText += '\n' + requiredItem.ItemPrefabs.First().Description;

View File

@@ -33,10 +33,7 @@ namespace Barotrauma.Items.Components
base.Update(deltaTime, cam);
if (selectionUI != null)
{
selectionUI.Update();
}
selectionUI?.Update();
}
}
}

View File

@@ -436,7 +436,9 @@ namespace Barotrauma.Items.Components
connectedSubUpdateTimer = ConnectedSubUpdateInterval;
}
if (sonarView.Rect.Contains(PlayerInput.MousePosition))
Steering steering = item.GetComponent<Steering>();
if (sonarView.Rect.Contains(PlayerInput.MousePosition) &&
(GUI.MouseOn == null || GUI.MouseOn == sonarView || sonarView.IsParentOf(GUI.MouseOn) || GUI.MouseOn == steering?.GuiFrame || (steering?.GuiFrame?.IsParentOf(GUI.MouseOn) ?? false)))
{
float scrollSpeed = PlayerInput.ScrollWheelSpeed / 1000.0f;
if (Math.Abs(scrollSpeed) > 0.0001f)
@@ -613,7 +615,6 @@ namespace Barotrauma.Items.Components
}
}
Steering steering = item.GetComponent<Steering>();
if (steering != null && steering.DockingModeEnabled && steering.ActiveDockingSource != null)
{
float dockingDist = Vector2.Distance(steering.ActiveDockingSource.Item.WorldPosition, steering.DockingTarget.Item.WorldPosition);
@@ -780,10 +781,7 @@ namespace Barotrauma.Items.Components
DisplayRadius = (rect.Width / 2.0f) * (1.0f - displayBorderSize);
displayScale = DisplayRadius / range * zoom;
if (screenBackground != null)
{
screenBackground.Draw(spriteBatch, center, 0.0f, rect.Width / screenBackground.size.X);
}
screenBackground?.Draw(spriteBatch, center, 0.0f, rect.Width / screenBackground.size.X);
if (useDirectionalPing)
{
@@ -871,10 +869,7 @@ namespace Barotrauma.Items.Components
GUI.DrawString(spriteBatch, rect.Location.ToVector2(), sonarBlips.Count.ToString(), Color.White);
}
if (screenOverlay != null)
{
screenOverlay.Draw(spriteBatch, center, 0.0f, rect.Width / screenOverlay.size.X);
}
screenOverlay?.Draw(spriteBatch, center, 0.0f, rect.Width / screenOverlay.size.X);
if (signalStrength <= 0.5f)
{
@@ -937,21 +932,25 @@ namespace Barotrauma.Items.Components
cave.StartPos.ToVector2(), transducerCenter,
displayScale, center, DisplayRadius);
}
int missionIndex = 0;
foreach (Mission mission in GameMain.GameSession.Missions)
{
if (!string.IsNullOrWhiteSpace(mission.SonarLabel))
{
int i = 0;
foreach (Vector2 sonarPosition in mission.SonarPositions)
{
DrawMarker(spriteBatch,
mission.SonarLabel,
mission.SonarIconIdentifier,
mission,
sonarPosition, transducerCenter,
"mission" + missionIndex + ":" + i,
sonarPosition, transducerCenter,
displayScale, center, DisplayRadius * 0.95f);
i++;
}
}
missionIndex++;
}
if (AllowUsingMineralScanner && useMineralScanner && CurrentMode == Mode.Active && MineralClusters != null)
@@ -964,7 +963,7 @@ namespace Barotrauma.Items.Components
var i = unobtainedMinerals.FirstOrDefault();
if (i == null) { continue; }
DrawMarker(spriteBatch,
i.Name, "mineral", i,
i.Name, "mineral", "mineralcluster" + i,
c.center, transducerCenter,
displayScale, center, DisplayRadius * 0.95f,
onlyShowTextOnMouseOver: true);
@@ -977,14 +976,14 @@ namespace Barotrauma.Items.Components
if (connectedSubs.Contains(sub)) { continue; }
if (sub.WorldPosition.Y > Level.Loaded.Size.Y) { continue; }
if (item.Submarine != null)
if (item.Submarine != null || Character.Controlled != null)
{
//hide enemy team
if (sub.TeamID == CharacterTeamType.Team1 && (item.Submarine.TeamID == CharacterTeamType.Team2 || Character.Controlled?.TeamID == CharacterTeamType.Team2))
if (sub.TeamID == CharacterTeamType.Team1 && (item.Submarine?.TeamID == CharacterTeamType.Team2 || Character.Controlled?.TeamID == CharacterTeamType.Team2))
{
continue;
}
else if (sub.TeamID == CharacterTeamType.Team2 && (item.Submarine.TeamID == CharacterTeamType.Team1 || Character.Controlled?.TeamID == CharacterTeamType.Team1))
else if (sub.TeamID == CharacterTeamType.Team2 && (item.Submarine?.TeamID == CharacterTeamType.Team1 || Character.Controlled?.TeamID == CharacterTeamType.Team1))
{
continue;
}
@@ -1095,7 +1094,7 @@ namespace Barotrauma.Items.Components
if (!dockingPort.Item.Submarine.ShowSonarMarker && dockingPort.Item.Submarine != item.Submarine && !dockingPort.Item.Submarine.Info.IsOutpost) { continue; }
//don't show the docking ports of the opposing team on the sonar
if (item.Submarine != null)
if (item.Submarine != null && item.Submarine != GameMain.NetworkMember?.RespawnManager?.RespawnShuttle && dockingPort.Item.Submarine.Info.Type != SubmarineType.Outpost)
{
// specifically checking for friendlyNPC seems more logical here
if (dockingPort.Item.Submarine.TeamID != item.Submarine.TeamID && dockingPort.Item.Submarine.TeamID != CharacterTeamType.FriendlyNPC) { continue; }

View File

@@ -111,7 +111,7 @@ namespace Barotrauma.Items.Components
Tuple<Vector2, Vector2> tracerPoints = new Tuple<Vector2, Vector2>(startLocation, endLocation);
foreach (ParticleEmitter emitter in particleEmitters)
{
emitter.Emit(1.0f, particlePos, hullGuess: null, angle: rotation, particleRotation: rotation, colorMultiplier: emitter.Prefab.ColorMultiplier, tracerPoints: tracerPoints);
emitter.Emit(1.0f, particlePos, hullGuess: null, angle: rotation, particleRotation: rotation, colorMultiplier: emitter.Prefab.Properties.ColorMultiplier, tracerPoints: tracerPoints);
}
}

View File

@@ -73,7 +73,7 @@ namespace Barotrauma.Items.Components
}
particleEmitter.Emit(
deltaTime, ConvertUnits.ToDisplayUnits(raystart),
item.CurrentHull, particleAngle, particleEmitter.Prefab.CopyEntityAngle ? -particleAngle : 0);
item.CurrentHull, particleAngle, particleEmitter.Prefab.Properties.CopyEntityAngle ? -particleAngle : 0);
}
}

View File

@@ -40,7 +40,7 @@ namespace Barotrauma.Items.Components
Wire equippedWire = null;
bool allowRewiring = GameMain.NetworkMember?.ServerSettings == null || GameMain.NetworkMember.ServerSettings.AllowRewiring || panel.AlwaysAllowRewiring;
if (allowRewiring && (!panel.Locked || Screen.Selected == GameMain.SubEditorScreen))
if (allowRewiring && (!panel.Locked && !panel.TemporarilyLocked || Screen.Selected == GameMain.SubEditorScreen))
{
//if the Character using the panel has a wire item equipped
//and the wire hasn't been connected yet, draw it on the panel
@@ -365,7 +365,7 @@ namespace Barotrauma.Items.Components
ConnectionPanel.HighlightedWire = wire;
bool allowRewiring = GameMain.NetworkMember?.ServerSettings == null || GameMain.NetworkMember.ServerSettings.AllowRewiring || panel.AlwaysAllowRewiring;
if (allowRewiring && (!wire.Locked && !panel.Locked || Screen.Selected == GameMain.SubEditorScreen))
if (allowRewiring && (!wire.Locked && !panel.Locked && !panel.TemporarilyLocked || Screen.Selected == GameMain.SubEditorScreen))
{
//start dragging the wire
if (PlayerInput.PrimaryMouseButtonHeld()) { DraggingConnected = wire; }

View File

@@ -46,6 +46,8 @@ namespace Barotrauma.Items.Components
private Character equipper;
private bool isEquippable;
public IEnumerable<Character> VisibleCharacters
{
get
@@ -55,14 +57,28 @@ namespace Barotrauma.Items.Components
}
}
public override void OnItemLoaded()
{
isEquippable = item.GetComponent<Pickable>() != null;
if (!isEquippable) { IsActive = true; }
}
public override void Update(float deltaTime, Camera cam)
{
base.Update(deltaTime, cam);
if (equipper == null || equipper.Removed)
Entity refEntity = equipper;
if (isEquippable)
{
IsActive = false;
return;
if (equipper == null || equipper.Removed)
{
IsActive = false;
return;
}
}
else
{
refEntity = item;
}
if (updateTimer > 0.0f)
@@ -76,11 +92,11 @@ namespace Barotrauma.Items.Components
{
if (c == equipper || !c.Enabled || c.Removed) { continue; }
float dist = Vector2.DistanceSquared(equipper.WorldPosition, c.WorldPosition);
float dist = Vector2.DistanceSquared(refEntity.WorldPosition, c.WorldPosition);
if (dist < Range * Range)
{
Vector2 diff = c.WorldPosition - equipper.WorldPosition;
if (Submarine.CheckVisibility(equipper.SimPosition, equipper.SimPosition + ConvertUnits.ToSimUnits(diff)) == null)
Vector2 diff = c.WorldPosition - refEntity.WorldPosition;
if (Submarine.CheckVisibility(refEntity.SimPosition, refEntity.SimPosition + ConvertUnits.ToSimUnits(diff)) == null)
{
visibleCharacters.Add(c);
}

View File

@@ -254,7 +254,7 @@ namespace Barotrauma.Items.Components
foreach (ParticleEmitter emitter in particleEmitterCharges)
{
// color is currently not connected to ammo type, should be updated when ammo is changed
emitter.Emit(deltaTime, particlePos, hullGuess: null, angle: -rotation, particleRotation: rotation, sizeMultiplier: sizeMultiplier, colorMultiplier: emitter.Prefab.ColorMultiplier);
emitter.Emit(deltaTime, particlePos, hullGuess: null, angle: -rotation, particleRotation: rotation, sizeMultiplier: sizeMultiplier, colorMultiplier: emitter.Prefab.Properties.ColorMultiplier);
}
if (chargeSoundChannel == null || !chargeSoundChannel.IsPlaying)

View File

@@ -1125,9 +1125,10 @@ namespace Barotrauma
if (selectedSlot == null)
{
if (DraggingItemToWorld &&
Character.Controlled.FocusedItem?.OwnInventory != null &&
(Character.Controlled.FocusedItem.GetComponent<ItemContainer>()?.HasRequiredItems(Character.Controlled, addMessage: false) ?? false) &&
Character.Controlled.FocusedItem.OwnInventory.CanBePut(DraggingItems.FirstOrDefault()))
Character.Controlled.FocusedItem is { OwnInventory: { } inventory } item && item.GetComponent<ItemContainer>() is { } container &&
container.HasRequiredItems(Character.Controlled, addMessage: false) &&
container.AllowDragAndDrop &&
inventory.CanBePut(DraggingItems.FirstOrDefault()))
{
bool anySuccess = false;
foreach (Item it in DraggingItems)

View File

@@ -462,10 +462,7 @@ namespace Barotrauma
if (GameMain.DebugDraw)
{
if (body != null)
{
body.DebugDraw(spriteBatch, Color.White);
}
body?.DebugDraw(spriteBatch, Color.White);
}
if (editing && IsSelected && PlayerInput.KeyDown(Keys.Space))
@@ -722,7 +719,7 @@ namespace Barotrauma
reloadTextureButton.OnClicked += (button, data) =>
{
Sprite.ReloadXML();
Sprite.ReloadTexture();
Sprite.ReloadTexture(updateAllSprites: true);
return true;
};
}
@@ -768,7 +765,7 @@ namespace Barotrauma
{
if (!ic.AllowInGameEditing) { continue; }
if (SerializableProperty.GetProperties<InGameEditable>(ic).Count == 0 &&
!SerializableProperty.GetProperties<ConditionallyEditable>(ic).Any(p => p.GetAttribute<ConditionallyEditable>().IsEditable()))
!SerializableProperty.GetProperties<ConditionallyEditable>(ic).Any(p => p.GetAttribute<ConditionallyEditable>().IsEditable(ic)))
{
continue;
}
@@ -1133,31 +1130,35 @@ namespace Barotrauma
texts.Add(new ColoredText(nameText, GUI.Style.TextColor, false, false));
bool noComponentText = true;
foreach (ItemComponent ic in components)
{
if (string.IsNullOrEmpty(ic.DisplayMsg)) { continue; }
if (!ic.CanBePicked && !ic.CanBeSelected) { continue; }
if (ic is Holdable holdable && !holdable.CanBeDeattached()) { continue; }
Color color = Color.Gray;
if (ic.HasRequiredItems(character, false))
{
if (ic is Repairable)
{
if (!IsFullCondition) { color = Color.Cyan; }
}
else
{
color = Color.Cyan;
}
}
texts.Add(new ColoredText(ic.DisplayMsg, color, false, false));
noComponentText = false;
}
if (noComponentText && CampaignInteractionType != CampaignMode.InteractionType.None)
if (CampaignInteractionType != CampaignMode.InteractionType.None)
{
texts.Add(new ColoredText(TextManager.GetWithVariable($"CampaignInteraction.{CampaignInteractionType}", "[key]", GameMain.Config.KeyBindText(InputType.Use)), Color.Cyan, false, false));
}
else
{
foreach (ItemComponent ic in components)
{
if (string.IsNullOrEmpty(ic.DisplayMsg)) { continue; }
if (!ic.CanBePicked && !ic.CanBeSelected) { continue; }
if (ic is Holdable holdable && !holdable.CanBeDeattached()) { continue; }
Color color = Color.Gray;
if (ic.HasRequiredItems(character, false))
{
if (ic is Repairable)
{
if (!IsFullCondition) { color = Color.Cyan; }
}
else
{
color = Color.Cyan;
}
}
texts.Add(new ColoredText(ic.DisplayMsg, color, false, false));
noComponentText = false;
}
}
if (PlayerInput.IsShiftDown() && CrewManager.DoesItemHaveContextualOrders(this))
{
texts.Add(new ColoredText(TextManager.ParseInputTypes(TextManager.Get("itemmsgcontextualorders")), Color.Cyan, false, false));

View File

@@ -77,9 +77,9 @@ namespace Barotrauma
if (flash)
{
float displayRange = flashRange.HasValue ? flashRange.Value : Attack.Range;
float displayRange = flashRange ?? Attack.Range;
if (displayRange < 0.1f) { return; }
var light = new LightSource(worldPosition, displayRange, Color.LightYellow, null);
var light = new LightSource(worldPosition, displayRange, flashColor, null);
CoroutineManager.StartCoroutine(DimLight(light));
}
}

View File

@@ -629,9 +629,9 @@ namespace Barotrauma
PowerConsumptionTimer = message.ReadSingle()
};
}
else if (BallastFlora != null)
else
{
BallastFlora.ClientRead(message, header);
BallastFlora?.ClientRead(message, header);
}
return;
}

View File

@@ -210,7 +210,7 @@ namespace Barotrauma
if (ParticleEmitterTriggers[i] != null && !ParticleEmitterTriggers[i].IsTriggered) { continue; }
Vector2 emitterPos = LocalToWorld(Prefab.EmitterPositions[i]);
ParticleEmitters[i].Emit(deltaTime, emitterPos, hullGuess: null,
angle: ParticleEmitters[i].Prefab.CopyEntityAngle ? -CurrentRotation + MathHelper.PiOver2 : 0.0f);
angle: ParticleEmitters[i].Prefab.Properties.CopyEntityAngle ? -CurrentRotation + MathHelper.PiOver2 : 0.0f);
}
}
@@ -293,6 +293,12 @@ namespace Barotrauma
public void ClientRead(IReadMessage msg)
{
if (Triggers == null) { return; }
if (Prefab.TakeLevelWallDamage)
{
float newHealth = msg.ReadRangedSingle(0.0f, Prefab.Health, 8);
AddDamage(Health - newHealth, 1.0f, null, isNetworkEvent: true);
}
for (int i = 0; i < Triggers.Count; i++)
{
if (!Triggers[i].UseNetworkSyncing) { continue; }

View File

@@ -20,6 +20,8 @@ namespace Barotrauma
const int MaxVisibleObjects = 500;
private Rectangle currentGridIndices;
public bool ForceRefreshVisibleObjects;
partial void UpdateProjSpecific(float deltaTime)
{
@@ -60,6 +62,8 @@ namespace Barotrauma
if (objectGrid[x, y] == null) { continue; }
foreach (LevelObject obj in objectGrid[x, y])
{
if (obj.Prefab.HideWhenBroken && obj.Health <= 0.0f) { continue; }
if (zoom < 0.05f)
{
//hide if the sprite is very small when zoomed this far out
@@ -154,9 +158,10 @@ namespace Barotrauma
indices.Height = Math.Min(indices.Height, objectGrid.GetLength(1) - 1);
float z = 0.0f;
if (currentGridIndices != indices && Timing.TotalTime > NextRefreshTime)
if (ForceRefreshVisibleObjects || (currentGridIndices != indices && Timing.TotalTime > NextRefreshTime))
{
RefreshVisibleObjects(indices, cam.Zoom);
ForceRefreshVisibleObjects = false;
if (cam.Zoom < 0.1f)
{
//when zoomed very far out, refresh a little less often

View File

@@ -361,6 +361,7 @@ namespace Barotrauma.Lights
void DrawHalo(Character character)
{
if (character == null || character.Removed) { return; }
Vector2 haloDrawPos = character.DrawPosition;
haloDrawPos.Y = -haloDrawPos.Y;
@@ -404,7 +405,7 @@ namespace Barotrauma.Lights
}
foreach (Item item in Item.ItemList)
{
if (item.IsHighlighted && !highlightedEntities.Contains(item))
if ((item.IsHighlighted || item.IconStyle != null) && !highlightedEntities.Contains(item))
{
highlightedEntities.Add(item);
}
@@ -425,7 +426,14 @@ namespace Barotrauma.Lights
{
if (highlighted is Item item)
{
item.Draw(spriteBatch, false, true);
if (item.IconStyle != null && (item != Character.Controlled.FocusedItem || Character.Controlled.FocusedItem == null))
{
//wait until next pass
}
else
{
item.Draw(spriteBatch, false, true);
}
}
else if (highlighted is Character character)
{
@@ -434,6 +442,22 @@ namespace Barotrauma.Lights
}
spriteBatch.End();
//draw items with iconstyles in the style's color
spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.Additive, samplerState: SamplerState.LinearWrap, effect: SolidColorEffect, transformMatrix: spriteBatchTransform);
foreach (Entity highlighted in highlightedEntities)
{
if (highlighted is Item item)
{
if (item.IconStyle != null && (item != Character.Controlled.FocusedItem || Character.Controlled.FocusedItem == null))
{
SolidColorEffect.Parameters["color"].SetValue(item.IconStyle.Color.ToVector4());
SolidColorEffect.CurrentTechnique.Passes[0].Apply();
item.Draw(spriteBatch, false, true);
}
}
}
spriteBatch.End();
//draw characters in black with a bit of blur, leaving the white edges visible
float phase = (float)(Math.Sin(Timing.TotalTime * 3.0f) + 1.0f) / 2.0f; //phase oscillates between 0 and 1
Vector4 overlayColor = Color.Black.ToVector4() * MathHelper.Lerp(0.5f, 0.9f, phase);

View File

@@ -607,15 +607,18 @@ namespace Barotrauma
tooltip = (new Rectangle(typeChangeIconPos.ToPoint(), new Point(30)), location.LastTypeChangeMessage);
}
}
if (location != CurrentLocation && CurrentLocation.AvailableMissions.Any(m => m.Locations.Contains(location)) && generationParams.MissionIcon != null)
if (location != CurrentLocation && generationParams.MissionIcon != null)
{
Vector2 missionIconPos = pos + new Vector2(1.35f, 0.35f) * generationParams.LocationIconSize * 0.5f * zoom;
float missionIconScale = 18.0f / generationParams.MissionIcon.SourceRect.Width;
generationParams.MissionIcon.Draw(spriteBatch, missionIconPos, generationParams.IndicatorColor, scale: missionIconScale * zoom);
if (Vector2.Distance(PlayerInput.MousePosition, missionIconPos) < generationParams.MissionIcon.SourceRect.Width * zoom && IsPreferredTooltip(missionIconPos))
if ((CurrentLocation == currentDisplayLocation && CurrentLocation.AvailableMissions.Any(m => m.Locations.Contains(location))) || location.AvailableMissions.Any(m => m.Prefab.Type == MissionType.GoTo))
{
var availableMissions = CurrentLocation.AvailableMissions.Where(m => m.Locations.Contains(location));
tooltip = (new Rectangle(missionIconPos.ToPoint(), new Point(30)), TextManager.Get("mission") + '\n'+ string.Join('\n', availableMissions.Select(m => "- " + m.Name)));
Vector2 missionIconPos = pos + new Vector2(1.35f, 0.35f) * generationParams.LocationIconSize * 0.5f * zoom;
float missionIconScale = 18.0f / generationParams.MissionIcon.SourceRect.Width;
generationParams.MissionIcon.Draw(spriteBatch, missionIconPos, generationParams.IndicatorColor, scale: missionIconScale * zoom);
if (Vector2.Distance(PlayerInput.MousePosition, missionIconPos) < generationParams.MissionIcon.SourceRect.Width * zoom && IsPreferredTooltip(missionIconPos))
{
var availableMissions = CurrentLocation.AvailableMissions.Where(m => m.Locations.Contains(location)).Concat(location.AvailableMissions.Where(m => m.Prefab.Type == MissionType.GoTo)).Distinct();
tooltip = (new Rectangle(missionIconPos.ToPoint(), new Point(30)), TextManager.Get("mission") + '\n'+ string.Join('\n', availableMissions.Select(m => "- " + m.Name)));
}
}
}

View File

@@ -153,7 +153,7 @@ namespace Barotrauma
OnClicked = (button, data) =>
{
Sprite.ReloadXML();
Sprite.ReloadTexture();
Sprite.ReloadTexture(updateAllSprites: true);
return true;
}
};

View File

@@ -89,9 +89,9 @@ namespace Barotrauma.Networking
var fadeOutTime = !orderPrefab.IsIgnoreOrder ? (float?)orderPrefab.FadeOutTime : null;
GameMain.GameSession?.CrewManager?.AddOrder(order, fadeOutTime);
}
else if (orderMessageInfo.TargetCharacter != null)
else
{
orderMessageInfo.TargetCharacter.SetOrder(order, orderOption, orderMessageInfo.Priority, senderCharacter);
orderMessageInfo.TargetCharacter?.SetOrder(order, orderOption, orderMessageInfo.Priority, senderCharacter);
}
}
}

View File

@@ -643,7 +643,7 @@ namespace Barotrauma.Networking
DebugConsole.ThrowError("Error while reading a message from server.", e);
new GUIMessageBox(TextManager.Get("Error"), TextManager.GetWithVariables("MessageReadError", new string[2] { "[message]", "[targetsite]" }, new string[2] { e.Message, e.TargetSite.ToString() }));
Disconnect();
GameMain.MainMenuScreen.Select();
GameMain.ServerListScreen.Select();
return;
}
@@ -659,10 +659,7 @@ namespace Barotrauma.Networking
{
EndVoteTickBox.Visible = serverSettings.Voting.AllowEndVoting && HasSpawned && !(GameMain.GameSession?.GameMode is CampaignMode);
if (respawnManager != null)
{
respawnManager.Update(deltaTime);
}
respawnManager?.Update(deltaTime);
if (updateTimer <= DateTime.Now)
{
@@ -936,9 +933,6 @@ namespace Barotrauma.Networking
}
}
break;
case ServerPacketHeader.RESET_UPGRADES:
campaign?.UpgradeManager.ClientRead(inc);
break;
case ServerPacketHeader.CREW:
campaign?.ClientReadCrew(inc);
break;
@@ -1313,10 +1307,7 @@ namespace Barotrauma.Networking
Client.ReadPermissions(inc, out permissions, out permittedCommands);
Client targetClient = ConnectedClients.Find(c => c.ID == clientID);
if (targetClient != null)
{
targetClient.SetPermissions(permissions, permittedCommands);
}
targetClient?.SetPermissions(permissions, permittedCommands);
if (clientID == myID)
{
SetMyPermissions(permissions, permittedCommands.Select(command => command.names[0]));
@@ -1427,7 +1418,7 @@ namespace Barotrauma.Networking
while (CoroutineManager.IsCoroutineRunning("EndGame"))
{
if (EndCinematic != null) { EndCinematic.Stop(); }
EndCinematic?.Stop();
yield return CoroutineStatus.Running;
}
@@ -2759,6 +2750,8 @@ namespace Barotrauma.Networking
public void Vote(VoteType voteType, object data)
{
if (clientPeer == null) return;
IWriteMessage msg = new WriteOnlyMessage();
msg.Write((byte)ClientPacketHeader.UPDATE_LOBBY);
msg.Write((byte)ClientNetObject.VOTE);

View File

@@ -7,7 +7,102 @@ namespace Barotrauma.Particles
{
class ParticleEmitterProperties : ISerializableEntity
{
public string Name => nameof(ParticleEmitterProperties);
private const float MinValue = int.MinValue,
MaxValue = int.MaxValue;
public string Name => nameof(ParticleEmitter);
private float angleMin, angleMax;
public float AngleMinRad { get; private set; }
public float AngleMaxRad { get; private set; }
[Editable(ValueStep = 1, DecimalCount = 2, MaxValueFloat = 360, MinValueFloat = -360f), Serialize(0f, true)]
public float AngleMin
{
get => angleMin;
set
{
angleMin = value;
AngleMinRad = MathHelper.ToRadians(MathHelper.Clamp(value, -360.0f, 360.0f));
}
}
[Editable(ValueStep = 1, DecimalCount = 2, MaxValueFloat = 360, MinValueFloat = -360f), Serialize(0f, true)]
public float AngleMax
{
get => angleMax;
set
{
angleMax = value;
AngleMaxRad = MathHelper.ToRadians(MathHelper.Clamp(value, -360.0f, 360.0f));
}
}
[Editable(ValueStep = 1, DecimalCount = 2, MaxValueFloat = MaxValue, MinValueFloat = MinValue), Serialize(0f, true)]
public float DistanceMin { get; set; }
[Editable(ValueStep = 1, DecimalCount = 2, MaxValueFloat = MaxValue, MinValueFloat = MinValue), Serialize(0f, true)]
public float DistanceMax { get; set; }
[Editable(ValueStep = 1, DecimalCount = 2, MaxValueFloat = MaxValue, MinValueFloat = MinValue), Serialize(0f, true)]
public float VelocityMin { get; set; }
[Editable(ValueStep = 1, DecimalCount = 2, MaxValueFloat = MaxValue, MinValueFloat = MinValue), Serialize(0f, true)]
public float VelocityMax { get; set; }
[Editable(ValueStep = 1, DecimalCount = 2, MaxValueFloat = MaxValue, MinValueFloat = MinValue), Serialize(1f, true)]
public float ScaleMin { get; set; }
[Editable(ValueStep = 1, DecimalCount = 2, MaxValueFloat = MaxValue, MinValueFloat = MinValue), Serialize(1f, true)]
public float ScaleMax { get; set; }
[Editable(), Serialize("1,1", true)]
public Vector2 ScaleMultiplier { get; set; }
[Editable(ValueStep = 1, DecimalCount = 2, MaxValueFloat = MaxValue, MinValueFloat = MinValue), Serialize(0f, true)]
public float EmitInterval { get; set; }
[Editable, Serialize(0, true)]
public int ParticleAmount { get; set; }
[Editable(ValueStep = 1, DecimalCount = 2, MaxValueFloat = MaxValue, MinValueFloat = 0), Serialize(0f, true)]
public float ParticlesPerSecond { get; set; }
[Editable, Serialize(false, true)]
public bool HighQualityCollisionDetection { get; set; }
[Editable, Serialize(false, true)]
public bool CopyEntityAngle { get; set; }
[Editable, Serialize("1,1,1,1", true)]
public Color ColorMultiplier { get; set; }
[Editable, Serialize(false, true)]
public bool DrawOnTop { get; set; }
[Serialize(0f, true)]
public float Angle
{
get => AngleMin;
set => AngleMin = AngleMax = value;
}
[Serialize(0f, true)]
public float Distance
{
get => DistanceMin;
set => DistanceMin = DistanceMax = value;
}
[Serialize(0f, true)]
public float Velocity
{
get => VelocityMin;
set => VelocityMin = VelocityMax = value;
}
public Dictionary<string, SerializableProperty> SerializableProperties { get; }
public ParticleEmitterProperties(XElement element)
@@ -39,9 +134,9 @@ namespace Barotrauma.Particles
emitTimer += deltaTime * amountMultiplier;
burstEmitTimer -= deltaTime;
if (Prefab.ParticlesPerSecond > 0)
if (Prefab.Properties.ParticlesPerSecond > 0)
{
float emitInterval = 1.0f / Prefab.ParticlesPerSecond;
float emitInterval = 1.0f / Prefab.Properties.ParticlesPerSecond;
while (emitTimer > emitInterval)
{
Emit(position, hullGuess, angle, particleRotation, velocityMultiplier, sizeMultiplier, colorMultiplier, overrideParticle, tracerPoints: tracerPoints);
@@ -50,9 +145,9 @@ namespace Barotrauma.Particles
}
if (burstEmitTimer > 0.0f) { return; }
burstEmitTimer = Prefab.EmitInterval;
for (int i = 0; i < Prefab.ParticleAmount * amountMultiplier; i++)
burstEmitTimer = Prefab.Properties.EmitInterval;
for (int i = 0; i < Prefab.Properties.ParticleAmount * amountMultiplier; i++)
{
Emit(position, hullGuess, angle, particleRotation, velocityMultiplier, sizeMultiplier, colorMultiplier, overrideParticle, tracerPoints: tracerPoints);
}
@@ -60,26 +155,29 @@ namespace Barotrauma.Particles
private void Emit(Vector2 position, Hull hullGuess, float angle, float particleRotation, float velocityMultiplier, float sizeMultiplier, Color? colorMultiplier = null, ParticlePrefab overrideParticle = null, Tuple<Vector2, Vector2> tracerPoints = null)
{
angle += Rand.Range(Prefab.AngleMin, Prefab.AngleMax);
var particlePrefab = overrideParticle ?? Prefab.ParticlePrefab;
if (particlePrefab == null) { return; }
angle += Rand.Range(Prefab.Properties.AngleMinRad, Prefab.Properties.AngleMaxRad);
Vector2 dir = new Vector2((float)Math.Cos(angle), (float)Math.Sin(angle));
Vector2 velocity = dir * Rand.Range(Prefab.VelocityMin, Prefab.VelocityMax) * velocityMultiplier;
position += dir * Rand.Range(Prefab.DistanceMin, Prefab.DistanceMax);
Vector2 velocity = dir * Rand.Range(Prefab.Properties.VelocityMin, Prefab.Properties.VelocityMax) * velocityMultiplier;
position += dir * Rand.Range(Prefab.Properties.DistanceMin, Prefab.Properties.DistanceMax);
var particle = GameMain.ParticleManager.CreateParticle(overrideParticle ?? Prefab.ParticlePrefab, position, velocity, particleRotation, hullGuess, Prefab.DrawOnTop, tracerPoints: tracerPoints);
var particle = GameMain.ParticleManager.CreateParticle(particlePrefab, position, velocity, particleRotation, hullGuess, Prefab.DrawOnTop, tracerPoints: tracerPoints);
if (particle != null)
{
particle.Size *= Rand.Range(Prefab.ScaleMin, Prefab.ScaleMax) * sizeMultiplier;
particle.Size *= Prefab.ScaleMultiplier;
particle.HighQualityCollisionDetection = Prefab.HighQualityCollisionDetection;
if (colorMultiplier.HasValue)
{
particle.ColorMultiplier = colorMultiplier.Value.ToVector4();
}
else if (Prefab.ColorMultiplier != Color.White)
particle.Size *= Rand.Range(Prefab.Properties.ScaleMin, Prefab.Properties.ScaleMax) * sizeMultiplier;
particle.Size *= Prefab.Properties.ScaleMultiplier;
particle.HighQualityCollisionDetection = Prefab.Properties.HighQualityCollisionDetection;
if (colorMultiplier.HasValue)
{
particle.ColorMultiplier = Prefab.ColorMultiplier.ToVector4();
particle.ColorMultiplier = colorMultiplier.Value.ToVector4();
}
else if (Prefab.Properties.ColorMultiplier != Color.White)
{
particle.ColorMultiplier = Prefab.Properties.ColorMultiplier.ToVector4();
}
}
}
@@ -88,9 +186,9 @@ namespace Barotrauma.Particles
{
Rectangle bounds = new Rectangle((int)startPosition.X, (int)startPosition.Y, (int)startPosition.X, (int)startPosition.Y);
for (float angle = Prefab.AngleMin; angle <= Prefab.AngleMax; angle += 0.1f)
for (float angle = Prefab.Properties.AngleMinRad; angle <= Prefab.Properties.AngleMaxRad; angle += 0.1f)
{
Vector2 velocity = new Vector2((float)Math.Cos(angle), (float)Math.Sin(angle)) * Prefab.VelocityMax;
Vector2 velocity = new Vector2((float)Math.Cos(angle), (float)Math.Sin(angle)) * Prefab.Properties.VelocityMax;
Vector2 endPosition = Prefab.ParticlePrefab.CalculateEndPosition(startPosition, velocity);
Vector2 endSize = Prefab.ParticlePrefab.CalculateEndSize();
@@ -103,15 +201,15 @@ namespace Barotrauma.Particles
}
else
{
spriteExtent = Math.Max(spriteExtent, Math.Max(sprite.size.X * endSize.X, sprite.size.Y * endSize.Y));
spriteExtent = Math.Max(spriteExtent, Math.Max(sprite.size.X * endSize.X, sprite.size.Y * endSize.Y));
}
}
bounds = new Rectangle(
(int)Math.Min(bounds.X, endPosition.X - Prefab.DistanceMax - spriteExtent / 2),
(int)Math.Min(bounds.Y, endPosition.Y - Prefab.DistanceMax - spriteExtent / 2),
(int)Math.Max(bounds.X, endPosition.X + Prefab.DistanceMax + spriteExtent / 2),
(int)Math.Max(bounds.Y, endPosition.Y + Prefab.DistanceMax + spriteExtent / 2));
(int)Math.Min(bounds.X, endPosition.X - Prefab.Properties.DistanceMax - spriteExtent / 2),
(int)Math.Min(bounds.Y, endPosition.Y - Prefab.Properties.DistanceMax - spriteExtent / 2),
(int)Math.Max(bounds.X, endPosition.X + Prefab.Properties.DistanceMax + spriteExtent / 2),
(int)Math.Max(bounds.Y, endPosition.Y + Prefab.Properties.DistanceMax + spriteExtent / 2));
}
bounds = new Rectangle(bounds.X, bounds.Y, bounds.Width - bounds.X, bounds.Height - bounds.Y);
@@ -121,9 +219,7 @@ namespace Barotrauma.Particles
}
class ParticleEmitterPrefab
{
public readonly string Name;
{
private string particlePrefabName;
private ParticlePrefab particlePrefab;
@@ -134,105 +230,30 @@ namespace Barotrauma.Particles
if (particlePrefab == null && particlePrefabName != null)
{
particlePrefab = GameMain.ParticleManager?.FindPrefab(particlePrefabName);
if (particlePrefab == null) { particlePrefabName = null; }
if (particlePrefab == null)
{
DebugConsole.ThrowError($"Failed to find particle prefab \"{particlePrefabName}\".");
particlePrefabName = null;
}
}
return particlePrefab;
}
}
public readonly float AngleMin, AngleMax;
public readonly ParticleEmitterProperties Properties;
public readonly float DistanceMin, DistanceMax;
public readonly float VelocityMin, VelocityMax;
public readonly float ScaleMin, ScaleMax;
public readonly Vector2 ScaleMultiplier;
public readonly float EmitInterval;
public readonly int ParticleAmount;
public readonly float ParticlesPerSecond;
public readonly bool HighQualityCollisionDetection;
public readonly bool CopyEntityAngle;
public readonly Color ColorMultiplier;
public bool DrawOnTop => forceDrawOnTop || ParticlePrefab.DrawOnTop;
private readonly bool forceDrawOnTop;
public bool DrawOnTop => Properties.DrawOnTop || ParticlePrefab.DrawOnTop;
public ParticleEmitterPrefab(XElement element)
{
Name = element.Name.ToString();
Properties = new ParticleEmitterProperties(element);
particlePrefabName = element.GetAttributeString("particle", "");
}
if (element.Attribute("startrotation") == null)
{
AngleMin = element.GetAttributeFloat("anglemin", 0.0f);
AngleMax = element.GetAttributeFloat("anglemax", 0.0f);
}
else
{
AngleMin = element.GetAttributeFloat("angle", 0.0f);
AngleMax = AngleMin;
}
AngleMin = MathHelper.ToRadians(MathHelper.Clamp(AngleMin, -360.0f, 360.0f));
AngleMax = MathHelper.ToRadians(MathHelper.Clamp(AngleMax, -360.0f, 360.0f));
if (element.Attribute("scalemin") == null)
{
ScaleMin = 1.0f;
ScaleMax = 1.0f;
}
else
{
ScaleMin = element.GetAttributeFloat("scalemin", 1.0f);
ScaleMax = Math.Max(ScaleMin, element.GetAttributeFloat("scalemax", 1.0f));
}
ScaleMultiplier = element.GetAttributeVector2("scalemultiplier", Vector2.One);
if (element.Attribute("distance") == null)
{
DistanceMin = element.GetAttributeFloat("distancemin", 0.0f);
DistanceMax = element.GetAttributeFloat("distancemax", 0.0f);
}
else
{
DistanceMin = DistanceMax = element.GetAttributeFloat("distance", 0.0f);
}
if (DistanceMax < DistanceMin)
{
var temp = DistanceMin;
DistanceMin = DistanceMax;
DistanceMax = temp;
}
if (element.Attribute("velocity") == null)
{
VelocityMin = element.GetAttributeFloat("velocitymin", 0.0f);
VelocityMax = element.GetAttributeFloat("velocitymax", 0.0f);
}
else
{
VelocityMin = VelocityMax = element.GetAttributeFloat("velocity", 0.0f);
}
if (VelocityMax < VelocityMin)
{
var temp = VelocityMin;
VelocityMin = VelocityMax;
VelocityMax = temp;
}
EmitInterval = element.GetAttributeFloat("emitinterval", 0.0f);
ParticlesPerSecond = element.GetAttributeFloat("particlespersecond", 0);
ParticleAmount = element.GetAttributeInt("particleamount", 0);
HighQualityCollisionDetection = element.GetAttributeBool("highqualitycollisiondetection", false);
CopyEntityAngle = element.GetAttributeBool("copyentityangle", false);
forceDrawOnTop = element.GetAttributeBool("drawontop", false);
ColorMultiplier = element.GetAttributeColor("colormultiplier", Color.White);
public ParticleEmitterPrefab(ParticlePrefab prefab, ParticleEmitterProperties properties)
{
Properties = properties;
particlePrefab = prefab;
}
}
}

View File

@@ -51,9 +51,18 @@ namespace Barotrauma
CreateUI(container);
campaign.Map.OnLocationSelected += SelectLocation;
campaign.Map.OnMissionSelected += (connection, mission) =>
campaign.Map.OnMissionsSelected += (connection, missions) =>
{
missionList?.Select(mission);
if (missionList?.Content != null)
{
foreach (GUIComponent missionElement in missionList.Content.Children)
{
if (missionElement.FindChild(c => c is GUITickBox, recursive: true) is GUITickBox tickBox)
{
tickBox.Selected = missions.Contains(tickBox.UserData as Mission);
}
}
}
};
}
@@ -436,6 +445,16 @@ namespace Barotrauma
{
Spacing = (int)(5 * GUI.yScale)
};
missionList.OnSelected = (GUIComponent selected, object userdata) =>
{
var tickBox = selected.FindChild(c => c is GUITickBox, recursive: true) as GUITickBox;
if (GUI.MouseOn == tickBox) { return false; }
if (tickBox != null)
{
tickBox.Selected = !tickBox.Selected;
}
return true;
};
SelectedLevel = connection?.LevelData;
Location currentDisplayLocation = Campaign.GetCurrentDisplayLocation();
@@ -444,9 +463,6 @@ namespace Barotrauma
List<Mission> availableMissions = currentDisplayLocation.GetMissionsInConnection(connection).ToList();
if (!availableMissions.Contains(null)) { availableMissions.Insert(0, null); }
Mission selectedMission = currentDisplayLocation.SelectedMission != null && availableMissions.Contains(currentDisplayLocation.SelectedMission) ?
currentDisplayLocation.SelectedMission : null;
missionList.Content.ClearChildren();
foreach (Mission mission in availableMissions)
@@ -458,53 +474,74 @@ namespace Barotrauma
var missionTextContent = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.9f), missionPanel.RectTransform, Anchor.Center))
{
Stretch = true,
CanBeFocused = true
CanBeFocused = true,
AbsoluteSpacing = GUI.IntScale(5)
};
var missionName = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform), mission?.Name ?? TextManager.Get("NoMission"), font: GUI.SubHeadingFont, wrap: true);
// missionName.RectTransform.MinSize = new Point(0, (int)(missionName.Rect.Height * 1.5f));
if (mission != null)
{
if (MapGenerationParams.Instance?.MissionIcon != null)
{
var tickBox = new GUITickBox(new RectTransform(Vector2.One * 0.9f, missionName.RectTransform, anchor: Anchor.CenterLeft, scaleBasis: ScaleBasis.Smallest) { AbsoluteOffset = new Point((int)missionName.Padding.X, 0) }, label: string.Empty)
{
var icon = new GUIImage(new RectTransform(Vector2.One * 0.9f, missionName.RectTransform, anchor: Anchor.CenterLeft, scaleBasis: ScaleBasis.Smallest) { AbsoluteOffset = new Point((int)missionName.Padding.X, 0) },
MapGenerationParams.Instance.MissionIcon, scaleToFit: true)
UserData = mission,
Selected = Campaign.Map.CurrentLocation?.SelectedMissions.Contains(mission) ?? false
};
tickBox.RectTransform.MinSize = new Point(tickBox.Rect.Height, 0);
tickBox.RectTransform.IsFixedSize = true;
if (Campaign.AllowedToManageCampaign())
{
tickBox.OnSelected += (GUITickBox tb) =>
{
Color = MapGenerationParams.Instance.IndicatorColor * 0.5f,
SelectedColor = MapGenerationParams.Instance.IndicatorColor,
HoverColor = Color.Lerp(MapGenerationParams.Instance.IndicatorColor, Color.White, 0.5f)
};
icon.RectTransform.IsFixedSize = true;
GUILayoutGroup difficultyIndicatorGroup = null;
if (mission.Difficulty.HasValue)
{
difficultyIndicatorGroup = new GUILayoutGroup(new RectTransform(Vector2.One * 0.9f, missionName.RectTransform, anchor: Anchor.CenterRight, scaleBasis: ScaleBasis.Smallest) { AbsoluteOffset = new Point((int)missionName.Padding.Z, 0) },
isHorizontal: true, childAnchor: Anchor.CenterRight)
if (tb.Selected)
{
AbsoluteSpacing = 1,
UserData = "difficulty"
};
var difficultyColor = mission.GetDifficultyColor();
for (int i = 0; i < mission.Difficulty; i++)
{
new GUIImage(new RectTransform(Vector2.One, difficultyIndicatorGroup.RectTransform, scaleBasis: ScaleBasis.Smallest) { IsFixedSize = true }, "DifficultyIndicator", scaleToFit: true)
{
Color = difficultyColor * 0.5f,
SelectedColor = difficultyColor,
HoverColor = Color.Lerp(difficultyColor, Color.White, 0.5f)
};
Campaign.Map.CurrentLocation.SelectMission(mission);
}
}
float extraPadding = 0.5f * icon.Rect.Width;
float extraZPadding = difficultyIndicatorGroup != null ? mission.Difficulty.Value * (difficultyIndicatorGroup.Children.First().Rect.Width + difficultyIndicatorGroup.AbsoluteSpacing) : 0;
missionName.Padding = new Vector4(missionName.Padding.X + icon.Rect.Width + extraPadding,
missionName.Padding.Y,
missionName.Padding.Z + extraZPadding + extraPadding,
missionName.Padding.W);
missionName.CalculateHeightFromText();
else
{
Campaign.Map.CurrentLocation.DeselectMission(mission);
}
if ((Campaign is MultiPlayerCampaign multiPlayerCampaign) && !multiPlayerCampaign.SuppressStateSending &&
Campaign.AllowedToManageCampaign())
{
GameMain.Client?.SendCampaignState();
}
return true;
};
}
GUILayoutGroup difficultyIndicatorGroup = null;
if (mission.Difficulty.HasValue)
{
difficultyIndicatorGroup = new GUILayoutGroup(new RectTransform(Vector2.One * 0.9f, missionName.RectTransform, anchor: Anchor.CenterRight, scaleBasis: ScaleBasis.Smallest) { AbsoluteOffset = new Point((int)missionName.Padding.Z, 0) },
isHorizontal: true, childAnchor: Anchor.CenterRight)
{
AbsoluteSpacing = 1,
UserData = "difficulty"
};
var difficultyColor = mission.GetDifficultyColor();
for (int i = 0; i < mission.Difficulty; i++)
{
new GUIImage(new RectTransform(Vector2.One, difficultyIndicatorGroup.RectTransform, scaleBasis: ScaleBasis.Smallest) { IsFixedSize = true }, "DifficultyIndicator", scaleToFit: true)
{
Color = difficultyColor,
SelectedColor = difficultyColor,
HoverColor = difficultyColor
};
}
}
float extraPadding = 0;// 0.8f * tickBox.Rect.Width;
float extraZPadding = difficultyIndicatorGroup != null ? mission.Difficulty.Value * (difficultyIndicatorGroup.Children.First().Rect.Width + difficultyIndicatorGroup.AbsoluteSpacing) : 0;
missionName.Padding = new Vector4(missionName.Padding.X + tickBox.Rect.Width * 1.2f + extraPadding,
missionName.Padding.Y,
missionName.Padding.Z + extraZPadding + extraPadding,
missionName.Padding.W);
missionName.CalculateHeightFromText();
//spacing
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform) { MinSize = new Point(0, GUI.IntScale(10)) }, style: null);
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform), mission.GetMissionRewardText(Submarine.MainSub), wrap: true, parseRichText: true);
string reputationText = mission.GetReputationRewardText(mission.Locations[0]);
@@ -512,14 +549,14 @@ namespace Barotrauma
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform), mission.Description, wrap: true, parseRichText: true);
}
missionPanel.RectTransform.MinSize = new Point(0, (int)(missionTextContent.Children.Sum(c => c.Rect.Height) / missionTextContent.RectTransform.RelativeSize.Y) + GUI.IntScale(20));
missionPanel.RectTransform.MinSize = new Point(0, (int)(missionTextContent.Children.Sum(c => c.Rect.Height + missionTextContent.AbsoluteSpacing) / missionTextContent.RectTransform.RelativeSize.Y) + GUI.IntScale(0));
foreach (GUIComponent child in missionTextContent.Children)
{
var textBlock = child as GUITextBlock;
textBlock.Color = textBlock.SelectedColor = textBlock.HoverColor = Color.Transparent;
textBlock.SelectedTextColor = textBlock.TextColor;
textBlock.TextColor *= 0.5f;
textBlock.HoverTextColor = textBlock.TextColor;
if (child is GUITextBlock textBlock)
{
textBlock.Color = textBlock.SelectedColor = textBlock.HoverColor = Color.Transparent;
textBlock.SelectedTextColor = textBlock.HoverTextColor = textBlock.TextColor;
}
}
missionPanel.OnAddedToGUIUpdateList = (c) =>
{
@@ -538,28 +575,10 @@ namespace Barotrauma
};
}
}
missionList.Select(selectedMission);
if (prevSelectedLocation == selectedLocation)
{
missionList.BarScroll = prevMissionListScroll;
}
if (Campaign.AllowedToManageCampaign())
{
missionList.OnSelected = (component, userdata) =>
{
Mission mission = userdata as Mission;
if (Campaign.Map.CurrentLocation.SelectedMission == mission) { return false; }
Campaign.Map.CurrentLocation.SelectedMission = mission;
//RefreshMissionInfo(mission);
if ((Campaign is MultiPlayerCampaign multiPlayerCampaign) && !multiPlayerCampaign.SuppressStateSending &&
Campaign.AllowedToManageCampaign())
{
GameMain.Client?.SendCampaignState();
}
return true;
};
}
}
StartButton = new GUIButton(new RectTransform(new Vector2(0.5f, 0.1f), content.RectTransform),
@@ -567,7 +586,8 @@ namespace Barotrauma
{
OnClicked = (GUIButton btn, object obj) =>
{
if (missionList.Content.Children.Any(c => c.UserData is Mission) && !(missionList.SelectedData is Mission))
if (missionList.Content.FindChild(c => c is GUITickBox tickBox && tickBox.Selected, recursive: true) == null &&
missionList.Content.Children.Any(c => c.UserData is Mission))
{
var noMissionVerification = new GUIMessageBox(string.Empty, TextManager.Get("nomissionprompt"), new string[] { TextManager.Get("yes"), TextManager.Get("no") });
noMissionVerification.Buttons[0].OnClicked = (btn, userdata) =>

View File

@@ -969,6 +969,16 @@ namespace Barotrauma
UserData = missionType,
};
if (MissionPrefab.HiddenMissionClasses.Contains(missionType))
{
missionTypeTickBoxes[index] = new GUITickBox(new RectTransform(Vector2.One, frame.RectTransform), string.Empty)
{
UserData = (int)missionType,
Visible = false,
CanBeFocused = false
};
continue;
}
missionTypeTickBoxes[index] = new GUITickBox(new RectTransform(Vector2.One, frame.RectTransform),
TextManager.Get("MissionType." + missionType.ToString()))
{
@@ -3214,7 +3224,12 @@ namespace Barotrauma
{
for (int i = 0; i < missionTypeTickBoxes.Length; i++)
{
MissionType missionType = (MissionType)((int)missionTypeTickBoxes[i].UserData);
MissionType missionType = (MissionType)(int)missionTypeTickBoxes[i].UserData;
if (MissionPrefab.HiddenMissionClasses.Contains(missionType))
{
missionTypeTickBoxes[i].Parent.Visible = false;
continue;
}
if (SelectedMode == GameModePreset.Mission)
{
missionTypeTickBoxes[i].Parent.Visible = MissionPrefab.CoOpMissionClasses.ContainsKey(missionType);

View File

@@ -18,55 +18,6 @@ namespace Barotrauma
{
class ParticleEditorScreen : EditorScreen
{
class Emitter : ISerializableEntity
{
public float EmitTimer;
public float BurstTimer;
[Editable, Serialize("0.0,360.0", false)]
public Vector2 AngleRange { get; private set; }
[Editable, Serialize("0.0,0.0", false)]
public Vector2 VelocityRange { get; private set; }
[Editable, Serialize("1.0,1.0", false)]
public Vector2 ScaleRange { get; private set; }
[Editable, Serialize(0, false)]
public int ParticleBurstAmount { get; private set; }
[Editable, Serialize(1.0f, false)]
public float ParticleBurstInterval { get; private set; }
[Editable, Serialize(1.0f, false)]
public float ParticlesPerSecond { get; private set; }
public string Name
{
get
{
return TextManager.Get("particleeditor.emitter");
}
}
public Dictionary<string, SerializableProperty> SerializableProperties
{
get;
private set;
}
public Emitter()
{
ScaleRange = Vector2.One;
AngleRange = new Vector2(0.0f, 360.0f);
ParticleBurstAmount = 1;
ParticleBurstInterval = 1.0f;
SerializableProperties = SerializableProperty.GetProperties(this);
}
}
private GUIComponent rightPanel, leftPanel;
private GUIListBox prefabList;
private GUITextBox filterBox;
@@ -74,7 +25,17 @@ namespace Barotrauma
private ParticlePrefab selectedPrefab;
private Emitter emitter;
private readonly ParticleEmitterProperties emitterProperties = new ParticleEmitterProperties(null)
{
ScaleMax = 1f,
ScaleMin = 1f,
AngleMax = 360f,
AngleMin = 0,
ParticlesPerSecond = 1f
};
private ParticleEmitterPrefab emitterPrefab;
private ParticleEmitter emitter;
private readonly Camera cam;
@@ -128,8 +89,8 @@ namespace Barotrauma
}
};
var serializeToClipBoardButton = new GUIButton(new RectTransform(new Vector2(1.0f, 0.03f), paddedRightPanel.RectTransform),
TextManager.Get("editor.copytoclipboard"))
new GUIButton(new RectTransform(new Vector2(1.0f, 0.03f), paddedRightPanel.RectTransform),
TextManager.Get("ParticleEditor.CopyPrefabToClipboard"))
{
OnClicked = (btn, obj) =>
{
@@ -138,11 +99,18 @@ namespace Barotrauma
}
};
emitter = new Emitter();
var emitterEditorContainer = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.25f), paddedRightPanel.RectTransform), style: null);
var emitterEditor = new SerializableEntityEditor(emitterEditorContainer.RectTransform, emitter, false, true, elementHeight: 20, titleFont: GUI.SubHeadingFont);
emitterEditor.RectTransform.RelativeSize = Vector2.One;
emitterEditorContainer.RectTransform.Resize(new Point(emitterEditorContainer.RectTransform.NonScaledSize.X, emitterEditor.ContentHeight), false);
new GUIButton(new RectTransform(new Vector2(1.0f, 0.03f), paddedRightPanel.RectTransform),
TextManager.Get("ParticleEditor.CopyEmitterToClipboard"))
{
OnClicked = (btn, obj) =>
{
SerializeEmitterToClipboard();
return true;
}
};
var emitterListBox = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.25f), paddedRightPanel.RectTransform));
new SerializableEntityEditor(emitterListBox.Content.RectTransform, emitterProperties, false, true, elementHeight: 20, titleFont: GUI.SubHeadingFont);
var listBox = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.6f), paddedRightPanel.RectTransform));
@@ -163,7 +131,10 @@ namespace Barotrauma
prefabList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.8f), paddedLeftPanel.RectTransform));
prefabList.OnSelected += (GUIComponent component, object obj) =>
{
cam.Position = Vector2.Zero;
selectedPrefab = obj as ParticlePrefab;
emitterPrefab = new ParticleEmitterPrefab(selectedPrefab, emitterProperties);
emitter = new ParticleEmitter(emitterPrefab);
listBox.ClearChildren();
new SerializableEntityEditor(listBox.Content.RectTransform, selectedPrefab, false, true, elementHeight: 20, titleFont: GUI.SubHeadingFont);
//listBox.Content.RectTransform.NonScaledSize = particlePrefabEditor.RectTransform.NonScaledSize;
@@ -204,19 +175,6 @@ namespace Barotrauma
}
}
private void Emit(Vector2 position)
{
float angle = MathHelper.ToRadians(Rand.Range(emitter.AngleRange.X, emitter.AngleRange.Y));
Vector2 velocity = new Vector2((float)Math.Cos(angle), (float)Math.Sin(angle)) * Rand.Range(emitter.VelocityRange.X, emitter.VelocityRange.Y);
var particle = GameMain.ParticleManager.CreateParticle(selectedPrefab, position, velocity, 0.0f);
if (particle != null)
{
particle.Size *= Rand.Range(emitter.ScaleRange.X, emitter.ScaleRange.Y);
}
}
private void FilterEmitters(string text)
{
if (string.IsNullOrWhiteSpace(text))
@@ -269,9 +227,34 @@ namespace Barotrauma
Barotrauma.IO.Validation.SkipValidationInDebugBuilds = false;
}
private void SerializeEmitterToClipboard()
{
XElement element = new XElement(nameof(ParticleEmitter));
if (selectedPrefab is { } prefab)
{
element.Add(new XAttribute("particle", prefab.Identifier));
}
SerializableProperty.SerializeProperties(emitterProperties, element, saveIfDefault: false);
StringBuilder sb = new StringBuilder();
System.Xml.XmlWriterSettings settings = new System.Xml.XmlWriterSettings
{
OmitXmlDeclaration = true
};
using (var writer = System.Xml.XmlWriter.Create(sb, settings))
{
element.WriteTo(writer);
writer.Flush();
}
Clipboard.SetText(sb.ToString());
}
private void SerializeToClipboard(ParticlePrefab prefab)
{
#if WINDOWS
if (prefab == null) { return; }
System.Xml.XmlWriterSettings settings = new System.Xml.XmlWriterSettings
@@ -314,7 +297,6 @@ namespace Barotrauma
}
Clipboard.SetText(sb.ToString());
#endif
}
public override void Update(double deltaTime)
@@ -331,31 +313,9 @@ namespace Barotrauma
CreateContextMenu();
}
if (selectedPrefab != null)
if (selectedPrefab != null && emitter != null)
{
emitter.EmitTimer += (float)deltaTime;
emitter.BurstTimer += (float)deltaTime;
if (emitter.ParticlesPerSecond > 0)
{
float emitInterval = 1.0f / emitter.ParticlesPerSecond;
while (emitter.EmitTimer > emitInterval)
{
Emit(Vector2.Zero);
emitter.EmitTimer -= emitInterval;
}
}
if (emitter.BurstTimer > emitter.ParticleBurstInterval)
{
for (int i = 0; i < emitter.ParticleBurstAmount; i++)
{
Emit(Vector2.Zero);
}
emitter.BurstTimer = 0.0f;
}
emitter.Emit((float) deltaTime, Vector2.Zero);
}
GameMain.ParticleManager.Update((float)deltaTime);

View File

@@ -365,7 +365,8 @@ namespace Barotrauma
"FlowerSprite",
"DecorativeSprite",
"BarrelSprite",
"RailSprite"
"RailSprite",
"SchematicSprite"
};
foreach (string spriteElementName in spriteElementNames)

View File

@@ -3200,6 +3200,8 @@ namespace Barotrauma
Color newColor = SetColor(null);
if (!IsSubEditor()) { return true; }
Dictionary<object, List<ISerializableEntity>> oldProperties = new Dictionary<object, List<ISerializableEntity>>();
foreach (var (sEntity, color, _) in entities)
@@ -3969,9 +3971,9 @@ namespace Barotrauma
{
loadFrame.AddToGUIUpdateList();
}
else if (saveFrame != null)
else
{
saveFrame.AddToGUIUpdateList();
saveFrame?.AddToGUIUpdateList();
}
}

View File

@@ -273,8 +273,8 @@ namespace Barotrauma
public SerializableEntityEditor(RectTransform parent, ISerializableEntity entity, bool inGame, bool showName, string style = "", int elementHeight = 24, ScalableFont titleFont = null)
: this(parent, entity, inGame ?
SerializableProperty.GetProperties<InGameEditable>(entity).Union(SerializableProperty.GetProperties<ConditionallyEditable>(entity).Where(p => p.GetAttribute<ConditionallyEditable>()?.IsEditable() ?? false))
: SerializableProperty.GetProperties<Editable>(entity), showName, style, elementHeight, titleFont)
SerializableProperty.GetProperties<InGameEditable>(entity).Union(SerializableProperty.GetProperties<ConditionallyEditable>(entity).Where(p => p.GetAttribute<ConditionallyEditable>()?.IsEditable(entity) ?? false))
: SerializableProperty.GetProperties<Editable>(entity).Where(p => p.GetAttribute<ConditionallyEditable>()?.IsEditable(entity) ?? true), showName, style, elementHeight, titleFont)
{
}

View File

@@ -826,36 +826,58 @@ namespace Barotrauma
IEnumerable<BackgroundMusic> suitableMusic = GetSuitableMusicClips(currentMusicType, currentIntensity);
int mainTrackIndex = 0;
if (suitableMusic.Count() == 0)
{
targetMusic[0] = null;
targetMusic[mainTrackIndex] = null;
}
//switch the music if nothing playing atm or the currently playing clip is not suitable anymore
else if (targetMusic[0] == null || currentMusic[0] == null || !currentMusic[0].IsPlaying() || !suitableMusic.Any(m => m.File == currentMusic[0].Filename))
else if (targetMusic[mainTrackIndex] == null || currentMusic[mainTrackIndex] == null || !currentMusic[mainTrackIndex].IsPlaying() || !suitableMusic.Any(m => m.File == currentMusic[mainTrackIndex].Filename))
{
if (currentMusicType == "default")
{
if (previousDefaultMusic == null)
{
targetMusic[0] = previousDefaultMusic = suitableMusic.GetRandom();
targetMusic[mainTrackIndex] = previousDefaultMusic = suitableMusic.GetRandom();
}
else
{
targetMusic[0] = previousDefaultMusic;
targetMusic[mainTrackIndex] = previousDefaultMusic;
}
}
else
{
targetMusic[0] = suitableMusic.GetRandom();
targetMusic[mainTrackIndex] = suitableMusic.GetRandom();
}
}
if (Level.Loaded?.Type == LevelData.LevelType.LocationConnection)
{
// Find background noise loop for the current biome
IEnumerable<BackgroundMusic> suitableNoiseLoops = Screen.Selected == GameMain.GameScreen ?
GetSuitableMusicClips(Level.Loaded.LevelData?.Biome?.Identifier, currentIntensity) :
Enumerable.Empty<BackgroundMusic>();
int noiseLoopIndex = 1;
if (suitableNoiseLoops.Count() == 0)
{
targetMusic[noiseLoopIndex] = null;
}
// Switch the noise loop if nothing playing atm or the currently playing clip is not suitable anymore
else if (targetMusic[noiseLoopIndex] == null || currentMusic[noiseLoopIndex] == null || !suitableNoiseLoops.Any(m => m.File == currentMusic[noiseLoopIndex].Filename))
{
targetMusic[noiseLoopIndex] = suitableNoiseLoops.GetRandom();
}
}
//get the appropriate intensity layers for current situation
IEnumerable<BackgroundMusic> suitableIntensityMusic = Screen.Selected == GameMain.GameScreen ?
GetSuitableMusicClips("intensity", currentIntensity) :
Enumerable.Empty<BackgroundMusic>();
for (int i = 1; i < MaxMusicChannels; i++)
int intensityTrackStartIndex = 2;
for (int i = intensityTrackStartIndex; i < MaxMusicChannels; i++)
{
//disable targetmusics that aren't suitable anymore
if (targetMusic[i] != null && !suitableIntensityMusic.Any(m => m.File == targetMusic[i].File))
@@ -869,7 +891,7 @@ namespace Barotrauma
//already playing, do nothing
if (targetMusic.Any(m => m != null && m.File == intensityMusic.File)) { continue; }
for (int i = 1; i < MaxMusicChannels; i++)
for (int i = intensityTrackStartIndex; i < MaxMusicChannels; i++)
{
if (targetMusic[i] == null)
{
@@ -877,7 +899,7 @@ namespace Barotrauma
break;
}
}
}
}
updateMusicTimer = UpdateMusicInterval;
}

View File

@@ -114,10 +114,7 @@ namespace Barotrauma.Sounds
{
lock (mutex)
{
if (soundChannel != null)
{
soundChannel.Dispose();
}
soundChannel?.Dispose();
base.Dispose();
}
}

View File

@@ -121,7 +121,7 @@ namespace Barotrauma
}
}
public void ReloadTexture(bool updateAllSprites = false) => ReloadTexture(updateAllSprites ? LoadedSprites.Where(s => s.Texture == texture) : new Sprite[] { this });
public void ReloadTexture(bool updateAllSprites = false) => ReloadTexture(updateAllSprites ? LoadedSprites.Where(s => s.texture == texture).ToList() : new List<Sprite>() { this });
public void ReloadTexture(IEnumerable<Sprite> spritesToUpdate)
{

View File

@@ -55,8 +55,6 @@ namespace Barotrauma
partial void ApplyProjSpecific(float deltaTime, Entity entity, IEnumerable<ISerializableEntity> targets, Hull hull, Vector2 worldPosition, bool playSound)
{
if (entity == null) { return; }
if (playSound)
{
PlaySound(entity, hull, worldPosition);
@@ -66,7 +64,7 @@ namespace Barotrauma
{
float angle = 0.0f;
float particleRotation = 0.0f;
if (emitter.Prefab.CopyEntityAngle)
if (emitter.Prefab.Properties.CopyEntityAngle)
{
Limb targetLimb = null;
if (entity is Item item && item.body != null)

View File

@@ -215,15 +215,10 @@ namespace Barotrauma
}
else
{
DebugConsole.NewMessage($"Could not compress a texture because the dimensions aren't a multiple of 4 (path: {path ?? "null"}, size: {width}x{height})", Color.Orange);
DebugConsole.AddWarning($"Could not compress a texture because the dimensions aren't a multiple of 4 (path: {path ?? "null"}, size: {width}x{height})");
}
}
if (((width & 0x03) != 0) || ((height & 0x03) != 0))
{
DebugConsole.AddWarning($"Cannot compress a texture because the dimensions are not a multiple of 4 (path: {path ?? "null"}, size: {width}x{height})");
}
Texture2D tex = null;
CrossThread.RequestExecutionOnMainThread(() =>
{

View File

@@ -6,7 +6,7 @@
<RootNamespace>Barotrauma</RootNamespace>
<Authors>FakeFish, Undertow Games</Authors>
<Product>Barotrauma</Product>
<Version>0.1400.0.0</Version>
<Version>0.1400.1.0</Version>
<Copyright>Copyright © FakeFish 2018-2020</Copyright>
<Platforms>AnyCPU;x64</Platforms>
<AssemblyName>Barotrauma</AssemblyName>

View File

@@ -6,7 +6,7 @@
<RootNamespace>Barotrauma</RootNamespace>
<Authors>FakeFish, Undertow Games</Authors>
<Product>Barotrauma</Product>
<Version>0.1400.0.0</Version>
<Version>0.1400.1.0</Version>
<Copyright>Copyright © FakeFish 2018-2020</Copyright>
<Platforms>AnyCPU;x64</Platforms>
<AssemblyName>Barotrauma</AssemblyName>

View File

@@ -6,7 +6,7 @@
<RootNamespace>Barotrauma</RootNamespace>
<Authors>FakeFish, Undertow Games</Authors>
<Product>Barotrauma</Product>
<Version>0.1400.0.0</Version>
<Version>0.1400.1.0</Version>
<Copyright>Copyright © FakeFish 2018-2020</Copyright>
<Platforms>AnyCPU;x64</Platforms>
<AssemblyName>Barotrauma</AssemblyName>

View File

@@ -6,7 +6,7 @@
<RootNamespace>Barotrauma</RootNamespace>
<Authors>FakeFish, Undertow Games</Authors>
<Product>Barotrauma Dedicated Server</Product>
<Version>0.1400.0.0</Version>
<Version>0.1400.1.0</Version>
<Copyright>Copyright © FakeFish 2018-2020</Copyright>
<Platforms>AnyCPU;x64</Platforms>
<AssemblyName>DedicatedServer</AssemblyName>

View File

@@ -6,7 +6,7 @@
<RootNamespace>Barotrauma</RootNamespace>
<Authors>FakeFish, Undertow Games</Authors>
<Product>Barotrauma Dedicated Server</Product>
<Version>0.1400.0.0</Version>
<Version>0.1400.1.0</Version>
<Copyright>Copyright © FakeFish 2018-2020</Copyright>
<Platforms>AnyCPU;x64</Platforms>
<AssemblyName>DedicatedServer</AssemblyName>

View File

@@ -356,8 +356,12 @@ namespace Barotrauma
int orderIndex = Order.PrefabList.IndexOf(orderPrefab);
msg.WriteRangedInteger(orderIndex, 0, Order.PrefabList.Count);
if (!orderPrefab.HasOptions) { break; }
int optionIndex = orderPrefab.Options.IndexOf(currentOrderInfo.Value.OrderOption);
msg.WriteRangedInteger(optionIndex, 0, orderPrefab.Options.Length);
int optionIndex = orderPrefab.AllOptions.IndexOf(currentOrderInfo.Value.OrderOption);
if (optionIndex == -1)
{
DebugConsole.AddWarning($"Error while writing order data. Order option \"{(currentOrderInfo.Value.OrderOption ?? null)}\" not found in the order prefab \"{orderPrefab.Name}\".");
}
msg.WriteRangedInteger(optionIndex, -1, orderPrefab.AllOptions.Length);
}
else if (type == 2)
{
@@ -381,6 +385,13 @@ namespace Barotrauma
break;
case NetEntityEvent.Type.AddToCrew:
msg.WriteRangedInteger(9, min, max);
msg.Write((byte)(CharacterTeamType)extraData[1]); // team id
ushort[] inventoryItemIDs = (ushort[])extraData[2];
msg.Write((ushort)inventoryItemIDs.Length);
for (int i = 0; i < inventoryItemIDs.Length; i++)
{
msg.Write(inventoryItemIDs[i]);
}
break;
default:
DebugConsole.ThrowError("Invalid NetworkEvent type for entity " + ToString() + " (" + (NetEntityEvent.Type)extraData[0] + ")");

View File

@@ -1,5 +1,7 @@
using Barotrauma.Networking;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Barotrauma
{
@@ -15,9 +17,45 @@ namespace Barotrauma
private static readonly Dictionary<Client, ConversationAction> lastActiveAction = new Dictionary<Client, ConversationAction>();
private readonly HashSet<Client> targetClients = new HashSet<Client>();
private readonly Dictionary<Client, DateTime> ignoredClients = new Dictionary<Client, DateTime>();
public IEnumerable<Client> TargetClients
{
get { return targetClients; }
get
{
UpdateIgnoredClients();
return targetClients.Where(c => !ignoredClients.ContainsKey(c));
}
}
private void UpdateIgnoredClients()
{
if (ignoredClients.Any())
{
HashSet<Client> clientsToRemove = null;
foreach (var k in ignoredClients.Keys)
{
if (ignoredClients[k] < DateTime.Now)
{
clientsToRemove ??= new HashSet<Client>();
clientsToRemove.Add(k);
}
}
if (!(clientsToRemove is null))
{
foreach (var k in clientsToRemove)
{
ignoredClients.Remove(k);
}
}
}
}
public void IgnoreClient(Client c, float seconds)
{
if (!ignoredClients.ContainsKey(c)) { ignoredClients.Add(c, DateTime.Now); }
ignoredClients[c] = DateTime.Now + TimeSpan.FromSeconds(seconds);
Reset();
}
private bool IsBlockedByAnotherConversation(IEnumerable<Entity> targets)

View File

@@ -28,7 +28,14 @@ namespace Barotrauma
continue;
}
convAction.SelectedOption = selectedOption;
if (selectedOption == byte.MaxValue)
{
convAction.IgnoreClient(sender, 3f);
}
else
{
convAction.SelectedOption = selectedOption;
}
return;
}
}

View File

@@ -1,16 +1,20 @@
using Barotrauma.Networking;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Barotrauma
{
partial class AbandonedOutpostMission : Mission
{
private readonly List<Item> spawnedItems = new List<Item>();
public override void ServerWriteInitial(IWriteMessage msg, Client c)
{
if (characters.Count == 0)
msg.Write((ushort)spawnedItems.Count);
foreach (Item item in spawnedItems)
{
throw new InvalidOperationException("Server attempted to write AbandonedOutpostMission data when no characters had been spawned.");
item.WriteSpawnData(msg, item.ID, Entity.NullEntityID, 0);
}
msg.Write((byte)characters.Count);

View File

@@ -21,7 +21,7 @@ namespace Barotrauma
}
}
public override void Update(float deltaTime)
protected override void UpdateMissionSpecific(float deltaTime)
{
if (!initialized)
{

View File

@@ -18,6 +18,7 @@ namespace Barotrauma
foreach (Character character in characters)
{
character.WriteSpawnData(msg, character.ID, restrictMessageSize: false);
msg.Write(terroristCharacters.Contains(character));
List<Item> characterItems = characterDictionary[character];
// items must be written in a specific sequence so that child items aren't written before their parents
msg.Write((ushort)characterItems.Count());

View File

@@ -6,10 +6,12 @@ namespace Barotrauma
{
partial void ShowMessageProjSpecific(int missionState)
{
if (missionState >= Headers.Count && missionState >= Messages.Count) return;
int messageIndex = missionState - 1;
if (messageIndex >= Headers.Count && messageIndex >= Messages.Count) { return; }
if (messageIndex < 0) { return; }
string header = missionState < Headers.Count ? Headers[missionState] : "";
string message = missionState < Messages.Count ? Messages[missionState] : "";
string header = messageIndex < Headers.Count ? Headers[messageIndex] : "";
string message = messageIndex < Messages.Count ? Messages[messageIndex] : "";
GameServer.Log(TextManager.Get("MissionInfo") + ": " + header + " - " + message, ServerLog.MessageType.ServerMessage);
}

View File

@@ -1,19 +0,0 @@
using Barotrauma.Networking;
using System.Collections.Generic;
namespace Barotrauma
{
partial class OutpostDestroyMission : AbandonedOutpostMission
{
private readonly List<Item> spawnedItems = new List<Item>();
public override void ServerWriteInitial(IWriteMessage msg, Client c)
{
base.ServerWriteInitial(msg, c);
msg.Write((ushort)spawnedItems.Count);
foreach (Item item in spawnedItems)
{
item.WriteSpawnData(msg, item.ID, Entity.NullEntityID, 0);
}
}
}
}

View File

@@ -35,6 +35,8 @@ namespace Barotrauma
private set;
}
public static Thread MainThread { get; private set; }
//only screens the server implements
public static GameScreen GameScreen;
public static NetLobbyScreen NetLobbyScreen;
@@ -91,6 +93,8 @@ namespace Barotrauma
Console.WriteLine("Initializing GameScreen");
GameScreen = new GameScreen();
MainThread = Thread.CurrentThread;
}
public void Init()
@@ -388,6 +392,8 @@ namespace Barotrauma
if (GameSettings.SaveDebugConsoleLogs) { DebugConsole.SaveLogs(); }
if (GameSettings.SendUserStatistics) { GameAnalytics.OnQuit(); }
MainThread = null;
}
public static void ResetFrameTime()

View File

@@ -214,6 +214,7 @@ namespace Barotrauma
c.CharacterHealth.Save(c.Info.HealthData);
c.Info.InventoryData = new XElement("inventory");
c.SaveInventory();
c.Info.SaveOrderData();
}
c.Inventory.DeleteAllItems();
@@ -332,7 +333,7 @@ namespace Barotrauma
CargoManager.OnSoldItemsChanged += () => { LastUpdateID++; };
UpgradeManager.OnUpgradesChanged += () => { LastUpdateID++; };
Map.OnLocationSelected += (loc, connection) => { LastUpdateID++; };
Map.OnMissionSelected += (loc, mission) => { LastUpdateID++; };
Map.OnMissionsSelected += (loc, mission) => { LastUpdateID++; };
Reputation.OnAnyReputationValueChanged += () => { LastUpdateID++; };
}
//increment save ID so clients know they're lacking the most up-to-date save file
@@ -431,8 +432,15 @@ namespace Barotrauma
msg.Write(lastSaveID);
msg.Write(map.Seed);
msg.Write(map.CurrentLocationIndex == -1 ? UInt16.MaxValue : (UInt16)map.CurrentLocationIndex);
msg.Write(map.SelectedLocationIndex == -1 ? UInt16.MaxValue : (UInt16)map.SelectedLocationIndex);
msg.Write(map.SelectedMissionIndex == -1 ? byte.MaxValue : (byte)map.SelectedMissionIndex);
msg.Write(map.SelectedLocationIndex == -1 ? UInt16.MaxValue : (UInt16)map.SelectedLocationIndex);
var selectedMissionIndices = map.GetSelectedMissionIndices();
msg.Write((byte)selectedMissionIndices.Count());
foreach (int selectedMissionIndex in selectedMissionIndices)
{
msg.Write((byte)selectedMissionIndex);
}
msg.Write(map.AllowDebugTeleport);
msg.Write(reputation != null);
if (reputation != null) { msg.Write(reputation.Value); }
@@ -535,7 +543,14 @@ namespace Barotrauma
{
UInt16 currentLocIndex = msg.ReadUInt16();
UInt16 selectedLocIndex = msg.ReadUInt16();
byte selectedMissionIndex = msg.ReadByte();
byte selectedMissionCount = msg.ReadByte();
List<int> selectedMissionIndices = new List<int>();
for (int i = 0; i < selectedMissionCount; i++)
{
selectedMissionIndices.Add(msg.ReadByte());
}
bool purchasedHullRepairs = msg.ReadBoolean();
bool purchasedItemRepairs = msg.ReadBoolean();
bool purchasedLostShuttles = msg.ReadBoolean();
@@ -663,7 +678,7 @@ namespace Barotrauma
Map.SelectLocation(selectedLocIndex == UInt16.MaxValue ? -1 : selectedLocIndex);
if (Map.SelectedLocation == null) { Map.SelectRandomLocation(preferUndiscovered: true); }
if (Map.SelectedConnection != null) { Map.SelectMission(selectedMissionIndex); }
if (Map.SelectedConnection != null) { Map.SelectMission(selectedMissionIndices); }
List<PurchasedItem> currentBuyCrateItems = new List<PurchasedItem>(CargoManager.ItemsInBuyCrate);
currentBuyCrateItems.ForEach(i => CargoManager.ModifyItemQuantityInBuyCrate(i.ItemPrefab, -i.Quantity));

View File

@@ -20,33 +20,5 @@ namespace Barotrauma
}
}
}
/// <summary>
/// Sends a message to all clients telling them that all upgrades on the submarine were reset.
/// </summary>
/// <remarks>
/// <param name="newUpgrades"/> is supposed to have a list of reloaded metadata but seeing as
/// this method is currently only used when switching submarines and that disables the repair NPC
/// until the next round so currently there's no need for it as we get the new values from the save
/// file anyways.
/// </remarks>
/// <see cref="UpgradeManager.ClientRead"/>
private void SendUpgradeResetMessage(Dictionary<string, int> newUpgrades)
{
foreach (Client c in GameMain.Server.ConnectedClients)
{
IWriteMessage outmsg = new WriteOnlyMessage();
outmsg.Write((byte)ServerPacketHeader.RESET_UPGRADES);
outmsg.Write(true);
outmsg.Write(Campaign.Money);
// outmsg.Write((uint)newUpgrades.Count);
// foreach (var (key, value) in newUpgrades)
// {
// outmsg.Write(key);
// outmsg.Write((byte)value);
// }
GameMain.Server?.ServerPeer?.Send(outmsg, c.Connection, DeliveryMethod.Reliable);
}
}
}
}

View File

@@ -41,7 +41,7 @@ namespace Barotrauma.Items.Components
}
//don't allow rewiring locked panels
if (Locked || !GameMain.NetworkMember.ServerSettings.AllowRewiring) { return; }
if (Locked || TemporarilyLocked || !GameMain.NetworkMember.ServerSettings.AllowRewiring) { return; }
item.CreateServerEvent(this);

View File

@@ -378,7 +378,7 @@ namespace Barotrauma.Networking
if (gameStarted)
{
if (respawnManager != null) { respawnManager.Update(deltaTime); }
respawnManager?.Update(deltaTime);
entityEventManager.Update(connectedClients);
@@ -406,10 +406,7 @@ namespace Barotrauma.Networking
}
}
if (TraitorManager != null)
{
TraitorManager.Update(deltaTime);
}
TraitorManager?.Update(deltaTime);
if (serverSettings.Voting.VoteRunning)
{
@@ -433,7 +430,7 @@ namespace Barotrauma.Networking
connectedClients.All(c => c.Character == null || c.Character.IsDead || c.Character.IsIncapacitated);
bool subAtLevelEnd = false;
if (Submarine.MainSub != null && Submarine.MainSubs[1] == null)
if (Submarine.MainSub != null && !(GameMain.GameSession.GameMode is PvPMode))
{
if (Level.Loaded?.EndOutpost != null)
{
@@ -488,8 +485,10 @@ namespace Barotrauma.Networking
}
else if (isCrewDead && (GameMain.GameSession?.GameMode is CampaignMode))
{
#if !DEBUG
endRoundDelay = 1.0f;
endRoundTimer += deltaTime;
#endif
}
else
{
@@ -3281,7 +3280,6 @@ namespace Barotrauma.Networking
if (voteType != VoteType.PurchaseSub)
{
SubmarineInfo newSub = GameMain.GameSession.SwitchSubmarine(targetSubmarine, deliveryFee);
GameMain.GameSession.Campaign.UpgradeManager.RefundResetAndReload(newSub, true);
}
serverSettings.Voting.StopSubmarineVote(true);

View File

@@ -306,7 +306,8 @@ namespace Barotrauma.Networking
{
if (Enum.TryParse(missionTypeName, out MissionType missionType))
{
if (missionType == Barotrauma.MissionType.None) continue;
if (missionType == Barotrauma.MissionType.None) { continue; }
if (MissionPrefab.HiddenMissionClasses.Contains(missionType)) { continue; }
AllowedRandomMissionTypes.Add(missionType);
}
}

View File

@@ -6,7 +6,7 @@
<RootNamespace>Barotrauma</RootNamespace>
<Authors>FakeFish, Undertow Games</Authors>
<Product>Barotrauma Dedicated Server</Product>
<Version>0.1400.0.0</Version>
<Version>0.1400.1.0</Version>
<Copyright>Copyright © FakeFish 2018-2020</Copyright>
<Platforms>AnyCPU;x64</Platforms>
<AssemblyName>DedicatedServer</AssemblyName>

View File

@@ -257,5 +257,7 @@
<OutpostModule file="Content/Map/Outposts/MineModule_04.sub" />
<OutpostModule file="Content/Map/Outposts/HallModuleHorizontal_Abandoned.sub" />
<OutpostModule file="Content/Map/Outposts/HallModuleVertical_Abandoned.sub" />
<EnemySubmarine file="Content/Map/EnemySubmarines/DugongPirate.sub"/>
<EnemySubmarine file="Content/Map/EnemySubmarines/HumpbackPirate.sub"/>
<EnemySubmarine file="Content/Map/EnemySubmarines/Typhon2Pirate.sub"/>
</contentpackage>

View File

@@ -66,7 +66,7 @@ namespace Barotrauma
private IEnumerable<object> Update(ISpatialEntity targetEntity, Camera cam)
{
if (targetEntity == null) { yield return CoroutineStatus.Success; }
if (targetEntity == null || (targetEntity is Entity e && e.Removed)) { yield return CoroutineStatus.Success; }
prevControlled = Character.Controlled;
if (RemoveControlFromCharacter)

View File

@@ -1475,7 +1475,9 @@ namespace Barotrauma
Character thief = character;
bool someoneSpoke = false;
if (item.SpawnedInOutpost && !item.AllowStealing && thief.TeamID != CharacterTeamType.FriendlyNPC && !item.HasTag("handlocker"))
bool stolenItemsInside = item.OwnInventory?.FindAllItems(it => it.SpawnedInOutpost && !it.AllowStealing, recursive: true).Any() ?? false;
if ((item.SpawnedInOutpost && !item.AllowStealing || stolenItemsInside) && thief.TeamID != CharacterTeamType.FriendlyNPC && !item.HasTag("handlocker"))
{
foreach (Character otherCharacter in Character.CharacterList)
{

View File

@@ -56,8 +56,23 @@ namespace Barotrauma
public float BasePriority { get; set; }
public float PriorityModifier { get; private set; } = 1;
// For forcing the highest priority temporarily. Will reset after each priority calculation, so it will need to be kept alive by something.
public bool ForceHighestPriority { get; set; }
private float resetPriorityTimer;
private readonly float resetPriorityTime = 1;
private bool _forceHighestPriority;
// For forcing the highest priority temporarily. Will reset automatically after one second, unless kept alive by something.
public bool ForceHighestPriority
{
get { return _forceHighestPriority; }
set
{
if (_forceHighestPriority == value) { return; }
_forceHighestPriority = value;
if (_forceHighestPriority)
{
resetPriorityTimer = resetPriorityTime;
}
}
}
// For temporarily forcing walking. Will reset after each priority calculation, so it will need to be kept alive by something.
// The intention of this boolean to allow walking even when the priority is higher than AIObjectiveManager.RunPriority.
@@ -171,7 +186,6 @@ namespace Barotrauma
Act(deltaTime);
}
// TODO: check turret aioperate
public void AddSubObjective(AIObjective objective, bool addFirst = false)
{
var type = objective.GetType();
@@ -294,6 +308,14 @@ namespace Barotrauma
public virtual void Update(float deltaTime)
{
if (resetPriorityTimer > 0)
{
resetPriorityTimer -= deltaTime;
}
else
{
ForceHighestPriority = false;
}
if (!objectiveManager.IsOrder(this) && objectiveManager.WaitTimer <= 0)
{
UpdateDevotion(deltaTime);

View File

@@ -91,7 +91,7 @@ namespace Barotrauma
protected override void Act(float deltaTime)
{
if (container == null || (container.Item != null && container.Item.IsThisOrAnyContainerIgnoredByAI()))
if (container?.Item == null || container.Item.Removed || container.Item.IsThisOrAnyContainerIgnoredByAI())
{
Abandon = true;
return;
@@ -146,7 +146,10 @@ namespace Barotrauma
{
DialogueIdentifier = "dialogcannotreachtarget",
TargetName = container.Item.Name,
AbortCondition = obj => !ItemToContain.IsOwnedBy(character),
AbortCondition = obj =>
container?.Item == null || container.Item.Removed || container.Item.IsThisOrAnyContainerIgnoredByAI() ||
ItemToContain == null || ItemToContain.Removed ||
!ItemToContain.IsOwnedBy(character) || container.Item.GetRootInventoryOwner() is Character c && c != character,
SpeakIfFails = !objectiveManager.IsCurrentOrder<AIObjectiveCleanupItems>()
},
onAbandon: () => Abandon = true,

View File

@@ -614,7 +614,11 @@ namespace Barotrauma
/// <summary>
/// Returns all active objectives of the specific type. Creates a new collection -> don't use too frequently.
/// </summary>
public IEnumerable<T> GetActiveObjectives<T>() where T : AIObjective => CurrentObjective?.GetSubObjectivesRecursive(includingSelf: true).Where(so => so is T).Select(so => so as T);
public IEnumerable<T> GetActiveObjectives<T>() where T : AIObjective
{
if (CurrentObjective == null) { return Enumerable.Empty<T>(); }
return CurrentObjective.GetSubObjectivesRecursive(includingSelf: true).Where(so => so is T).Select(so => so as T);
}
public bool HasActiveObjective<T>() where T : AIObjective => CurrentObjective is T || CurrentObjective != null && CurrentObjective.GetSubObjectivesRecursive().Any(so => so is T);

View File

@@ -46,7 +46,7 @@ namespace Barotrauma
Abandon = !isOrder;
return Priority;
}
if (component.Item.ConditionPercentage <= 0)
if (!isOrder && component.Item.ConditionPercentage <= 0)
{
Priority = 0;
}

View File

@@ -1,6 +1,7 @@
using Barotrauma.Items.Components;
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using Barotrauma.Extensions;
@@ -43,7 +44,6 @@ namespace Barotrauma
}
return Priority;
}
// TODO: priority list?
// Ignore items that are being repaired by someone else.
if (Item.Repairables.Any(r => r.CurrentFixer != null && r.CurrentFixer != character))
{
@@ -66,7 +66,20 @@ namespace Barotrauma
float devotion = (CumulatedDevotion + selectedBonus) / 100;
float reduction = isPriority ? 1 : isSelected ? 2 : 3;
float max = AIObjectiveManager.LowestOrderPriority - reduction;
Priority = MathHelper.Lerp(0, max, MathHelper.Clamp(devotion + (severity * distanceFactor * PriorityModifier), 0, 1));
float highestWeight = -1;
foreach (string tag in Item.Prefab.Tags)
{
if (JobPrefab.ItemRepairPriorities.TryGetValue(tag, out float weight) && weight > highestWeight)
{
highestWeight = weight;
}
}
if (highestWeight == -1)
{
// Predefined weight not found.
highestWeight = 1;
}
Priority = MathHelper.Lerp(0, max, MathHelper.Clamp(devotion + (severity * distanceFactor * highestWeight * PriorityModifier), 0, 1));
}
return Priority;
}

View File

@@ -150,6 +150,8 @@ namespace Barotrauma
//legacy support
public readonly string[] AppropriateJobs;
public readonly string[] Options;
public readonly string[] HiddenOptions;
public readonly string[] AllOptions;
private readonly Dictionary<string, string> OptionNames;
public readonly Dictionary<string, Sprite> OptionSprites;
@@ -310,6 +312,8 @@ namespace Barotrauma
TargetAllCharacters = orderElement.GetAttributeBool("targetallcharacters", false);
AppropriateJobs = orderElement.GetAttributeStringArray("appropriatejobs", new string[0]);
Options = orderElement.GetAttributeStringArray("options", new string[0]);
HiddenOptions = orderElement.GetAttributeStringArray("hiddenoptions", new string[0]);
AllOptions = Options.Concat(HiddenOptions).ToArray();
var category = orderElement.GetAttributeString("category", null);
if (!string.IsNullOrWhiteSpace(category)) { this.Category = (OrderCategory)Enum.Parse(typeof(OrderCategory), category, true); }
MustSetTarget = orderElement.GetAttributeBool("mustsettarget", false);

View File

@@ -400,7 +400,7 @@ namespace Barotrauma
spawnPos = spawnPoint?.WorldPosition ?? Submarine.MainSub.WorldPosition;
}
var pet = Character.Create(speciesName, spawnPos, seed);
var petBehavior = (pet.AIController as EnemyAIController)?.PetBehavior;
var petBehavior = (pet?.AIController as EnemyAIController)?.PetBehavior;
if (petBehavior != null)
{
petBehavior.Owner = owner;

View File

@@ -113,7 +113,7 @@ namespace Barotrauma
if (CurrentOrder != null && OrderedCharacter.GetCurrentOrderWithTopPriority()?.Order != CurrentOrder)
{
#if DEBUG
DebugConsole.NewMessage($"Order {CurrentOrder.Name} did not match current order for character {OrderedCharacter} in {this}");
ShipCommandManager.ShipCommandLog($"Order {CurrentOrder.Name} did not match current order for character {OrderedCharacter} in {this}");
#endif
return false;
}
@@ -121,7 +121,7 @@ namespace Barotrauma
if (!shipCommandManager.AbleToTakeOrder(OrderedCharacter))
{
#if DEBUG
DebugConsole.NewMessage(OrderedCharacter + " was unable to perform assigned order in " + this);
ShipCommandManager.ShipCommandLog(OrderedCharacter + " was unable to perform assigned order in " + this);
#endif
return false;
}

View File

@@ -93,7 +93,7 @@ namespace Barotrauma
}
}
static void ShipCommandLog(string text)
public static void ShipCommandLog(string text)
{
if (GameSettings.VerboseLogging)
{

View File

@@ -74,7 +74,7 @@ namespace Barotrauma
}
}
public bool HasMultipleLimbsOfSameType => Limbs.Length > limbDictionary.Count;
public bool HasMultipleLimbsOfSameType => limbs == null ? false : Limbs.Length > limbDictionary.Count;
private bool frozen;
public bool Frozen
@@ -416,10 +416,7 @@ namespace Barotrauma
protected void CreateColliders()
{
if (collider != null)
{
collider.ForEach(c => c.Remove());
}
collider?.ForEach(c => c.Remove());
DebugConsole.Log($"Creating colliders from {RagdollParams.Name}.");
collider = new List<PhysicsBody>();
foreach (var cParams in RagdollParams.Colliders)
@@ -479,10 +476,7 @@ namespace Barotrauma
protected void CreateLimbs()
{
if (limbs != null)
{
limbs.ForEach(l => l.Remove());
}
limbs?.ForEach(l => l.Remove());
DebugConsole.Log($"Creating limbs from {RagdollParams.Name}.");
limbDictionary = new Dictionary<LimbType, Limb>();
limbs = new Limb[RagdollParams.Limbs.Count];

View File

@@ -395,14 +395,12 @@ namespace Barotrauma
Affliction affliction;
string afflictionIdentifier = subElement.GetAttributeString("identifier", "").ToLowerInvariant();
afflictionPrefab = AfflictionPrefab.List.FirstOrDefault(ap => ap.Identifier.Equals(afflictionIdentifier, System.StringComparison.OrdinalIgnoreCase));
if (afflictionPrefab != null)
if (afflictionPrefab == null)
{
affliction = afflictionPrefab.Instantiate(0.0f);
}
else
{
affliction = new Affliction(null, 0);
DebugConsole.ThrowError($"Couldn't find the affliction with the identifier {afflictionIdentifier} referenced in {element.Document.ParseContentPathFromUri()}");
continue;
}
affliction = afflictionPrefab.Instantiate(0.0f);
affliction.Deserialize(subElement);
//backwards compatibility
if (subElement.Attribute("amount") != null && subElement.Attribute("strength") == null)

View File

@@ -1523,6 +1523,16 @@ namespace Barotrauma
greatestNegativeHealthMultiplier = 1f;
}
/// <summary>
/// Can be used to modify a character's health for runtime session. Change with AddHealthMultiplier
/// </summary>
public float StaticHealthMultiplier { get; private set; } = 1;
public void AddStaticHealthMultiplier(float newMultiplier)
{
StaticHealthMultiplier *= newMultiplier;
}
/// <summary>
/// Speed reduction from the current limb specific damage. Min 0, max 1.
/// </summary>
@@ -1916,19 +1926,19 @@ namespace Barotrauma
return AnimController.GetLimb(LimbType.Head) ?? AnimController.GetLimb(LimbType.Torso) ?? AnimController.MainLimb;
}
public bool CanSeeTarget(ISpatialEntity target, Limb seeingLimb = null)
public bool CanSeeTarget(ISpatialEntity target, ISpatialEntity seeingEntity = null)
{
seeingLimb ??= GetSeeingLimb();
if (seeingLimb == null) { return false; }
ISpatialEntity seeingEntity = AnimController.SimplePhysicsEnabled ? this : seeingLimb as ISpatialEntity;
seeingEntity ??= AnimController.SimplePhysicsEnabled ? this as ISpatialEntity : GetSeeingLimb() as ISpatialEntity;
if (seeingEntity == null) { return false; }
ISpatialEntity sourceEntity = seeingEntity ;
// TODO: Could we just use the method below? If not, let's refactor it so that we can.
Vector2 diff = ConvertUnits.ToSimUnits(target.WorldPosition - seeingEntity.WorldPosition);
Vector2 diff = ConvertUnits.ToSimUnits(target.WorldPosition - sourceEntity.WorldPosition);
Body closestBody;
//both inside the same sub (or both outside)
//OR the we're inside, the other character outside
if (target.Submarine == Submarine || target.Submarine == null)
{
closestBody = Submarine.CheckVisibility(seeingEntity.SimPosition, seeingEntity.SimPosition + diff);
closestBody = Submarine.CheckVisibility(sourceEntity.SimPosition, sourceEntity.SimPosition + diff);
}
//we're outside, the other character inside
else if (Submarine == null)
@@ -1938,7 +1948,7 @@ namespace Barotrauma
//both inside different subs
else
{
closestBody = Submarine.CheckVisibility(seeingEntity.SimPosition, seeingEntity.SimPosition + diff);
closestBody = Submarine.CheckVisibility(sourceEntity.SimPosition, sourceEntity.SimPosition + diff);
if (!IsBlocking(closestBody))
{
closestBody = Submarine.CheckVisibility(target.SimPosition, target.SimPosition - diff);
@@ -1966,29 +1976,6 @@ namespace Barotrauma
}
}
/// <summary>
/// TODO: ensure that works. CheckVisibility takes positions in sim space, but this method uses world positions
/// </summary>
public bool CanSeeCharacter(Character target, Vector2 sourceWorldPos)
{
Vector2 diff = ConvertUnits.ToSimUnits(target.WorldPosition - sourceWorldPos);
Body closestBody;
if (target.Submarine == null)
{
closestBody = Submarine.CheckVisibility(sourceWorldPos, sourceWorldPos + diff);
if (closestBody == null) { return true; }
}
else
{
closestBody = Submarine.CheckVisibility(target.WorldPosition, target.WorldPosition - diff);
if (closestBody == null) { return true; }
}
Structure wall = closestBody.UserData as Structure;
Item item = closestBody.UserData as Item;
Door door = item?.GetComponent<Door>();
return (wall == null || !wall.CastShadow) && (door == null || door.CanBeTraversed);
}
/// <summary>
/// A simple check if the character Dir is towards the target or not. Uses the world coordinates.
/// </summary>
@@ -2233,7 +2220,10 @@ namespace Barotrauma
Rectangle itemDisplayRect = new Rectangle(item.InteractionRect.X, item.InteractionRect.Y - item.InteractionRect.Height, item.InteractionRect.Width, item.InteractionRect.Height);
// Get the point along the line between lowerBodyPosition and upperBodyPosition which is closest to the center of itemDisplayRect
Vector2 playerDistanceCheckPosition = Vector2.Clamp(itemDisplayRect.Center.ToVector2(), lowerBodyPosition, upperBodyPosition);
Vector2 playerDistanceCheckPosition =
lowerBodyPosition.Y < upperBodyPosition.Y ?
Vector2.Clamp(itemDisplayRect.Center.ToVector2(), lowerBodyPosition, upperBodyPosition) :
Vector2.Clamp(itemDisplayRect.Center.ToVector2(), upperBodyPosition, lowerBodyPosition);
// If playerDistanceCheckPosition is inside the itemDisplayRect then we consider the character to within 0 distance of the item
if (itemDisplayRect.Contains(playerDistanceCheckPosition))
@@ -2271,7 +2261,7 @@ namespace Barotrauma
itemPosition -= Submarine.SimPosition;
}
var body = Submarine.CheckVisibility(SimPosition, itemPosition, ignoreLevel: true);
if (body != null && body.UserData as Item != item) { return false; }
if (body != null && body.UserData as Item != item && Submarine.LastPickedFixture?.UserData as Item != item) { return false; }
}
return true;
@@ -3657,7 +3647,11 @@ namespace Barotrauma
// OnDamaged is called only for the limb that is hit.
AnimController.Limbs.ForEach(l => l.ApplyStatusEffects(actionType, deltaTime));
}
CharacterHealth.ApplyAfflictionStatusEffects(actionType);
//OnActive effects are handled by the afflictions themselves
if (actionType != ActionType.OnActive)
{
CharacterHealth.ApplyAfflictionStatusEffects(actionType);
}
}
private void Implode(bool isNetworkMessage = false)
@@ -3801,10 +3795,7 @@ namespace Barotrauma
return;
}
if (aiTarget != null)
{
aiTarget.Remove();
}
aiTarget?.Remove();
aiTarget = new AITarget(this);
CharacterHealth.RemoveAllAfflictions();

View File

@@ -456,7 +456,7 @@ namespace Barotrauma
public bool IsAttachmentsLoaded => HairIndex > -1 && BeardIndex > -1 && MoustacheIndex > -1 && FaceAttachmentIndex > -1;
// Used for creating the data
public CharacterInfo(string speciesName, string name = "", string originalName = "", JobPrefab jobPrefab = null, string ragdollFileName = null, int variant = 0, Rand.RandSync randSync = Rand.RandSync.Unsynced)
public CharacterInfo(string speciesName, string name = "", string originalName = "", JobPrefab jobPrefab = null, string ragdollFileName = null, int variant = 0, Rand.RandSync randSync = Rand.RandSync.Unsynced, string npcIdentifier = "")
{
if (speciesName.EndsWith(".xml", StringComparison.OrdinalIgnoreCase))
{
@@ -485,8 +485,12 @@ namespace Barotrauma
{
Name = name;
}
else
else if (!string.IsNullOrEmpty(npcIdentifier) && TextManager.Get("npctitle." + npcIdentifier, true) is string npcTitle)
{
Name = npcTitle;
}
else
{
name = "";
if (CharacterConfigElement.Element("name") != null)
{

View File

@@ -150,12 +150,9 @@ namespace Barotrauma
{
max += Character.Info.Job.Prefab.VitalityModifier;
}
max *= Character.StaticHealthMultiplier;
return max * Character.HealthMultiplier;
}
set
{
maxVitality = Math.Max(0, value);
}
}
public float MinVitality

View File

@@ -121,11 +121,12 @@ namespace Barotrauma
public void InitializeCharacter(Character npc, ISpatialEntity positionToStayIn = null)
{
npc.CharacterHealth.MaxVitality *= HealthMultiplier;
npc.AddStaticHealthMultiplier(HealthMultiplier);
if (GameMain.NetworkMember != null)
{
npc.CharacterHealth.MaxVitality *= HealthMultiplierInMultiplayer;
npc.AddStaticHealthMultiplier(HealthMultiplierInMultiplayer);
}
var humanAI = npc.AIController as HumanAIController;
if (humanAI != null)
{
@@ -227,10 +228,7 @@ namespace Barotrauma
}
IdCard idCardComponent = item.GetComponent<IdCard>();
if (idCardComponent != null)
{
idCardComponent.Initialize(character.Info);
}
idCardComponent?.Initialize(character.Info);
var idCardTags = itemElement.GetAttributeStringArray("tags", new string[0]);
foreach (string tag in idCardTags)
@@ -243,10 +241,7 @@ namespace Barotrauma
{
wifiComponent.TeamID = character.TeamID;
}
if (parentItem != null)
{
parentItem.Combine(item, user: null);
}
parentItem?.Combine(item, user: null);
foreach (XElement childItemElement in itemElement.Elements())
{
InitializeItem(character, childItemElement, submarine, humanPrefab, item, createNetworkEvents);

View File

@@ -204,10 +204,7 @@ namespace Barotrauma
item.AddTag("job:" + Name);
IdCard idCardComponent = item.GetComponent<IdCard>();
if (idCardComponent != null)
{
idCardComponent.Initialize(character.Info);
}
idCardComponent?.Initialize(character.Info);
}
foreach (WifiComponent wifiComponent in item.GetComponents<WifiComponent>())

View File

@@ -1,9 +1,9 @@
using Microsoft.Xna.Framework;
using System.Collections.Generic;
using System.Xml.Linq;
using Barotrauma.Extensions;
using Barotrauma.Extensions;
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
namespace Barotrauma
{
@@ -43,6 +43,12 @@ namespace Barotrauma
Prefabs.Remove(this);
}
private static readonly Dictionary<string, float> _itemRepairPriorities = new Dictionary<string, float>();
/// <summary>
/// Tag -> priority.
/// </summary>
public static IReadOnlyDictionary<string, float> ItemRepairPriorities => _itemRepairPriorities;
public static XElement NoJobElement;
public static JobPrefab Get(string identifier)
{
@@ -294,7 +300,7 @@ namespace Barotrauma
}
foreach (XElement element in mainElement.Elements())
{
if (element.Name.ToString().Equals("nojob", StringComparison.OrdinalIgnoreCase)) { continue; }
if (!element.Name.ToString().Equals("job", StringComparison.OrdinalIgnoreCase)) { continue; }
if (element.IsOverride())
{
var job = new JobPrefab(element.FirstElement(), file.Path)
@@ -312,8 +318,31 @@ namespace Barotrauma
Prefabs.Add(job, false);
}
}
NoJobElement = NoJobElement ?? mainElement.Element("NoJob");
NoJobElement = NoJobElement ?? mainElement.Element("nojob");
NoJobElement ??= mainElement.GetChildElement("nojob");
var itemRepairPrioritiesElement = mainElement.GetChildElement("ItemRepairPriorities");
if (itemRepairPrioritiesElement != null)
{
foreach (var subElement in itemRepairPrioritiesElement.Elements())
{
string tag = subElement.GetAttributeString("tag", null);
if (tag != null)
{
float priority = subElement.GetAttributeFloat("priority", -1f);
if (priority >= 0)
{
_itemRepairPriorities.TryAdd(tag, priority);
}
else
{
DebugConsole.AddWarning($"The 'priority' attribute is missing from the the item repair priorities definition in {subElement} of {file.Path}.");
}
}
else
{
DebugConsole.AddWarning($"The 'tag' attribute is missing from the the item repair priorities definition in {subElement} of {file.Path}.");
}
}
}
}
public static void RemoveByFile(string filePath)

View File

@@ -837,10 +837,7 @@ namespace Barotrauma
}
}
if (attack != null)
{
attack.UpdateCoolDown(deltaTime);
}
attack?.UpdateCoolDown(deltaTime);
}
private float reEnableTimer = -1;

View File

@@ -194,13 +194,13 @@ namespace Barotrauma
isCorePackage = value;
if (isCorePackage && regularPackages.Contains(this))
{
corePackages.Add(this);
regularPackages.Remove(this);
corePackages.AddOnMainThread(this);
regularPackages.RemoveOnMainThread(this);
}
else if (!isCorePackage && corePackages.Contains(this))
{
regularPackages.Add(this);
corePackages.Remove(this);
regularPackages.AddOnMainThread(this);
corePackages.RemoveOnMainThread(this);
}
}
}
@@ -411,6 +411,7 @@ namespace Barotrauma
case ContentType.Submarine:
case ContentType.Wreck:
case ContentType.BeaconStation:
case ContentType.EnemySubmarine:
break;
default:
try
@@ -528,7 +529,7 @@ namespace Barotrauma
{
refreshFiles = true;
}
corePackages.Remove(p);
corePackages.RemoveOnMainThread(p);
}
else
{
@@ -536,16 +537,16 @@ namespace Barotrauma
{
refreshFiles = true;
}
regularPackages.Remove(p);
regularPackages.RemoveOnMainThread(p);
}
}
if (IsCorePackage)
{
corePackages.Add(this);
corePackages.AddOnMainThread(this);
}
else
{
regularPackages.Add(this);
regularPackages.AddOnMainThread(this);
}
if (refreshFiles)
@@ -743,18 +744,18 @@ namespace Barotrauma
}
if (newPackage.IsCorePackage)
{
corePackages.Add(newPackage);
corePackages.AddOnMainThread(newPackage);
}
else
{
regularPackages.Add(newPackage);
regularPackages.AddOnMainThread(newPackage);
}
}
public static void RemovePackage(ContentPackage package)
{
if (package.IsCorePackage) { corePackages.Remove(package); }
else { regularPackages.Remove(package); }
if (package.IsCorePackage) { corePackages.RemoveOnMainThread(package); }
else { regularPackages.RemoveOnMainThread(package); }
}
public static void LoadAll()
@@ -775,9 +776,9 @@ namespace Barotrauma
IEnumerable<string> files = Directory.GetFiles(folder, "*.xml");
corePackages.Clear();
corePackages.ClearOnMainThread();
var prevRegularPackages = regularPackages.Select(p => p.Name.ToLowerInvariant()).ToList();
regularPackages.Clear();
regularPackages.ClearOnMainThread();
foreach (string filePath in files)
{
@@ -815,7 +816,7 @@ namespace Barotrauma
.OrderBy(p => order(p))
.ThenBy(p => regularPackages.IndexOf(p))
.ToList();
regularPackages.Clear(); regularPackages.AddRange(ordered);
regularPackages.ClearOnMainThread(); regularPackages.AddRangeOnMainThread(ordered);
(config ?? GameMain.Config)?.SortContentPackages(refreshAll);
}
@@ -825,12 +826,12 @@ namespace Barotrauma
{
if (IsCorePackage)
{
corePackages.Remove(this);
corePackages.RemoveOnMainThread(this);
if (GameMain.Config.CurrentCorePackage == this) { GameMain.Config.AutoSelectCorePackage(null); }
}
else
{
regularPackages.Remove(this);
regularPackages.RemoveOnMainThread(this);
if (GameMain.Config.EnabledRegularPackages.Contains(this)) { GameMain.Config.DisableRegularPackage(this); }
}
GameMain.Config.SaveNewPlayerConfig();

View File

@@ -303,9 +303,15 @@ namespace Barotrauma
private bool IsValidTarget(Entity e)
{
return
e is Character character && !character.Removed && !character.IsDead && !character.IsIncapacitated &&
bool isValid = e is Character character && !character.Removed && !character.IsDead && !character.IsIncapacitated &&
(e == Character.Controlled || character.IsRemotePlayer);
#if SERVER
UpdateIgnoredClients();
isValid &= !ignoredClients.Keys.Any(c => c.Character == e);
#elif CLIENT
isValid &= (e != Character.Controlled || !GUI.InputBlockingMenuOpen);
#endif
return isValid;
}
private void TryStartConversation(Character speaker, Character targetCharacter = null)
@@ -348,7 +354,7 @@ namespace Barotrauma
{
ParentEvent.AddTarget(InvokerTag, targetCharacter);
}
ShowDialog(speaker, targetCharacter);
dialogOpened = true;

Some files were not shown because too many files have changed in this diff Show More