Build 0.18.4.0

This commit is contained in:
Markus Isberg
2022-05-31 23:13:05 +09:00
parent 077917fa5d
commit 64db1a6a44
175 changed files with 4916 additions and 2393 deletions
@@ -144,9 +144,16 @@ namespace Barotrauma.Items.Components
}
}
public bool Combine(GeneticMaterial otherGeneticMaterial, Character user)
public enum CombineResult
{
if (!CanBeCombinedWith(otherGeneticMaterial)) { return false; }
None,
Refined,
Combined
}
public CombineResult Combine(GeneticMaterial otherGeneticMaterial, Character user)
{
if (!CanBeCombinedWith(otherGeneticMaterial)) { return CombineResult.None; }
float conditionIncrease = Rand.Range(ConditionIncreaseOnCombineMin, ConditionIncreaseOnCombineMax);
conditionIncrease += user?.GetStatValue(StatTypes.GeneticMaterialRefineBonus) ?? 0.0f;
@@ -158,7 +165,7 @@ namespace Barotrauma.Items.Components
{
MakeTainted();
}
return true;
return CombineResult.Refined;
}
else
{
@@ -171,7 +178,7 @@ namespace Barotrauma.Items.Components
{
MakeTainted();
}
return false;
return CombineResult.Combined;
}
}
@@ -697,14 +697,17 @@ namespace Barotrauma.Items.Components
Vector2 fromCharacterToLeak = leak.WorldPosition - character.AnimController.AimSourceWorldPos;
float dist = fromCharacterToLeak.Length();
float reach = AIObjectiveFixLeak.CalculateReach(this, character);
if (dist > reach * 3)
if (dist > reach * 2)
{
// Too far away -> consider this done and hope the AI is smart enough to move closer
Reset();
return true;
}
character.AIController.SteeringManager.Reset();
if (character.AIController.SteeringManager is IndoorsSteeringManager pathSteering)
{
pathSteering.ResetPath();
}
if (!character.AnimController.InWater)
{
// TODO: use the collider size?
@@ -714,34 +717,25 @@ namespace Barotrauma.Items.Components
humanAnim.Crouching = true;
}
}
if (dist > reach * 0.8f || dist > reach * 0.5f && character.AnimController.Limbs.Any(l => l.InWater))
if (!character.IsClimbing)
{
// Steer closer
if (character.AIController.SteeringManager is IndoorsSteeringManager indoorSteering)
if (dist > reach * 0.8f || dist > reach * 0.5f && character.AnimController.Limbs.Any(l => l.InWater))
{
// Swimming inside the sub
if (indoorSteering.CurrentPath != null && !indoorSteering.IsPathDirty && (indoorSteering.CurrentPath.Unreachable || indoorSteering.CurrentPath.Finished))
// Steer closer
Vector2 dir = Vector2.Normalize(fromCharacterToLeak);
if (!character.InWater)
{
Vector2 dir = Vector2.Normalize(fromCharacterToLeak);
character.AIController.SteeringManager.SteeringManual(deltaTime, dir);
}
else
{
character.AIController.SteeringManager.SteeringSeek(character.GetRelativeSimPosition(leak));
dir.Y = 0;
}
character.AIController.SteeringManager.SteeringManual(deltaTime, dir);
}
else
else if (dist < reach * 0.25f && !character.IsClimbing)
{
// Swimming outside the sub
character.AIController.SteeringManager.SteeringSeek(character.GetRelativeSimPosition(leak));
// Too close -> steer away
character.AIController.SteeringManager.SteeringManual(deltaTime, Vector2.Normalize(character.SimPosition - leak.SimPosition));
}
}
else if (dist < reach * 0.25f)
{
// Too close -> steer away
character.AIController.SteeringManager.SteeringManual(deltaTime, Vector2.Normalize(character.SimPosition - leak.SimPosition));
}
if (dist <= reach)
if (dist <= reach || character.IsClimbing)
{
// In range
character.CursorPosition = leak.WorldPosition;
@@ -815,7 +809,7 @@ namespace Barotrauma.Items.Components
}
bool leakFixed = (leak.Open <= 0.0f || leak.Removed) &&
(leak.ConnectedWall == null || leak.ConnectedWall.Sections.Average(s => s.damage) < 1);
(leak.ConnectedWall == null || leak.ConnectedWall.Sections.Max(s => s.damage) < 0.1f);
if (leakFixed && leak.FlowTargetHull?.DisplayName != null && character.IsOnPlayerTeam)
{
@@ -187,7 +187,12 @@ namespace Barotrauma.Items.Components
[Serialize(false, IsPropertySaveable.No)]
public bool RemoveContainedItemsOnDeconstruct { get; set; }
private SlotRestrictions[] slotRestrictions;
private readonly ImmutableArray<SlotRestrictions> slotRestrictions;
readonly List<ISerializableEntity> targets = new List<ISerializableEntity>();
private Vector2 prevContainedItemPositions;
public bool ShouldBeContained(string[] identifiersOrTags, out bool isRestrictionsDefined)
{
@@ -237,10 +242,11 @@ namespace Barotrauma.Items.Components
}
}
Inventory = new ItemInventory(item, this, totalCapacity, SlotsPerRow);
slotRestrictions = new SlotRestrictions[totalCapacity];
List<SlotRestrictions> newSlotRestrictions = new List<SlotRestrictions>(totalCapacity);
for (int i = 0; i < capacity; i++)
{
slotRestrictions[i] = new SlotRestrictions(maxStackSize, ContainableItems);
newSlotRestrictions.Add(new SlotRestrictions(maxStackSize, ContainableItems));
}
int subContainerIndex = capacity;
@@ -268,11 +274,13 @@ namespace Barotrauma.Items.Components
for (int i = subContainerIndex; i < subContainerIndex + subCapacity; i++)
{
slotRestrictions[i] = new SlotRestrictions(subMaxStackSize, subContainableItems);
newSlotRestrictions.Add(new SlotRestrictions(subMaxStackSize, subContainableItems));
}
subContainerIndex += subCapacity;
}
capacity = totalCapacity;
slotRestrictions = newSlotRestrictions.ToImmutableArray();
System.Diagnostics.Debug.Assert(totalCapacity == slotRestrictions.Length);
InitProjSpecific(element);
}
@@ -365,18 +373,21 @@ namespace Barotrauma.Items.Components
return false;
}
readonly List<ISerializableEntity> targets = new List<ISerializableEntity>();
public override void Update(float deltaTime, Camera cam)
{
if (!string.IsNullOrEmpty(SpawnWithId) && !alwaysContainedItemsSpawned)
{
SpawnAlwaysContainedItems();
alwaysContainedItemsSpawned = true;
}
if (item.ParentInventory is CharacterInventory ownerInventory)
{
item.SetContainedItemPositions();
if (Vector2.DistanceSquared(prevContainedItemPositions, item.Position) > 10.0f)
{
SetContainedItemPositions();
prevContainedItemPositions = item.Position;
}
if (AutoInject)
{
@@ -397,7 +408,7 @@ namespace Barotrauma.Items.Components
item.body.Enabled &&
item.body.FarseerBody.Awake)
{
item.SetContainedItemPositions();
SetContainedItemPositions();
}
else if (activeContainedItems.Count == 0)
{
@@ -147,7 +147,7 @@ namespace Barotrauma.Items.Components
CancelUsing(user);
user = null;
}
if (!IsToggle) { IsActive = false; }
if (!IsToggle || item.Connections == null) { IsActive = false; }
return;
}
@@ -231,28 +231,40 @@ namespace Barotrauma.Items.Components
if (targetItem == otherItem) { continue; }
if (deconstructProduct.RequiredOtherItem.Any(r => otherItem.HasTag(r) || r == otherItem.Prefab.Identifier))
{
user?.CheckTalents(AbilityEffectType.OnGeneticMaterialCombinedOrRefined);
foreach (Character character in Character.GetFriendlyCrew(user))
{
character.CheckTalents(AbilityEffectType.OnCrewGeneticMaterialCombinedOrRefined);
}
var geneticMaterial1 = targetItem.GetComponent<GeneticMaterial>();
var geneticMaterial2 = otherItem.GetComponent<GeneticMaterial>();
if (geneticMaterial1 != null && geneticMaterial2 != null)
{
if (geneticMaterial1.Combine(geneticMaterial2, user))
var result = geneticMaterial1.Combine(geneticMaterial2, user);
if (result == GeneticMaterial.CombineResult.Refined)
{
inputContainer.Inventory.RemoveItem(otherItem);
OutputContainer.Inventory.RemoveItem(otherItem);
Entity.Spawner.AddItemToRemoveQueue(otherItem);
}
if (result != GeneticMaterial.CombineResult.None)
{
OnCombinedOrRefined();
}
allowRemove = false;
return;
}
inputContainer.Inventory.RemoveItem(otherItem);
OutputContainer.Inventory.RemoveItem(otherItem);
Entity.Spawner.AddItemToRemoveQueue(otherItem);
else
{
inputContainer.Inventory.RemoveItem(otherItem);
OutputContainer.Inventory.RemoveItem(otherItem);
Entity.Spawner.AddItemToRemoveQueue(otherItem);
OnCombinedOrRefined();
}
}
}
void OnCombinedOrRefined()
{
user?.CheckTalents(AbilityEffectType.OnGeneticMaterialCombinedOrRefined);
foreach (Character character in Character.GetFriendlyCrew(user))
{
character.CheckTalents(AbilityEffectType.OnCrewGeneticMaterialCombinedOrRefined);
}
}
}
@@ -400,8 +400,8 @@ namespace Barotrauma.Items.Components
private void IncreaseSkillLevel(Character user, float deltaTime)
{
if (user?.Info == null) { return; }
// Do not increase the helm skill when "steering" the sub in an outpost level
if (GameMain.GameSession?.Campaign != null && Level.IsLoadedOutpost) { return; }
// Do not increase the helm skill when "steering" the sub while docked into something static (e.g. outpost or wreck)
if (GameMain.GameSession?.Campaign != null && controlledSub != null && controlledSub.DockedTo.Any(d => d.PhysicsBody.BodyType == BodyType.Static)) { return; }
float userSkill = Math.Max(user.GetSkillLevel("helm"), 1.0f) / 100.0f;
user.Info.IncreaseSkillLevel(
@@ -3,7 +3,6 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Xml.Linq;
using Microsoft.Xna.Framework;
namespace Barotrauma.Items.Components
@@ -81,6 +80,8 @@ namespace Barotrauma.Items.Components
private ItemContainer? container;
private float growthTickTimer;
private List<LightComponent>? lightComponents;
public Planter(Item item, ContentXElement element) : base(item, element)
{
canBePicked = true;
@@ -107,10 +108,14 @@ namespace Barotrauma.Items.Components
base.OnItemLoaded();
IsActive = true;
#if CLIENT
lightComponent = item.GetComponent<LightComponent>();
if (lightComponent != null)
var lights = item.GetComponents<LightComponent>();
if (lights.Any())
{
lightComponent.Light.Enabled = false;
lightComponents = lights.ToList();
foreach (var light in lightComponents)
{
light.Light.Enabled = false;
}
}
#endif
container = item.GetComponent<ItemContainer>();
@@ -227,12 +232,17 @@ namespace Barotrauma.Items.Components
base.Update(deltaTime, cam);
#if CLIENT
if (lightComponent != null)
if (lightComponents != null && lightComponents.Count > 0)
{
bool hasSeed = false;
foreach (Growable? seed in GrowableSeeds) { hasSeed |= seed != null; }
lightComponent.Light.Enabled = hasSeed;
foreach (Growable? seed in GrowableSeeds)
{
hasSeed |= seed != null;
}
foreach (var light in lightComponents)
{
light.Light.Enabled = hasSeed;
}
}
#endif
@@ -602,7 +602,7 @@ namespace Barotrauma.Items.Components
private bool ShouldDeteriorate()
{
if (Level.IsLoadedOutpost) { return false; }
if (Level.IsLoadedFriendlyOutpost) { return false; }
if (LastActiveTime > Timing.TotalTime) { return true; }
foreach (ItemComponent ic in item.Components)
@@ -13,12 +13,13 @@ namespace Barotrauma.Items.Components
private float updateTimer;
[Flags]
public enum TargetType
{
Any,
Human,
Monster,
Wall
Human = 1,
Monster = 2,
Wall = 4,
Any = Human | Monster | Wall,
}
[Serialize(false, IsPropertySaveable.No, description: "Has the item currently detected movement. Intended to be used by StatusEffect conditionals (setting this value in XML has no effect).")]
@@ -179,6 +180,11 @@ namespace Barotrauma.Items.Components
if (!string.IsNullOrEmpty(signalOut)) { item.SendSignal(new Signal(signalOut, 1), "state_out"); }
if (MotionDetected)
{
ApplyStatusEffects(ActionType.OnUse, deltaTime);
}
updateTimer -= deltaTime;
if (updateTimer > 0.0f) { return; }
@@ -199,8 +205,7 @@ namespace Barotrauma.Items.Components
float broadRangeX = Math.Max(rangeX * 2, 500);
float broadRangeY = Math.Max(rangeY * 2, 500);
if (item.CurrentHull == null && item.Submarine != null &&
(Target == TargetType.Wall || Target == TargetType.Any))
if (item.CurrentHull == null && item.Submarine != null && Target.HasFlag(TargetType.Wall))
{
if (Level.Loaded != null && (Math.Abs(item.Submarine.Velocity.X) > MinimumVelocity || Math.Abs(item.Submarine.Velocity.Y) > MinimumVelocity))
{
@@ -248,7 +253,7 @@ namespace Barotrauma.Items.Components
}
}
if (Target != TargetType.Wall)
if (Target.HasFlag(TargetType.Human) || Target.HasFlag(TargetType.Monster))
{
foreach (Character c in Character.CharacterList)
{
@@ -258,14 +263,13 @@ namespace Barotrauma.Items.Components
//makes it possible to detect when a spawned character moves without triggering the detector immediately as the ragdoll spawns and drops to the ground
if (c.SpawnTime > Timing.TotalTime - 1.0) { continue; }
switch (Target)
if (c.IsHuman)
{
case TargetType.Human:
if (!c.IsHuman) { continue; }
break;
case TargetType.Monster:
if (c.IsHuman || c.IsPet) { continue; }
break;
if (!Target.HasFlag(TargetType.Human)) { continue; }
}
else if (!c.IsPet)
{
if (!Target.HasFlag(TargetType.Monster)) { continue; }
}
//do a rough check based on the position of the character's collider first
@@ -4,6 +4,7 @@ using FarseerPhysics.Dynamics.Contacts;
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
namespace Barotrauma.Items.Components
@@ -12,6 +13,46 @@ namespace Barotrauma.Items.Components
{
[Editable, Serialize(0.0f, IsPropertySaveable.Yes, description: "The maximum amount of force applied to the triggering entitites.", alwaysUseInstanceValues: true)]
public float Force { get; set; }
[Editable, Serialize(false, IsPropertySaveable.Yes, description: "Determines if the force gets higher the closer the triggerer is to the center of the trigger.", alwaysUseInstanceValues: true)]
public bool DistanceBasedForce { get; set; }
[Editable, Serialize(false, IsPropertySaveable.Yes, description: "Determines if the force fluctuates over time or if it stays constant.", alwaysUseInstanceValues: true)]
public bool ForceFluctuation { get; set; }
[Serialize(1.0f, IsPropertySaveable.Yes, description: "How much the fluctuation affects the force. 1 is the maximum fluctuation, 0 is no fluctuation.", alwaysUseInstanceValues: true)]
private float ForceFluctuationStrength
{
get
{
return forceFluctuationStrength;
}
set
{
forceFluctuationStrength = Math.Clamp(value, 0.0f, 1.0f);
}
}
[Serialize(1.0f, IsPropertySaveable.Yes, description: "How fast (cycles per second) the force fluctuates.", alwaysUseInstanceValues: true)]
private float ForceFluctuationFrequency
{
get
{
return forceFluctuationFrequency;
}
set
{
forceFluctuationFrequency = Math.Max(value, 0.01f);
}
}
[Serialize(0.01f, IsPropertySaveable.Yes, description: "How often (in seconds) the force fluctuation is calculated.", alwaysUseInstanceValues: true)]
private float ForceFluctuationInterval
{
get
{
return forceFluctuationInterval;
}
set
{
forceFluctuationInterval = Math.Max(value, 0.01f);
}
}
public PhysicsBody PhysicsBody { get; private set; }
private float Radius { get; set; }
@@ -38,11 +79,6 @@ namespace Barotrauma.Items.Components
private readonly LevelTrigger.TriggererType triggeredBy;
private readonly HashSet<Entity> triggerers = new HashSet<Entity>();
private readonly bool triggerOnce;
private readonly bool distanceBasedForce;
private readonly bool forceFluctuation;
private readonly float forceFluctuationStrength;
private readonly float forceFluctuationFrequency;
private readonly float forceFluctuationInterval;
private readonly List<ISerializableEntity> statusEffectTargets = new List<ISerializableEntity>();
/// <summary>
/// Effects applied to entities inside the trigger
@@ -53,6 +89,10 @@ namespace Barotrauma.Items.Components
/// </summary>
private readonly List<Attack> attacks = new List<Attack>();
private float forceFluctuationStrength;
private float forceFluctuationFrequency;
private float forceFluctuationInterval;
public TriggerComponent(Item item, ContentXElement element) : base(item, element)
{
string triggeredByAttribute = element.GetAttributeString("triggeredby", "Character");
@@ -61,15 +101,6 @@ namespace Barotrauma.Items.Components
DebugConsole.ThrowError($"Error in ForceComponent config: \"{triggeredByAttribute}\" is not a valid triggerer type.");
}
triggerOnce = element.GetAttributeBool("triggeronce", false);
distanceBasedForce = element.GetAttributeBool("distancebasedforce", false);
forceFluctuation = element.GetAttributeBool("forcefluctuation", false);
forceFluctuationStrength = element.GetAttributeFloat("forcefluctuationstrength", 1.0f);
forceFluctuationStrength = Math.Clamp(forceFluctuationStrength, 0.0f, 1.0f);
forceFluctuationFrequency = element.GetAttributeFloat("fluctuationfrequency", 1.0f);
forceFluctuationFrequency = Math.Max(forceFluctuationFrequency, 0.01f);
forceFluctuationInterval = element.GetAttributeFloat("fluctuationinterval", 0.01f);
forceFluctuationInterval = Math.Max(forceFluctuationInterval, 0.01f);
string parentDebugName = $"TriggerComponent in {item.Name}";
foreach (var subElement in element.Elements())
{
@@ -153,14 +184,14 @@ namespace Barotrauma.Items.Components
TriggerActive = triggerers.Any();
if (forceFluctuation && TriggerActive && (GameMain.NetworkMember == null || GameMain.NetworkMember.IsServer))
if (ForceFluctuation && TriggerActive && (GameMain.NetworkMember == null || GameMain.NetworkMember.IsServer))
{
ForceFluctuationTimer += deltaTime;
if (ForceFluctuationTimer >= forceFluctuationInterval)
if (ForceFluctuationTimer >= ForceFluctuationInterval)
{
float v = MathF.Sin(2 * MathF.PI * forceFluctuationFrequency * TimeInLevel);
float v = MathF.Sin(2 * MathF.PI * ForceFluctuationFrequency * TimeInLevel);
float amount = MathUtils.InverseLerp(-1.0f, 1.0f, v);
CurrentForceFluctuation = MathHelper.Lerp(1.0f - forceFluctuationStrength, 1.0f, amount);
CurrentForceFluctuation = MathHelper.Lerp(1.0f - ForceFluctuationStrength, 1.0f, amount);
ForceFluctuationTimer = 0.0f;
GameMain.NetworkMember?.CreateEntityEvent(this);
}
@@ -179,7 +210,7 @@ namespace Barotrauma.Items.Components
LevelTrigger.ApplyAttacks(attacks, item.WorldPosition, deltaTime);
}
if (Force < 0.01f)
if (Math.Abs(Force) < 0.01f)
{
// Just ignore very minimal forces
continue;
@@ -205,7 +236,7 @@ namespace Barotrauma.Items.Components
{
Vector2 diff = ConvertUnits.ToDisplayUnits(PhysicsBody.SimPosition - body.SimPosition);
if (diff.LengthSquared() < 0.0001f) { return; }
float distanceFactor = distanceBasedForce ? LevelTrigger.GetDistanceFactor(body, PhysicsBody, RadiusInDisplayUnits) : 1.0f;
float distanceFactor = DistanceBasedForce ? LevelTrigger.GetDistanceFactor(body, PhysicsBody, RadiusInDisplayUnits) : 1.0f;
if (distanceFactor <= 0.0f) { return; }
Vector2 force = distanceFactor * (CurrentForceFluctuation * Force) * Vector2.Normalize(diff);
if (force.LengthSquared() < 0.01f) { return; }
@@ -227,5 +258,43 @@ namespace Barotrauma.Items.Components
PhysicsBody.Submarine = item.Submarine;
}
}
public override void ReceiveSignal(Signal signal, Connection connection)
{
base.ReceiveSignal(signal, connection);
switch (connection.Name)
{
case "set_force":
if (!FloatTryParse(signal, out float force)) { break; }
Force = force;
break;
case "set_distancebasedforce":
if (!bool.TryParse(signal.value, out bool distanceBasedForce)) { break; }
DistanceBasedForce = distanceBasedForce;
break;
case "set_forcefluctuation":
if (!bool.TryParse(signal.value, out bool forceFluctuation)) { break; }
ForceFluctuation = forceFluctuation;
break;
case "set_forcefluctuationstrength":
if (!FloatTryParse(signal, out float forceFluctuationStrength)) { break; }
ForceFluctuationStrength = forceFluctuationStrength;
break;
case "set_forcefluctuationfrequency":
if (!FloatTryParse(signal, out float forceFluctuationFrequency)) { break; }
ForceFluctuationFrequency = forceFluctuationFrequency;
break;
case "set_forcefluctuationinterval":
if (!FloatTryParse(signal, out float forceFluctuationInterval)) { break; }
ForceFluctuationInterval = forceFluctuationInterval;
break;
}
static bool FloatTryParse(Signal signal, out float value)
{
return float.TryParse(signal.value, NumberStyles.Any, CultureInfo.InvariantCulture, out value);
}
}
}
}
}
@@ -4,9 +4,7 @@ using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.Globalization;
using Barotrauma.IO;
using System.Linq;
using System.Xml.Linq;
using Barotrauma.Extensions;
using FarseerPhysics.Dynamics;
@@ -20,8 +18,6 @@ namespace Barotrauma.Items.Components
private Vector2 barrelPos;
private Vector2 transformedBarrelPos;
private LightComponent lightComponent;
private float rotation, targetRotation;
@@ -71,6 +67,8 @@ namespace Barotrauma.Items.Components
public Character ActiveUser;
private float resetActiveUserTimer;
private List<LightComponent> lightComponents;
public float Rotation
{
get { return rotation; }
@@ -168,10 +166,13 @@ namespace Barotrauma.Items.Components
rotation = (minRotation + maxRotation) / 2;
#if CLIENT
if (lightComponent != null)
if (lightComponents != null)
{
lightComponent.Rotation = rotation;
lightComponent.Light.Rotation = -rotation;
foreach (var light in lightComponents)
{
light.Rotation = rotation;
light.Light.Rotation = -rotation;
}
}
#endif
}
@@ -331,27 +332,39 @@ namespace Barotrauma.Items.Components
if (loadedRotationLimits.HasValue) { RotationLimits = loadedRotationLimits.Value; }
if (loadedBaseRotation.HasValue) { BaseRotation = loadedBaseRotation.Value; }
targetRotation = rotation;
FindLightComponent();
UpdateTransformedBarrelPos();
}
private void FindLightComponent()
private void FindLightComponents()
{
if (lightComponents != null)
{
// Can't run again, because of reparenting.
return;
}
foreach (LightComponent lc in item.GetComponents<LightComponent>())
{
// Only make the Turret control the LightComponents that are it's children. So it'd be possible to for example have some extra lights on the turret that don't rotate with it.
if (lc?.Parent == this)
{
lightComponent = lc;
break;
if (lightComponents == null)
{
lightComponents = new List<LightComponent>();
}
lightComponents.Add(lc);
}
}
#if CLIENT
if (lightComponent != null)
if (lightComponents != null)
{
lightComponent.Parent = null;
lightComponent.Rotation = Rotation - item.RotationRad;
lightComponent.Light.Rotation = -rotation;
foreach (var light in lightComponents)
{
// We want the turret to control the state of the LightComponent, not tie it's state to the state of the Turret (the light can be inactive even if the turret is active)
light.Parent = null;
light.Rotation = Rotation - item.RotationRad;
light.Light.Rotation = -rotation;
}
}
#endif
}
@@ -428,7 +441,7 @@ namespace Barotrauma.Items.Components
if (MathUtils.NearlyEqual(minRotation, maxRotation))
{
UpdateLightComponent();
UpdateLightComponents();
return;
}
@@ -452,7 +465,7 @@ namespace Barotrauma.Items.Components
}
// Do not increase the weapons skill when operating a turret in an outpost level
if (user?.Info != null && (GameMain.GameSession?.Campaign == null || !Level.IsLoadedOutpost))
if (user?.Info != null && (GameMain.GameSession?.Campaign == null || !Level.IsLoadedFriendlyOutpost))
{
user.Info.IncreaseSkillLevel("weapons".ToIdentifier(),
SkillSettings.Current.SkillIncreasePerSecondWhenOperatingTurret * deltaTime / Math.Max(user.GetSkillLevel("weapons"), 1.0f));
@@ -509,14 +522,17 @@ namespace Barotrauma.Items.Components
aiFindTargetTimer -= deltaTime;
}
UpdateLightComponent();
UpdateLightComponents();
}
private void UpdateLightComponent()
private void UpdateLightComponents()
{
if (lightComponent != null)
if (lightComponents != null)
{
lightComponent.Rotation = Rotation - item.RotationRad;
foreach (var light in lightComponents)
{
light.Rotation = Rotation - item.RotationRad;
}
}
}
@@ -1601,21 +1617,24 @@ namespace Barotrauma.Items.Components
}
break;
case "toggle_light":
if (lightComponent != null && signal.value != "0")
if (lightComponents != null && signal.value != "0")
{
lightComponent.IsOn = !lightComponent.IsOn;
UpdateLightComponent();
foreach (var light in lightComponents)
{
light.IsOn = !light.IsOn;
}
UpdateLightComponents();
}
break;
case "set_light":
if (lightComponent != null)
if (lightComponents != null)
{
bool shouldBeOn = signal.value != "0";
if (shouldBeOn != lightComponent.IsOn)
foreach (var light in lightComponents)
{
lightComponent.IsOn = shouldBeOn;
UpdateLightComponent();
light.IsOn = shouldBeOn;
}
UpdateLightComponents();
}
break;
}
@@ -1633,7 +1652,7 @@ namespace Barotrauma.Items.Components
public override void OnItemLoaded()
{
base.OnItemLoaded();
FindLightComponent();
FindLightComponents();
targetRotation = rotation;
if (!loadedBaseRotation.HasValue)
{
@@ -6,7 +6,6 @@ using System.Linq;
using System.Xml.Linq;
using Barotrauma.Items.Components;
using Barotrauma.Networking;
using System.Collections.Immutable;
using Barotrauma.Abilities;
namespace Barotrauma
@@ -82,7 +81,20 @@ namespace Barotrauma
public string Sound { get; private set; }
public Point? SheetIndex { get; private set; }
public LightComponent LightComponent { get; set; }
public LightComponent LightComponent => LightComponents?.FirstOrDefault();
public List<LightComponent> LightComponents
{
get
{
if (_lightComponents == null)
{
_lightComponents = new List<LightComponent>();
}
return _lightComponents;
}
}
private List<LightComponent> _lightComponents;
public int Variant { get; set; }
@@ -338,11 +350,14 @@ namespace Barotrauma.Items.Components
foreach (var lightElement in subElement.Elements())
{
if (!lightElement.Name.ToString().Equals("lightcomponent", StringComparison.OrdinalIgnoreCase)) { continue; }
wearableSprites[i].LightComponent = new LightComponent(item, lightElement)
wearableSprites[i].LightComponents.Add(new LightComponent(item, lightElement)
{
Parent = this
};
item.AddComponent(wearableSprites[i].LightComponent);
});
foreach (var light in wearableSprites[i].LightComponents)
{
item.AddComponent(light);
}
}
i++;
@@ -413,7 +428,10 @@ namespace Barotrauma.Items.Components
IsActive = true;
if (wearableSprite.LightComponent != null)
{
wearableSprite.LightComponent.ParentBody = equipLimb.body;
foreach (var light in wearableSprite.LightComponents)
{
light.ParentBody = equipLimb.body;
}
}
limb[i] = equipLimb;
@@ -467,7 +485,10 @@ namespace Barotrauma.Items.Components
if (wearableSprites[i].LightComponent != null)
{
wearableSprites[i].LightComponent.ParentBody = null;
foreach (var light in wearableSprites[i].LightComponents)
{
light.ParentBody = null;
}
}
equipLimb.WearingItems.RemoveAll(w => w != null && w == wearableSprites[i]);
@@ -494,7 +515,6 @@ namespace Barotrauma.Items.Components
}
item.SetTransform(picker.SimPosition, 0.0f);
item.SetContainedItemPositions();
item.ApplyStatusEffects(ActionType.OnWearing, deltaTime, picker);