v0.12.0.2
This commit is contained in:
@@ -20,7 +20,7 @@ using Microsoft.Xna.Framework.Graphics;
|
||||
namespace Barotrauma
|
||||
{
|
||||
|
||||
partial class Item : MapEntity, IDamageable, ISerializableEntity, IServerSerializable, IClientSerializable
|
||||
partial class Item : MapEntity, IDamageable, IIgnorable, ISerializableEntity, IServerSerializable, IClientSerializable
|
||||
{
|
||||
public static List<Item> ItemList = new List<Item>();
|
||||
public ItemPrefab Prefab => prefab as ItemPrefab;
|
||||
@@ -76,7 +76,7 @@ namespace Barotrauma
|
||||
private readonly bool hasWaterStatusEffects;
|
||||
|
||||
private Inventory parentInventory;
|
||||
private readonly Inventory ownInventory;
|
||||
private readonly ItemInventory ownInventory;
|
||||
|
||||
private Rectangle defaultRect;
|
||||
|
||||
@@ -171,6 +171,43 @@ namespace Barotrauma
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use <see cref="IsPlayerInteractable"/> to also check <see cref="NonInteractable"/>
|
||||
/// </summary>
|
||||
[Editable, Serialize(false, true, description: "When enabled, item is interactable only for characters on non-player teams.", alwaysUseInstanceValues: true)]
|
||||
public bool NonPlayerTeamInteractable
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks both <see cref="NonInteractable"/> and <see cref="NonPlayerTeamInteractable"/>
|
||||
/// </summary>
|
||||
public bool IsPlayerTeamInteractable
|
||||
{
|
||||
get
|
||||
{
|
||||
return !NonInteractable && !NonPlayerTeamInteractable;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns interactibility based on whether the character is on a player team
|
||||
/// </summary>
|
||||
public bool IsInteractable(Character character)
|
||||
{
|
||||
if (character != null && character.IsOnPlayerTeam)
|
||||
{
|
||||
|
||||
return IsPlayerTeamInteractable;
|
||||
}
|
||||
else
|
||||
{
|
||||
return !NonInteractable;
|
||||
}
|
||||
}
|
||||
|
||||
private float rotationRad;
|
||||
|
||||
[Editable(0.0f, 360.0f, DecimalCount = 1, ValueStep = 1f), Serialize(0.0f, true)]
|
||||
@@ -414,6 +451,7 @@ namespace Barotrauma
|
||||
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) { return; }
|
||||
if (!MathUtils.IsValid(value)) { return; }
|
||||
if (Indestructible) { return; }
|
||||
if (InvulnerableToDamage && value <= condition) { return;}
|
||||
|
||||
float prev = condition;
|
||||
bool wasInFullCondition = IsFullCondition;
|
||||
@@ -466,10 +504,13 @@ namespace Barotrauma
|
||||
/// </summary>
|
||||
public bool Indestructible
|
||||
{
|
||||
get { return indestructible ?? Prefab.Indestructible; }
|
||||
set { indestructible = value; }
|
||||
get => indestructible ?? Prefab.Indestructible;
|
||||
set => indestructible = value;
|
||||
}
|
||||
|
||||
[Editable, Serialize(false, isSaveable: true, "When enabled will prevent the item from taking damage from all sources")]
|
||||
public bool InvulnerableToDamage { get; set; }
|
||||
|
||||
public bool StolenDuringRound;
|
||||
|
||||
private bool spawnedInOutpost;
|
||||
@@ -566,12 +607,12 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
//which type of inventory slots (head, torso, any, etc) the item can be placed in
|
||||
public List<InvSlotType> AllowedSlots
|
||||
public IEnumerable<InvSlotType> AllowedSlots
|
||||
{
|
||||
get
|
||||
{
|
||||
Pickable p = GetComponent<Pickable>();
|
||||
return (p == null) ? new List<InvSlotType>() { InvSlotType.Any } : p.AllowedSlots;
|
||||
return (p == null) ? InvSlotType.Any.ToEnumerable() : p.AllowedSlots;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -589,19 +630,11 @@ namespace Barotrauma
|
||||
{
|
||||
get
|
||||
{
|
||||
// It's not a good practice to return null if the method tells that it returns a collection, because:
|
||||
// a) the user has to handle this -> more code and more null reference exceptions
|
||||
// b) it makes it more difficult to make use of chained function calls (which are quite powerful), although '?' makes it possible
|
||||
// c) it's against the functional paradigm that e.g. Linq follows (for good reasons)
|
||||
// In general, it's better to return an empty collection instead,
|
||||
// but changing it here might cause unwanted implications.
|
||||
// Also it can be a minor optimization to return null instead of creating an empty collection,
|
||||
// but if that's the case I'd prefer caching an empty collection and using that instead. Just something to consider in the future.
|
||||
return ownInventory?.Items.Where(i => i != null);
|
||||
return ownInventory?.AllItems ?? Enumerable.Empty<Item>();
|
||||
}
|
||||
}
|
||||
|
||||
public Inventory OwnInventory
|
||||
public ItemInventory OwnInventory
|
||||
{
|
||||
get { return ownInventory; }
|
||||
}
|
||||
@@ -643,6 +676,8 @@ namespace Barotrauma
|
||||
get { return allPropertyObjects; }
|
||||
}
|
||||
|
||||
public bool IgnoreByAI => OrderedToBeIgnored || HasTag("ignorebyai");
|
||||
public bool OrderedToBeIgnored { get; set; }
|
||||
|
||||
public Item(ItemPrefab itemPrefab, Vector2 position, Submarine submarine, ushort id = Entity.NullEntityID)
|
||||
: this(new Rectangle(
|
||||
@@ -845,6 +880,8 @@ namespace Barotrauma
|
||||
|
||||
partial void InitProjSpecific();
|
||||
|
||||
public bool IsContainerPreferred(ItemContainer container, out bool isPreferencesDefined, out bool isSecondary) => Prefab.IsContainerPreferred(this, container, out isPreferencesDefined, out isSecondary);
|
||||
|
||||
public override MapEntity Clone()
|
||||
{
|
||||
Item clone = new Item(rect, Prefab, Submarine, callOnItemLoaded: false)
|
||||
@@ -899,14 +936,12 @@ namespace Barotrauma
|
||||
component.OnItemLoaded();
|
||||
}
|
||||
|
||||
if (ContainedItems != null)
|
||||
foreach (Item containedItem in ContainedItems)
|
||||
{
|
||||
foreach (Item containedItem in ContainedItems)
|
||||
{
|
||||
var containedClone = containedItem.Clone();
|
||||
clone.ownInventory.TryPutItem(containedClone as Item, null);
|
||||
}
|
||||
}
|
||||
var containedClone = containedItem.Clone();
|
||||
clone.ownInventory.TryPutItem(containedClone as Item, null);
|
||||
}
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
@@ -1141,13 +1176,13 @@ namespace Barotrauma
|
||||
{
|
||||
if (parentInventory != null && parentInventory.Owner != null)
|
||||
{
|
||||
if (parentInventory.Owner is Character)
|
||||
if (parentInventory.Owner is Character character)
|
||||
{
|
||||
CurrentHull = ((Character)parentInventory.Owner).AnimController.CurrentHull;
|
||||
CurrentHull = character.AnimController.CurrentHull;
|
||||
}
|
||||
else if (parentInventory.Owner is Item)
|
||||
else if (parentInventory.Owner is Item item)
|
||||
{
|
||||
CurrentHull = ((Item)parentInventory.Owner).CurrentHull;
|
||||
CurrentHull = item.CurrentHull;
|
||||
}
|
||||
|
||||
Submarine = parentInventory.Owner.Submarine;
|
||||
@@ -1157,7 +1192,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
CurrentHull = Hull.FindHull(WorldPosition, CurrentHull);
|
||||
if (body != null && body.Enabled)
|
||||
if (body != null && body.Enabled && (body.BodyType == BodyType.Dynamic || Submarine == null))
|
||||
{
|
||||
Submarine = CurrentHull?.Submarine;
|
||||
body.Submarine = Submarine;
|
||||
@@ -1180,7 +1215,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Is the item or any of its containers of the item set to be ignored?
|
||||
/// Should this item or any of its containers be ignored by the AI?
|
||||
/// </summary>
|
||||
public bool IsThisOrAnyContainerIgnoredByAI()
|
||||
{
|
||||
@@ -1308,22 +1343,17 @@ namespace Barotrauma
|
||||
|
||||
if (effect.HasTargetType(StatusEffect.TargetType.Contained))
|
||||
{
|
||||
var containedItems = ownInventory?.Items;
|
||||
if (containedItems != null)
|
||||
foreach (Item containedItem in ContainedItems)
|
||||
{
|
||||
foreach (Item containedItem in containedItems)
|
||||
if (effect.TargetIdentifiers != null &&
|
||||
!effect.TargetIdentifiers.Contains(containedItem.prefab.Identifier) &&
|
||||
!effect.TargetIdentifiers.Any(id => containedItem.HasTag(id)))
|
||||
{
|
||||
if (containedItem == null) { continue; }
|
||||
if (effect.TargetIdentifiers != null &&
|
||||
!effect.TargetIdentifiers.Contains(containedItem.prefab.Identifier) &&
|
||||
!effect.TargetIdentifiers.Any(id => containedItem.HasTag(id)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
hasTargets = true;
|
||||
targets.Add(containedItem);
|
||||
continue;
|
||||
}
|
||||
|
||||
hasTargets = true;
|
||||
targets.Add(containedItem);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1385,7 +1415,7 @@ namespace Barotrauma
|
||||
|
||||
public AttackResult AddDamage(Character attacker, Vector2 worldPosition, Attack attack, float deltaTime, bool playSound = true)
|
||||
{
|
||||
if (Indestructible) { return new AttackResult(); }
|
||||
if (Indestructible || InvulnerableToDamage) { return new AttackResult(); }
|
||||
|
||||
float damageAmount = attack.GetItemDamage(deltaTime);
|
||||
Condition -= damageAmount;
|
||||
@@ -1575,8 +1605,7 @@ namespace Barotrauma
|
||||
body.SetTransform(body.SimPosition + prevSub.SimPosition - Submarine.SimPosition, body.Rotation);
|
||||
}
|
||||
|
||||
var containedItems = ownInventory?.Items;
|
||||
if (Submarine != prevSub && containedItems != null)
|
||||
if (Submarine != prevSub)
|
||||
{
|
||||
foreach (Item containedItem in ContainedItems)
|
||||
{
|
||||
@@ -1664,15 +1693,10 @@ namespace Barotrauma
|
||||
#endif
|
||||
}
|
||||
|
||||
var containedItems = ownInventory?.Items;
|
||||
if (containedItems != null)
|
||||
foreach (Item contained in ContainedItems)
|
||||
{
|
||||
foreach (Item contained in containedItems)
|
||||
{
|
||||
if (contained == null) { continue; }
|
||||
if (contained.body != null) { contained.HandleCollision(impact); }
|
||||
}
|
||||
}
|
||||
if (contained.body != null) { contained.HandleCollision(impact); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1936,7 +1960,7 @@ namespace Barotrauma
|
||||
Skill requiredSkill = null;
|
||||
float skillMultiplier = 1;
|
||||
#endif
|
||||
if (NonInteractable) { return false; }
|
||||
if (!IsInteractable(picker)) { return false; }
|
||||
foreach (ItemComponent ic in components)
|
||||
{
|
||||
bool pickHit = false, selectHit = false;
|
||||
@@ -2040,24 +2064,19 @@ namespace Barotrauma
|
||||
|
||||
public float GetContainedItemConditionPercentage()
|
||||
{
|
||||
var containedItems = ContainedItems;
|
||||
if (ownInventory == null) { return -1; }
|
||||
|
||||
if (containedItems != null)
|
||||
float condition = 0f;
|
||||
float maxCondition = 0f;
|
||||
foreach (Item item in ContainedItems)
|
||||
{
|
||||
float condition = 0f;
|
||||
float maxCondition = 0f;
|
||||
|
||||
foreach (Item item in containedItems)
|
||||
{
|
||||
condition += item.condition;
|
||||
maxCondition += item.MaxCondition;
|
||||
}
|
||||
|
||||
if (maxCondition > 0.0f)
|
||||
{
|
||||
return condition / maxCondition;
|
||||
}
|
||||
condition += item.condition;
|
||||
maxCondition += item.MaxCondition;
|
||||
}
|
||||
if (maxCondition > 0.0f)
|
||||
{
|
||||
return condition / maxCondition;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
@@ -2252,7 +2271,6 @@ namespace Barotrauma
|
||||
|
||||
public void Unequip(Character character)
|
||||
{
|
||||
character.DeselectItem(this);
|
||||
foreach (ItemComponent ic in components) { ic.Unequip(character); }
|
||||
}
|
||||
|
||||
@@ -2689,11 +2707,18 @@ namespace Barotrauma
|
||||
|
||||
public virtual void Reset()
|
||||
{
|
||||
var holdable = GetComponent<Holdable>();
|
||||
bool wasAttached = holdable?.Attached ?? false;
|
||||
|
||||
SerializableProperties = SerializableProperty.DeserializeProperties(this, Prefab.ConfigElement);
|
||||
Sprite.ReloadXML();
|
||||
SpriteDepth = Sprite.Depth;
|
||||
condition = MaxCondition;
|
||||
components.ForEach(c => c.Reset());
|
||||
if (wasAttached)
|
||||
{
|
||||
holdable.AttachToWall();
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnMapLoaded()
|
||||
@@ -2740,11 +2765,7 @@ namespace Barotrauma
|
||||
|
||||
foreach (Character character in Character.CharacterList)
|
||||
{
|
||||
if (character.SelectedConstruction == this) character.SelectedConstruction = null;
|
||||
for (int i = 0; i < character.SelectedItems.Length; i++)
|
||||
{
|
||||
if (character.SelectedItems[i] == this) character.SelectedItems[i] = null;
|
||||
}
|
||||
if (character.SelectedConstruction == this) { character.SelectedConstruction = null; }
|
||||
}
|
||||
|
||||
Door door = GetComponent<Door>();
|
||||
|
||||
Reference in New Issue
Block a user