v0.11.0.9

This commit is contained in:
Joonas Rikkonen
2020-12-09 16:34:16 +02:00
parent bbf06f0984
commit f433a7ba10
325 changed files with 13947 additions and 3652 deletions
@@ -199,7 +199,7 @@ namespace Barotrauma
var headset = GetHeadset(Character.Controlled, true);
if (headset != null && headset.CanTransmit())
{
headset.TransmitSignal(stepsTaken: 0, signal: msg, source: headset.Item, sender: Character.Controlled, sendToChat: false);
headset.TransmitSignal(stepsTaken: 0, signal: msg, source: headset.Item, sender: Character.Controlled, sentFromChat: true);
}
}
textbox.Deselect();
@@ -232,7 +232,7 @@ namespace Barotrauma
};
}
var reports = Order.PrefabList.FindAll(o => o.TargetAllCharacters && o.SymbolSprite != null);
var reports = Order.PrefabList.FindAll(o => o.IsReport && o.SymbolSprite != null);
if (reports.None())
{
DebugConsole.ThrowError("No valid orders for report buttons found! Cannot create report buttons. The orders for the report buttons must have 'targetallcharacters' attribute enabled and a valid 'symbolsprite' defined.");
@@ -252,7 +252,7 @@ namespace Barotrauma
//report buttons
foreach (Order order in reports)
{
if (!order.TargetAllCharacters || order.SymbolSprite == null) { continue; }
if (!order.IsReport || order.SymbolSprite == null) { continue; }
var btn = new GUIButton(new RectTransform(new Point(ReportButtonFrame.Rect.Width), ReportButtonFrame.RectTransform), style: null)
{
OnClicked = (GUIButton button, object userData) =>
@@ -667,6 +667,8 @@ namespace Barotrauma
#region Crew List Order Displayment
// TODO: CHECK ALL THE ORDER CONSTUCTOR CALLS
/// <summary>
/// Sets the character's current order (if it's close enough to receive messages from orderGiver) and
/// displays the order in the crew UI
@@ -675,16 +677,69 @@ namespace Barotrauma
{
if (order != null && order.TargetAllCharacters)
{
if (orderGiver == null || orderGiver.CurrentHull == null) { return; }
var hull = orderGiver.CurrentHull;
AddOrder(new Order(order.Prefab ?? order, hull, null, orderGiver), order.FadeOutTime);
Hull hull = null;
if (order.IsReport)
{
if (orderGiver?.CurrentHull == null) { return; }
hull = orderGiver.CurrentHull;
AddOrder(new Order(order.Prefab ?? order, hull, null, orderGiver), order.FadeOutTime);
}
else if(order.IsIgnoreOrder)
{
WallSection ws = null;
if (order.TargetType == Order.OrderTargetType.Entity && order.TargetEntity is MapEntity me)
{
if (order.Identifier == "ignorethis")
{
me.SetIgnoreByAI(true);
AddOrder(new Order(order.Prefab ?? order, order.TargetEntity, order.TargetItemComponent, orderGiver), null);
}
else
{
me.SetIgnoreByAI(false);
ActiveOrders.RemoveAll(p => p.First.Identifier == "ignorethis" && p.First.TargetEntity == order.TargetEntity);
}
}
else if (order.TargetType == Order.OrderTargetType.WallSection && order.TargetEntity is Structure s)
{
var wallSectionIndex = order.WallSectionIndex ?? s.Sections.IndexOf(wallContext);
ws = s.GetSection(wallSectionIndex);
if (ws != null)
{
if (order.Identifier == "ignorethis")
{
ws.SetIgnoreByAI(true);
AddOrder(new Order(order.Prefab ?? order, s, wallSectionIndex, orderGiver), null);
}
else
{
ws.SetIgnoreByAI(false);
ActiveOrders.RemoveAll(p => p.First.Identifier == "ignorethis" && p.First.TargetEntity == s && p.First.WallSectionIndex == wallSectionIndex);
}
}
}
if (ws != null)
{
hull = Hull.FindHull(ws.WorldPosition);
}
else if (order.TargetEntity is Item i)
{
hull = i.CurrentHull;
}
else if (order.TargetEntity is ISpatialEntity se)
{
hull = Hull.FindHull(se.WorldPosition);
}
}
if (IsSinglePlayer)
{
orderGiver.Speak(order.GetChatMessage("", hull.DisplayName, givingOrderToSelf: character == orderGiver), ChatMessageType.Order);
orderGiver.Speak(order.GetChatMessage("", hull?.DisplayName, givingOrderToSelf: character == orderGiver), ChatMessageType.Order);
}
else
{
OrderChatMessage msg = new OrderChatMessage(order, "", hull, null, orderGiver);
OrderChatMessage msg = new OrderChatMessage(order, "", order.IsReport ? hull : order.TargetEntity, null, orderGiver);
GameMain.Client?.SendChatMessage(msg);
}
}
@@ -696,7 +751,7 @@ namespace Barotrauma
if (IsSinglePlayer)
{
character.SetOrder(order, option, orderGiver, speak: orderGiver != character);
orderGiver?.Speak(order.GetChatMessage(character.Name, orderGiver.CurrentHull?.DisplayName, givingOrderToSelf: character == orderGiver, orderOption: option), null);
orderGiver?.Speak(order?.GetChatMessage(character.Name, orderGiver.CurrentHull?.DisplayName, givingOrderToSelf: character == orderGiver, orderOption: option));
}
else if (orderGiver != null)
{
@@ -1591,6 +1646,7 @@ namespace Barotrauma
private Character characterContext;
private Item itemContext;
private Hull hullContext;
private WallSection wallContext;
private bool isContextual;
private readonly List<Order> contextualOrders = new List<Order>();
private Point shorcutCenterNodeOffset;
@@ -1640,7 +1696,7 @@ namespace Barotrauma
}
}
else if (TryGetBreachedHullAtHoveredWall(out Hull breachedHull))
else if (TryGetBreachedHullAtHoveredWall(out Hull breachedHull, out wallContext))
{
return breachedHull;
}
@@ -1662,16 +1718,24 @@ namespace Barotrauma
if (entityContext is Character character)
{
characterContext = character;
itemContext = null;
hullContext = null;
wallContext = null;
isContextual = false;
}
else if (entityContext is Item item)
{
itemContext = item;
characterContext = null;
hullContext = null;
wallContext = null;
isContextual = true;
}
else if (entityContext is Hull hull)
{
hullContext = hull;
characterContext = null;
itemContext = null;
isContextual = true;
}
@@ -1785,7 +1849,7 @@ namespace Barotrauma
availableCategories = new List<OrderCategory>();
foreach (OrderCategory category in Enum.GetValues(typeof(OrderCategory)))
{
if (Order.PrefabList.Any(o => o.Category == category && !o.TargetAllCharacters))
if (Order.PrefabList.Any(o => o.Category == category && !o.IsReport))
{
availableCategories.Add(category);
}
@@ -2129,7 +2193,7 @@ namespace Barotrauma
if (Order.GetPrefab(orderIdentifier) is Order orderPrefab &&
shortcutNodes.None(n => (n.UserData is Order order && order.Identifier == orderIdentifier) ||
(n.UserData is Tuple<Order, string> orderWithOption && orderWithOption.Item1.Identifier == orderIdentifier)) &&
!orderPrefab.TargetAllCharacters && orderPrefab.Category != null)
!orderPrefab.IsReport && orderPrefab.Category != null)
{
if (!orderPrefab.MustSetTarget || orderPrefab.GetMatchingItems(sub, true).Any())
{
@@ -2172,7 +2236,7 @@ namespace Barotrauma
private void CreateOrderNodes(OrderCategory orderCategory)
{
var orders = Order.PrefabList.FindAll(o => o.Category == orderCategory && !o.TargetAllCharacters);
var orders = Order.PrefabList.FindAll(o => o.Category == orderCategory && !o.IsReport);
Order order;
bool disableNode;
var offsets = MathUtils.GetPointsOnCircumference(Vector2.Zero, nodeDistance,
@@ -2250,34 +2314,38 @@ namespace Barotrauma
if (contextualOrders.None())
{
orderIdentifier = "cleanupitems";
if (contextualOrders.None(o => o.Identifier.Equals(orderIdentifier)) && AIObjectiveCleanupItems.IsValidTarget(itemContext, Character.Controlled))
if (contextualOrders.None(o => o.Identifier.Equals(orderIdentifier)) && AIObjectiveCleanupItems.IsValidTarget(itemContext, Character.Controlled, checkInventory: false))
{
contextualOrders.Add(new Order(Order.GetPrefab(orderIdentifier), itemContext, targetItem: null, Character.Controlled));
}
}
AddIgnoreOrder(itemContext);
}
else if (hullContext != null)
{
contextualOrders.Add(new Order(Order.GetPrefab("fixleaks"), hullContext, targetItem: null, Character.Controlled));
if (wallContext != null)
{
AddIgnoreOrder(wallContext);
}
}
if (contextualOrders.None(o => o.Category != OrderCategory.Movement))
orderIdentifier = "wait";
if (contextualOrders.None(o => o.Identifier.Equals(orderIdentifier)))
{
orderIdentifier = "wait";
Vector2 position = GameMain.GameScreen.Cam.ScreenToWorld(PlayerInput.MousePosition);
Hull hull = Hull.FindHull(position, guess: Character.Controlled?.CurrentHull);
contextualOrders.Add(new Order(Order.GetPrefab(orderIdentifier), new OrderTarget(position, hull), Character.Controlled));
}
if (contextualOrders.None(o => o.Category != OrderCategory.Movement) && characters.Any(c => c != Character.Controlled))
{
orderIdentifier = "follow";
if (contextualOrders.None(o => o.Identifier.Equals(orderIdentifier)))
{
Vector2 position = GameMain.GameScreen.Cam.ScreenToWorld(PlayerInput.MousePosition);
Hull hull = Hull.FindHull(position, guess: Character.Controlled?.CurrentHull);
contextualOrders.Add(new Order(Order.GetPrefab(orderIdentifier), new OrderTarget(position, hull), Character.Controlled));
}
if (characters.Any(c => c != Character.Controlled))
{
orderIdentifier = "follow";
if (contextualOrders.None(o => o.Identifier.Equals(orderIdentifier)))
{
contextualOrders.Add(Order.GetPrefab(orderIdentifier));
}
contextualOrders.Add(Order.GetPrefab(orderIdentifier));
}
}
@@ -2298,6 +2366,35 @@ namespace Barotrauma
CreateOrderNode(nodeSize, commandFrame.RectTransform, offsets[i].ToPoint(), contextualOrders[i], (i + 1) % 10, disableNode: disableNode, checkIfOrderCanBeHeard: false),
!disableNode ? Keys.D0 + (i + 1) % 10 : Keys.None));
}
void AddIgnoreOrder(ISpatialEntity target)
{
var orderIdentifier = "ignorethis";
if (!target.IgnoreByAI && contextualOrders.None(o => o.Identifier.Equals(orderIdentifier)))
{
AddOrder(orderIdentifier, target);
}
else
{
orderIdentifier = "unignorethis";
if (target.IgnoreByAI && contextualOrders.None(o => o.Identifier.Equals(orderIdentifier)))
{
AddOrder(orderIdentifier, target);
}
}
void AddOrder(string id, ISpatialEntity target)
{
if (target is WallSection ws)
{
contextualOrders.Add(new Order(Order.GetPrefab(orderIdentifier), ws.Wall, ws.Wall.Sections.IndexOf(ws), orderGiver: Character.Controlled));
}
else
{
contextualOrders.Add(new Order(Order.GetPrefab(orderIdentifier), target as Entity, null, Character.Controlled));
}
}
}
}
// TODO: there's duplicate logic here and above -> would be better to refactor so that the conditions are only defined in one place
@@ -2306,7 +2403,7 @@ namespace Barotrauma
if (Order.PrefabList.Any(o => o.TargetItems.Length > 0 && o.TargetItems.Contains(item.Prefab.Identifier))) { return true; }
if (Order.PrefabList.Any(o => item.HasTag(o.TargetItems))) { return true; }
if (Order.PrefabList.Any(o => o.TryGetTargetItemComponent(item, out _))) { return true; }
if (AIObjectiveCleanupItems.IsValidTarget(item, Character.Controlled)) { return true; }
if (AIObjectiveCleanupItems.IsValidTarget(item, Character.Controlled, checkInventory: false)) { return true; }
if (item.Repairables.Any(r => item.ConditionPercentage < r.RepairThreshold)) { return true; }
var operateWeaponsPrefab = Order.GetPrefab("operateweapons");
@@ -2367,11 +2464,13 @@ namespace Barotrauma
{
o = new Order(o.Prefab, orderTargetEntity, orderTargetEntity.Components.FirstOrDefault(ic => ic.GetType() == order.ItemComponentType), orderGiver: order.OrderGiver);
}
SetCharacterOrder(characterContext ?? GetCharacterForQuickAssignment(o), o, null, Character.Controlled);
var character = !o.TargetAllCharacters ? characterContext ?? GetCharacterForQuickAssignment(o) : null;
SetCharacterOrder(character, o, null, Character.Controlled);
DisableCommandUI();
}
return true;
};
// TODO: Might need to edit the tooltip
var icon = CreateNodeIcon(node.RectTransform, order.SymbolSprite, order.Color,
tooltip: mustSetOptionOrTarget || characterContext != null ? order.Name : order.Name +
"\n" + (!PlayerInput.MouseButtonsSwapped() ? TextManager.Get("input.leftmouse") : TextManager.Get("input.rightmouse")) + ": " + TextManager.Get("commandui.quickassigntooltip") +
@@ -2948,9 +3047,10 @@ namespace Barotrauma
return (degrees < 0) ? (degrees + 360) : degrees;
}
private bool TryGetBreachedHullAtHoveredWall(out Hull breachedHull)
private bool TryGetBreachedHullAtHoveredWall(out Hull breachedHull, out WallSection hoveredWall)
{
breachedHull = null;
hoveredWall = null;
// Based on the IsValidTarget() method of AIObjectiveFixLeaks class
List<Gap> leaks = Gap.GapList.FindAll(g =>
g != null && g.ConnectedWall != null && g.ConnectedDoor == null && g.Open > 0 && g.linkedTo.Any(l => l != null) &&
@@ -2962,6 +3062,15 @@ namespace Barotrauma
if (Submarine.RectContains(leak.ConnectedWall.WorldRect, mouseWorldPosition))
{
breachedHull = leak.FlowTargetHull;
foreach (var section in leak.ConnectedWall.Sections)
{
if (Submarine.RectContains(section.WorldRect, mouseWorldPosition))
{
hoveredWall = section;
break;
}
}
return true;
}
}
@@ -20,6 +20,7 @@ namespace Barotrauma
protected GUIButton endRoundButton;
public GUIButton ReadyCheckButton;
public GUIButton EndRoundButton => endRoundButton;
protected GUIFrame campaignUIContainer;
@@ -142,7 +143,8 @@ namespace Barotrauma
if (GUI.DisableHUD || GUI.DisableUpperHUD || ForceMapUI || CoroutineManager.IsCoroutineRunning("LevelTransition"))
{
endRoundButton.Visible = false;
endRoundButton.Visible = false;
if (ReadyCheckButton != null) { ReadyCheckButton.Visible = false; }
return;
}
if (Submarine.MainSub == null) { return; }
@@ -188,6 +190,8 @@ namespace Barotrauma
break;
}
if (ReadyCheckButton != null) { ReadyCheckButton.Visible = endRoundButton.Visible; }
if (endRoundButton.Visible)
{
if (!AllowedToEndRound()) { buttonText = TextManager.Get("map"); }
@@ -211,6 +215,10 @@ namespace Barotrauma
}
}
endRoundButton.DrawManually(spriteBatch);
if (this is MultiPlayerCampaign)
{
ReadyCheckButton?.DrawManually(spriteBatch);
}
}
public Task SelectSummaryScreen(RoundSummary roundSummary, LevelData newLevel, bool mirror, Action action)
@@ -279,6 +287,7 @@ namespace Barotrauma
base.AddToGUIUpdateList();
CrewManager.AddToGUIUpdateList();
endRoundButton.AddToGUIUpdateList();
ReadyCheckButton?.AddToGUIUpdateList();
}
public override void Update(float deltaTime)
@@ -34,7 +34,6 @@ namespace Barotrauma
}
}
public static void StartCampaignSetup(IEnumerable<string> saveFiles)
{
var parent = GameMain.NetLobbyScreen.CampaignSetupFrame;
@@ -103,11 +102,13 @@ namespace Barotrauma
{
CanBeFocused = false
};
int buttonHeight = (int)(GUI.Scale * 40);
int buttonWidth = GUI.IntScale(450);
endRoundButton = new GUIButton(HUDLayoutSettings.ToRectTransform(new Rectangle((GameMain.GraphicsWidth / 2) - (buttonWidth / 2), HUDLayoutSettings.ButtonAreaTop.Center.Y - (buttonHeight / 2), buttonWidth, buttonHeight), GUICanvas.Instance),
int buttonHeight = (int) (GUI.Scale * 40),
buttonWidth = GUI.IntScale(450),
buttonCenter = buttonHeight / 2,
screenMiddle = GameMain.GraphicsWidth / 2;
endRoundButton = new GUIButton(HUDLayoutSettings.ToRectTransform(new Rectangle(screenMiddle - buttonWidth / 2, HUDLayoutSettings.ButtonAreaTop.Center.Y - buttonCenter, buttonWidth, buttonHeight), GUICanvas.Instance),
TextManager.Get("EndRound"), textAlignment: Alignment.Center, style: "EndRoundButton")
{
Pulse = true,
@@ -140,6 +141,25 @@ namespace Barotrauma
return true;
}
};
int readyButtonHeight = buttonHeight;
int readyButtonWidth = (int) (GUI.Scale * 50);
ReadyCheckButton = new GUIButton(HUDLayoutSettings.ToRectTransform(new Rectangle(screenMiddle + (buttonWidth / 2) + GUI.IntScale(16), HUDLayoutSettings.ButtonAreaTop.Center.Y - buttonCenter, readyButtonWidth, readyButtonHeight), GUICanvas.Instance),
style: "RepairBuyButton")
{
ToolTip = TextManager.Get("ReadyCheck.Tooltip"),
OnClicked = delegate
{
if (CrewManager != null && CrewManager.ActiveReadyCheck == null)
{
ReadyCheck.CreateReadyCheck();
}
return true;
},
UserData = "ReadyCheckButton"
};
buttonContainer.Recalculate();
}
@@ -378,6 +398,7 @@ namespace Barotrauma
if (!GUI.DisableHUD && !GUI.DisableUpperHUD)
{
endRoundButton.UpdateManually(deltaTime);
ReadyCheckButton?.UpdateManually(deltaTime);
if (CoroutineManager.IsCoroutineRunning("LevelTransition") || ForceMapUI) { return; }
}
@@ -368,6 +368,9 @@ namespace Barotrauma
SoundPlayer.OverrideMusicDuration = 18.0f;
crewDead = false;
LevelData lvlData = GameMain.GameSession.LevelData;
bool beaconActive = GameMain.GameSession.Level.CheckBeaconActive();
GameMain.GameSession.EndRound("", traitorResults, transitionType);
var continueButton = GameMain.GameSession.RoundSummary?.ContinueButton;
RoundSummary roundSummary = null;
@@ -452,6 +455,8 @@ namespace Barotrauma
}
}
lvlData.IsBeaconActive = beaconActive;
SaveUtil.SaveGame(GameMain.GameSession.SavePath);
}
else
@@ -39,6 +39,10 @@ namespace Barotrauma
base.Start();
CrewManager.InitSinglePlayerRound();
foreach (Submarine submarine in Submarine.Loaded)
{
submarine.NeutralizeBallast();
}
if (SpawnOutpost)
{
@@ -121,7 +121,7 @@ namespace Barotrauma.Tutorials
return;
}
character = Character.Create(charInfo, wayPoint.WorldPosition, "", false, false);
character = Character.Create(charInfo, wayPoint.WorldPosition, "", isRemotePlayer: false, hasAi: false);
character.TeamID = Character.TeamType.Team1;
Character.Controlled = character;
character.GiveJobItems(null);
@@ -0,0 +1,287 @@
#nullable enable
using System;
using System.Collections.Generic;
using System.Linq;
using Barotrauma.Networking;
using Microsoft.Xna.Framework;
namespace Barotrauma
{
internal partial class ReadyCheck
{
private static string readyCheckBody(string name) => string.IsNullOrWhiteSpace(name) ? TextManager.Get("readycheck.serverbody") : TextManager.GetWithVariable("readycheck.body", "[player]", name);
private static string readyCheckStatus(int ready, int total) => TextManager.GetWithVariables("readycheck.readycount", new[] { "[ready]", "[total]" }, new[] { ready.ToString(), total.ToString() });
private static string readyCheckPleaseWait(int seconds) => TextManager.GetWithVariable("readycheck.pleasewait", "[seconds]", seconds.ToString());
private static readonly string readyCheckHeader = TextManager.Get("ReadyCheck.Title");
private static readonly string noButton = TextManager.Get("No"),
yesButton = TextManager.Get("Yes"),
closeButton = TextManager.Get("Close");
private const string TimerData = "Timer",
PromptData = "ReadyCheck",
ResultData = "ReadyCheckResults",
UserListData = "ReadyUserList",
ReadySpriteData = "ReadySprite";
private int lastSecond;
private GUIMessageBox? msgBox;
private GUIMessageBox? resultsBox;
public static DateTime lastReadyCheck = DateTime.MinValue;
private void CreateMessageBox(string author)
{
Vector2 relativeSize = new Vector2(GUI.IsFourByThree() ? 0.3f : 0.2f, 0.15f);
Point minSize = new Point(300, 200);
msgBox = new GUIMessageBox(readyCheckHeader, readyCheckBody(author), new[] { yesButton, noButton }, relativeSize, minSize, type: GUIMessageBox.Type.Vote) { UserData = PromptData, Draggable = true };
GUILayoutGroup contentLayout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.125f), msgBox.Content.RectTransform), childAnchor: Anchor.Center);
new GUIProgressBar(new RectTransform(new Vector2(0.8f, 1f), contentLayout.RectTransform), time / endTime, GUI.Style.Orange) { UserData = TimerData };
// Yes
msgBox.Buttons[0].OnClicked = delegate
{
msgBox.Close();
SendState(ReadyStatus.Yes);
CreateResultsMessage();
return true;
};
// No
msgBox.Buttons[1].OnClicked = delegate
{
msgBox.Close();
SendState(ReadyStatus.No);
CreateResultsMessage();
return true;
};
}
private void CreateResultsMessage()
{
Vector2 relativeSize = new Vector2(0.2f, 0.3f);
Point minSize = new Point(300, 400);
resultsBox = new GUIMessageBox(readyCheckHeader, string.Empty, new[] { closeButton }, relativeSize, minSize, type: GUIMessageBox.Type.Vote) { UserData = ResultData, Draggable = true };
if (msgBox != null)
{
resultsBox.RectTransform.ScreenSpaceOffset = msgBox.RectTransform.ScreenSpaceOffset;
}
GUIListBox listBox = new GUIListBox(new RectTransform(new Vector2(1f, 0.8f), resultsBox.Content.RectTransform)) { UserData = UserListData };
foreach (var (id, _) in Clients)
{
Client? client = GameMain.Client.ConnectedClients.FirstOrDefault(c => c.ID == id);
GUIFrame container = new GUIFrame(new RectTransform(new Vector2(1f, 0.15f), listBox.Content.RectTransform), style: "ListBoxElement") { UserData = id };
GUILayoutGroup frame = new GUILayoutGroup(new RectTransform(Vector2.One, container.RectTransform), isHorizontal: true) { Stretch = true };
int height = frame.Rect.Height;
JobPrefab? jobPrefab = client?.Character?.Info?.Job?.Prefab;
if (client == null)
{
string list = GameMain.Client.ConnectedClients.Aggregate("Available clients:\n", (current, c) => current + $"{c.ID}: {c.Name}\n");
DebugConsole.ThrowError($"Client ID {id} was reported in ready check but was not found.\n" + list.TrimEnd('\n'));
}
if (jobPrefab?.Icon != null)
{
// job icon
new GUIImage(new RectTransform(new Point(height, height), frame.RectTransform), jobPrefab.Icon, scaleToFit: true) { Color = jobPrefab.UIColor };
}
new GUITextBlock(new RectTransform(new Vector2(0.75f, 1), frame.RectTransform), client?.Name ?? $"Unknown ID {id}", jobPrefab?.UIColor ?? Color.White, textAlignment: Alignment.Center) { AutoScaleHorizontal = true };
new GUIImage(new RectTransform(new Point(height, height), frame.RectTransform), null, scaleToFit: true) { UserData = ReadySpriteData };
}
resultsBox.Buttons[0].OnClicked = delegate
{
resultsBox.Close();
return true;
};
}
private void UpdateBar()
{
if (msgBox != null && !msgBox.Closed && GUIMessageBox.MessageBoxes.Contains(msgBox))
{
if (msgBox.FindChild(TimerData, true) is GUIProgressBar bar)
{
bar.BarSize = time / endTime;
}
}
// play click sound after a second has passed
int second = (int) Math.Ceiling(time);
if (second < lastSecond)
{
SoundPlayer.PlayUISound(GUISoundType.PopupMenu);
lastSecond = second;
}
}
public static void ClientRead(IReadMessage inc)
{
ReadyCheckState state = (ReadyCheckState) inc.ReadByte();
CrewManager? crewManager = GameMain.GameSession?.CrewManager;
List<Client> otherClients = GameMain.Client.ConnectedClients;
if (crewManager == null || otherClients == null)
{
if (state == ReadyCheckState.Start)
{
SendState(ReadyStatus.No);
}
return;
}
switch (state)
{
case ReadyCheckState.Start:
bool isOwn = false;
byte authorId = 0;
float duration = inc.ReadSingle();
string author = inc.ReadString();
bool hasAuthor = inc.ReadBoolean();
if (hasAuthor)
{
authorId = inc.ReadByte();
isOwn = authorId == GameMain.Client.ID;
}
ushort clientCount = inc.ReadUInt16();
List<byte> clients = new List<byte>();
for (int i = 0; i < clientCount; i++)
{
clients.Add(inc.ReadByte());
}
ReadyCheck rCheck = new ReadyCheck(clients, duration);
crewManager.ActiveReadyCheck = rCheck;
if (isOwn)
{
SendState(ReadyStatus.Yes);
rCheck.CreateResultsMessage();
}
else
{
rCheck.CreateMessageBox(author);
}
if (hasAuthor && rCheck.Clients.ContainsKey(authorId))
{
rCheck.Clients[authorId] = ReadyStatus.Yes;
}
break;
case ReadyCheckState.Update:
float time = inc.ReadSingle();
ReadyStatus newState = (ReadyStatus) inc.ReadByte();
byte targetId = inc.ReadByte();
if (crewManager.ActiveReadyCheck != null)
{
crewManager.ActiveReadyCheck.time = time;
crewManager.ActiveReadyCheck?.UpdateState(targetId, newState);
}
break;
case ReadyCheckState.End:
ushort count = inc.ReadUInt16();
for (int i = 0; i < count; i++)
{
byte id = inc.ReadByte();
ReadyStatus status = (ReadyStatus) inc.ReadByte();
crewManager.ActiveReadyCheck?.UpdateState(id, status);
}
crewManager.ActiveReadyCheck?.EndReadyCheck();
crewManager.ActiveReadyCheck?.msgBox?.Close();
crewManager.ActiveReadyCheck = null;
break;
}
}
partial void EndReadyCheck()
{
if (IsFinished) { return; }
IsFinished = true;
int readyCount = Clients.Count(pair => pair.Value == ReadyStatus.Yes);
int totalCount = Clients.Count;
GameMain.Client.AddChatMessage(ChatMessage.Create(string.Empty, readyCheckStatus(readyCount, totalCount), ChatMessageType.Server, null));
}
private void UpdateState(byte id, ReadyStatus status)
{
if (Clients.ContainsKey(id))
{
Clients[id] = status;
}
if (resultsBox == null || resultsBox.Closed || !GUIMessageBox.MessageBoxes.Contains(resultsBox)) { return; }
if (resultsBox.Content.FindChild(UserListData) is GUIListBox userList)
{
// for some reason FindChild doesn't work here?
foreach (GUIComponent child in userList.Content.Children)
{
if (!(child.UserData is byte b) || b != id) { continue; }
if (child.GetChild<GUILayoutGroup>().FindChild(ReadySpriteData) is GUIImage image)
{
string style;
switch (status)
{
case ReadyStatus.Yes:
style = "MissionCompletedIcon";
break;
case ReadyStatus.No:
style = "MissionFailedIcon";
break;
default:
return;
}
image.ApplyStyle(GUI.Style.GetComponentStyle(style));
}
}
}
}
private static void SendState(ReadyStatus status)
{
IWriteMessage msg = new WriteOnlyMessage();
msg.Write((byte) ClientPacketHeader.READY_CHECK);
msg.Write((byte) ReadyCheckState.Update);
msg.Write((byte) status);
GameMain.Client?.ClientPeer?.Send(msg, DeliveryMethod.Reliable);
}
public static void CreateReadyCheck()
{
if (lastReadyCheck < DateTime.Now)
{
#if !DEBUG
lastReadyCheck = DateTime.Now.AddMinutes(1);
#endif
IWriteMessage msg = new WriteOnlyMessage();
msg.Write((byte) ClientPacketHeader.READY_CHECK);
msg.Write((byte) ReadyCheckState.Start);
GameMain.Client?.ClientPeer?.Send(msg, DeliveryMethod.Reliable);
return;
}
GUIMessageBox msgBox = new GUIMessageBox(readyCheckHeader, readyCheckPleaseWait((lastReadyCheck - DateTime.Now).Seconds), new[] { closeButton });
msgBox.Buttons[0].OnClicked = delegate
{
msgBox.Close();
return true;
};
}
}
}
@@ -503,7 +503,7 @@ namespace Barotrauma
Character character = characterInfo.Character;
if (character == null || character.IsDead)
{
if (character == null && characterInfo.IsNewHire)
if (character == null && characterInfo.IsNewHire && characterInfo.CauseOfDeath == null)
{
statusText = TextManager.Get("CampaignCrew.NewHire");
statusColor = GUI.Style.Blue;