v0.11.0.9
This commit is contained in:
@@ -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)
|
||||
|
||||
+26
-5
@@ -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)
|
||||
{
|
||||
|
||||
+1
-1
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user