|
|
|
@@ -330,7 +330,7 @@ namespace Barotrauma
|
|
|
|
|
if (data == null) { return false; }
|
|
|
|
|
if (GameMain.NetworkMember?.ConnectedClients?.Find(c => c.Character == data) is Client client)
|
|
|
|
|
{
|
|
|
|
|
CreateModerationContextMenu(PlayerInput.MousePosition.ToPoint(), client);
|
|
|
|
|
NetLobbyScreen.CreateModerationContextMenu(client);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
@@ -789,7 +789,7 @@ namespace Barotrauma
|
|
|
|
|
}
|
|
|
|
|
else if (orderGiver != null)
|
|
|
|
|
{
|
|
|
|
|
OrderChatMessage msg = new OrderChatMessage(order, option, priority, order?.TargetSpatialEntity ?? order?.TargetItemComponent?.Item as ISpatialEntity, character, orderGiver);
|
|
|
|
|
OrderChatMessage msg = new OrderChatMessage(order, option, priority, order?.TargetSpatialEntity ?? order?.TargetItemComponent?.Item, character, orderGiver);
|
|
|
|
|
GameMain.Client?.SendChatMessage(msg);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@@ -968,7 +968,8 @@ namespace Barotrauma
|
|
|
|
|
{
|
|
|
|
|
if (!CanIssueOrders) { return false; }
|
|
|
|
|
var orderInfo = (OrderInfo)userData;
|
|
|
|
|
SetCharacterOrder(character, orderInfo.Order, orderInfo.OrderOption, CharacterInfo.HighestManualOrderPriority, Character.Controlled);
|
|
|
|
|
int priority = GetManualOrderPriority(character, orderInfo.Order);
|
|
|
|
|
SetCharacterOrder(character, orderInfo.Order, orderInfo.OrderOption, priority, Character.Controlled);
|
|
|
|
|
return true;
|
|
|
|
|
},
|
|
|
|
|
OnSecondaryClicked = (button, userData) =>
|
|
|
|
@@ -1153,105 +1154,6 @@ namespace Barotrauma
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#region Context Menu
|
|
|
|
|
|
|
|
|
|
public void CreateModerationContextMenu(Point mousePos, Client client)
|
|
|
|
|
{
|
|
|
|
|
if (GUIContextMenu.CurrentContextMenu != null) { return; }
|
|
|
|
|
if (IsSinglePlayer || client == null || ((!GameMain.Client?.PreviouslyConnectedClients?.Contains(client)) ?? true)) { return; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool hasSteam = client.SteamID > 0 && SteamManager.IsInitialized,
|
|
|
|
|
canKick = GameMain.Client.HasPermission(ClientPermissions.Kick),
|
|
|
|
|
canBan = GameMain.Client.HasPermission(ClientPermissions.Ban) && client.AllowKicking,
|
|
|
|
|
canPromo = GameMain.Client.HasPermission(ClientPermissions.ManagePermissions);
|
|
|
|
|
|
|
|
|
|
// Disable options if we are targeting ourselves
|
|
|
|
|
if (client.ID == GameMain.Client?.ID)
|
|
|
|
|
{
|
|
|
|
|
canKick = canBan = canPromo = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
List<ContextMenuOption> options = new List<ContextMenuOption>();
|
|
|
|
|
|
|
|
|
|
options.Add(new ContextMenuOption("ViewSteamProfile", isEnabled: hasSteam, onSelected: delegate
|
|
|
|
|
{
|
|
|
|
|
Steamworks.SteamFriends.OpenWebOverlay($"https://steamcommunity.com/profiles/{client.SteamID}");
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
options.Add(new ContextMenuOption("ModerationMenu.UserDetails", isEnabled: true, onSelected: delegate
|
|
|
|
|
{
|
|
|
|
|
GameMain.NetLobbyScreen?.SelectPlayer(client);
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Creates sub context menu options for all the ranks
|
|
|
|
|
List<ContextMenuOption> permissionOptions = new List<ContextMenuOption>();
|
|
|
|
|
foreach (PermissionPreset rank in PermissionPreset.List)
|
|
|
|
|
{
|
|
|
|
|
permissionOptions.Add(new ContextMenuOption(rank.Name, isEnabled: true, onSelected: () =>
|
|
|
|
|
{
|
|
|
|
|
string label = TextManager.GetWithVariables(rank.Permissions == ClientPermissions.None ? "clearrankprompt" : "giverankprompt", new []{ "[user]", "[rank]" }, new []{ client.Name, rank.Name });
|
|
|
|
|
GUIMessageBox msgBox = new GUIMessageBox(string.Empty, label, new[] { TextManager.Get("Yes"), TextManager.Get("Cancel") });
|
|
|
|
|
|
|
|
|
|
msgBox.Buttons[0].OnClicked = delegate
|
|
|
|
|
{
|
|
|
|
|
client.SetPermissions(rank.Permissions, rank.PermittedCommands);
|
|
|
|
|
GameMain.Client.UpdateClientPermissions(client);
|
|
|
|
|
msgBox.Close();
|
|
|
|
|
return true;
|
|
|
|
|
};
|
|
|
|
|
msgBox.Buttons[1].OnClicked = delegate
|
|
|
|
|
{
|
|
|
|
|
msgBox.Close();
|
|
|
|
|
return true;
|
|
|
|
|
};
|
|
|
|
|
}) { Tooltip = rank.Description });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
options.Add(new ContextMenuOption("Permissions", isEnabled: canPromo, options: permissionOptions.ToArray()));
|
|
|
|
|
|
|
|
|
|
Color clientColor = client.Character?.Info?.Job.Prefab.UIColor ?? Color.White;
|
|
|
|
|
|
|
|
|
|
if (GameMain.Client.ConnectedClients.Contains(client))
|
|
|
|
|
{
|
|
|
|
|
options.Add(new ContextMenuOption(client.MutedLocally ? "Unmute" : "Mute", isEnabled: client.ID != GameMain.Client?.ID, onSelected: delegate
|
|
|
|
|
{
|
|
|
|
|
client.MutedLocally = !client.MutedLocally;
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
bool kickEnabled = client.ID != GameMain.Client?.ID && client.AllowKicking;
|
|
|
|
|
|
|
|
|
|
// if the user can kick create a kick option else create the votekick option
|
|
|
|
|
ContextMenuOption kickOption;
|
|
|
|
|
if (canKick)
|
|
|
|
|
{
|
|
|
|
|
kickOption = new ContextMenuOption("Kick", isEnabled: kickEnabled, onSelected: delegate
|
|
|
|
|
{
|
|
|
|
|
GameMain.Client?.CreateKickReasonPrompt(client.Name, false);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
kickOption = new ContextMenuOption("VoteToKick", isEnabled: kickEnabled, onSelected: delegate
|
|
|
|
|
{
|
|
|
|
|
GameMain.Client?.VoteForKick(client);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
options.Add(kickOption);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
options.Add(new ContextMenuOption("Ban", isEnabled: canBan, onSelected: delegate
|
|
|
|
|
{
|
|
|
|
|
GameMain.Client?.CreateKickReasonPrompt(client.Name, true);
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
GUIContextMenu.CreateContextMenu(null, client.Name, headerColor: clientColor, options.ToArray());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
public void AddToGUIUpdateList()
|
|
|
|
|
{
|
|
|
|
|
if (GUI.DisableHUD) { return; }
|
|
|
|
@@ -1902,7 +1804,7 @@ namespace Barotrauma
|
|
|
|
|
private Hull hullContext;
|
|
|
|
|
private WallSection wallContext;
|
|
|
|
|
private bool isContextual;
|
|
|
|
|
private readonly List<Order> contextualOrders = new List<Order>();
|
|
|
|
|
private readonly List<OrderInfo> contextualOrders = new List<OrderInfo>();
|
|
|
|
|
private Point shorcutCenterNodeOffset;
|
|
|
|
|
private const int maxShortcutNodeCount = 4;
|
|
|
|
|
|
|
|
|
@@ -2605,7 +2507,7 @@ namespace Barotrauma
|
|
|
|
|
{
|
|
|
|
|
order = orders[i];
|
|
|
|
|
disableNode = !CanCharacterBeHeard() ||
|
|
|
|
|
(order.MustSetTarget && (order.ItemComponentType != null || order.TargetItems.Length > 0) &&
|
|
|
|
|
(order.MustSetTarget && (order.ItemComponentType != null || order.GetTargetItems().Any() || order.RequireItems.Any()) &&
|
|
|
|
|
order.GetMatchingItems(true, interactableFor: characterContext ?? Character.Controlled).None());
|
|
|
|
|
optionNodes.Add(new Tuple<GUIComponent, Keys>(
|
|
|
|
|
CreateOrderNode(nodeSize, commandFrame.RectTransform, offsets[i].ToPoint(), order, (i + 1) % 10, disableNode: disableNode, checkIfOrderCanBeHeard: false),
|
|
|
|
@@ -2621,7 +2523,6 @@ namespace Barotrauma
|
|
|
|
|
if (contextualOrders.None())
|
|
|
|
|
{
|
|
|
|
|
string orderIdentifier;
|
|
|
|
|
|
|
|
|
|
// Check if targeting an item or a hull
|
|
|
|
|
if (itemContext != null && itemContext.IsPlayerTeamInteractable)
|
|
|
|
|
{
|
|
|
|
@@ -2630,84 +2531,89 @@ namespace Barotrauma
|
|
|
|
|
{
|
|
|
|
|
targetComponent = null;
|
|
|
|
|
if (p.UseController && itemContext.Components.None(c => c is Controller)) { continue; }
|
|
|
|
|
if ((p.TargetItems.Length > 0 && (p.TargetItems.Contains(itemContext.Prefab.Identifier) || itemContext.HasTag(p.TargetItems))) ||
|
|
|
|
|
p.TryGetTargetItemComponent(itemContext, out targetComponent))
|
|
|
|
|
if (p.HasOptionSpecificTargetItems)
|
|
|
|
|
{
|
|
|
|
|
contextualOrders.Add(p.HasOptions ? p : new Order(p, itemContext, targetComponent, Character.Controlled));
|
|
|
|
|
foreach (string option in p.Options)
|
|
|
|
|
{
|
|
|
|
|
if (p.TargetItemsMatchItem(itemContext, option))
|
|
|
|
|
{
|
|
|
|
|
contextualOrders.Add(new OrderInfo(new Order(p, itemContext, targetComponent, Character.Controlled), option));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (p.TargetItemsMatchItem(itemContext) || p.TryGetTargetItemComponent(itemContext, out targetComponent))
|
|
|
|
|
{
|
|
|
|
|
contextualOrders.Add(new OrderInfo(p.HasOptions ? p : new Order(p, itemContext, targetComponent, Character.Controlled), null));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If targeting a periscope connected to a turret, show the 'operateweapons' order
|
|
|
|
|
orderIdentifier = "operateweapons";
|
|
|
|
|
var operateWeaponsPrefab = Order.GetPrefab(orderIdentifier);
|
|
|
|
|
if (contextualOrders.None(o => o.Identifier.Equals(orderIdentifier)) && itemContext.Components.Any(c => c is Controller))
|
|
|
|
|
if (contextualOrders.None(info => info.Order.Identifier.Equals(orderIdentifier)) && itemContext.Components.Any(c => c is Controller))
|
|
|
|
|
{
|
|
|
|
|
var turret = itemContext.GetConnectedComponents<Turret>().FirstOrDefault(c => c.Item.HasTag(operateWeaponsPrefab.TargetItems)) ??
|
|
|
|
|
itemContext.GetConnectedComponents<Turret>(recursive: true).FirstOrDefault(c => c.Item.HasTag(operateWeaponsPrefab.TargetItems));
|
|
|
|
|
if (turret != null) { contextualOrders.Add(new Order(operateWeaponsPrefab, turret.Item, turret, Character.Controlled)); }
|
|
|
|
|
var turret = itemContext.GetConnectedComponents<Turret>().FirstOrDefault(c => operateWeaponsPrefab.TargetItemsMatchItem(c.Item)) ??
|
|
|
|
|
itemContext.GetConnectedComponents<Turret>(recursive: true).FirstOrDefault(c => operateWeaponsPrefab.TargetItemsMatchItem(c.Item));
|
|
|
|
|
if (turret != null)
|
|
|
|
|
{
|
|
|
|
|
contextualOrders.Add(new OrderInfo(new Order(operateWeaponsPrefab, turret.Item, turret, Character.Controlled), null));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If targeting a repairable item with condition below the repair threshold, show the 'repairsystems' order
|
|
|
|
|
orderIdentifier = "repairsystems";
|
|
|
|
|
if (contextualOrders.None(o => o.Identifier.Equals(orderIdentifier)) && itemContext.Repairables.Any(r => r.IsBelowRepairThreshold))
|
|
|
|
|
if (contextualOrders.None(info => info.Order.Identifier.Equals(orderIdentifier)) && itemContext.Repairables.Any(r => r.IsBelowRepairThreshold))
|
|
|
|
|
{
|
|
|
|
|
if (itemContext.Repairables.Any(r => r != null && r.requiredSkills.Any(s => s != null && s.Identifier.Equals("electrical"))))
|
|
|
|
|
{
|
|
|
|
|
contextualOrders.Add(new Order(Order.GetPrefab("repairelectrical"), itemContext, targetItem: null, Character.Controlled));
|
|
|
|
|
contextualOrders.Add(new OrderInfo(new Order(Order.GetPrefab("repairelectrical"), itemContext, targetItem: null, Character.Controlled), null));
|
|
|
|
|
}
|
|
|
|
|
else if (itemContext.Repairables.Any(r => r != null && r.requiredSkills.Any(s => s != null && s.Identifier.Equals("mechanical"))))
|
|
|
|
|
{
|
|
|
|
|
contextualOrders.Add(new Order(Order.GetPrefab("repairmechanical"), itemContext, targetItem: null, Character.Controlled));
|
|
|
|
|
contextualOrders.Add(new OrderInfo(new Order(Order.GetPrefab("repairmechanical"), itemContext, targetItem: null, Character.Controlled), null));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
contextualOrders.Add(new Order(Order.GetPrefab(orderIdentifier), itemContext, targetItem: null, Character.Controlled));
|
|
|
|
|
contextualOrders.Add(new OrderInfo(new Order(Order.GetPrefab(orderIdentifier), itemContext, targetItem: null, Character.Controlled), null));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Remove the 'pumpwater' order if the target pump is auto-controlled (as it will immediately overwrite the work done by the bot)
|
|
|
|
|
orderIdentifier = "pumpwater";
|
|
|
|
|
if (contextualOrders.FirstOrDefault(o => o.Identifier.Equals(orderIdentifier)) is Order o &&
|
|
|
|
|
itemContext.Components.FirstOrDefault(c => c.GetType() == o.ItemComponentType) is Pump pump)
|
|
|
|
|
if (contextualOrders.FirstOrDefault(info => info.Order.Identifier.Equals(orderIdentifier)) is OrderInfo pumpOrderInfo && pumpOrderInfo.Order is Order pumpOrder &&
|
|
|
|
|
itemContext.Components.FirstOrDefault(c => c.GetType() == pumpOrder.ItemComponentType) is Pump pump && pump.IsAutoControlled)
|
|
|
|
|
{
|
|
|
|
|
if (pump.IsAutoControlled) { contextualOrders.Remove(o); }
|
|
|
|
|
contextualOrders.Remove(pumpOrderInfo);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (contextualOrders.None())
|
|
|
|
|
{
|
|
|
|
|
orderIdentifier = "cleanupitems";
|
|
|
|
|
if (contextualOrders.None(o => o.Identifier.Equals(orderIdentifier)))
|
|
|
|
|
if (contextualOrders.None(info => info.Order.Identifier.Equals(orderIdentifier)))
|
|
|
|
|
{
|
|
|
|
|
if (AIObjectiveCleanupItems.IsValidTarget(itemContext, Character.Controlled, checkInventory: false) || AIObjectiveCleanupItems.IsValidContainer(itemContext, Character.Controlled))
|
|
|
|
|
{
|
|
|
|
|
contextualOrders.Add(new Order(Order.GetPrefab(orderIdentifier), itemContext, targetItem: null, Character.Controlled));
|
|
|
|
|
contextualOrders.Add(new OrderInfo(new Order(Order.GetPrefab(orderIdentifier), itemContext, targetItem: null, Character.Controlled), null));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AddIgnoreOrder(itemContext);
|
|
|
|
|
}
|
|
|
|
|
else if (hullContext != null)
|
|
|
|
|
{
|
|
|
|
|
contextualOrders.Add(new Order(Order.GetPrefab("fixleaks"), hullContext, targetItem: null, Character.Controlled));
|
|
|
|
|
|
|
|
|
|
contextualOrders.Add(new OrderInfo(new Order(Order.GetPrefab("fixleaks"), hullContext, targetItem: null, Character.Controlled), null));
|
|
|
|
|
if (wallContext != null)
|
|
|
|
|
{
|
|
|
|
|
AddIgnoreOrder(wallContext);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AddIgnoreOrder(IIgnorable target)
|
|
|
|
|
{
|
|
|
|
|
var orderIdentifier = "ignorethis";
|
|
|
|
|
if (!target.OrderedToBeIgnored && contextualOrders.None(o => o.Identifier == orderIdentifier))
|
|
|
|
|
if (!target.OrderedToBeIgnored && contextualOrders.None(info => info.Order.Identifier == orderIdentifier))
|
|
|
|
|
{
|
|
|
|
|
AddOrder();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
orderIdentifier = "unignorethis";
|
|
|
|
|
if (target.OrderedToBeIgnored && contextualOrders.None(o => o.Identifier == orderIdentifier))
|
|
|
|
|
if (target.OrderedToBeIgnored && contextualOrders.None(info => info.Order.Identifier == orderIdentifier))
|
|
|
|
|
{
|
|
|
|
|
AddOrder();
|
|
|
|
|
}
|
|
|
|
@@ -2717,64 +2623,61 @@ namespace Barotrauma
|
|
|
|
|
{
|
|
|
|
|
if (target is WallSection ws)
|
|
|
|
|
{
|
|
|
|
|
contextualOrders.Add(new Order(Order.GetPrefab(orderIdentifier), ws.Wall, ws.Wall.Sections.IndexOf(ws), orderGiver: Character.Controlled));
|
|
|
|
|
contextualOrders.Add(new OrderInfo(new Order(Order.GetPrefab(orderIdentifier), ws.Wall, ws.Wall.Sections.IndexOf(ws), orderGiver: Character.Controlled), null));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
contextualOrders.Add(new Order(Order.GetPrefab(orderIdentifier), target as Entity, null, Character.Controlled));
|
|
|
|
|
contextualOrders.Add(new OrderInfo(new Order(Order.GetPrefab(orderIdentifier), target as Entity, null, Character.Controlled), null));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
orderIdentifier = "wait";
|
|
|
|
|
if (contextualOrders.None(o => o.Identifier.Equals(orderIdentifier)))
|
|
|
|
|
if (contextualOrders.None(info => info.Order.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));
|
|
|
|
|
contextualOrders.Add(new OrderInfo(new Order(Order.GetPrefab(orderIdentifier), new OrderTarget(position, hull), Character.Controlled), null));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (contextualOrders.None(o => o.Category != OrderCategory.Movement) && characters.Any(c => c != Character.Controlled))
|
|
|
|
|
if (contextualOrders.None(info => info.Order.Category != OrderCategory.Movement) && characters.Any(c => c != Character.Controlled))
|
|
|
|
|
{
|
|
|
|
|
orderIdentifier = "follow";
|
|
|
|
|
if (contextualOrders.None(o => o.Identifier.Equals(orderIdentifier)))
|
|
|
|
|
if (contextualOrders.None(info => info.Order.Identifier.Equals(orderIdentifier)))
|
|
|
|
|
{
|
|
|
|
|
contextualOrders.Add(Order.GetPrefab(orderIdentifier));
|
|
|
|
|
contextualOrders.Add(new OrderInfo(Order.GetPrefab(orderIdentifier), null));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Show 'dismiss' order only when there are crew members with active orders
|
|
|
|
|
orderIdentifier = "dismissed";
|
|
|
|
|
if (contextualOrders.None(o => o.Identifier.Equals(orderIdentifier)) && characters.Any(c => !c.IsDismissed))
|
|
|
|
|
if (contextualOrders.None(info => info.Order.Identifier.Equals(orderIdentifier)) && characters.Any(c => !c.IsDismissed))
|
|
|
|
|
{
|
|
|
|
|
contextualOrders.Add(Order.GetPrefab(orderIdentifier));
|
|
|
|
|
contextualOrders.Add(new OrderInfo(Order.GetPrefab(orderIdentifier), null));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var offsets = MathUtils.GetPointsOnCircumference(Vector2.Zero, nodeDistance, contextualOrders.Count, MathHelper.ToRadians(90f + 180f / contextualOrders.Count));
|
|
|
|
|
bool disableNode = !CanCharacterBeHeard();
|
|
|
|
|
for (int i = 0; i < contextualOrders.Count; i++)
|
|
|
|
|
{
|
|
|
|
|
optionNodes.Add(new Tuple<GUIComponent, Keys>(
|
|
|
|
|
CreateOrderNode(nodeSize, commandFrame.RectTransform, offsets[i].ToPoint(), contextualOrders[i], (i + 1) % 10, disableNode: disableNode, checkIfOrderCanBeHeard: false),
|
|
|
|
|
!disableNode ? Keys.D0 + (i + 1) % 10 : Keys.None));
|
|
|
|
|
var info = contextualOrders[i];
|
|
|
|
|
int hotkey = (i + 1) % 10;
|
|
|
|
|
var component = string.IsNullOrEmpty(info.OrderOption) ?
|
|
|
|
|
CreateOrderNode(nodeSize, commandFrame.RectTransform, offsets[i].ToPoint(), info.Order, hotkey, disableNode: disableNode, checkIfOrderCanBeHeard: false) :
|
|
|
|
|
CreateOrderOptionNode(nodeSize, commandFrame.RectTransform, offsets[i].ToPoint(), info.Order, info.OrderOption, info.Order.Prefab.GetOptionName(info.OrderOption), hotkey);
|
|
|
|
|
optionNodes.Add(new Tuple<GUIComponent, Keys>(component, !disableNode ? Keys.D0 + (i + 1) % 10 : Keys.None));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO: there's duplicate logic here and above -> would be better to refactor so that the conditions are only defined in one place
|
|
|
|
|
public static bool DoesItemHaveContextualOrders(Item item)
|
|
|
|
|
{
|
|
|
|
|
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.TargetItemsMatchItem(item))) { return true; }
|
|
|
|
|
if (Order.PrefabList.Any(o => o.TryGetTargetItemComponent(item, out _))) { return true; }
|
|
|
|
|
if (AIObjectiveCleanupItems.IsValidTarget(item, Character.Controlled, checkInventory: false)) { return true; }
|
|
|
|
|
if (AIObjectiveCleanupItems.IsValidContainer(item, Character.Controlled)) { return true; }
|
|
|
|
|
|
|
|
|
|
if (Order.GetPrefab("loaditems") is Order loadItemsPrefab && AIObjectiveLoadItems.IsValidTarget(item, Character.Controlled, targetContainerTags: loadItemsPrefab.GetTargetItems())) { return true; }
|
|
|
|
|
if (item.Repairables.Any(r => r.IsBelowRepairThreshold)) { return true; }
|
|
|
|
|
var operateWeaponsPrefab = Order.GetPrefab("operateweapons");
|
|
|
|
|
return item.Components.Any(c => c is Controller) &&
|
|
|
|
|
(item.GetConnectedComponents<Turret>().Any(c => c.Item.HasTag(operateWeaponsPrefab.TargetItems)) ||
|
|
|
|
|
item.GetConnectedComponents<Turret>(recursive: true).Any(c => c.Item.HasTag(operateWeaponsPrefab.TargetItems)));
|
|
|
|
|
return Order.GetPrefab("operateweapons") is Order operateWeaponsPrefab && item.Components.Any(c => c is Controller) &&
|
|
|
|
|
(item.GetConnectedComponents<Turret>().Any(c => operateWeaponsPrefab.TargetItemsMatchItem(c.Item)) ||
|
|
|
|
|
item.GetConnectedComponents<Turret>(recursive: true).Any(c => operateWeaponsPrefab.TargetItemsMatchItem(c.Item)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <param name="hotkey">Use a negative value (e.g. -1) if there should be no hotkey associated with the node</param>
|
|
|
|
@@ -2831,7 +2734,8 @@ namespace Barotrauma
|
|
|
|
|
o = new Order(o.Prefab, orderTargetEntity, orderTargetEntity.Components.FirstOrDefault(ic => ic.GetType() == order.ItemComponentType), orderGiver: order.OrderGiver);
|
|
|
|
|
}
|
|
|
|
|
var character = !o.TargetAllCharacters ? characterContext ?? GetCharacterForQuickAssignment(o) : null;
|
|
|
|
|
SetCharacterOrder(character, o, null, CharacterInfo.HighestManualOrderPriority, Character.Controlled);
|
|
|
|
|
int priority = GetManualOrderPriority(character, o);
|
|
|
|
|
SetCharacterOrder(character, o, null, priority, Character.Controlled);
|
|
|
|
|
DisableCommandUI();
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
@@ -2943,7 +2847,9 @@ namespace Barotrauma
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
SetCharacterOrder(characterContext ?? GetCharacterForQuickAssignment(o.Item1), o.Item1, o.Item2, CharacterInfo.HighestManualOrderPriority, Character.Controlled);
|
|
|
|
|
var character = characterContext ?? GetCharacterForQuickAssignment(o.Item1);
|
|
|
|
|
int priority = GetManualOrderPriority(character, o.Item1);
|
|
|
|
|
SetCharacterOrder(character, o.Item1, o.Item2, priority, Character.Controlled);
|
|
|
|
|
DisableCommandUI();
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
@@ -3013,7 +2919,9 @@ namespace Barotrauma
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
SetCharacterOrder(characterContext ?? GetCharacterForQuickAssignment(o.Item1), o.Item1, o.Item2, CharacterInfo.HighestManualOrderPriority, Character.Controlled);
|
|
|
|
|
var character = characterContext ?? GetCharacterForQuickAssignment(o.Item1);
|
|
|
|
|
int priority = GetManualOrderPriority(character, o.Item1);
|
|
|
|
|
SetCharacterOrder(character, o.Item1, o.Item2, priority, Character.Controlled);
|
|
|
|
|
DisableCommandUI();
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
@@ -3218,7 +3126,9 @@ namespace Barotrauma
|
|
|
|
|
OnClicked = (_, userData) =>
|
|
|
|
|
{
|
|
|
|
|
if (!CanIssueOrders) { return false; }
|
|
|
|
|
SetCharacterOrder(userData as Character, order.Item1, order.Item2, CharacterInfo.HighestManualOrderPriority, Character.Controlled);
|
|
|
|
|
var character = userData as Character;
|
|
|
|
|
int priority = GetManualOrderPriority(character, order.Item1);
|
|
|
|
|
SetCharacterOrder(character, order.Item1, order.Item2, priority, Character.Controlled);
|
|
|
|
|
DisableCommandUI();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
@@ -3496,6 +3406,11 @@ namespace Barotrauma
|
|
|
|
|
return order.Name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private int GetManualOrderPriority(Character character, Order order)
|
|
|
|
|
{
|
|
|
|
|
return character?.Info?.GetManualOrderPriority(order) ?? CharacterInfo.HighestManualOrderPriority;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#region Crew Member Assignment Logic
|
|
|
|
|
private bool CanOpenManualAssignment(GUIComponent node)
|
|
|
|
|
{
|
|
|
|
|