v1.4.4.1 (Blood in the Water Update)
This commit is contained in:
@@ -35,12 +35,7 @@ namespace Barotrauma
|
||||
//spawn items in wrecks, beacon stations and pirate subs
|
||||
foreach (var sub in Submarine.Loaded)
|
||||
{
|
||||
if (sub.Info.Type == SubmarineType.Player ||
|
||||
sub.Info.Type == SubmarineType.Outpost ||
|
||||
sub.Info.Type == SubmarineType.OutpostModule)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (sub.Info.Type is SubmarineType.Player or SubmarineType.Outpost or SubmarineType.OutpostModule) { continue; }
|
||||
if (sub.Info.InitialSuppliesSpawned) { continue; }
|
||||
CreateAndPlace(sub.ToEnumerable());
|
||||
sub.Info.InitialSuppliesSpawned = true;
|
||||
|
||||
@@ -661,6 +661,10 @@ namespace Barotrauma
|
||||
#if SERVER
|
||||
Entity.Spawner?.CreateNetworkEvent(new EntitySpawner.SpawnEntity(item));
|
||||
#endif
|
||||
if (item.GetComponent<Holdable>() is { Attached: true })
|
||||
{
|
||||
item.Drop(dropper: null);
|
||||
}
|
||||
if (!character.Inventory.TryPutItem(item, user: null, item.AllowedSlots))
|
||||
{
|
||||
foreach (Item containedItem in character.Inventory.AllItemsMod)
|
||||
|
||||
@@ -35,8 +35,6 @@ namespace Barotrauma
|
||||
|
||||
private Character welcomeMessageNPC;
|
||||
|
||||
public List<CharacterInfo> CharacterInfos => characterInfos;
|
||||
|
||||
public bool HasBots { get; set; }
|
||||
|
||||
public class ActiveOrder
|
||||
@@ -74,8 +72,8 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
// Ignore orders work a bit differently since the "unignore" order counters the "ignore" order
|
||||
var isUnignoreOrder = order.Identifier == "unignorethis";
|
||||
var orderPrefab = !isUnignoreOrder ? order.Prefab : OrderPrefab.Prefabs["ignorethis"];
|
||||
var isUnignoreOrder = order.Identifier == Tags.UnignoreThis;
|
||||
var orderPrefab = !isUnignoreOrder ? order.Prefab : OrderPrefab.Prefabs[Tags.IgnoreThis];
|
||||
ActiveOrder existingOrder = ActiveOrders.Find(o =>
|
||||
o.Order.Prefab == orderPrefab && MatchesTarget(o.Order.TargetEntity, order.TargetEntity) &&
|
||||
(o.Order.TargetType != Order.OrderTargetType.WallSection || o.Order.WallSectionIndex == order.WallSectionIndex));
|
||||
@@ -95,6 +93,23 @@ namespace Barotrauma
|
||||
}
|
||||
else if (!isUnignoreOrder)
|
||||
{
|
||||
if (order.IsDeconstructOrder)
|
||||
{
|
||||
if (order.TargetEntity is Item item)
|
||||
{
|
||||
if (order.Identifier == Tags.DeconstructThis)
|
||||
{
|
||||
Item.DeconstructItems.Add(item);
|
||||
#if CLIENT
|
||||
HintManager.OnItemMarkedForDeconstruction(order.OrderGiver);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
Item.DeconstructItems.Remove(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
ActiveOrders.Add(new ActiveOrder(order, fadeOutTime));
|
||||
#if CLIENT
|
||||
HintManager.OnActiveOrderAdded(order);
|
||||
@@ -198,6 +213,11 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsFired(Character character)
|
||||
{
|
||||
return !GetCharacterInfos().Contains(character.Info);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove the character from the crew (and crew menus).
|
||||
/// </summary>
|
||||
@@ -237,6 +257,11 @@ namespace Barotrauma
|
||||
characterInfos.Add(characterInfo);
|
||||
}
|
||||
|
||||
public void ClearCharacterInfos()
|
||||
{
|
||||
characterInfos.Clear();
|
||||
}
|
||||
|
||||
public void InitRound()
|
||||
{
|
||||
#if CLIENT
|
||||
|
||||
@@ -147,6 +147,8 @@ namespace Barotrauma
|
||||
|
||||
public bool DivingSuitWarningShown;
|
||||
|
||||
public bool ItemsRelocatedToMainSub;
|
||||
|
||||
private static bool AnyOneAllowedToManageCampaign(ClientPermissions permissions)
|
||||
{
|
||||
if (GameMain.NetworkMember == null) { return true; }
|
||||
@@ -878,7 +880,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
foreach (CharacterInfo ci in CrewManager.CharacterInfos.ToList())
|
||||
foreach (CharacterInfo ci in CrewManager.GetCharacterInfos().ToList())
|
||||
{
|
||||
if (ci.CauseOfDeath != null)
|
||||
{
|
||||
@@ -979,7 +981,7 @@ namespace Barotrauma
|
||||
Preset?.Identifier.Value ?? "none");
|
||||
string eventId = "FinishCampaign:";
|
||||
GameAnalyticsManager.AddDesignEvent(eventId + "Submarine:" + (Submarine.MainSub?.Info?.Name ?? "none"));
|
||||
GameAnalyticsManager.AddDesignEvent(eventId + "CrewSize:" + (CrewManager?.CharacterInfos?.Count() ?? 0));
|
||||
GameAnalyticsManager.AddDesignEvent(eventId + "CrewSize:" + (CrewManager?.GetCharacterInfos()?.Count() ?? 0));
|
||||
GameAnalyticsManager.AddDesignEvent(eventId + "Money", Bank.Balance);
|
||||
GameAnalyticsManager.AddDesignEvent(eventId + "Playtime", TotalPlayTime);
|
||||
GameAnalyticsManager.AddDesignEvent(eventId + "PassedLevels", TotalPassedLevels);
|
||||
@@ -1024,7 +1026,7 @@ namespace Barotrauma
|
||||
return ToolBox.SelectWeightedRandom(factionsList, weights, random);
|
||||
}
|
||||
|
||||
public bool TryHireCharacter(Location location, CharacterInfo characterInfo, Character hirer, Client client = null)
|
||||
public bool TryHireCharacter(Location location, CharacterInfo characterInfo, bool takeMoney = true, Client client = null)
|
||||
{
|
||||
if (characterInfo == null) { return false; }
|
||||
if (characterInfo.MinReputationToHire.factionId != Identifier.Empty)
|
||||
@@ -1034,8 +1036,8 @@ namespace Barotrauma
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (takeMoney && !TryPurchase(client, HireManager.GetSalaryFor(characterInfo))) { return false; }
|
||||
|
||||
if (!TryPurchase(client, HireManager.GetSalaryFor(characterInfo))) { return false; }
|
||||
characterInfo.IsNewHire = true;
|
||||
characterInfo.Title = null;
|
||||
location.RemoveHireableCharacter(characterInfo);
|
||||
@@ -1047,7 +1049,6 @@ namespace Barotrauma
|
||||
private void NPCInteract(Character npc, Character interactor)
|
||||
{
|
||||
if (!npc.AllowCustomInteract) { return; }
|
||||
GameAnalyticsManager.AddDesignEvent("CampaignInteraction:" + Preset.Identifier + ":" + npc.CampaignInteractionType);
|
||||
NPCInteractProjSpecific(npc, interactor);
|
||||
string coroutineName = "DoCharacterWait." + (npc?.ID ?? Entity.NullEntityID);
|
||||
if (!CoroutineManager.IsCoroutineRunning(coroutineName))
|
||||
|
||||
+29
-44
@@ -8,7 +8,7 @@ namespace Barotrauma
|
||||
internal static class CampaignModePresets
|
||||
{
|
||||
public static readonly ImmutableArray<CampaignSettings> List;
|
||||
public static readonly ImmutableDictionary<Identifier, CampaignSettingDefinitions> Definitions;
|
||||
private static readonly ImmutableDictionary<Identifier, CampaignSettingDefinitions> definitions;
|
||||
|
||||
private static readonly string fileListPath = Path.Combine("Data", "campaignsettings.xml");
|
||||
|
||||
@@ -20,73 +20,58 @@ namespace Barotrauma
|
||||
return;
|
||||
}
|
||||
|
||||
List<CampaignSettings> list = new List<CampaignSettings>();
|
||||
Dictionary<Identifier, CampaignSettingDefinitions> definitions = new Dictionary<Identifier, CampaignSettingDefinitions>();
|
||||
List<CampaignSettings> presetList = new List<CampaignSettings>();
|
||||
Dictionary<Identifier, CampaignSettingDefinitions> tempDefinitions = new Dictionary<Identifier, CampaignSettingDefinitions>();
|
||||
|
||||
foreach (XElement element in docRoot.Elements())
|
||||
{
|
||||
Identifier name = element.NameAsIdentifier();
|
||||
|
||||
// The campaign setting presets
|
||||
if (name == CampaignSettings.LowerCaseSaveElementName)
|
||||
{
|
||||
list.Add(new CampaignSettings(element));
|
||||
presetList.Add(new CampaignSettings(element));
|
||||
}
|
||||
// All the definitions for the setting value options
|
||||
else if (name == nameof(CampaignSettingDefinitions))
|
||||
{
|
||||
// The single definitions that the settings may refer to (eg. PatdownProbabilityMin)
|
||||
foreach (XElement subElement in element.Elements())
|
||||
{
|
||||
definitions.Add(subElement.NameAsIdentifier(), new CampaignSettingDefinitions(subElement));
|
||||
tempDefinitions.Add(subElement.NameAsIdentifier(), new CampaignSettingDefinitions(subElement));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List = list.ToImmutableArray();
|
||||
Definitions = definitions.ToImmutableDictionary();
|
||||
List = presetList.ToImmutableArray();
|
||||
definitions = tempDefinitions.ToImmutableDictionary();
|
||||
}
|
||||
|
||||
public static bool TryGetAttribute(Identifier propertyName, Identifier attributeName, out XAttribute attribute)
|
||||
{
|
||||
attribute = null;
|
||||
if (definitions.TryGetValue(propertyName, out CampaignSettingDefinitions definition))
|
||||
{
|
||||
if (definition.Attributes.TryGetValue(attributeName, out XAttribute att))
|
||||
{
|
||||
attribute = att;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
internal readonly struct CampaignSettingDefinitions
|
||||
{
|
||||
// Definitely not the best way to do this
|
||||
private readonly ImmutableDictionary<Identifier, Either<int, float>> values;
|
||||
public readonly ImmutableDictionary<Identifier, XAttribute> Attributes;
|
||||
|
||||
public CampaignSettingDefinitions(XElement element)
|
||||
{
|
||||
var definitions = new Dictionary<Identifier, Either<int, float>>();
|
||||
foreach (XAttribute attribute in element.Attributes())
|
||||
{
|
||||
Identifier name = attribute.NameAsIdentifier();
|
||||
if (attribute.Value.Contains('.'))
|
||||
{
|
||||
definitions.Add(name, element.GetAttributeFloat(name.Value, 0));
|
||||
}
|
||||
else
|
||||
{
|
||||
definitions.Add(name, element.GetAttributeInt(name.Value, 0));
|
||||
}
|
||||
}
|
||||
|
||||
values = definitions.ToImmutableDictionary();
|
||||
}
|
||||
|
||||
public float GetFloat(Identifier identifier)
|
||||
{
|
||||
float range = 0;
|
||||
if (!values.TryGetValue(identifier, out Either<int, float> value) || !value.TryGet(out range))
|
||||
{
|
||||
DebugConsole.ThrowError($"CampaignSettings: Can't find value for {identifier}");
|
||||
}
|
||||
return range;
|
||||
}
|
||||
|
||||
public int GetInt(Identifier identifier)
|
||||
{
|
||||
int integer = 0;
|
||||
if (!values.TryGetValue(identifier, out Either<int, float> value) || !value.TryGet(out integer))
|
||||
{
|
||||
DebugConsole.ThrowError($"CampaignSettings: Can't find value for {identifier}");
|
||||
}
|
||||
return integer;
|
||||
Attributes = element.Attributes().ToImmutableDictionary(
|
||||
a => a.NameAsIdentifier(),
|
||||
a => a
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
+183
-22
@@ -1,4 +1,4 @@
|
||||
#nullable enable
|
||||
#nullable enable
|
||||
|
||||
using Microsoft.Xna.Framework;
|
||||
using System.Collections.Generic;
|
||||
@@ -27,6 +27,10 @@ namespace Barotrauma
|
||||
[Serialize(false, IsPropertySaveable.Yes), NetworkSerialize]
|
||||
public bool RadiationEnabled { get; set; }
|
||||
|
||||
public const int DefaultMaxMissionCount = 2;
|
||||
public const int MaxMissionCountLimit = 10;
|
||||
public const int MinMissionCountLimit = 1;
|
||||
|
||||
private int maxMissionCount;
|
||||
|
||||
[Serialize(DefaultMaxMissionCount, IsPropertySaveable.Yes), NetworkSerialize(MinValueInt = MinMissionCountLimit, MaxValueInt = MaxMissionCountLimit)]
|
||||
@@ -38,60 +42,200 @@ namespace Barotrauma
|
||||
|
||||
public int TotalMaxMissionCount => MaxMissionCount + GetAddedMissionCount();
|
||||
|
||||
[Serialize(StartingBalanceAmount.Medium, IsPropertySaveable.Yes), NetworkSerialize]
|
||||
public StartingBalanceAmount StartingBalanceAmount { get; set; }
|
||||
|
||||
[Serialize(GameDifficulty.Medium, IsPropertySaveable.Yes), NetworkSerialize]
|
||||
public GameDifficulty Difficulty { get; set; }
|
||||
[Serialize(WorldHostilityOption.Medium, IsPropertySaveable.Yes), NetworkSerialize]
|
||||
public WorldHostilityOption WorldHostility { get; set; }
|
||||
|
||||
[Serialize("normal", IsPropertySaveable.Yes), NetworkSerialize]
|
||||
public Identifier StartItemSet { get; set; }
|
||||
|
||||
[Serialize(StartingBalanceAmountOption.Medium, IsPropertySaveable.Yes), NetworkSerialize]
|
||||
public StartingBalanceAmountOption StartingBalanceAmount { get; set; }
|
||||
|
||||
private int? _initialMoney;
|
||||
public const int DefaultInitialMoney = 8000;
|
||||
|
||||
public int InitialMoney
|
||||
{
|
||||
get
|
||||
{
|
||||
if (CampaignModePresets.Definitions.TryGetValue(nameof(StartingBalanceAmount).ToIdentifier(), out var definition))
|
||||
if (_initialMoney is int alreadyCachedValue)
|
||||
{
|
||||
return definition.GetInt(StartingBalanceAmount.ToIdentifier());
|
||||
return alreadyCachedValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
_initialMoney = DefaultInitialMoney;
|
||||
Identifier settingDefinitionIdentifier = nameof(StartingBalanceAmount).ToIdentifier();
|
||||
Identifier attributeIdentifier = StartingBalanceAmount.ToIdentifier();
|
||||
if (CampaignModePresets.TryGetAttribute(settingDefinitionIdentifier, attributeIdentifier, out XAttribute? attribute))
|
||||
{
|
||||
_initialMoney = attribute.GetAttributeInt(DefaultInitialMoney);
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugConsole.ThrowError($"CampaignSettings: Can't find value for {attributeIdentifier} in {settingDefinitionIdentifier}");
|
||||
}
|
||||
return _initialMoney ?? DefaultInitialMoney;
|
||||
}
|
||||
return 8000;
|
||||
}
|
||||
}
|
||||
|
||||
private float? _extraEventManagerDifficulty;
|
||||
private const float defaultExtraEventManagerDifficulty = 0;
|
||||
|
||||
public float ExtraEventManagerDifficulty
|
||||
{
|
||||
get
|
||||
{
|
||||
if (CampaignModePresets.Definitions.TryGetValue(nameof(ExtraEventManagerDifficulty).ToIdentifier(), out var definition))
|
||||
if (_extraEventManagerDifficulty is float alreadyCachedValue)
|
||||
{
|
||||
return definition.GetFloat(Difficulty.ToIdentifier());
|
||||
return alreadyCachedValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
_extraEventManagerDifficulty = defaultExtraEventManagerDifficulty;
|
||||
Identifier settingDefinitionIdentifier = nameof(ExtraEventManagerDifficulty).ToIdentifier();
|
||||
Identifier attributeIdentifier = WorldHostility.ToIdentifier();
|
||||
if (CampaignModePresets.TryGetAttribute(settingDefinitionIdentifier, attributeIdentifier, out XAttribute? attribute))
|
||||
{
|
||||
_extraEventManagerDifficulty = attribute.GetAttributeFloat(defaultExtraEventManagerDifficulty);
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugConsole.ThrowError($"CampaignSettings: Can't find value for {attributeIdentifier} in {settingDefinitionIdentifier}");
|
||||
}
|
||||
return _extraEventManagerDifficulty ?? defaultExtraEventManagerDifficulty;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
private float? _levelDifficultyMultiplier;
|
||||
private const float defaultLevelDifficultyMultiplier = 1.0f;
|
||||
|
||||
public float LevelDifficultyMultiplier
|
||||
{
|
||||
get
|
||||
{
|
||||
if (CampaignModePresets.Definitions.TryGetValue(nameof(LevelDifficultyMultiplier).ToIdentifier(), out var definition))
|
||||
if (_levelDifficultyMultiplier is float alreadyCachedValue)
|
||||
{
|
||||
return definition.GetFloat(Difficulty.ToIdentifier());
|
||||
return alreadyCachedValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
_levelDifficultyMultiplier = defaultLevelDifficultyMultiplier;
|
||||
Identifier settingDefinitionIdentifier = nameof(LevelDifficultyMultiplier).ToIdentifier();
|
||||
Identifier attributeIdentifier = WorldHostility.ToIdentifier();
|
||||
if (CampaignModePresets.TryGetAttribute(settingDefinitionIdentifier, attributeIdentifier, out XAttribute? attribute))
|
||||
{
|
||||
_levelDifficultyMultiplier = attribute.GetAttributeFloat(defaultLevelDifficultyMultiplier);
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugConsole.ThrowError($"CampaignSettings: Can't find value for {attributeIdentifier} in {settingDefinitionIdentifier}");
|
||||
}
|
||||
return _levelDifficultyMultiplier ?? defaultLevelDifficultyMultiplier;
|
||||
}
|
||||
return 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
[Serialize(0.2f, IsPropertySaveable.Yes, description: "How likely it is for security to inspect player characters for stolen items when your reputation is high?")]
|
||||
public float MinStolenItemInspectionProbability { get; set; }
|
||||
private static readonly Dictionary<string, MultiplierSettings> _multiplierSettings = new Dictionary<string, MultiplierSettings>
|
||||
{
|
||||
{ "default", new MultiplierSettings { Min = 0.2f, Max = 2.0f, Step = 0.1f } },
|
||||
{ nameof(CrewVitalityMultiplier), new MultiplierSettings { Min = 0.5f, Max = 2.0f, Step = 0.1f } },
|
||||
{ nameof(NonCrewVitalityMultiplier),new MultiplierSettings { Min = 0.5f, Max = 3.0f, Step = 0.1f } },
|
||||
{ nameof(MissionRewardMultiplier), new MultiplierSettings { Min = 0.5f, Max = 2.0f, Step = 0.1f } },
|
||||
{ nameof(RepairFailMultiplier), new MultiplierSettings { Min = 0.5f, Max = 5.0f, Step = 0.5f } },
|
||||
{ nameof(ShopPriceMultiplier), new MultiplierSettings { Min = 0.1f, Max = 3.0f, Step = 0.1f } },
|
||||
{ nameof(ShipyardPriceMultiplier), new MultiplierSettings { Min = 0.1f, Max = 3.0f, Step = 0.1f } }
|
||||
// Add overrides for default values here
|
||||
};
|
||||
|
||||
[Serialize(0.9f, IsPropertySaveable.Yes, description: "How likely it is for security to inspect player characters for stolen items when your reputation is low?")]
|
||||
public float MaxStolenItemInspectionProbability { get; set; }
|
||||
[Serialize(1.0f, IsPropertySaveable.Yes), NetworkSerialize]
|
||||
public float CrewVitalityMultiplier { get; set; }
|
||||
|
||||
public const int DefaultMaxMissionCount = 2;
|
||||
public const int MaxMissionCountLimit = 10;
|
||||
public const int MinMissionCountLimit = 1;
|
||||
[Serialize(1.0f, IsPropertySaveable.Yes), NetworkSerialize]
|
||||
public float NonCrewVitalityMultiplier { get; set; }
|
||||
|
||||
[Serialize(1.0f, IsPropertySaveable.Yes), NetworkSerialize]
|
||||
public float OxygenMultiplier { get; set; }
|
||||
|
||||
[Serialize(1.0f, IsPropertySaveable.Yes), NetworkSerialize]
|
||||
public float FuelMultiplier { get; set; }
|
||||
|
||||
[Serialize(1.0f, IsPropertySaveable.Yes), NetworkSerialize]
|
||||
public float MissionRewardMultiplier { get; set; }
|
||||
|
||||
[Serialize(1.0f, IsPropertySaveable.Yes), NetworkSerialize]
|
||||
public float ShopPriceMultiplier { get; set; }
|
||||
|
||||
[Serialize(1.0f, IsPropertySaveable.Yes), NetworkSerialize]
|
||||
public float ShipyardPriceMultiplier { get; set; }
|
||||
|
||||
[Serialize(1.0f, IsPropertySaveable.Yes), NetworkSerialize]
|
||||
public float RepairFailMultiplier { get; set; }
|
||||
|
||||
[Serialize(true, IsPropertySaveable.Yes), NetworkSerialize]
|
||||
public bool ShowHuskWarning { get; set; }
|
||||
|
||||
[Serialize(PatdownProbabilityOption.Medium, IsPropertySaveable.Yes), NetworkSerialize]
|
||||
public PatdownProbabilityOption PatdownProbability { get; set; }
|
||||
|
||||
private float? _minPatdownProbability;
|
||||
private float? _maxPatdownProbability;
|
||||
public const float DefaultMinPatdownProbability = 0.2f;
|
||||
public const float DefaultMaxPatdownProbability = 0.9f;
|
||||
|
||||
public float PatdownProbabilityMin
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_minPatdownProbability is float alreadyCachedValue)
|
||||
{
|
||||
return alreadyCachedValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
_minPatdownProbability = DefaultMinPatdownProbability;
|
||||
Identifier settingDefinitionIdentifier = nameof(PatdownProbabilityMin).ToIdentifier();
|
||||
Identifier attributeIdentifier = PatdownProbability.ToIdentifier();
|
||||
if (CampaignModePresets.TryGetAttribute(settingDefinitionIdentifier, attributeIdentifier, out XAttribute? attribute))
|
||||
{
|
||||
_minPatdownProbability = attribute.GetAttributeFloat(DefaultMinPatdownProbability);
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugConsole.ThrowError($"CampaignSettings: Can't find value for {attributeIdentifier} in {settingDefinitionIdentifier}");
|
||||
}
|
||||
return _minPatdownProbability ?? DefaultMinPatdownProbability;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public float PatdownProbabilityMax
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_maxPatdownProbability is float alreadyCachedValue)
|
||||
{
|
||||
return alreadyCachedValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
_maxPatdownProbability = DefaultMaxPatdownProbability;
|
||||
Identifier settingDefinitionIdentifier = nameof(PatdownProbabilityMax).ToIdentifier();
|
||||
Identifier attributeIdentifier = PatdownProbability.ToIdentifier();
|
||||
if (CampaignModePresets.TryGetAttribute(settingDefinitionIdentifier, attributeIdentifier, out XAttribute? attribute))
|
||||
{
|
||||
_maxPatdownProbability = attribute.GetAttributeFloat(DefaultMaxPatdownProbability);
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugConsole.ThrowError($"CampaignSettings: Can't find value for {attributeIdentifier} in {settingDefinitionIdentifier}");
|
||||
}
|
||||
return _maxPatdownProbability ?? DefaultMaxPatdownProbability;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Dictionary<Identifier, SerializableProperty> SerializableProperties { get; private set; }
|
||||
|
||||
@@ -119,5 +263,22 @@ namespace Barotrauma
|
||||
if (!characters.Any()) { return 0; }
|
||||
return characters.Max(static character => (int)character.GetStatValue(StatTypes.ExtraMissionCount));
|
||||
}
|
||||
|
||||
public struct MultiplierSettings
|
||||
{
|
||||
public float Min { get; set; }
|
||||
public float Max { get; set; }
|
||||
public float Step { get; set; }
|
||||
}
|
||||
|
||||
public static MultiplierSettings GetMultiplierSettings(string multiplierName)
|
||||
{
|
||||
if (_multiplierSettings.TryGetValue(multiplierName, out MultiplierSettings value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
return _multiplierSettings["default"];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -390,11 +390,27 @@ namespace Barotrauma
|
||||
.Where(lt => missionPrefab.AllowedLocationTypes.Any(m => m == lt.Identifier))
|
||||
.GetRandom(rand);
|
||||
dummyLocations = CreateDummyLocations(levelSeed, locationType);
|
||||
if (!mission.Prefab.RequiredLocationFaction.IsEmpty &&
|
||||
FactionPrefab.Prefabs.TryGet(mission.Prefab.RequiredLocationFaction, out var factionPrefab))
|
||||
|
||||
if (!tryCreateFaction(mission.Prefab.RequiredLocationFaction, dummyLocations, static (loc, fac) => loc.Faction = fac))
|
||||
{
|
||||
dummyLocations[0].Faction = dummyLocations[1].Faction = new Faction(metadata: null, factionPrefab);
|
||||
tryCreateFaction(locationType.Faction, dummyLocations, static (loc, fac) => loc.Faction = fac);
|
||||
tryCreateFaction(locationType.SecondaryFaction, dummyLocations, static (loc, fac) => loc.SecondaryFaction = fac);
|
||||
}
|
||||
static bool tryCreateFaction(Identifier factionIdentifier, Location[] locations, Action<Location, Faction> setter)
|
||||
{
|
||||
if (factionIdentifier.IsEmpty) { return false; }
|
||||
if (!FactionPrefab.Prefabs.TryGet(factionIdentifier, out var prefab)) { return false; }
|
||||
if (locations.Length == 0) { return false; }
|
||||
|
||||
var newFaction = new Faction(metadata: null, prefab);
|
||||
for (int i = 0; i < locations.Length; i++)
|
||||
{
|
||||
setter(locations[i], newFaction);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
randomLevel = LevelData.CreateRandom(levelSeed, difficulty, levelGenerationParams, requireOutpost: true);
|
||||
break;
|
||||
}
|
||||
@@ -473,6 +489,11 @@ namespace Barotrauma
|
||||
}
|
||||
foreach (Item item in items)
|
||||
{
|
||||
if (item.GetComponent<CircuitBox>() is { } cb)
|
||||
{
|
||||
cb.Locked = true;
|
||||
}
|
||||
|
||||
Wire wire = item.GetComponent<Wire>();
|
||||
if (wire != null && !wire.NoAutoLock && wire.Connections.Any(c => c != null)) { wire.Locked = true; }
|
||||
}
|
||||
@@ -498,7 +519,7 @@ namespace Barotrauma
|
||||
string eventId = "StartRound:" + (GameMode?.Preset?.Identifier.Value ?? "none") + ":";
|
||||
GameAnalyticsManager.AddDesignEvent(eventId + "Submarine:" + (Submarine.MainSub?.Info?.Name ?? "none"));
|
||||
GameAnalyticsManager.AddDesignEvent(eventId + "GameMode:" + (GameMode?.Preset?.Identifier.Value ?? "none"));
|
||||
GameAnalyticsManager.AddDesignEvent(eventId + "CrewSize:" + (CrewManager?.CharacterInfos?.Count() ?? 0));
|
||||
GameAnalyticsManager.AddDesignEvent(eventId + "CrewSize:" + (CrewManager?.GetCharacterInfos()?.Count() ?? 0));
|
||||
foreach (Mission mission in missions)
|
||||
{
|
||||
GameAnalyticsManager.AddDesignEvent(eventId + "MissionType:" + (mission.Prefab.Type.ToString() ?? "none") + ":" + mission.Prefab.Identifier);
|
||||
@@ -523,16 +544,24 @@ namespace Barotrauma
|
||||
GameAnalyticsManager.AddDesignEvent($"{eventId}HintManager:{(HintManager.Enabled ? "Enabled" : "Disabled")}");
|
||||
#endif
|
||||
var campaignMode = GameMode as CampaignMode;
|
||||
if (campaignMode != null)
|
||||
{
|
||||
if (campaignMode.Map?.Radiation != null && campaignMode.Map.Radiation.Enabled)
|
||||
{
|
||||
GameAnalyticsManager.AddDesignEvent(eventId + "Radiation:Enabled");
|
||||
}
|
||||
else
|
||||
{
|
||||
GameAnalyticsManager.AddDesignEvent(eventId + "Radiation:Disabled");
|
||||
}
|
||||
if (campaignMode != null)
|
||||
{
|
||||
GameAnalyticsManager.AddDesignEvent("CampaignSettings:RadiationEnabled:" + campaignMode.Settings.RadiationEnabled);
|
||||
GameAnalyticsManager.AddDesignEvent("CampaignSettings:WorldHostility:" + campaignMode.Settings.WorldHostility);
|
||||
GameAnalyticsManager.AddDesignEvent("CampaignSettings:ShowHuskWarning:" + campaignMode.Settings.ShowHuskWarning);
|
||||
GameAnalyticsManager.AddDesignEvent("CampaignSettings:StartItemSet:" + campaignMode.Settings.StartItemSet);
|
||||
GameAnalyticsManager.AddDesignEvent("CampaignSettings:MaxMissionCount:" + campaignMode.Settings.MaxMissionCount);
|
||||
//log the multipliers as integers to reduce the number of distinct values
|
||||
GameAnalyticsManager.AddDesignEvent("CampaignSettings:RepairFailMultiplier:" + (int)(campaignMode.Settings.RepairFailMultiplier * 100));
|
||||
GameAnalyticsManager.AddDesignEvent("CampaignSettings:FuelMultiplier:" + (int)(campaignMode.Settings.FuelMultiplier * 100));
|
||||
GameAnalyticsManager.AddDesignEvent("CampaignSettings:MissionRewardMultiplier:" + (int)(campaignMode.Settings.MissionRewardMultiplier * 100));
|
||||
GameAnalyticsManager.AddDesignEvent("CampaignSettings:CrewVitalityMultiplier:" + (int)(campaignMode.Settings.CrewVitalityMultiplier * 100));
|
||||
GameAnalyticsManager.AddDesignEvent("CampaignSettings:NonCrewVitalityMultiplier:" + (int)(campaignMode.Settings.NonCrewVitalityMultiplier * 100));
|
||||
GameAnalyticsManager.AddDesignEvent("CampaignSettings:OxygenMultiplier:" + (int)(campaignMode.Settings.OxygenMultiplier * 100));
|
||||
GameAnalyticsManager.AddDesignEvent("CampaignSettings:RepairFailMultiplier:" + (int)(campaignMode.Settings.RepairFailMultiplier * 100));
|
||||
GameAnalyticsManager.AddDesignEvent("CampaignSettings:ShipyardPriceMultiplier:" + (int)(campaignMode.Settings.ShipyardPriceMultiplier * 100));
|
||||
GameAnalyticsManager.AddDesignEvent("CampaignSettings:ShopPriceMultiplier:" + (int)(campaignMode.Settings.ShopPriceMultiplier * 100));
|
||||
|
||||
bool firstTimeInBiome = Map != null && !Map.Connections.Any(c => c.Passed && c.Biome == LevelData!.Biome);
|
||||
if (firstTimeInBiome)
|
||||
{
|
||||
@@ -593,6 +622,19 @@ namespace Barotrauma
|
||||
HintManager.OnRoundStarted();
|
||||
EnableEventLogNotificationIcon(enabled: false);
|
||||
#endif
|
||||
if (campaignMode is { ItemsRelocatedToMainSub: true })
|
||||
{
|
||||
#if SERVER
|
||||
GameMain.Server.SendChatMessage(TextManager.Get("itemrelocated").Value, ChatMessageType.ServerMessageBoxInGame);
|
||||
#else
|
||||
if (campaignMode.IsSinglePlayer)
|
||||
{
|
||||
new GUIMessageBox(string.Empty, TextManager.Get("itemrelocated"));
|
||||
}
|
||||
#endif
|
||||
campaignMode.ItemsRelocatedToMainSub = false;
|
||||
}
|
||||
|
||||
EventManager?.EventLog?.Clear();
|
||||
if (campaignMode is { DivingSuitWarningShown: false } &&
|
||||
Level.Loaded != null && Level.Loaded.GetRealWorldDepth(0) > 4000)
|
||||
@@ -1002,46 +1044,54 @@ namespace Barotrauma
|
||||
|
||||
public void LogEndRoundStats(string eventId, TraitorManager.TraitorResults? traitorResults = null)
|
||||
{
|
||||
GameAnalyticsManager.AddDesignEvent(eventId + "Submarine:" + (Submarine.MainSub?.Info?.Name ?? "none"), RoundDuration);
|
||||
if (Submarine.MainSub?.Info?.IsVanillaSubmarine() ?? false)
|
||||
{
|
||||
//don't log modded subs, that's a ton of extra data to collect
|
||||
GameAnalyticsManager.AddDesignEvent(eventId + "Submarine:" + (Submarine.MainSub?.Info?.Name ?? "none"), RoundDuration);
|
||||
}
|
||||
GameAnalyticsManager.AddDesignEvent(eventId + "GameMode:" + (GameMode?.Name.Value ?? "none"), RoundDuration);
|
||||
GameAnalyticsManager.AddDesignEvent(eventId + "CrewSize:" + (CrewManager?.CharacterInfos?.Count ?? 0), RoundDuration);
|
||||
GameAnalyticsManager.AddDesignEvent(eventId + "CrewSize:" + (CrewManager?.GetCharacterInfos()?.Count() ?? 0), RoundDuration);
|
||||
foreach (Mission mission in missions)
|
||||
{
|
||||
GameAnalyticsManager.AddDesignEvent(eventId + "MissionType:" + (mission.Prefab.Type.ToString() ?? "none") + ":" + mission.Prefab.Identifier + ":" + (mission.Completed ? "Completed" : "Failed"), RoundDuration);
|
||||
}
|
||||
if (Level.Loaded != null)
|
||||
if (!ContentPackageManager.ModsEnabled)
|
||||
{
|
||||
Identifier levelId = (Level.Loaded.Type == LevelData.LevelType.Outpost ?
|
||||
Level.Loaded.StartOutpost?.Info?.OutpostGenerationParams?.Identifier :
|
||||
Level.Loaded.GenerationParams?.Identifier) ?? "null".ToIdentifier();
|
||||
GameAnalyticsManager.AddDesignEvent(eventId + "LevelType:" + (Level.Loaded?.Type.ToString() ?? "none" + ":" + levelId), RoundDuration);
|
||||
GameAnalyticsManager.AddDesignEvent(eventId + "Biome:" + (Level.Loaded?.LevelData?.Biome?.Identifier.Value ?? "none"), RoundDuration);
|
||||
}
|
||||
|
||||
if (Submarine.MainSub != null)
|
||||
{
|
||||
Dictionary<ItemPrefab, int> submarineInventory = new Dictionary<ItemPrefab, int>();
|
||||
foreach (Item item in Item.ItemList)
|
||||
if (Level.Loaded != null)
|
||||
{
|
||||
var rootContainer = item.RootContainer ?? item;
|
||||
if (rootContainer.Submarine?.Info == null || rootContainer.Submarine.Info.Type != SubmarineType.Player) { continue; }
|
||||
if (rootContainer.Submarine != Submarine.MainSub && !Submarine.MainSub.DockedTo.Contains(rootContainer.Submarine)) { continue; }
|
||||
Identifier levelId = (Level.Loaded.Type == LevelData.LevelType.Outpost ?
|
||||
Level.Loaded.StartOutpost?.Info?.OutpostGenerationParams?.Identifier :
|
||||
Level.Loaded.GenerationParams?.Identifier) ?? "null".ToIdentifier();
|
||||
GameAnalyticsManager.AddDesignEvent(eventId + "LevelType:" + (Level.Loaded?.Type.ToString() ?? "none" + ":" + levelId), RoundDuration);
|
||||
GameAnalyticsManager.AddDesignEvent(eventId + "Biome:" + (Level.Loaded?.LevelData?.Biome?.Identifier.Value ?? "none"), RoundDuration);
|
||||
}
|
||||
|
||||
var holdable = item.GetComponent<Holdable>();
|
||||
if (holdable == null || holdable.Attached) { continue; }
|
||||
var wire = item.GetComponent<Wire>();
|
||||
if (wire != null && wire.Connections.Any(c => c != null)) { continue; }
|
||||
|
||||
if (!submarineInventory.ContainsKey(item.Prefab))
|
||||
//disabled for now, we're collecting too many events and this is information we don't need atm
|
||||
/*if (Submarine.MainSub != null)
|
||||
{
|
||||
Dictionary<ItemPrefab, int> submarineInventory = new Dictionary<ItemPrefab, int>();
|
||||
foreach (Item item in Item.ItemList)
|
||||
{
|
||||
submarineInventory.Add(item.Prefab, 0);
|
||||
var rootContainer = item.RootContainer ?? item;
|
||||
if (rootContainer.Submarine?.Info == null || rootContainer.Submarine.Info.Type != SubmarineType.Player) { continue; }
|
||||
if (rootContainer.Submarine != Submarine.MainSub && !Submarine.MainSub.DockedTo.Contains(rootContainer.Submarine)) { continue; }
|
||||
|
||||
var holdable = item.GetComponent<Holdable>();
|
||||
if (holdable == null || holdable.Attached) { continue; }
|
||||
var wire = item.GetComponent<Wire>();
|
||||
if (wire != null && wire.Connections.Any(c => c != null)) { continue; }
|
||||
|
||||
if (!submarineInventory.ContainsKey(item.Prefab))
|
||||
{
|
||||
submarineInventory.Add(item.Prefab, 0);
|
||||
}
|
||||
submarineInventory[item.Prefab]++;
|
||||
}
|
||||
submarineInventory[item.Prefab]++;
|
||||
}
|
||||
foreach (var subItem in submarineInventory)
|
||||
{
|
||||
GameAnalyticsManager.AddDesignEvent(eventId + "SubmarineInventory:" + subItem.Key.Identifier, subItem.Value);
|
||||
}
|
||||
foreach (var subItem in submarineInventory)
|
||||
{
|
||||
GameAnalyticsManager.AddDesignEvent(eventId + "SubmarineInventory:" + subItem.Key.Identifier, subItem.Value);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
if (traitorResults.HasValue)
|
||||
|
||||
@@ -278,6 +278,20 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used for purchasing upgrades from outside the upgrade store.
|
||||
/// Doesn't deduct the credit, adds the upgrade to the pending list and performs a level sanity check.
|
||||
/// </summary>
|
||||
public void AddUpgradeExternally(UpgradePrefab prefab, UpgradeCategory category, int level)
|
||||
{
|
||||
int maxLevel = prefab.GetMaxLevelForCurrentSub();
|
||||
int currentLevel = GetUpgradeLevel(prefab, category);
|
||||
if (currentLevel + 1 > maxLevel) { return; }
|
||||
|
||||
PendingUpgrades.Add(new PurchasedUpgrade(prefab, category, level));
|
||||
OnUpgradesChanged?.Invoke(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Purchases an item swap and handles logic for deducting the credit.
|
||||
/// </summary>
|
||||
|
||||
Reference in New Issue
Block a user