Build 0.20.4.0
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
using Barotrauma.Extensions;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
|
||||
namespace Barotrauma
|
||||
@@ -18,6 +20,14 @@ namespace Barotrauma
|
||||
|
||||
public readonly ImmutableHashSet<int> AllowedZones;
|
||||
|
||||
private readonly SubmarineAvailability? submarineAvailability;
|
||||
private readonly ImmutableHashSet<SubmarineAvailability> submarineAvailabilityOverrides;
|
||||
|
||||
public readonly record struct SubmarineAvailability(
|
||||
Identifier LocationType,
|
||||
SubmarineClass Class = SubmarineClass.Undefined,
|
||||
int MaxTier = 0);
|
||||
|
||||
public Biome(ContentXElement element, LevelGenerationParametersFile file) : base(file, ParseIdentifier(element))
|
||||
{
|
||||
OldIdentifier = element.GetAttributeIdentifier("oldidentifier", Identifier.Empty);
|
||||
@@ -34,6 +44,26 @@ namespace Barotrauma
|
||||
AllowedZones = element.GetAttributeIntArray("AllowedZones", new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }).ToImmutableHashSet();
|
||||
MinDifficulty = element.GetAttributeFloat("MinDifficulty", 0);
|
||||
maxDifficulty = element.GetAttributeFloat("MaxDifficulty", 100);
|
||||
|
||||
var submarineAvailabilityOverrides = new HashSet<SubmarineAvailability>();
|
||||
if (element.GetChildElement("submarines") is ContentXElement availabilityElement)
|
||||
{
|
||||
submarineAvailability = GetAvailability(availabilityElement);
|
||||
foreach (var overrideElement in availabilityElement.GetChildElements("override"))
|
||||
{
|
||||
var availabilityOverride = GetAvailability(overrideElement);
|
||||
submarineAvailabilityOverrides.Add(availabilityOverride);
|
||||
}
|
||||
}
|
||||
this.submarineAvailabilityOverrides = submarineAvailabilityOverrides.ToImmutableHashSet();
|
||||
|
||||
static SubmarineAvailability GetAvailability(ContentXElement element)
|
||||
{
|
||||
return new SubmarineAvailability(
|
||||
LocationType: element.GetAttributeIdentifier("locationtype", Identifier.Empty),
|
||||
Class: element.GetAttributeEnum("class", SubmarineClass.Undefined),
|
||||
MaxTier: element.GetAttributeInt("maxtier", 0));
|
||||
}
|
||||
}
|
||||
|
||||
public static Identifier ParseIdentifier(ContentXElement element)
|
||||
@@ -47,6 +77,31 @@ namespace Barotrauma
|
||||
return identifier;
|
||||
}
|
||||
|
||||
public int HighestSubmarineTierAvailable(SubmarineClass subClass, Identifier locationType)
|
||||
{
|
||||
if (!submarineAvailability.HasValue)
|
||||
{
|
||||
// If the availability is not explicitly defined, make all subs available
|
||||
return SubmarineInfo.HighestTier;
|
||||
}
|
||||
int maxTier = submarineAvailability.Value.MaxTier;
|
||||
if (submarineAvailabilityOverrides.FirstOrNull(a => a.LocationType == locationType && a.Class == subClass) is SubmarineAvailability locationAndClassOverride)
|
||||
{
|
||||
maxTier = locationAndClassOverride.MaxTier;
|
||||
}
|
||||
else if (submarineAvailabilityOverrides.FirstOrNull(a => a.LocationType == locationType && a.Class == SubmarineClass.Undefined) is SubmarineAvailability locationOverride)
|
||||
{
|
||||
maxTier = locationOverride.MaxTier;
|
||||
}
|
||||
else if (submarineAvailabilityOverrides.FirstOrNull(a => a.LocationType == Identifier.Empty && a.Class == subClass) is SubmarineAvailability classOverride)
|
||||
{
|
||||
maxTier = classOverride.MaxTier;
|
||||
}
|
||||
return maxTier;
|
||||
}
|
||||
|
||||
public bool IsSubmarineAvailable(SubmarineInfo info, Identifier locationType) => info.Tier <= HighestSubmarineTierAvailable(info.SubmarineClass, locationType);
|
||||
|
||||
public override void Dispose() { }
|
||||
}
|
||||
}
|
||||
@@ -447,7 +447,7 @@ namespace Barotrauma
|
||||
|
||||
private Level(LevelData levelData) : base(null, 0)
|
||||
{
|
||||
this.LevelData = levelData;
|
||||
LevelData = levelData;
|
||||
borders = new Rectangle(Point.Zero, levelData.Size);
|
||||
}
|
||||
|
||||
@@ -3939,7 +3939,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
SubmarineInfo outpostInfo;
|
||||
Submarine outpost;
|
||||
Submarine outpost = null;
|
||||
if (i == 0 && preSelectedStartOutpost == null || i == 1 && preSelectedEndOutpost == null)
|
||||
{
|
||||
if (OutpostGenerationParams.OutpostParams.Any() || LevelData.ForceOutpostGenerationParams != null)
|
||||
|
||||
@@ -59,6 +59,7 @@ namespace Barotrauma
|
||||
|
||||
public readonly List<EventPrefab> EventHistory = new List<EventPrefab>();
|
||||
public readonly List<EventPrefab> NonRepeatableEvents = new List<EventPrefab>();
|
||||
public readonly HashSet<Identifier> UsedUniqueSets = new HashSet<Identifier>();
|
||||
|
||||
public bool EventsExhausted { get; set; }
|
||||
|
||||
@@ -143,10 +144,11 @@ namespace Barotrauma
|
||||
string[] nonRepeatablePrefabNames = element.GetAttributeStringArray("nonrepeatableevents", new string[] { });
|
||||
NonRepeatableEvents.AddRange(EventPrefab.Prefabs.Where(p => nonRepeatablePrefabNames.Any(n => p.Identifier == n)));
|
||||
|
||||
UsedUniqueSets = element.GetAttributeIdentifierArray(nameof(UsedUniqueSets), Array.Empty<Identifier>()).ToHashSet();
|
||||
|
||||
EventsExhausted = element.GetAttributeBool(nameof(EventsExhausted).ToLower(), false);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Instantiates level data using the properties of the connection (seed, size, difficulty)
|
||||
/// </summary>
|
||||
@@ -284,6 +286,12 @@ namespace Barotrauma
|
||||
newElement.Add(new XAttribute("nonrepeatableevents", string.Join(',', NonRepeatableEvents.Select(p => p.Identifier))));
|
||||
}
|
||||
}
|
||||
|
||||
if (UsedUniqueSets.Any())
|
||||
{
|
||||
newElement.Add(new XAttribute(nameof(UsedUniqueSets), string.Join(',', UsedUniqueSets)));
|
||||
}
|
||||
|
||||
parentElement.Add(newElement);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -287,6 +287,13 @@ namespace Barotrauma
|
||||
private set;
|
||||
}
|
||||
|
||||
[Serialize("1.0,1.0,1.0,1.0", IsPropertySaveable.Yes), Editable]
|
||||
public Color SpriteColor
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public string Name => Identifier.Value;
|
||||
|
||||
public List<ChildObject> ChildObjects
|
||||
|
||||
@@ -661,7 +661,7 @@ namespace Barotrauma
|
||||
if (effect.HasTargetType(StatusEffect.TargetType.NearbyItems) || effect.HasTargetType(StatusEffect.TargetType.NearbyCharacters))
|
||||
{
|
||||
targets.Clear();
|
||||
targets.AddRange(effect.GetNearbyTargets(worldPosition, targets));
|
||||
effect.AddNearbyTargets(worldPosition, targets);
|
||||
effect.Apply(effect.type, deltaTime, triggerer, targets);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ namespace Barotrauma
|
||||
|
||||
private LocationType addInitialMissionsForType;
|
||||
|
||||
public bool Discovered { get; private set; }
|
||||
public bool Discovered => GameMain.GameSession?.Map?.IsDiscovered(this) ?? false;
|
||||
|
||||
public readonly Dictionary<LocationTypeChange.Requirement, int> ProximityTimer = new Dictionary<LocationTypeChange.Requirement, int>();
|
||||
public (LocationTypeChange typeChange, int delay, MissionPrefab parentMission)? PendingLocationTypeChange;
|
||||
@@ -287,12 +287,12 @@ namespace Barotrauma
|
||||
var characters = GameSession.GetSessionCrewCharacters(CharacterType.Both);
|
||||
if (characters.Any())
|
||||
{
|
||||
if (Location.Reputation?.Faction is { } faction && faction.IsAffiliated())
|
||||
if (Location.Reputation?.Faction is { } faction && faction.GetPlayerAffiliationStatus() is FactionAffiliation.Affiliated)
|
||||
{
|
||||
price *= 1f - characters.Max(static c => c.GetStatValue(StatTypes.StoreBuyMultiplierAffiliated));
|
||||
}
|
||||
price *= 1f - characters.Max(static c => c.GetStatValue(StatTypes.StoreBuyMultiplier));
|
||||
price *= 1f + characters.Max(c => item.Tags.Sum(tag => c.Info.GetSavedStatValue(StatTypes.StoreBuyMultiplier, tag)));
|
||||
price *= 1f - characters.Max(static c => c.GetStatValue(StatTypes.StoreBuyMultiplier, includeSaved: false));
|
||||
price *= 1f - characters.Max(c => item.Tags.Sum(tag => c.Info.GetSavedStatValue(StatTypes.StoreBuyMultiplier, tag)));
|
||||
}
|
||||
// Price should never go below 1 mk
|
||||
return Math.Max((int)price, 1);
|
||||
@@ -497,7 +497,6 @@ namespace Barotrauma
|
||||
baseName = element.GetAttributeString("basename", "");
|
||||
Name = element.GetAttributeString("name", "");
|
||||
MapPosition = element.GetAttributeVector2("position", Vector2.Zero);
|
||||
Discovered = element.GetAttributeBool("discovered", false);
|
||||
PriceMultiplier = element.GetAttributeFloat("pricemultiplier", 1.0f);
|
||||
IsGateBetweenBiomes = element.GetAttributeBool("isgatebetweenbiomes", false);
|
||||
MechanicalPriceMultiplier = element.GetAttributeFloat("mechanicalpricemultipler", 1.0f);
|
||||
@@ -1292,14 +1291,17 @@ namespace Barotrauma
|
||||
return characters.Sum(c => (int)c.GetStatValue(StatTypes.ExtraSpecialSalesCount));
|
||||
}
|
||||
|
||||
public void Discover(bool checkTalents = true)
|
||||
public int HighestSubmarineTierAvailable(SubmarineClass submarineClass)
|
||||
{
|
||||
if (Discovered) { return; }
|
||||
Discovered = true;
|
||||
if (checkTalents)
|
||||
{
|
||||
GameSession.GetSessionCrewCharacters(CharacterType.Both).ForEach(c => c.CheckTalents(AbilityEffectType.OnLocationDiscovered, new AbilityLocation(this)));
|
||||
}
|
||||
if (!HasOutpost()) { return 0; }
|
||||
return Biome?.HighestSubmarineTierAvailable(submarineClass, Type.Identifier) ?? SubmarineInfo.HighestTier;
|
||||
}
|
||||
|
||||
public int HighestSubmarineTierAvailable() => HighestSubmarineTierAvailable(SubmarineClass.Undefined);
|
||||
|
||||
public bool IsSubmarineAvailable(SubmarineInfo info)
|
||||
{
|
||||
return Biome?.IsSubmarineAvailable(info, Type.Identifier) ?? true;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
@@ -1313,7 +1315,6 @@ namespace Barotrauma
|
||||
ClearMissions();
|
||||
LevelData?.EventHistory?.Clear();
|
||||
UnlockInitialMissions();
|
||||
Discovered = false;
|
||||
}
|
||||
|
||||
public XElement Save(Map map, XElement parentElement)
|
||||
@@ -1324,7 +1325,6 @@ namespace Barotrauma
|
||||
new XAttribute("basename", BaseName),
|
||||
new XAttribute("name", Name),
|
||||
new XAttribute("biome", Biome?.Identifier.Value ?? string.Empty),
|
||||
new XAttribute("discovered", Discovered),
|
||||
new XAttribute("position", XMLExtensions.Vector2ToString(MapPosition)),
|
||||
new XAttribute("pricemultiplier", PriceMultiplier),
|
||||
new XAttribute("isgatebetweenbiomes", IsGateBetweenBiomes),
|
||||
@@ -1453,7 +1453,7 @@ namespace Barotrauma
|
||||
HireManager?.Remove();
|
||||
}
|
||||
|
||||
class AbilityLocation : AbilityObject, IAbilityLocation
|
||||
public class AbilityLocation : AbilityObject, IAbilityLocation
|
||||
{
|
||||
public AbilityLocation(Location location)
|
||||
{
|
||||
|
||||
@@ -24,6 +24,7 @@ namespace Barotrauma
|
||||
public readonly Dictionary<int, int> MinCountPerZone = new Dictionary<int, int>();
|
||||
|
||||
public readonly LocalizedString Name;
|
||||
public readonly LocalizedString Description;
|
||||
|
||||
public readonly float BeaconStationChance;
|
||||
|
||||
@@ -70,6 +71,13 @@ namespace Barotrauma
|
||||
public Sprite Sprite { get; private set; }
|
||||
public Sprite RadiationSprite { get; }
|
||||
|
||||
private readonly Identifier forceOutpostGenerationParamsIdentifier;
|
||||
|
||||
/// <summary>
|
||||
/// If set to true, only event sets that explicitly define this location type in <see cref="EventSet.LocationTypeIdentifiers"/> can be selected at this location. Defaults to false.
|
||||
/// </summary>
|
||||
public bool IgnoreGenericEvents { get; }
|
||||
|
||||
public Color SpriteColor
|
||||
{
|
||||
get;
|
||||
@@ -96,6 +104,7 @@ namespace Barotrauma
|
||||
public LocationType(ContentXElement element, LocationTypesFile file) : base(file, element.GetAttributeIdentifier("identifier", element.Name.LocalName))
|
||||
{
|
||||
Name = TextManager.Get("LocationName." + Identifier, "unknown");
|
||||
Description = TextManager.Get("LocationDescription." + Identifier, "");
|
||||
|
||||
BeaconStationChance = element.GetAttributeFloat("beaconstationchance", 0.0f);
|
||||
|
||||
@@ -110,6 +119,10 @@ namespace Barotrauma
|
||||
|
||||
ReplaceInRadiation = element.GetAttributeIdentifier(nameof(ReplaceInRadiation), Identifier.Empty);
|
||||
|
||||
forceOutpostGenerationParamsIdentifier = element.GetAttributeIdentifier("forceoutpostgenerationparams", Identifier.Empty);
|
||||
|
||||
IgnoreGenericEvents = element.GetAttributeBool(nameof(IgnoreGenericEvents), false);
|
||||
|
||||
string teamStr = element.GetAttributeString("outpostteam", "FriendlyNPC");
|
||||
Enum.TryParse(teamStr, out OutpostTeam);
|
||||
|
||||
@@ -261,6 +274,15 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public OutpostGenerationParams GetForcedOutpostGenerationParams()
|
||||
{
|
||||
if (OutpostGenerationParams.OutpostParams.TryGet(forceOutpostGenerationParamsIdentifier, out var parameters))
|
||||
{
|
||||
return parameters;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public override void Dispose() { }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,10 +68,15 @@ namespace Barotrauma
|
||||
|
||||
public List<Location> Locations { get; private set; }
|
||||
|
||||
private readonly List<Location> locationsDiscovered = new List<Location>();
|
||||
private readonly List<Location> outpostsVisited = new List<Location>();
|
||||
|
||||
public List<LocationConnection> Connections { get; private set; }
|
||||
|
||||
public Radiation Radiation;
|
||||
|
||||
private bool wasLocationDiscoveryOrderTracked = true;
|
||||
|
||||
public Map(CampaignSettings settings)
|
||||
{
|
||||
generationParams = MapGenerationParams.Instance;
|
||||
@@ -282,7 +287,12 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
CurrentLocation.Discover(true);
|
||||
if (campaign.IsSinglePlayer && campaign.Settings.TutorialEnabled && LocationType.Prefabs.TryGet("tutorialoutpost", out var tutorialOutpost))
|
||||
{
|
||||
CurrentLocation.ChangeType(tutorialOutpost);
|
||||
}
|
||||
Discover(CurrentLocation);
|
||||
Visit(CurrentLocation);
|
||||
CurrentLocation.CreateStores();
|
||||
|
||||
foreach (var location in Locations)
|
||||
@@ -820,7 +830,8 @@ namespace Barotrauma
|
||||
SelectedConnection.Passed = true;
|
||||
|
||||
CurrentLocation = SelectedLocation;
|
||||
CurrentLocation.Discover();
|
||||
Discover(CurrentLocation);
|
||||
Visit(CurrentLocation);
|
||||
SelectedLocation = null;
|
||||
|
||||
CurrentLocation.CreateStores();
|
||||
@@ -851,7 +862,7 @@ namespace Barotrauma
|
||||
|
||||
Location prevLocation = CurrentLocation;
|
||||
CurrentLocation = Locations[index];
|
||||
CurrentLocation.Discover();
|
||||
Discover(CurrentLocation);
|
||||
|
||||
CurrentLocation.CreateStores();
|
||||
if (prevLocation != CurrentLocation)
|
||||
@@ -1184,6 +1195,51 @@ namespace Barotrauma
|
||||
|
||||
partial void ClearAnimQueue();
|
||||
|
||||
public void Discover(Location location, bool checkTalents = true)
|
||||
{
|
||||
if (location is null) { return; }
|
||||
if (locationsDiscovered.Contains(location)) { return; }
|
||||
locationsDiscovered.Add(location);
|
||||
if (checkTalents)
|
||||
{
|
||||
GameSession.GetSessionCrewCharacters(CharacterType.Both).ForEach(c => c.CheckTalents(AbilityEffectType.OnLocationDiscovered, new Location.AbilityLocation(location)));
|
||||
}
|
||||
}
|
||||
|
||||
public void Visit(Location location)
|
||||
{
|
||||
if (location is null) { return; }
|
||||
if (!location.HasOutpost()) { return; }
|
||||
if (outpostsVisited.Contains(location)) { return; }
|
||||
outpostsVisited.Add(location);
|
||||
}
|
||||
|
||||
public void ClearLocationHistory()
|
||||
{
|
||||
locationsDiscovered.Clear();
|
||||
outpostsVisited.Clear();
|
||||
}
|
||||
|
||||
public int? GetDiscoveryIndex(Location location)
|
||||
{
|
||||
if (!wasLocationDiscoveryOrderTracked) { return null; }
|
||||
if (location is null) { return -1; }
|
||||
return locationsDiscovered.IndexOf(location);
|
||||
}
|
||||
|
||||
public int? GetVisitIndex(Location location)
|
||||
{
|
||||
if (!wasLocationDiscoveryOrderTracked) { return null; }
|
||||
if (location is null) { return -1; }
|
||||
return outpostsVisited.IndexOf(location);
|
||||
}
|
||||
|
||||
public bool IsDiscovered(Location location)
|
||||
{
|
||||
if (location is null) { return false; }
|
||||
return locationsDiscovered.Contains(location);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Load a previously saved map from an xml element
|
||||
/// </summary>
|
||||
@@ -1211,6 +1267,7 @@ namespace Barotrauma
|
||||
return;
|
||||
}
|
||||
|
||||
ClearLocationHistory();
|
||||
foreach (var subElement in element.Elements())
|
||||
{
|
||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||
@@ -1226,19 +1283,12 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
location.LoadLocationTypeChange(subElement);
|
||||
|
||||
// Backwards compatibility
|
||||
if (subElement.GetAttributeBool("discovered", false))
|
||||
{
|
||||
location.Discover(checkTalents: false);
|
||||
}
|
||||
if (location.Discovered)
|
||||
{
|
||||
#if CLIENT
|
||||
RemoveFogOfWar(location);
|
||||
#endif
|
||||
if (furthestDiscoveredLocation == null || location.MapPosition.X > furthestDiscoveredLocation.MapPosition.X)
|
||||
{
|
||||
furthestDiscoveredLocation = location;
|
||||
}
|
||||
Discover(location);
|
||||
wasLocationDiscoveryOrderTracked = false;
|
||||
}
|
||||
|
||||
Identifier locationType = subElement.GetAttributeIdentifier("type", Identifier.Empty);
|
||||
@@ -1268,6 +1318,36 @@ namespace Barotrauma
|
||||
case "radiation":
|
||||
Radiation = new Radiation(this, generationParams.RadiationParams, subElement);
|
||||
break;
|
||||
case "discovered":
|
||||
foreach (var childElement in subElement.GetChildElements("location"))
|
||||
{
|
||||
int index = childElement.GetAttributeInt("i", -1);
|
||||
if (index < 0) { continue; }
|
||||
if (Locations[index] is not Location l) { continue; }
|
||||
Discover(l);
|
||||
}
|
||||
break;
|
||||
case "visited":
|
||||
foreach (var childElement in subElement.GetChildElements("location"))
|
||||
{
|
||||
int index = childElement.GetAttributeInt("i", -1);
|
||||
if (index < 0) { continue; }
|
||||
if (Locations[index] is not Location l) { continue; }
|
||||
Visit(l);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Discover(Location location)
|
||||
{
|
||||
this.Discover(location, checkTalents: false);
|
||||
#if CLIENT
|
||||
RemoveFogOfWar(location);
|
||||
#endif
|
||||
if (furthestDiscoveredLocation == null || location.MapPosition.X > furthestDiscoveredLocation.MapPosition.X)
|
||||
{
|
||||
furthestDiscoveredLocation = location;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1343,6 +1423,30 @@ namespace Barotrauma
|
||||
mapElement.Add(Radiation.Save());
|
||||
}
|
||||
|
||||
if (locationsDiscovered.Any())
|
||||
{
|
||||
var discoveryElement = new XElement("discovered");
|
||||
foreach (Location location in locationsDiscovered)
|
||||
{
|
||||
int index = Locations.IndexOf(location);
|
||||
var locationElement = new XElement("location", new XAttribute("i", index));
|
||||
discoveryElement.Add(locationElement);
|
||||
}
|
||||
mapElement.Add(discoveryElement);
|
||||
}
|
||||
|
||||
if (outpostsVisited.Any())
|
||||
{
|
||||
var visitElement = new XElement("visited");
|
||||
foreach (Location location in outpostsVisited)
|
||||
{
|
||||
int index = Locations.IndexOf(location);
|
||||
var locationElement = new XElement("location", new XAttribute("i", index));
|
||||
visitElement.Add(locationElement);
|
||||
}
|
||||
mapElement.Add(visitElement);
|
||||
}
|
||||
|
||||
element.Add(mapElement);
|
||||
}
|
||||
|
||||
|
||||
@@ -96,6 +96,8 @@ namespace Barotrauma
|
||||
[Serialize("", IsPropertySaveable.Yes), Editable]
|
||||
public string ReplaceInRadiation { get; set; }
|
||||
|
||||
public ContentPath OutpostFilePath { get; set; }
|
||||
|
||||
public class ModuleCount
|
||||
{
|
||||
public Identifier Identifier;
|
||||
@@ -182,6 +184,7 @@ namespace Barotrauma
|
||||
Name = element.GetAttributeString("name", Identifier.Value);
|
||||
allowedLocationTypes = element.GetAttributeIdentifierArray("allowedlocationtypes", Array.Empty<Identifier>()).ToHashSet();
|
||||
SerializableProperties = SerializableProperty.DeserializeProperties(this, element);
|
||||
OutpostFilePath = element.GetAttributeContentPath(nameof(OutpostFilePath));
|
||||
|
||||
var humanPrefabCollections = new List<IReadOnlyList<HumanPrefab>>();
|
||||
foreach (var subElement in element.Elements())
|
||||
|
||||
@@ -143,7 +143,7 @@ namespace Barotrauma
|
||||
//select which module types the outpost should consist of
|
||||
List<Identifier> pendingModuleFlags =
|
||||
onlyEntrance ?
|
||||
generationParams.ModuleCounts.First().Identifier.ToEnumerable().ToList() :
|
||||
(generationParams.ModuleCounts.FirstOrDefault()?.Identifier.ToEnumerable() ?? Enumerable.Empty<Identifier>()).ToList() :
|
||||
SelectModules(outpostModules, generationParams);
|
||||
|
||||
foreach (Identifier flag in pendingModuleFlags)
|
||||
@@ -246,6 +246,7 @@ namespace Barotrauma
|
||||
|
||||
var outpostFiles = ContentPackageManager.EnabledPackages.All
|
||||
.SelectMany(p => p.GetFiles<OutpostFile>())
|
||||
.Where(f => !TutorialPrefab.Prefabs.Any(tp => tp.OutpostPath == f.Path))
|
||||
.OrderBy(f => f.UintIdentifier).ToArray();
|
||||
if (!outpostFiles.Any())
|
||||
{
|
||||
@@ -696,6 +697,14 @@ namespace Barotrauma
|
||||
rect.Location += (module.Offset + module.MoveOffset).ToPoint();
|
||||
rect.Y += module.Bounds.Height;
|
||||
|
||||
Vector2? selfGapPos1 = null;
|
||||
Vector2? selfGapPos2 = null;
|
||||
if (module.PreviousModule != null)
|
||||
{
|
||||
selfGapPos1 = module.Offset + module.ThisGap.Position + module.MoveOffset;
|
||||
selfGapPos2 = module.PreviousModule.Offset + module.PreviousGap.Position + module.PreviousModule.MoveOffset;
|
||||
}
|
||||
|
||||
foreach (PlacedModule otherModule in modules)
|
||||
{
|
||||
if (otherModule == module || otherModule.PreviousModule == null || otherModule.PreviousModule == module) { continue; }
|
||||
@@ -710,7 +719,17 @@ namespace Barotrauma
|
||||
|
||||
Vector2 gapPos1 = otherModule.Offset + otherModule.ThisGap.Position + gapEdgeOffset + otherModule.MoveOffset;
|
||||
Vector2 gapPos2 = otherModule.PreviousModule.Offset + otherModule.PreviousGap.Position + gapEdgeOffset + otherModule.PreviousModule.MoveOffset;
|
||||
if (Submarine.RectContains(rect, gapPos1) || Submarine.RectContains(rect, gapPos2) || MathUtils.GetLineRectangleIntersection(gapPos1, gapPos2, rect, out _))
|
||||
if (Submarine.RectContains(rect, gapPos1) ||
|
||||
Submarine.RectContains(rect, gapPos2) ||
|
||||
MathUtils.GetLineRectangleIntersection(gapPos1, gapPos2, rect, out _))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
//check if the connection overlaps with this module's connection
|
||||
if (selfGapPos1.HasValue && selfGapPos2.HasValue &&
|
||||
!gapPos1.NearlyEquals(gapPos2) && !selfGapPos1.Value.NearlyEquals(selfGapPos2.Value) &&
|
||||
MathUtils.LinesIntersect(gapPos1, gapPos2, selfGapPos1.Value, selfGapPos2.Value))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ namespace Barotrauma
|
||||
|
||||
public PriceInfo(int price, bool canBeBought,
|
||||
int minAmount = 0, int maxAmount = 0, bool canBeSpecial = true, int minLevelDifficulty = 0, float buyingPriceMultiplier = 1f,
|
||||
bool displayNonEmpty = false, string storeIdentifier = null)
|
||||
bool displayNonEmpty = false, bool requiresUnlock = false, string storeIdentifier = null)
|
||||
{
|
||||
Price = price;
|
||||
CanBeBought = canBeBought;
|
||||
@@ -67,6 +67,7 @@ namespace Barotrauma
|
||||
CanBeSpecial = canBeSpecial;
|
||||
DisplayNonEmpty = displayNonEmpty;
|
||||
StoreIdentifier = new Identifier(storeIdentifier);
|
||||
RequiresUnlock = requiresUnlock;
|
||||
}
|
||||
|
||||
public static List<PriceInfo> CreatePriceInfos(XElement element, out PriceInfo defaultPrice)
|
||||
@@ -81,6 +82,7 @@ namespace Barotrauma
|
||||
float buyingPriceMultiplier = element.GetAttributeFloat("buyingpricemultiplier", 1f);
|
||||
bool displayNonEmpty = element.GetAttributeBool("displaynonempty", false);
|
||||
bool soldByDefault = element.GetAttributeBool("sold", element.GetAttributeBool("soldbydefault", true));
|
||||
bool requiresUnlock = element.GetAttributeBool("requiresunlock", false);
|
||||
foreach (XElement childElement in element.GetChildElements("price"))
|
||||
{
|
||||
float priceMultiplier = childElement.GetAttributeFloat("multiplier", 1.0f);
|
||||
@@ -94,26 +96,28 @@ namespace Barotrauma
|
||||
}
|
||||
string storeIdentifier = childElement.GetAttributeString("storeidentifier", backwardsCompatibleIdentifier);
|
||||
// TODO: Add some error messages if we have defined the min or max amount while the item is not sold
|
||||
var priceInfo = new PriceInfo((int)(priceMultiplier * basePrice),
|
||||
sold,
|
||||
sold ? GetMinAmount(childElement, minAmount) : 0,
|
||||
sold ? GetMaxAmount(childElement, maxAmount) : 0,
|
||||
canBeSpecial,
|
||||
storeMinLevelDifficulty,
|
||||
storeBuyingMultiplier,
|
||||
displayNonEmpty,
|
||||
storeIdentifier);
|
||||
var priceInfo = new PriceInfo(price: (int)(priceMultiplier * basePrice),
|
||||
canBeBought: sold,
|
||||
minAmount: sold ? GetMinAmount(childElement, minAmount) : 0,
|
||||
maxAmount: sold ? GetMaxAmount(childElement, maxAmount) : 0,
|
||||
canBeSpecial: canBeSpecial,
|
||||
minLevelDifficulty: storeMinLevelDifficulty,
|
||||
buyingPriceMultiplier: storeBuyingMultiplier,
|
||||
displayNonEmpty: displayNonEmpty,
|
||||
requiresUnlock: requiresUnlock,
|
||||
storeIdentifier: storeIdentifier);
|
||||
priceInfos.Add(priceInfo);
|
||||
}
|
||||
bool soldElsewhere = soldByDefault && element.GetAttributeBool("soldelsewhere", element.GetAttributeBool("soldeverywhere", false));
|
||||
defaultPrice = new PriceInfo(basePrice,
|
||||
soldElsewhere,
|
||||
soldElsewhere ? minAmount : 0,
|
||||
soldElsewhere ? maxAmount : 0,
|
||||
canBeSpecial,
|
||||
minLevelDifficulty,
|
||||
buyingPriceMultiplier,
|
||||
displayNonEmpty);
|
||||
defaultPrice = new PriceInfo(price: basePrice,
|
||||
canBeBought: soldElsewhere,
|
||||
minAmount: soldElsewhere ? minAmount : 0,
|
||||
maxAmount: soldElsewhere ? maxAmount : 0,
|
||||
canBeSpecial: canBeSpecial,
|
||||
minLevelDifficulty: minLevelDifficulty,
|
||||
buyingPriceMultiplier: buyingPriceMultiplier,
|
||||
displayNonEmpty: displayNonEmpty,
|
||||
requiresUnlock: requiresUnlock);
|
||||
return priceInfos;
|
||||
}
|
||||
|
||||
|
||||
@@ -1114,7 +1114,8 @@ namespace Barotrauma
|
||||
{
|
||||
if (item.Submarine != this) { continue; }
|
||||
var pump = item.GetComponent<Pump>();
|
||||
if (pump == null || !item.HasTag("ballast") || item.CurrentHull == null) { continue; }
|
||||
if (pump == null || item.CurrentHull == null) { continue; }
|
||||
if (!item.HasTag("ballast") && !item.CurrentHull.RoomName.Contains("ballast", StringComparison.OrdinalIgnoreCase)) { continue; }
|
||||
pump.FlowPercentage = 0.0f;
|
||||
ballastHulls.Add(item.CurrentHull);
|
||||
}
|
||||
|
||||
@@ -314,6 +314,7 @@ namespace Barotrauma
|
||||
Tier = original.Tier;
|
||||
IsManuallyOutfitted = original.IsManuallyOutfitted;
|
||||
Tags = original.Tags;
|
||||
OutpostGenerationParams = original.OutpostGenerationParams;
|
||||
if (original.OutpostModuleInfo != null)
|
||||
{
|
||||
OutpostModuleInfo = new OutpostModuleInfo(original.OutpostModuleInfo);
|
||||
@@ -747,6 +748,8 @@ namespace Barotrauma
|
||||
return doc;
|
||||
}
|
||||
|
||||
public static int GetDefaultTier(int price) => price > 20000 ? 3 : price > 10000 ? 2 : 1;
|
||||
public static int GetDefaultTier(int price) => price > 20000 ? HighestTier : price > 10000 ? 2 : 1;
|
||||
|
||||
public const int HighestTier = 3;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user