(7788ec72a) Test issuing orders automatically.

This commit is contained in:
Joonas Rikkonen
2019-05-16 05:03:49 +03:00
parent d00e2975ba
commit 60f52375e6
202 changed files with 2714 additions and 5825 deletions
@@ -176,9 +176,6 @@ namespace Barotrauma
{
if (allowedSlot.HasFlag(SlotTypes[i]) && Items[i] != null && Items[i] != item)
{
#if CLIENT
if (PersonalSlots.HasFlag(SlotTypes[i])) { hidePersonalSlots = false; }
#endif
if (!Items[i].AllowedSlots.Contains(InvSlotType.Any) || !TryPutItem(Items[i], character, new List<InvSlotType> { InvSlotType.Any }, true))
{
free = false;
@@ -198,9 +195,6 @@ namespace Barotrauma
{
if (allowedSlot.HasFlag(SlotTypes[i]) && Items[i] == null)
{
#if CLIENT
if (PersonalSlots.HasFlag(SlotTypes[i])) { hidePersonalSlots = false; }
#endif
bool removeFromOtherSlots = item.ParentInventory != this;
if (placedInSlot == -1 && inWrongSlot)
{
@@ -254,9 +248,7 @@ namespace Barotrauma
GameAnalyticsManager.AddErrorEventOnce("CharacterInventory.TryPutItem:IndexOutOfRange", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
return false;
}
#if CLIENT
if (PersonalSlots.HasFlag(SlotTypes[index])) { hidePersonalSlots = false; }
#endif
//there's already an item in the slot
if (Items[index] != null)
{
@@ -281,9 +273,7 @@ namespace Barotrauma
foreach (InvSlotType allowedSlot in allowedSlots)
{
if (!allowedSlot.HasFlag(SlotTypes[index])) continue;
#if CLIENT
if (PersonalSlots.HasFlag(allowedSlot)) { hidePersonalSlots = false; }
#endif
for (int i = 0; i < capacity; i++)
{
if (allowedSlot.HasFlag(SlotTypes[i]) && Items[i] != null && Items[i] != item)
@@ -219,29 +219,31 @@ namespace Barotrauma.Items.Components
private bool hasValidIdCard;
public override bool HasRequiredItems(Character character, bool addMessage, string msg = null)
{
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";
Msg = hasValidIdCard ? "ItemMsgOpen" : "ItemMsgForceOpenCrowbar";
ParseMsg();
if (addMessage)
{
msg = msg ?? (HasIntegratedButtons ? accessDeniedTxt : cannotOpenText);
msg = msg ?? (requiredItems.Any(ri => ri.Value.Any(r => r.Identifiers.Contains("idcard"))) ? accessDeniedTxt : cannotOpenText);
}
if (isBroken) { return true; }
return base.HasRequiredItems(character, addMessage, msg);
//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)
{
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; }
if (item.Condition <= RepairThreshold) return true; //repairs
if (requiredItems.Any() && !hasValidIdCard)
{
ForceOpen(ActionType.OnPicked);
@@ -259,24 +261,23 @@ namespace Barotrauma.Items.Components
public override bool Select(Character character)
{
if (!isBroken)
//can only be selected if the item is broken
if (item.Condition <= RepairThreshold) return true; //repairs
bool hasRequiredItems = HasRequiredItems(character, false);
if (requiredItems.None() || hasRequiredItems && hasValidIdCard)
{
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
}
float originalPickingTime = PickingTime;
PickingTime = 0;
ForceOpen(ActionType.OnUse);
PickingTime = originalPickingTime;
}
return item.Condition <= RepairThreshold;
else if (hasRequiredItems)
{
#if CLIENT
GUI.AddMessage(accessDeniedTxt, Color.Red);
#endif
}
return false;
}
public override void Update(float deltaTime, Camera cam)
@@ -122,12 +122,10 @@ namespace Barotrauma.Items.Components
foreach (Item subItem in containedSubItems)
{
projectile = subItem.GetComponent<Projectile>();
//apply OnUse statuseffects to the container in case it has to react to it somehow
//(play a sound, spawn more projectiles, reduce condition...)
if (subItem.Condition > 0.0f)
{
subItem.GetComponent<ItemContainer>()?.Item.ApplyStatusEffects(ActionType.OnUse, deltaTime);
}
subItem.GetComponent<ItemContainer>()?.Item.ApplyStatusEffects(ActionType.OnUse, deltaTime);
if (projectile != null) break;
}
}
@@ -293,35 +293,10 @@ namespace Barotrauma.Items.Components
//steer closer if almost in range
if (dist > Range)
{
Vector2 standPos = new Vector2(Math.Sign(-fromItemToLeak.X), Math.Sign(-fromItemToLeak.Y)) / 2;
if (!character.AnimController.InWater)
{
if (leak.IsHorizontal)
{
standPos.X *= 2;
standPos.Y = 0;
}
else
{
standPos.X = 0;
}
}
if (character.AIController.SteeringManager is IndoorsSteeringManager indoorSteering)
{
if (indoorSteering.CurrentPath != null && !indoorSteering.IsPathDirty && indoorSteering.CurrentPath.Unreachable)
{
Vector2 dir = Vector2.Normalize(standPos - character.WorldPosition);
character.AIController.SteeringManager.SteeringManual(deltaTime, dir / 2);
}
else
{
character.AIController.SteeringManager.SteeringSeek(standPos);
}
}
else
{
character.AIController.SteeringManager.SteeringSeek(standPos);
}
Vector2 standPos = leak.IsHorizontal ? new Vector2(Math.Sign(-fromItemToLeak.X), 0.0f) : new Vector2(0.0f, Math.Sign(-fromItemToLeak.Y) * 0.5f);
standPos = leak.WorldPosition + standPos * Range;
Vector2 dir = Vector2.Normalize(standPos - character.WorldPosition);
character.AIController.SteeringManager.SteeringManual(deltaTime, dir / 2);
}
else
{
@@ -330,29 +305,30 @@ namespace Barotrauma.Items.Components
// Too close -> steer away
character.AIController.SteeringManager.SteeringManual(deltaTime, Vector2.Normalize(character.SimPosition - leak.SimPosition) / 2);
}
else if (dist <= Range)
{
// In range
character.AIController.SteeringManager.Reset();
}
else
{
return false;
character.AIController.SteeringManager.Reset();
}
}
sinTime += deltaTime;
character.CursorPosition = leak.Position + VectorExtensions.Forward(Item.body.TransformedRotation + (float)Math.Sin(sinTime), dist);
if (item.RequireAimToUse)
{
character.SetInput(InputType.Aim, false, true);
}
// Press the trigger only when the tool is approximately facing the target.
var angle = VectorExtensions.Angle(VectorExtensions.Forward(item.body.TransformedRotation), fromItemToLeak);
if (angle < MathHelper.PiOver4)
// 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
{
sinTime -= deltaTime * 2;
}
bool leakFixed = (leak.Open <= 0.0f || leak.Removed) &&
(leak.ConnectedWall == null || leak.ConnectedWall.Sections.Average(s => s.damage) < 1);
@@ -362,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.DisplayName), null, 0.0f, "leaksfixed", 10.0f);
character.Speak(TextManager.Get("DialogLeaksFixed").Replace("[roomname]", leak.FlowTargetHull.RoomName), null, 0.0f, "leaksfixed", 10.0f);
}
else
{
character.Speak(TextManager.Get("DialogLeakFixed").Replace("[roomname]", leak.FlowTargetHull.DisplayName), null, 0.0f, "leakfixed", 10.0f);
character.Speak(TextManager.Get("DialogLeakFixed").Replace("[roomname]", leak.FlowTargetHull.RoomName), null, 0.0f, "leakfixed", 10.0f);
}
}
@@ -190,7 +190,7 @@ namespace Barotrauma.Items.Components
get { return name; }
}
[Editable, Serialize("", true, translationTextTag: "ItemMsg")]
[Editable, Serialize("", true)]
public string Msg
{
get;
@@ -580,8 +580,8 @@ namespace Barotrauma.Items.Components
public virtual bool HasRequiredItems(Character character, bool addMessage, string msg = null)
{
if (!requiredItems.Any()) { return true; }
if (character.Inventory == null) { return false; }
if (!requiredItems.Any()) return true;
if (character.Inventory == null) return false;
bool hasRequiredItems = false;
bool canContinue = true;
if (requiredItems.ContainsKey(RelatedItem.RelationType.Equipped))
@@ -615,15 +615,7 @@ namespace Barotrauma.Items.Components
{
bool Predicate(Item it) => it != null && it.Condition > 0.0f && relatedItem.MatchesItem(it);
bool shouldBreak = false;
bool inEditor = false;
#if CLIENT
inEditor = Screen.Selected == GameMain.SubEditorScreen;
#endif
if (relatedItem.IgnoreInEditor && inEditor)
{
hasRequiredItems = true;
}
else if (relatedItem.IsOptional)
if (relatedItem.IsOptional)
{
if (!hasRequiredItems)
{
@@ -792,7 +784,6 @@ namespace Barotrauma.Items.Components
newRequiredItem.statusEffects = prevRequiredItem.statusEffects;
newRequiredItem.Msg = prevRequiredItem.Msg;
newRequiredItem.IsOptional = prevRequiredItem.IsOptional;
newRequiredItem.IgnoreInEditor = prevRequiredItem.IgnoreInEditor;
}
if (!requiredItems.ContainsKey(newRequiredItem.Type))
@@ -810,7 +801,10 @@ namespace Barotrauma.Items.Components
string msg = TextManager.Get(Msg, true);
if (msg != null)
{
msg = TextManager.ParseInputTypes(msg);
foreach (InputType inputType in Enum.GetValues(typeof(InputType)))
{
msg = msg.Replace("[" + inputType.ToString().ToLowerInvariant() + "]", GameMain.Config.KeyBind(inputType).ToString());
}
DisplayMsg = msg;
}
else
@@ -13,11 +13,6 @@ namespace Barotrauma.Items.Components
private ItemContainer inputContainer, outputContainer;
public ItemContainer InputContainer
{
get { return inputContainer; }
}
public ItemContainer OutputContainer
{
get { return outputContainer; }
@@ -76,10 +71,8 @@ namespace Barotrauma.Items.Components
var targetItem = inputContainer.Inventory.Items.LastOrDefault(i => i != null);
if (targetItem == null) { return; }
float deconstructTime = targetItem.Prefab.DeconstructItems.Any() ? targetItem.Prefab.DeconstructTime : 1.0f;
progressState = Math.Min(progressTimer / deconstructTime, 1.0f);
if (progressTimer > deconstructTime)
progressState = Math.Min(progressTimer / targetItem.Prefab.DeconstructTime, 1.0f);
if (progressTimer > targetItem.Prefab.DeconstructTime)
{
foreach (DeconstructItem deconstructProduct in targetItem.Prefab.DeconstructItems)
{
@@ -107,24 +100,10 @@ namespace Barotrauma.Items.Components
}
}
if (targetItem.Prefab.DeconstructItems.Any())
{
inputContainer.Inventory.RemoveItem(targetItem);
Entity.Spawner.AddToRemoveQueue(targetItem);
MoveInputQueue();
PutItemsToLinkedContainer();
}
else
{
if (outputContainer.Inventory.Items.All(i => i != null))
{
targetItem.Drop(dropper: null);
}
else
{
outputContainer.Inventory.TryPutItem(targetItem, user: null, createNetworkEvent: true);
}
}
inputContainer.Inventory.RemoveItem(targetItem);
Entity.Spawner.AddToRemoveQueue(targetItem);
MoveInputQueue();
PutItemsToLinkedContainer();
if (inputContainer.Inventory.Items.Any(i => i != null))
{
@@ -23,16 +23,6 @@ namespace Barotrauma.Items.Components
private ItemContainer inputContainer, outputContainer;
public ItemContainer InputContainer
{
get { return inputContainer; }
}
public ItemContainer OutputContainer
{
get { return outputContainer; }
}
private float progressState;
public Fabricator(Item item, XElement element)
@@ -108,23 +98,7 @@ namespace Barotrauma.Items.Components
{
return (picker != null);
}
public void RemoveFabricationRecipes(List<string> allowedIdentifiers)
{
for (int i = 0; i < fabricationRecipes.Count; i++)
{
if (!allowedIdentifiers.Contains(fabricationRecipes[i].TargetItem.Identifier))
{
fabricationRecipes.RemoveAt(i);
i--;
}
}
CreateRecipes();
}
partial void CreateRecipes();
private void StartFabricating(FabricationRecipe selectedItem, Character user)
{
if (selectedItem == null) return;
@@ -473,8 +473,6 @@ namespace Barotrauma.Items.Components
{
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) { return false; }
IsActive = true;
float degreeOfSuccess = DegreeOfSuccess(character);
//characters with insufficient skill levels don't refuel the reactor
@@ -47,9 +47,8 @@ namespace Barotrauma.Items.Components
//was the last ping sent with directional pinging
private bool isLastPingDirectional;
private Sprite pingCircle, directionalPingCircle, screenOverlay, screenBackground;
private Sprite sonarBlip;
private Sprite lineSprite;
private readonly Sprite pingCircle, directionalPingCircle, screenOverlay, screenBackground;
private readonly Sprite sonarBlip;
private bool aiPingCheckPending;
@@ -86,7 +85,7 @@ namespace Barotrauma.Items.Components
{
get { return zoom; }
}
public override bool IsActive
{
get
@@ -112,7 +111,29 @@ namespace Barotrauma.Items.Components
: base(item, element)
{
connectedTransducers = new List<ConnectedTransducer>();
foreach (XElement subElement in element.Elements())
{
switch (subElement.Name.ToString().ToLowerInvariant())
{
case "pingcircle":
pingCircle = new Sprite(subElement);
break;
case "directionalpingcircle":
directionalPingCircle = new Sprite(subElement);
break;
case "screenoverlay":
screenOverlay = new Sprite(subElement);
break;
case "screenbackground":
screenBackground = new Sprite(subElement);
break;
case "blip":
sonarBlip = new Sprite(subElement);
break;
}
}
IsActive = false;
InitProjSpecific(element);
}
@@ -184,7 +205,6 @@ namespace Barotrauma.Items.Components
directionalPingCircle?.Remove();
screenOverlay?.Remove();
screenBackground?.Remove();
lineSprite?.Remove();
}
public override bool AIOperate(float deltaTime, Character character, AIObjectiveOperateItem objective)
@@ -239,24 +259,15 @@ namespace Barotrauma.Items.Components
int clockDir = (int)Math.Round((angle / MathHelper.TwoPi) * 12);
if (clockDir == 0) clockDir = 12;
return TextManager.Get("roomname.subdiroclock").Replace("[dir]", clockDir.ToString());
return TextManager.Get("SubDirOClock").Replace("[dir]", clockDir.ToString());
}
private Vector2 GetTransducerPos()
private Vector2 GetTransducerCenter()
{
if (!UseTransducers || connectedTransducers.Count == 0)
{
//use the position of the sub if the item is static (no body) and inside a sub
return item.Submarine != null && item.body == null ? item.Submarine.WorldPosition : item.WorldPosition;
}
if (!UseTransducers || connectedTransducers.Count == 0) return Vector2.Zero;
Vector2 transducerPosSum = Vector2.Zero;
foreach (ConnectedTransducer transducer in connectedTransducers)
{
if (transducer.Transducer.Item.Submarine != null)
{
return transducer.Transducer.Item.Submarine.WorldPosition;
}
transducerPosSum += transducer.Transducer.Item.WorldPosition;
}
return transducerPosSum / connectedTransducers.Count;
@@ -172,6 +172,19 @@ namespace Barotrauma.Items.Components
return true;
}
public override void OnItemLoaded()
{
sonar = item.GetComponent<Sonar>();
}
public override bool Select(Character character)
{
if (!CanBeSelected) return false;
user = character;
return true;
}
public override void Update(float deltaTime, Camera cam)
{
networkUpdateTimer -= deltaTime;
@@ -474,9 +487,7 @@ namespace Barotrauma.Items.Components
if (!posToMaintain.HasValue)
{
unsentChanges = true;
posToMaintain = controlledSub != null ?
controlledSub.WorldPosition :
item.Submarine == null ? item.WorldPosition : item.Submarine.WorldPosition;
posToMaintain = controlledSub == null ? item.WorldPosition : controlledSub.WorldPosition;
}
if (!AutoPilot || !MaintainPos) unsentChanges = true;
@@ -201,7 +201,7 @@ namespace Barotrauma.Items.Components
if (sparkSounds.Count > 0)
{
var sparkSound = sparkSounds[Rand.Int(sparkSounds.Count)];
SoundPlayer.PlaySound(sparkSound.Sound, pt.item.WorldPosition, sparkSound.Volume, sparkSound.Range, pt.item.CurrentHull);
SoundPlayer.PlaySound(sparkSound.Sound, sparkSound.Volume, sparkSound.Range, pt.item.WorldPosition, pt.item.CurrentHull);
}
Vector2 baseVel = Rand.Vector(300.0f);
@@ -103,7 +103,7 @@ namespace Barotrauma.Items.Components
ApplyStatusEffects(ActionType.OnActive, deltaTime, null);
if (!powerOnSoundPlayed && powerOnSound != null)
{
SoundPlayer.PlaySound(powerOnSound.Sound, item.WorldPosition, powerOnSound.Volume, powerOnSound.Range, item.CurrentHull);
SoundPlayer.PlaySound(powerOnSound.Sound, powerOnSound.Volume, powerOnSound.Range, item.WorldPosition, item.CurrentHull);
powerOnSoundPlayed = true;
}
}
@@ -241,12 +241,5 @@ namespace Barotrauma.Items.Components
{
character.AnimController.UpdateUseItem(false, item.WorldPosition + new Vector2(0.0f, 100.0f) * ((item.Condition / item.MaxCondition) % 0.1f));
}
public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0, float signalStrength = 1)
{
//do nothing
//Repairables should always stay active, so we don't want to use the default behavior
//where set_active/set_state signals can disable the component
}
}
}
@@ -8,19 +8,11 @@ namespace Barotrauma.Items.Components
{
partial class CustomInterface : ItemComponent, IClientSerializable, IServerSerializable
{
class CustomInterfaceElement : ISerializableEntity
class CustomInterfaceElement
{
public bool ContinuousSignal;
public bool State;
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 string Label, Connection, Signal;
public List<StatusEffect> StatusEffects = new List<StatusEffect>();
@@ -41,7 +33,7 @@ namespace Barotrauma.Items.Components
}
private string[] labels;
[Serialize("", true)]
[Serialize("", true), Editable()]
public string Labels
{
get { return string.Join(",", labels); }
@@ -56,7 +48,7 @@ namespace Barotrauma.Items.Components
}
}
private string[] signals;
[Serialize("", true)]
[Serialize("", true), Editable()]
public string Signals
{
//use semicolon as a separator because comma may be needed in the signals (for color or vector values for example)
@@ -125,7 +117,7 @@ namespace Barotrauma.Items.Components
for (int i = 0; i < labels.Length; i++)
{
labels[i] = i < newLabels.Length ? newLabels[i] : customInterfaceElementList[i].Label;
customInterfaceElementList[i].Label = TextManager.Get(labels[i], returnNull: true) ?? labels[i];
customInterfaceElementList[i].Label = labels[i];
}
UpdateLabelsProjSpecific();
}
@@ -170,12 +162,5 @@ namespace Barotrauma.Items.Components
}
}
}
public override XElement Save(XElement parentElement)
{
labels = customInterfaceElementList.Select(ci => ci.Label).ToArray();
signals = customInterfaceElementList.Select(ci => ci.Signal).ToArray();
return base.Save(parentElement);
}
}
}
@@ -219,7 +219,7 @@ namespace Barotrauma.Items.Components
if (voltage > 0.1f && sparkSounds.Count > 0)
{
var sparkSound = sparkSounds[Rand.Int(sparkSounds.Count)];
SoundPlayer.PlaySound(sparkSound.Sound, item.WorldPosition, sparkSound.Volume, sparkSound.Range, item.CurrentHull);
SoundPlayer.PlaySound(sparkSound.Sound, sparkSound.Volume, sparkSound.Range, item.WorldPosition, item.CurrentHull);
}
#endif
lightBrightness = 0.0f;
@@ -5,7 +5,6 @@ using System.IO;
using System.Linq;
using System.Xml.Linq;
using Barotrauma.Items.Components;
using Barotrauma.Extensions;
namespace Barotrauma
{
@@ -67,8 +66,6 @@ namespace Barotrauma
public LightComponent LightComponent { get; set; }
public int Variant { get; set; }
private Gender _gender;
/// <summary>
/// None = Any/Not Defined -> no effect.
@@ -115,65 +112,30 @@ 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, int variant = 0)
public WearableSprite(XElement subElement, Wearable wearable)
{
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;
ParsePath(false);
if (_gender != Gender.None)
{
SpritePath = SpritePath.Replace("[GENDER]", (_gender == Gender.Female) ? "female" : "male");
}
if (Sprite != null)
{
Sprite.Remove();
}
Sprite = new Sprite(SourceElement, file: SpritePath);
Sprite = new Sprite(SourceElement, "", SpritePath);
Limb = (LimbType)Enum.Parse(typeof(LimbType), SourceElement.GetAttributeString("limb", "Head"), true);
HideLimb = SourceElement.GetAttributeBool("hidelimb", false);
HideOtherWearables = SourceElement.GetAttributeBool("hideotherwearables", false);
@@ -208,7 +170,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;
@@ -235,7 +197,7 @@ namespace Barotrauma.Items.Components
limbType[i] = (LimbType)Enum.Parse(typeof(LimbType),
subElement.GetAttributeString("limb", "Head"), true);
wearableSprites[i] = new WearableSprite(subElement, this, variant);
wearableSprites[i] = new WearableSprite(subElement, this);
foreach (XElement lightElement in subElement.Elements())
{
@@ -206,16 +206,6 @@ namespace Barotrauma
return true;
}
public bool IsFull()
{
for (int i = 0; i < capacity; i++)
{
if (Items[i] == null) return false;
}
return true;
}
protected bool TrySwapping(int index, Item item, Character user, bool createNetworkEvent)
{
if (item?.ParentInventory == null || Items[index] == null) return false;
@@ -928,9 +928,14 @@ namespace Barotrauma
public void ApplyStatusEffects(ActionType type, float deltaTime, Character character = null, Limb limb = null, bool isNetworkEvent = false)
{
if (!hasStatusEffectsOfType[(int)type]) { return; }
foreach (StatusEffect effect in statusEffectLists[type])
if (statusEffectLists == null) return;
if (!statusEffectLists.TryGetValue(type, out List<StatusEffect> statusEffects)) return;
bool broken = condition <= 0.0f;
foreach (StatusEffect effect in statusEffects)
{
if (broken && effect.type != ActionType.OnBroken) continue;
ApplyStatusEffect(effect, type, deltaTime, character, limb, isNetworkEvent, false);
}
}
@@ -1047,8 +1052,6 @@ namespace Barotrauma
aiTarget.SoundRange -= deltaTime * 1000.0f;
}
bool broken = condition <= 0.0f;
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsServer)
{
sendConditionUpdateTimer -= deltaTime;
@@ -1124,10 +1127,7 @@ namespace Barotrauma
container = container.Container;
}
}
if (!broken)
{
ApplyStatusEffects(!waterProof && inWater ? ActionType.InWater : ActionType.NotInWater, deltaTime);
}
ApplyStatusEffects(!waterProof && inWater ? ActionType.InWater : ActionType.NotInWater, deltaTime);
if (body == null || !body.Enabled || !inWater || ParentInventory != null || Removed) { return; }
@@ -1149,10 +1149,6 @@ namespace Barotrauma
{
body.SetTransform(body.SimPosition - Submarine.SimPosition, body.Rotation);
}
else if (Submarine != null && prevSub != null && Submarine != prevSub)
{
body.SetTransform(body.SimPosition + prevSub.SimPosition - Submarine.SimPosition, body.Rotation);
}
Vector2 displayPos = ConvertUnits.ToDisplayUnits(body.SimPosition);
rect.X = (int)(displayPos.X - rect.Width / 2.0f);
@@ -1210,7 +1206,7 @@ namespace Barotrauma
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) { return true; }
if (ImpactTolerance > 0.0f && condition > 0.0f && impact > ImpactTolerance)
if (ImpactTolerance > 0.0f && impact > ImpactTolerance)
{
ApplyStatusEffects(ActionType.OnImpact, 1.0f);
#if SERVER
@@ -1269,7 +1265,7 @@ namespace Barotrauma
if (recursive)
{
HashSet<Connection> alreadySearched = new HashSet<Connection>();
List<Item> alreadySearched = new List<Item>() { this };
GetConnectedComponentsRecursive(alreadySearched, connectedComponents);
return connectedComponents;
@@ -1291,7 +1287,7 @@ namespace Barotrauma
return connectedComponents;
}
private void GetConnectedComponentsRecursive<T>(HashSet<Connection> alreadySearched, List<T> connectedComponents) where T : ItemComponent
private void GetConnectedComponentsRecursive<T>(List<Item> alreadySearched, List<T> connectedComponents) where T : ItemComponent
{
ConnectionPanel connectionPanel = GetComponent<ConnectionPanel>();
if (connectionPanel == null) { return; }
@@ -1315,35 +1311,28 @@ namespace Barotrauma
}
}
recipient.Item.GetConnectedComponentsRecursive<T>(alreadySearched, connectedComponents);
}
}
}
public List<T> GetConnectedComponentsRecursive<T>(Connection c) where T : ItemComponent
{
List<T> connectedComponents = new List<T>();
HashSet<Connection> alreadySearched = new HashSet<Connection>();
List<T> connectedComponents = new List<T>();
List<Item> alreadySearched = new List<Item>() { this };
GetConnectedComponentsRecursive(c, alreadySearched, connectedComponents);
return connectedComponents;
}
private static readonly Pair<string, string>[] connectionPairs = new Pair<string, string>[]
{
new Pair<string, string>("power_in", "power_out"),
new Pair<string, string>("signal_in1", "signal_out1"),
new Pair<string, string>("signal_in2", "signal_out2"),
new Pair<string, string>("signal_in3", "signal_out3"),
new Pair<string, string>("signal_in4", "signal_out4"),
new Pair<string, string>("signal_in", "signal_out"),
new Pair<string, string>("signal_in1", "signal_out"),
new Pair<string, string>("signal_in2", "signal_out")
};
private void GetConnectedComponentsRecursive<T>(Connection c, HashSet<Connection> alreadySearched, List<T> connectedComponents) where T : ItemComponent
private void GetConnectedComponentsRecursive<T>(Connection c, List<Item> alreadySearched, List<T> connectedComponents) where T : ItemComponent
{
alreadySearched.Add(c);
alreadySearched.Add(this);
var recipients = c.Recipients;
foreach (Connection recipient in recipients)
{
if (alreadySearched.Contains(recipient)) { continue; }
if (alreadySearched.Contains(recipient.Item)) continue;
var component = recipient.Item.GetComponent<T>();
if (component != null)
@@ -1352,29 +1341,7 @@ namespace Barotrauma
}
recipient.Item.GetConnectedComponentsRecursive(recipient, alreadySearched, connectedComponents);
}
foreach (Pair<string, string> connectionPair in connectionPairs)
{
if (connectionPair.First == c.Name)
{
var pairedConnection = c.Item.Connections.FirstOrDefault(c2 => c2.Name == connectionPair.Second);
if (pairedConnection != null)
{
if (alreadySearched.Contains(pairedConnection)) { continue; }
GetConnectedComponentsRecursive(pairedConnection, alreadySearched, connectedComponents);
}
}
else if (connectionPair.Second == c.Name)
{
var pairedConnection = c.Item.Connections.FirstOrDefault(c2 => c2.Name == connectionPair.First);
if (pairedConnection != null)
{
if (alreadySearched.Contains(pairedConnection)) { continue; }
GetConnectedComponentsRecursive(pairedConnection, alreadySearched, connectedComponents);
}
}
}
}
}
@@ -138,6 +138,16 @@ namespace Barotrauma
private Dictionary<string, PriceInfo> prices;
//an area next to the construction
//the construction can be Activated() by a Character inside the area
public List<Rectangle> Triggers;
private List<XElement> fabricationRecipeElements = new List<XElement>();
private bool canSpriteFlipX, canSpriteFlipY;
private Dictionary<string, PriceInfo> prices;
/// <summary>
/// Defines areas where the item can be interacted with. If RequireBodyInsideTrigger is set to true, the character
/// has to be within the trigger to interact. If it's set to false, having the cursor within the trigger is enough.
@@ -460,11 +470,11 @@ namespace Barotrauma
DeconstructItems = new List<DeconstructItem>();
FabricationRecipes = new List<FabricationRecipe>();
DeconstructTime = 1.0f;
Tags = new HashSet<string>(element.GetAttributeStringArray("tags", new string[0], convertToLowerInvariant: true));
Tags = element.GetAttributeStringArray("tags", new string[0], convertToLowerInvariant: true).ToHashSet();
if (Tags.None())
{
Tags = new HashSet<string>(element.GetAttributeStringArray("Tags", new string[0], convertToLowerInvariant: true));
Tags = element.GetAttributeStringArray("Tags", new string[0], convertToLowerInvariant: true).ToHashSet();
}
if (element.Attribute("cargocontainername") != null)
@@ -626,25 +636,10 @@ namespace Barotrauma
string treatmentIdentifier = subElement.GetAttributeString("identifier", "").ToLowerInvariant();
List<AfflictionPrefab> matchingAfflictions = AfflictionPrefab.List.FindAll(a => a.Identifier == treatmentIdentifier || a.AfflictionType == treatmentIdentifier);
if (matchingAfflictions.Count == 0)
var matchingAffliction = AfflictionPrefab.List.Find(a => a.Identifier == treatmentIdentifier);
if (matchingAffliction != null)
{
DebugConsole.ThrowError("Error in item prefab \"" + Name + "\" - couldn't define as a treatment, no treatments with the identifier or type \"" + treatmentIdentifier + "\" were found.");
continue;
}
float suitability = subElement.GetAttributeFloat("suitability", 0.0f);
foreach (AfflictionPrefab matchingAffliction in matchingAfflictions)
{
if (matchingAffliction.TreatmentSuitability.ContainsKey(identifier))
{
matchingAffliction.TreatmentSuitability[identifier] =
Math.Max(matchingAffliction.TreatmentSuitability[identifier], suitability);
}
else
{
matchingAffliction.TreatmentSuitability.Add(identifier, suitability);
}
matchingAffliction.TreatmentSuitability.Add(identifier, subElement.GetAttributeFloat("suitability", 0.0f));
}
break;
}
@@ -17,8 +17,8 @@ namespace Barotrauma
}
public bool IsOptional { get; set; }
public bool IgnoreInEditor { get; set; }
private string[] identifiers;
private string[] excludedIdentifiers;
@@ -35,20 +35,23 @@ namespace Barotrauma
public string JoinedIdentifiers
{
get { return string.Join(",", Identifiers); }
get { return string.Join(",", identifiers); }
set
{
if (value == null) return;
Identifiers = value.Split(',');
for (int i = 0; i < Identifiers.Length; i++)
identifiers = value.Split(',');
for (int i = 0; i < identifiers.Length; i++)
{
Identifiers[i] = Identifiers[i].Trim().ToLowerInvariant();
identifiers[i] = identifiers[i].Trim().ToLowerInvariant();
}
}
}
public string[] Identifiers { get; private set; }
public string[] Identifiers
{
get { return identifiers; }
}
public string JoinedExcludedIdentifiers
{
@@ -69,7 +72,7 @@ namespace Barotrauma
{
if (item == null) return false;
if (excludedIdentifiers.Any(id => item.Prefab.Identifier == id || item.HasTag(id))) return false;
return Identifiers.Any(id => item.Prefab.Identifier == id || item.HasTag(id));
return identifiers.Any(id => item.Prefab.Identifier == id || item.HasTag(id));
}
public RelatedItem(string[] identifiers, string[] excludedIdentifiers)
@@ -78,7 +81,7 @@ namespace Barotrauma
{
identifiers[i] = identifiers[i].Trim().ToLowerInvariant();
}
this.Identifiers = identifiers;
this.identifiers = identifiers;
for (int i = 0; i < excludedIdentifiers.Length; i++)
{
@@ -138,8 +141,7 @@ namespace Barotrauma
element.Add(
new XAttribute("identifiers", JoinedIdentifiers),
new XAttribute("type", type.ToString()),
new XAttribute("optional", IsOptional),
new XAttribute("ignoreineditor", IgnoreInEditor));
new XAttribute("optional", IsOptional));
if (excludedIdentifiers.Length > 0)
{
@@ -221,7 +223,6 @@ namespace Barotrauma
}
ri.IsOptional = element.GetAttributeBool("optional", false);
ri.IgnoreInEditor = element.GetAttributeBool("ignoreineditor", false);
return ri;
}
}