Unstable 1.2.1.0

This commit is contained in:
Markus Isberg
2023-11-10 17:45:19 +02:00
parent 2ea58c58a7
commit 8a2e2ea0ae
268 changed files with 4076 additions and 1843 deletions
@@ -229,7 +229,7 @@ namespace Barotrauma
/// </summary>
public readonly int FabricationLimitMin, FabricationLimitMax;
public FabricationRecipe(XElement element, Identifier itemPrefab)
public FabricationRecipe(ContentXElement element, Identifier itemPrefab)
{
TargetItemPrefabIdentifier = itemPrefab;
var displayNameIdentifier = element.GetAttributeIdentifier("displayname", "");
@@ -245,7 +245,8 @@ namespace Barotrauma
OutCondition = element.GetAttributeFloat("outcondition", 1.0f);
if (OutCondition > 1.0f)
{
DebugConsole.AddWarning($"Error in \"{itemPrefab}\"'s fabrication recipe: out condition is above 100% ({OutCondition * 100}).");
DebugConsole.AddWarning($"Error in \"{itemPrefab}\"'s fabrication recipe: out condition is above 100% ({OutCondition * 100}).",
element.ContentPackage);
}
var requiredItems = new List<RequiredItem>();
RequiresRecipe = element.GetAttributeBool("requiresrecipe", false);
@@ -267,9 +268,10 @@ namespace Barotrauma
switch (subElement.Name.ToString().ToLowerInvariant())
{
case "requiredskill":
if (subElement.Attribute("name") != null)
if (subElement.GetAttribute("name") != null)
{
DebugConsole.ThrowError("Error in fabricable item " + itemPrefab + "! Use skill identifiers instead of names.");
DebugConsole.ThrowError("Error in fabricable item " + itemPrefab + "! Use skill identifiers instead of names.",
contentPackage: element.ContentPackage);
continue;
}
@@ -283,7 +285,8 @@ namespace Barotrauma
Identifier requiredItemTag = subElement.GetAttributeIdentifier("tag", Identifier.Empty);
if (requiredItemIdentifier == Identifier.Empty && requiredItemTag == Identifier.Empty)
{
DebugConsole.ThrowError("Error in fabricable item " + itemPrefab + "! One of the required items has no identifier or tag.");
DebugConsole.ThrowError("Error in fabricable item " + itemPrefab + "! One of the required items has no identifier or tag.",
contentPackage: element.ContentPackage);
continue;
}
@@ -819,7 +822,7 @@ namespace Barotrauma
[Serialize(null, IsPropertySaveable.No)]
public string EquipConfirmationText { get; set; }
[Serialize(true, IsPropertySaveable.No, description: "Can the item be rotated in the submarine editor.")]
[Serialize(true, IsPropertySaveable.No, description: "Can the item be rotated in the submarine editor?")]
public bool AllowRotatingInEditor { get; set; }
[Serialize(false, IsPropertySaveable.No)]
@@ -830,7 +833,13 @@ namespace Barotrauma
[Serialize(true, IsPropertySaveable.No)]
public bool CanFlipY { get; private set; }
[Serialize(0.1f, IsPropertySaveable.No)]
public float MinScale { get; private set; }
[Serialize(10.0f, IsPropertySaveable.No)]
public float MaxScale { get; private set; }
[Serialize(false, IsPropertySaveable.No)]
public bool IsDangerous { get; private set; }
@@ -843,7 +852,7 @@ namespace Barotrauma
}
private int maxStackSizeCharacterInventory;
[Serialize(-1, IsPropertySaveable.No)]
[Serialize(-1, IsPropertySaveable.No, description: "Maximum stack size when the item is in a character inventory.")]
public int MaxStackSizeCharacterInventory
{
get { return maxStackSizeCharacterInventory; }
@@ -851,7 +860,9 @@ namespace Barotrauma
}
private int maxStackSizeHoldableOrWearableInventory;
[Serialize(-1, IsPropertySaveable.No)]
[Serialize(-1, IsPropertySaveable.No, description:
"Maximum stack size when the item is inside a holdable or wearable item. "+
"If not set, defaults to MaxStackSizeCharacterInventory.")]
public int MaxStackSizeHoldableOrWearableInventory
{
get { return maxStackSizeHoldableOrWearableInventory; }
@@ -864,15 +875,20 @@ namespace Barotrauma
{
return maxStackSizeCharacterInventory;
}
else if (maxStackSizeHoldableOrWearableInventory > 0 &&
inventory?.Owner is Item item && (item.GetComponent<Holdable>() != null || item.GetComponent<Wearable>() != null))
else if (inventory?.Owner is Item item &&
(item.GetComponent<Holdable>() is { Attachable: false } || item.GetComponent<Wearable>() != null))
{
return maxStackSizeHoldableOrWearableInventory;
}
else
{
return maxStackSize;
if (maxStackSizeHoldableOrWearableInventory > 0)
{
return maxStackSizeHoldableOrWearableInventory;
}
else if (maxStackSizeCharacterInventory > 0)
{
//if maxStackSizeHoldableOrWearableInventory is not set, it defaults to maxStackSizeCharacterInventory
return maxStackSizeCharacterInventory;
}
}
return maxStackSize;
}
[Serialize(false, IsPropertySaveable.No)]
@@ -880,7 +896,7 @@ namespace Barotrauma
public ImmutableHashSet<Identifier> AllowDroppingOnSwapWith { get; private set; }
[Serialize(false, IsPropertySaveable.No)]
[Serialize(false, IsPropertySaveable.No, "If enabled, the item is not transferred when the player transfers items between subs.")]
public bool DontTransferBetweenSubs { get; private set; }
[Serialize(true, IsPropertySaveable.No)]
@@ -1009,7 +1025,8 @@ namespace Barotrauma
if (ConfigElement.GetAttribute("cargocontainername") != null)
{
DebugConsole.ThrowError($"Error in item prefab \"{ToString()}\" - cargo container should be configured using the item's identifier, not the name.");
DebugConsole.ThrowError($"Error in item prefab \"{ToString()}\" - cargo container should be configured using the item's identifier, not the name.",
contentPackage: ConfigElement.ContentPackage);
}
SerializableProperty.DeserializeProperties(this, ConfigElement);
@@ -1032,6 +1049,7 @@ namespace Barotrauma
var levelCommonness = new Dictionary<Identifier, CommonnessInfo>();
var levelQuantity = new Dictionary<Identifier, FixedQuantityResourceInfo>();
List<FabricationRecipe> loadedRecipes = new List<FabricationRecipe>();
foreach (ContentXElement subElement in ConfigElement.Elements())
{
switch (subElement.Name.ToString().ToLowerInvariant())
@@ -1046,7 +1064,8 @@ namespace Barotrauma
if (subElement.GetAttribute("sourcerect") == null &&
subElement.GetAttribute("sheetindex") == null)
{
DebugConsole.ThrowError($"Warning - sprite sourcerect not configured for item \"{ToString()}\"!");
DebugConsole.ThrowError($"Warning - sprite sourcerect not configured for item \"{ToString()}\"!",
contentPackage: ConfigElement.ContentPackage);
}
Size = Sprite.size;
@@ -1064,7 +1083,8 @@ namespace Barotrauma
if (priceInfo.StoreIdentifier.IsEmpty) { continue; }
if (storePrices.ContainsKey(priceInfo.StoreIdentifier))
{
DebugConsole.AddWarning($"Error in item prefab \"{this}\": price for the store \"{priceInfo.StoreIdentifier}\" defined more than once.");
DebugConsole.AddWarning($"Error in item prefab \"{this}\": price for the store \"{priceInfo.StoreIdentifier}\" defined more than once.",
ContentPackage);
storePrices[priceInfo.StoreIdentifier] = priceInfo;
}
else
@@ -1077,7 +1097,8 @@ namespace Barotrauma
{
if (storePrices.ContainsKey(locationType))
{
DebugConsole.AddWarning($"Error in item prefab \"{this}\": price for the location type \"{locationType}\" defined more than once.");
DebugConsole.AddWarning($"Error in item prefab \"{this}\": price for the location type \"{locationType}\" defined more than once.",
ContentPackage);
storePrices[locationType] = new PriceInfo(subElement);
}
else
@@ -1095,13 +1116,15 @@ namespace Barotrauma
{
if (itemElement.Attribute("name") != null)
{
DebugConsole.ThrowError($"Error in item config \"{ToString()}\" - use item identifiers instead of names to configure the deconstruct items.");
DebugConsole.ThrowError($"Error in item config \"{ToString()}\" - use item identifiers instead of names to configure the deconstruct items.",
contentPackage: ConfigElement.ContentPackage);
continue;
}
var deconstructItem = new DeconstructItem(itemElement, Identifier);
if (deconstructItem.ItemIdentifier.IsEmpty)
{
DebugConsole.ThrowError($"Error in item config \"{ToString()}\" - deconstruction output contains an item with no identifier.");
DebugConsole.ThrowError($"Error in item config \"{ToString()}\" - deconstruction output contains an item with no identifier.",
contentPackage: ConfigElement.ContentPackage);
continue;
}
deconstructItems.Add(deconstructItem);
@@ -1114,16 +1137,21 @@ namespace Barotrauma
var newRecipe = new FabricationRecipe(subElement, Identifier);
if (fabricationRecipes.TryGetValue(newRecipe.RecipeHash, out var prevRecipe))
{
//the errors below may be caused by a mod overriding a base item instead of this one, log the package of the base item in that case
var packageToLog = GetParentModPackageOrThisPackage();
int prevRecipeIndex = loadedRecipes.IndexOf(prevRecipe);
DebugConsole.ThrowError(
$"Error in item prefab \"{ToString()}\": " +
$"{prevRecipe.TargetItemPrefabIdentifier} has the same hash as {newRecipe.TargetItemPrefabIdentifier}. " +
$"This will cause issues with fabrication."
);
$"Fabrication recipe #{loadedRecipes.Count + 1} has the same hash as recipe #{prevRecipeIndex + 1}. This is most likely caused by identical, duplicate recipes. " +
$"This will cause issues with fabrication.",
contentPackage: packageToLog);
}
else
{
fabricationRecipes.Add(newRecipe.RecipeHash, newRecipe);
}
loadedRecipes.Add(newRecipe);
break;
case "preferredcontainer":
var preferredContainer = new PreferredContainer(subElement);
@@ -1132,7 +1160,8 @@ namespace Barotrauma
//it's ok for variants to clear the primary and secondary containers to disable the PreferredContainer element
if (variantOf == null)
{
DebugConsole.ThrowError($"Error in item prefab \"{ToString()}\": preferred container has no preferences defined ({subElement}).");
DebugConsole.ThrowError($"Error in item prefab \"{ToString()}\": preferred container has no preferences defined ({subElement}).",
contentPackage: ConfigElement.ContentPackage);
}
}
else
@@ -1182,7 +1211,8 @@ namespace Barotrauma
case "suitabletreatment":
if (subElement.GetAttribute("name") != null)
{
DebugConsole.ThrowError($"Error in item prefab \"{ToString()}\" - suitable treatments should be defined using item identifiers, not item names.");
DebugConsole.ThrowError($"Error in item prefab \"{ToString()}\" - suitable treatments should be defined using item identifiers, not item names.",
contentPackage: ConfigElement.ContentPackage);
}
Identifier treatmentIdentifier = subElement.GetAttributeIdentifier("identifier", subElement.GetAttributeIdentifier("type", Identifier.Empty));
float suitability = subElement.GetAttributeFloat("suitability", 0.0f);
@@ -1191,6 +1221,8 @@ namespace Barotrauma
}
}
Size = ConfigElement.GetAttributeVector2(nameof(Size), Size);
#if CLIENT
ParseSubElementsClient(ConfigElement, variantOf);
#endif
@@ -1221,7 +1253,7 @@ namespace Barotrauma
if (Sprite == null)
{
DebugConsole.ThrowError($"Item \"{ToString()}\" has no sprite!");
DebugConsole.ThrowError($"Item \"{ToString()}\" has no sprite!", contentPackage: ConfigElement.ContentPackage);
#if SERVER
this.sprite = new Sprite("", Vector2.Zero);
this.sprite.SourceRect = new Rectangle(0, 0, 32, 32);
@@ -1238,7 +1270,8 @@ namespace Barotrauma
if (Identifier == Identifier.Empty)
{
DebugConsole.ThrowError(
$"Item prefab \"{ToString()}\" has no identifier. All item prefabs have a unique identifier string that's used to differentiate between items during saving and loading.");
$"Item prefab \"{ToString()}\" has no identifier. All item prefabs have a unique identifier string that's used to differentiate between items during saving and loading.",
contentPackage: ConfigElement.ContentPackage);
}
#if DEBUG
@@ -1246,7 +1279,8 @@ namespace Barotrauma
{
if (!string.IsNullOrEmpty(OriginalName))
{
DebugConsole.AddWarning($"Item \"{(Identifier == Identifier.Empty ? Name : Identifier.Value)}\" has a hard-coded name, and won't be localized to other languages.");
DebugConsole.AddWarning($"Item \"{(Identifier == Identifier.Empty ? Name : Identifier.Value)}\" has a hard-coded name, and won't be localized to other languages.",
ContentPackage);
}
}
#endif
@@ -1306,9 +1340,9 @@ namespace Barotrauma
{
string message = $"Tried to get price info for \"{Identifier}\" with a null store parameter!\n{Environment.StackTrace.CleanupStackTrace()}";
#if DEBUG
DebugConsole.LogError(message);
DebugConsole.LogError(message, contentPackage: ContentPackage);
#else
DebugConsole.AddWarning(message);
DebugConsole.AddWarning(message, ContentPackage);
GameAnalyticsManager.AddErrorEventOnce("ItemPrefab.GetPriceInfo:StoreParameterNull", GameAnalyticsManager.ErrorSeverity.Error, message);
#endif
return null;
@@ -1515,6 +1549,9 @@ namespace Barotrauma
void CheckXML(XElement originalElement, XElement variantElement, XElement result)
{
//if either the parent or the variant are non-vanilla, assume the error is coming from that package
var packageToLog = parent.ContentPackage != GameMain.VanillaContent ? parent.ContentPackage : ContentPackage;
if (result == null) { return; }
if (result.Name.ToIdentifier() == "RequiredItem" &&
result.Parent?.Name.ToIdentifier() == "Fabricate")
@@ -1528,7 +1565,8 @@ namespace Barotrauma
{
DebugConsole.AddWarning($"Potential error in item variant \"{Identifier}\": " +
$"the item inherits the fabrication requirement of x{originalAmount} \"{originalIdentifier}\" from the base item \"{parent.Identifier}\". " +
$"If this is not intentional, you can use empty <RequiredItem /> elements in the item variant to remove any excess inherited fabrication requirements.");
$"If this is not intentional, you can use empty <RequiredItem /> elements in the item variant to remove any excess inherited fabrication requirements.",
packageToLog);
}
return;
}
@@ -1539,7 +1577,8 @@ namespace Barotrauma
DebugConsole.AddWarning($"Potential error in item variant \"{Identifier}\": " +
$"the base item \"{parent.Identifier}\" requires x{originalAmount} \"{originalIdentifier}\" to fabricate. " +
$"The variant only overrides the required item, not the amount, resulting in a requirement of x{originalAmount} \"{resultIdentifier}\". "+
"Specify the amount in the variant to fix this.");
"Specify the amount in the variant to fix this.",
packageToLog);
}
}
if (originalElement?.Name.ToIdentifier() == "Deconstruct" &&
@@ -1549,18 +1588,35 @@ namespace Barotrauma
variantElement.Elements().Any(e => e.Name.ToIdentifier() == "RequiredItem"))
{
DebugConsole.AddWarning($"Potential error in item variant \"{Identifier}\": " +
$"the item defines deconstruction recipes using 'RequiredItem' instead of 'Item'. Overriding the base recipe may not work correctly.");
$"the item defines deconstruction recipes using 'RequiredItem' instead of 'Item'. Overriding the base recipe may not work correctly.",
packageToLog);
}
if (variantElement.Elements().Any(e => e.Name.ToIdentifier() == "Item") &&
originalElement.Elements().Any(e => e.Name.ToIdentifier() == "RequiredItem"))
{
DebugConsole.AddWarning($"Potential error in item \"{parent.Identifier}\": " +
$"the item defines deconstruction recipes using 'RequiredItem' instead of 'Item'. The item variant \"{Identifier}\" may not override the base recipe correctly.");
$"the item defines deconstruction recipes using 'RequiredItem' instead of 'Item'. The item variant \"{Identifier}\" may not override the base recipe correctly.",
packageToLog);
}
}
}
}
/// <summary>
/// If the base prefab this one is a variant of is defined in a non-vanilla package, returns that non-vanilla package.
/// Otherwise returns the package of this prefab. Can be useful for logging errors that may have been caused by a mod overriding
/// the base item.
/// </summary>
public ContentPackage GetParentModPackageOrThisPackage()
{
if (ParentPrefab != null &&
ParentPrefab.ContentPackage != ContentPackageManager.VanillaCorePackage)
{
return ParentPrefab.ContentPackage;
}
return ContentPackage;
}
public override string ToString()
{
return $"{Name} (identifier: {Identifier})";