(ad567dea) v0.9.7.1

This commit is contained in:
Juan Pablo Arce
2020-03-04 19:54:29 -03:00
parent 3c09ebe02f
commit 3e99a49383
212 changed files with 1970 additions and 3265 deletions
@@ -58,13 +58,6 @@ namespace Barotrauma.Items.Components
set;
}
[Serialize(false, false, description: "If set to true, this docking port is used when spawning the submarine docked to an outpost (if possible).")]
public bool MainDockingPort
{
get;
set;
}
public DockingPort DockingTarget { get; private set; }
public bool Docked
@@ -180,8 +173,8 @@ namespace Barotrauma.Items.Components
if (!item.linkedTo.Contains(target.item)) item.linkedTo.Add(target.item);
if (!target.item.linkedTo.Contains(item)) target.item.linkedTo.Add(item);
if (!target.item.Submarine.DockedTo.Contains(item.Submarine)) target.item.Submarine.ConnectedDockingPorts.Add(item.Submarine, target);
if (!item.Submarine.DockedTo.Contains(target.item.Submarine)) item.Submarine.ConnectedDockingPorts.Add(target.item.Submarine, this);
if (!target.item.Submarine.DockedTo.Contains(item.Submarine)) target.item.Submarine.DockedTo.Add(item.Submarine);
if (!item.Submarine.DockedTo.Contains(target.item.Submarine)) item.Submarine.DockedTo.Add(target.item.Submarine);
DockingTarget = target;
DockingTarget.DockingTarget = this;
@@ -710,8 +703,8 @@ namespace Barotrauma.Items.Components
ApplyStatusEffects(ActionType.OnSecondaryUse, 1.0f);
DockingTarget.item.Submarine.ConnectedDockingPorts.Remove(item.Submarine);
item.Submarine.ConnectedDockingPorts.Remove(DockingTarget.item.Submarine);
DockingTarget.item.Submarine.DockedTo.Remove(item.Submarine);
item.Submarine.DockedTo.Remove(DockingTarget.item.Submarine);
if (door != null && DockingTarget.door != null)
{
@@ -287,21 +287,24 @@ namespace Barotrauma.Items.Components
public override bool Select(Character character)
{
if (isBroken) { return true; }
bool hasRequiredItems = HasRequiredItems(character, false);
if (HasAccess(character))
if (!isBroken)
{
float originalPickingTime = PickingTime;
PickingTime = 0;
ToggleState(ActionType.OnUse, character);
PickingTime = originalPickingTime;
}
bool hasRequiredItems = HasRequiredItems(character, false);
if (HasAccess(character))
{
float originalPickingTime = PickingTime;
PickingTime = 0;
ToggleState(ActionType.OnUse, character);
PickingTime = originalPickingTime;
}
#if CLIENT
else if (hasRequiredItems && character != null && character == Character.Controlled)
{
GUI.AddMessage(accessDeniedTxt, GUI.Style.Red);
}
else if (hasRequiredItems && character != null && character == Character.Controlled)
{
GUI.AddMessage(accessDeniedTxt, GUI.Style.Red);
}
#endif
}
return false;
}
@@ -54,7 +54,7 @@ namespace Barotrauma.Items.Components
{
foreach (XElement subElement in element.Elements())
{
if (!subElement.Name.ToString().Equals("attack", StringComparison.OrdinalIgnoreCase)) { continue; }
if (subElement.Name.ToString().ToLowerInvariant() != "attack") { continue; }
attack = new Attack(subElement, item.Name + ", MeleeWeapon");
}
item.IsShootable = true;
@@ -29,13 +29,6 @@ namespace Barotrauma.Items.Components
set { reload = Math.Max(value, 0.0f); }
}
[Serialize(1, false, description: "How projectiles the weapon launches when fired once.")]
public int ProjectileCount
{
get;
set;
}
[Serialize(0.0f, false, description: "Random spread applied to the firing angle of the projectiles when used by a character with sufficient skills to use the weapon (in degrees).")]
public float Spread
{
@@ -117,61 +110,55 @@ namespace Barotrauma.Items.Components
ApplyStatusEffects(ActionType.OnFailure, 1.0f, character);
}
for (int i = 0; i < ProjectileCount; i++)
Projectile projectile = FindProjectile(triggerOnUseOnContainers: true);
if (projectile == null) { return true; }
float spread = GetSpread(character);
float rotation = (item.body.Dir == 1.0f) ? item.body.Rotation : item.body.Rotation - MathHelper.Pi;
rotation += spread * Rand.Range(-0.5f, 0.5f);
projectile.User = character;
//add the limbs of the shooter to the list of bodies to be ignored
//so that the player can't shoot himself
projectile.IgnoredBodies = new List<Body>(limbBodies);
Vector2 projectilePos = item.SimPosition;
Vector2 sourcePos = character?.AnimController == null ? item.SimPosition : character.AnimController.AimSourceSimPos;
Vector2 barrelPos = TransformedBarrelPos + item.body.SimPosition;
//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(sourcePos, barrelPos, projectile.IgnoredBodies, Physics.CollisionWall | Physics.CollisionLevel | Physics.CollisionItemBlocking) == null)
{
Projectile projectile = FindProjectile(triggerOnUseOnContainers: true);
if (projectile == null) { return true; }
float spread = GetSpread(character);
float rotation = (item.body.Dir == 1.0f) ? item.body.Rotation : item.body.Rotation - MathHelper.Pi;
rotation += spread * Rand.Range(-0.5f, 0.5f);
projectile.User = character;
//add the limbs of the shooter to the list of bodies to be ignored
//so that the player can't shoot himself
projectile.IgnoredBodies = new List<Body>(limbBodies);
Vector2 projectilePos = item.SimPosition;
Vector2 sourcePos = character?.AnimController == null ? item.SimPosition : character.AnimController.AimSourceSimPos;
Vector2 barrelPos = TransformedBarrelPos + item.body.SimPosition;
//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(sourcePos, barrelPos, projectile.IgnoredBodies, Physics.CollisionWall | Physics.CollisionLevel | Physics.CollisionItemBlocking) == null)
{
//no obstacles -> we can spawn the projectile at the barrel
projectilePos = barrelPos;
}
else if ((sourcePos - barrelPos).LengthSquared() > 0.0001f)
{
//spawn the projectile body.GetMaxExtent() away from the position where the raycast hit the obstacle
projectilePos = sourcePos - Vector2.Normalize(barrelPos - projectilePos) * Math.Max(projectile.Item.body.GetMaxExtent(), 0.1f);
}
projectile.Item.body.ResetDynamics();
projectile.Item.SetTransform(projectilePos, rotation);
projectile.Use(deltaTime);
if (projectile.Item.Removed) { continue; }
projectile.User = character;
projectile.Item.body.ApplyTorque(projectile.Item.body.Mass * degreeOfFailure * Rand.Range(-10.0f, 10.0f));
//set the rotation of the projectile again because dropping the projectile resets the rotation
projectile.Item.SetTransform(projectilePos,
rotation + (projectile.Item.body.Dir * projectile.LaunchRotationRadians));
item.RemoveContained(projectile.Item);
if (i == 0)
{
//recoil
item.body.ApplyLinearImpulse(
new Vector2((float)Math.Cos(projectile.Item.body.Rotation), (float)Math.Sin(projectile.Item.body.Rotation)) * item.body.Mass * -50.0f,
maxVelocity: NetConfig.MaxPhysicsBodyVelocity);
}
//no obstacles -> we can spawn the projectile at the barrel
projectilePos = barrelPos;
}
else if ((sourcePos - barrelPos).LengthSquared() > 0.0001f)
{
//spawn the projectile body.GetMaxExtent() away from the position where the raycast hit the obstacle
projectilePos = sourcePos - Vector2.Normalize(barrelPos - projectilePos) * Math.Max(projectile.Item.body.GetMaxExtent(), 0.1f);
}
projectile.Item.body.ResetDynamics();
projectile.Item.SetTransform(projectilePos, rotation);
projectile.Use(deltaTime);
if (projectile.Item.Removed) { return true; }
projectile.User = character;
projectile.Item.body.ApplyTorque(projectile.Item.body.Mass * degreeOfFailure * Rand.Range(-10.0f, 10.0f));
//set the rotation of the projectile again because dropping the projectile resets the rotation
projectile.Item.SetTransform(projectilePos,
rotation + (projectile.Item.body.Dir * projectile.LaunchRotationRadians));
//recoil
item.body.ApplyLinearImpulse(
new Vector2((float)Math.Cos(projectile.Item.body.Rotation), (float)Math.Sin(projectile.Item.body.Rotation)) * item.body.Mass * -50.0f,
maxVelocity: NetConfig.MaxPhysicsBodyVelocity);
LaunchProjSpecific();
item.RemoveContained(projectile.Item);
return true;
}
@@ -578,7 +578,13 @@ namespace Barotrauma.Items.Components
{
character.SetInput(InputType.Aim, false, true);
}
sinTime += deltaTime * 5;
bool isAiming = false;
var holdable = item.GetComponent<Holdable>();
if (holdable != null)
{
isAiming = holdable.ControlPose;
}
sinTime = isAiming ? sinTime + deltaTime * 5 : 0;
}
// Press the trigger only when the tool is approximately facing the target.
Vector2 fromItemToLeak = leak.WorldPosition - item.WorldPosition;
@@ -741,7 +741,7 @@ namespace Barotrauma.Items.Components
{
foreach (XAttribute attribute in componentElement.Attributes())
{
if (!SerializableProperties.TryGetValue(attribute.Name.ToString().ToLowerInvariant(), out SerializableProperty property)) { continue; }
if (!SerializableProperties.TryGetValue(attribute.Name.ToString().ToLowerInvariant(), out SerializableProperty property)) continue;
property.TrySetValue(this, attribute.Value);
}
ParseMsg();
@@ -870,7 +870,6 @@ namespace Barotrauma.Items.Components
switch (subElement.Name.ToString().ToLowerInvariant())
{
case "requireditem":
case "requireditems":
RelatedItem newRequiredItem = RelatedItem.Load(subElement, returnEmptyRequirements, item.Name);
if (newRequiredItem == null) continue;
@@ -39,7 +39,7 @@ namespace Barotrauma.Items.Components
{
foreach (XElement subElement in element.Elements())
{
if (subElement.Name.ToString().Equals("fabricableitem", StringComparison.OrdinalIgnoreCase))
if (subElement.Name.ToString().ToLowerInvariant() == "fabricableitem")
{
DebugConsole.ThrowError("Error in item " + item.Name + "! Fabrication recipes should be defined in the craftable item's xml, not in the fabricator.");
break;
@@ -144,7 +144,7 @@ namespace Barotrauma.Items.Components
if (GameMain.Client != null) { return false; }
#endif
if (objective.Option.Equals("stoppumping", StringComparison.OrdinalIgnoreCase))
if (objective.Option.ToLowerInvariant() == "stoppumping")
{
#if SERVER
if (FlowPercentage > 0.0f)
@@ -5,7 +5,6 @@ using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using Barotrauma.Extensions;
using System.Globalization;
namespace Barotrauma.Items.Components
{
@@ -652,20 +651,6 @@ namespace Barotrauma.Items.Components
unsentChanges = true;
}
break;
case "set_fissionrate":
if (float.TryParse(signal, NumberStyles.Float, CultureInfo.InvariantCulture, out float newFissionRate))
{
FissionRate = newFissionRate;
unsentChanges = true;
}
break;
case "set_turbineoutput":
if (float.TryParse(signal, NumberStyles.Float, CultureInfo.InvariantCulture, out float newTurbineOutput))
{
TurbineOutput = newTurbineOutput;
unsentChanges = true;
}
break;
}
}
@@ -213,7 +213,7 @@ namespace Barotrauma.Items.Components
}
if (HasBeenTuned) { return true; }
if (string.IsNullOrEmpty(objective.Option) || objective.Option.Equals("charge", StringComparison.OrdinalIgnoreCase))
if (string.IsNullOrEmpty(objective.Option) || objective.Option.ToLowerInvariant() == "charge")
{
if (Math.Abs(rechargeSpeed - maxRechargeSpeed * aiRechargeTargetRatio) > 0.05f)
{
@@ -53,9 +53,7 @@ namespace Barotrauma.Items.Components
private PrismaticJoint stickJoint;
private Body stickTarget;
private readonly Attack attack;
private Vector2 launchPos;
private Attack attack;
public List<Body> IgnoredBodies;
@@ -159,7 +157,7 @@ namespace Barotrauma.Items.Components
foreach (XElement subElement in element.Elements())
{
if (!subElement.Name.ToString().Equals("attack", StringComparison.OrdinalIgnoreCase)) { continue; }
if (subElement.Name.ToString().ToLowerInvariant() != "attack") continue;
attack = new Attack(subElement, item.Name + ", Projectile");
}
}
@@ -222,8 +220,6 @@ namespace Barotrauma.Items.Components
item.Drop(null);
launchPos = item.SimPosition;
item.body.Enabled = true;
item.body.ApplyLinearImpulse(impulse, maxVelocity: NetConfig.MaxPhysicsBodyVelocity);
@@ -419,9 +415,7 @@ namespace Barotrauma.Items.Components
item.body.SimPosition - ConvertUnits.ToSimUnits(sub.Position) - dir,
item.body.SimPosition - ConvertUnits.ToSimUnits(sub.Position) + dir,
collisionCategory: Physics.CollisionWall);
if (wallBody?.FixtureList?.First() != null && wallBody.UserData is Structure structure &&
//ignore the hit if it's behind the position the item was launched from, and the projectile is travelling in the opposite direction
Vector2.Dot(item.body.SimPosition - launchPos, dir) > 0)
if (wallBody?.FixtureList?.First() != null && wallBody.UserData is Structure structure)
{
target = wallBody.FixtureList.First();
}
@@ -1,5 +1,4 @@
using Barotrauma.Extensions;
using Barotrauma.Networking;
using Barotrauma.Networking;
using Microsoft.Xna.Framework;
using System;
using System.Globalization;
@@ -112,7 +111,7 @@ namespace Barotrauma.Items.Components
element.GetAttributeString("name", "");
//backwards compatibility
var showRepairUIAttribute = element.Attributes().FirstOrDefault(a => a.Name.ToString().Equals("showrepairuithreshold", StringComparison.OrdinalIgnoreCase));
var showRepairUIAttribute = element.Attributes().FirstOrDefault(a => a.Name.ToString().ToLowerInvariant() == "showrepairuithreshold");
if (showRepairUIAttribute != null)
{
float repairThreshold;
@@ -131,26 +130,7 @@ namespace Barotrauma.Items.Components
}
partial void InitProjSpecific(XElement element);
/// <summary>
/// Check if the character manages to succesfully repair the item
/// </summary>
public bool CheckCharacterSuccess(Character character)
{
if (character == null) { return false; }
// Only check for success when repairing electrical devices
if (requiredSkills.None(s => s != null && s.Identifier.Equals("electrical", StringComparison.OrdinalIgnoreCase))) { return true; }
//unpowered items can be repaired without a risk of electrical shock
if (item.GetComponent<Powered>() is Powered powered && powered.Voltage < 0.1f) { return true; }
if (Rand.Range(0.0f, 0.5f) < DegreeOfSuccess(character)) { return true; }
item.ApplyStatusEffects(ActionType.OnFailure, 1.0f, character);
return false;
}
public bool StartRepairing(Character character, FixActions action)
{
if (character == null || character.IsDead || action == FixActions.None)
@@ -163,15 +143,8 @@ namespace Barotrauma.Items.Components
#if SERVER
if (CurrentFixer != character || currentFixerAction != action)
{
if (!CheckCharacterSuccess(character))
{
GameMain.Server?.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.ApplyStatusEffect, ActionType.OnFailure, this, character.ID });
return false;
}
item.CreateServerEvent(this);
}
#else
if (GameMain.Client == null && (CurrentFixer != character || currentFixerAction != action) && !CheckCharacterSuccess(character)) { return false; }
#endif
CurrentFixer = character;
CurrentFixerAction = action;
@@ -88,7 +88,7 @@ namespace Barotrauma.Items.Components
{
foreach (XElement subElement in item.Prefab.ConfigElement.Elements())
{
if (!subElement.Name.ToString().Equals("connectionpanel", StringComparison.OrdinalIgnoreCase)) { continue; }
if (subElement.Name.ToString().ToLowerInvariant() != "connectionpanel") { continue; }
foreach (XElement connectionElement in subElement.Elements())
{
@@ -32,7 +32,7 @@ namespace Barotrauma.Items.Components
foreach (XElement subElement in element.Elements())
{
if (subElement.Name.ToString().Equals("statuseffect", System.StringComparison.OrdinalIgnoreCase))
if (subElement.Name.ToString().ToLowerInvariant() == "statuseffect")
{
StatusEffects.Add(StatusEffect.Load(subElement, parentDebugName: "custom interface element (label " + Label + ")"));
}
@@ -272,12 +272,13 @@ namespace Barotrauma.Items.Components
private void UpdateAITarget(AITarget target)
{
target.Enabled = IsActive;
if (!IsActive) { return; }
if (target.MaxSightRange <= 0)
{
target.MaxSightRange = Range * 5;
}
target.SightRange = Math.Max(target.SightRange, target.MaxSightRange * lightBrightness);
target.SightRange = target.MaxSightRange * lightBrightness;
}
partial void SetLightSourceState(bool enabled, float brightness);
@@ -39,14 +39,6 @@ namespace Barotrauma.Items.Components
}
}
[Serialize(false, false, description: "Can the component communicate with wifi components in another team's submarine (e.g. enemy sub in Combat missions, respawn shuttle). Needs to be enabled on both the component transmitting the signal and the component receiving it.")]
public bool AllowCrossTeamCommunication
{
get;
set;
}
[Editable, Serialize(false, false, description: "If enabled, any signals received from another chat-linked wifi component are displayed " +
"as chat messages in the chatbox of the player holding the item.")]
public bool LinkToChat
@@ -92,7 +84,7 @@ namespace Barotrauma.Items.Components
{
if (sender == null || sender.channel != channel) { return false; }
if (sender.TeamID != TeamID && !AllowCrossTeamCommunication)
if (sender.TeamID != TeamID)
{
return false;
}
@@ -72,13 +72,6 @@ namespace Barotrauma.Items.Components
set { reloadTime = value; }
}
[Serialize(1, false, description: "How projectiles the weapon launches when fired once.")]
public int ProjectileCount
{
get;
set;
}
[Editable, Serialize("0.0,0.0", true, description: "The range at which the barrel can rotate. TODO")]
public Vector2 RotationLimits
{
@@ -220,13 +213,13 @@ namespace Barotrauma.Items.Components
{
this.cam = cam;
if (reload > 0.0f) { reload -= deltaTime; }
if (reload > 0.0f) reload -= deltaTime;
ApplyStatusEffects(ActionType.OnActive, deltaTime, null);
UpdateProjSpecific(deltaTime);
if (minRotation == maxRotation) { return; }
if (minRotation == maxRotation) return;
float targetMidDiff = MathHelper.WrapAngle(targetRotation - (minRotation + maxRotation) / 2.0f);
@@ -237,19 +230,12 @@ namespace Barotrauma.Items.Components
targetRotation = (targetMidDiff < 0.0f) ? minRotation : maxRotation;
}
float degreeOfSuccess = user == null ? 0.5f : DegreeOfSuccess(user);
if (degreeOfSuccess < 0.5f) { degreeOfSuccess *= degreeOfSuccess; } //the ease of aiming drops quickly with insufficient skill levels
float degreeOfSuccess = user == null ? 0.5f : DegreeOfSuccess(user);
if (degreeOfSuccess < 0.5f) degreeOfSuccess *= degreeOfSuccess; //the ease of aiming drops quickly with insufficient skill levels
float springStiffness = MathHelper.Lerp(SpringStiffnessLowSkill, SpringStiffnessHighSkill, degreeOfSuccess);
float springDamping = MathHelper.Lerp(SpringDampingLowSkill, SpringDampingHighSkill, degreeOfSuccess);
float rotationSpeed = MathHelper.Lerp(RotationSpeedLowSkill, RotationSpeedHighSkill, degreeOfSuccess);
if (user?.Info != null)
{
user.Info.IncreaseSkillLevel("weapons",
SkillSettings.Current.SkillIncreasePerSecondWhenOperatingTurret * deltaTime / Math.Max(user.GetSkillLevel("weapons"), 1.0f),
user.WorldPosition + Vector2.UnitY * 150.0f);
}
angularVelocity +=
(MathHelper.WrapAngle(targetRotation - rotation) * springStiffness - angularVelocity * springDamping) * deltaTime;
angularVelocity = MathHelper.Clamp(angularVelocity, -rotationSpeed, rotationSpeed);
@@ -279,16 +265,18 @@ namespace Barotrauma.Items.Components
public override bool Use(float deltaTime, Character character = null)
{
if (!characterUsable && character != null) { return false; }
if (!characterUsable && character != null) return false;
return TryLaunch(deltaTime, character);
}
private bool TryLaunch(float deltaTime, Character character = null)
{
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) { return false; }
#if CLIENT
if (GameMain.Client != null) return false;
#endif
if (reload > 0.0f) return false;
if (reload > 0.0f) { return false; }
if (GetAvailableBatteryPower() < powerConsumption)
{
#if CLIENT
@@ -300,77 +288,72 @@ namespace Barotrauma.Items.Components
#endif
return false;
}
Projectile launchedProjectile = null;
for (int i = 0; i < ProjectileCount; i++)
foreach (MapEntity e in item.linkedTo)
{
foreach (MapEntity e in item.linkedTo)
//use linked projectile containers in case they have to react to the turret being launched somehow
//(play a sound, spawn more projectiles)
if (!(e is Item linkedItem)) continue;
ItemContainer projectileContainer = linkedItem.GetComponent<ItemContainer>();
if (projectileContainer != null)
{
//use linked projectile containers in case they have to react to the turret being launched somehow
//(play a sound, spawn more projectiles)
if (!(e is Item linkedItem)) { continue; }
ItemContainer projectileContainer = linkedItem.GetComponent<ItemContainer>();
if (projectileContainer != null)
linkedItem.Use(deltaTime, null);
var repairable = linkedItem.GetComponent<Repairable>();
if (repairable != null)
{
linkedItem.Use(deltaTime, null);
var repairable = linkedItem.GetComponent<Repairable>();
if (repairable != null)
{
repairable.LastActiveTime = (float)Timing.TotalTime + 1.0f;
}
repairable.LastActiveTime = (float)Timing.TotalTime + 1.0f;
}
}
var projectiles = GetLoadedProjectiles(true);
if (projectiles.Count == 0)
{
//coilguns spawns ammo in the ammo boxes with the OnUse statuseffect when the turret is launched,
//causing a one frame delay before the gun can be launched (or more in multiplayer where there may be a longer delay)
// -> attempt to launch the gun multiple times before showing the "no ammo" flash
failedLaunchAttempts++;
#if CLIENT
if (!flashNoAmmo && character != null && character == Character.Controlled && failedLaunchAttempts > 20)
{
flashNoAmmo = true;
failedLaunchAttempts = 0;
GUI.PlayUISound(GUISoundType.PickItemFail);
}
#endif
return false;
}
failedLaunchAttempts = 0;
var batteries = item.GetConnectedComponents<PowerContainer>();
float neededPower = powerConsumption;
while (neededPower > 0.0001f && batteries.Count > 0)
{
batteries.RemoveAll(b => b.Charge <= 0.0001f || b.MaxOutPut <= 0.0001f);
float takePower = neededPower / batteries.Count;
takePower = Math.Min(takePower, batteries.Min(b => Math.Min(b.Charge * 3600.0f, b.MaxOutPut)));
foreach (PowerContainer battery in batteries)
{
neededPower -= takePower;
battery.Charge -= takePower / 3600.0f;
#if SERVER
if (GameMain.Server != null)
{
battery.Item.CreateServerEvent(battery);
}
#endif
}
}
launchedProjectile = projectiles[0];
Launch(projectiles[0].Item, character);
}
#if SERVER
if (character != null && launchedProjectile != null)
var projectiles = GetLoadedProjectiles(true);
if (projectiles.Count == 0)
{
string msg = character.LogName + " launched " + item.Name + " (projectile: " + launchedProjectile.Item.Name;
var containedItems = launchedProjectile.Item.ContainedItems;
//coilguns spawns ammo in the ammo boxes with the OnUse statuseffect when the turret is launched,
//causing a one frame delay before the gun can be launched (or more in multiplayer where there may be a longer delay)
// -> attempt to launch the gun multiple times before showing the "no ammo" flash
failedLaunchAttempts++;
#if CLIENT
if (!flashNoAmmo && character != null && character == Character.Controlled && failedLaunchAttempts > 20)
{
flashNoAmmo = true;
failedLaunchAttempts = 0;
GUI.PlayUISound(GUISoundType.PickItemFail);
}
#endif
return false;
}
failedLaunchAttempts = 0;
var batteries = item.GetConnectedComponents<PowerContainer>();
float neededPower = powerConsumption;
while (neededPower > 0.0001f && batteries.Count > 0)
{
batteries.RemoveAll(b => b.Charge <= 0.0001f || b.MaxOutPut <= 0.0001f);
float takePower = neededPower / batteries.Count;
takePower = Math.Min(takePower, batteries.Min(b => Math.Min(b.Charge * 3600.0f, b.MaxOutPut)));
foreach (PowerContainer battery in batteries)
{
neededPower -= takePower;
battery.Charge -= takePower / 3600.0f;
#if SERVER
if (GameMain.Server != null)
{
battery.Item.CreateServerEvent(battery);
}
#endif
}
}
Launch(projectiles[0].Item, character);
#if SERVER
if (character != null)
{
string msg = character.LogName + " launched " + item.Name + " (projectile: " + projectiles[0].Item.Name;
var containedItems = projectiles[0].Item.ContainedItems;
if (containedItems == null || !containedItems.Any())
{
msg += ")";
@@ -564,7 +547,7 @@ namespace Barotrauma.Items.Components
return false;
}
if (objective.Option.Equals("fireatwill", StringComparison.OrdinalIgnoreCase))
if (objective.Option.ToLowerInvariant() == "fireatwill")
{
character?.Speak(TextManager.GetWithVariable("DialogFireTurret", "[itemname]", item.Name, true), null, 0.0f, "fireturret", 5.0f);
character.SetInput(InputType.Shoot, true, true);
@@ -211,7 +211,6 @@ namespace Barotrauma.Items.Components
}
public bool AutoEquipWhenFull { get; private set; }
public bool DisplayContainedStatus { get; private set; }
public readonly int Variants;
@@ -265,7 +264,6 @@ namespace Barotrauma.Items.Components
limbType = new LimbType[spriteCount];
limb = new Limb[spriteCount];
AutoEquipWhenFull = element.GetAttributeBool("autoequipwhenfull", true);
DisplayContainedStatus = element.GetAttributeBool("displaycontainedstatus", false);
int i = 0;
foreach (XElement subElement in element.Elements())
{
@@ -286,7 +284,7 @@ namespace Barotrauma.Items.Components
foreach (XElement lightElement in subElement.Elements())
{
if (!lightElement.Name.ToString().Equals("lightcomponent", StringComparison.OrdinalIgnoreCase)) { continue; }
if (lightElement.Name.ToString().ToLowerInvariant() != "lightcomponent") continue;
wearableSprites[i].LightComponent = new LightComponent(item, lightElement)
{
Parent = this