v1.2.6.0 (Winter Update)

This commit is contained in:
Regalis11
2023-12-14 16:11:27 +02:00
parent af8cc89fce
commit b91e85559d
375 changed files with 7771 additions and 2874 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; }
@@ -862,24 +871,43 @@ namespace Barotrauma
public int GetMaxStackSize(Inventory inventory)
{
int extraStackSize = inventory switch
{
ItemInventory { Owner: Item it } i => (int)it.StatManager.GetAdjustedValueAdditive(ItemTalentStats.ExtraStackSize, i.ExtraStackSize),
CharacterInventory { Owner: Character { Info: { } info } } i => i.ExtraStackSize + (int)info.GetSavedStatValueWithAll(StatTypes.InventoryExtraStackSize, Category.ToIdentifier()),
not null => inventory.ExtraStackSize,
null => 0
};
if (inventory is CharacterInventory && maxStackSizeCharacterInventory > 0)
{
return maxStackSizeCharacterInventory;
return MaxStackWithExtra(maxStackSizeCharacterInventory, extraStackSize);
}
else if (inventory?.Owner is Item item &&
(item.GetComponent<Holdable>() is { Attachable: false } || item.GetComponent<Wearable>() != null))
{
if (maxStackSizeHoldableOrWearableInventory > 0)
{
return maxStackSizeHoldableOrWearableInventory;
return MaxStackWithExtra(maxStackSizeHoldableOrWearableInventory, extraStackSize);
}
else if (maxStackSizeCharacterInventory > 0)
{
//if maxStackSizeHoldableOrWearableInventory is not set, it defaults to maxStackSizeCharacterInventory
return maxStackSizeCharacterInventory;
return MaxStackWithExtra(maxStackSizeCharacterInventory, extraStackSize);
}
}
return maxStackSize;
return MaxStackWithExtra(maxStackSize, extraStackSize);
static int MaxStackWithExtra(int maxStackSize, int extraStackSize)
{
extraStackSize = Math.Max(extraStackSize, 0);
if (maxStackSize == 1)
{
return Math.Min(maxStackSize, Inventory.MaxPossibleStackSize);
}
return Math.Min(maxStackSize + extraStackSize, Inventory.MaxPossibleStackSize);
}
}
[Serialize(false, IsPropertySaveable.No)]
@@ -1016,7 +1044,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);
@@ -1054,7 +1083,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;
@@ -1072,7 +1102,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
@@ -1085,7 +1116,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
@@ -1103,13 +1135,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);
@@ -1122,12 +1156,18 @@ 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 =
(variantOf.ContentPackage != null && variantOf.ContentPackage != ContentPackageManager.VanillaCorePackage) ?
variantOf.ContentPackage :
GetParentModPackageOrThisPackage();
int prevRecipeIndex = loadedRecipes.IndexOf(prevRecipe);
DebugConsole.ThrowError(
DebugConsole.AddWarning(
$"Error in item prefab \"{ToString()}\": " +
$"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."
);
$"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
{
@@ -1142,7 +1182,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
@@ -1192,7 +1233,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);
@@ -1201,6 +1243,8 @@ namespace Barotrauma
}
}
Size = ConfigElement.GetAttributeVector2(nameof(Size), Size);
#if CLIENT
ParseSubElementsClient(ConfigElement, variantOf);
#endif
@@ -1231,7 +1275,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);
@@ -1248,7 +1292,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
@@ -1256,7 +1301,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
@@ -1316,9 +1362,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;
@@ -1525,6 +1571,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")
@@ -1538,7 +1587,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;
}
@@ -1549,7 +1599,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" &&
@@ -1559,18 +1610,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})";