Unstable 0.1400.0.0
This commit is contained in:
@@ -71,6 +71,7 @@ namespace Barotrauma
|
||||
: this(isSinglePlayer)
|
||||
{
|
||||
AddCharacterElements(element);
|
||||
ActiveOrdersElement = element.GetChildElement("activeorders");
|
||||
}
|
||||
|
||||
partial void InitProjectSpecific()
|
||||
@@ -192,7 +193,8 @@ namespace Barotrauma
|
||||
{
|
||||
AbsoluteSpacing = (int)(5 * GUI.Scale),
|
||||
UserData = "reportbuttons",
|
||||
CanBeFocused = false
|
||||
CanBeFocused = false,
|
||||
Visible = false
|
||||
};
|
||||
|
||||
ReportButtonFrame.RectTransform.AbsoluteOffset = new Point(0, -chatBox.ToggleButton.Rect.Height);
|
||||
@@ -433,13 +435,20 @@ namespace Barotrauma
|
||||
Stretch = false
|
||||
};
|
||||
|
||||
var soundIcons = new GUIFrame(new RectTransform(new Vector2(0.8f * iconRelativeWidth, 0.8f), layoutGroup.RectTransform), style: null)
|
||||
var extraIconFrame = new GUIFrame(new RectTransform(new Vector2(0.8f * iconRelativeWidth, 0.8f), layoutGroup.RectTransform), style: null)
|
||||
{
|
||||
CanBeFocused = false,
|
||||
UserData = "soundicons"
|
||||
UserData = "extraicons"
|
||||
};
|
||||
|
||||
var soundIconParent = new GUIFrame(new RectTransform(Vector2.One, extraIconFrame.RectTransform), style: null)
|
||||
{
|
||||
CanBeFocused = false,
|
||||
UserData = "soundicons",
|
||||
Visible = character.IsPlayer
|
||||
};
|
||||
new GUIImage(
|
||||
new RectTransform(Vector2.One, soundIcons.RectTransform),
|
||||
new RectTransform(Vector2.One, soundIconParent.RectTransform),
|
||||
GUI.Style.GetComponentStyle("GUISoundIcon").GetDefaultSprite(),
|
||||
scaleToFit: true)
|
||||
{
|
||||
@@ -448,7 +457,7 @@ namespace Barotrauma
|
||||
Visible = true
|
||||
};
|
||||
new GUIImage(
|
||||
new RectTransform(Vector2.One, soundIcons.RectTransform),
|
||||
new RectTransform(Vector2.One, soundIconParent.RectTransform),
|
||||
"GUISoundIconDisabled",
|
||||
scaleToFit: true)
|
||||
{
|
||||
@@ -457,6 +466,16 @@ namespace Barotrauma
|
||||
Visible = false
|
||||
};
|
||||
|
||||
if (character.IsBot)
|
||||
{
|
||||
new GUIFrame(new RectTransform(Vector2.One, extraIconFrame.RectTransform), style: null)
|
||||
{
|
||||
CanBeFocused = false,
|
||||
UserData = "objectiveicon",
|
||||
Visible = false
|
||||
};
|
||||
}
|
||||
|
||||
new GUIButton(new RectTransform(new Point((int)commandButtonAbsoluteHeight), background.RectTransform), style: "CrewListCommandButton")
|
||||
{
|
||||
ToolTip = TextManager.Get("inputtype.command"),
|
||||
@@ -624,9 +643,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (client?.Character == null) { return; }
|
||||
|
||||
if (crewList.Content.GetChildByUserData(client.Character)?
|
||||
.FindChild(c => c is GUILayoutGroup)?
|
||||
.GetChildByUserData("soundicons") is GUIComponent soundIcons)
|
||||
if (GetSoundIconParent(client.Character) is GUIComponent soundIcons)
|
||||
{
|
||||
var soundIcon = soundIcons.FindChild(c => c.UserData is Pair<string, float> pair && pair.First == "soundicon");
|
||||
var soundIconDisabled = soundIcons.FindChild("soundicondisabled");
|
||||
@@ -638,15 +655,17 @@ namespace Barotrauma
|
||||
|
||||
public void SetClientSpeaking(Client client)
|
||||
{
|
||||
if (client?.Character != null) { SetCharacterSpeaking(client.Character); }
|
||||
if (client?.Character != null)
|
||||
{
|
||||
SetCharacterSpeaking(client.Character);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetCharacterSpeaking(Character character)
|
||||
{
|
||||
if (crewList.Content.GetChildByUserData(character)?
|
||||
.FindChild(c => c is GUILayoutGroup)?
|
||||
.GetChildByUserData("soundicons")?
|
||||
.FindChild(c => c.UserData is Pair<string, float> pair && pair.First == "soundicon") is GUIComponent soundIcon)
|
||||
if (character == null || character.IsBot) { return; }
|
||||
|
||||
if (GetSoundIconParent(character)?.FindChild(c => c.UserData is Pair<string, float> pair && pair.First == "soundicon") is GUIComponent soundIcon)
|
||||
{
|
||||
soundIcon.Color = Color.White;
|
||||
Pair<string, float> userdata = soundIcon.UserData as Pair<string, float>;
|
||||
@@ -654,6 +673,19 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
private GUIComponent GetSoundIconParent(GUIComponent characterComponent)
|
||||
{
|
||||
return characterComponent?
|
||||
.FindChild(c => c is GUILayoutGroup)?
|
||||
.GetChildByUserData("extraicons")?
|
||||
.GetChildByUserData("soundicons");
|
||||
}
|
||||
|
||||
private GUIComponent GetSoundIconParent(Character character)
|
||||
{
|
||||
return GetSoundIconParent(crewList?.Content.GetChildByUserData(character));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Crew List Order Displayment
|
||||
@@ -770,6 +802,7 @@ namespace Barotrauma
|
||||
if (icon is GUIImage image)
|
||||
{
|
||||
image.Sprite = GetOrderIconSprite(order, option);
|
||||
image.ToolTip = CreateOrderTooltip(order, option);
|
||||
}
|
||||
updatedExistingIcon = true;
|
||||
}
|
||||
@@ -835,7 +868,7 @@ namespace Barotrauma
|
||||
Visible = false
|
||||
};
|
||||
|
||||
int hierarchyIndex = GetOrderIconHierarchyIndex(priority);
|
||||
int hierarchyIndex = Math.Clamp(CharacterInfo.HighestManualOrderPriority - priority, 0, Math.Max(currentOrderIconList.Content.CountChildren - 1, 0));
|
||||
if (hierarchyIndex != currentOrderIconList.Content.GetChildIndex(nodeIcon))
|
||||
{
|
||||
nodeIcon.RectTransform.RepositionChildInHierarchy(hierarchyIndex);
|
||||
@@ -878,11 +911,6 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int GetOrderIconHierarchyIndex(int priority)
|
||||
{
|
||||
return CharacterInfo.HighestManualOrderPriority - priority;
|
||||
}
|
||||
}
|
||||
|
||||
public void AddCurrentOrderIcon(Character character, OrderInfo? orderInfo)
|
||||
@@ -1020,29 +1048,36 @@ namespace Barotrauma
|
||||
SetCharacterOrder(character, orderInfo.Order, orderInfo.OrderOption, priority, Character.Controlled);
|
||||
}
|
||||
|
||||
private string CreateOrderTooltip(Order order, string option)
|
||||
private string CreateOrderTooltip(Order orderPrefab, string option, Entity targetEntity)
|
||||
{
|
||||
if (order == null) { return ""; }
|
||||
if (orderPrefab == null) { return ""; }
|
||||
if (!string.IsNullOrEmpty(option))
|
||||
{
|
||||
return TextManager.GetWithVariables("crewlistordericontooltip",
|
||||
new string[2] { "[ordername]", "[orderoption]" },
|
||||
new string[2] { order.Name, order.GetOptionName(option) });
|
||||
new string[2] { orderPrefab.Name, orderPrefab.GetOptionName(option) });
|
||||
}
|
||||
else if (order.TargetEntity is Item targetItem && order.MinimapIcons.ContainsKey(targetItem.Prefab.Identifier))
|
||||
else if (targetEntity is Item targetItem && targetItem.Prefab.MinimapIcon != null)
|
||||
{
|
||||
return TextManager.GetWithVariables("crewlistordericontooltip",
|
||||
new string[2] { "[ordername]", "[orderoption]" },
|
||||
new string[2] { order.Name, targetItem.Name });
|
||||
new string[2] { orderPrefab.Name, targetItem.Name });
|
||||
}
|
||||
else
|
||||
{
|
||||
return order.Name;
|
||||
return orderPrefab.Name;
|
||||
}
|
||||
}
|
||||
|
||||
private string CreateOrderTooltip(OrderInfo orderInfo) =>
|
||||
CreateOrderTooltip(orderInfo.Order, orderInfo.OrderOption);
|
||||
private string CreateOrderTooltip(Order order, string option)
|
||||
{
|
||||
return CreateOrderTooltip(order?.Prefab ?? order, option, order?.TargetEntity);
|
||||
}
|
||||
|
||||
private string CreateOrderTooltip(OrderInfo orderInfo)
|
||||
{
|
||||
return CreateOrderTooltip(orderInfo.Order?.Prefab ?? orderInfo.Order, orderInfo.OrderOption, orderInfo.Order?.TargetEntity);
|
||||
}
|
||||
|
||||
private Sprite GetOrderIconSprite(Order order, string option)
|
||||
{
|
||||
@@ -1052,9 +1087,9 @@ namespace Barotrauma
|
||||
{
|
||||
order.Prefab.OptionSprites.TryGetValue(option, out sprite);
|
||||
}
|
||||
if (sprite == null && order.TargetEntity is Item targetItem && order.MinimapIcons.Any())
|
||||
if (sprite == null && order.TargetEntity is Item targetItem && targetItem.Prefab.MinimapIcon != null)
|
||||
{
|
||||
order.MinimapIcons.TryGetValue(targetItem.Prefab.Identifier, out sprite);
|
||||
sprite = targetItem.Prefab.MinimapIcon;
|
||||
}
|
||||
return sprite ?? order.SymbolSprite;
|
||||
}
|
||||
@@ -1272,7 +1307,7 @@ namespace Barotrauma
|
||||
partial void UpdateProjectSpecific(float deltaTime)
|
||||
{
|
||||
// Quick selection
|
||||
if (!GameMain.IsMultiplayer && GUI.KeyboardDispatcher.Subscriber == null)
|
||||
if (GameMain.IsSingleplayer && GUI.KeyboardDispatcher.Subscriber == null)
|
||||
{
|
||||
if (PlayerInput.KeyHit(InputType.SelectNextCharacter))
|
||||
{
|
||||
@@ -1294,7 +1329,7 @@ namespace Barotrauma
|
||||
(GUI.KeyboardDispatcher.Subscriber == null || (GUI.KeyboardDispatcher.Subscriber is GUIComponent component && (component == crewList || component.IsChildOf(crewList)))) &&
|
||||
commandFrame == null && !clicklessSelectionActive && CanIssueOrders && !(GameMain.GameSession?.Campaign?.ShowCampaignUI ?? false))
|
||||
{
|
||||
if (PlayerInput.KeyDown(Keys.LeftShift) || PlayerInput.KeyDown(Keys.RightShift))
|
||||
if (PlayerInput.IsShiftDown())
|
||||
{
|
||||
CreateCommandUI(FindEntityContext(), true);
|
||||
}
|
||||
@@ -1521,19 +1556,44 @@ namespace Barotrauma
|
||||
{
|
||||
crewList.Select(character, force: true);
|
||||
}
|
||||
if (character.AIController is HumanAIController controller)
|
||||
if (GameMain.IsSingleplayer && character.IsBot && character.AIController is HumanAIController controller &&
|
||||
controller.ObjectiveManager is AIObjectiveManager objectiveManager)
|
||||
{
|
||||
OrderInfo? currentOrderInfo = controller.ObjectiveManager?.GetCurrentOrderInfo();
|
||||
if (currentOrderInfo.HasValue)
|
||||
// In multiplayer, these are set through character networking (the server lets the clients now when these are updated)
|
||||
if (objectiveManager.CurrentObjective is AIObjective currentObjective)
|
||||
{
|
||||
SetHighlightedOrderIcon(characterComponent, currentOrderInfo.Value.Order?.Identifier, currentOrderInfo.Value.OrderOption);
|
||||
if (objectiveManager.IsOrder(currentObjective))
|
||||
{
|
||||
var orderInfo = objectiveManager.CurrentOrders.FirstOrDefault(o => o.Objective == currentObjective);
|
||||
SetOrderHighlight(characterComponent, orderInfo.Order?.Identifier, orderInfo.OrderOption);
|
||||
}
|
||||
else
|
||||
{
|
||||
CreateObjectiveIcon(characterComponent, currentObjective);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (characterComponent.GetChild<GUILayoutGroup>().GetChildByUserData("soundicons") is GUIComponent soundIconParent)
|
||||
// Order highlighting and objective icons are intended to communicate bot behavior so they should be disabled for player characters
|
||||
if (character.IsPlayer)
|
||||
{
|
||||
DisableOrderHighlight(characterComponent);
|
||||
RemoveObjectiveIcon(characterComponent);
|
||||
}
|
||||
if (GetSoundIconParent(characterComponent) is GUIComponent soundIconParent)
|
||||
{
|
||||
if (soundIconParent.FindChild(c => c.UserData is Pair<string, float> pair && pair.First == "soundicon") is GUIImage soundIcon)
|
||||
{
|
||||
VoipClient.UpdateVoiceIndicator(soundIcon, 0.0f, deltaTime);
|
||||
if (character.IsPlayer)
|
||||
{
|
||||
soundIconParent.Visible = true;
|
||||
VoipClient.UpdateVoiceIndicator(soundIcon, 0.0f, deltaTime);
|
||||
}
|
||||
else if(soundIcon.Visible)
|
||||
{
|
||||
var userdata = soundIcon.UserData as Pair<string, float>;
|
||||
userdata.Second = 0.0f;
|
||||
soundIconParent.Visible = soundIcon.Visible = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1559,31 +1619,127 @@ namespace Barotrauma
|
||||
UpdateReports();
|
||||
}
|
||||
|
||||
private void SetHighlightedOrderIcon(GUIComponent characterComponent, string orderIdentifier, string orderOption)
|
||||
private void SetOrderHighlight(GUIComponent characterComponent, string orderIdentifier, string orderOption)
|
||||
{
|
||||
var currentOrderIconList = GetCurrentOrderIconList(characterComponent);
|
||||
if (currentOrderIconList == null) { return; }
|
||||
bool foundMatch = false;
|
||||
foreach (var orderIcon in currentOrderIconList.Content.Children)
|
||||
if (characterComponent == null) { return; }
|
||||
RemoveObjectiveIcon(characterComponent);
|
||||
if (GetCurrentOrderIconList(characterComponent) is GUIListBox currentOrderIconList)
|
||||
{
|
||||
var glowComponent = orderIcon.GetChildByUserData("glow");
|
||||
if (glowComponent == null) { continue; }
|
||||
if (foundMatch)
|
||||
bool foundMatch = false;
|
||||
foreach (var orderIcon in currentOrderIconList.Content.Children)
|
||||
{
|
||||
glowComponent.Visible = false;
|
||||
continue;
|
||||
var glowComponent = orderIcon.GetChildByUserData("glow");
|
||||
if (glowComponent == null) { continue; }
|
||||
if (foundMatch)
|
||||
{
|
||||
glowComponent.Visible = false;
|
||||
continue;
|
||||
}
|
||||
var orderInfo = (OrderInfo)orderIcon.UserData;
|
||||
foundMatch = orderInfo.MatchesOrder(orderIdentifier, orderOption);
|
||||
glowComponent.Visible = foundMatch;
|
||||
}
|
||||
var orderInfo = (OrderInfo)orderIcon.UserData;
|
||||
foundMatch = orderInfo.MatchesOrder(orderIdentifier, orderOption);
|
||||
glowComponent.Visible = foundMatch;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetHighlightedOrderIcon(Character character, string orderIdentifier, string orderOption)
|
||||
public void SetOrderHighlight(Character character, string orderIdentifier, string orderOption)
|
||||
{
|
||||
if (crewList == null) { return; }
|
||||
var characterComponent = crewList.Content.GetChildByUserData(character);
|
||||
SetHighlightedOrderIcon(characterComponent, orderIdentifier, orderOption);
|
||||
SetOrderHighlight(characterComponent, orderIdentifier, orderOption);
|
||||
}
|
||||
|
||||
private void DisableOrderHighlight(GUIComponent characterComponent)
|
||||
{
|
||||
if (GetCurrentOrderIconList(characterComponent) is GUIListBox currentOrderIconList)
|
||||
{
|
||||
foreach (var orderIcon in currentOrderIconList.Content.Children)
|
||||
{
|
||||
var glowComponent = orderIcon.GetChildByUserData("glow");
|
||||
if (glowComponent == null) { continue; }
|
||||
glowComponent.Visible = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateObjectiveIcon(GUIComponent characterComponent, Sprite sprite, string tooltip)
|
||||
{
|
||||
if (characterComponent == null || !(characterComponent.UserData is Character character) || character.IsPlayer) { return; }
|
||||
DisableOrderHighlight(characterComponent);
|
||||
if (GetObjectiveIconParent(characterComponent) is GUIFrame objectiveIconFrame)
|
||||
{
|
||||
var existingObjectiveIcon = objectiveIconFrame.GetChild<GUIImage>();
|
||||
if (existingObjectiveIcon == null || existingObjectiveIcon.Sprite != sprite || existingObjectiveIcon.ToolTip != tooltip)
|
||||
{
|
||||
objectiveIconFrame.ClearChildren();
|
||||
if (sprite != null)
|
||||
{
|
||||
var objectiveIcon = CreateNodeIcon(Vector2.One, objectiveIconFrame.RectTransform, sprite, Color.LightGray, tooltip: tooltip);
|
||||
new GUIFrame(new RectTransform(new Vector2(1.5f), objectiveIcon.RectTransform, anchor: Anchor.Center), style: "OuterGlowCircular")
|
||||
{
|
||||
CanBeFocused = false,
|
||||
Color = Color.LightGray
|
||||
};
|
||||
objectiveIconFrame.Visible = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
objectiveIconFrame.Visible = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void CreateObjectiveIcon(Character character, string identifier, string option, Entity targetEntity)
|
||||
{
|
||||
CreateObjectiveIcon(crewList?.Content.GetChildByUserData(character),
|
||||
AIObjective.GetSprite(identifier, option, targetEntity),
|
||||
GetObjectiveIconTooltip(identifier, option, targetEntity));
|
||||
}
|
||||
|
||||
private void CreateObjectiveIcon(GUIComponent characterComponent, AIObjective objective)
|
||||
{
|
||||
CreateObjectiveIcon(characterComponent,
|
||||
objective?.GetSprite(),
|
||||
GetObjectiveIconTooltip(objective));
|
||||
}
|
||||
|
||||
private string GetObjectiveIconTooltip(string identifier, string option, Entity targetEntity)
|
||||
{
|
||||
string variableValue;
|
||||
identifier = identifier.RemoveWhitespace();
|
||||
if (Order.Prefabs.TryGetValue(identifier, out Order orderPrefab))
|
||||
{
|
||||
variableValue = CreateOrderTooltip(orderPrefab, option, targetEntity);
|
||||
}
|
||||
else
|
||||
{
|
||||
variableValue = TextManager.Get($"objective.{identifier}", returnNull: true) ?? "";
|
||||
}
|
||||
return string.IsNullOrEmpty(variableValue) ? variableValue : TextManager.GetWithVariable("crewlistobjectivetooltip", "[objective]", variableValue);
|
||||
}
|
||||
|
||||
private string GetObjectiveIconTooltip(AIObjective objective)
|
||||
{
|
||||
return objective == null ? "" :
|
||||
GetObjectiveIconTooltip(objective.Identifier, objective.Option, (objective as AIObjectiveOperateItem)?.OperateTarget);
|
||||
}
|
||||
|
||||
private GUIComponent GetObjectiveIconParent(GUIComponent characterComponent)
|
||||
{
|
||||
return characterComponent?
|
||||
.GetChild<GUILayoutGroup>()?
|
||||
.GetChildByUserData("extraicons")?
|
||||
.GetChildByUserData("objectiveicon");
|
||||
}
|
||||
|
||||
private void RemoveObjectiveIcon(GUIComponent characterComponent)
|
||||
{
|
||||
if (GetObjectiveIconParent(characterComponent) is GUIFrame objectiveIconFrame)
|
||||
{
|
||||
objectiveIconFrame.ClearChildren();
|
||||
objectiveIconFrame.Visible = false;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -2126,6 +2282,8 @@ namespace Barotrauma
|
||||
|
||||
private void CreateShortcutNodes()
|
||||
{
|
||||
bool HasAppropriateJob(Character c, string jobId) => c.Info?.Job != null && c.Info.Job.Prefab.AppropriateOrders.Contains(jobId);
|
||||
|
||||
Submarine sub = GetTargetSubmarine();
|
||||
|
||||
if (sub == null) { return; }
|
||||
@@ -2138,7 +2296,7 @@ namespace Barotrauma
|
||||
var reactorOutput = -reactor.CurrPowerConsumption;
|
||||
// If player is not an engineer AND the reactor is not powered up AND nobody is using the reactor
|
||||
// ---> Create shortcut node for "Operate Reactor" order's "Power Up" option
|
||||
if ((Character.Controlled == null || Character.Controlled.Info?.Job?.Prefab != JobPrefab.Get("engineer")) &&
|
||||
if ((Character.Controlled == null || !HasAppropriateJob(Character.Controlled, "operatereactor")) &&
|
||||
reactorOutput < float.Epsilon && characters.None(c => c.SelectedConstruction == reactor.Item))
|
||||
{
|
||||
var order = new Order(Order.GetPrefab("operatereactor"), reactor.Item, reactor, Character.Controlled);
|
||||
@@ -2151,7 +2309,7 @@ namespace Barotrauma
|
||||
// TODO: Reconsider the conditions as bot captain can have the nav term selected without operating it
|
||||
// If player is not a captain AND nobody is using the nav terminal AND the nav terminal is powered up
|
||||
// --> Create shortcut node for Steer order
|
||||
if (shortcutNodes.Count < maxShortCutNodeCount && (Character.Controlled == null || Character.Controlled.Info?.Job?.Prefab != JobPrefab.Get("captain")) &&
|
||||
if (shortcutNodes.Count < maxShortCutNodeCount && (Character.Controlled == null || !HasAppropriateJob(Character.Controlled, "steer")) &&
|
||||
sub.GetItems(false).Find(i => i.HasTag("navterminal") && i.IsPlayerTeamInteractable) is Item nav && characters.None(c => c.SelectedConstruction == nav) &&
|
||||
nav.GetComponent<Steering>() is Steering steering && steering.Voltage > steering.MinVoltage)
|
||||
{
|
||||
@@ -2161,8 +2319,8 @@ namespace Barotrauma
|
||||
|
||||
// If player is not a security officer AND invaders are reported
|
||||
// --> Create shorcut node for Fight Intruders order
|
||||
if (shortcutNodes.Count < maxShortCutNodeCount && (Character.Controlled == null || Character.Controlled.Info?.Job?.Prefab != JobPrefab.Get("securityofficer")) &&
|
||||
(Order.GetPrefab("reportintruders") is Order reportIntruders && ActiveOrders.Any(o => o.First.Prefab == reportIntruders)))
|
||||
if (shortcutNodes.Count < maxShortCutNodeCount && (Character.Controlled == null || !HasAppropriateJob(Character.Controlled, "fightintruders")) &&
|
||||
Order.GetPrefab("reportintruders") is Order reportIntruders && ActiveOrders.Any(o => o.First.Prefab == reportIntruders))
|
||||
{
|
||||
shortcutNodes.Add(
|
||||
CreateOrderNode(shortcutNodeSize, null, Point.Zero, Order.GetPrefab("fightintruders"), -1));
|
||||
@@ -2170,25 +2328,43 @@ namespace Barotrauma
|
||||
|
||||
// If player is not a mechanic AND a breach has been reported
|
||||
// --> Create shorcut node for Fix Leaks order
|
||||
if (shortcutNodes.Count < maxShortCutNodeCount && (Character.Controlled == null || Character.Controlled.Info?.Job?.Prefab != JobPrefab.Get("mechanic")) &&
|
||||
(Order.GetPrefab("reportbreach") is Order reportBreach && ActiveOrders.Any(o => o.First.Prefab == reportBreach)))
|
||||
if (shortcutNodes.Count < maxShortCutNodeCount && (Character.Controlled == null || !HasAppropriateJob(Character.Controlled, "fixleaks")) &&
|
||||
Order.GetPrefab("reportbreach") is Order reportBreach && ActiveOrders.Any(o => o.First.Prefab == reportBreach))
|
||||
{
|
||||
shortcutNodes.Add(
|
||||
CreateOrderNode(shortcutNodeSize, null, Point.Zero, Order.GetPrefab("fixleaks"), -1));
|
||||
}
|
||||
|
||||
// If player is not an engineer AND broken devices have been reported
|
||||
// --> Create shortcut node for Repair Damaged Systems order
|
||||
if (shortcutNodes.Count < maxShortCutNodeCount && (Character.Controlled == null || Character.Controlled.Info?.Job?.Prefab != JobPrefab.Get("engineer")) &&
|
||||
(Order.GetPrefab("reportbrokendevices") is Order reportBrokenDevices && ActiveOrders.Any(o => o.First.Prefab == reportBrokenDevices)))
|
||||
// --> Create shortcut nodes for the Repair orders
|
||||
if (shortcutNodes.Count < maxShortCutNodeCount && Order.GetPrefab("reportbrokendevices") is Order reportBrokenDevices && ActiveOrders.Any(o => o.First.Prefab == reportBrokenDevices))
|
||||
{
|
||||
shortcutNodes.Add(
|
||||
CreateOrderNode(shortcutNodeSize, null, Point.Zero, Order.GetPrefab("repairsystems"), -1));
|
||||
// TODO: Doesn't work for player issued reports, because they don't have a target.
|
||||
int repairNodes = 0;
|
||||
string tag = "repairelectrical";
|
||||
if (shortcutNodes.Count < maxShortCutNodeCount && (Character.Controlled == null || !HasAppropriateJob(Character.Controlled, tag)) && ActiveOrders.Any(o => o.First.Prefab == reportBrokenDevices && o.First.TargetItemComponent is Repairable r && r.requiredSkills.Any(s => s.Identifier == "electrical")))
|
||||
{
|
||||
shortcutNodes.Add(CreateOrderNode(shortcutNodeSize, null, Point.Zero, Order.GetPrefab(tag), -1));
|
||||
repairNodes++;
|
||||
}
|
||||
tag = "repairmechanical";
|
||||
if (shortcutNodes.Count < maxShortCutNodeCount && (Character.Controlled == null || !HasAppropriateJob(Character.Controlled, tag)) && ActiveOrders.Any(o => o.First.Prefab == reportBrokenDevices && o.First.TargetItemComponent is Repairable r && r.requiredSkills.Any(s => s.Identifier == "mechanical")))
|
||||
{
|
||||
shortcutNodes.Add(CreateOrderNode(shortcutNodeSize, null, Point.Zero, Order.GetPrefab(tag), -1));
|
||||
repairNodes++;
|
||||
}
|
||||
if (repairNodes == 0 && shortcutNodes.Count < maxShortCutNodeCount)
|
||||
{
|
||||
tag = "repairsystems";
|
||||
if (Character.Controlled == null || !HasAppropriateJob(Character.Controlled, tag))
|
||||
{
|
||||
shortcutNodes.Add(CreateOrderNode(shortcutNodeSize, null, Point.Zero, Order.GetPrefab(tag), -1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If fire is reported
|
||||
// --> Create shortcut node for Extinguish Fires order
|
||||
if (shortcutNodes.Count < maxShortCutNodeCount && ActiveOrders.Any(o=> o.First.Prefab == Order.GetPrefab("reportfire")))
|
||||
if (shortcutNodes.Count < maxShortCutNodeCount && ActiveOrders.Any(o => o.First.Prefab == Order.GetPrefab("reportfire")))
|
||||
{
|
||||
shortcutNodes.Add(
|
||||
CreateOrderNode(shortcutNodeSize, null, Point.Zero, Order.GetPrefab("extinguishfires"), -1));
|
||||
@@ -2645,16 +2821,10 @@ namespace Barotrauma
|
||||
{
|
||||
optionElement.OnSecondaryClicked = (button, _) => CreateAssignmentNodes(button);
|
||||
}
|
||||
Sprite icon = null;
|
||||
order.MinimapIcons?.TryGetValue(item.Prefab.Identifier, out icon);
|
||||
if (item.Prefab.MinimapIcon != null)
|
||||
{
|
||||
icon = item.Prefab.MinimapIcon;
|
||||
}
|
||||
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, icon ?? order.SymbolSprite, order.Color * colorMultiplier);
|
||||
CreateNodeIcon(Vector2.One, optionElement.RectTransform, item.Prefab.MinimapIcon ?? order.SymbolSprite, order.Color * colorMultiplier);
|
||||
optionNodes.Add(new Tuple<GUIComponent, Keys>(optionElement, Keys.None));
|
||||
}
|
||||
optionElements.Add(optionElement);
|
||||
@@ -3182,16 +3352,7 @@ namespace Barotrauma
|
||||
|
||||
private Character GetCharacterForQuickAssignment(Order order)
|
||||
{
|
||||
var controllingCharacter = Character.Controlled != null;
|
||||
#if !DEBUG
|
||||
if (!controllingCharacter) { return null; }
|
||||
#endif
|
||||
if (order.Category == OrderCategory.Operate && HumanAIController.IsItemOperatedByAnother(null, order.TargetItemComponent, out Character operatingCharacter) &&
|
||||
(!controllingCharacter || operatingCharacter.CanHearCharacter(Character.Controlled)))
|
||||
{
|
||||
return operatingCharacter;
|
||||
}
|
||||
return GetCharactersSortedForOrder(order, false).FirstOrDefault(c => !controllingCharacter || c.CanHearCharacter(Character.Controlled)) ?? Character.Controlled;
|
||||
return GetCharacterForQuickAssignment(order, Character.Controlled, characters);
|
||||
}
|
||||
|
||||
private List<Character> GetCharactersForManualAssignment(Order order)
|
||||
@@ -3203,34 +3364,15 @@ namespace Barotrauma
|
||||
{
|
||||
return characters.Union(GetOrderableFriendlyNPCs()).Where(c => !c.IsDismissed).OrderBy(c => c.Info.DisplayName).ToList();
|
||||
}
|
||||
return GetCharactersSortedForOrder(order, order.Identifier != "follow").ToList();
|
||||
}
|
||||
|
||||
private IEnumerable<Character> GetCharactersSortedForOrder(Order order, bool includeSelf)
|
||||
{
|
||||
return characters.Where(c => Character.Controlled == null || ((includeSelf || c != Character.Controlled) && c.TeamID == Character.Controlled.TeamID)).Union(GetOrderableFriendlyNPCs())
|
||||
// 1. Prioritize those who are on the same submarine than the controlled character
|
||||
.OrderByDescending(c => Character.Controlled == null || c.Submarine == Character.Controlled.Submarine)
|
||||
// 2. Prioritize those who have been given the same maintenance or operate order as now issued
|
||||
.ThenByDescending(c => c.CurrentOrders.Any(o =>
|
||||
o.Order != null && o.Order.Identifier == order.Identifier &&
|
||||
(order.Category == OrderCategory.Maintenance || order.Category == OrderCategory.Operate)))
|
||||
// 3. Prioritize those with the appropriate job for the order
|
||||
.ThenByDescending(c => order.HasAppropriateJob(c))
|
||||
// 4. Prioritize bots over player controlled characters
|
||||
.ThenByDescending(c => c.IsBot)
|
||||
// 5. Use the priority value of the current objective
|
||||
.ThenBy(c => c.AIController is HumanAIController humanAI ? humanAI.ObjectiveManager.CurrentObjective?.Priority : 0)
|
||||
// 6. Prioritize those with the best skill for the order
|
||||
.ThenByDescending(c => c.GetSkillLevel(order.AppropriateSkill));
|
||||
return GetCharactersSortedForOrder(order, characters, Character.Controlled, order.Identifier != "follow", extraCharacters: GetOrderableFriendlyNPCs()).ToList();
|
||||
}
|
||||
|
||||
private IEnumerable<Character> GetOrderableFriendlyNPCs()
|
||||
{
|
||||
// TODO: change this so that we can get the data without having to rely on ui elements.
|
||||
return crewList.Content.Children.Where(c => c.UserData is Character character && character.TeamID == CharacterTeamType.FriendlyNPC).Select(c => (Character)c.UserData);
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
@@ -3325,15 +3467,76 @@ namespace Barotrauma
|
||||
public void Save(XElement parentElement)
|
||||
{
|
||||
XElement element = new XElement("crew");
|
||||
|
||||
foreach (CharacterInfo ci in characterInfos)
|
||||
{
|
||||
var infoElement = ci.Save(element);
|
||||
if (ci.InventoryData != null) { infoElement.Add(ci.InventoryData); }
|
||||
if (ci.HealthData != null) { infoElement.Add(ci.HealthData); }
|
||||
if (ci.OrderData != null) { infoElement.Add(ci.OrderData); }
|
||||
if (ci.LastControlled) { infoElement.Add(new XAttribute("lastcontrolled", true)); }
|
||||
}
|
||||
SaveActiveOrders(element);
|
||||
parentElement.Add(element);
|
||||
}
|
||||
|
||||
public static void ClientReadActiveOrders(IReadMessage inc)
|
||||
{
|
||||
ushort count = inc.ReadUInt16();
|
||||
if (count < 1) { return; }
|
||||
var activeOrders = new List<(Order, float?)>();
|
||||
for (ushort i = 0; i < count; i++)
|
||||
{
|
||||
var orderMessageInfo = OrderChatMessage.ReadOrder(inc);
|
||||
Character orderGiver = null;
|
||||
if (inc.ReadBoolean())
|
||||
{
|
||||
ushort orderGiverId = inc.ReadUInt16();
|
||||
orderGiver = orderGiverId != Entity.NullEntityID ? Entity.FindEntityByID(orderGiverId) as Character : null;
|
||||
}
|
||||
if (orderMessageInfo.OrderIndex < 0 || orderMessageInfo.OrderIndex >= Order.PrefabList.Count)
|
||||
{
|
||||
DebugConsole.ThrowError("Invalid active order - order index out of bounds.");
|
||||
continue;
|
||||
}
|
||||
Order orderPrefab = orderMessageInfo.OrderPrefab ?? Order.PrefabList[orderMessageInfo.OrderIndex];
|
||||
Order order = orderMessageInfo.TargetType switch
|
||||
{
|
||||
Order.OrderTargetType.Entity =>
|
||||
new Order(orderPrefab, orderMessageInfo.TargetEntity, orderPrefab.GetTargetItemComponent(orderMessageInfo.TargetEntity as Item), orderGiver: orderGiver),
|
||||
Order.OrderTargetType.Position =>
|
||||
new Order(orderPrefab, orderMessageInfo.TargetPosition, orderGiver: orderGiver),
|
||||
Order.OrderTargetType.WallSection =>
|
||||
new Order(orderPrefab, orderMessageInfo.TargetEntity as Structure, orderMessageInfo.WallSectionIndex, orderGiver: orderGiver),
|
||||
_ => throw new NotImplementedException()
|
||||
};
|
||||
if (order != null && order.TargetAllCharacters)
|
||||
{
|
||||
var fadeOutTime = !orderPrefab.IsIgnoreOrder ? (float?)orderPrefab.FadeOutTime : null;
|
||||
activeOrders.Add((order, fadeOutTime));
|
||||
}
|
||||
}
|
||||
foreach (var (order, fadeOutTime) in activeOrders)
|
||||
{
|
||||
if (order.IsIgnoreOrder)
|
||||
{
|
||||
switch (order.TargetType)
|
||||
{
|
||||
case Order.OrderTargetType.Entity:
|
||||
if (!(order.TargetEntity is IIgnorable ignorableEntity)) { break; }
|
||||
ignorableEntity.OrderedToBeIgnored = order.Identifier == "ignorethis";
|
||||
break;
|
||||
case Order.OrderTargetType.Position:
|
||||
throw new NotImplementedException();
|
||||
case Order.OrderTargetType.WallSection:
|
||||
if (!order.WallSectionIndex.HasValue) { break; }
|
||||
if (!(order.TargetEntity is Structure s)) { break; }
|
||||
if (!(s.GetSection(order.WallSectionIndex.Value) is IIgnorable ignorableWall)) { break; }
|
||||
ignorableWall.OrderedToBeIgnored = order.Identifier == "ignorethis";
|
||||
break;
|
||||
}
|
||||
}
|
||||
GameMain.GameSession?.CrewManager?.AddOrder(order, fadeOutTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -189,7 +189,7 @@ namespace Barotrauma
|
||||
case TransitionType.None:
|
||||
default:
|
||||
if (Level.Loaded.Type == LevelData.LevelType.Outpost &&
|
||||
(Character.Controlled?.Submarine?.Info.Type == SubmarineType.Player || (Character.Controlled?.CurrentHull?.OutpostModuleTags?.Contains("airlock") ?? false)))
|
||||
(Character.Controlled?.Submarine?.Info.Type == SubmarineType.Player || (Character.Controlled?.CurrentHull?.OutpostModuleTags.Contains("airlock") ?? false)))
|
||||
{
|
||||
buttonText = TextManager.GetWithVariable("LeaveLocation", "[locationname]", Level.Loaded.StartLocation?.Name ?? "[ERROR]");
|
||||
endRoundButton.Visible = !ForceMapUI && !ShowCampaignUI;
|
||||
@@ -287,6 +287,7 @@ namespace Barotrauma
|
||||
{
|
||||
case InteractionType.None:
|
||||
case InteractionType.Talk:
|
||||
case InteractionType.Examine:
|
||||
return;
|
||||
case InteractionType.Upgrade when !UpgradeManager.CanUpgradeSub():
|
||||
UpgradeManager.CreateUpgradeErrorMessage(TextManager.Get("Dialog.CantUpgrade"), IsSinglePlayer, npc);
|
||||
|
||||
+44
-1
@@ -326,7 +326,6 @@ namespace Barotrauma
|
||||
Level prevLevel = Level.Loaded;
|
||||
|
||||
bool success = CrewManager.GetCharacters().Any(c => !c.IsDead);
|
||||
GUI.SetSavingIndicatorState(success);
|
||||
crewDead = false;
|
||||
|
||||
var continueButton = GameMain.GameSession.RoundSummary?.ContinueButton;
|
||||
@@ -484,6 +483,8 @@ namespace Barotrauma
|
||||
{
|
||||
IsFirstRound = false;
|
||||
CoroutineManager.StartCoroutine(DoLevelTransition(), "LevelTransition");
|
||||
bool success = CrewManager.GetCharacters().Any(c => !c.IsDead);
|
||||
GUI.SetSavingIndicatorState(success && (Level.IsLoadedOutpost || transitionType != TransitionType.None));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -569,6 +570,13 @@ namespace Barotrauma
|
||||
msg.Write(category.Identifier);
|
||||
msg.Write((byte)level);
|
||||
}
|
||||
|
||||
msg.Write((ushort)UpgradeManager.PurchasedItemSwaps.Count);
|
||||
foreach (var itemSwap in UpgradeManager.PurchasedItemSwaps)
|
||||
{
|
||||
msg.Write(itemSwap.ItemToRemove.ID);
|
||||
msg.Write(itemSwap.ItemToInstall?.Identifier ?? string.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
//static because we may need to instantiate the campaign if it hasn't been done yet
|
||||
@@ -657,6 +665,21 @@ namespace Barotrauma
|
||||
pendingUpgrades.Add(new PurchasedUpgrade(prefab, category, upgradeLevel));
|
||||
}
|
||||
|
||||
ushort purchasedItemSwapCount = msg.ReadUInt16();
|
||||
List<PurchasedItemSwap> purchasedItemSwaps = new List<PurchasedItemSwap>();
|
||||
for (int i = 0; i < purchasedItemSwapCount; i++)
|
||||
{
|
||||
UInt16 itemToRemoveID = msg.ReadUInt16();
|
||||
Item itemToRemove = Entity.FindEntityByID(itemToRemoveID) as Item;
|
||||
|
||||
string itemToInstallIdentifier = msg.ReadString();
|
||||
ItemPrefab itemToInstall = string.IsNullOrEmpty(itemToInstallIdentifier) ? null : ItemPrefab.Find(string.Empty, itemToInstallIdentifier);
|
||||
|
||||
if (itemToRemove == null) { continue; }
|
||||
|
||||
purchasedItemSwaps.Add(new PurchasedItemSwap(itemToRemove, itemToInstall));
|
||||
}
|
||||
|
||||
bool hasCharacterData = msg.ReadBoolean();
|
||||
CharacterInfo myCharacterInfo = null;
|
||||
if (hasCharacterData)
|
||||
@@ -703,6 +726,26 @@ namespace Barotrauma
|
||||
campaign.UpgradeManager.SetPendingUpgrades(pendingUpgrades);
|
||||
campaign.UpgradeManager.PurchasedUpgrades.Clear();
|
||||
|
||||
campaign.UpgradeManager.PurchasedUpgrades.Clear();
|
||||
foreach (var purchasedItemSwap in purchasedItemSwaps)
|
||||
{
|
||||
if (purchasedItemSwap.ItemToInstall == null)
|
||||
{
|
||||
campaign.UpgradeManager.CancelItemSwap(purchasedItemSwap.ItemToRemove, force: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
campaign.UpgradeManager.PurchaseItemSwap(purchasedItemSwap.ItemToRemove, purchasedItemSwap.ItemToInstall, force: true);
|
||||
}
|
||||
}
|
||||
foreach (Item item in Item.ItemList)
|
||||
{
|
||||
if (item.PendingItemSwap != null && !purchasedItemSwaps.Any(it => it.ItemToRemove == item))
|
||||
{
|
||||
item.PendingItemSwap = null;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var (identifier, rep) in factionReps)
|
||||
{
|
||||
Faction faction = campaign.Factions.FirstOrDefault(f => f.Prefab.Identifier.Equals(identifier, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
+8
-3
@@ -101,7 +101,8 @@ namespace Barotrauma
|
||||
case "cargo":
|
||||
CargoManager.LoadPurchasedItems(subElement);
|
||||
break;
|
||||
case "pendingupgrades":
|
||||
case "pendingupgrades": //backwards compatibility
|
||||
case "upgrademanager":
|
||||
UpgradeManager = new UpgradeManager(this, subElement, isSingleplayer: true);
|
||||
break;
|
||||
case "pets":
|
||||
@@ -229,6 +230,7 @@ namespace Barotrauma
|
||||
{
|
||||
PetBehavior.LoadPets(petsElement);
|
||||
}
|
||||
CrewManager.LoadActiveOrders();
|
||||
|
||||
GUI.DisableSavingIndicatorDelayed();
|
||||
}
|
||||
@@ -480,6 +482,8 @@ namespace Barotrauma
|
||||
EnableRoundSummaryGameOverState();
|
||||
}
|
||||
|
||||
CrewManager?.ClearCurrentOrders();
|
||||
|
||||
//--------------------------------------
|
||||
|
||||
SelectSummaryScreen(roundSummary, newLevel, mirror, () =>
|
||||
@@ -735,9 +739,10 @@ namespace Barotrauma
|
||||
if (c.Inventory != null)
|
||||
{
|
||||
c.Info.InventoryData = new XElement("inventory");
|
||||
c.SaveInventory(c.Inventory, c.Info.InventoryData);
|
||||
c.SaveInventory();
|
||||
c.Inventory?.DeleteAllItems();
|
||||
}
|
||||
c.Info.SaveOrderData();
|
||||
}
|
||||
|
||||
petsElement = new XElement("pets");
|
||||
@@ -748,7 +753,7 @@ namespace Barotrauma
|
||||
CampaignMetadata.Save(modeElement);
|
||||
Map.Save(modeElement);
|
||||
CargoManager?.SavePurchasedItems(modeElement);
|
||||
UpgradeManager?.SavePendingUpgrades(modeElement, UpgradeManager?.PendingUpgrades);
|
||||
UpgradeManager?.Save(modeElement);
|
||||
element.Add(modeElement);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -531,7 +531,7 @@ namespace Barotrauma.Tutorials
|
||||
}
|
||||
}
|
||||
yield return null;
|
||||
} while (!mechanic.HasEquippedItem("divingsuit"));
|
||||
} while (!mechanic.HasEquippedItem("divingsuit", slotType: InvSlotType.OuterClothes));
|
||||
SetHighlight(mechanic_divingSuitContainer.Item, false);
|
||||
RemoveCompletedObjective(segments[8]);
|
||||
SetDoorAccess(tutorial_mechanicFinalDoor, tutorial_mechanicFinalDoorLight, true);
|
||||
|
||||
@@ -524,7 +524,7 @@ namespace Barotrauma
|
||||
private static void CheckIfDivingGearOutOfOxygen()
|
||||
{
|
||||
if (!CanDisplayHints()) { return; }
|
||||
var divingGear = Character.Controlled.GetEquippedItem("diving");
|
||||
var divingGear = Character.Controlled.GetEquippedItem("diving", InvSlotType.OuterClothes);
|
||||
if (divingGear?.OwnInventory == null) { return; }
|
||||
if (divingGear.GetContainedItemConditionPercentage() > 0.0f) { return; }
|
||||
DisplayHint("ondivinggearoutofoxygen", onUpdate: () =>
|
||||
|
||||
@@ -311,10 +311,11 @@ namespace Barotrauma
|
||||
}
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform),
|
||||
missionMessage, wrap: true, parseRichText: true);
|
||||
if (selectedMissions.Contains(displayedMission) && displayedMission.Completed && displayedMission.Reward > 0)
|
||||
int reward = displayedMission.GetReward(Submarine.MainSub);
|
||||
if (selectedMissions.Contains(displayedMission) && displayedMission.Completed && reward > 0)
|
||||
{
|
||||
string rewardText = TextManager.GetWithVariable("currencyformat", "[credits]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", displayedMission.Reward));
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform), displayedMission.GetMissionRewardText(), parseRichText: true);
|
||||
string rewardText = TextManager.GetWithVariable("currencyformat", "[credits]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", reward));
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform), displayedMission.GetMissionRewardText(Submarine.MainSub), parseRichText: true);
|
||||
}
|
||||
|
||||
if (displayedMission != missionsToDisplay.Last())
|
||||
|
||||
Reference in New Issue
Block a user