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
@@ -184,6 +184,8 @@ namespace Barotrauma.Items.Components
public bool IsFullyClosed => IsClosed && OpenState <= 0f;
public bool HasWindow => Window != Rectangle.Empty;
[Serialize(false, IsPropertySaveable.No, description: "If the door has integrated buttons, it can be opened by interacting with it directly (instead of using buttons wired to it).")]
public bool HasIntegratedButtons { get; private set; }
@@ -381,6 +383,31 @@ namespace Barotrauma.Items.Components
return false;
}
/// <summary>
/// Is the given position inside the vertical bounds of the window, and roughly on the door horizontally? Or the other way around if the door opens horizontally.
/// </summary>
/// <param name="position">Position in the same coordinate space as the door.</param>
/// <param name="maxPerpendicularDistance">Maximum horizontal distance from the door (or vertical if the door opens horizontally)</param>
public bool IsPositionOnWindow(Vector2 position, float maxPerpendicularDistance = 10.0f)
{
if (IsHorizontal)
{
return
position.X >= item.Rect.X + Window.X &&
position.X <= item.Rect.X + Window.X + Window.Width &&
position.Y >= item.Rect.Y - maxPerpendicularDistance &&
position.Y <= item.Rect.Y - item.Rect.Height - maxPerpendicularDistance;
}
else
{
return
position.Y >= item.Rect.Y + Window.Y &&
position.Y <= item.Rect.Y + Window.Y + Window.Height &&
position.X >= item.Rect.X - maxPerpendicularDistance &&
position.Y <= item.Rect.Right + maxPerpendicularDistance;
}
}
public override void Update(float deltaTime, Camera cam)
{
UpdateProjSpecific(deltaTime);
@@ -226,7 +226,8 @@ namespace Barotrauma.Items.Components
foreach ((Character character, Node node) in charactersInRange)
{
if (character == null || character.Removed) { continue; }
character.ApplyAttack(user, node.WorldPosition, attack, MathHelper.Clamp(Voltage, 1.0f, MaxOverVoltageFactor));
character.ApplyAttack(user, node.WorldPosition, attack, MathHelper.Clamp(Voltage, 1.0f, MaxOverVoltageFactor),
impulseDirection: character.WorldPosition - node.WorldPosition);
}
}
DischargeProjSpecific();
@@ -168,8 +168,8 @@ namespace Barotrauma.Items.Components
conditionIncrease += user?.GetStatValue(StatTypes.GeneticMaterialRefineBonus) ?? 0.0f;
if (item.Prefab == otherGeneticMaterial.item.Prefab)
{
float taintedProbability = GetTaintedProbabilityOnRefine(otherGeneticMaterial, user);
item.Condition = Math.Max(item.Condition, otherGeneticMaterial.item.Condition) + conditionIncrease;
float taintedProbability = GetTaintedProbabilityOnRefine(user);
if (taintedProbability >= Rand.Range(0.0f, 1.0f))
{
MakeTainted();
@@ -221,10 +221,10 @@ namespace Barotrauma.Items.Components
return taintedEffectStrength;
}
private float GetTaintedProbabilityOnRefine(Character user)
private float GetTaintedProbabilityOnRefine(GeneticMaterial otherGeneticMaterial, Character user)
{
if (user == null) { return 1.0f; }
float probability = MathHelper.Lerp(0.0f, 0.99f, item.Condition / 100.0f);
float probability = MathHelper.Lerp(0.0f, 0.99f, Math.Max(item.Condition, otherGeneticMaterial.Item.Condition) / 100.0f);
probability *= MathHelper.Lerp(1.0f, 0.25f, DegreeOfSuccess(user));
return MathHelper.Clamp(probability, 0.0f, 1.0f);
}
@@ -59,7 +59,8 @@ namespace Barotrauma.Items.Components
StatusEffect effect = StatusEffect.Load(subElement, Prefab?.Name.Value);
if (effect.type != ActionType.OnProduceSpawned)
{
DebugConsole.ThrowError("Only OnProduceSpawned type can be used in <ProducedItem>.");
DebugConsole.ThrowError("Only OnProduceSpawned type can be used in <ProducedItem>.",
contentPackage: element.ContentPackage);
continue;
}
@@ -134,7 +134,8 @@ namespace Barotrauma.Items.Components
suitableProjectiles = element.GetAttributeIdentifierArray(nameof(suitableProjectiles), Array.Empty<Identifier>()).ToHashSet();
if (ReloadSkillRequirement > 0 && ReloadNoSkill <= reload)
{
DebugConsole.AddWarning($"Invalid XML at {item.Name}: ReloadNoSkill is lower or equal than it's reload skill, despite having ReloadSkillRequirement.");
DebugConsole.AddWarning($"Invalid XML at {item.Name}: ReloadNoSkill is lower or equal than it's reload skill, despite having ReloadSkillRequirement.",
item.Prefab.ContentPackage);
}
InitProjSpecific(element);
}
@@ -137,7 +137,8 @@ namespace Barotrauma.Items.Components
if (element.GetAttribute("limbfixamount") != null)
{
DebugConsole.ThrowError("Error in item \"" + item.Name + "\" - RepairTool damage should be configured using a StatusEffect with Afflictions, not the limbfixamount attribute.");
DebugConsole.ThrowError("Error in item \"" + item.Name + "\" - RepairTool damage should be configured using a StatusEffect with Afflictions, not the limbfixamount attribute.",
contentPackage: element.ContentPackage);
}
fixableEntities = new HashSet<Identifier>();
@@ -149,7 +150,8 @@ namespace Barotrauma.Items.Components
case "fixable":
if (subElement.GetAttribute("name") != null)
{
DebugConsole.ThrowError("Error in RepairTool " + item.Name + " - use identifiers instead of names to configure fixable entities.");
DebugConsole.ThrowError("Error in RepairTool " + item.Name + " - use identifiers instead of names to configure fixable entities.",
contentPackage: element.ContentPackage);
fixableEntities.Add(subElement.GetAttribute("name").Value.ToIdentifier());
}
else
@@ -536,7 +538,7 @@ namespace Barotrauma.Items.Components
{
Vector2 displayPos = ConvertUnits.ToDisplayUnits(rayStart + (rayEnd - rayStart) * lastPickedFraction * 0.9f);
if (item.CurrentHull.Submarine != null) { displayPos += item.CurrentHull.Submarine.Position; }
new FireSource(displayPos);
new FireSource(displayPos, sourceCharacter: user);
}
}
}
@@ -38,7 +38,7 @@ namespace Barotrauma.Items.Components
{
if (aimPos == Vector2.Zero)
{
aimPos = new Vector2(0.6f, 0.1f);
aimPos = new Vector2(0.45f, 0.1f);
}
}
@@ -71,6 +71,18 @@ namespace Barotrauma.Items.Components
protected const float CorrectionDelay = 1.0f;
protected CoroutineHandle delayedCorrectionCoroutine;
/// <summary>
/// If enabled, the contents of the item are not transferred when the player transfers items between subs.
/// Use this if this component uses item containers in a way where removing the item from the container via external means would cause problems.
/// </summary>
public virtual bool DontTransferInventoryBetweenSubs => false;
/// <summary>
/// If enabled, the items inside any of the item containers on this item cannot be sold at an outpost.
/// Use in similar cases as <see cref="DontTransferInventoryBetweenSubs"/>.
/// </summary>
public virtual bool DisallowSellingItemsFromContainer => false;
[Editable, Serialize(0.0f, IsPropertySaveable.No, description: "How long it takes to pick up the item (in seconds).")]
public float PickingTime
{
@@ -285,7 +297,8 @@ namespace Barotrauma.Items.Components
}
catch (Exception e)
{
DebugConsole.ThrowError("Invalid select key in " + element + "!", e);
DebugConsole.ThrowError("Invalid select key in " + element + "!", e,
contentPackage: element.ContentPackage);
}
PickKey = InputType.Select;
@@ -298,7 +311,8 @@ namespace Barotrauma.Items.Components
}
catch (Exception e)
{
DebugConsole.ThrowError("Invalid pick key in " + element + "!", e);
DebugConsole.ThrowError("Invalid pick key in " + element + "!", e,
contentPackage: element.ContentPackage);
}
SerializableProperties = SerializableProperty.DeserializeProperties(this, element);
@@ -310,7 +324,8 @@ namespace Barotrauma.Items.Components
var component = item.Components.Find(ic => ic.Name.Equals(inheritRequiredSkillsFrom, StringComparison.OrdinalIgnoreCase));
if (component == null)
{
DebugConsole.ThrowError($"Error in item \"{item.Name}\" - component \"{name}\" is set to inherit its required skills from \"{inheritRequiredSkillsFrom}\", but a component of that type couldn't be found.");
DebugConsole.ThrowError($"Error in item \"{item.Name}\" - component \"{name}\" is set to inherit its required skills from \"{inheritRequiredSkillsFrom}\", but a component of that type couldn't be found.",
contentPackage: element.ContentPackage);
}
else
{
@@ -325,7 +340,8 @@ namespace Barotrauma.Items.Components
var component = item.Components.Find(ic => ic.Name.Equals(inheritStatusEffectsFrom, StringComparison.OrdinalIgnoreCase));
if (component == null)
{
DebugConsole.ThrowError($"Error in item \"{item.Name}\" - component \"{name}\" is set to inherit its StatusEffects from \"{inheritStatusEffectsFrom}\", but a component of that type couldn't be found.");
DebugConsole.ThrowError($"Error in item \"{item.Name}\" - component \"{name}\" is set to inherit its StatusEffects from \"{inheritStatusEffectsFrom}\", but a component of that type couldn't be found.",
contentPackage: element.ContentPackage);
}
else if (component.statusEffectLists != null)
{
@@ -360,7 +376,8 @@ namespace Barotrauma.Items.Components
case "requiredskills":
if (subElement.GetAttribute("name") != null)
{
DebugConsole.ThrowError("Error in item config \"" + item.ConfigFilePath + "\" - skill requirement in component " + GetType().ToString() + " should use a skill identifier instead of the name of the skill.");
DebugConsole.ThrowError("Error in item config \"" + item.ConfigFilePath + "\" - skill requirement in component " + GetType().ToString() + " should use a skill identifier instead of the name of the skill.",
contentPackage: element.ContentPackage);
continue;
}
@@ -426,7 +443,8 @@ namespace Barotrauma.Items.Components
}
else if (!allowEmpty)
{
DebugConsole.ThrowError("Error in item config \"" + item.ConfigFilePath + "\" - component " + GetType().ToString() + " requires an item with no identifiers.");
DebugConsole.ThrowError("Error in item config \"" + item.ConfigFilePath + "\" - component " + GetType().ToString() + " requires an item with no identifiers.",
contentPackage: element.ContentPackage);
}
}
@@ -968,7 +986,8 @@ namespace Barotrauma.Items.Components
{
if (errorMessages)
{
DebugConsole.ThrowError($"Could not find the component \"{typeName}\" ({item.Prefab.ContentFile.Path})");
DebugConsole.ThrowError($"Could not find the component \"{typeName}\" ({item.Prefab.ContentFile.Path})",
contentPackage: element.ContentPackage);
}
return null;
}
@@ -977,7 +996,8 @@ namespace Barotrauma.Items.Components
{
if (errorMessages)
{
DebugConsole.ThrowError($"Could not find the component \"{typeName}\" ({item.Prefab.ContentFile.Path})", e);
DebugConsole.ThrowError($"Could not find the component \"{typeName}\" ({item.Prefab.ContentFile.Path})", e,
contentPackage: element.ContentPackage);
}
return null;
}
@@ -990,14 +1010,16 @@ namespace Barotrauma.Items.Components
if (constructor == null)
{
DebugConsole.ThrowError(
$"Could not find the constructor of the component \"{typeName}\" ({item.Prefab.ContentFile.Path})");
$"Could not find the constructor of the component \"{typeName}\" ({item.Prefab.ContentFile.Path})",
contentPackage: element.ContentPackage);
return null;
}
}
catch (Exception e)
{
DebugConsole.ThrowError(
$"Could not find the constructor of the component \"{typeName}\" ({item.Prefab.ContentFile.Path})", e);
$"Could not find the constructor of the component \"{typeName}\" ({item.Prefab.ContentFile.Path})", e,
contentPackage: element.ContentPackage);
return null;
}
ItemComponent ic = null;
@@ -1010,7 +1032,7 @@ namespace Barotrauma.Items.Components
}
catch (TargetInvocationException e)
{
DebugConsole.ThrowError($"Error while loading component of the type {type}.", e.InnerException);
DebugConsole.ThrowError($"Error while loading component of the type {type}.", e.InnerException, contentPackage: element.ContentPackage);
GameAnalyticsManager.AddErrorEventOnce(
$"ItemComponent.Load:TargetInvocationException{item.Name}{element.Name}",
GameAnalyticsManager.ErrorSeverity.Error,
@@ -284,7 +284,8 @@ namespace Barotrauma.Items.Components
RelatedItem containable = RelatedItem.Load(subElement, returnEmpty: false, parentDebugName: item.Name);
if (containable == null)
{
DebugConsole.ThrowError("Error in item config \"" + item.ConfigFilePath + "\" - containable with no identifiers.");
DebugConsole.ThrowError("Error in item config \"" + item.ConfigFilePath + "\" - containable with no identifiers.",
contentPackage: element.ContentPackage);
continue;
}
ContainableItems ??= new List<RelatedItem>();
@@ -321,7 +322,8 @@ namespace Barotrauma.Items.Components
RelatedItem containable = RelatedItem.Load(subSubElement, returnEmpty: false, parentDebugName: item.Name);
if (containable == null)
{
DebugConsole.ThrowError("Error in item config \"" + item.ConfigFilePath + "\" - containable with no identifiers.");
DebugConsole.ThrowError("Error in item config \"" + item.ConfigFilePath + "\" - containable with no identifiers.",
contentPackage: element.ContentPackage);
continue;
}
subContainableItems.Add(containable);
@@ -349,7 +351,8 @@ namespace Barotrauma.Items.Components
RelatedItem containable = RelatedItem.Load(subElement, returnEmpty: false, parentDebugName: item.Name);
if (containable == null)
{
DebugConsole.ThrowError("Error when loading containable restrictions for \"" + item.Name + "\" - containable with no identifiers.");
DebugConsole.ThrowError("Error when loading containable restrictions for \"" + item.Name + "\" - containable with no identifiers.",
contentPackage: element.ContentPackage);
continue;
}
ContainableItems[containableIndex] = containable;
@@ -622,7 +622,7 @@ namespace Barotrauma.Items.Components
return element;
}
private void LoadLimbPositions(XElement element)
private void LoadLimbPositions(ContentXElement element)
{
limbPositions.Clear();
foreach (var subElement in element.Elements())
@@ -631,7 +631,8 @@ namespace Barotrauma.Items.Components
string limbStr = subElement.GetAttributeString("limb", "");
if (!Enum.TryParse(subElement.GetAttribute("limb").Value, out LimbType limbType))
{
DebugConsole.ThrowError($"Error in item \"{item.Name}\" - {limbStr} is not a valid limb type.");
DebugConsole.ThrowError($"Error in item \"{item.Name}\" - {limbStr} is not a valid limb type.",
contentPackage: element.ContentPackage);
}
else
{
@@ -101,7 +101,8 @@ namespace Barotrauma.Items.Components
{
if (subElement.Name.ToString().Equals("fabricableitem", StringComparison.OrdinalIgnoreCase))
{
DebugConsole.ThrowError("Error in item " + item.Name + "! Fabrication recipes should be defined in the craftable item's xml, not in the fabricator.");
DebugConsole.ThrowError("Error in item " + item.Name + "! Fabrication recipes should be defined in the craftable item's xml, not in the fabricator.",
contentPackage: element.ContentPackage);
break;
}
}
@@ -119,12 +120,16 @@ namespace Barotrauma.Items.Components
}
}
//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 = itemPrefab.GetParentModPackageOrThisPackage();
bool recipeInvalid = false;
foreach (var requiredItem in recipe.RequiredItems)
{
if (requiredItem.ItemPrefabs.None())
{
DebugConsole.ThrowError($"Error in the fabrication recipe for \"{itemPrefab.Name}\". Could not find the ingredient \"{requiredItem}\".");
DebugConsole.ThrowError($"Error in the fabrication recipe for \"{itemPrefab.Name}\". Could not find the ingredient \"{requiredItem}\".",
contentPackage: packageToLog);
recipeInvalid = true;
}
}
@@ -132,7 +137,8 @@ namespace Barotrauma.Items.Components
if (fabricationRecipes.TryGetValue(recipe.RecipeHash, out var duplicateRecipe))
{
DebugConsole.ThrowError($"Error in the fabrication recipe for \"{itemPrefab.Name}\". Duplicate recipe in \"{duplicateRecipe.TargetItem.Identifier}\".");
DebugConsole.ThrowError($"Error in the fabrication recipe for \"{itemPrefab.Name}\". Duplicate recipe in \"{duplicateRecipe.TargetItem.Identifier}\".",
contentPackage: packageToLog);
continue;
}
fabricationRecipes.Add(recipe.RecipeHash, recipe);
@@ -416,7 +422,7 @@ namespace Barotrauma.Items.Components
if (requiredItem.UseCondition && suitableIngredient.ConditionPercentage - requiredItem.MinCondition * 100 > 0.0f)
{
suitableIngredient.Condition -= suitableIngredient.Prefab.Health * requiredItem.MinCondition;
continue;
break;
}
if (suitableIngredient.OwnInventory != null)
{
@@ -82,6 +82,9 @@ namespace Barotrauma.Items.Components
private List<LightComponent>? lightComponents;
// We don't want the seeds to be transferred to a new submarine as seeds are not supposed to leave the container after they have been planted.
public override bool DontTransferInventoryBetweenSubs => true;
public Planter(Item item, ContentXElement element) : base(item, element)
{
canBePicked = true;
@@ -407,7 +407,7 @@ namespace Barotrauma.Items.Components
}
}
if (!(this is RelayComponent))
if (this is not RelayComponent)
{
if (PowerConnections.Any(p => !p.IsOutput) && PowerConnections.Any(p => p.IsOutput))
{
@@ -306,7 +306,8 @@ namespace Barotrauma.Items.Components
if (item.body == null)
{
DebugConsole.ThrowError($"Error in projectile definition ({item.Name}): No body defined!");
DebugConsole.ThrowError($"Error in projectile definition ({item.Name}): No body defined!",
contentPackage: element.ContentPackage);
return;
}
@@ -60,7 +60,8 @@ namespace Barotrauma.Items.Components
string statTypeString = subElement.GetAttributeString("stattype", "");
if (!Enum.TryParse(statTypeString, true, out StatType statType))
{
DebugConsole.ThrowError("Invalid stat type type \"" + statTypeString + "\" in item (" + ((MapEntity)item).Prefab.Identifier + ")");
DebugConsole.ThrowError("Invalid stat type type \"" + statTypeString + "\" in item (" + ((MapEntity)item).Prefab.Identifier + ")",
contentPackage: element.ContentPackage);
}
float statValue = subElement.GetAttributeFloat("value", 0f);
statValues.TryAdd(statType, statValue);
@@ -82,7 +82,8 @@ namespace Barotrauma.Items.Components
Holdable = item.GetComponent<Holdable>();
if (Holdable == null || !Holdable.Attachable)
{
DebugConsole.ThrowError("Error in initializing a Scanner component: an attachable Holdable component is required on the same item and none was found");
DebugConsole.ThrowError("Error in initializing a Scanner component: an attachable Holdable component is required on the same item and none was found",
contentPackage: item.Prefab.ContentPackage);
IsActive = false;
}
}
@@ -26,7 +26,8 @@ namespace Barotrauma.Items.Components
RequiredSignalCount = element.GetChildElements("TerminalButton").Count(c => c.GetAttribute("style") != null);
if (RequiredSignalCount < 1)
{
DebugConsole.ThrowError($"Error in item \"{item.Name}\": no TerminalButton elements defined for the ButtonTerminal component!");
DebugConsole.ThrowError($"Error in item \"{item.Name}\": no TerminalButton elements defined for the ButtonTerminal component!",
contentPackage: element.ContentPackage);
}
InitProjSpecific(element);
}
@@ -26,19 +26,40 @@ namespace Barotrauma.Items.Components
public override bool IsActive => true;
// We don't want the components and wires to transfer between subs as it would cause issues.
public override bool DontTransferInventoryBetweenSubs => true;
// We don't want to sell the components and wires inside the circuit box
public override bool DisallowSellingItemsFromContainer => true;
public Option<CircuitBoxConnection> FindInputOutputConnection(Identifier connectionName)
{
foreach (CircuitBoxInputConnection input in Inputs)
{
if (input.Name != connectionName) { continue; }
return Option.Some<CircuitBoxConnection>(input);
}
foreach (CircuitBoxOutputConnection output in Outputs)
{
if (output.Name != connectionName) { continue; }
return Option.Some<CircuitBoxConnection>(output);
}
return Option.None;
}
public Option<CircuitBoxConnection> FindInputOutputConnection(Connection connection)
{
foreach (CircuitBoxInputConnection input in Inputs)
{
if (input.Connection != connection) { continue; }
return Option.Some<CircuitBoxConnection>(input);
}
foreach (CircuitBoxOutputConnection output in Outputs)
{
if (output.Connection != connection) { continue; }
return Option.Some<CircuitBoxConnection>(output);
}
@@ -338,7 +359,7 @@ namespace Barotrauma.Items.Components
return;
}
SpawnItem(this, prefab, WireContainer, wire =>
SpawnItem(prefab, user: null, container: WireContainer, onSpawned: wire =>
{
AddWireDirect(wireId, prefab, Option.Some(wire), one, two);
onItemSpawned(wire);
@@ -359,7 +380,7 @@ namespace Barotrauma.Items.Components
private void AddWireDirect(ushort id, ItemPrefab prefab, Option<Item> backingItem, CircuitBoxConnection one, CircuitBoxConnection two)
=> Wires.Add(new CircuitBoxWire(this, id, backingItem, one, two, prefab));
private bool AddComponentInternal(ushort id, ItemPrefab prefab, ItemPrefab usedResource, Vector2 pos, Action<Item> onItemSpawned)
private bool AddComponentInternal(ushort id, ItemPrefab prefab, ItemPrefab usedResource, Vector2 pos, Character? user, Action<Item>? onItemSpawned)
{
if (id is ICircuitBoxIdentifiable.NullComponentID)
{
@@ -373,12 +394,12 @@ namespace Barotrauma.Items.Components
return false;
}
SpawnItem(this, prefab, ComponentContainer, spawnedItem =>
SpawnItem(prefab, user, ComponentContainer, spawnedItem =>
{
Components.Add(new CircuitBoxComponent(id, spawnedItem, pos, this, usedResource));
onItemSpawned(spawnedItem);
onItemSpawned?.Invoke(spawnedItem);
OnViewUpdateProjSpecific();
});
OnViewUpdateProjSpecific();
return true;
}
@@ -646,7 +667,7 @@ namespace Barotrauma.Items.Components
return Option.None;
}
public static void SpawnItem(CircuitBox circuitBox, ItemPrefab prefab, ItemContainer? container, Action<Item> onSpawned)
public static void SpawnItem(ItemPrefab prefab, Character? user, ItemContainer? container, Action<Item> onSpawned)
{
if (container is null)
{
@@ -655,13 +676,27 @@ namespace Barotrauma.Items.Components
if (IsInGame())
{
Entity.Spawner?.AddItemToSpawnQueue(prefab, container.Inventory, onSpawned: onSpawned);
Entity.Spawner?.AddItemToSpawnQueue(prefab, container.Inventory, onSpawned: it =>
{
AssignWifiComponentTeam(it, user);
onSpawned(it);
});
return;
}
Item forceSpawnedItem = new Item(prefab, Vector2.Zero, null);
container.Inventory.TryPutItem(forceSpawnedItem, null);
onSpawned(forceSpawnedItem);
AssignWifiComponentTeam(forceSpawnedItem, user);
static void AssignWifiComponentTeam(Item item, Character? user)
{
if (user == null) { return; }
foreach (WifiComponent wifiComponent in item.GetComponents<WifiComponent>())
{
wifiComponent.TeamID = user.TeamID;
}
}
}
public static void RemoveItem(Item item)
@@ -97,7 +97,8 @@ namespace Barotrauma.Items.Components
string triggeredByAttribute = element.GetAttributeString("triggeredby", "Character");
if (!Enum.TryParse(triggeredByAttribute, out triggeredBy))
{
DebugConsole.ThrowError($"Error in ForceComponent config: \"{triggeredByAttribute}\" is not a valid triggerer type.");
DebugConsole.ThrowError($"Error in ForceComponent config: \"{triggeredByAttribute}\" is not a valid triggerer type.",
contentPackage: element.ContentPackage);
}
triggerOnce = element.GetAttributeBool("triggeronce", false);
string parentDebugName = $"TriggerComponent in {item.Name}";
@@ -362,7 +362,8 @@ namespace Barotrauma.Items.Components
case "sprite":
if (subElement.GetAttribute("texture") == null)
{
DebugConsole.ThrowError("Item \"" + item.Name + "\" doesn't have a texture specified!");
DebugConsole.ThrowError("Item \"" + item.Name + "\" doesn't have a texture specified!",
contentPackage: element.ContentPackage);
return;
}