(ce8e185aa) Merge branch 'dev' of https://github.com/Regalis11/Barotrauma-development into dev
This commit is contained in:
@@ -221,29 +221,64 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
if (item.Condition <= RepairThreshold) return true; //For repairing
|
||||
|
||||
var idCard = character.Inventory.FindItemByIdentifier("idcard");
|
||||
hasValidIdCard = requiredItems.Any(ri => ri.Value.Any(r => r.MatchesItem(idCard)));
|
||||
Msg = requiredItems.None() || hasValidIdCard ? "ItemMsgOpen" : "ItemMsgForceOpenCrowbar";
|
||||
ParseMsg();
|
||||
if (addMessage)
|
||||
{
|
||||
msg = msg ?? (HasIntegratedButtons ? accessDeniedTxt : cannotOpenText);
|
||||
}
|
||||
|
||||
//this is a bit pointless atm because if canBePicked is false it won't allow you to do Pick() anyway, however it's still good for future-proofing.
|
||||
return requiredItems.Any() ? base.HasRequiredItems(character, addMessage, msg) : canBePicked;
|
||||
}
|
||||
|
||||
public override bool Pick(Character picker)
|
||||
{
|
||||
return item.Condition <= RepairThreshold ? true : base.Pick(picker);
|
||||
if (item.Condition <= RepairThreshold) { return true; }
|
||||
if (requiredItems.None()) { return false; }
|
||||
if (HasRequiredItems(picker, false) && hasValidIdCard) { return false; }
|
||||
return base.Pick(picker);
|
||||
}
|
||||
|
||||
public override bool OnPicked(Character picker)
|
||||
{
|
||||
if (item.Condition <= RepairThreshold) return true; //repairs
|
||||
if (requiredItems.Any() && !hasValidIdCard)
|
||||
{
|
||||
ForceOpen(ActionType.OnPicked);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void ForceOpen(ActionType actionType)
|
||||
{
|
||||
SetState(PredictedState == null ? !isOpen : !PredictedState.Value, false, true); //crowbar function
|
||||
#if CLIENT
|
||||
PlaySound(ActionType.OnPicked, item.WorldPosition, picker);
|
||||
PlaySound(actionType, item.WorldPosition, picker);
|
||||
#endif
|
||||
}
|
||||
|
||||
public override bool Select(Character character)
|
||||
{
|
||||
//can only be selected if the item is broken
|
||||
return item.Condition <= RepairThreshold;
|
||||
if (item.Condition <= RepairThreshold) return true; //repairs
|
||||
bool hasRequiredItems = HasRequiredItems(character, false);
|
||||
if (requiredItems.None() || hasRequiredItems && hasValidIdCard)
|
||||
{
|
||||
float originalPickingTime = PickingTime;
|
||||
PickingTime = 0;
|
||||
ForceOpen(ActionType.OnUse);
|
||||
PickingTime = originalPickingTime;
|
||||
}
|
||||
else if (hasRequiredItems)
|
||||
{
|
||||
#if CLIENT
|
||||
GUI.AddMessage(accessDeniedTxt, Color.Red);
|
||||
#endif
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void Update(float deltaTime, Camera cam)
|
||||
|
||||
@@ -34,6 +34,20 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
public override bool IsActive
|
||||
{
|
||||
get { return base.IsActive; }
|
||||
set
|
||||
{
|
||||
base.IsActive = value;
|
||||
if (!value)
|
||||
{
|
||||
nodes.Clear();
|
||||
charactersInRange.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Serialize(100.0f, true), Editable(MinValueFloat = 0.0f, MaxValueFloat = 5000.0f)]
|
||||
public float Range
|
||||
{
|
||||
@@ -126,14 +140,19 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
else
|
||||
{
|
||||
nodes.Clear();
|
||||
charactersInRange.Clear();
|
||||
IsActive = false;
|
||||
}
|
||||
|
||||
voltage = 0.0f;
|
||||
}
|
||||
|
||||
public override void UpdateBroken(float deltaTime, Camera cam)
|
||||
{
|
||||
base.UpdateBroken(deltaTime, cam);
|
||||
nodes.Clear();
|
||||
charactersInRange.Clear();
|
||||
}
|
||||
|
||||
private void Discharge()
|
||||
{
|
||||
ApplyStatusEffects(ActionType.OnUse, 1.0f);
|
||||
|
||||
@@ -58,13 +58,6 @@ namespace Barotrauma.Items.Components
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize(true, true)]
|
||||
public bool Aimable
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize(false, false)]
|
||||
public bool ControlPose
|
||||
{
|
||||
|
||||
@@ -11,6 +11,12 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
private float lastSentDeattachTimer;
|
||||
|
||||
private PhysicsBody trigger;
|
||||
|
||||
private Holdable holdable;
|
||||
|
||||
private float deattachTimer;
|
||||
|
||||
[Serialize(1.0f, false)]
|
||||
public float DeattachDuration
|
||||
{
|
||||
@@ -49,13 +55,7 @@ namespace Barotrauma.Items.Components
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
private PhysicsBody trigger;
|
||||
|
||||
private Holdable holdable;
|
||||
|
||||
private float deattachTimer;
|
||||
|
||||
|
||||
public LevelResource(Item item, XElement element) : base(item, element)
|
||||
{
|
||||
IsActive = true;
|
||||
|
||||
@@ -142,8 +142,6 @@ namespace Barotrauma.Items.Components
|
||||
pickTimer / requiredTime,
|
||||
Color.Red, Color.Green);
|
||||
#endif
|
||||
|
||||
picker.AnimController.UpdateUseItem(true, item.WorldPosition + new Vector2(0.0f, 100.0f) * ((pickTimer / 10.0f) % 0.1f));
|
||||
|
||||
picker.AnimController.UpdateUseItem(true, item.WorldPosition + new Vector2(0.0f, 100.0f) * ((pickTimer / 10.0f) % 0.1f));
|
||||
pickTimer += CoroutineManager.DeltaTime;
|
||||
|
||||
@@ -322,6 +322,7 @@ namespace Barotrauma.Items.Components
|
||||
// If the character is climbing, ignore the check, because we cannot aim while climbing.
|
||||
if (VectorExtensions.Angle(VectorExtensions.Forward(item.body.TransformedRotation), fromItemToLeak) < MathHelper.PiOver4)
|
||||
{
|
||||
character.SetInput(InputType.Shoot, false, true);
|
||||
Use(deltaTime, character);
|
||||
}
|
||||
else
|
||||
@@ -337,11 +338,11 @@ namespace Barotrauma.Items.Components
|
||||
sinTime = 0;
|
||||
if (!leak.FlowTargetHull.ConnectedGaps.Any(g => !g.IsRoomToRoom && g.Open > 0.0f))
|
||||
{
|
||||
character.Speak(TextManager.Get("DialogLeaksFixed").Replace("[roomname]", leak.FlowTargetHull.RoomName), null, 0.0f, "leaksfixed", 10.0f);
|
||||
character.Speak(TextManager.Get("DialogLeaksFixed").Replace("[roomname]", leak.FlowTargetHull.DisplayName), null, 0.0f, "leaksfixed", 10.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
character.Speak(TextManager.Get("DialogLeakFixed").Replace("[roomname]", leak.FlowTargetHull.RoomName), null, 0.0f, "leakfixed", 10.0f);
|
||||
character.Speak(TextManager.Get("DialogLeakFixed").Replace("[roomname]", leak.FlowTargetHull.DisplayName), null, 0.0f, "leakfixed", 10.0f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -190,7 +190,7 @@ namespace Barotrauma.Items.Components
|
||||
get { return name; }
|
||||
}
|
||||
|
||||
[Editable, Serialize("", true)]
|
||||
[Editable, Serialize("", true, translationTextTag: "ItemMsg")]
|
||||
public string Msg
|
||||
{
|
||||
get;
|
||||
@@ -538,7 +538,6 @@ namespace Barotrauma.Items.Components
|
||||
GameAnalyticsManager.AddErrorEventOnce("ItemComponent.DegreeOfSuccess:CharacterNull", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||
return 0.0f;
|
||||
}
|
||||
float average = skillSuccessSum / requiredSkills.Count;
|
||||
|
||||
float skillSuccessSum = 0.0f;
|
||||
for (int i = 0; i < requiredSkills.Count; i++)
|
||||
@@ -555,7 +554,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public virtual void FlipY(bool relativeToSub) { }
|
||||
|
||||
public bool HasRequiredContainedItems(bool addMessage)
|
||||
public bool HasRequiredContainedItems(bool addMessage, string msg = null)
|
||||
{
|
||||
if (!requiredItems.ContainsKey(RelatedItem.RelationType.Contained)) return true;
|
||||
if (item.OwnInventory == null) return false;
|
||||
@@ -582,33 +581,52 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
if (!requiredItems.Any()) return true;
|
||||
if (character.Inventory == null) return false;
|
||||
|
||||
bool hasRequiredItems = false;
|
||||
bool canContinue = true;
|
||||
if (requiredItems.ContainsKey(RelatedItem.RelationType.Equipped))
|
||||
{
|
||||
foreach (RelatedItem ri in requiredItems[RelatedItem.RelationType.Equipped])
|
||||
{
|
||||
if (character.SelectedItems.FirstOrDefault(it => it != null && it.Condition > 0.0f && ri.MatchesItem(it)) == null)
|
||||
canContinue = CheckItems(ri, character.SelectedItems);
|
||||
if (!canContinue) { break; }
|
||||
}
|
||||
}
|
||||
if (canContinue)
|
||||
{
|
||||
if (requiredItems.ContainsKey(RelatedItem.RelationType.Picked))
|
||||
{
|
||||
foreach (RelatedItem ri in requiredItems[RelatedItem.RelationType.Picked])
|
||||
{
|
||||
#if CLIENT
|
||||
if (addMessage && !string.IsNullOrEmpty(ri.Msg)) GUI.AddMessage(ri.Msg, Color.Red);
|
||||
#endif
|
||||
return false;
|
||||
if (!CheckItems(ri, character.Inventory.Items)) { break; }
|
||||
}
|
||||
}
|
||||
}
|
||||
if (requiredItems.ContainsKey(RelatedItem.RelationType.Picked))
|
||||
{
|
||||
foreach (RelatedItem ri in requiredItems[RelatedItem.RelationType.Picked])
|
||||
{
|
||||
if (character.Inventory.Items.FirstOrDefault(it => it != null && it.Condition > 0.0f && ri.MatchesItem(it)) == null)
|
||||
{
|
||||
|
||||
#if CLIENT
|
||||
if (!hasRequiredItems && addMessage && !string.IsNullOrEmpty(msg))
|
||||
{
|
||||
GUI.AddMessage(msg, Color.Red);
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
return hasRequiredItems;
|
||||
|
||||
bool CheckItems(RelatedItem relatedItem, IEnumerable<Item> itemList)
|
||||
{
|
||||
bool Predicate(Item it) => it != null && it.Condition > 0.0f && relatedItem.MatchesItem(it);
|
||||
bool shouldBreak = false;
|
||||
if (relatedItem.IsOptional)
|
||||
{
|
||||
if (!hasRequiredItems)
|
||||
{
|
||||
hasRequiredItems = itemList.Any(Predicate);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hasRequiredItems = itemList.Any(Predicate);
|
||||
if (!hasRequiredItems)
|
||||
{
|
||||
shouldBreak = true;
|
||||
}
|
||||
}
|
||||
if (!hasRequiredItems)
|
||||
@@ -620,8 +638,6 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
return !shouldBreak;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void ApplyStatusEffects(ActionType type, float deltaTime, Character character = null, Limb targetLimb = null, Character user = null)
|
||||
@@ -766,6 +782,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
newRequiredItem.statusEffects = prevRequiredItem.statusEffects;
|
||||
newRequiredItem.Msg = prevRequiredItem.Msg;
|
||||
newRequiredItem.IsOptional = prevRequiredItem.IsOptional;
|
||||
}
|
||||
|
||||
if (!requiredItems.ContainsKey(newRequiredItem.Type))
|
||||
|
||||
@@ -343,5 +343,7 @@ namespace Barotrauma.Items.Components
|
||||
limbPositions[i] = new LimbPos(limbPositions[i].limbType, flippedPos);
|
||||
}
|
||||
}
|
||||
|
||||
partial void HideHUDs(bool value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,11 +8,19 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
partial class CustomInterface : ItemComponent, IClientSerializable, IServerSerializable
|
||||
{
|
||||
class CustomInterfaceElement
|
||||
class CustomInterfaceElement : ISerializableEntity
|
||||
{
|
||||
public bool ContinuousSignal;
|
||||
public bool State;
|
||||
public string Label, Connection, Signal;
|
||||
public string Connection;
|
||||
[Serialize("", false, translationTextTag = "Label.")]
|
||||
public string Label { get; set; }
|
||||
[Serialize("1", false)]
|
||||
public string Signal { get; set; }
|
||||
|
||||
public string Name => "CustomInterfaceElement";
|
||||
|
||||
public Dictionary<string, SerializableProperty> SerializableProperties { get; set; }
|
||||
|
||||
public List<StatusEffect> StatusEffects = new List<StatusEffect>();
|
||||
|
||||
@@ -33,7 +41,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
|
||||
private string[] labels;
|
||||
[Serialize("", true), Editable()]
|
||||
[Serialize("", true)]
|
||||
public string Labels
|
||||
{
|
||||
get { return string.Join(",", labels); }
|
||||
@@ -48,7 +56,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
private string[] signals;
|
||||
[Serialize("", true), Editable()]
|
||||
[Serialize("", true)]
|
||||
public string Signals
|
||||
{
|
||||
//use semicolon as a separator because comma may be needed in the signals (for color or vector values for example)
|
||||
|
||||
@@ -5,6 +5,7 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using Barotrauma.Items.Components;
|
||||
using Barotrauma.Extensions;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -66,6 +67,8 @@ namespace Barotrauma
|
||||
|
||||
public LightComponent LightComponent { get; set; }
|
||||
|
||||
public int Variant { get; set; }
|
||||
|
||||
private Gender _gender;
|
||||
/// <summary>
|
||||
/// None = Any/Not Defined -> no effect.
|
||||
@@ -112,30 +115,65 @@ namespace Barotrauma
|
||||
/// <summary>
|
||||
/// Note: this constructor cannot initialize automatically, because the gender is unknown at this point. We only know it when the item is equipped.
|
||||
/// </summary>
|
||||
public WearableSprite(XElement subElement, Wearable wearable)
|
||||
public WearableSprite(XElement subElement, Wearable wearable, int variant = 0)
|
||||
{
|
||||
Type = WearableType.Item;
|
||||
WearableComponent = wearable;
|
||||
Variant = Math.Max(variant, 0);
|
||||
SpritePath = ParseSpritePath(subElement.GetAttributeString("texture", string.Empty));
|
||||
SourceElement = subElement;
|
||||
}
|
||||
|
||||
private string ParseSpritePath(string texturePath) => texturePath.Contains("/") ? texturePath : $"{Path.GetDirectoryName(WearableComponent.Item.Prefab.ConfigFile)}/{texturePath}";
|
||||
|
||||
public void RefreshPath()
|
||||
{
|
||||
if (Variant > 0)
|
||||
{
|
||||
// Restore the tag so that we can parse it again.
|
||||
ReplaceNumbersWith("[VARIANT]");
|
||||
}
|
||||
ParsePath(true);
|
||||
}
|
||||
|
||||
private void ReplaceNumbersWith(string replacement)
|
||||
{
|
||||
var fileName = Path.GetFileName(SpritePath);
|
||||
var path = Path.GetDirectoryName(SpritePath);
|
||||
fileName = fileName.Replace(replacement, c => char.IsNumber(c));
|
||||
SpritePath = Path.Combine(path, fileName);
|
||||
}
|
||||
|
||||
private void ParsePath(bool parseSpritePath)
|
||||
{
|
||||
if (_gender != Gender.None)
|
||||
{
|
||||
SpritePath = SpritePath.Replace("[GENDER]", (_gender == Gender.Female) ? "female" : "male");
|
||||
}
|
||||
SpritePath = SpritePath.Replace("[VARIANT]", Variant.ToString());
|
||||
if (!File.Exists(SpritePath))
|
||||
{
|
||||
// If the variant does not exist, parse the path so that it uses first variant.
|
||||
Variant = 1;
|
||||
ReplaceNumbersWith(Variant.ToString());
|
||||
}
|
||||
if (parseSpritePath)
|
||||
{
|
||||
Sprite.ParseTexturePath(file: SpritePath);
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsInitialized { get; private set; }
|
||||
public void Init(Gender gender = Gender.None)
|
||||
{
|
||||
if (IsInitialized) { return; }
|
||||
_gender = SpritePath.Contains("[GENDER]") ? gender : Gender.None;
|
||||
if (_gender != Gender.None)
|
||||
{
|
||||
SpritePath = SpritePath.Replace("[GENDER]", (_gender == Gender.Female) ? "female" : "male");
|
||||
}
|
||||
ParsePath(false);
|
||||
if (Sprite != null)
|
||||
{
|
||||
Sprite.Remove();
|
||||
}
|
||||
Sprite = new Sprite(SourceElement, "", SpritePath);
|
||||
Sprite = new Sprite(SourceElement, file: SpritePath);
|
||||
Limb = (LimbType)Enum.Parse(typeof(LimbType), SourceElement.GetAttributeString("limb", "Head"), true);
|
||||
HideLimb = SourceElement.GetAttributeBool("hidelimb", false);
|
||||
HideOtherWearables = SourceElement.GetAttributeBool("hideotherwearables", false);
|
||||
@@ -170,7 +208,7 @@ namespace Barotrauma.Items.Components
|
||||
get { return damageModifiers; }
|
||||
}
|
||||
|
||||
public Wearable (Item item, XElement element) : base(item, element)
|
||||
public Wearable(Item item, XElement element) : base(item, element)
|
||||
{
|
||||
this.item = item;
|
||||
|
||||
@@ -197,7 +235,7 @@ namespace Barotrauma.Items.Components
|
||||
limbType[i] = (LimbType)Enum.Parse(typeof(LimbType),
|
||||
subElement.GetAttributeString("limb", "Head"), true);
|
||||
|
||||
wearableSprites[i] = new WearableSprite(subElement, this);
|
||||
wearableSprites[i] = new WearableSprite(subElement, this, variant);
|
||||
|
||||
foreach (XElement lightElement in subElement.Elements())
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user