Unstable 0.16.0.0
This commit is contained in:
@@ -144,16 +144,6 @@ namespace Barotrauma.Items.Components
|
||||
if (linkedGap == null)
|
||||
{
|
||||
Rectangle rect = item.Rect;
|
||||
if (IsHorizontal)
|
||||
{
|
||||
rect.Y += 5;
|
||||
rect.Height += 10;
|
||||
}
|
||||
else
|
||||
{
|
||||
rect.X -= 5;
|
||||
rect.Width += 10;
|
||||
}
|
||||
linkedGap = new Gap(rect, !IsHorizontal, Item.Submarine)
|
||||
{
|
||||
Submarine = item.Submarine
|
||||
|
||||
+20
-14
@@ -55,17 +55,22 @@ namespace Barotrauma.Items.Components
|
||||
[Editable(MaxValueFloat = int.MaxValue, MinValueFloat = 1f, ValueStep = 1f, DecimalCount = 0), Serialize("1,3", true, "Minumum and maximum amount of items or creatures to spawn in one attempt")]
|
||||
public Vector2 SpawnAmountRange { get; set; }
|
||||
|
||||
[Editable(MinValueInt = int.MinValue, MaxValueInt = int.MaxValue), Serialize(8, true, "Amount of items or creatures in the spawn area that will prevent further items or creatures from being spawned")]
|
||||
[Editable(MinValueInt = 0, MaxValueInt = int.MaxValue), Serialize(8, true, "Total maximum amount of items or creatures that can be spawned. 0 = unrestricted.")]
|
||||
public int MaximumAmount { get; set; }
|
||||
|
||||
[Editable(MaxValueFloat = int.MaxValue, MinValueFloat = int.MinValue, ValueStep = 10f), Serialize(500f, true, "Inflate the circle of rectangle by this value to extend the area that counts towards the maximum amount of items or enemies to be spawned")]
|
||||
[Editable(MinValueInt = 0, MaxValueInt = int.MaxValue), Serialize(8, true, "Amount of items or creatures in the spawn area that will prevent further items or creatures from being spawned. 0 = unrestricted.")]
|
||||
public int MaximumAmountInArea { get; set; }
|
||||
|
||||
[Editable(MaxValueFloat = int.MaxValue, MinValueFloat = 0, ValueStep = 10f), Serialize(500f, true, "Inflate the circle of rectangle by this value to extend the area that counts towards the maximum amount of items or enemies to be spawned")]
|
||||
public float MaximumAmountRangePadding { get; set; }
|
||||
|
||||
[Serialize(true, true, "")]
|
||||
public bool CanSpawn { get; set; } = true;
|
||||
|
||||
private float SpawnTimer;
|
||||
private float? SpawnTimerGoal;
|
||||
private float spawnTimer;
|
||||
private float? spawnTimerGoal;
|
||||
|
||||
private int spawnedAmount = 0;
|
||||
|
||||
public EntitySpawnerComponent(Item item, XElement element) : base(item, element)
|
||||
{
|
||||
@@ -115,15 +120,15 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
if (minTime < 0 && maxTime < 0) { return; }
|
||||
|
||||
SpawnTimerGoal ??= Rand.Range(minTime, maxTime, Rand.RandSync.Unsynced);
|
||||
spawnTimerGoal ??= Rand.Range(minTime, maxTime, Rand.RandSync.Unsynced);
|
||||
|
||||
SpawnTimer += deltaTime;
|
||||
spawnTimer += deltaTime;
|
||||
|
||||
if (SpawnTimer > SpawnTimerGoal)
|
||||
if (spawnTimer > spawnTimerGoal)
|
||||
{
|
||||
Spawn();
|
||||
SpawnTimerGoal = null;
|
||||
SpawnTimer = 0;
|
||||
spawnTimerGoal = null;
|
||||
spawnTimer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,12 +154,12 @@ namespace Barotrauma.Items.Components
|
||||
private RectangleF GetAreaRectangle(Vector2 size, Vector2 offset, bool draw)
|
||||
{
|
||||
Vector2 pos = item.WorldPosition;
|
||||
pos += offset;
|
||||
if (draw)
|
||||
{
|
||||
pos.Y = -pos.Y;
|
||||
}
|
||||
|
||||
pos += offset;
|
||||
RectangleF rect = new RectangleF(pos.X - size.X / 2f, pos.Y - size.Y / 2f, size.X, size.Y);
|
||||
return rect;
|
||||
}
|
||||
@@ -162,6 +167,7 @@ namespace Barotrauma.Items.Components
|
||||
private bool CanSpawnMore()
|
||||
{
|
||||
if (!CanSpawn) { return false; }
|
||||
if (MaximumAmount > 0 && spawnedAmount >= MaximumAmount) { return false; }
|
||||
|
||||
if (OnlySpawnWhenCrewInRange)
|
||||
{
|
||||
@@ -171,10 +177,9 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
if (MaximumAmount < 0) { return true; }
|
||||
if (MaximumAmountInArea <= 0) { return true; }
|
||||
|
||||
int amount;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(SpeciesName))
|
||||
{
|
||||
amount = Character.CharacterList.Count(c => !c.IsDead && c.SpeciesName.Equals(SpeciesName, StringComparison.OrdinalIgnoreCase) && IsInRange(c.WorldPosition, crewArea: false, rangePad: true));
|
||||
@@ -188,13 +193,12 @@ namespace Barotrauma.Items.Components
|
||||
return false;
|
||||
}
|
||||
|
||||
return amount < MaximumAmount;
|
||||
return amount < MaximumAmountInArea;
|
||||
}
|
||||
|
||||
private bool IsInRange(Vector2 worldPos, bool crewArea = false, bool rangePad = false)
|
||||
{
|
||||
Vector2 offset = crewArea ? CrewAreaOffset : SpawnAreaOffset;
|
||||
offset.Y = -offset.Y;
|
||||
switch (crewArea ? CrewAreaShape : SpawnAreaShape)
|
||||
{
|
||||
case AreaShape.Circle:
|
||||
@@ -269,6 +273,7 @@ namespace Barotrauma.Items.Components
|
||||
string[] allSpecies = SpeciesName.Split(',');
|
||||
string species = allSpecies.GetRandom().Trim();
|
||||
Entity.Spawner?.AddToSpawnQueue(species, pos);
|
||||
spawnedAmount++;
|
||||
}
|
||||
else if (!string.IsNullOrWhiteSpace(ItemIdentifier))
|
||||
{
|
||||
@@ -283,6 +288,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
|
||||
Entity.Spawner?.AddToSpawnQueue(prefab, pos, item.Submarine);
|
||||
spawnedAmount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,6 +74,7 @@ namespace Barotrauma.Items.Components
|
||||
a.Identifier.Equals(Effect, StringComparison.OrdinalIgnoreCase) ||
|
||||
a.AfflictionType.Equals(Effect, StringComparison.OrdinalIgnoreCase)).GetRandom();
|
||||
}
|
||||
Tainted = true;
|
||||
}
|
||||
|
||||
[Serialize(3.0f, false)]
|
||||
@@ -94,37 +95,28 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
if (targetCharacter != null) { return; }
|
||||
|
||||
if (tainted)
|
||||
{
|
||||
if (selectedTaintedEffect != null)
|
||||
{
|
||||
float selectedTaintedEffectStrength = item.ConditionPercentage / 100.0f * selectedTaintedEffect.MaxStrength;
|
||||
character.CharacterHealth.ApplyAffliction(null, selectedTaintedEffect.Instantiate(selectedTaintedEffectStrength));
|
||||
var existingAffliction = character.CharacterHealth.GetAllAfflictions().FirstOrDefault(a => a.Prefab == selectedTaintedEffect);
|
||||
if (existingAffliction != null)
|
||||
{
|
||||
existingAffliction.Strength = selectedTaintedEffectStrength;
|
||||
}
|
||||
targetCharacter = character;
|
||||
#if SERVER
|
||||
item.CreateServerEvent(this);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if (selectedEffect != null)
|
||||
{
|
||||
ApplyStatusEffects(ActionType.OnWearing, 1.0f);
|
||||
float selectedEffectStrength = item.ConditionPercentage / 100.0f * selectedEffect.MaxStrength;
|
||||
character.CharacterHealth.ApplyAffliction(null, selectedEffect.Instantiate(selectedEffectStrength));
|
||||
var existingAffliction = character.CharacterHealth.GetAllAfflictions().FirstOrDefault(a => a.Prefab == selectedEffect);
|
||||
if (existingAffliction != null)
|
||||
{
|
||||
existingAffliction.Strength = selectedEffectStrength;
|
||||
}
|
||||
targetCharacter = character;
|
||||
ApplyStatusEffects(ActionType.OnWearing, 1.0f);
|
||||
float selectedEffectStrength = GetCombinedEffectStrength();
|
||||
character.CharacterHealth.ApplyAffliction(null, selectedEffect.Instantiate(selectedEffectStrength));
|
||||
var affliction = character.CharacterHealth.GetAllAfflictions().FirstOrDefault(a => a.Prefab == selectedEffect);
|
||||
if (affliction != null) { affliction.Strength = selectedEffectStrength; }
|
||||
#if SERVER
|
||||
item.CreateServerEvent(this);
|
||||
#endif
|
||||
}
|
||||
if (tainted && selectedTaintedEffect != null)
|
||||
{
|
||||
float selectedTaintedEffectStrength = GetCombinedTaintedEffectStrength();
|
||||
character.CharacterHealth.ApplyAffliction(null, selectedTaintedEffect.Instantiate(selectedTaintedEffectStrength));
|
||||
var affliction = character.CharacterHealth.GetAllAfflictions().FirstOrDefault(a => a.Prefab == selectedTaintedEffect);
|
||||
if (affliction != null) { affliction.Strength = selectedTaintedEffectStrength; }
|
||||
targetCharacter = character;
|
||||
#if SERVER
|
||||
item.CreateServerEvent(this);
|
||||
#endif
|
||||
}
|
||||
foreach (Item containedItem in item.ContainedItems)
|
||||
{
|
||||
@@ -142,13 +134,14 @@ namespace Barotrauma.Items.Components
|
||||
(rootContainer == null || !targetCharacter.HasEquippedItem(rootContainer) || !targetCharacter.Inventory.IsInLimbSlot(rootContainer, InvSlotType.HealthInterface)))
|
||||
{
|
||||
item.ApplyStatusEffects(ActionType.OnSevered, 1.0f, targetCharacter);
|
||||
targetCharacter.CharacterHealth.ReduceAffliction(null, selectedEffect.Identifier, selectedEffect.MaxStrength);
|
||||
if (tainted)
|
||||
{
|
||||
targetCharacter.CharacterHealth.ReduceAffliction(null, selectedTaintedEffect.Identifier, selectedTaintedEffect.MaxStrength);
|
||||
}
|
||||
targetCharacter = null;
|
||||
IsActive = false;
|
||||
|
||||
var affliction = targetCharacter.CharacterHealth.GetAllAfflictions().FirstOrDefault(a => a.Prefab == selectedEffect);
|
||||
if (affliction != null) { affliction.Strength = GetCombinedEffectStrength(); }
|
||||
var taintedAffliction = targetCharacter.CharacterHealth.GetAllAfflictions().FirstOrDefault(a => a.Prefab == selectedTaintedEffect);
|
||||
if (taintedAffliction != null) { taintedAffliction.Strength = GetCombinedTaintedEffectStrength(); }
|
||||
|
||||
targetCharacter = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -184,6 +177,36 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
private float GetCombinedEffectStrength()
|
||||
{
|
||||
float effectStrength = 0.0f;
|
||||
foreach (Item otherItem in targetCharacter.Inventory.FindAllItems(recursive: true))
|
||||
{
|
||||
var geneticMaterial = otherItem.GetComponent<GeneticMaterial>();
|
||||
if (geneticMaterial == null || !geneticMaterial.IsActive) { continue; }
|
||||
if (geneticMaterial.selectedEffect == selectedEffect)
|
||||
{
|
||||
effectStrength += otherItem.ConditionPercentage / 100.0f * selectedEffect.MaxStrength;
|
||||
}
|
||||
}
|
||||
return effectStrength;
|
||||
}
|
||||
|
||||
private float GetCombinedTaintedEffectStrength()
|
||||
{
|
||||
float taintedEffectStrength = 0.0f;
|
||||
foreach (Item otherItem in targetCharacter.Inventory.FindAllItems(recursive: true))
|
||||
{
|
||||
var geneticMaterial = otherItem.GetComponent<GeneticMaterial>();
|
||||
if (geneticMaterial == null || !geneticMaterial.IsActive) { continue; }
|
||||
if (selectedTaintedEffect != null && geneticMaterial.selectedTaintedEffect == selectedTaintedEffect)
|
||||
{
|
||||
taintedEffectStrength += otherItem.ConditionPercentage / 100.0f * selectedTaintedEffect.MaxStrength;
|
||||
}
|
||||
}
|
||||
return taintedEffectStrength;
|
||||
}
|
||||
|
||||
private float GetTaintedProbabilityOnRefine(Character user)
|
||||
{
|
||||
if (user == null) { return 1.0f; }
|
||||
|
||||
@@ -278,7 +278,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
for (int i = 0, j = 0; i < maxSides; i++)
|
||||
{
|
||||
if (!occupiedSides.IsBitSet((TileSide) (1 << i)))
|
||||
if (!occupiedSides.HasFlag((TileSide) (1 << i)))
|
||||
{
|
||||
pool[j] = i;
|
||||
j++;
|
||||
@@ -303,7 +303,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public bool CanGrowMore() => (Sides | BlockedSides).Count() < 4;
|
||||
|
||||
public bool IsSideBlocked(TileSide side) => BlockedSides.IsBitSet(side) || Sides.IsBitSet(side);
|
||||
public bool IsSideBlocked(TileSide side) => BlockedSides.HasFlag(side) || Sides.HasFlag(side);
|
||||
|
||||
public static Rectangle CreatePlantRect(Vector2 pos) => new Rectangle((int) pos.X - Size / 2, (int) pos.Y + Size / 2, Size, Size);
|
||||
}
|
||||
@@ -774,7 +774,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
TileSide oppositeSide = connectingSide.GetOppositeSide();
|
||||
|
||||
if (otherVine.BlockedSides.IsBitSet(connectingSide))
|
||||
if (otherVine.BlockedSides.HasFlag(connectingSide))
|
||||
{
|
||||
newVine.BlockedSides |= oppositeSide;
|
||||
continue;
|
||||
|
||||
@@ -166,7 +166,7 @@ namespace Barotrauma.Items.Components
|
||||
Pusher = new PhysicsBody(item.body.width, item.body.height, item.body.radius, item.body.Density)
|
||||
{
|
||||
BodyType = BodyType.Dynamic,
|
||||
CollidesWith = Physics.CollisionCharacter,
|
||||
CollidesWith = Physics.CollisionCharacter | Physics.CollisionProjectile,
|
||||
CollisionCategories = Physics.CollisionItemBlocking,
|
||||
Enabled = false,
|
||||
UserData = this
|
||||
@@ -604,7 +604,14 @@ namespace Barotrauma.Items.Components
|
||||
int maxAttachableCount = (int)character.Info.GetSavedStatValue(StatTypes.MaxAttachableCount, item.Prefab.Identifier);
|
||||
int currentlyAttachedCount = Item.ItemList.Count(
|
||||
i => i.Submarine == attachTarget?.Submarine && i.GetComponent<Holdable>() is Holdable holdable && holdable.Attached && i.Prefab.Identifier == item.prefab.Identifier);
|
||||
if (currentlyAttachedCount >= maxAttachableCount)
|
||||
if (maxAttachableCount == 0)
|
||||
{
|
||||
#if CLIENT
|
||||
GUI.AddMessage(TextManager.Get("itemmsgrequiretraining"), Color.Red);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
else if (currentlyAttachedCount >= maxAttachableCount)
|
||||
{
|
||||
#if CLIENT
|
||||
GUI.AddMessage($"{TextManager.Get("itemmsgtotalnumberlimited")} ({currentlyAttachedCount}/{maxAttachableCount})", Color.Red);
|
||||
@@ -801,7 +808,7 @@ namespace Barotrauma.Items.Components
|
||||
equipLimb = picker.AnimController.GetLimb(LimbType.Torso);
|
||||
}
|
||||
|
||||
if (equipLimb != null)
|
||||
if (equipLimb != null && !equipLimb.Removed)
|
||||
{
|
||||
float itemAngle = (equipLimb.Rotation + holdAngle * picker.AnimController.Dir);
|
||||
|
||||
@@ -814,6 +821,11 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
public override void ReceiveSignal(Signal signal, Connection connection)
|
||||
{
|
||||
//do nothing
|
||||
}
|
||||
|
||||
public override void FlipX(bool relativeToSub)
|
||||
{
|
||||
handlePos[0].X = -handlePos[0].X;
|
||||
|
||||
@@ -115,7 +115,7 @@ namespace Barotrauma.Items.Components
|
||||
reloadTimer /= (1f + item.GetQualityModifier(Quality.StatType.StrikingSpeedMultiplier));
|
||||
|
||||
item.body.FarseerBody.CollisionCategories = Physics.CollisionProjectile;
|
||||
item.body.FarseerBody.CollidesWith = Physics.CollisionCharacter | Physics.CollisionWall;
|
||||
item.body.FarseerBody.CollidesWith = Physics.CollisionCharacter | Physics.CollisionWall | Physics.CollisionItemBlocking;
|
||||
item.body.FarseerBody.OnCollision += OnCollision;
|
||||
item.body.FarseerBody.IsBullet = true;
|
||||
item.body.PhysEnabled = true;
|
||||
@@ -361,6 +361,10 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
hitTargets.Add(targetItem);
|
||||
}
|
||||
else if (f2.Body.UserData is Holdable holdable && holdable.CanPush)
|
||||
{
|
||||
hitTargets.Add(holdable.Item);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
@@ -411,6 +415,14 @@ namespace Barotrauma.Items.Components
|
||||
if (targetItem.Removed) { return; }
|
||||
Attack.DoDamage(User, targetItem, item.WorldPosition, 1.0f);
|
||||
}
|
||||
else if (target.UserData is Holdable holdable && holdable.CanPush)
|
||||
{
|
||||
if (holdable.Item.Removed) { return; }
|
||||
Attack.DoDamage(User, holdable.Item, item.WorldPosition, 1.0f);
|
||||
RestoreCollision();
|
||||
hitting = false;
|
||||
User = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
|
||||
@@ -74,7 +74,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
if (PickingTime > 0.0f)
|
||||
{
|
||||
var abilityPickingTime = new AbilityValueItem(PickingTime, item.Prefab);
|
||||
var abilityPickingTime = new AbilityItemPickingTime(PickingTime, item.Prefab);
|
||||
picker.CheckTalents(AbilityEffectType.OnItemPicked, abilityPickingTime);
|
||||
|
||||
if (requiredItems.ContainsKey(RelatedItem.RelationType.Equipped))
|
||||
@@ -300,4 +300,15 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class AbilityItemPickingTime : AbilityObject, IAbilityValue, IAbilityItemPrefab
|
||||
{
|
||||
public AbilityItemPickingTime(float pickingTime, ItemPrefab itemPrefab)
|
||||
{
|
||||
Value = pickingTime;
|
||||
ItemPrefab = itemPrefab;
|
||||
}
|
||||
public float Value { get; set; }
|
||||
public ItemPrefab ItemPrefab { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,7 +158,7 @@ namespace Barotrauma.Items.Components
|
||||
return MathHelper.ToRadians(spread);
|
||||
}
|
||||
|
||||
private readonly List<Body> limbBodies = new List<Body>();
|
||||
private readonly List<Body> ignoredBodies = new List<Body>();
|
||||
public override bool Use(float deltaTime, Character character = null)
|
||||
{
|
||||
tryingToCharge = true;
|
||||
@@ -172,8 +172,8 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
if (character != null)
|
||||
{
|
||||
var abilityItem = new AbilityItem(item);
|
||||
character.CheckTalents(AbilityEffectType.OnUseRangedWeapon, abilityItem);
|
||||
var abilityRangedWeapon = new AbilityRangedWeapon(item);
|
||||
character.CheckTalents(AbilityEffectType.OnUseRangedWeapon, abilityRangedWeapon);
|
||||
}
|
||||
|
||||
if (item.AiTarget != null)
|
||||
@@ -182,11 +182,20 @@ namespace Barotrauma.Items.Components
|
||||
item.AiTarget.SightRange = item.AiTarget.MaxSightRange;
|
||||
}
|
||||
|
||||
limbBodies.Clear();
|
||||
ignoredBodies.Clear();
|
||||
foreach (Limb l in character.AnimController.Limbs)
|
||||
{
|
||||
if (l.IsSevered) { continue; }
|
||||
limbBodies.Add(l.body.FarseerBody);
|
||||
ignoredBodies.Add(l.body.FarseerBody);
|
||||
}
|
||||
|
||||
foreach (Item heldItem in character.HeldItems)
|
||||
{
|
||||
var holdable = heldItem.GetComponent<Holdable>();
|
||||
if (holdable?.Pusher != null)
|
||||
{
|
||||
ignoredBodies.Add(holdable.Pusher.FarseerBody);
|
||||
}
|
||||
}
|
||||
|
||||
float degreeOfFailure = 1.0f - DegreeOfSuccess(character);
|
||||
@@ -211,7 +220,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
float damageMultiplier = 1f + item.GetQualityModifier(Quality.StatType.FirepowerMultiplier);
|
||||
projectile.Launcher = item;
|
||||
projectile.Shoot(character, character.AnimController.AimSourceSimPos, barrelPos, rotation + spread, ignoredBodies: limbBodies.ToList(), createNetworkEvent: false, damageMultiplier);
|
||||
projectile.Shoot(character, character.AnimController.AimSourceSimPos, barrelPos, rotation + spread, ignoredBodies: ignoredBodies.ToList(), createNetworkEvent: false, damageMultiplier);
|
||||
projectile.Item.GetComponent<Rope>()?.Attach(Item, projectile.Item);
|
||||
if (i == 0)
|
||||
{
|
||||
@@ -270,4 +279,12 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
partial void LaunchProjSpecific();
|
||||
}
|
||||
class AbilityRangedWeapon : AbilityObject, IAbilityItem
|
||||
{
|
||||
public AbilityRangedWeapon(Item item)
|
||||
{
|
||||
Item = item;
|
||||
}
|
||||
public Item Item { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -521,7 +521,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
if (!fixableEntities.Contains("structure") && !fixableEntities.Contains(targetStructure.Prefab.Identifier)) { return true; }
|
||||
|
||||
ApplyStatusEffectsOnTarget(user, deltaTime, ActionType.OnUse, new ISerializableEntity[] { targetStructure });
|
||||
ApplyStatusEffectsOnTarget(user, deltaTime, ActionType.OnUse, structure: targetStructure);
|
||||
FixStructureProjSpecific(user, deltaTime, targetStructure, sectionIndex);
|
||||
|
||||
float structureFixAmount = StructureFixAmount;
|
||||
@@ -589,8 +589,7 @@ namespace Barotrauma.Items.Components
|
||||
closestLimb.body.ApplyForce(dir * TargetForce, maxVelocity: 10.0f);
|
||||
}
|
||||
|
||||
ApplyStatusEffectsOnTarget(user, deltaTime, ActionType.OnUse,
|
||||
closestLimb == null ? new ISerializableEntity[] { targetCharacter } : new ISerializableEntity[] { targetCharacter, closestLimb });
|
||||
ApplyStatusEffectsOnTarget(user, deltaTime, ActionType.OnUse, character: targetCharacter, limb: closestLimb);
|
||||
FixCharacterProjSpecific(user, deltaTime, targetCharacter);
|
||||
return true;
|
||||
}
|
||||
@@ -606,7 +605,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
|
||||
targetLimb.character.LastDamageSource = item;
|
||||
ApplyStatusEffectsOnTarget(user, deltaTime, ActionType.OnUse, new ISerializableEntity[] { targetLimb.character, targetLimb });
|
||||
ApplyStatusEffectsOnTarget(user, deltaTime, ActionType.OnUse, character: targetLimb.character, limb: targetLimb);
|
||||
FixCharacterProjSpecific(user, deltaTime, targetLimb.character);
|
||||
return true;
|
||||
}
|
||||
@@ -645,7 +644,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
targetItem.IsHighlighted = true;
|
||||
|
||||
ApplyStatusEffectsOnTarget(user, deltaTime, ActionType.OnUse, targetItem.AllPropertyObjects);
|
||||
ApplyStatusEffectsOnTarget(user, deltaTime, ActionType.OnUse, targetItem);
|
||||
|
||||
if (targetItem.body != null && !MathUtils.NearlyEqual(TargetForce, 0.0f))
|
||||
{
|
||||
@@ -682,7 +681,7 @@ namespace Barotrauma.Items.Components
|
||||
Reset();
|
||||
return true;
|
||||
}
|
||||
if (leak.Submarine == null)
|
||||
if (leak.Submarine == null || leak.Submarine != character.Submarine)
|
||||
{
|
||||
Reset();
|
||||
return true;
|
||||
@@ -836,32 +835,44 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyStatusEffectsOnTarget(Character user, float deltaTime, ActionType actionType, IEnumerable<ISerializableEntity> targets)
|
||||
private static List<ISerializableEntity> currentTargets = new List<ISerializableEntity>();
|
||||
private void ApplyStatusEffectsOnTarget(Character user, float deltaTime, ActionType actionType, Item targetItem = null, Character character = null, Limb limb = null, Structure structure = null)
|
||||
{
|
||||
if (statusEffectLists == null) { return; }
|
||||
if (!statusEffectLists.TryGetValue(actionType, out List<StatusEffect> statusEffects)) { return; }
|
||||
|
||||
currentTargets.Clear();
|
||||
foreach (StatusEffect effect in statusEffects)
|
||||
{
|
||||
effect.SetUser(user);
|
||||
if (effect.HasTargetType(StatusEffect.TargetType.UseTarget))
|
||||
{
|
||||
effect.Apply(actionType, deltaTime, item, targets);
|
||||
if (targetItem != null)
|
||||
{
|
||||
currentTargets.AddRange(targetItem.AllPropertyObjects);
|
||||
}
|
||||
if (structure != null)
|
||||
{
|
||||
currentTargets.Add(structure);
|
||||
}
|
||||
effect.Apply(actionType, deltaTime, item, currentTargets);
|
||||
}
|
||||
else if (effect.HasTargetType(StatusEffect.TargetType.Character))
|
||||
{
|
||||
effect.Apply(actionType, deltaTime, item, targets.Where(t => t is Character));
|
||||
currentTargets.Add(character);
|
||||
effect.Apply(actionType, deltaTime, item, currentTargets);
|
||||
}
|
||||
else if (effect.HasTargetType(StatusEffect.TargetType.Limb))
|
||||
{
|
||||
effect.Apply(actionType, deltaTime, item, targets.Where(t => t is Limb));
|
||||
currentTargets.Add(limb);
|
||||
effect.Apply(actionType, deltaTime, item, currentTargets);
|
||||
}
|
||||
|
||||
#if CLIENT
|
||||
if (user == null) { return; }
|
||||
// Hard-coded progress bars for welding doors stuck.
|
||||
// A general purpose system could be better, but it would most likely require changes in the way we define the status effects in xml.
|
||||
foreach (ISerializableEntity target in targets)
|
||||
foreach (ISerializableEntity target in currentTargets)
|
||||
{
|
||||
if (!(target is Door door)) { continue; }
|
||||
if (!door.CanBeWelded || !door.Item.IsInteractable(user)) { continue; }
|
||||
|
||||
@@ -284,6 +284,43 @@ namespace Barotrauma.Items.Components
|
||||
SerializableProperties = SerializableProperty.DeserializeProperties(this, element);
|
||||
ParseMsg();
|
||||
|
||||
string inheritRequiredSkillsFrom = element.GetAttributeString("inheritrequiredskillsfrom", "");
|
||||
if (!string.IsNullOrEmpty(inheritRequiredSkillsFrom))
|
||||
{
|
||||
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.");
|
||||
}
|
||||
else
|
||||
{
|
||||
requiredSkills = component.requiredSkills;
|
||||
}
|
||||
}
|
||||
|
||||
string inheritStatusEffectsFrom = element.GetAttributeString("inheritstatuseffectsfrom", "");
|
||||
if (!string.IsNullOrEmpty(inheritStatusEffectsFrom))
|
||||
{
|
||||
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.");
|
||||
}
|
||||
else if (component.statusEffectLists != null)
|
||||
{
|
||||
statusEffectLists ??= new Dictionary<ActionType, List<StatusEffect>>();
|
||||
foreach (KeyValuePair<ActionType, List<StatusEffect>> kvp in component.statusEffectLists)
|
||||
{
|
||||
if (!statusEffectLists.TryGetValue(kvp.Key, out List<StatusEffect> effectList))
|
||||
{
|
||||
effectList = new List<StatusEffect>();
|
||||
statusEffectLists.Add(kvp.Key, effectList);
|
||||
}
|
||||
effectList.AddRange(kvp.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (XElement subElement in element.Elements())
|
||||
{
|
||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||
@@ -315,19 +352,8 @@ namespace Barotrauma.Items.Components
|
||||
requiredSkills.Add(new Skill(skillIdentifier, subElement.GetAttributeInt("level", 0)));
|
||||
break;
|
||||
case "statuseffect":
|
||||
var statusEffect = StatusEffect.Load(subElement, item.Name);
|
||||
|
||||
if (statusEffectLists == null) statusEffectLists = new Dictionary<ActionType, List<StatusEffect>>();
|
||||
|
||||
List<StatusEffect> effectList;
|
||||
if (!statusEffectLists.TryGetValue(statusEffect.type, out effectList))
|
||||
{
|
||||
effectList = new List<StatusEffect>();
|
||||
statusEffectLists.Add(statusEffect.type, effectList);
|
||||
}
|
||||
|
||||
effectList.Add(statusEffect);
|
||||
|
||||
statusEffectLists ??= new Dictionary<ActionType, List<StatusEffect>>();
|
||||
LoadStatusEffect(subElement);
|
||||
break;
|
||||
default:
|
||||
if (LoadElemProjSpecific(subElement)) { break; }
|
||||
@@ -342,6 +368,17 @@ namespace Barotrauma.Items.Components
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void LoadStatusEffect(XElement subElement)
|
||||
{
|
||||
var statusEffect = StatusEffect.Load(subElement, item.Name);
|
||||
if (!statusEffectLists.TryGetValue(statusEffect.type, out List<StatusEffect> effectList))
|
||||
{
|
||||
effectList = new List<StatusEffect>();
|
||||
statusEffectLists.Add(statusEffect.type, effectList);
|
||||
}
|
||||
effectList.Add(statusEffect);
|
||||
}
|
||||
}
|
||||
|
||||
private void SetActiveState(bool isActive)
|
||||
@@ -399,6 +436,8 @@ namespace Barotrauma.Items.Components
|
||||
return false;
|
||||
}
|
||||
|
||||
public virtual bool UpdateWhenInactive => false;
|
||||
|
||||
//called when isActive is true and condition > 0.0f
|
||||
public virtual void Update(float deltaTime, Camera cam)
|
||||
{
|
||||
@@ -798,7 +837,10 @@ namespace Barotrauma.Items.Components
|
||||
foreach (ItemComponent ic in item.Components)
|
||||
{
|
||||
if (ic.statusEffectLists == null || !ic.statusEffectLists.TryGetValue(ActionType.OnBroken, out List<StatusEffect> brokenEffects)) { continue; }
|
||||
brokenEffects.ForEach(e => e.SetUser(user));
|
||||
foreach (var brokenEffect in brokenEffects)
|
||||
{
|
||||
brokenEffect.SetUser(user);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1007,7 +1049,8 @@ namespace Barotrauma.Items.Components
|
||||
return 0.0f;
|
||||
}
|
||||
}
|
||||
return 1.0f;
|
||||
// Prefer items with the same identifier as the contained items'
|
||||
return container.ContainsItemsWithSameIdentifier(i) ? 1.0f : 0.5f;
|
||||
}
|
||||
};
|
||||
containObjective.Abandoned += () => aiController.IgnoredItems.Add(container.Item);
|
||||
|
||||
@@ -208,12 +208,13 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public override bool RecreateGUIOnResolutionChange => true;
|
||||
|
||||
public List<RelatedItem> ContainableItems { get; }
|
||||
|
||||
public ItemContainer(Item item, XElement element)
|
||||
: base(item, element)
|
||||
{
|
||||
int totalCapacity = capacity;
|
||||
|
||||
List<RelatedItem> containableItems = null;
|
||||
foreach (XElement subElement in element.Elements())
|
||||
{
|
||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||
@@ -225,8 +226,8 @@ namespace Barotrauma.Items.Components
|
||||
DebugConsole.ThrowError("Error in item config \"" + item.ConfigFile + "\" - containable with no identifiers.");
|
||||
continue;
|
||||
}
|
||||
containableItems ??= new List<RelatedItem>();
|
||||
containableItems.Add(containable);
|
||||
ContainableItems ??= new List<RelatedItem>();
|
||||
ContainableItems.Add(containable);
|
||||
break;
|
||||
case "subcontainer":
|
||||
totalCapacity += subElement.GetAttributeInt("capacity", 1);
|
||||
@@ -237,7 +238,7 @@ namespace Barotrauma.Items.Components
|
||||
slotRestrictions = new SlotRestrictions[totalCapacity];
|
||||
for (int i = 0; i < capacity; i++)
|
||||
{
|
||||
slotRestrictions[i] = new SlotRestrictions(maxStackSize, containableItems);
|
||||
slotRestrictions[i] = new SlotRestrictions(maxStackSize, ContainableItems);
|
||||
}
|
||||
|
||||
int subContainerIndex = capacity;
|
||||
@@ -344,6 +345,19 @@ namespace Barotrauma.Items.Components
|
||||
return slotRestrictions[index].MatchesItem(itemPrefab);
|
||||
}
|
||||
|
||||
public bool ContainsItemsWithSameIdentifier(Item item)
|
||||
{
|
||||
if (item == null) { return false; }
|
||||
foreach (var containedItem in Inventory.AllItems)
|
||||
{
|
||||
if (containedItem.Prefab.Identifier == item.Prefab.Identifier)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
readonly List<ISerializableEntity> targets = new List<ISerializableEntity>();
|
||||
|
||||
public override void Update(float deltaTime, Camera cam)
|
||||
@@ -432,7 +446,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
}
|
||||
var abilityItem = new AbilityItem(item);
|
||||
var abilityItem = new AbilityItemContainer(item);
|
||||
character.CheckTalents(AbilityEffectType.OnOpenItemContainer, abilityItem);
|
||||
|
||||
return base.Select(character);
|
||||
@@ -494,6 +508,21 @@ namespace Barotrauma.Items.Components
|
||||
IsActive = true;
|
||||
}
|
||||
|
||||
public override void ReceiveSignal(Signal signal, Connection connection)
|
||||
{
|
||||
switch (connection.Name)
|
||||
{
|
||||
case "activate":
|
||||
case "use":
|
||||
case "trigger_in":
|
||||
if (signal.value != "0")
|
||||
{
|
||||
item.Use(1.0f, signal.sender);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetContainedItemPositions()
|
||||
{
|
||||
Vector2 transformedItemPos = ItemPos * item.Scale;
|
||||
@@ -689,7 +718,6 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected override void ShallowRemoveComponentSpecific()
|
||||
{
|
||||
}
|
||||
@@ -743,4 +771,13 @@ namespace Barotrauma.Items.Components
|
||||
return componentElement;
|
||||
}
|
||||
}
|
||||
|
||||
class AbilityItemContainer : AbilityObject, IAbilityItem
|
||||
{
|
||||
public AbilityItemContainer(Item item)
|
||||
{
|
||||
Item = item;
|
||||
}
|
||||
public Item Item { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -370,18 +370,29 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public Item GetFocusTarget()
|
||||
{
|
||||
item.SendSignal(new Signal(MathHelper.ToDegrees(targetRotation).ToString("G", CultureInfo.InvariantCulture), sender: user), "position_out");
|
||||
|
||||
for (int i = item.LastSentSignalRecipients.Count - 1; i >= 0; i--)
|
||||
Item focusTarget = null;
|
||||
for (int c = 0; c < 2; c++)
|
||||
{
|
||||
if (item.LastSentSignalRecipients[i].Item.Condition <= 0.0f || item.LastSentSignalRecipients[i].IsPower) { continue; }
|
||||
if (item.LastSentSignalRecipients[i].Item.Prefab.FocusOnSelected)
|
||||
//try finding the item to focus on using trigger_out, and if that fails, using position_out
|
||||
string connectionName = c == 0 ? "trigger_out" : "position_out";
|
||||
string signal = c == 0 ? "0" : MathHelper.ToDegrees(targetRotation).ToString("G", CultureInfo.InvariantCulture);
|
||||
if (!item.SendSignal(new Signal(signal, sender: user), connectionName) || focusTarget != null)
|
||||
{
|
||||
return item.LastSentSignalRecipients[i].Item;
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int i = item.LastSentSignalRecipients.Count - 1; i >= 0; i--)
|
||||
{
|
||||
if (item.LastSentSignalRecipients[i].Item.Condition <= 0.0f || item.LastSentSignalRecipients[i].IsPower) { continue; }
|
||||
if (item.LastSentSignalRecipients[i].Item.Prefab.FocusOnSelected)
|
||||
{
|
||||
focusTarget = item.LastSentSignalRecipients[i].Item;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
return focusTarget;
|
||||
}
|
||||
|
||||
public override bool Pick(Character picker)
|
||||
|
||||
+26
-4
@@ -170,7 +170,7 @@ namespace Barotrauma.Items.Components
|
||||
character.CheckTalents(AbilityEffectType.OnItemDeconstructedByAlly, abilityTargetItem);
|
||||
}
|
||||
|
||||
var itemCreationMultiplier = new AbilityValueItem(amountMultiplier, targetItem.Prefab);
|
||||
var itemCreationMultiplier = new AbilityItemCreationMultiplier(targetItem.Prefab, amountMultiplier);
|
||||
user.CheckTalents(AbilityEffectType.OnItemDeconstructedMaterial, itemCreationMultiplier);
|
||||
amountMultiplier = (int)itemCreationMultiplier.Value;
|
||||
}
|
||||
@@ -261,8 +261,8 @@ namespace Barotrauma.Items.Components
|
||||
if (user != null && !user.Removed)
|
||||
{
|
||||
// used to spawn items directly into the deconstructor
|
||||
var itemContainer = new AbilityItemPrefabItem(item, targetItem.Prefab);
|
||||
user.CheckTalents(AbilityEffectType.OnItemDeconstructedInventory, itemContainer);
|
||||
var itemDeconstructedInventory = new AbilityItemDeconstructedInventory(targetItem.Prefab, item);
|
||||
user.CheckTalents(AbilityEffectType.OnItemDeconstructedInventory, itemDeconstructedInventory);
|
||||
}
|
||||
|
||||
int amount = (int)amountMultiplier;
|
||||
@@ -333,7 +333,7 @@ namespace Barotrauma.Items.Components
|
||||
for (int i = 0; i < outputContainer.Capacity; i++)
|
||||
{
|
||||
var containedItem = outputContainer.Inventory.GetItemAt(i);
|
||||
if (containedItem?.OwnInventory != null && containedItem.OwnInventory.TryPutItem(item, user: null))
|
||||
if (containedItem?.OwnInventory != null && containedItem.GetComponent<GeneticMaterial>() == null && containedItem.OwnInventory.TryPutItem(item, user: null))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -454,4 +454,26 @@ namespace Barotrauma.Items.Components
|
||||
public Character Character { get; set; }
|
||||
}
|
||||
|
||||
class AbilityItemCreationMultiplier : AbilityObject, IAbilityValue, IAbilityItemPrefab
|
||||
{
|
||||
public AbilityItemCreationMultiplier(ItemPrefab itemPrefab, float itemAmountMultiplier)
|
||||
{
|
||||
ItemPrefab = itemPrefab;
|
||||
Value = itemAmountMultiplier;
|
||||
}
|
||||
public ItemPrefab ItemPrefab { get; set; }
|
||||
public float Value { get; set; }
|
||||
}
|
||||
|
||||
class AbilityItemDeconstructedInventory : AbilityObject, IAbilityItem, IAbilityItemPrefab
|
||||
{
|
||||
public AbilityItemDeconstructedInventory(ItemPrefab itemPrefab, Item item)
|
||||
{
|
||||
ItemPrefab = itemPrefab;
|
||||
Item = item;
|
||||
}
|
||||
public ItemPrefab ItemPrefab { get; set; }
|
||||
public Item Item { get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -179,8 +179,6 @@ namespace Barotrauma.Items.Components
|
||||
if (selectedItem == null) { return; }
|
||||
if (!outputContainer.Inventory.CanBePut(selectedItem.TargetItem, selectedItem.OutCondition * selectedItem.TargetItem.Health)) { return; }
|
||||
|
||||
RefreshAvailableIngredients();
|
||||
|
||||
#if CLIENT
|
||||
itemList.Enabled = false;
|
||||
activateButton.Text = TextManager.Get("FabricatorCancel");
|
||||
@@ -189,7 +187,13 @@ namespace Barotrauma.Items.Components
|
||||
IsActive = true;
|
||||
this.user = user;
|
||||
fabricatedItem = selectedItem;
|
||||
MoveIngredientsToInputContainer(selectedItem);
|
||||
RefreshAvailableIngredients();
|
||||
|
||||
bool isClient = GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient;
|
||||
if (!isClient)
|
||||
{
|
||||
MoveIngredientsToInputContainer(selectedItem);
|
||||
}
|
||||
|
||||
requiredTime = GetRequiredTime(fabricatedItem, user);
|
||||
timeUntilReady = requiredTime;
|
||||
@@ -230,21 +234,19 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
|
||||
if (fabricatedItem == null) { return; }
|
||||
fabricatedItem = null;
|
||||
|
||||
#if CLIENT
|
||||
#if SERVER
|
||||
if (user != null)
|
||||
{
|
||||
GameServer.Log(GameServer.CharacterLogName(user) + " cancelled the fabrication of " + fabricatedItem.DisplayName + " in " + item.Name, ServerLog.MessageType.ItemInteraction);
|
||||
}
|
||||
#elif CLIENT
|
||||
itemList.Enabled = true;
|
||||
if (activateButton != null)
|
||||
{
|
||||
activateButton.Text = TextManager.Get("FabricatorCreate");
|
||||
}
|
||||
#endif
|
||||
#if SERVER
|
||||
if (user != null)
|
||||
{
|
||||
GameServer.Log(GameServer.CharacterLogName(user) + " cancelled the fabrication of " + fabricatedItem.DisplayName + " in " + item.Name, ServerLog.MessageType.ItemInteraction);
|
||||
}
|
||||
#endif
|
||||
fabricatedItem = null;
|
||||
}
|
||||
|
||||
public override void Update(float deltaTime, Camera cam)
|
||||
@@ -256,15 +258,20 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
refreshIngredientsTimer -= deltaTime;
|
||||
|
||||
if (fabricatedItem == null || !CanBeFabricated(fabricatedItem, availableIngredients, user))
|
||||
bool isClient = GameMain.NetworkMember?.IsClient ?? false;
|
||||
|
||||
if (!isClient)
|
||||
{
|
||||
CancelFabricating();
|
||||
return;
|
||||
if (fabricatedItem == null || !CanBeFabricated(fabricatedItem, availableIngredients, user))
|
||||
{
|
||||
CancelFabricating();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
progressState = fabricatedItem == null ? 0.0f : (requiredTime - timeUntilReady) / requiredTime;
|
||||
|
||||
if (GameMain.NetworkMember?.IsClient ?? false)
|
||||
if (isClient)
|
||||
{
|
||||
hasPower = State != FabricatorState.Paused;
|
||||
if (!hasPower)
|
||||
@@ -365,28 +372,29 @@ namespace Barotrauma.Items.Components
|
||||
availableItems.Remove(availableItem);
|
||||
Entity.Spawner.AddToRemoveQueue(availableItem);
|
||||
inputContainer.Inventory.RemoveItem(availableItem);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
int amountFittingContainer = outputContainer.Inventory.HowManyCanBePut(fabricatedItem.TargetItem, fabricatedItem.OutCondition * fabricatedItem.TargetItem.Health);
|
||||
|
||||
var fabricationValueItem = new AbilityValueItem(fabricatedItem.Amount, fabricatedItem.TargetItem);
|
||||
var fabricationitemAmount = new AbilityFabricationItemAmount(fabricatedItem.TargetItem, fabricatedItem.Amount);
|
||||
|
||||
int quality = 0;
|
||||
if (user?.Info != null)
|
||||
{
|
||||
foreach (Character character in Character.GetFriendlyCrew(user))
|
||||
{
|
||||
character.CheckTalents(AbilityEffectType.OnAllyItemFabricatedAmount, fabricationValueItem);
|
||||
character.CheckTalents(AbilityEffectType.OnAllyItemFabricatedAmount, fabricationitemAmount);
|
||||
}
|
||||
user.CheckTalents(AbilityEffectType.OnItemFabricatedAmount, fabricationValueItem);
|
||||
user.CheckTalents(AbilityEffectType.OnItemFabricatedAmount, fabricationitemAmount);
|
||||
|
||||
quality = GetFabricatedItemQuality(fabricatedItem, user);
|
||||
}
|
||||
|
||||
var tempUser = user;
|
||||
for (int i = 0; i < (int)fabricationValueItem.Value; i++)
|
||||
for (int i = 0; i < (int)fabricationitemAmount.Value; i++)
|
||||
{
|
||||
float outCondition = fabricatedItem.OutCondition;
|
||||
if (i < amountFittingContainer)
|
||||
@@ -433,7 +441,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
float userSkill = user.GetSkillLevel(skill.Identifier);
|
||||
float addedSkill = skill.Level * SkillSettings.Current.SkillIncreasePerFabricatorRequiredSkill / Math.Max(userSkill, 1.0f);
|
||||
var addedSkillValue = new AbilityValueString(addedSkill, skill.Identifier);
|
||||
var addedSkillValue = new AbilityFabricatorSkillGain(skill.Identifier, addedSkill);
|
||||
user.CheckTalents(AbilityEffectType.OnItemFabricationSkillGain, addedSkillValue);
|
||||
|
||||
user.Info.IncreaseSkillLevel(
|
||||
@@ -542,6 +550,11 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
private void RefreshAvailableIngredients()
|
||||
{
|
||||
Character user = this.user;
|
||||
#if CLIENT
|
||||
user ??= Character.Controlled;
|
||||
#endif
|
||||
|
||||
List<Item> itemList = new List<Item>();
|
||||
itemList.AddRange(inputContainer.Inventory.AllItems);
|
||||
foreach (MapEntity linkedTo in item.linkedTo)
|
||||
@@ -550,6 +563,10 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
var itemContainer = linkedItem.GetComponent<ItemContainer>();
|
||||
if (itemContainer == null) { continue; }
|
||||
if (user != null)
|
||||
{
|
||||
if (!itemContainer.HasRequiredItems(user, addMessage: false)) { continue; }
|
||||
}
|
||||
|
||||
var deconstructor = linkedItem.GetComponent<Deconstructor>();
|
||||
if (deconstructor != null)
|
||||
@@ -568,17 +585,10 @@ namespace Barotrauma.Items.Components
|
||||
itemList.AddRange(container.Inventory.AllItems);
|
||||
}
|
||||
}
|
||||
#if CLIENT
|
||||
if (Character.Controlled?.Inventory != null)
|
||||
{
|
||||
itemList.AddRange(Character.Controlled.Inventory.AllItems);
|
||||
}
|
||||
#else
|
||||
if (user?.Inventory != null)
|
||||
{
|
||||
itemList.AddRange(user.Inventory.AllItems);
|
||||
}
|
||||
#endif
|
||||
availableIngredients.Clear();
|
||||
foreach (Item item in itemList)
|
||||
{
|
||||
@@ -600,8 +610,6 @@ namespace Barotrauma.Items.Components
|
||||
//required ingredients that are already present in the input container
|
||||
List<Item> usedItems = new List<Item>();
|
||||
|
||||
bool isClient = GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient;
|
||||
|
||||
targetItem.RequiredItems.ForEach(requiredItem => {
|
||||
for (int i = 0; i < requiredItem.Amount; i++)
|
||||
{
|
||||
@@ -630,10 +638,11 @@ namespace Barotrauma.Items.Components
|
||||
if (!inputContainer.Inventory.CanBePut(availablePrefab))
|
||||
{
|
||||
var unneededItem = inputContainer.Inventory.AllItems.FirstOrDefault(it => !usedItems.Contains(it));
|
||||
unneededItem?.Drop(null, createNetworkEvent: !isClient);
|
||||
unneededItem?.Drop(null);
|
||||
}
|
||||
inputContainer.Inventory.TryPutItem(availablePrefab, user: null, createNetworkEvent: !isClient);
|
||||
inputContainer.Inventory.TryPutItem(availablePrefab, user: null);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -684,5 +693,26 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
savedFabricatedItem = null;
|
||||
}
|
||||
class AbilityFabricatorSkillGain : AbilityObject, IAbilityValue, IAbilitySkillIdentifier
|
||||
{
|
||||
public AbilityFabricatorSkillGain(string skillIdentifier, float skillAmount)
|
||||
{
|
||||
SkillIdentifier = skillIdentifier;
|
||||
Value = skillAmount;
|
||||
}
|
||||
public float Value { get; set; }
|
||||
public string SkillIdentifier { get; set; }
|
||||
}
|
||||
|
||||
class AbilityFabricationItemAmount : AbilityObject, IAbilityValue, IAbilityItemPrefab
|
||||
{
|
||||
public AbilityFabricationItemAmount(ItemPrefab itemPrefab, float itemAmount)
|
||||
{
|
||||
ItemPrefab = itemPrefab;
|
||||
Value = itemAmount;
|
||||
}
|
||||
public float Value { get; set; }
|
||||
public ItemPrefab ItemPrefab { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,15 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
public float CurrentBrokenVolume
|
||||
{
|
||||
get
|
||||
{
|
||||
if (item.ConditionPercentage > 10.0f || !IsActive) { return 0.0f; }
|
||||
return (1.0f - item.ConditionPercentage / 10.0f) * 100.0f;
|
||||
}
|
||||
}
|
||||
|
||||
private float pumpSpeedLockTimer, isActiveLockTimer;
|
||||
|
||||
[Serialize(0.0f, true, description: "How fast the item is currently pumping water (-100 = full speed out, 100 = full speed in). Intended to be used by StatusEffect conditionals (setting this value in XML has no effect).")]
|
||||
@@ -72,6 +81,8 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
private const float TinkeringSpeedIncrease = 4.0f;
|
||||
|
||||
public override bool UpdateWhenInactive => true;
|
||||
|
||||
public Pump(Item item, XElement element)
|
||||
: base(item, element)
|
||||
{
|
||||
@@ -82,11 +93,15 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public override void Update(float deltaTime, Camera cam)
|
||||
{
|
||||
pumpSpeedLockTimer -= deltaTime;
|
||||
isActiveLockTimer -= deltaTime;
|
||||
|
||||
if (!IsActive) { return; }
|
||||
|
||||
currFlow = 0.0f;
|
||||
|
||||
if (TargetLevel != null)
|
||||
{
|
||||
pumpSpeedLockTimer -= deltaTime;
|
||||
float hullPercentage = 0.0f;
|
||||
if (item.CurrentHull != null) { hullPercentage = (item.CurrentHull.WaterVolume / item.CurrentHull.Volume) * 100.0f; }
|
||||
FlowPercentage = ((float)TargetLevel - hullPercentage) * 10.0f;
|
||||
|
||||
@@ -76,7 +76,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
if (lastUser == value) { return; }
|
||||
lastUser = value;
|
||||
degreeOfSuccess = lastUser == null ? 0.0f : DegreeOfSuccess(lastUser);
|
||||
degreeOfSuccess = lastUser == null ? 0.0f : Math.Min(DegreeOfSuccess(lastUser), 1.0f);
|
||||
LastUserWasPlayer = lastUser.IsPlayer;
|
||||
}
|
||||
}
|
||||
@@ -601,7 +601,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
if (!shutDown)
|
||||
{
|
||||
float degreeOfSuccess = DegreeOfSuccess(character);
|
||||
float degreeOfSuccess = Math.Min(DegreeOfSuccess(character), 1.0f);
|
||||
float refuelLimit = 0.3f;
|
||||
//characters with insufficient skill levels don't refuel the reactor
|
||||
if (degreeOfSuccess > refuelLimit)
|
||||
|
||||
@@ -106,6 +106,13 @@ namespace Barotrauma.Items.Components
|
||||
set;
|
||||
}
|
||||
|
||||
[Editable, Serialize(false, false, description: "Should the sonar view be centered on the transducers or the submarine's center of mass. Only has an effect if UseTransducers is enabled.")]
|
||||
public bool CenterOnTransducers
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Editable, Serialize(false, false, description: "Does the sonar have mineral scanning mode. " +
|
||||
"Only available in-game when the Item has no Steering component.")]
|
||||
public bool HasMineralScanner { get; set; }
|
||||
@@ -318,7 +325,7 @@ namespace Barotrauma.Items.Components
|
||||
Vector2 transducerPosSum = Vector2.Zero;
|
||||
foreach (ConnectedTransducer transducer in connectedTransducers)
|
||||
{
|
||||
if (transducer.Transducer.Item.Submarine != null)
|
||||
if (transducer.Transducer.Item.Submarine != null && CenterOnTransducers)
|
||||
{
|
||||
return transducer.Transducer.Item.Submarine.WorldPosition;
|
||||
}
|
||||
|
||||
@@ -311,7 +311,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
|
||||
// override autopilot pathing while the AI rams, and go full speed ahead
|
||||
if (AIRamTimer > 0f)
|
||||
if (AIRamTimer > 0f && controlledSub != null)
|
||||
{
|
||||
AIRamTimer -= deltaTime;
|
||||
TargetVelocity = GetSteeringVelocity(AITacticalTarget, 0f);
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using Barotrauma.Networking;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Xml.Linq;
|
||||
|
||||
@@ -111,6 +110,17 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
[Serialize(false, true, description: "If true, the recharge speed (and power consumption) of the device goes up exponentially as the recharge rate is increased.")]
|
||||
public bool ExponentialRechargeSpeed { get; set; }
|
||||
|
||||
private float efficiency;
|
||||
[Editable(minValue: 0.0f, maxValue: 1.0f, decimals: 2), Serialize(0.95f, true, description: "The amount of power you can get out of a item relative to the amount of power that's put into it.")]
|
||||
public float Efficiency
|
||||
{
|
||||
get { return efficiency; }
|
||||
set { efficiency = MathHelper.Clamp(value, 0.0f, 1.0f); }
|
||||
}
|
||||
|
||||
public float RechargeRatio => RechargeSpeed / MaxRechargeSpeed;
|
||||
|
||||
public const float aiRechargeTargetRatio = 0.5f;
|
||||
@@ -170,7 +180,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
ApplyStatusEffects(ActionType.OnActive, deltaTime, null);
|
||||
}
|
||||
|
||||
|
||||
if (charge >= capacity)
|
||||
{
|
||||
//rechargeVoltage = 0.0f;
|
||||
@@ -181,13 +191,17 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
float missingCharge = capacity - charge;
|
||||
float targetRechargeSpeed = rechargeSpeed;
|
||||
if (ExponentialRechargeSpeed)
|
||||
{
|
||||
targetRechargeSpeed = MathF.Pow(rechargeSpeed / maxRechargeSpeed, 2) * maxRechargeSpeed;
|
||||
}
|
||||
if (missingCharge < 1.0f)
|
||||
{
|
||||
targetRechargeSpeed *= missingCharge;
|
||||
}
|
||||
currPowerConsumption = MathHelper.Lerp(currPowerConsumption, targetRechargeSpeed, 0.05f);
|
||||
Charge += currPowerConsumption * Math.Min(Voltage, 1.0f) / 3600.0f;
|
||||
}
|
||||
Charge += currPowerConsumption * Math.Min(Voltage, 1.0f) / 3600.0f * efficiency;
|
||||
}
|
||||
|
||||
if (charge <= 0.0f)
|
||||
{
|
||||
|
||||
@@ -10,6 +10,8 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
public List<Connection> PowerConnections { get; private set; }
|
||||
|
||||
private readonly HashSet<Connection> signalConnections = new HashSet<Connection>();
|
||||
|
||||
private readonly Dictionary<Connection, bool> connectionDirty = new Dictionary<Connection, bool>();
|
||||
|
||||
//a list of connections a given connection is connected to, either directly or via other power transfer components
|
||||
@@ -121,6 +123,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
partial void InitProjectSpecific(XElement element);
|
||||
|
||||
private static readonly HashSet<PowerTransfer> recipientsToRefresh = new HashSet<PowerTransfer>();
|
||||
public override void UpdateBroken(float deltaTime, Camera cam)
|
||||
{
|
||||
base.UpdateBroken(deltaTime, cam);
|
||||
@@ -132,7 +135,8 @@ namespace Barotrauma.Items.Components
|
||||
powerLoad = 0.0f;
|
||||
currPowerConsumption = 0.0f;
|
||||
SetAllConnectionsDirty();
|
||||
foreach (HashSet<Connection> recipientList in connectedRecipients.Values.ToList())
|
||||
recipientsToRefresh.Clear();
|
||||
foreach (HashSet<Connection> recipientList in connectedRecipients.Values)
|
||||
{
|
||||
foreach (Connection c in recipientList)
|
||||
{
|
||||
@@ -140,16 +144,26 @@ namespace Barotrauma.Items.Components
|
||||
var recipientPowerTransfer = c.Item.GetComponent<PowerTransfer>();
|
||||
if (recipientPowerTransfer != null)
|
||||
{
|
||||
recipientPowerTransfer.SetAllConnectionsDirty();
|
||||
recipientPowerTransfer.RefreshConnections();
|
||||
recipientsToRefresh.Add(recipientPowerTransfer);
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach (PowerTransfer recipientPowerTransfer in recipientsToRefresh)
|
||||
{
|
||||
recipientPowerTransfer.SetAllConnectionsDirty();
|
||||
recipientPowerTransfer.RefreshConnections();
|
||||
}
|
||||
RefreshConnections();
|
||||
isBroken = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private int prevSentPowerValue;
|
||||
private string powerSignal;
|
||||
private int prevSentLoadValue;
|
||||
private string loadSignal;
|
||||
|
||||
public override void Update(float deltaTime, Camera cam)
|
||||
{
|
||||
RefreshConnections();
|
||||
@@ -172,6 +186,19 @@ namespace Barotrauma.Items.Components
|
||||
//if the item can't be fixed, don't allow it to break
|
||||
if (!item.Repairables.Any() || !CanBeOverloaded) { return; }
|
||||
|
||||
if (prevSentPowerValue != (int)-CurrPowerConsumption || powerSignal == null)
|
||||
{
|
||||
prevSentPowerValue = (int)Math.Round(-CurrPowerConsumption);
|
||||
powerSignal = prevSentPowerValue.ToString();
|
||||
}
|
||||
if (prevSentLoadValue != (int)powerLoad || loadSignal == null)
|
||||
{
|
||||
prevSentLoadValue = (int)Math.Round(powerLoad);
|
||||
loadSignal = prevSentLoadValue.ToString();
|
||||
}
|
||||
item.SendSignal(powerSignal, "power_value_out");
|
||||
item.SendSignal(loadSignal, "load_value_out");
|
||||
|
||||
float maxOverVoltage = Math.Max(OverloadVoltage, 1.0f);
|
||||
Overload = -currPowerConsumption > Math.Max(powerLoad, 200.0f) * maxOverVoltage;
|
||||
if (Overload && (GameMain.NetworkMember == null || GameMain.NetworkMember.IsServer))
|
||||
@@ -217,6 +244,7 @@ namespace Barotrauma.Items.Components
|
||||
return picker != null;
|
||||
}
|
||||
|
||||
private static readonly HashSet<Connection> tempConnected = new HashSet<Connection>();
|
||||
protected void RefreshConnections()
|
||||
{
|
||||
var connections = item.Connections;
|
||||
@@ -229,15 +257,15 @@ namespace Barotrauma.Items.Components
|
||||
else if (!connectionDirty[c])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
//find all connections that are connected to this one (directly or via another PowerTransfer)
|
||||
HashSet<Connection> connected = new HashSet<Connection>();
|
||||
tempConnected.Clear();
|
||||
if (item.Condition > 0.0f)
|
||||
{
|
||||
if (!connectedRecipients.ContainsKey(c))
|
||||
{
|
||||
connectedRecipients.Add(c, connected);
|
||||
connectedRecipients.Add(c, tempConnected);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -249,24 +277,22 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
connected.Add(c);
|
||||
GetConnected(c, connected);
|
||||
tempConnected.Add(c);
|
||||
GetConnected(c, tempConnected);
|
||||
}
|
||||
connectedRecipients[c] = connected;
|
||||
connectedRecipients[c] = tempConnected;
|
||||
|
||||
//go through all the PowerTransfers that we're connected to and set their connections to match the ones we just calculated
|
||||
//(no need to go through the recursive GetConnected method again)
|
||||
foreach (Connection recipient in connected)
|
||||
foreach (Connection recipient in tempConnected)
|
||||
{
|
||||
if (recipient == c) { continue; }
|
||||
var recipientPowerTransfer = recipient.Item.GetComponent<PowerTransfer>();
|
||||
if (recipientPowerTransfer == null) continue;
|
||||
|
||||
if (recipientPowerTransfer == null) { continue; }
|
||||
if (!connectedRecipients.ContainsKey(recipient))
|
||||
{
|
||||
connectedRecipients.Add(recipient, connected);
|
||||
connectedRecipients.Add(recipient, tempConnected);
|
||||
}
|
||||
|
||||
recipientPowerTransfer.connectedRecipients[recipient] = connected;
|
||||
recipientPowerTransfer.connectionDirty[recipient] = false;
|
||||
}
|
||||
}
|
||||
@@ -296,7 +322,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public void SetAllConnectionsDirty()
|
||||
{
|
||||
if (item.Connections == null) return;
|
||||
if (item.Connections == null) { return; }
|
||||
foreach (Connection c in item.Connections)
|
||||
{
|
||||
connectionDirty[c] = true;
|
||||
@@ -321,6 +347,14 @@ namespace Barotrauma.Items.Components
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (Connection c in connections)
|
||||
{
|
||||
if (c.Name.Length > 5 && c.Name.Substring(0, 6) == "signal")
|
||||
{
|
||||
signalConnections.Add(c);
|
||||
}
|
||||
}
|
||||
|
||||
if (!(this is RelayComponent))
|
||||
{
|
||||
if (PowerConnections.Any(p => !p.IsOutput) && PowerConnections.Any(p => p.IsOutput))
|
||||
@@ -356,29 +390,30 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
if (item.Condition <= 0.0f || connection.IsPower) { return; }
|
||||
if (!connectedRecipients.ContainsKey(connection)) { return; }
|
||||
if (!signalConnections.Contains(connection)) { return; }
|
||||
|
||||
if (connection.Name.Length > 5 && connection.Name.Substring(0, 6) == "signal")
|
||||
foreach (Connection recipient in connectedRecipients[connection])
|
||||
{
|
||||
foreach (Connection recipient in connectedRecipients[connection])
|
||||
if (recipient.Item == item || recipient.Item == signal.source) { continue; }
|
||||
|
||||
signal.source?.LastSentSignalRecipients.Add(recipient);
|
||||
|
||||
foreach (ItemComponent ic in recipient.Item.Components)
|
||||
{
|
||||
if (recipient.Item == item || recipient.Item == signal.source) { continue; }
|
||||
|
||||
signal.source?.LastSentSignalRecipients.Add(recipient);
|
||||
|
||||
foreach (ItemComponent ic in recipient.Item.Components)
|
||||
{
|
||||
//other junction boxes don't need to receive the signal in the pass-through signal connections
|
||||
//because we relay it straight to the connected items without going through the whole chain of junction boxes
|
||||
if (ic is PowerTransfer && !(ic is RelayComponent)) { continue; }
|
||||
ic.ReceiveSignal(signal, recipient);
|
||||
}
|
||||
//other junction boxes don't need to receive the signal in the pass-through signal connections
|
||||
//because we relay it straight to the connected items without going through the whole chain of junction boxes
|
||||
if (ic is PowerTransfer && !(ic is RelayComponent)) { continue; }
|
||||
ic.ReceiveSignal(signal, recipient);
|
||||
}
|
||||
|
||||
if (recipient.Effects != null && signal.value != "0" && !string.IsNullOrEmpty(signal.value))
|
||||
{
|
||||
foreach (StatusEffect effect in recipient.Effects)
|
||||
{
|
||||
recipient.Item.ApplyStatusEffect(effect, ActionType.OnUse, 1.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void RemoveComponentSpecific()
|
||||
|
||||
@@ -272,7 +272,7 @@ namespace Barotrauma.Items.Components
|
||||
powered.voltage = -pt1.CurrPowerConsumption / Math.Max(pt1.PowerLoad, 1.0f);
|
||||
continue;
|
||||
}
|
||||
if (powered.powerConsumption <= 0.0f && !(powered is PowerContainer))
|
||||
if ((powered.powerConsumption <= 0.0f || (powered.Item.GetComponent<Repairable>() is Repairable repairable && repairable.IsTinkering && repairable.TinkeringPowersDevices)) && !(powered is PowerContainer))
|
||||
{
|
||||
powered.voltage = 1.0f;
|
||||
continue;
|
||||
|
||||
@@ -268,7 +268,8 @@ namespace Barotrauma.Items.Components
|
||||
IgnoredBodies = ignoredBodies;
|
||||
Vector2 projectilePos = weaponPos;
|
||||
//make sure there's no obstacles between the base of the weapon (or the shoulder of the character) and the end of the barrel
|
||||
if (Submarine.PickBody(weaponPos, spawnPos, IgnoredBodies, Physics.CollisionWall | Physics.CollisionLevel | Physics.CollisionItemBlocking) == null)
|
||||
if (Submarine.PickBody(weaponPos, spawnPos, IgnoredBodies, Physics.CollisionWall | Physics.CollisionLevel | Physics.CollisionItemBlocking,
|
||||
customPredicate: (Fixture f) => { return !IgnoredBodies.Contains(f.Body); }) == null)
|
||||
{
|
||||
//no obstacles -> we can spawn the projectile at the barrel
|
||||
projectilePos = spawnPos;
|
||||
@@ -359,7 +360,7 @@ namespace Barotrauma.Items.Components
|
||||
item.body.FarseerBody.IsBullet = true;
|
||||
|
||||
item.body.CollisionCategories = Physics.CollisionProjectile;
|
||||
item.body.CollidesWith = Physics.CollisionCharacter | Physics.CollisionWall | Physics.CollisionLevel;
|
||||
item.body.CollidesWith = Physics.CollisionCharacter | Physics.CollisionWall | Physics.CollisionLevel | Physics.CollisionItemBlocking;
|
||||
|
||||
IsActive = true;
|
||||
|
||||
|
||||
@@ -16,6 +16,9 @@ namespace Barotrauma.Items.Components
|
||||
private float deteriorationTimer;
|
||||
private float deteriorateAlwaysResetTimer;
|
||||
|
||||
private int prevSentConditionValue;
|
||||
private string conditionSignal;
|
||||
|
||||
bool wasBroken;
|
||||
bool wasGoodCondition;
|
||||
|
||||
@@ -113,6 +116,9 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public float TinkeringStrength => tinkeringStrength;
|
||||
|
||||
private bool tinkeringPowersDevices;
|
||||
public bool TinkeringPowersDevices => tinkeringPowersDevices;
|
||||
|
||||
public bool IsBelowRepairThreshold => item.ConditionPercentage <= RepairThreshold;
|
||||
public bool IsBelowRepairIconThreshold => item.ConditionPercentage <= RepairThreshold / 2;
|
||||
|
||||
@@ -266,6 +272,7 @@ namespace Barotrauma.Items.Components
|
||||
if (action == FixActions.Tinker)
|
||||
{
|
||||
tinkeringStrength = 1f + CurrentFixer.GetStatValue(StatTypes.TinkeringStrength);
|
||||
tinkeringPowersDevices = CurrentFixer.HasAbilityFlag(AbilityFlags.TinkeringPowersDevices);
|
||||
|
||||
if (character.HasAbilityFlag(AbilityFlags.CanTinkerFabricatorsAndDeconstructors) && item.GetComponent<Deconstructor>() != null || item.GetComponent<Fabricator>() != null)
|
||||
{
|
||||
@@ -346,7 +353,13 @@ namespace Barotrauma.Items.Components
|
||||
UpdateProjSpecific(deltaTime);
|
||||
IsTinkering = false;
|
||||
|
||||
item.SendSignal($"{(int) item.ConditionPercentage}", "condition_out");
|
||||
if (prevSentConditionValue != (int)item.ConditionPercentage || conditionSignal == null)
|
||||
{
|
||||
prevSentConditionValue = (int)item.ConditionPercentage;
|
||||
conditionSignal = prevSentConditionValue.ToString();
|
||||
}
|
||||
|
||||
item.SendSignal(conditionSignal, "condition_out");
|
||||
|
||||
if (CurrentFixer == null)
|
||||
{
|
||||
|
||||
@@ -12,6 +12,8 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
//the output is sent if both inputs have received a signal within the timeframe
|
||||
protected float timeFrame;
|
||||
|
||||
protected readonly Character[] signalSender = new Character[2];
|
||||
|
||||
[InGameEditable(DecimalCount = 2), Serialize(0.0f, true, description: "The item sends the output if both inputs have received a non-zero signal within the timeframe. If set to 0, the inputs must receive a signal at the same time.", alwaysUseInstanceValues: true)]
|
||||
public float TimeFrame
|
||||
@@ -80,14 +82,14 @@ namespace Barotrauma.Items.Components
|
||||
bool sendOutput = true;
|
||||
for (int i = 0; i < timeSinceReceived.Length; i++)
|
||||
{
|
||||
if (timeSinceReceived[i] > timeFrame) sendOutput = false;
|
||||
if (timeSinceReceived[i] > timeFrame) { sendOutput = false; }
|
||||
timeSinceReceived[i] += deltaTime;
|
||||
}
|
||||
|
||||
string signalOut = sendOutput ? output : falseOutput;
|
||||
if (string.IsNullOrEmpty(signalOut)) return;
|
||||
if (string.IsNullOrEmpty(signalOut)) { return; }
|
||||
|
||||
item.SendSignal(signalOut, "signal_out");
|
||||
item.SendSignal(new Signal(signalOut, sender: signalSender[0] ?? signalSender[1]), "signal_out");
|
||||
}
|
||||
|
||||
public override void ReceiveSignal(Signal signal, Connection connection)
|
||||
@@ -95,12 +97,14 @@ namespace Barotrauma.Items.Components
|
||||
switch (connection.Name)
|
||||
{
|
||||
case "signal_in1":
|
||||
if (signal.value == "0") return;
|
||||
if (signal.value == "0") { return; }
|
||||
timeSinceReceived[0] = 0.0f;
|
||||
signalSender[0] = signal.sender;
|
||||
break;
|
||||
case "signal_in2":
|
||||
if (signal.value == "0") return;
|
||||
if (signal.value == "0") { return; }
|
||||
timeSinceReceived[1] = 0.0f;
|
||||
signalSender[1] = signal.sender;
|
||||
break;
|
||||
case "set_output":
|
||||
output = signal.value;
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace Barotrauma.Items.Components
|
||||
private HashSet<ItemPrefab> ActivatingItemPrefabs { get; set; } = new HashSet<ItemPrefab>();
|
||||
|
||||
|
||||
private bool AllowUsingButtons => ActivatingItemPrefabs.None() || Container.Inventory.AllItems.Any(i => i != null && ActivatingItemPrefabs.Any(p => p == i.Prefab));
|
||||
private bool AllowUsingButtons => ActivatingItemPrefabs.None() || (Container != null && Container.Inventory.AllItems.Any(i => i != null && ActivatingItemPrefabs.Any(p => p == i.Prefab)));
|
||||
|
||||
public ButtonTerminal(Item item, XElement element) : base(item, element)
|
||||
{
|
||||
@@ -101,12 +101,12 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
partial void OnItemLoadedProjSpecific();
|
||||
|
||||
private bool SendSignal(int signalIndex, bool isServerMessage = false)
|
||||
private bool SendSignal(int signalIndex, Character sender, bool isServerMessage = false)
|
||||
{
|
||||
if (!isServerMessage && !AllowUsingButtons) { return false; }
|
||||
string signal = Signals[signalIndex];
|
||||
string connectionName = $"signal_out{signalIndex + 1}";
|
||||
item.SendSignal(signal, connectionName);
|
||||
item.SendSignal(new Signal(signal, sender: sender), connectionName);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
+15
-1
@@ -17,6 +17,12 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
[Editable, Serialize("", false)]
|
||||
public string Separator
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public ConcatComponent(Item item, XElement element)
|
||||
: base(item, element)
|
||||
@@ -25,7 +31,15 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
protected override string Calculate(string signal1, string signal2)
|
||||
{
|
||||
string output = signal1 + signal2;
|
||||
string output;
|
||||
if (string.IsNullOrEmpty(Separator))
|
||||
{
|
||||
output = signal1 + signal2;
|
||||
}
|
||||
else
|
||||
{
|
||||
output = signal1 + Separator + signal2;
|
||||
}
|
||||
return output.Length <= maxOutputLength ? output : output.Substring(0, MaxOutputLength);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace Barotrauma.Items.Components
|
||||
get { return wires; }
|
||||
}
|
||||
|
||||
private Item item;
|
||||
private readonly Item item;
|
||||
|
||||
public readonly bool IsOutput;
|
||||
|
||||
@@ -142,7 +142,6 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
IsPower = Name == "power_in" || Name == "power" || Name == "power_out";
|
||||
|
||||
Effects = new List<StatusEffect>();
|
||||
|
||||
wireId = new ushort[MaxWires];
|
||||
|
||||
@@ -164,6 +163,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
break;
|
||||
case "statuseffect":
|
||||
Effects ??= new List<StatusEffect>();
|
||||
Effects.Add(StatusEffect.Load(subElement, item.Name + ", connection " + Name));
|
||||
break;
|
||||
}
|
||||
@@ -272,7 +272,7 @@ namespace Barotrauma.Items.Components
|
||||
ic.ReceiveSignal(signal, connection);
|
||||
}
|
||||
|
||||
if (signal.value != "0")
|
||||
if (recipient.Effects != null && signal.value != "0" && !string.IsNullOrEmpty(signal.value))
|
||||
{
|
||||
foreach (StatusEffect effect in recipient.Effects)
|
||||
{
|
||||
|
||||
+13
-1
@@ -24,7 +24,19 @@ namespace Barotrauma.Items.Components
|
||||
/// </summary>
|
||||
public bool AlwaysAllowRewiring
|
||||
{
|
||||
get { return item.Submarine?.Info.Type == SubmarineType.BeaconStation; }
|
||||
get
|
||||
{
|
||||
if (item.Submarine == null) { return true; }
|
||||
switch (item.Submarine.Info.Type)
|
||||
{
|
||||
case SubmarineType.Wreck:
|
||||
case SubmarineType.BeaconStation:
|
||||
case SubmarineType.EnemySubmarine:
|
||||
case SubmarineType.Ruin:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
[Editable, Serialize(false, true, description: "Locked connection panels cannot be rewired in-game.", alwaysUseInstanceValues: true)]
|
||||
|
||||
@@ -301,7 +301,6 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public override void Update(float deltaTime, Camera cam)
|
||||
{
|
||||
UpdateProjSpecific();
|
||||
foreach (CustomInterfaceElement ciElement in customInterfaceElementList)
|
||||
{
|
||||
if (!ciElement.ContinuousSignal) { continue; }
|
||||
@@ -318,8 +317,6 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
partial void UpdateProjSpecific();
|
||||
|
||||
public override XElement Save(XElement parentElement)
|
||||
{
|
||||
labels = customInterfaceElementList.Select(ci => ci.Label).ToArray();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Xml.Linq;
|
||||
using Microsoft.Xna.Framework;
|
||||
namespace Barotrauma.Items.Components
|
||||
@@ -24,7 +25,7 @@ namespace Barotrauma.Items.Components
|
||||
private int signalQueueSize;
|
||||
private int delayTicks;
|
||||
|
||||
private readonly Queue<DelayedSignal> signalQueue;
|
||||
private readonly Queue<DelayedSignal> signalQueue = new Queue<DelayedSignal>();
|
||||
|
||||
private DelayedSignal prevQueuedSignal;
|
||||
|
||||
@@ -39,6 +40,7 @@ namespace Barotrauma.Items.Components
|
||||
delay = value;
|
||||
delayTicks = (int)(delay / Timing.Step);
|
||||
signalQueueSize = Math.Max(delayTicks, 1) * 2;
|
||||
signalQueue.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,7 +61,6 @@ namespace Barotrauma.Items.Components
|
||||
public DelayComponent(Item item, XElement element)
|
||||
: base (item, element)
|
||||
{
|
||||
signalQueue = new Queue<DelayedSignal>();
|
||||
IsActive = true;
|
||||
}
|
||||
|
||||
@@ -74,7 +75,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
var signalOut = signalQueue.Peek();
|
||||
signalOut.SendDuration -= 1;
|
||||
item.SendSignal(new Signal(signalOut.Signal.value, strength: signalOut.Signal.strength), "signal_out");
|
||||
item.SendSignal(new Signal(signalOut.Signal.value, sender: signalOut.Signal.sender, strength: signalOut.Signal.strength), "signal_out");
|
||||
if (signalOut.SendDuration <= 0)
|
||||
{
|
||||
signalQueue.Dequeue();
|
||||
@@ -115,7 +116,7 @@ namespace Barotrauma.Items.Components
|
||||
signalQueue.Enqueue(prevQueuedSignal);
|
||||
break;
|
||||
case "set_delay":
|
||||
if (float.TryParse(signal.value, out float newDelay))
|
||||
if (float.TryParse(signal.value, NumberStyles.Any, CultureInfo.InvariantCulture, out float newDelay))
|
||||
{
|
||||
newDelay = MathHelper.Clamp(newDelay, 0, 60);
|
||||
if (signalQueue.Count > 0 && newDelay != Delay)
|
||||
|
||||
@@ -12,6 +12,8 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
protected string[] receivedSignal;
|
||||
|
||||
private readonly Character[] signalSender = new Character[2];
|
||||
|
||||
//the output is sent if both inputs have received a signal within the timeframe
|
||||
protected float timeFrame;
|
||||
|
||||
@@ -90,9 +92,8 @@ namespace Barotrauma.Items.Components
|
||||
if (sendOutput)
|
||||
{
|
||||
string signalOut = receivedSignal[0] == receivedSignal[1] ? output : falseOutput;
|
||||
if (string.IsNullOrEmpty(signalOut)) return;
|
||||
|
||||
item.SendSignal(signalOut, "signal_out");
|
||||
if (string.IsNullOrEmpty(signalOut)) { return; }
|
||||
item.SendSignal(new Signal(signalOut, sender: signalSender[0] ?? signalSender[1]), "signal_out");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,10 +104,15 @@ namespace Barotrauma.Items.Components
|
||||
case "signal_in1":
|
||||
receivedSignal[0] = signal.value;
|
||||
timeSinceReceived[0] = 0.0f;
|
||||
signalSender[0] = signal.sender;
|
||||
break;
|
||||
case "signal_in2":
|
||||
receivedSignal[1] = signal.value;
|
||||
timeSinceReceived[1] = 0.0f;
|
||||
signalSender[1] = signal.sender;
|
||||
break;
|
||||
case "set_output":
|
||||
output = signal.value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
+16
-4
@@ -32,10 +32,22 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
|
||||
public override void ReceiveSignal(Signal signal, Connection connection)
|
||||
{
|
||||
base.ReceiveSignal(signal, connection);
|
||||
float.TryParse(receivedSignal[0], NumberStyles.Float, CultureInfo.InvariantCulture, out val1);
|
||||
float.TryParse(receivedSignal[1], NumberStyles.Float, CultureInfo.InvariantCulture, out val2);
|
||||
{
|
||||
//base.ReceiveSignal(signal, connection);
|
||||
switch (connection.Name)
|
||||
{
|
||||
case "signal_in1":
|
||||
float.TryParse(signal.value, NumberStyles.Float, CultureInfo.InvariantCulture, out val1);
|
||||
timeSinceReceived[0] = 0.0f;
|
||||
break;
|
||||
case "signal_in2":
|
||||
float.TryParse(signal.value, NumberStyles.Float, CultureInfo.InvariantCulture, out val2);
|
||||
timeSinceReceived[1] = 0.0f;
|
||||
break;
|
||||
case "set_output":
|
||||
output = signal.value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace Barotrauma.Items.Components
|
||||
set
|
||||
{
|
||||
rotation = value;
|
||||
SetLightSourceTransform();
|
||||
SetLightSourceTransformProjSpecific();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -256,7 +256,7 @@ namespace Barotrauma.Items.Components
|
||||
return;
|
||||
}
|
||||
|
||||
SetLightSourceTransform();
|
||||
SetLightSourceTransformProjSpecific();
|
||||
|
||||
PhysicsBody body = ParentBody ?? item.body;
|
||||
if (body != null && !body.Enabled)
|
||||
@@ -338,7 +338,11 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
partial void SetLightSourceState(bool enabled, float brightness);
|
||||
|
||||
partial void SetLightSourceTransform();
|
||||
public void SetLightSourceTransform()
|
||||
{
|
||||
SetLightSourceTransformProjSpecific();
|
||||
}
|
||||
|
||||
partial void SetLightSourceTransformProjSpecific();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,6 +74,17 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
public Vector2 TransformedDetectOffset
|
||||
{
|
||||
get
|
||||
{
|
||||
Vector2 transformedDetectOffset = detectOffset;
|
||||
if (item.FlippedX) { transformedDetectOffset.X = -transformedDetectOffset.X; }
|
||||
if (item.FlippedY) { transformedDetectOffset.Y = -transformedDetectOffset.Y; }
|
||||
return transformedDetectOffset;
|
||||
}
|
||||
}
|
||||
|
||||
[Editable(MinValueFloat = 0.1f, MaxValueFloat = 100.0f, DecimalCount = 2), Serialize(0.1f, true, description: "How often the sensor checks if there's something moving near it. Higher values are better for performance.", alwaysUseInstanceValues: true)]
|
||||
public float UpdateInterval
|
||||
{
|
||||
@@ -184,15 +195,15 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
Vector2 detectPos = item.WorldPosition + detectOffset;
|
||||
Vector2 detectPos = item.WorldPosition + TransformedDetectOffset;
|
||||
Rectangle detectRect = new Rectangle((int)(detectPos.X - rangeX), (int)(detectPos.Y - rangeY), (int)(rangeX * 2), (int)(rangeY * 2));
|
||||
float broadRangeX = Math.Max(rangeX * 2, 500);
|
||||
float broadRangeY = Math.Max(rangeY * 2, 500);
|
||||
|
||||
if (item.CurrentHull == null && item.Submarine != null && Level.Loaded != null &&
|
||||
if (item.CurrentHull == null && item.Submarine != null &&
|
||||
(Target == TargetType.Wall || Target == TargetType.Any))
|
||||
{
|
||||
if (Math.Abs(item.Submarine.Velocity.X) > MinimumVelocity || Math.Abs(item.Submarine.Velocity.Y) > MinimumVelocity)
|
||||
if (Level.Loaded != null && (Math.Abs(item.Submarine.Velocity.X) > MinimumVelocity || Math.Abs(item.Submarine.Velocity.Y) > MinimumVelocity))
|
||||
{
|
||||
var cells = Level.Loaded.GetCells(item.WorldPosition, 1);
|
||||
foreach (var cell in cells)
|
||||
@@ -268,7 +279,7 @@ namespace Barotrauma.Items.Components
|
||||
foreach (Limb limb in c.AnimController.Limbs)
|
||||
{
|
||||
if (limb.IsSevered) { continue; }
|
||||
if (limb.LinearVelocity.LengthSquared() <= MinimumVelocity * MinimumVelocity) { continue; }
|
||||
if (limb.LinearVelocity.LengthSquared() < MinimumVelocity * MinimumVelocity) { continue; }
|
||||
if (MathUtils.CircleIntersectsRectangle(limb.WorldPosition, ConvertUnits.ToDisplayUnits(limb.body.GetMaxExtent()), detectRect))
|
||||
{
|
||||
MotionDetected = true;
|
||||
@@ -276,23 +287,12 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void FlipX(bool relativeToSub)
|
||||
{
|
||||
detectOffset.X = -detectOffset.X;
|
||||
}
|
||||
public override void FlipY(bool relativeToSub)
|
||||
{
|
||||
detectOffset.Y = -detectOffset.Y;
|
||||
}
|
||||
public override XElement Save(XElement parentElement)
|
||||
{
|
||||
Vector2 prevDetectOffset = detectOffset;
|
||||
//undo flipping before saving
|
||||
if (item.FlippedX) { detectOffset.X = -detectOffset.X; }
|
||||
if (item.FlippedY) { detectOffset.Y = -detectOffset.Y; }
|
||||
XElement element = base.Save(parentElement);
|
||||
detectOffset = prevDetectOffset;
|
||||
return element;
|
||||
|
||||
@@ -15,14 +15,14 @@ namespace Barotrauma.Items.Components
|
||||
bool sendOutput = false;
|
||||
for (int i = 0; i < timeSinceReceived.Length; i++)
|
||||
{
|
||||
if (timeSinceReceived[i] <= timeFrame) sendOutput = true;
|
||||
if (timeSinceReceived[i] <= timeFrame) { sendOutput = true; }
|
||||
timeSinceReceived[i] += deltaTime;
|
||||
}
|
||||
|
||||
string signalOut = sendOutput ? output : falseOutput;
|
||||
if (string.IsNullOrEmpty(signalOut)) return;
|
||||
if (string.IsNullOrEmpty(signalOut)) { return; }
|
||||
|
||||
item.SendSignal(signalOut, "signal_out");
|
||||
item.SendSignal(new Signal(signalOut, sender: signalSender[0] ?? signalSender[1]), "signal_out");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,9 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
class OxygenDetector : ItemComponent
|
||||
{
|
||||
private int prevSentOxygenValue;
|
||||
private string oxygenSignal;
|
||||
|
||||
public OxygenDetector(Item item, XElement element)
|
||||
: base (item, element)
|
||||
{
|
||||
@@ -12,9 +15,15 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public override void Update(float deltaTime, Camera cam)
|
||||
{
|
||||
if (item.CurrentHull == null) return;
|
||||
if (item.CurrentHull == null) { return; }
|
||||
|
||||
item.SendSignal(((int)item.CurrentHull.OxygenPercentage).ToString(), "signal_out");
|
||||
if (prevSentOxygenValue != (int)item.CurrentHull.OxygenPercentage || oxygenSignal == null)
|
||||
{
|
||||
prevSentOxygenValue = (int)item.CurrentHull.OxygenPercentage;
|
||||
oxygenSignal = prevSentOxygenValue.ToString();
|
||||
}
|
||||
|
||||
item.SendSignal(oxygenSignal, "signal_out");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -9,6 +9,9 @@ namespace Barotrauma.Items.Components
|
||||
//how often the detector can switch from state to another
|
||||
const float StateSwitchInterval = 1.0f;
|
||||
|
||||
private int prevSentWaterPercentageValue;
|
||||
private string waterPercentageSignal;
|
||||
|
||||
private bool isInWater;
|
||||
private float stateSwitchDelay;
|
||||
|
||||
@@ -106,7 +109,12 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
waterPercentage = MathHelper.Clamp((int)Math.Ceiling(item.CurrentHull.WaterPercentage), 0, 100);
|
||||
}
|
||||
item.SendSignal(waterPercentage.ToString(), "water_%");
|
||||
if (prevSentWaterPercentageValue != waterPercentage || waterPercentageSignal == null)
|
||||
{
|
||||
prevSentWaterPercentageValue = waterPercentage;
|
||||
waterPercentageSignal = prevSentWaterPercentageValue.ToString();
|
||||
}
|
||||
item.SendSignal(waterPercentageSignal, "water_%");
|
||||
}
|
||||
string highPressureOut = (item.CurrentHull == null || item.CurrentHull.LethalPressure > 5.0f) ? "1" : "0";
|
||||
item.SendSignal(highPressureOut, "high_pressure");
|
||||
|
||||
@@ -24,6 +24,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
private readonly int[] channelMemory = new int[ChannelMemorySize];
|
||||
|
||||
private Connection signalInConnection;
|
||||
private Connection signalOutConnection;
|
||||
|
||||
[Serialize(CharacterTeamType.None, true, description: "WiFi components can only communicate with components that have the same Team ID.", alwaysUseInstanceValues: true)]
|
||||
@@ -98,6 +99,7 @@ namespace Barotrauma.Items.Components
|
||||
if (item.Connections != null)
|
||||
{
|
||||
signalOutConnection = item.Connections.Find(c => c.Name == "signal_out");
|
||||
signalInConnection = item.Connections.Find(c => c.Name == "signal_in");
|
||||
}
|
||||
if (channelMemory.All(m => m == 0))
|
||||
{
|
||||
@@ -207,6 +209,18 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
if (wifiComp.signalOutConnection != null)
|
||||
{
|
||||
if (signal.source != null && wifiComp.signalInConnection != null)
|
||||
{
|
||||
if (signal.source.LastSentSignalRecipients.Contains(wifiComp.signalInConnection))
|
||||
{
|
||||
//signal already passed through this wifi component -> stop here to prevent an infinite loop
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
signal.source.LastSentSignalRecipients.Add(wifiComp.signalInConnection);
|
||||
}
|
||||
}
|
||||
wifiComp.item.SendSignal(s, wifiComp.signalOutConnection);
|
||||
}
|
||||
|
||||
|
||||
@@ -503,13 +503,6 @@ namespace Barotrauma.Items.Components
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void Move(Vector2 amount)
|
||||
{
|
||||
#if CLIENT
|
||||
if (item.IsSelected) MoveNodes(amount);
|
||||
#endif
|
||||
}
|
||||
|
||||
public List<Vector2> GetNodes()
|
||||
{
|
||||
return new List<Vector2>(nodes);
|
||||
|
||||
@@ -15,14 +15,14 @@ namespace Barotrauma.Items.Components
|
||||
int sendOutput = 0;
|
||||
for (int i = 0; i < timeSinceReceived.Length; i++)
|
||||
{
|
||||
if (timeSinceReceived[i] <= timeFrame) sendOutput += 1;
|
||||
if (timeSinceReceived[i] <= timeFrame) { sendOutput += 1; }
|
||||
timeSinceReceived[i] += deltaTime;
|
||||
}
|
||||
|
||||
string signalOut = sendOutput == 1 ? output : falseOutput;
|
||||
if (string.IsNullOrEmpty(signalOut)) return;
|
||||
if (string.IsNullOrEmpty(signalOut)) { return; }
|
||||
|
||||
item.SendSignal(signalOut, "signal_out");
|
||||
item.SendSignal(new Signal(signalOut, sender: signalSender[0] ?? signalSender[1]), "signal_out");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,8 +141,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public override void Update(float deltaTime, Camera cam)
|
||||
{
|
||||
triggerers.RemoveWhere(t => t.Removed);
|
||||
LevelTrigger.RemoveDistantTriggerers(PhysicsBody, triggerers, item.WorldPosition);
|
||||
LevelTrigger.RemoveInActiveTriggerers(PhysicsBody, triggerers);
|
||||
|
||||
if (triggerOnce)
|
||||
{
|
||||
|
||||
@@ -333,6 +333,7 @@ namespace Barotrauma.Items.Components
|
||||
FindLightComponent();
|
||||
if (loadedRotationLimits.HasValue) { RotationLimits = loadedRotationLimits.Value; }
|
||||
if (loadedBaseRotation.HasValue) { BaseRotation = loadedBaseRotation.Value; }
|
||||
targetRotation = rotation;
|
||||
UpdateTransformedBarrelPos();
|
||||
}
|
||||
|
||||
@@ -1516,7 +1517,7 @@ namespace Barotrauma.Items.Components
|
||||
minRotation += MathHelper.TwoPi;
|
||||
maxRotation += MathHelper.TwoPi;
|
||||
}
|
||||
rotation = (minRotation + maxRotation) / 2;
|
||||
targetRotation = rotation = (minRotation + maxRotation) / 2;
|
||||
|
||||
UpdateTransformedBarrelPos();
|
||||
}
|
||||
@@ -1537,7 +1538,7 @@ namespace Barotrauma.Items.Components
|
||||
minRotation += MathHelper.TwoPi;
|
||||
maxRotation += MathHelper.TwoPi;
|
||||
}
|
||||
rotation = (minRotation + maxRotation) / 2;
|
||||
targetRotation = rotation = (minRotation + maxRotation) / 2;
|
||||
|
||||
UpdateTransformedBarrelPos();
|
||||
}
|
||||
@@ -1607,6 +1608,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
base.OnItemLoaded();
|
||||
FindLightComponent();
|
||||
targetRotation = rotation;
|
||||
if (!loadedBaseRotation.HasValue)
|
||||
{
|
||||
if (item.FlippedX) { FlipX(relativeToSub: false); }
|
||||
|
||||
Reference in New Issue
Block a user