v0.12.0.2

This commit is contained in:
Joonas Rikkonen
2021-02-10 17:08:21 +02:00
parent 5c80a59bdd
commit 694cdfee7b
353 changed files with 12897 additions and 5028 deletions
@@ -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>();