Unstable v0.19.1.0

This commit is contained in:
Juan Pablo Arce
2022-08-19 13:59:08 -03:00
parent 6b55adcdd9
commit 1219615d64
192 changed files with 3875 additions and 2648 deletions
@@ -203,7 +203,7 @@ namespace Barotrauma.Items.Components
foreach ((Character character, Node node) in charactersInRange)
{
if (character == null || character.Removed) { continue; }
character.ApplyAttack(null, node.WorldPosition, attack, 1.0f);
character.ApplyAttack(null, node.WorldPosition, attack, MathHelper.Clamp(Voltage, 1.0f, MaxOverVoltageFactor));
}
}
DischargeProjSpecific();
@@ -295,12 +295,11 @@ namespace Barotrauma.Items.Components
if (attachable)
{
DeattachFromWall();
if (body != null)
{
item.body = body;
}
DeattachFromWall();
}
if (Pusher != null) { Pusher.Enabled = false; }
@@ -619,6 +618,10 @@ namespace Barotrauma.Items.Components
#if CLIENT
item.DrawDepthOffset = SpriteDepthWhenDropped - item.SpriteDepth;
#endif
foreach (LightComponent light in item.GetComponents<LightComponent>())
{
light.CheckIfNeedsUpdate();
}
}
public override void ParseMsg()
@@ -165,31 +165,32 @@ namespace Barotrauma.Items.Components
pickTimer = 0.0f;
while (pickTimer < requiredTime && Screen.Selected != GameMain.SubEditorScreen)
{
//cancel if the item is currently selected
//attempting to pick does not select the item, so if it is selected at this point, another ItemComponent
//must have been selected and we should not keep deattaching (happens when for example interacting with
//an electrical component while holding both a screwdriver and a wrench).
if (picker.IsAnySelectedItem(item)||
picker.IsKeyDown(InputType.Aim) ||
!picker.CanInteractWith(item) ||
item.Removed || item.ParentInventory != null)
if (!CoroutineManager.Paused)
{
StopPicking(picker);
yield return CoroutineStatus.Success;
}
//cancel if the item is currently selected
//attempting to pick does not select the item, so if it is selected at this point, another ItemComponent
//must have been selected and we should not keep deattaching (happens when for example interacting with
//an electrical component while holding both a screwdriver and a wrench).
if (picker.IsAnySelectedItem(item) ||
picker.IsKeyDown(InputType.Aim) ||
!picker.CanInteractWith(item) ||
item.Removed || item.ParentInventory != null)
{
StopPicking(picker);
yield return CoroutineStatus.Success;
}
#if CLIENT
Character.Controlled?.UpdateHUDProgressBar(
this,
item.WorldPosition,
pickTimer / requiredTime,
GUIStyle.Red, GUIStyle.Green,
!string.IsNullOrWhiteSpace(PickingMsg) ? PickingMsg : this is Door ? "progressbar.opening" : "progressbar.deattaching");
Character.Controlled?.UpdateHUDProgressBar(
this,
item.WorldPosition,
pickTimer / requiredTime,
GUIStyle.Red, GUIStyle.Green,
!string.IsNullOrWhiteSpace(PickingMsg) ? PickingMsg : this is Door ? "progressbar.opening" : "progressbar.deattaching");
#endif
picker.AnimController.UpdateUseItem(!picker.IsClimbing, item.WorldPosition + new Vector2(0.0f, 100.0f) * ((pickTimer / 10.0f) % 0.1f));
pickTimer += CoroutineManager.DeltaTime;
picker.AnimController.UpdateUseItem(!picker.IsClimbing, item.WorldPosition + new Vector2(0.0f, 100.0f) * ((pickTimer / 10.0f) % 0.1f));
pickTimer += CoroutineManager.DeltaTime;
}
yield return CoroutineStatus.Running;
}
@@ -96,7 +96,7 @@ namespace Barotrauma.Items.Components
ApplyStatusEffects(ActionType.OnActive, deltaTime, null);
progressTimer += deltaTime * Math.Min(powerConsumption <= 0.0f ? 1 : Voltage, 1.0f);
progressTimer += deltaTime * Math.Min(powerConsumption <= 0.0f ? 1 : Voltage, MaxOverVoltageFactor);
float tinkeringStrength = 0f;
if (repairable.IsTinkering)
@@ -205,18 +205,18 @@ namespace Barotrauma.Items.Components
foreach (DeconstructItem deconstructProduct in products)
{
CreateDeconstructProduct(deconstructProduct, inputItems, amountMultiplier);
CreateDeconstructProduct(deconstructProduct, inputItems, (int)(amountMultiplier * deconstructProduct.Amount));
}
}
else
{
foreach (DeconstructItem deconstructProduct in validDeconstructItems)
{
CreateDeconstructProduct(deconstructProduct, inputItems, amountMultiplier);
CreateDeconstructProduct(deconstructProduct, inputItems, (int)(amountMultiplier * deconstructProduct.Amount));
}
}
void CreateDeconstructProduct(DeconstructItem deconstructProduct, IEnumerable<Item> inputItems, float amountMultiplier)
void CreateDeconstructProduct(DeconstructItem deconstructProduct, IEnumerable<Item> inputItems, int amount)
{
float percentageHealth = targetItem.Condition / targetItem.MaxCondition;
@@ -284,7 +284,6 @@ namespace Barotrauma.Items.Components
user.CheckTalents(AbilityEffectType.OnItemDeconstructedInventory, itemDeconstructedInventory);
}
int amount = (int)amountMultiplier;
for (int i = 0; i < amount; i++)
{
Entity.Spawner.AddItemToSpawnQueue(itemPrefab, outputContainer.Inventory, condition, onSpawned: (Item spawnedItem) =>
@@ -117,7 +117,7 @@ namespace Barotrauma.Items.Components
Force = MathHelper.Lerp(force, (Voltage < MinVoltage) ? 0.0f : targetForce, deltaTime * 10.0f);
if (Math.Abs(Force) > 1.0f)
{
float voltageFactor = MinVoltage <= 0.0f ? 1.0f : Math.Min(Voltage, 1.0f);
float voltageFactor = MinVoltage <= 0.0f ? 1.0f : Math.Min(Voltage, MaxOverVoltageFactor);
float currForce = force * voltageFactor;
float condition = item.Condition / item.MaxCondition;
// Broken engine makes more noise.
@@ -305,7 +305,7 @@ namespace Barotrauma.Items.Components
float fabricationSpeedIncrease = 1f + tinkeringStrength * TinkeringSpeedIncrease;
timeUntilReady -= deltaTime * fabricationSpeedIncrease * Math.Min(powerConsumption <= 0 ? 1 : Voltage, 1.0f);
timeUntilReady -= deltaTime * fabricationSpeedIncrease * Math.Min(powerConsumption <= 0 ? 1 : Voltage, MaxOverVoltageFactor);
UpdateRequiredTimeProjSpecific();
@@ -371,8 +371,7 @@ namespace Barotrauma.Items.Components
var availableItems = availableIngredients[requiredPrefab.Identifier];
var availableItem = availableItems.FirstOrDefault(potentialPrefab =>
{
return potentialPrefab.ConditionPercentage >= requiredItem.MinCondition * 100.0f &&
potentialPrefab.ConditionPercentage <= requiredItem.MaxCondition * 100.0f;
return requiredItem.IsConditionSuitable(potentialPrefab.ConditionPercentage);
});
if (availableItem == null) { continue; }
@@ -616,8 +615,7 @@ namespace Barotrauma.Items.Components
var availablePrefabs = availableIngredients[requiredPrefab.Identifier];
foreach (Item availablePrefab in availablePrefabs)
{
if (availablePrefab.ConditionPercentage / 100.0f >= requiredItem.MinCondition &&
availablePrefab.ConditionPercentage / 100.0f <= requiredItem.MaxCondition)
if (requiredItem.IsConditionSuitable(availablePrefab.ConditionPercentage))
{
availablePrefabsAmount++;
}
@@ -732,9 +730,7 @@ namespace Barotrauma.Items.Components
var availablePrefabs = availableIngredients[requiredPrefab.Identifier];
var availablePrefab = availablePrefabs.FirstOrDefault(potentialPrefab =>
{
return !usedItems.Contains(potentialPrefab) &&
potentialPrefab.ConditionPercentage >= requiredItem.MinCondition * 100.0f &&
potentialPrefab.ConditionPercentage <= requiredItem.MaxCondition * 100.0f;
return !usedItems.Contains(potentialPrefab) && requiredItem.IsConditionSuitable(potentialPrefab.ConditionPercentage);
});
if (availablePrefab == null) { continue; }
@@ -2,7 +2,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
namespace Barotrauma.Items.Components
{
@@ -52,7 +51,7 @@ namespace Barotrauma.Items.Components
return;
}
CurrFlow = Math.Min(PowerConsumption > 0 ? Voltage : 1.0f, 1.0f) * generatedAmount * 100.0f;
CurrFlow = Math.Min(PowerConsumption > 0 ? Voltage : 1.0f, MaxOverVoltageFactor) * generatedAmount * 100.0f;
float conditionMult = item.Condition / item.MaxCondition;
//100% condition = 100% oxygen
//50% condition = 25% oxygen
@@ -130,7 +130,7 @@ namespace Barotrauma.Items.Components
if (item.CurrentHull == null) { return; }
float powerFactor = Math.Min(currPowerConsumption <= 0.0f || MinVoltage <= 0.0f ? 1.0f : Voltage, 1.0f);
float powerFactor = Math.Min(currPowerConsumption <= 0.0f || MinVoltage <= 0.0f ? 1.0f : Voltage, MaxOverVoltageFactor);
currFlow = flowPercentage / 100.0f * maxFlow * powerFactor;
@@ -11,6 +11,8 @@ namespace Barotrauma.Items.Components
{
const float NetworkUpdateIntervalHigh = 0.5f;
const float TemperatureBoostAmount = 20;
//the rate at which the reactor is being run on (higher rate -> higher temperature)
private float fissionRate;
@@ -46,6 +48,8 @@ namespace Barotrauma.Items.Components
private Vector2 optimalFissionRate, allowedFissionRate;
private Vector2 optimalTurbineOutput, allowedTurbineOutput;
private float temperatureBoost;
private bool _powerOn;
[Serialize(defaultValue: false, isSaveable: IsPropertySaveable.Yes)]
@@ -241,6 +245,34 @@ namespace Barotrauma.Items.Components
}
#endif
if (signalControlledTargetFissionRate.HasValue && Math.Abs(signalControlledTargetFissionRate.Value - TargetFissionRate) > 1.0f)
{
TargetFissionRate = adjustValueWithoutOverShooting(TargetFissionRate, signalControlledTargetFissionRate.Value, deltaTime * 5.0f);
#if CLIENT
FissionRateScrollBar.BarScroll = TargetFissionRate / 100.0f;
#endif
}
else
{
signalControlledTargetFissionRate = null;
}
if (signalControlledTargetTurbineOutput.HasValue && Math.Abs(signalControlledTargetTurbineOutput.Value - TargetTurbineOutput) > 1.0f)
{
TargetTurbineOutput = adjustValueWithoutOverShooting(TargetTurbineOutput, signalControlledTargetTurbineOutput.Value, deltaTime * 5.0f);
#if CLIENT
TurbineOutputScrollBar.BarScroll = TargetTurbineOutput / 100.0f;
#endif
}
else
{
signalControlledTargetTurbineOutput = null;
}
static float adjustValueWithoutOverShooting(float current, float target, float speed)
{
return target < current ? Math.Max(target, current - speed) : Math.Min(target, current + speed);
}
prevAvailableFuel = AvailableFuel;
ApplyStatusEffects(ActionType.OnActive, deltaTime, null);
@@ -270,7 +302,10 @@ namespace Barotrauma.Items.Components
float temperatureDiff = (heatAmount - turbineOutput) - Temperature;
Temperature += MathHelper.Clamp(Math.Sign(temperatureDiff) * 10.0f * deltaTime, -Math.Abs(temperatureDiff), Math.Abs(temperatureDiff));
//if (item.InWater && AvailableFuel < 100.0f) Temperature -= 12.0f * deltaTime;
temperatureBoost = adjustValueWithoutOverShooting(temperatureBoost, 0.0f, deltaTime);
#if CLIENT
temperatureBoostUpButton.Enabled = temperatureBoostDownButton.Enabled = Math.Abs(temperatureBoost) < TemperatureBoostAmount * 0.9f;
#endif
FissionRate = MathHelper.Lerp(fissionRate, Math.Min(TargetFissionRate, AvailableFuel), deltaTime);
@@ -438,7 +473,7 @@ namespace Barotrauma.Items.Components
private float GetGeneratedHeat(float fissionRate)
{
return fissionRate * (prevAvailableFuel / 100.0f) * 2.0f;
return fissionRate * (prevAvailableFuel / 100.0f) * 2.0f + temperatureBoost;
}
/// <summary>
@@ -486,13 +521,15 @@ namespace Barotrauma.Items.Components
if (temperature > allowedTemperature.Y)
{
item.SendSignal("1", "meltdown_warning");
//faster meltdown if the item is in a bad condition
meltDownTimer += MathHelper.Lerp(deltaTime * 2.0f, deltaTime, item.Condition / item.MaxCondition);
if (meltDownTimer > MeltdownDelay)
if (!item.InvulnerableToDamage)
{
MeltDown();
return;
//faster meltdown if the item is in a bad condition
meltDownTimer += MathHelper.Lerp(deltaTime * 2.0f, deltaTime, item.Condition / item.MaxCondition);
if (meltDownTimer > MeltdownDelay)
{
MeltDown();
return;
}
}
}
else
@@ -797,30 +834,31 @@ namespace Barotrauma.Items.Components
AutoTemp = false;
TargetFissionRate = 0.0f;
TargetTurbineOutput = 0.0f;
if (GameMain.NetworkMember?.IsServer ?? false) { unsentChanges = true; }
registerUnsentChanges();
}
break;
case "set_fissionrate":
if (PowerOn && float.TryParse(signal.value, NumberStyles.Float, CultureInfo.InvariantCulture, out float newFissionRate))
{
TargetFissionRate = MathHelper.Clamp(newFissionRate, 0.0f, 100.0f);
if (GameMain.NetworkMember?.IsServer ?? false) { unsentChanges = true; }
#if CLIENT
FissionRateScrollBar.BarScroll = TargetFissionRate / 100.0f;
#endif
signalControlledTargetFissionRate = MathHelper.Clamp(newFissionRate, 0.0f, 100.0f);
registerUnsentChanges();
}
break;
case "set_turbineoutput":
if (PowerOn && float.TryParse(signal.value, NumberStyles.Float, CultureInfo.InvariantCulture, out float newTurbineOutput))
{
TargetTurbineOutput = MathHelper.Clamp(newTurbineOutput, 0.0f, 100.0f);
if (GameMain.NetworkMember?.IsServer ?? false) { unsentChanges = true; }
#if CLIENT
TurbineOutputScrollBar.BarScroll = TargetTurbineOutput / 100.0f;
#endif
signalControlledTargetTurbineOutput = MathHelper.Clamp(newTurbineOutput, 0.0f, 100.0f);
registerUnsentChanges();
}
break;
}
void registerUnsentChanges()
{
if (GameMain.NetworkMember is { IsServer: true }) { unsentChanges = true; }
}
}
private float? signalControlledTargetFissionRate, signalControlledTargetTurbineOutput;
}
}
@@ -98,7 +98,7 @@ namespace Barotrauma.Items.Components
set { maxRechargeSpeed = Math.Max(value, 1.0f); }
}
[Editable, Serialize(10.0f, IsPropertySaveable.Yes, description: "The current recharge speed of the device.")]
[Editable, Serialize(0.0f, IsPropertySaveable.Yes, description: "The current recharge speed of the device.")]
public float RechargeSpeed
{
get { return rechargeSpeed; }
@@ -243,8 +243,13 @@ namespace Barotrauma.Items.Components
//damage the item if voltage is too high (except if running as a client)
float prevCondition = item.Condition;
item.Condition -= deltaTime * 10.0f;
//some randomness to prevent all junction boxes from breaking at the same time
if (Rand.Range(0.0f, 1.0f) < 0.01f)
{
//damaged boxes are more sensitive to overvoltage (also preventing all boxes from breaking at the same time)
float conditionFactor = MathHelper.Lerp(5.0f, 1.0f, item.Condition / item.MaxCondition);
item.Condition -= deltaTime * Rand.Range(10.0f, 500.0f) * conditionFactor;
}
if (item.Condition <= 0.0f && prevCondition > 0.0f)
{
overloadCooldownTimer = OverloadCooldown;
@@ -94,6 +94,11 @@ namespace Barotrauma.Items.Components
protected Connection powerIn, powerOut;
/// <summary>
/// Maximum voltage factor when the device is being overvolted. I.e. how many times more effectively the device can function when it's being overvolted
/// </summary>
protected const float MaxOverVoltageFactor = 2.0f;
protected virtual PowerPriority Priority { get { return PowerPriority.Default; } }
[Editable, Serialize(0.5f, IsPropertySaveable.Yes, description: "The minimum voltage required for the device to function. " +
@@ -244,6 +244,13 @@ namespace Barotrauma.Items.Components
private set;
}
[Serialize(false, IsPropertySaveable.No)]
public bool DamageDoors
{
get;
set;
}
public bool IsStuckToTarget => StickTarget != null;
private Category originalCollisionCategories;
@@ -288,7 +295,7 @@ namespace Barotrauma.Items.Components
}
}
private void Launch(Character user, Vector2 simPosition, float rotation, float damageMultiplier = 1f)
private void Launch(Character user, Vector2 simPosition, float rotation, float damageMultiplier = 1f, float launchImpulseModifier = 0f)
{
Item.body.ResetDynamics();
Item.SetTransform(simPosition, rotation);
@@ -299,7 +306,7 @@ namespace Barotrauma.Items.Components
// Set user for hitscan projectiles to work properly.
User = user;
// Need to set null for non-characterusable items.
Use(character: null);
Use(character: null, launchImpulseModifier);
// Set user for normal projectiles to work properly.
User = user;
if (Item.Removed) { return; }
@@ -312,7 +319,7 @@ namespace Barotrauma.Items.Components
}
}
public void Shoot(Character user, Vector2 weaponPos, Vector2 spawnPos, float rotation, List<Body> ignoredBodies, bool createNetworkEvent, float damageMultiplier = 1f)
public void Shoot(Character user, Vector2 weaponPos, Vector2 spawnPos, float rotation, List<Body> ignoredBodies, bool createNetworkEvent, float damageMultiplier = 1f, float launchImpulseModifier = 0f)
{
//add the limbs of the shooter to the list of bodies to be ignored
//so that the player can't shoot himself
@@ -320,7 +327,7 @@ namespace Barotrauma.Items.Components
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,
customPredicate: (Fixture f) => { return !IgnoredBodies.Contains(f.Body); }) == null)
customPredicate: (Fixture f) => { return IgnoredBodies == null || !IgnoredBodies.Contains(f.Body); }) == null)
{
//no obstacles -> we can spawn the projectile at the barrel
projectilePos = spawnPos;
@@ -334,7 +341,7 @@ namespace Barotrauma.Items.Components
projectilePos = newPos;
}
}
Launch(user, projectilePos, rotation, damageMultiplier);
Launch(user, projectilePos, rotation, damageMultiplier, launchImpulseModifier);
if (createNetworkEvent && !Item.Removed && GameMain.NetworkMember != null && GameMain.NetworkMember.IsServer)
{
#if SERVER
@@ -344,7 +351,7 @@ namespace Barotrauma.Items.Components
}
}
public bool Use(Character character = null)
public bool Use(Character character = null, float launchImpulseModifier = 0f)
{
if (character != null && !characterUsable) { return false; }
@@ -379,7 +386,7 @@ namespace Barotrauma.Items.Components
else
{
item.body.SetTransform(item.body.SimPosition, launchAngle);
float modifiedLaunchImpulse = LaunchImpulse * (1 + Rand.Range(-ImpulseSpread, ImpulseSpread));
float modifiedLaunchImpulse = (LaunchImpulse + launchImpulseModifier) * (1 + Rand.Range(-ImpulseSpread, ImpulseSpread));
DoLaunch(launchDir * modifiedLaunchImpulse * item.body.Mass);
System.Diagnostics.Debug.WriteLine("launch: " + modifiedLaunchImpulse + " - " + item.body.LinearVelocity);
}
@@ -723,7 +730,7 @@ namespace Barotrauma.Items.Components
private bool OnProjectileCollision(Fixture f1, Fixture target, Contact contact)
{
if (User != null && User.Removed) { User = null; return false; }
if (IgnoredBodies.Contains(target.Body)) { return false; }
if (IgnoredBodies != null && IgnoredBodies.Contains(target.Body)) { return false; }
//ignore character colliders (the projectile only hits limbs)
if (target.CollisionCategories == Physics.CollisionCharacter && target.Body.UserData is Character)
{
@@ -828,7 +835,7 @@ namespace Barotrauma.Items.Components
private bool HandleProjectileCollision(Fixture target, Vector2 collisionNormal, Vector2 velocity)
{
if (User != null && User.Removed) { User = null; }
if (IgnoredBodies.Contains(target.Body)) { return false; }
if (IgnoredBodies != null && IgnoredBodies.Contains(target.Body)) { return false; }
//ignore character colliders (the projectile only hits limbs)
if (target.CollisionCategories == Physics.CollisionCharacter && target.Body.UserData is Character)
{
@@ -870,7 +877,7 @@ namespace Barotrauma.Items.Components
else if ((target.Body.UserData as Item ?? (target.Body.UserData as ItemComponent)?.Item) is Item targetItem)
{
if (targetItem.Removed) { return false; }
if (Attack != null && targetItem.Prefab.DamagedByProjectiles && targetItem.Condition > 0)
if (Attack != null && (targetItem.Prefab.DamagedByProjectiles || DamageDoors && targetItem.GetComponent<Door>() != null) && targetItem.Condition > 0)
{
attackResult = Attack.DoDamage(User ?? Attacker, targetItem, item.WorldPosition, 1.0f);
#if CLIENT
@@ -1067,7 +1074,7 @@ namespace Barotrauma.Items.Components
item.body.CollidesWith = Physics.CollisionWall | Physics.CollisionLevel;
}
}
IgnoredBodies.Clear();
IgnoredBodies?.Clear();
}
private void StickToTarget(Body targetBody, Vector2 axis)
@@ -23,6 +23,9 @@ namespace Barotrauma.Items.Components
private readonly HashSet<Wire> wires;
public IReadOnlyCollection<Wire> Wires => wires;
private bool enumeratingWires;
private readonly HashSet<Wire> removedWires = new HashSet<Wire>();
private readonly Item item;
public readonly bool IsOutput;
@@ -239,7 +242,14 @@ namespace Barotrauma.Items.Components
}
prevOtherConnection.recipientsDirty = true;
}
wires.Remove(wire);
if (enumeratingWires)
{
removedWires.Add(wire);
}
else
{
wires.Remove(wire);
}
recipientsDirty = true;
}
@@ -278,6 +288,7 @@ namespace Barotrauma.Items.Components
public void SendSignal(Signal signal)
{
enumeratingWires = true;
foreach (var wire in wires)
{
Connection recipient = wire.OtherConnection(this);
@@ -301,6 +312,12 @@ namespace Barotrauma.Items.Components
}
}
}
enumeratingWires = false;
foreach (var removedWire in removedWires)
{
wires.Remove(removedWire);
}
removedWires.Clear();
}
public void ClearConnections()
@@ -313,13 +330,23 @@ namespace Barotrauma.Items.Components
Powered.ChangedConnections.Add(c);
}
}
foreach (var wire in wires)
{
wire.RemoveConnection(this);
recipientsDirty = true;
}
wires.Clear();
if (enumeratingWires)
{
foreach (var wire in wires)
{
removedWires.Add(wire);
}
}
else
{
wires.Clear();
}
}
public void InitializeFromLoaded()
@@ -247,9 +247,14 @@ namespace Barotrauma.Items.Components
}
public override void OnMapLoaded()
{
CheckIfNeedsUpdate();
}
public void CheckIfNeedsUpdate()
{
if (item.body == null && powerConsumption <= 0.0f && Parent == null && turret == null && IsOn &&
(statusEffectLists == null || !statusEffectLists.ContainsKey(ActionType.OnActive)) &&
(statusEffectLists == null || !statusEffectLists.ContainsKey(ActionType.OnActive)) &&
(IsActiveConditionals == null || IsActiveConditionals.Count == 0))
{
lightBrightness = 1.0f;
@@ -261,6 +266,10 @@ namespace Barotrauma.Items.Components
Light.ParentSub = item.Submarine;
#endif
}
else
{
IsActive = true;
}
}
public override void Update(float deltaTime, Camera cam)
@@ -21,12 +21,15 @@ namespace Barotrauma.Items.Components
private float rotation, targetRotation;
private float reload, reloadTime;
private float reload, reloadTime, delayBetweenBurst;
private int shotsPerBurst, shotCounter;
private float minRotation, maxRotation;
private float launchImpulse;
private float damageMultiplier;
private Camera cam;
private float angularVelocity;
@@ -94,6 +97,16 @@ namespace Barotrauma.Items.Components
get;
set;
}
public bool flipFiringOffset;
[Serialize(false, IsPropertySaveable.No, description: "If enabled, the firing offset will alternate from left to right (i.e. flipping the x-component of the offset each shot.)")]
public bool AlternatingFiringOffset
{
get;
set;
}
public Vector2 TransformedBarrelPos
{
get
@@ -116,6 +129,20 @@ namespace Barotrauma.Items.Components
set { reloadTime = value; }
}
[Editable(1, 100), Serialize(1, IsPropertySaveable.No, description: "How many projectiles needs to be shot before we add an extra break? Think of the double coilgun.")]
public int ShotsPerBurst
{
get { return shotsPerBurst; }
set { shotsPerBurst = value; }
}
[Editable(0.0f, 1000.0f, decimals: 3), Serialize(0.0f, IsPropertySaveable.No, description: "An extra delay between the bursts. Added to the reload.")]
public float DelayBetweenBursts
{
get { return delayBetweenBurst; }
set { delayBetweenBurst = value; }
}
[Editable(0.1f, 10f), Serialize(1.0f, IsPropertySaveable.No, description: "Modifies the duration of retraction of the barrell after recoil to get back to the original position after shooting. Reload time affects this too.")]
public float RetractionDurationMultiplier
{
@@ -137,6 +164,13 @@ namespace Barotrauma.Items.Components
set;
}
[Serialize(1.0f, IsPropertySaveable.No, description: "Multiplies the damage the turret deals by this amount.")]
public float DamageMultiplier
{
get { return damageMultiplier; }
set { damageMultiplier = value; }
}
[Serialize(1, IsPropertySaveable.No, description: "How many projectiles the weapon launches when fired once.")]
public int ProjectileCount
{
@@ -602,9 +636,9 @@ namespace Barotrauma.Items.Components
if (projectiles.Any())
{
ItemContainer projectileContainer = projectiles.First().Item.Container?.GetComponent<ItemContainer>();
if (projectileContainer != null && projectileContainer.Item != item)
{
projectileContainer?.Item.Use(deltaTime, null);
if (projectileContainer != null && projectileContainer.Item != item)
{
projectileContainer?.Item.Use(deltaTime, null);
}
}
else
@@ -764,6 +798,15 @@ namespace Barotrauma.Items.Components
private void Launch(Item projectile, Character user = null, float? launchRotation = null, float tinkeringStrength = 0f)
{
reload = reloadTime;
if (ShotsPerBurst > 1)
{
shotCounter++;
if (shotCounter >= ShotsPerBurst)
{
reload += DelayBetweenBursts;
shotCounter = 0;
}
}
reload /= 1f + (tinkeringStrength * TinkeringReloadDecrease);
if (user != null)
@@ -773,6 +816,10 @@ namespace Barotrauma.Items.Components
if (projectile != null)
{
if (AlternatingFiringOffset)
{
flipFiringOffset = !flipFiringOffset;
}
activeProjectiles.Add(projectile);
projectile.Drop(null, setTransform: false);
if (projectile.body != null)
@@ -796,9 +843,9 @@ namespace Barotrauma.Items.Components
projectileComponent.Attacker = projectileComponent.User = user;
if (projectileComponent.Attack != null)
{
projectileComponent.Attack.DamageMultiplier = 1f + (TinkeringDamageIncrease * tinkeringStrength);
projectileComponent.Attack.DamageMultiplier = (1f * DamageMultiplier) + (TinkeringDamageIncrease * tinkeringStrength);
}
projectileComponent.Use();
projectileComponent.Use(null, LaunchImpulse);
projectile.GetComponent<Rope>()?.Attach(item, projectile);
projectileComponent.User = user;
@@ -1452,7 +1499,9 @@ namespace Barotrauma.Items.Components
Vector2 transformedFiringOffset = Vector2.Zero;
if (useOffset)
{
transformedFiringOffset = MathUtils.RotatePoint(new Vector2(-FiringOffset.Y, -FiringOffset.X) * item.Scale, -rotation);
Vector2 currOffSet = FiringOffset;
if (flipFiringOffset) { currOffSet.X = -currOffSet.X; }
transformedFiringOffset = MathUtils.RotatePoint(new Vector2(-currOffSet.Y, -currOffSet.X) * item.Scale, -rotation);
}
return new Vector2(item.WorldRect.X + transformedBarrelPos.X + transformedFiringOffset.X, item.WorldRect.Y - transformedBarrelPos.Y + transformedFiringOffset.Y);
}