v1.6.17.0 (Unto the Breach update)
This commit is contained in:
@@ -183,6 +183,13 @@ namespace Barotrauma.Items.Components
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize(false, IsPropertySaveable.No, description: "Does the Controller require power to function (= to send signals and move the camera focus to a connected item)?")]
|
||||
public bool RequirePower
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize(false, IsPropertySaveable.No, description: "If true, other items can be used simultaneously.")]
|
||||
public bool IsSecondaryItem
|
||||
{
|
||||
@@ -190,6 +197,13 @@ namespace Barotrauma.Items.Components
|
||||
private set;
|
||||
}
|
||||
|
||||
[Serialize(false, IsPropertySaveable.No, description: "If enabled, the user sticks to the position of this item even if the item moves.")]
|
||||
public bool ForceUserToStayAttached
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public Controller(Item item, ContentXElement element)
|
||||
: base(item, element)
|
||||
{
|
||||
@@ -199,22 +213,35 @@ namespace Barotrauma.Items.Components
|
||||
IsActive = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Hack for allowing characters to interact with a loader to get inside a boarding pod.
|
||||
/// Doing that simply by autointeracting with the contained pod is difficult, because interacting with the loader selects it
|
||||
/// _after_ the Select method of the pod is called by the autointeract logic, and the character only goes inside the pod if it's the selected item.
|
||||
/// </summary>
|
||||
private bool forceSelectNextFrame;
|
||||
|
||||
public override void Update(float deltaTime, Camera cam)
|
||||
{
|
||||
this.cam = cam;
|
||||
UserInCorrectPosition = false;
|
||||
if (!ForceUserToStayAttached) { UserInCorrectPosition = false; }
|
||||
|
||||
string signal = IsToggle && State ? output : falseOutput;
|
||||
if (item.Connections != null && IsToggle && !string.IsNullOrEmpty(signal))
|
||||
if (item.Connections != null && IsToggle && !string.IsNullOrEmpty(signal) && !IsOutOfPower())
|
||||
{
|
||||
item.SendSignal(signal, "signal_out");
|
||||
item.SendSignal(signal, "trigger_out");
|
||||
}
|
||||
|
||||
if (forceSelectNextFrame && user != null)
|
||||
{
|
||||
user.SelectedItem = item;
|
||||
}
|
||||
forceSelectNextFrame = false;
|
||||
|
||||
if (user == null
|
||||
|| user.Removed
|
||||
|| !user.IsAnySelectedItem(item)
|
||||
|| item.ParentInventory != null
|
||||
|| (item.ParentInventory != null && !IsAttachedUser(user))
|
||||
|| !user.CanInteractWith(item)
|
||||
|| (UsableIn == UseEnvironment.Water && !user.AnimController.InWater)
|
||||
|| (UsableIn == UseEnvironment.Air && user.AnimController.InWater))
|
||||
@@ -228,6 +255,17 @@ namespace Barotrauma.Items.Components
|
||||
return;
|
||||
}
|
||||
|
||||
if (ForceUserToStayAttached && Vector2.DistanceSquared(item.WorldPosition, user.WorldPosition) > 0.1f)
|
||||
{
|
||||
user.TeleportTo(item.WorldPosition);
|
||||
user.AnimController.Collider.ResetDynamics();
|
||||
foreach (var limb in user.AnimController.Limbs)
|
||||
{
|
||||
if (limb.Removed || limb.IsSevered) { continue; }
|
||||
limb.body?.ResetDynamics();
|
||||
}
|
||||
}
|
||||
|
||||
user.AnimController.StartUsingItem();
|
||||
|
||||
if (userPos != Vector2.Zero)
|
||||
@@ -344,6 +382,8 @@ namespace Barotrauma.Items.Components
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IsOutOfPower()) { return false; }
|
||||
|
||||
if (IsToggle && (activator == null || lastUsed < Timing.TotalTime - 0.1))
|
||||
{
|
||||
if (GameMain.NetworkMember == null || GameMain.NetworkMember.IsServer)
|
||||
@@ -380,6 +420,8 @@ namespace Barotrauma.Items.Components
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IsOutOfPower()) { return false; }
|
||||
|
||||
focusTarget = GetFocusTarget();
|
||||
|
||||
if (focusTarget == null)
|
||||
@@ -417,11 +459,20 @@ namespace Barotrauma.Items.Components
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool IsOutOfPower()
|
||||
{
|
||||
if (!RequirePower) { return false; }
|
||||
var powered = item.GetComponent<Powered>();
|
||||
return powered == null || powered.Voltage < powered.MinVoltage;
|
||||
}
|
||||
|
||||
public Item GetFocusTarget()
|
||||
{
|
||||
var positionOut = item.Connections?.Find(c => c.Name == "position_out");
|
||||
if (positionOut == null) { return null; }
|
||||
|
||||
if (IsOutOfPower()) { return null; }
|
||||
|
||||
item.SendSignal(new Signal(MathHelper.ToDegrees(targetRotation).ToString("G", CultureInfo.InvariantCulture), sender: user), positionOut);
|
||||
|
||||
for (int i = item.LastSentSignalRecipients.Count - 1; i >= 0; i--)
|
||||
@@ -447,6 +498,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public override bool Pick(Character picker)
|
||||
{
|
||||
if (IsOutOfPower()) { return false; }
|
||||
#if CLIENT
|
||||
if (Screen.Selected == GameMain.SubEditorScreen) { return false; }
|
||||
#endif
|
||||
@@ -539,7 +591,16 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
user = activator;
|
||||
IsActive = true;
|
||||
if (ForceUserToStayAttached && item.Container != null)
|
||||
{
|
||||
forceSelectNextFrame = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//allow the selection logic above to run when out of power, but allow sending signals
|
||||
if (IsOutOfPower()) { return false; }
|
||||
|
||||
#if SERVER
|
||||
item.CreateServerEvent(this);
|
||||
#endif
|
||||
@@ -550,6 +611,14 @@ namespace Barotrauma.Items.Components
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// "Attached user" sticks to this item. Can be used for things such as clown crates and boarding pods.
|
||||
/// </summary>
|
||||
public bool IsAttachedUser(Character character)
|
||||
{
|
||||
return character != null && character == user && ForceUserToStayAttached;
|
||||
}
|
||||
|
||||
public override void FlipX(bool relativeToSub)
|
||||
{
|
||||
if (dir != Direction.None)
|
||||
|
||||
+22
-17
@@ -14,8 +14,6 @@ namespace Barotrauma.Items.Components
|
||||
private float progressTimer;
|
||||
private float progressState;
|
||||
|
||||
private bool hasPower;
|
||||
|
||||
private Character user;
|
||||
|
||||
private float userDeconstructorSpeedMultiplier = 1.0f;
|
||||
@@ -88,9 +86,8 @@ namespace Barotrauma.Items.Components
|
||||
SetActive(false);
|
||||
return;
|
||||
}
|
||||
|
||||
hasPower = Voltage >= MinVoltage;
|
||||
if (!hasPower) { return; }
|
||||
|
||||
if (!HasPower) { return; }
|
||||
|
||||
var repairable = item.GetComponent<Repairable>();
|
||||
if (repairable != null)
|
||||
@@ -243,16 +240,16 @@ namespace Barotrauma.Items.Components
|
||||
if (targetItem == otherItem) { continue; }
|
||||
if (deconstructProduct.RequiredOtherItem.Any(r => otherItem.HasTag(r) || r == otherItem.Prefab.Identifier))
|
||||
{
|
||||
var geneticMaterial1 = targetItem.GetComponent<GeneticMaterial>();
|
||||
var geneticMaterial2 = otherItem.GetComponent<GeneticMaterial>();
|
||||
if (geneticMaterial1 != null && geneticMaterial2 != null)
|
||||
var targetGeneticMaterial = targetItem.GetComponent<GeneticMaterial>();
|
||||
var otherGeneticMaterial = otherItem.GetComponent<GeneticMaterial>();
|
||||
if (targetGeneticMaterial != null && otherGeneticMaterial != null)
|
||||
{
|
||||
var result = geneticMaterial1.Combine(geneticMaterial2, user);
|
||||
var result = targetGeneticMaterial.Combine(otherGeneticMaterial, user, out Item itemToDestroy);
|
||||
if (result == GeneticMaterial.CombineResult.Refined)
|
||||
{
|
||||
inputContainer.Inventory.RemoveItem(otherItem);
|
||||
OutputContainer.Inventory.RemoveItem(otherItem);
|
||||
Entity.Spawner.AddItemToRemoveQueue(otherItem);
|
||||
Entity.Spawner.AddItemToRemoveQueue(itemToDestroy);
|
||||
}
|
||||
if (result != GeneticMaterial.CombineResult.None)
|
||||
{
|
||||
@@ -425,31 +422,39 @@ namespace Barotrauma.Items.Components
|
||||
foreach (Item inputItem in items)
|
||||
{
|
||||
if (!inputItem.AllowDeconstruct) { continue; }
|
||||
|
||||
foreach (var deconstructItem in inputItem.Prefab.DeconstructItems)
|
||||
{
|
||||
// check for deconstructor compatibility (for example, 'geneticresearchstation' tag)
|
||||
if (deconstructItem.RequiredDeconstructor.Length > 0)
|
||||
{
|
||||
if (!deconstructItem.RequiredDeconstructor.Any(r => item.HasTag(r) || item.Prefab.Identifier == r)) { continue; }
|
||||
if (deconstructItem.RequiredDeconstructor.None(requiredId => item.HasTag(requiredId) || item.Prefab.Identifier == requiredId)) { continue; }
|
||||
}
|
||||
|
||||
// check for other required items in the same deconstructor (for example, 'geneticmaterial')
|
||||
if (deconstructItem.RequiredOtherItem.Length > 0 && checkRequiredOtherItems)
|
||||
{
|
||||
if (!deconstructItem.RequiredOtherItem.Any(r => items.Any(it => it.HasTag(r) || it.Prefab.Identifier == r))) { continue; }
|
||||
// no matching item with the required id, skip
|
||||
if (deconstructItem.RequiredOtherItem.None(requiredId => items.Any(it => it.HasTag(requiredId) || it.Prefab.Identifier == requiredId))) { continue; }
|
||||
|
||||
bool validOtherItemFound = false;
|
||||
foreach (Item otherInputItem in items)
|
||||
{
|
||||
if (otherInputItem == inputItem) { continue; }
|
||||
if (!deconstructItem.RequiredOtherItem.Any(r => otherInputItem.HasTag(r) || otherInputItem.Prefab.Identifier == r)) { continue; }
|
||||
if (deconstructItem.RequiredOtherItem.None(requiredId => otherInputItem.HasTag(requiredId) || otherInputItem.Prefab.Identifier == requiredId)) { continue; }
|
||||
|
||||
var geneticMaterial1 = inputItem.GetComponent<GeneticMaterial>();
|
||||
var geneticMaterial2 = otherInputItem.GetComponent<GeneticMaterial>();
|
||||
if (geneticMaterial1 != null && geneticMaterial2 != null)
|
||||
// skip if genetic materials cannot be combined (or refined)
|
||||
var geneticMaterial = inputItem.GetComponent<GeneticMaterial>();
|
||||
var otherGeneticMaterial = otherInputItem.GetComponent<GeneticMaterial>();
|
||||
if (geneticMaterial != null && otherGeneticMaterial != null)
|
||||
{
|
||||
if (!geneticMaterial1.CanBeCombinedWith(geneticMaterial2)) { continue; }
|
||||
if (!geneticMaterial.CanBeCombinedWith(otherGeneticMaterial)) { continue; }
|
||||
}
|
||||
validOtherItemFound = true;
|
||||
}
|
||||
if (!validOtherItemFound) { continue; }
|
||||
}
|
||||
|
||||
yield return (inputItem, deconstructItem);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,7 +126,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
else
|
||||
{
|
||||
hasPower = Voltage > MinVoltage;
|
||||
hasPower = HasPower;
|
||||
}
|
||||
|
||||
if (lastReceivedTargetForce.HasValue)
|
||||
@@ -146,7 +146,7 @@ namespace Barotrauma.Items.Components
|
||||
float forceMultiplier = 0.1f;
|
||||
if (User != null)
|
||||
{
|
||||
forceMultiplier *= MathHelper.Lerp(0.5f, 2.0f, (float)Math.Sqrt(User.GetSkillLevel("helm") / 100));
|
||||
forceMultiplier *= MathHelper.Lerp(0.5f, 2.0f, (float)Math.Sqrt(User.GetSkillLevel(Tags.HelmSkill) / 100));
|
||||
}
|
||||
currForce *= item.StatManager.GetAdjustedValueMultiplicative(ItemTalentStats.EngineMaxSpeed, MaxForce) * forceMultiplier;
|
||||
if (item.GetComponent<Repairable>() is { IsTinkering: true } repairable)
|
||||
|
||||
@@ -319,7 +319,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
else
|
||||
{
|
||||
hasPower = Voltage >= MinVoltage;
|
||||
hasPower = HasPower;
|
||||
|
||||
if (!hasPower)
|
||||
{
|
||||
|
||||
@@ -80,7 +80,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public override void Update(float deltaTime, Camera cam)
|
||||
{
|
||||
hasPower = Voltage > MinVoltage;
|
||||
hasPower = HasPower;
|
||||
if (hasPower)
|
||||
{
|
||||
ApplyStatusEffects(ActionType.OnActive, deltaTime);
|
||||
|
||||
+1
-1
@@ -46,7 +46,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
if (item.CurrentHull == null) { return; }
|
||||
|
||||
if (Voltage < MinVoltage && PowerConsumption > 0)
|
||||
if (!HasPower && PowerConsumption > 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasPower => IsActive && Voltage >= MinVoltage;
|
||||
public override bool HasPower => IsActive && Voltage >= MinVoltage;
|
||||
public bool IsAutoControlled => pumpSpeedLockTimer > 0.0f || isActiveLockTimer > 0.0f;
|
||||
|
||||
private const float TinkeringSpeedIncrease = 4.0f;
|
||||
@@ -140,13 +140,11 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
float powerFactor = Math.Min(currPowerConsumption <= 0.0f || MinVoltage <= 0.0f ? 1.0f : Voltage, MaxOverVoltageFactor);
|
||||
|
||||
currFlow = flowPercentage / 100.0f * item.StatManager.GetAdjustedValueMultiplicative(ItemTalentStats.PumpMaxFlow, MaxFlow) * powerFactor;
|
||||
|
||||
currFlow = flowPercentage / 100.0f * MaxFlow * powerFactor;
|
||||
if (item.GetComponent<Repairable>() is { IsTinkering: true } repairable)
|
||||
{
|
||||
currFlow *= 1f + repairable.TinkeringStrength * TinkeringSpeedIncrease;
|
||||
}
|
||||
|
||||
currFlow = item.StatManager.GetAdjustedValueMultiplicative(ItemTalentStats.PumpSpeed, currFlow);
|
||||
|
||||
//less effective when in a bad condition
|
||||
|
||||
@@ -340,7 +340,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
foreach (Item item in containedItems)
|
||||
{
|
||||
if (!item.HasTag(Tags.Fuel)) { continue; }
|
||||
if (!item.HasTag(Tags.ReactorFuel)) { continue; }
|
||||
if (fissionRate > 0.0f)
|
||||
{
|
||||
bool isConnectedToFriendlyOutpost = Level.IsLoadedOutpost &&
|
||||
@@ -707,13 +707,13 @@ namespace Barotrauma.Items.Components
|
||||
var containObjective = AIContainItems<Reactor>(container, character, objective, itemCount: 1, equip: true, removeEmpty: true, spawnItemIfNotFound: !character.IsOnPlayerTeam, dropItemOnDeselected: true);
|
||||
containObjective.Completed += ReportFuelRodCount;
|
||||
containObjective.Abandoned += ReportFuelRodCount;
|
||||
character.Speak(TextManager.Get("DialogReactorFuel").Value, null, 0.0f, Tags.Fuel, 30.0f);
|
||||
character.Speak(TextManager.Get("DialogReactorFuel").Value, null, 0.0f, Tags.ReactorFuel, 30.0f);
|
||||
|
||||
void ReportFuelRodCount()
|
||||
{
|
||||
if (!character.IsOnPlayerTeam) { return; }
|
||||
if (character.Submarine != Submarine.MainSub) { return; }
|
||||
int remainingFuelRods = Submarine.MainSub.GetItems(false).Count(i => i.HasTag(Tags.Fuel) && i.Condition > 1);
|
||||
int remainingFuelRods = Submarine.MainSub.GetItems(false).Count(i => i.HasTag(Tags.ReactorFuel) && i.Condition > 1);
|
||||
if (remainingFuelRods == 0)
|
||||
{
|
||||
character.Speak(TextManager.Get("DialogOutOfFuelRods").Value, null, 0.0f, "outoffuelrods".ToIdentifier(), 30.0f);
|
||||
|
||||
@@ -191,8 +191,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
if (currentMode == Mode.Active)
|
||||
{
|
||||
if ((Voltage >= MinVoltage) &&
|
||||
(!UseTransducers || connectedTransducers.Count > 0))
|
||||
if (HasPower && (!UseTransducers || connectedTransducers.Count > 0))
|
||||
{
|
||||
if (currentPingIndex != -1)
|
||||
{
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
UpdateOnActiveEffects(deltaTime);
|
||||
|
||||
if (Voltage >= MinVoltage)
|
||||
if (HasPower)
|
||||
{
|
||||
sendSignalTimer += deltaTime;
|
||||
if (sendSignalTimer > SendSignalInterval)
|
||||
|
||||
@@ -298,7 +298,7 @@ namespace Barotrauma.Items.Components
|
||||
controlledSub = sonar.ConnectedTransducers.Any() ? sonar.ConnectedTransducers.First().Item.Submarine : null;
|
||||
}
|
||||
|
||||
if (Voltage < MinVoltage) { return; }
|
||||
if (!HasPower) { return; }
|
||||
|
||||
if (user != null && user.Removed)
|
||||
{
|
||||
@@ -311,7 +311,7 @@ namespace Barotrauma.Items.Components
|
||||
if (user != null && controlledSub != null &&
|
||||
(user.SelectedItem == item || item.linkedTo.Contains(user.SelectedItem)))
|
||||
{
|
||||
userSkill = user.GetSkillLevel("helm") / 100.0f;
|
||||
userSkill = user.GetSkillLevel(Tags.HelmSkill) / 100.0f;
|
||||
}
|
||||
|
||||
// override autopilot pathing while the AI rams, and go full speed ahead
|
||||
|
||||
Reference in New Issue
Block a user