Unstable 0.17.1.0
This commit is contained in:
@@ -184,7 +184,7 @@ namespace Barotrauma
|
||||
}
|
||||
// Exchange money
|
||||
Location.StoreCurrentBalance -= itemValue;
|
||||
campaign.Money += itemValue;
|
||||
campaign.Wallet.TryDeduct(itemValue);
|
||||
GameAnalyticsManager.AddMoneyGainedEvent(itemValue, GameAnalyticsManager.MoneySource.Store, item.ItemPrefab.Identifier.Value);
|
||||
|
||||
// Remove from the sell crate
|
||||
|
||||
@@ -236,7 +236,7 @@ namespace Barotrauma
|
||||
|
||||
if (crewManager != null)
|
||||
{
|
||||
Order order = new Order(orderPrefab, Identifier.Empty, CharacterInfo.HighestManualOrderPriority, Order.OrderType.Current, null, null, orderGiver: Character.Controlled);
|
||||
Order order = orderPrefab.CreateInstance(OrderPrefab.OrderTargetType.Entity, orderGiver: Character.Controlled);
|
||||
crewManager.SetCharacterOrder(null, order);
|
||||
if (crewManager.IsSinglePlayer) { HumanAIController.ReportProblem(Character.Controlled, order); }
|
||||
}
|
||||
@@ -290,16 +290,6 @@ namespace Barotrauma
|
||||
return crewArea.Rect;
|
||||
}
|
||||
|
||||
public IEnumerable<Character> GetCharacters()
|
||||
{
|
||||
return characters;
|
||||
}
|
||||
|
||||
public IEnumerable<CharacterInfo> GetCharacterInfos()
|
||||
{
|
||||
return characterInfos;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove the character from the crew (and crew menus).
|
||||
/// </summary>
|
||||
@@ -708,7 +698,8 @@ namespace Barotrauma
|
||||
List<Character> availableSpeakers = Character.CharacterList.FindAll(c =>
|
||||
c.AIController is HumanAIController &&
|
||||
!c.IsDead &&
|
||||
c.SpeechImpediment <= 100.0f);
|
||||
c.SpeechImpediment <= 100.0f &&
|
||||
c.CharacterHealth.GetAllAfflictions(a => a is AfflictionHusk huskInfection && huskInfection.Prefab is AfflictionPrefabHusk { CauseSpeechImpediment: true }).None());
|
||||
pendingConversationLines.AddRange(NPCConversation.CreateRandom(availableSpeakers));
|
||||
}
|
||||
|
||||
@@ -837,7 +828,7 @@ namespace Barotrauma
|
||||
var orderGiver = order?.OrderGiver;
|
||||
if (IsSinglePlayer)
|
||||
{
|
||||
character.SetOrder(order, speak: orderGiver != character);
|
||||
character.SetOrder(order, isNewOrder, speak: orderGiver != character);
|
||||
string message = order?.GetChatMessage(character.Name, orderGiver?.CurrentHull?.DisplayName?.Value, givingOrderToSelf: character == orderGiver, orderOption: order?.Option ?? Identifier.Empty, isNewOrder: isNewOrder);
|
||||
orderGiver?.Speak(message);
|
||||
}
|
||||
@@ -2437,26 +2428,26 @@ namespace Barotrauma
|
||||
optionNodes.Add(new OptionNode(node, Keys.D0 + hotkey % 10));
|
||||
}
|
||||
|
||||
/// <remarks>
|
||||
/// The order giver doesn't need to be set for the Order instances as it will be set when the node button is clicked.
|
||||
/// </remarks>
|
||||
private void CreateShortcutNodes()
|
||||
{
|
||||
bool HasAppropriateJobId(Character c, Identifier jobId) => c.Info?.Job != null && c.Info.Job.Prefab.AppropriateOrders.Contains(jobId);
|
||||
bool HasAppropriateJob(Character c, string jobId) => HasAppropriateJobId(c, jobId.ToIdentifier());
|
||||
|
||||
var sub = GetTargetSubmarine();
|
||||
if (sub == null) { return; }
|
||||
if (!(GetTargetSubmarine() is { } sub)) { return; }
|
||||
shortcutNodes.Clear();
|
||||
if (CanFitMoreNodes() && sub.GetItems(false).Find(i => i.HasTag("reactor") && i.IsPlayerTeamInteractable)?.GetComponent<Reactor>() is Reactor reactor)
|
||||
var subItems = sub.GetItems(false);
|
||||
if (CanFitMoreNodes() && subItems.Find(i => i.HasTag("reactor") && i.IsPlayerTeamInteractable)?.GetComponent<Reactor>() is Reactor reactor)
|
||||
{
|
||||
float 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
|
||||
// --> Create shortcut node for "Operate Reactor" order's "Power Up" option
|
||||
if (ShouldDelegateOrder("operatereactor") && reactorOutput < float.Epsilon && characters.None(c => c.SelectedConstruction == reactor.Item))
|
||||
{
|
||||
var orderPrefab = OrderPrefab.Prefabs["operatereactor"];
|
||||
var order = new Order(orderPrefab, orderPrefab.Options[0], reactor.Item, reactor, Character.Controlled);
|
||||
var order = new Order(orderPrefab, orderPrefab.Options[0], reactor.Item, reactor);
|
||||
if (IsNonDuplicateOrder(order))
|
||||
{
|
||||
shortcutNodes.Add(CreateOrderOptionNode(shortcutNodeSize, null, Point.Zero, order, -1));
|
||||
AddOrderNode(order);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2464,11 +2455,11 @@ namespace Barotrauma
|
||||
// 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 (CanFitMoreNodes() && ShouldDelegateOrder("steer") && IsNonDuplicateOrderPrefab(OrderPrefab.Prefabs["steer"]) &&
|
||||
sub.GetItems(false).Find(i => i.HasTag("navterminal") && i.IsPlayerTeamInteractable) is Item nav && characters.None(c => c.SelectedConstruction == nav) &&
|
||||
subItems.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)
|
||||
{
|
||||
var order = new Order(OrderPrefab.Prefabs["steer"], steering.Item, steering, Character.Controlled);
|
||||
shortcutNodes.Add(CreateOrderNode(shortcutNodeSize, null, Point.Zero, order, -1));
|
||||
var order = new Order(OrderPrefab.Prefabs["steer"], steering.Item, steering);
|
||||
AddOrderNode(order);
|
||||
}
|
||||
// If player is not a security officer AND invaders are reported
|
||||
// --> Create shorcut node for Fight Intruders order
|
||||
@@ -2476,8 +2467,7 @@ namespace Barotrauma
|
||||
ActiveOrders.Any(o => o.Order.Identifier == "reportintruders") &&
|
||||
IsNonDuplicateOrderPrefab(OrderPrefab.Prefabs["fightintruders"]))
|
||||
{
|
||||
var order = new Order(OrderPrefab.Prefabs["fightintruders"], null, orderGiver: Character.Controlled);
|
||||
shortcutNodes.Add(CreateOrderNode(shortcutNodeSize, null, Point.Zero, order, -1));
|
||||
AddOrderNodeWithIdentifier("fightintruders");
|
||||
}
|
||||
// If player is not a mechanic AND a breach has been reported
|
||||
// --> Create shorcut node for Fix Leaks order
|
||||
@@ -2485,8 +2475,7 @@ namespace Barotrauma
|
||||
IsNonDuplicateOrderPrefab(OrderPrefab.Prefabs["fixleaks"]) &&
|
||||
ActiveOrders.Any(o => o.Order.Identifier == "reportbreach"))
|
||||
{
|
||||
var order = new Order(OrderPrefab.Prefabs["fixleaks"], null, orderGiver: Character.Controlled);
|
||||
shortcutNodes.Add(CreateOrderNode(shortcutNodeSize, null, Point.Zero, order, -1));
|
||||
AddOrderNodeWithIdentifier("fixleaks");
|
||||
}
|
||||
// --> Create shortcut nodes for the Repair orders
|
||||
if (CanFitMoreNodes() && ActiveOrders.Any(o => o.Order.Identifier == "reportbrokendevices"))
|
||||
@@ -2494,33 +2483,27 @@ namespace Barotrauma
|
||||
var reportBrokenDevices = OrderPrefab.Prefabs["reportbrokendevices"];
|
||||
// TODO: Doesn't work for player issued reports, because they don't have a target.
|
||||
bool useSpecificRepairOrder = false;
|
||||
string tag = "repairelectrical";
|
||||
if (CanFitMoreNodes() && ShouldDelegateOrder(tag) &&
|
||||
if (CanFitMoreNodes() && ShouldDelegateOrder("repairelectrical") &&
|
||||
ActiveOrders.Any(o => o.Order.Prefab == reportBrokenDevices && o.Order.TargetItemComponent is Repairable r && r.requiredSkills.Any(s => s.Identifier == "electrical")))
|
||||
{
|
||||
if (IsNonDuplicateOrderPrefab(OrderPrefab.Prefabs[tag]))
|
||||
if (IsNonDuplicateOrderPrefab(OrderPrefab.Prefabs["repairelectrical"]))
|
||||
{
|
||||
var order = new Order(OrderPrefab.Prefabs[tag], null, orderGiver: Character.Controlled);
|
||||
shortcutNodes.Add(CreateOrderNode(shortcutNodeSize, null, Point.Zero, order, -1));
|
||||
AddOrderNodeWithIdentifier("repairelectrical");
|
||||
}
|
||||
useSpecificRepairOrder = true;
|
||||
}
|
||||
tag = "repairmechanical";
|
||||
if (CanFitMoreNodes() && ShouldDelegateOrder(tag) &&
|
||||
if (CanFitMoreNodes() && ShouldDelegateOrder("repairmechanical") &&
|
||||
ActiveOrders.Any(o => o.Order.Prefab == reportBrokenDevices && o.Order.TargetItemComponent is Repairable r && r.requiredSkills.Any(s => s.Identifier == "mechanical")))
|
||||
{
|
||||
if (IsNonDuplicateOrderPrefab(OrderPrefab.Prefabs[tag]))
|
||||
if (IsNonDuplicateOrderPrefab(OrderPrefab.Prefabs["repairmechanical"]))
|
||||
{
|
||||
var order = new Order(OrderPrefab.Prefabs[tag], null, orderGiver: Character.Controlled);
|
||||
shortcutNodes.Add(CreateOrderNode(shortcutNodeSize, null, Point.Zero, order, -1));
|
||||
AddOrderNodeWithIdentifier("repairmechanical");
|
||||
}
|
||||
useSpecificRepairOrder = true;
|
||||
}
|
||||
tag = "repairsystems";
|
||||
if (!useSpecificRepairOrder && CanFitMoreNodes() && ShouldDelegateOrder(tag) && OrderPrefab.Prefabs[tag] is OrderPrefab repairOrder && IsNonDuplicateOrderPrefab(repairOrder))
|
||||
if (!useSpecificRepairOrder && CanFitMoreNodes() && ShouldDelegateOrder("repairsystems") && OrderPrefab.Prefabs["repairsystems"] is OrderPrefab repairOrder && IsNonDuplicateOrderPrefab(repairOrder))
|
||||
{
|
||||
var order = new Order(OrderPrefab.Prefabs[tag], null, orderGiver: Character.Controlled);
|
||||
shortcutNodes.Add(CreateOrderNode(shortcutNodeSize, null, Point.Zero, order, -1));
|
||||
AddOrderNodeWithIdentifier("repairsystems");
|
||||
}
|
||||
}
|
||||
// If fire is reported
|
||||
@@ -2528,8 +2511,7 @@ namespace Barotrauma
|
||||
if (CanFitMoreNodes() && IsNonDuplicateOrderPrefab(OrderPrefab.Prefabs["extinguishfires"]) &&
|
||||
ActiveOrders.Any(o => o.Order.Identifier == "reportfire"))
|
||||
{
|
||||
var order = new Order(OrderPrefab.Prefabs["extinguishfires"], null, orderGiver: Character.Controlled);
|
||||
shortcutNodes.Add(CreateOrderNode(shortcutNodeSize, null, Point.Zero, order, -1));
|
||||
AddOrderNodeWithIdentifier("extinguishfires");
|
||||
}
|
||||
if (CanFitMoreNodes() && characterContext?.Info?.Job?.Prefab?.AppropriateOrders != null)
|
||||
{
|
||||
@@ -2541,8 +2523,8 @@ namespace Barotrauma
|
||||
{
|
||||
if (!orderPrefab.MustSetTarget || orderPrefab.GetMatchingItems(sub, true, interactableFor: characterContext ?? Character.Controlled).Any())
|
||||
{
|
||||
var order = new Order(orderPrefab, null, orderGiver: Character.Controlled);
|
||||
shortcutNodes.Add(CreateOrderNode(shortcutNodeSize, null, Point.Zero, order, -1));
|
||||
var order = orderPrefab.CreateInstance(OrderPrefab.OrderTargetType.Entity);
|
||||
AddOrderNode(order);
|
||||
}
|
||||
if (!CanFitMoreNodes()) { break; }
|
||||
}
|
||||
@@ -2550,9 +2532,8 @@ namespace Barotrauma
|
||||
}
|
||||
if (CanFitMoreNodes() && characterContext != null && !characterContext.IsDismissed)
|
||||
{
|
||||
var order = new Order(OrderPrefab.Dismissal, null, orderGiver: Character.Controlled);
|
||||
shortcutNodes.Add(
|
||||
CreateOrderNode(shortcutNodeSize, null, Point.Zero, order, -1));
|
||||
var order = OrderPrefab.Dismissal.CreateInstance(OrderPrefab.OrderTargetType.Entity);
|
||||
AddOrderNode(order);
|
||||
}
|
||||
shortcutNodes.RemoveAll(n => n.UserData is Order o && !IsOrderAvailable(o));
|
||||
if (shortcutNodes.Count < 1) { return; }
|
||||
@@ -2593,18 +2574,30 @@ namespace Barotrauma
|
||||
characterContext.CurrentOrders.None(oi => oi?.Identifier == orderPrefab?.Identifier) :
|
||||
characterContext.CurrentOrders.None(oi => oi?.Identifier == orderPrefab?.Identifier && oi.Option == option));
|
||||
}
|
||||
void AddOrderNodeWithIdentifier(string identifier)
|
||||
{
|
||||
var order = OrderPrefab.Prefabs[identifier].CreateInstance(OrderPrefab.OrderTargetType.Entity);
|
||||
AddOrderNode(order);
|
||||
}
|
||||
void AddOrderNode(Order order)
|
||||
{
|
||||
var node = order.Option.IsEmpty ?
|
||||
CreateOrderNode(shortcutNodeSize, null, Point.Zero, order, -1) :
|
||||
CreateOrderOptionNode(shortcutNodeSize, null, Point.Zero, order, -1);
|
||||
shortcutNodes.Add(node);
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateOrderNodes(OrderCategory orderCategory)
|
||||
{
|
||||
var orderPrefabs = OrderPrefab.Prefabs.Where(o => o.Category == orderCategory && !o.IsReport && IsOrderAvailable(o)).ToArray();
|
||||
var orderPrefabs = OrderPrefab.Prefabs.Where(o => o.Category == orderCategory && !o.IsReport && IsOrderAvailable(o)).OrderBy(o => o.Identifier).ToArray();
|
||||
Order order;
|
||||
bool disableNode;
|
||||
var offsets = MathUtils.GetPointsOnCircumference(Vector2.Zero, nodeDistance,
|
||||
GetCircumferencePointCount(orderPrefabs.Length), GetFirstNodeAngle(orderPrefabs.Length));
|
||||
for (int i = 0; i < orderPrefabs.Length; i++)
|
||||
{
|
||||
order = new Order(orderPrefabs[i], null, orderGiver: Character.Controlled);
|
||||
order = orderPrefabs[i].CreateInstance(OrderPrefab.OrderTargetType.Entity);
|
||||
disableNode = !CanCharacterBeHeard() ||
|
||||
(order.MustSetTarget && (order.ItemComponentType != null || order.GetTargetItems().Any() || order.RequireItems.Any()) &&
|
||||
order.GetMatchingItems(true, interactableFor: characterContext ?? Character.Controlled).None());
|
||||
@@ -2617,11 +2610,13 @@ namespace Barotrauma
|
||||
/// <summary>
|
||||
/// Create order nodes based on the item context
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The order giver doesn't need to be set for the Order instances as it will be set when the node button is clicked.
|
||||
/// </remarks>
|
||||
private void CreateContextualOrderNodes()
|
||||
{
|
||||
if (contextualOrders.None())
|
||||
{
|
||||
string orderIdentifier;
|
||||
// Check if targeting an item or a hull
|
||||
if (itemContext != null && itemContext.IsPlayerTeamInteractable)
|
||||
{
|
||||
@@ -2636,66 +2631,62 @@ namespace Barotrauma
|
||||
{
|
||||
if (p.TargetItemsMatchItem(itemContext, option))
|
||||
{
|
||||
contextualOrders.Add(new Order(p, itemContext, targetComponent, Character.Controlled).WithOption(option));
|
||||
contextualOrders.Add(new Order(p, option, itemContext, targetComponent));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (p.TargetItemsMatchItem(itemContext) || p.TryGetTargetItemComponent(itemContext, out targetComponent))
|
||||
{
|
||||
contextualOrders.Add(p.HasOptions ?
|
||||
new Order(p, null, orderGiver: Character.Controlled) :
|
||||
new Order(p, itemContext, targetComponent, Character.Controlled));
|
||||
p.CreateInstance(OrderPrefab.OrderTargetType.Entity) :
|
||||
new Order(p, itemContext, targetComponent));
|
||||
}
|
||||
}
|
||||
// If targeting a periscope connected to a turret, show the 'operateweapons' order
|
||||
orderIdentifier = "operateweapons";
|
||||
var operateWeaponsPrefab = OrderPrefab.Prefabs[orderIdentifier];
|
||||
if (contextualOrders.None(o => o.Identifier == orderIdentifier) && itemContext.Components.Any(c => c is Controller))
|
||||
var operateWeaponsPrefab = OrderPrefab.Prefabs["operateweapons"];
|
||||
if (contextualOrders.None(o => o.Identifier == "operateweapons") && itemContext.Components.Any(c => c is Controller))
|
||||
{
|
||||
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 Order(operateWeaponsPrefab, turret.Item, turret, Character.Controlled));
|
||||
contextualOrders.Add(new Order(operateWeaponsPrefab, turret.Item, turret));
|
||||
}
|
||||
}
|
||||
// If targeting a repairable item with condition below the repair threshold, show the 'repairsystems' order
|
||||
orderIdentifier = "repairsystems";
|
||||
if (contextualOrders.None(order => order.Identifier == orderIdentifier) && itemContext.Repairables.Any(r => r.IsBelowRepairThreshold))
|
||||
if (contextualOrders.None(order => order.Identifier == "repairsystems") && 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(OrderPrefab.Prefabs["repairelectrical"], itemContext, targetItem: null, Character.Controlled));
|
||||
contextualOrders.Add(new Order(OrderPrefab.Prefabs["repairelectrical"], itemContext, targetItem: null));
|
||||
}
|
||||
else if (itemContext.Repairables.Any(r => r != null && r.requiredSkills.Any(s => s != null && s.Identifier.Equals("mechanical"))))
|
||||
{
|
||||
contextualOrders.Add(new Order(OrderPrefab.Prefabs["repairmechanical"], itemContext, targetItem: null, Character.Controlled));
|
||||
contextualOrders.Add(new Order(OrderPrefab.Prefabs["repairmechanical"], itemContext, targetItem: null));
|
||||
}
|
||||
else
|
||||
{
|
||||
contextualOrders.Add(new Order(OrderPrefab.Prefabs[orderIdentifier], itemContext, targetItem: null, Character.Controlled));
|
||||
contextualOrders.Add(new Order(OrderPrefab.Prefabs["repairsystems"], itemContext, targetItem: 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(order => order.Identifier.Equals(orderIdentifier)) is Order pumpOrder &&
|
||||
if (contextualOrders.FirstOrDefault(order => order.Identifier.Equals("pumpwater")) is Order pumpOrder &&
|
||||
itemContext.Components.FirstOrDefault(c => c.GetType() == pumpOrder.ItemComponentType) is Pump pump && pump.IsAutoControlled)
|
||||
{
|
||||
contextualOrders.Remove(pumpOrder);
|
||||
}
|
||||
orderIdentifier = "cleanupitems";
|
||||
if (contextualOrders.None(info => info.Identifier.Equals(orderIdentifier)))
|
||||
if (contextualOrders.None(info => info.Identifier.Equals("cleanupitems")))
|
||||
{
|
||||
if (AIObjectiveCleanupItems.IsValidTarget(itemContext, Character.Controlled, checkInventory: false) || AIObjectiveCleanupItems.IsValidContainer(itemContext, Character.Controlled))
|
||||
{
|
||||
contextualOrders.Add(new Order(OrderPrefab.Prefabs[orderIdentifier], itemContext, targetItem: null, Character.Controlled));
|
||||
contextualOrders.Add(new Order(OrderPrefab.Prefabs["cleanupitems"], itemContext, targetItem: null));
|
||||
}
|
||||
}
|
||||
AddIgnoreOrder(itemContext);
|
||||
}
|
||||
else if (hullContext != null)
|
||||
{
|
||||
contextualOrders.Add(new Order(OrderPrefab.Prefabs["fixleaks"], hullContext, targetItem: null, Character.Controlled));
|
||||
contextualOrders.Add(new Order(OrderPrefab.Prefabs["fixleaks"], hullContext, targetItem: null));
|
||||
if (wallContext != null)
|
||||
{
|
||||
AddIgnoreOrder(wallContext);
|
||||
@@ -2729,26 +2720,23 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
}
|
||||
orderIdentifier = "wait";
|
||||
if (contextualOrders.None(order => order.Identifier.Equals(orderIdentifier)))
|
||||
if (contextualOrders.None(order => order.Identifier.Equals("wait")))
|
||||
{
|
||||
Vector2 position = GameMain.GameScreen.Cam.ScreenToWorld(PlayerInput.MousePosition);
|
||||
Hull hull = Hull.FindHull(position, guess: Character.Controlled?.CurrentHull);
|
||||
contextualOrders.Add(new Order(OrderPrefab.Prefabs[orderIdentifier], new OrderTarget(position, hull), Character.Controlled));
|
||||
contextualOrders.Add(new Order(OrderPrefab.Prefabs["wait"], new OrderTarget(position, hull)));
|
||||
}
|
||||
if (contextualOrders.None(order => order.Category != OrderCategory.Movement) && characters.Any(c => c != Character.Controlled))
|
||||
{
|
||||
orderIdentifier = "follow";
|
||||
if (contextualOrders.None(order => order.Identifier.Equals(orderIdentifier)))
|
||||
if (contextualOrders.None(order => order.Identifier.Equals("follow")))
|
||||
{
|
||||
contextualOrders.Add(new Order(OrderPrefab.Prefabs[orderIdentifier], null, orderGiver: Character.Controlled));
|
||||
contextualOrders.Add(OrderPrefab.Prefabs["follow"].CreateInstance(OrderPrefab.OrderTargetType.Entity));
|
||||
}
|
||||
}
|
||||
// Show 'dismiss' order only when there are crew members with active orders
|
||||
orderIdentifier = "dismissed";
|
||||
if (contextualOrders.None(order => order.Identifier.Equals(orderIdentifier)) && characters.Any(c => !c.IsDismissed))
|
||||
if (contextualOrders.None(order => order.IsDismissal) && characters.Any(c => !c.IsDismissed))
|
||||
{
|
||||
contextualOrders.Add(new Order(OrderPrefab.Prefabs[orderIdentifier], null, orderGiver: Character.Controlled));
|
||||
contextualOrders.Add(OrderPrefab.Dismissal.CreateInstance(OrderPrefab.OrderTargetType.Entity));
|
||||
}
|
||||
}
|
||||
contextualOrders.RemoveAll(o => !IsOrderAvailable(o));
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
namespace Barotrauma
|
||||
{
|
||||
internal partial class Wallet
|
||||
{
|
||||
public bool IsOwnWallet =>
|
||||
GameMain.GameSession?.Campaign switch
|
||||
{
|
||||
null => false,
|
||||
SinglePlayerCampaign spCampaign => this == spCampaign.Bank,
|
||||
MultiPlayerCampaign mpCampaign => this == mpCampaign.PersonalWallet,
|
||||
_ => false
|
||||
};
|
||||
|
||||
partial void SettingsChanged(Option<int> balanceChanged, Option<int> rewardChanged)
|
||||
{
|
||||
CampaignMode campaign = GameMain.GameSession?.Campaign;
|
||||
WalletChangedData data = new WalletChangedData
|
||||
{
|
||||
BalanceChanged = balanceChanged,
|
||||
RewardDistributionChanged = rewardChanged,
|
||||
};
|
||||
|
||||
campaign?.OnMoneyChanged.Invoke(new WalletChangedEvent(this, data, CreateWalletInfo()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -63,6 +63,8 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public virtual Wallet Wallet => GetWallet();
|
||||
|
||||
public override void ShowStartMessage()
|
||||
{
|
||||
foreach (Mission mission in Missions.ToList())
|
||||
@@ -310,7 +312,7 @@ namespace Barotrauma
|
||||
if (ShowCampaignUI || ForceMapUI)
|
||||
{
|
||||
campaignUIContainer?.AddToGUIUpdateList();
|
||||
if (CampaignUI?.UpgradeStore?.HoveredItem != null)
|
||||
if (CampaignUI?.UpgradeStore?.HoveredEntity != null)
|
||||
{
|
||||
if (CampaignUI.SelectedTab != InteractionType.Upgrade) { return; }
|
||||
CampaignUI?.UpgradeStore?.ItemInfoFrame.AddToGUIUpdateList(order: 1);
|
||||
|
||||
+54
-7
@@ -21,7 +21,7 @@ namespace Barotrauma
|
||||
private UInt16 pendingSaveID = 1;
|
||||
public UInt16 PendingSaveID
|
||||
{
|
||||
get
|
||||
get
|
||||
{
|
||||
return pendingSaveID;
|
||||
}
|
||||
@@ -34,6 +34,14 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public Wallet PersonalWallet => Character.Controlled?.Wallet ?? Wallet.Invalid;
|
||||
public override Wallet Wallet => GetWallet();
|
||||
|
||||
public override Wallet GetWallet(Client client = null)
|
||||
{
|
||||
return PersonalWallet;
|
||||
}
|
||||
|
||||
public static void StartCampaignSetup(IEnumerable<string> saveFiles)
|
||||
{
|
||||
var parent = GameMain.NetLobbyScreen.CampaignSetupFrame;
|
||||
@@ -195,6 +203,11 @@ namespace Barotrauma
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
if (GameMain.Client == null)
|
||||
{
|
||||
yield return CoroutineStatus.Failure;
|
||||
}
|
||||
|
||||
if (GameMain.Client.LateCampaignJoin)
|
||||
{
|
||||
GameMain.Client.LateCampaignJoin = false;
|
||||
@@ -618,7 +631,6 @@ namespace Barotrauma
|
||||
|
||||
bool forceMapUI = msg.ReadBoolean();
|
||||
|
||||
int money = msg.ReadInt32();
|
||||
bool purchasedHullRepairs = msg.ReadBoolean();
|
||||
bool purchasedItemRepairs = msg.ReadBoolean();
|
||||
bool purchasedLostShuttles = msg.ReadBoolean();
|
||||
@@ -812,12 +824,10 @@ namespace Barotrauma
|
||||
GameMain.NetLobbyScreen.ToggleCampaignMode(true);
|
||||
}
|
||||
|
||||
bool shouldRefresh = campaign.Money != money ||
|
||||
campaign.PurchasedHullRepairs != purchasedHullRepairs ||
|
||||
bool shouldRefresh = campaign.PurchasedHullRepairs != purchasedHullRepairs ||
|
||||
campaign.PurchasedItemRepairs != purchasedItemRepairs ||
|
||||
campaign.PurchasedLostShuttles != purchasedLostShuttles;
|
||||
|
||||
campaign.Money = money;
|
||||
campaign.PurchasedHullRepairs = purchasedHullRepairs;
|
||||
campaign.PurchasedItemRepairs = purchasedItemRepairs;
|
||||
campaign.PurchasedLostShuttles = purchasedLostShuttles;
|
||||
@@ -896,6 +906,43 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public void ClientReadMoney(IReadMessage inc)
|
||||
{
|
||||
NetWalletUpdate update = INetSerializableStruct.Read<NetWalletUpdate>(inc);
|
||||
foreach (NetWalletTransaction transaction in update.Transactions)
|
||||
{
|
||||
WalletInfo info = transaction.Info;
|
||||
switch (transaction.CharacterID)
|
||||
{
|
||||
case Some<ushort> { Value: var charID}:
|
||||
{
|
||||
Character targetCharacter = Character.CharacterList?.FirstOrDefault(c => c.ID == charID);
|
||||
if (targetCharacter is null) { break; }
|
||||
Wallet wallet = targetCharacter.Wallet;
|
||||
|
||||
wallet.Balance = info.Balance;
|
||||
wallet.RewardDistribution = info.RewardDistribution;
|
||||
TryInvokeEvent(wallet, transaction.ChangedData, info);
|
||||
break;
|
||||
}
|
||||
case None<ushort> _:
|
||||
{
|
||||
Bank.Balance = info.Balance;
|
||||
TryInvokeEvent(Bank, transaction.ChangedData, info);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TryInvokeEvent(Wallet wallet, WalletChangedData data, WalletInfo info)
|
||||
{
|
||||
if (data.BalanceChanged.IsSome() || data.RewardDistributionChanged.IsSome())
|
||||
{
|
||||
OnMoneyChanged.Invoke(new WalletChangedEvent(wallet, data, info));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Save(XElement element)
|
||||
{
|
||||
//do nothing, the clients get the save files from the server
|
||||
@@ -908,10 +955,10 @@ namespace Barotrauma
|
||||
|
||||
string gamesessionDocPath = Path.Combine(SaveUtil.TempPath, "gamesession.xml");
|
||||
XDocument doc = XMLExtensions.TryLoadXml(gamesessionDocPath);
|
||||
if (doc == null)
|
||||
if (doc == null)
|
||||
{
|
||||
DebugConsole.ThrowError($"Failed to load the state of a multiplayer campaign. Could not open the file \"{gamesessionDocPath}\".");
|
||||
return;
|
||||
return;
|
||||
}
|
||||
Load(doc.Root.Element("MultiPlayerCampaign"));
|
||||
GameMain.GameSession.OwnedSubmarines = SaveUtil.LoadOwnedSubmarines(doc, out SubmarineInfo selectedSub);
|
||||
|
||||
+15
-3
@@ -6,6 +6,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Linq;
|
||||
using Barotrauma.Networking;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -108,6 +109,9 @@ namespace Barotrauma
|
||||
case "pets":
|
||||
petsElement = subElement;
|
||||
break;
|
||||
case Wallet.LowerCaseSaveElementName:
|
||||
Bank = new Wallet(subElement);
|
||||
break;
|
||||
case "stats":
|
||||
LoadStats(subElement);
|
||||
break;
|
||||
@@ -121,7 +125,15 @@ namespace Barotrauma
|
||||
|
||||
InitUI();
|
||||
|
||||
Money = element.GetAttributeInt("money", 0);
|
||||
int oldMoney = element.GetAttributeInt("money", 0);
|
||||
if (oldMoney > 0)
|
||||
{
|
||||
Bank = new Wallet
|
||||
{
|
||||
Balance = oldMoney
|
||||
};
|
||||
}
|
||||
|
||||
PurchasedLostShuttles = element.GetAttributeBool("purchasedlostshuttles", false);
|
||||
PurchasedHullRepairs = element.GetAttributeBool("purchasedhullrepairs", false);
|
||||
PurchasedItemRepairs = element.GetAttributeBool("purchaseditemrepairs", false);
|
||||
@@ -729,7 +741,6 @@ namespace Barotrauma
|
||||
public override void Save(XElement element)
|
||||
{
|
||||
XElement modeElement = new XElement("SinglePlayerCampaign",
|
||||
new XAttribute("money", Money),
|
||||
new XAttribute("purchasedlostshuttles", PurchasedLostShuttles),
|
||||
new XAttribute("purchasedhullrepairs", PurchasedHullRepairs),
|
||||
new XAttribute("purchaseditemrepairs", PurchasedItemRepairs),
|
||||
@@ -756,13 +767,14 @@ namespace Barotrauma
|
||||
|
||||
petsElement = new XElement("pets");
|
||||
PetBehavior.SavePets(petsElement);
|
||||
modeElement.Add(petsElement);
|
||||
modeElement.Add(petsElement);
|
||||
|
||||
CrewManager.Save(modeElement);
|
||||
CampaignMetadata.Save(modeElement);
|
||||
Map.Save(modeElement);
|
||||
CargoManager?.SavePurchasedItems(modeElement);
|
||||
UpgradeManager?.Save(modeElement);
|
||||
modeElement.Add(Bank.Save());
|
||||
element.Add(modeElement);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace Barotrauma
|
||||
|
||||
public TestGameMode(GameModePreset preset) : base(preset)
|
||||
{
|
||||
foreach (JobPrefab jobPrefab in JobPrefab.Prefabs)
|
||||
foreach (JobPrefab jobPrefab in JobPrefab.Prefabs.OrderBy(p => p.Identifier))
|
||||
{
|
||||
for (int i = 0; i < jobPrefab.InitialCount; i++)
|
||||
{
|
||||
|
||||
@@ -190,7 +190,7 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
tabMenu.Update();
|
||||
tabMenu.Update(deltaTime);
|
||||
if ((PlayerInput.KeyHit(InputType.InfoTab) || PlayerInput.KeyHit(Microsoft.Xna.Framework.Input.Keys.Escape)) &&
|
||||
!(GUI.KeyboardDispatcher.Subscriber is GUITextBox))
|
||||
{
|
||||
|
||||
@@ -181,6 +181,11 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
private void OnMoneyChanged(WalletChangedEvent e)
|
||||
{
|
||||
if (e.Wallet.IsOwnWallet) { OnUpdate?.Invoke(); }
|
||||
}
|
||||
|
||||
// if you have more than 5000 ping there are probably more important things to worry about but hey just in case
|
||||
private static DateTimeOffset GetTimeout() => DateTimeOffset.Now.AddSeconds(5).AddMilliseconds(GetPing());
|
||||
|
||||
@@ -241,6 +246,7 @@ namespace Barotrauma
|
||||
private void HealRequestReceived(IReadMessage inc)
|
||||
{
|
||||
NetHealRequest request = INetSerializableStruct.Read<NetHealRequest>(inc);
|
||||
|
||||
if (request.Result == HealRequestResult.Success)
|
||||
{
|
||||
HealAllPending(force: true);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
|
||||
@@ -15,7 +16,6 @@ namespace Barotrauma
|
||||
|
||||
private int jobColumnWidth, characterColumnWidth, statusColumnWidth;
|
||||
|
||||
private readonly SubmarineInfo sub;
|
||||
private readonly List<Mission> selectedMissions;
|
||||
private readonly Location startLocation, endLocation;
|
||||
|
||||
@@ -30,11 +30,8 @@ namespace Barotrauma
|
||||
|
||||
public GUIComponent Frame { get; private set; }
|
||||
|
||||
|
||||
|
||||
public RoundSummary(SubmarineInfo sub, GameMode gameMode, IEnumerable<Mission> selectedMissions, Location startLocation, Location endLocation)
|
||||
public RoundSummary(GameMode gameMode, IEnumerable<Mission> selectedMissions, Location startLocation, Location endLocation)
|
||||
{
|
||||
this.sub = sub;
|
||||
this.gameMode = gameMode;
|
||||
this.selectedMissions = selectedMissions.ToList();
|
||||
this.startLocation = startLocation;
|
||||
@@ -320,6 +317,16 @@ namespace Barotrauma
|
||||
{
|
||||
LocalizedString rewardText = TextManager.GetWithVariable("currencyformat", "[credits]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", reward));
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform), RichString.Rich(displayedMission.GetMissionRewardText(Submarine.MainSub)));
|
||||
if (Character.Controlled is { } controlled)
|
||||
{
|
||||
var (share, percentage) = Mission.GetRewardShare(controlled.Wallet.RewardDistribution, Mission.GetSalaryEligibleCrew(), Option<int>.Some(reward));
|
||||
if (share > 0)
|
||||
{
|
||||
string shareFormatted = string.Format(CultureInfo.InvariantCulture, "{0:N0}", share);
|
||||
RichString yourShareString = RichString.Rich(TextManager.GetWithVariables("crewwallet.missionreward.get", ("[money]", $"{shareFormatted}"), ("[share]", $"{percentage}")));
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform), yourShareString);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (displayedMission != missionsToDisplay.Last())
|
||||
@@ -407,7 +414,7 @@ namespace Barotrauma
|
||||
CreatePathUnlockElement(locationFrame, null, startLocation);
|
||||
}
|
||||
|
||||
foreach (Faction faction in campaignMode.Factions)
|
||||
foreach (Faction faction in campaignMode.Factions.OrderBy(f => f.Prefab.MenuOrder).ThenBy(f => f.Prefab.Name))
|
||||
{
|
||||
float initialReputation = faction.Reputation.Value;
|
||||
if (initialFactionReputations.ContainsKey(faction))
|
||||
@@ -728,7 +735,7 @@ namespace Barotrauma
|
||||
if (Math.Abs(reputationChange) > 0)
|
||||
{
|
||||
string changeText = $"{(reputationChange > 0 ? "+" : "") + reputationChange}";
|
||||
string colorStr = XMLExtensions.ColorToString(reputationChange > 0 ? GUIStyle.Green : GUIStyle.Red);
|
||||
string colorStr = XMLExtensions.ToStringHex(reputationChange > 0 ? GUIStyle.Green : GUIStyle.Red);
|
||||
var richText = RichString.Rich($"{reputationText} (‖color:{colorStr}‖{changeText}‖color:end‖)");
|
||||
new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), sliderHolder.RectTransform),
|
||||
richText,
|
||||
|
||||
Reference in New Issue
Block a user