@@ -442,7 +442,7 @@ namespace Barotrauma
|
||||
Character.AnimController.InWater ||
|
||||
Character.AnimController.HeadInWater ||
|
||||
Character.CurrentHull == null ||
|
||||
Character.Submarine.TeamID != Character.TeamID ||
|
||||
Character.Submarine?.TeamID != Character.TeamID ||
|
||||
ObjectiveManager.IsCurrentObjective<AIObjectiveFindSafety>() ||
|
||||
ObjectiveManager.CurrentOrder is AIObjectiveGoTo goTo && goTo.Target == Character || // wait order
|
||||
ObjectiveManager.CurrentObjective.GetSubObjectivesRecursive(true).Any(o => o.KeepDivingGearOn);
|
||||
|
||||
+31
-18
@@ -245,6 +245,12 @@ namespace Barotrauma
|
||||
{
|
||||
IsCompleted = true;
|
||||
}
|
||||
else if (Enemy.IsKnockedDown &&
|
||||
!objectiveManager.IsCurrentObjective<AIObjectiveFightIntruders>() &&
|
||||
!HumanAIController.HasItem(character, "handlocker", out _, requireEquipped: false))
|
||||
{
|
||||
IsCompleted = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -738,7 +744,7 @@ namespace Barotrauma
|
||||
},
|
||||
onAbandon: () => Abandon = true);
|
||||
if (followTargetObjective == null) { return; }
|
||||
if (Mode == CombatMode.Arrest && (Enemy.Stun > 1 || Enemy.IsKnockedDown))
|
||||
if (Mode == CombatMode.Arrest && Enemy.IsKnockedDown)
|
||||
{
|
||||
if (HumanAIController.HasItem(character, "handlocker", out _))
|
||||
{
|
||||
@@ -786,6 +792,23 @@ namespace Barotrauma
|
||||
|
||||
private void OnArrestTargetReached()
|
||||
{
|
||||
if (!Enemy.IsKnockedDown)
|
||||
{
|
||||
RemoveFollowTarget();
|
||||
return;
|
||||
}
|
||||
if (character.TeamID == CharacterTeamType.FriendlyNPC)
|
||||
{
|
||||
// Confiscate stolen goods.
|
||||
foreach (var item in Enemy.Inventory.AllItemsMod)
|
||||
{
|
||||
if (item.StolenDuringRound)
|
||||
{
|
||||
item.Drop(character);
|
||||
character.Inventory.TryPutItem(item, character, CharacterInventory.anySlot);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (HumanAIController.HasItem(character, "handlocker", out IEnumerable<Item> matchingItems) && !Enemy.IsUnconscious && Enemy.IsKnockedDown && character.CanInteractWith(Enemy))
|
||||
{
|
||||
var handCuffs = matchingItems.First();
|
||||
@@ -794,20 +817,18 @@ namespace Barotrauma
|
||||
#if DEBUG
|
||||
DebugConsole.NewMessage($"{character.Name}: Failed to handcuff the target.", Color.Red);
|
||||
#endif
|
||||
}
|
||||
// Confiscate stolen goods.
|
||||
foreach (var item in Enemy.Inventory.AllItemsMod)
|
||||
{
|
||||
if (item == handCuffs) { continue; }
|
||||
if (item.StolenDuringRound)
|
||||
if (objectiveManager.IsCurrentObjective<AIObjectiveFightIntruders>())
|
||||
{
|
||||
item.Drop(character);
|
||||
character.Inventory.TryPutItem(item, character, CharacterInventory.anySlot);
|
||||
Abandon = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
character.Speak(TextManager.Get("DialogTargetArrested"), null, 3.0f, "targetarrested", 30.0f);
|
||||
}
|
||||
IsCompleted = true;
|
||||
if (!objectiveManager.IsCurrentObjective<AIObjectiveFightIntruders>())
|
||||
{
|
||||
IsCompleted = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -941,14 +962,6 @@ namespace Barotrauma
|
||||
return;
|
||||
}
|
||||
if (reloadTimer > 0) { return; }
|
||||
if (Mode == CombatMode.Arrest)
|
||||
{
|
||||
// If the target is arrested or if it's stunned and we can't lock the target up, consider the objective done.
|
||||
if (Enemy.IsKnockedDown && !HumanAIController.HasItem(character, "handlocker", out _, requireEquipped: false) || HumanAIController.HasItem(Enemy, "handlocker", out _, requireEquipped: true))
|
||||
{
|
||||
IsCompleted = true;
|
||||
}
|
||||
}
|
||||
if (holdFireCondition != null && holdFireCondition()) { return; }
|
||||
float sqrDist = Vector2.DistanceSquared(character.Position, Enemy.Position);
|
||||
if (WeaponComponent is MeleeWeapon meleeWeapon)
|
||||
|
||||
@@ -334,9 +334,15 @@ namespace Barotrauma
|
||||
return (int)Math.Round(MathHelper.Lerp(minValue, maxValue, Level.Loaded.Difficulty * 0.01f * Config.AgentSpawnCountDifficultyMultiplier));
|
||||
}
|
||||
|
||||
private float GetSpawnTime() =>
|
||||
Math.Max(Config.AgentSpawnDelay * Rand.Range(Config.AgentSpawnDelayRandomFactor, 1 + Config.AgentSpawnDelayRandomFactor)
|
||||
/ (Math.Max(Level.Loaded.Difficulty, 1) * 0.01f * Config.AgentSpawnDelayDifficultyMultiplier), Config.AgentSpawnDelay);
|
||||
private float GetSpawnTime()
|
||||
{
|
||||
float randomFactor = Config.AgentSpawnDelayRandomFactor;
|
||||
float delay = Config.AgentSpawnDelay;
|
||||
float min = delay;
|
||||
float max = delay * 6;
|
||||
float t = Level.Loaded.Difficulty * Config.AgentSpawnDelayDifficultyMultiplier * Rand.Range(1 - randomFactor, 1 + randomFactor);
|
||||
return MathHelper.Lerp(max, min, MathUtils.InverseLerp(0, 100, t));
|
||||
}
|
||||
|
||||
void UpdateReinforcements(float deltaTime)
|
||||
{
|
||||
|
||||
@@ -3414,7 +3414,7 @@ namespace Barotrauma
|
||||
/// Is the character knocked down regardless whether the technical state is dead, unconcious, paralyzed, or stunned.
|
||||
/// With stunning, the parameter uses a half a second delay before the character is treated as knocked down. The purpose of this is to ignore minor stunning. If you don't want to to ignore any stun, use the Stun property.
|
||||
/// </summary>
|
||||
public bool IsKnockedDown => IsDead || IsIncapacitated || CharacterHealth.StunTimer > 0.5f;
|
||||
public bool IsKnockedDown => IsDead || IsIncapacitated || CharacterHealth.StunTimer > 0.5f || IsRagdolled;
|
||||
|
||||
public void SetStun(float newStun, bool allowStunDecrease = false, bool isNetworkMessage = false)
|
||||
{
|
||||
|
||||
+6
-1
@@ -131,7 +131,12 @@ namespace Barotrauma
|
||||
|
||||
public static string GetFolder(XDocument doc, string filePath)
|
||||
{
|
||||
var folder = doc.Root?.Element("animations")?.GetAttributeString("folder", string.Empty);
|
||||
var root = doc.Root;
|
||||
if (root?.IsOverride() ?? false)
|
||||
{
|
||||
root = root.FirstElement();
|
||||
}
|
||||
var folder = root?.Element("animations")?.GetAttributeString("folder", string.Empty);
|
||||
if (string.IsNullOrEmpty(folder) || folder.Equals("default", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
folder = Path.Combine(Path.GetDirectoryName(filePath), "Animations");
|
||||
|
||||
@@ -105,7 +105,12 @@ namespace Barotrauma
|
||||
|
||||
public static string GetFolder(XDocument doc, string filePath)
|
||||
{
|
||||
var folder = doc.Root?.Element("ragdolls")?.GetAttributeString("folder", string.Empty);
|
||||
var root = doc.Root;
|
||||
if (root?.IsOverride() ?? false)
|
||||
{
|
||||
root = root.FirstElement();
|
||||
}
|
||||
var folder = root?.Element("ragdolls")?.GetAttributeString("folder", string.Empty);
|
||||
if (string.IsNullOrEmpty(folder) || folder.Equals("default", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
folder = Path.Combine(Path.GetDirectoryName(filePath), "Ragdolls") + Path.DirectorySeparatorChar;
|
||||
|
||||
@@ -276,7 +276,16 @@ namespace Barotrauma
|
||||
{
|
||||
SteamWorkshopId = SteamManager.GetWorkshopItemIDFromUrl(workshopUrl);
|
||||
}
|
||||
GameVersion = new Version(doc.Root.GetAttributeString("gameversion", "0.0.0.0"));
|
||||
string versionStr = doc.Root.GetAttributeString("gameversion", "0.0.0.0");
|
||||
try
|
||||
{
|
||||
GameVersion = new Version(versionStr);
|
||||
}
|
||||
catch
|
||||
{
|
||||
DebugConsole.ThrowError($"Invalid version number in content package \"{Name}\" ({versionStr}).");
|
||||
GameVersion = GameMain.Version;
|
||||
}
|
||||
if (doc.Root.Attribute("installtime") != null)
|
||||
{
|
||||
InstallTime = ToolBox.Epoch.ToDateTime(doc.Root.GetAttributeUInt("installtime", 0));
|
||||
|
||||
@@ -23,9 +23,9 @@ namespace Barotrauma
|
||||
{
|
||||
if (isFinished) { return; }
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(Tag) && ParentEvent.Targets.ContainsKey(Tag))
|
||||
if (!string.IsNullOrWhiteSpace(Tag))
|
||||
{
|
||||
ParentEvent.Targets.Remove(Tag);
|
||||
ParentEvent.RemoveTag(Tag);
|
||||
}
|
||||
isFinished = true;
|
||||
}
|
||||
|
||||
@@ -42,6 +42,11 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
if (requiredDeliveryAmount == 0) { requiredDeliveryAmount = items.Count; }
|
||||
if (requiredDeliveryAmount > items.Count)
|
||||
{
|
||||
DebugConsole.AddWarning($"Error in mission \"{Prefab.Identifier}\". Required delivery amount is {requiredDeliveryAmount} but there's only {items.Count} items to deliver.");
|
||||
requiredDeliveryAmount = items.Count;
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadItemAsChild(XElement element, Item parent)
|
||||
|
||||
@@ -138,6 +138,14 @@ namespace Barotrauma
|
||||
return targetsToReturn;
|
||||
}
|
||||
|
||||
public void RemoveTag(string tag)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(tag)) { return; }
|
||||
if (Targets.ContainsKey(tag)) { Targets.Remove(tag); }
|
||||
if (cachedTargets.ContainsKey(tag)) { cachedTargets.Remove(tag); }
|
||||
if (targetPredicates.ContainsKey(tag)) { targetPredicates.Remove(tag); }
|
||||
}
|
||||
|
||||
public override void Update(float deltaTime)
|
||||
{
|
||||
int botCount = 0;
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
namespace Barotrauma.Extensions
|
||||
{
|
||||
public static class StructExtensions
|
||||
{
|
||||
public static bool TryGetValue<T>(this T? nullableStruct, out T nonNullable) where T : struct
|
||||
{
|
||||
if (nullableStruct.HasValue)
|
||||
{
|
||||
nonNullable = nullableStruct.Value;
|
||||
return true;
|
||||
}
|
||||
nonNullable = default(T);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -265,7 +265,7 @@ namespace Barotrauma
|
||||
if (beaconMissionPrefabs.Any())
|
||||
{
|
||||
Random rand = new MTRandom(ToolBox.StringToInt(levelData.Seed));
|
||||
var beaconMissionPrefab = beaconMissionPrefabs.GetRandom(rand);
|
||||
var beaconMissionPrefab = ToolBox.SelectWeightedRandom(beaconMissionPrefabs, beaconMissionPrefabs.Select(p => (float)p.Commonness).ToList(), rand);
|
||||
if (!Missions.Any(m => m.Prefab.Type == beaconMissionPrefab.Type))
|
||||
{
|
||||
extraMissions.Add(beaconMissionPrefab.Instantiate(Map.SelectedConnection.Locations));
|
||||
@@ -282,7 +282,7 @@ namespace Barotrauma
|
||||
else
|
||||
{
|
||||
Random rand = new MTRandom(ToolBox.StringToInt(levelData.Seed));
|
||||
var huntingGroundsMissionPrefab = huntingGroundsMissionPrefabs.GetRandom(rand);
|
||||
var huntingGroundsMissionPrefab = ToolBox.SelectWeightedRandom(huntingGroundsMissionPrefabs, huntingGroundsMissionPrefabs.Select(p => (float)p.Commonness).ToList(), rand);
|
||||
if (!Missions.Any(m => m.Prefab.Tags.Any(t => t.Equals("huntinggrounds", StringComparison.OrdinalIgnoreCase))))
|
||||
{
|
||||
extraMissions.Add(huntingGroundsMissionPrefab.Instantiate(Map.SelectedConnection.Locations));
|
||||
@@ -613,6 +613,13 @@ namespace Barotrauma
|
||||
|
||||
public void EndCampaign()
|
||||
{
|
||||
foreach (Character c in Character.CharacterList)
|
||||
{
|
||||
if (c.IsOnPlayerTeam)
|
||||
{
|
||||
c.CharacterHealth.RemoveAllAfflictions();
|
||||
}
|
||||
}
|
||||
foreach (LocationConnection connection in Map.Connections)
|
||||
{
|
||||
connection.Difficulty = MathHelper.Lerp(connection.Difficulty, 100.0f, 0.25f);
|
||||
|
||||
@@ -32,6 +32,8 @@ namespace Barotrauma
|
||||
public Level Level { get; private set; }
|
||||
public LevelData LevelData { get; private set; }
|
||||
|
||||
public bool MirrorLevel { get; private set; }
|
||||
|
||||
public Map Map
|
||||
{
|
||||
get
|
||||
@@ -318,6 +320,7 @@ namespace Barotrauma
|
||||
|
||||
public void StartRound(LevelData levelData, bool mirrorLevel = false, SubmarineInfo startOutpost = null, SubmarineInfo endOutpost = null)
|
||||
{
|
||||
MirrorLevel = mirrorLevel;
|
||||
if (SubmarineInfo == null)
|
||||
{
|
||||
DebugConsole.ThrowError("Couldn't start game session, submarine not selected.");
|
||||
@@ -583,6 +586,7 @@ namespace Barotrauma
|
||||
if (ls.Sub == null || ls.Submarine != Submarine) { continue; }
|
||||
if (!ls.LoadSub || ls.Sub.DockedTo.Contains(Submarine)) { continue; }
|
||||
if (Submarine.Info.LeftBehindDockingPortIDs.Contains(ls.OriginalLinkedToID)) { continue; }
|
||||
if (ls.Sub.Info.SubmarineElement.Attribute("location") != null) { continue; }
|
||||
ls.Sub.SetPosition(ls.Sub.WorldPosition + (Submarine.WorldPosition - originalSubPos));
|
||||
}
|
||||
}
|
||||
@@ -743,7 +747,8 @@ namespace Barotrauma
|
||||
|
||||
doc.Root.Add(new XAttribute("savetime", ToolBox.Epoch.NowLocal));
|
||||
doc.Root.Add(new XAttribute("version", GameMain.Version));
|
||||
doc.Root.Add(new XAttribute("submarine", SubmarineInfo == null ? "" : SubmarineInfo.Name));
|
||||
var submarineInfo = Campaign?.PendingSubmarineSwitch ?? SubmarineInfo;
|
||||
doc.Root.Add(new XAttribute("submarine", submarineInfo == null ? "" : submarineInfo.Name));
|
||||
if (OwnedSubmarines != null)
|
||||
{
|
||||
List<string> ownedSubmarineNames = new List<string>();
|
||||
|
||||
@@ -311,8 +311,6 @@ namespace Barotrauma
|
||||
public bool ModBreakerMode { get; set; }
|
||||
#endif
|
||||
|
||||
private System.IO.FileSystemWatcher modsFolderWatcher;
|
||||
|
||||
private static int ContentFileLoadOrder(ContentFile a)
|
||||
{
|
||||
switch (a.Type)
|
||||
@@ -805,87 +803,6 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
LoadPlayerConfig();
|
||||
|
||||
modsFolderWatcher = new System.IO.FileSystemWatcher("Mods");
|
||||
modsFolderWatcher.Filter = "*";
|
||||
modsFolderWatcher.NotifyFilter = System.IO.NotifyFilters.LastWrite | System.IO.NotifyFilters.FileName | System.IO.NotifyFilters.DirectoryName;
|
||||
modsFolderWatcher.Created += OnModFolderUpdate;
|
||||
modsFolderWatcher.Deleted += OnModFolderUpdate;
|
||||
modsFolderWatcher.Renamed += OnModFolderUpdate;
|
||||
modsFolderWatcher.EnableRaisingEvents = true;
|
||||
}
|
||||
|
||||
private void OnModFolderUpdate(object sender, System.IO.FileSystemEventArgs e)
|
||||
{
|
||||
if (SuppressModFolderWatcher || (GameMain.NetworkMember?.IsClient ?? false)) { return; }
|
||||
switch (e.ChangeType)
|
||||
{
|
||||
case System.IO.WatcherChangeTypes.Created:
|
||||
{
|
||||
string cpPath = Path.GetFullPath(Path.Combine(e.FullPath, Steam.SteamManager.MetadataFileName)).CleanUpPath();
|
||||
if (File.Exists(cpPath) &&
|
||||
!ContentPackage.AllPackages.Any(cp => Path.GetFullPath(cp.Path).CleanUpPath() == cpPath))
|
||||
{
|
||||
var newPackage = new ContentPackage(cpPath);
|
||||
if (!newPackage.IsCorrupt) { ContentPackage.AddPackage(newPackage); }
|
||||
}
|
||||
}
|
||||
break;
|
||||
case System.IO.WatcherChangeTypes.Deleted:
|
||||
{
|
||||
string cpPath = Path.GetFullPath(Path.Combine(e.FullPath, Steam.SteamManager.MetadataFileName)).CleanUpPath();
|
||||
var toRemove = ContentPackage.RegularPackages.Where(cp => Path.GetFullPath(cp.Path).CleanUpPath() == cpPath).ToList();
|
||||
foreach (var cp in toRemove)
|
||||
{
|
||||
if (enabledRegularPackages.Contains(cp)) { DisableRegularPackage(cp); }
|
||||
}
|
||||
|
||||
toRemove.AddRange(ContentPackage.CorePackages.Where(cp => Path.GetFullPath(cp.Path).CleanUpPath() == cpPath));
|
||||
bool reselectCore = false;
|
||||
foreach (var cp in toRemove)
|
||||
{
|
||||
ContentPackage.RemovePackage(cp);
|
||||
if (cp.IsCorePackage)
|
||||
{
|
||||
reselectCore = true;
|
||||
}
|
||||
}
|
||||
if (reselectCore) { AutoSelectCorePackage(null); }
|
||||
}
|
||||
break;
|
||||
case System.IO.WatcherChangeTypes.Renamed:
|
||||
{
|
||||
System.IO.RenamedEventArgs renameArgs = e as System.IO.RenamedEventArgs;
|
||||
|
||||
string cpPath = Path.GetFullPath(Path.Combine(e.FullPath, Steam.SteamManager.MetadataFileName)).CleanUpPath();
|
||||
var toRemove = ContentPackage.RegularPackages.Where(cp => Path.GetFullPath(cp.Path).CleanUpPath() == cpPath).ToList();
|
||||
foreach (var cp in toRemove)
|
||||
{
|
||||
if (enabledRegularPackages.Contains(cp)) { DisableRegularPackage(cp); }
|
||||
}
|
||||
|
||||
toRemove.AddRange(ContentPackage.CorePackages.Where(cp => Path.GetFullPath(cp.Path).CleanUpPath() == cpPath));
|
||||
bool reselectCore = false;
|
||||
foreach (var cp in toRemove)
|
||||
{
|
||||
ContentPackage.RemovePackage(cp);
|
||||
if (cp.IsCorePackage)
|
||||
{
|
||||
reselectCore = true;
|
||||
}
|
||||
}
|
||||
|
||||
cpPath = Path.GetFullPath(Path.Combine(renameArgs.FullPath, Steam.SteamManager.MetadataFileName)).CleanUpPath();
|
||||
if (File.Exists(cpPath) &&
|
||||
!ContentPackage.AllPackages.Any(cp => Path.GetFullPath(cp.Path).CleanUpPath() == cpPath))
|
||||
{
|
||||
var newPackage = new ContentPackage(cpPath);
|
||||
if (!newPackage.IsCorrupt) { ContentPackage.AddPackage(newPackage); }
|
||||
}
|
||||
if (reselectCore) { AutoSelectCorePackage(null); }
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadDefaultConfig(bool setLanguage = true, bool loadContentPackages = true)
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace Barotrauma.Items.Components
|
||||
: base(item,element)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
public override bool Use(float deltaTime, Character character = null)
|
||||
{
|
||||
if (character == null || character.Removed) return false;
|
||||
@@ -61,7 +61,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
Vector2 propulsion = dir * Force * character.PropulsionSpeedMultiplier;
|
||||
|
||||
if (character.AnimController.InWater) character.AnimController.TargetMovement = dir;
|
||||
if (character.AnimController.InWater && Force > 0.0f) { character.AnimController.TargetMovement = dir; }
|
||||
|
||||
foreach (Limb limb in character.AnimController.Limbs)
|
||||
{
|
||||
|
||||
@@ -757,7 +757,7 @@ namespace Barotrauma.Items.Components
|
||||
bool reducesCondition = false;
|
||||
foreach (StatusEffect effect in statusEffects)
|
||||
{
|
||||
if (broken && effect.type != ActionType.OnBroken) { continue; }
|
||||
if (broken && !effect.AllowWhenBroken && effect.type != ActionType.OnBroken) { continue; }
|
||||
if (user != null) { effect.SetUser(user); }
|
||||
item.ApplyStatusEffect(effect, type, deltaTime, character, targetLimb, useTarget, false, false, worldPosition);
|
||||
reducesCondition |= effect.ReducesItemCondition();
|
||||
|
||||
@@ -153,6 +153,7 @@ namespace Barotrauma.Items.Components
|
||||
if (IsToggle)
|
||||
{
|
||||
item.SendSignal(State ? "1" : "0", "signal_out");
|
||||
item.SendSignal(State ? "1" : "0", "trigger_out");
|
||||
}
|
||||
|
||||
if (user == null
|
||||
@@ -263,6 +264,8 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
private double lastUsed;
|
||||
|
||||
public override bool Use(float deltaTime, Character activator = null)
|
||||
{
|
||||
if (activator != user)
|
||||
@@ -277,7 +280,22 @@ namespace Barotrauma.Items.Components
|
||||
return false;
|
||||
}
|
||||
|
||||
item.SendSignal(new Signal("1", sender: user), "trigger_out");
|
||||
if (IsToggle && (activator == null || lastUsed < Timing.TotalTime - 0.1))
|
||||
{
|
||||
if (GameMain.NetworkMember == null || GameMain.NetworkMember.IsServer)
|
||||
{
|
||||
State = !State;
|
||||
#if SERVER
|
||||
item.CreateServerEvent(this);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
item.SendSignal(new Signal("1", sender: user), "trigger_out");
|
||||
}
|
||||
|
||||
lastUsed = Timing.TotalTime;
|
||||
|
||||
ApplyStatusEffects(ActionType.OnUse, 1.0f, activator);
|
||||
|
||||
|
||||
@@ -308,7 +308,15 @@ namespace Barotrauma.Items.Components
|
||||
if (AutoPilot)
|
||||
{
|
||||
UpdateAutoPilot(deltaTime);
|
||||
TargetVelocity = TargetVelocity.ClampLength(MathHelper.Lerp(AutoPilotMaxSpeed, AIPilotMaxSpeed, userSkill) * 100.0f);
|
||||
float throttle = 1.0f;
|
||||
if (controlledSub != null)
|
||||
{
|
||||
//if the sub is heading in the correct direction, throttle the speed according to the user's skill
|
||||
//if it's e.g. sinking due to extra water, don't throttle, but allow emptying up the ballast completely
|
||||
throttle = MathHelper.Clamp(Vector2.Dot(controlledSub.Velocity, TargetVelocity) / 100.0f, 0.0f, 1.0f);
|
||||
}
|
||||
float maxSpeed = MathHelper.Lerp(AutoPilotMaxSpeed, AIPilotMaxSpeed, userSkill) * 100.0f;
|
||||
TargetVelocity = TargetVelocity.ClampLength(MathHelper.Lerp(100.0f, maxSpeed, throttle));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -372,7 +372,7 @@ namespace Barotrauma.Items.Components
|
||||
hits = hits.OrderBy(h => h.Fraction).ToList();
|
||||
foreach (HitscanResult h in hits)
|
||||
{
|
||||
item.body.SetTransform(h.Point, rotation);
|
||||
item.SetTransform(h.Point, rotation);
|
||||
if (HandleProjectileCollision(h.Fixture, h.Normal, Vector2.Zero))
|
||||
{
|
||||
hitSomething = true;
|
||||
|
||||
@@ -23,6 +23,17 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
private int maxOutputLength;
|
||||
[Editable, Serialize(200, false, description: "The maximum length of the output strings. Warning: Large values can lead to large memory usage or networking issues.")]
|
||||
public int MaxOutputLength
|
||||
{
|
||||
get { return maxOutputLength; }
|
||||
set
|
||||
{
|
||||
maxOutputLength = Math.Max(value, 0);
|
||||
}
|
||||
}
|
||||
|
||||
[InGameEditable, Serialize("1", true, description: "The signal sent when the condition is met.", alwaysUseInstanceValues: true)]
|
||||
public string Output
|
||||
{
|
||||
@@ -53,17 +64,6 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
private int maxOutputLength;
|
||||
[Editable, Serialize(200, false, description: "The maximum length of the output strings. Warning: Large values can lead to large memory usage or networking issues.")]
|
||||
public int MaxOutputLength
|
||||
{
|
||||
get { return maxOutputLength; }
|
||||
set
|
||||
{
|
||||
maxOutputLength = Math.Max(value, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public AndComponent(Item item, XElement element)
|
||||
: base(item, element)
|
||||
{
|
||||
|
||||
+11
-11
@@ -15,6 +15,17 @@ namespace Barotrauma.Items.Components
|
||||
//the output is sent if both inputs have received a signal within the timeframe
|
||||
protected float timeFrame;
|
||||
|
||||
private int maxOutputLength;
|
||||
[Editable, Serialize(200, false, description: "The maximum length of the output strings. Warning: Large values can lead to large memory usage or networking issues.")]
|
||||
public int MaxOutputLength
|
||||
{
|
||||
get { return maxOutputLength; }
|
||||
set
|
||||
{
|
||||
maxOutputLength = Math.Max(value, 0);
|
||||
}
|
||||
}
|
||||
|
||||
[InGameEditable, Serialize("1", true, description: "The signal sent when the condition is met.", alwaysUseInstanceValues: true)]
|
||||
public string Output
|
||||
{
|
||||
@@ -45,17 +56,6 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
private int maxOutputLength;
|
||||
[Editable, Serialize(200, false, description: "The maximum length of the output strings. Warning: Large values can lead to large memory usage or networking issues.")]
|
||||
public int MaxOutputLength
|
||||
{
|
||||
get { return maxOutputLength; }
|
||||
set
|
||||
{
|
||||
maxOutputLength = Math.Max(value, 0);
|
||||
}
|
||||
}
|
||||
|
||||
[InGameEditable(DecimalCount = 2), Serialize(0.0f, true, description: "The maximum amount of time between the received signals. If set to 0, the signals must be received at the same time.", alwaysUseInstanceValues: true)]
|
||||
public float TimeFrame
|
||||
{
|
||||
|
||||
+11
-11
@@ -6,6 +6,17 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
partial class MemoryComponent : ItemComponent, IServerSerializable
|
||||
{
|
||||
private int maxValueLength;
|
||||
[Editable, Serialize(200, false, description: "The maximum length of the stored value. Warning: Large values can lead to large memory usage or networking issues.")]
|
||||
public int MaxValueLength
|
||||
{
|
||||
get { return maxValueLength; }
|
||||
set
|
||||
{
|
||||
maxValueLength = Math.Max(value, 0);
|
||||
}
|
||||
}
|
||||
|
||||
private string value;
|
||||
|
||||
[InGameEditable, Serialize("", true, description: "The currently stored signal the item outputs.", alwaysUseInstanceValues: true)]
|
||||
@@ -23,17 +34,6 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
private int maxValueLength;
|
||||
[Editable, Serialize(200, false, description: "The maximum length of the stored value. Warning: Large values can lead to large memory usage or networking issues.")]
|
||||
public int MaxValueLength
|
||||
{
|
||||
get { return maxValueLength; }
|
||||
set
|
||||
{
|
||||
maxValueLength = Math.Max(value, 0);
|
||||
}
|
||||
}
|
||||
|
||||
protected bool writeable = true;
|
||||
|
||||
public MemoryComponent(Item item, XElement element)
|
||||
|
||||
@@ -74,6 +74,17 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
private int maxOutputLength;
|
||||
[Editable, Serialize(200, false, description: "The maximum length of the output strings. Warning: Large values can lead to large memory usage or networking issues.")]
|
||||
public int MaxOutputLength
|
||||
{
|
||||
get { return maxOutputLength; }
|
||||
set
|
||||
{
|
||||
maxOutputLength = Math.Max(value, 0);
|
||||
}
|
||||
}
|
||||
|
||||
private string output;
|
||||
[InGameEditable, Serialize("1", true, description: "The signal the item outputs when it has detected movement.", alwaysUseInstanceValues: true)]
|
||||
public string Output
|
||||
@@ -106,17 +117,6 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
private int maxOutputLength;
|
||||
[Editable, Serialize(200, false, description: "The maximum length of the output strings. Warning: Large values can lead to large memory usage or networking issues.")]
|
||||
public int MaxOutputLength
|
||||
{
|
||||
get { return maxOutputLength; }
|
||||
set
|
||||
{
|
||||
maxOutputLength = Math.Max(value, 0);
|
||||
}
|
||||
}
|
||||
|
||||
[Editable(DecimalCount = 3), Serialize(0.01f, true, description: "How fast the objects within the detector's range have to be moving (in m/s).", alwaysUseInstanceValues: true)]
|
||||
public float MinimumVelocity
|
||||
{
|
||||
|
||||
+11
-12
@@ -18,6 +18,17 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
private bool nonContinuousOutputSent;
|
||||
|
||||
private int maxOutputLength;
|
||||
[Editable, Serialize(200, false, description: "The maximum length of the output string. Warning: Large values can lead to large memory usage or networking issues.")]
|
||||
public int MaxOutputLength
|
||||
{
|
||||
get { return maxOutputLength; }
|
||||
set
|
||||
{
|
||||
maxOutputLength = Math.Max(value, 0);
|
||||
}
|
||||
}
|
||||
|
||||
private string output;
|
||||
|
||||
[InGameEditable, Serialize("1", true, description: "The signal this item outputs when the received signal matches the regular expression.", alwaysUseInstanceValues: true)]
|
||||
@@ -61,23 +72,11 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
catch
|
||||
{
|
||||
item.SendSignal("ERROR", "signal_out");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int maxOutputLength;
|
||||
[Editable, Serialize(200, false, description: "The maximum length of the output string. Warning: Large values can lead to large memory usage or networking issues.")]
|
||||
public int MaxOutputLength
|
||||
{
|
||||
get { return maxOutputLength; }
|
||||
set
|
||||
{
|
||||
maxOutputLength = Math.Max(value, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public RegExFindComponent(Item item, XElement element)
|
||||
: base(item, element)
|
||||
{
|
||||
|
||||
+11
-11
@@ -5,6 +5,17 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
class SignalCheckComponent : ItemComponent
|
||||
{
|
||||
private int maxOutputLength;
|
||||
[Editable, Serialize(200, false, description: "The maximum length of the output strings. Warning: Large values can lead to large memory usage or networking issues.")]
|
||||
public int MaxOutputLength
|
||||
{
|
||||
get { return maxOutputLength; }
|
||||
set
|
||||
{
|
||||
maxOutputLength = Math.Max(value, 0);
|
||||
}
|
||||
}
|
||||
|
||||
private string output;
|
||||
[InGameEditable, Serialize("1", true, description: "The signal this item outputs when the received signal matches the target signal.", alwaysUseInstanceValues: true)]
|
||||
public string Output
|
||||
@@ -40,17 +51,6 @@ namespace Barotrauma.Items.Components
|
||||
[InGameEditable, Serialize("", true, description: "The value to compare the received signals against.", alwaysUseInstanceValues: true)]
|
||||
public string TargetSignal { get; set; }
|
||||
|
||||
private int maxOutputLength;
|
||||
[Editable, Serialize(200, false, description: "The maximum length of the output strings. Warning: Large values can lead to large memory usage or networking issues.")]
|
||||
public int MaxOutputLength
|
||||
{
|
||||
get { return maxOutputLength; }
|
||||
set
|
||||
{
|
||||
maxOutputLength = Math.Max(value, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public SignalCheckComponent(Item item, XElement element)
|
||||
: base(item, element)
|
||||
{
|
||||
|
||||
@@ -10,6 +10,17 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
private bool fireInRange;
|
||||
|
||||
private int maxOutputLength;
|
||||
[Editable, Serialize(200, false, description: "The maximum length of the output strings. Warning: Large values can lead to large memory usage or networking issues.")]
|
||||
public int MaxOutputLength
|
||||
{
|
||||
get { return maxOutputLength; }
|
||||
set
|
||||
{
|
||||
maxOutputLength = Math.Max(value, 0);
|
||||
}
|
||||
}
|
||||
|
||||
private string output;
|
||||
[InGameEditable, Serialize("1", true, description: "The signal the item outputs when it has detected a fire.", alwaysUseInstanceValues: true)]
|
||||
public string Output
|
||||
@@ -42,17 +53,6 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
private int maxOutputLength;
|
||||
[Editable, Serialize(200, false, description: "The maximum length of the output strings. Warning: Large values can lead to large memory usage or networking issues.")]
|
||||
public int MaxOutputLength
|
||||
{
|
||||
get { return maxOutputLength; }
|
||||
set
|
||||
{
|
||||
maxOutputLength = Math.Max(value, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public SmokeDetector(Item item, XElement element)
|
||||
: base(item, element)
|
||||
{
|
||||
|
||||
@@ -12,6 +12,17 @@ namespace Barotrauma.Items.Components
|
||||
private bool isInWater;
|
||||
private float stateSwitchDelay;
|
||||
|
||||
private int maxOutputLength;
|
||||
[Editable, Serialize(200, false, description: "The maximum length of the output strings. Warning: Large values can lead to large memory usage or networking issues.")]
|
||||
public int MaxOutputLength
|
||||
{
|
||||
get { return maxOutputLength; }
|
||||
set
|
||||
{
|
||||
maxOutputLength = Math.Max(value, 0);
|
||||
}
|
||||
}
|
||||
|
||||
private string output;
|
||||
[InGameEditable, Serialize("1", true, description: "The signal the item sends out when it's underwater.", alwaysUseInstanceValues: true)]
|
||||
public string Output
|
||||
@@ -44,17 +55,6 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
private int maxOutputLength;
|
||||
[Editable, Serialize(200, false, description: "The maximum length of the output strings. Warning: Large values can lead to large memory usage or networking issues.")]
|
||||
public int MaxOutputLength
|
||||
{
|
||||
get { return maxOutputLength; }
|
||||
set
|
||||
{
|
||||
maxOutputLength = Math.Max(value, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public WaterDetector(Item item, XElement element)
|
||||
: base(item, element)
|
||||
{
|
||||
|
||||
@@ -144,6 +144,11 @@ namespace Barotrauma
|
||||
// If the variant does not exist, parse the path so that it uses first variant.
|
||||
SpritePath = tempPath.Replace("[VARIANT]", "1");
|
||||
}
|
||||
if (!File.Exists(SpritePath) && _gender == Gender.None)
|
||||
{
|
||||
// If there's no sprite for Gender.None does not exist, try to use male sprite
|
||||
SpritePath = tempPath.Replace("[GENDER]", "male");
|
||||
}
|
||||
if (parseSpritePath)
|
||||
{
|
||||
Sprite.ParseTexturePath(file: SpritePath);
|
||||
|
||||
@@ -507,7 +507,8 @@ namespace Barotrauma
|
||||
#if CLIENT
|
||||
if (visualSlots != null)
|
||||
{
|
||||
visualSlots[i]?.ShowBorderHighlight(Color.White, 0.1f, 0.4f);
|
||||
visualSlots[i].ShowBorderHighlight(Color.White, 0.1f, 0.4f);
|
||||
if (selectedSlot?.Inventory == this) { selectedSlot.ForceTooltipRefresh = true; }
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -625,7 +626,10 @@ namespace Barotrauma
|
||||
else
|
||||
{
|
||||
existingItems.Add(slots[index].FirstOrDefault());
|
||||
slots[index].RemoveItem(existingItems.First());
|
||||
for (int j = 0; j < capacity; j++)
|
||||
{
|
||||
if (existingItems.Any(existingItem => slots[j].Contains(existingItem))) { slots[j].RemoveItem(existingItems.First()); }
|
||||
}
|
||||
}
|
||||
|
||||
List<Item> stackedItems = new List<Item>();
|
||||
@@ -831,7 +835,14 @@ namespace Barotrauma
|
||||
if (!slots[n].Contains(item)) { continue; }
|
||||
|
||||
slots[n].RemoveItem(item);
|
||||
item.ParentInventory = null;
|
||||
item.ParentInventory = null;
|
||||
#if CLIENT
|
||||
if (visualSlots != null)
|
||||
{
|
||||
visualSlots[n].ShowBorderHighlight(Color.White, 0.1f, 0.4f);
|
||||
if (selectedSlot?.Inventory == this) { selectedSlot.ForceTooltipRefresh = true; }
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1356,11 +1356,11 @@ namespace Barotrauma
|
||||
{
|
||||
if (!isNetworkEvent && checkCondition)
|
||||
{
|
||||
if (condition == 0.0f && effect.type != ActionType.OnBroken) return;
|
||||
if (condition == 0.0f && !effect.AllowWhenBroken && effect.type != ActionType.OnBroken) { return; }
|
||||
}
|
||||
if (effect.type != type) return;
|
||||
if (effect.type != type) { return; }
|
||||
|
||||
bool hasTargets = (effect.TargetIdentifiers == null);
|
||||
bool hasTargets = effect.TargetIdentifiers == null;
|
||||
|
||||
targets.Clear();
|
||||
|
||||
@@ -2611,7 +2611,7 @@ namespace Barotrauma
|
||||
|
||||
foreach (XAttribute attribute in element.Attributes())
|
||||
{
|
||||
if (!item.SerializableProperties.TryGetValue(attribute.Name.ToString(), out SerializableProperty property)) continue;
|
||||
if (!item.SerializableProperties.TryGetValue(attribute.Name.ToString(), out SerializableProperty property)) { continue; }
|
||||
bool shouldBeLoaded = false;
|
||||
foreach (var propertyAttribute in property.Attributes.OfType<Serialize>())
|
||||
{
|
||||
@@ -2622,7 +2622,31 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldBeLoaded) { property.TrySetValue(item, attribute.Value); }
|
||||
if (shouldBeLoaded)
|
||||
{
|
||||
object prevValue = property.GetValue(item);
|
||||
property.TrySetValue(item, attribute.Value);
|
||||
//create network events for properties that differ from the prefab values
|
||||
//(e.g. if a character has an item with modified colors in their inventory)
|
||||
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsServer && property.Attributes.OfType<Editable>().Any() &&
|
||||
(submarine == null || !submarine.Loading ))
|
||||
{
|
||||
switch (property.Name)
|
||||
{
|
||||
case "Tags":
|
||||
case "Condition":
|
||||
case "Description":
|
||||
//these can be ignored, they're always written in the spawn data
|
||||
break;
|
||||
default:
|
||||
if (!(property.GetValue(item)?.Equals(prevValue) ?? true))
|
||||
{
|
||||
GameMain.NetworkMember.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.ChangeProperty, property });
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
item.ParseLinks(element, idRemap);
|
||||
|
||||
@@ -424,15 +424,9 @@ namespace Barotrauma
|
||||
}
|
||||
foreach (var edge in cell.Edges)
|
||||
{
|
||||
if (!MathUtils.GetLineIntersection(worldPosition, cell.Center, edge.Point1 + cell.Translation, edge.Point2 + cell.Translation, out Vector2 intersection))
|
||||
if (MathUtils.LineSegmentToPointDistanceSquared((edge.Point1 + cell.Translation).ToPoint(), (edge.Point2 + cell.Translation).ToPoint(), worldPosition.ToPoint()) < worldRange * worldRange)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
float wallDist = Vector2.DistanceSquared(worldPosition, intersection);
|
||||
if (wallDist < worldRange * worldRange)
|
||||
{
|
||||
destructibleWall.AddDamage(damage, worldPosition);
|
||||
destructibleWall.AddDamage(levelWallDamage, worldPosition);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -501,7 +501,7 @@ namespace Barotrauma
|
||||
EntityGrids.Add(newGrid);
|
||||
foreach (Hull hull in hullList)
|
||||
{
|
||||
if (hull.Submarine == submarine) newGrid.InsertEntity(hull);
|
||||
if (hull.Submarine == submarine && !hull.IdFreed) { newGrid.InsertEntity(hull); }
|
||||
}
|
||||
return newGrid;
|
||||
}
|
||||
|
||||
@@ -3663,7 +3663,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
//break powered items
|
||||
foreach (Item item in beaconItems.Where(it => it.Components.Any(c => c is Powered)))
|
||||
foreach (Item item in beaconItems.Where(it => it.Components.Any(c => c is Powered) && it.Components.Any(c => c is Repairable)))
|
||||
{
|
||||
if (item.NonInteractable) { continue; }
|
||||
if (Rand.Range(0f, 1f, Rand.RandSync.Unsynced) < 0.5f)
|
||||
|
||||
@@ -252,6 +252,10 @@ namespace Barotrauma
|
||||
Vector2 worldPos = saveElement.GetAttributeVector2("worldpos", Vector2.Zero);
|
||||
if (worldPos != Vector2.Zero)
|
||||
{
|
||||
if (GameMain.GameSession != null && GameMain.GameSession.MirrorLevel)
|
||||
{
|
||||
worldPos.X = GameMain.GameSession.LevelData.Size.X - worldPos.X;
|
||||
}
|
||||
sub.SetPosition(worldPos);
|
||||
}
|
||||
else
|
||||
@@ -417,7 +421,12 @@ namespace Barotrauma
|
||||
if (leaveBehind)
|
||||
{
|
||||
saveElement.SetAttributeValue("location", Level.Loaded.Seed);
|
||||
saveElement.SetAttributeValue("worldpos", XMLExtensions.Vector2ToString(sub.SubBody.Position));
|
||||
Vector2 position = sub.SubBody.Position;
|
||||
if (Level.Loaded.Mirrored)
|
||||
{
|
||||
position.X = Level.Loaded.Size.X - position.X;
|
||||
}
|
||||
saveElement.SetAttributeValue("worldpos", XMLExtensions.Vector2ToString(position));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -975,7 +975,14 @@ namespace Barotrauma
|
||||
private void ChangeLocationType(Location location, LocationTypeChange change)
|
||||
{
|
||||
string prevName = location.Name;
|
||||
location.ChangeType(LocationType.List.Find(lt => lt.Identifier.Equals(change.ChangeToType, StringComparison.OrdinalIgnoreCase)));
|
||||
|
||||
var newType = LocationType.List.Find(lt => lt.Identifier.Equals(change.ChangeToType, StringComparison.OrdinalIgnoreCase));
|
||||
if (newType.OutpostTeam != location.Type.OutpostTeam ||
|
||||
newType.HasOutpost != location.Type.HasOutpost)
|
||||
{
|
||||
location.ClearMissions();
|
||||
}
|
||||
location.ChangeType(newType);
|
||||
ChangeLocationTypeProjSpecific(location, prevName, change);
|
||||
foreach (var requirement in change.Requirements)
|
||||
{
|
||||
|
||||
@@ -1068,12 +1068,36 @@ namespace Barotrauma
|
||||
public void NeutralizeBallast()
|
||||
{
|
||||
float neutralBallastLevel = 0.5f;
|
||||
int selectedSteeringValue = 0;
|
||||
foreach (Item item in Item.ItemList)
|
||||
{
|
||||
if (item.Submarine != this) { continue; }
|
||||
var steering = item.GetComponent<Steering>();
|
||||
if (steering == null) { continue; }
|
||||
neutralBallastLevel = Math.Min(neutralBallastLevel, steering.NeutralBallastLevel);
|
||||
|
||||
//find how many pumps/engines in this sub the steering item is connected to
|
||||
int steeringValue = 1;
|
||||
Connection connectionX = item.GetComponent<ConnectionPanel>()?.Connections.Find(c => c.Name == "velocity_x_out");
|
||||
Connection connectionY = item.GetComponent<ConnectionPanel>()?.Connections.Find(c => c.Name == "velocity_y_out");
|
||||
if (connectionX != null)
|
||||
{
|
||||
foreach (Engine engine in steering.Item.GetConnectedComponentsRecursive<Engine>(connectionX))
|
||||
{
|
||||
if (engine.Item.Submarine == this) { steeringValue++; }
|
||||
}
|
||||
}
|
||||
if (connectionY != null)
|
||||
{
|
||||
foreach (Pump pump in steering.Item.GetConnectedComponentsRecursive<Pump>(connectionY))
|
||||
{
|
||||
if (pump.Item.Submarine == this) { steeringValue++; }
|
||||
}
|
||||
}
|
||||
//the nav terminal that's connected to the most engines/pumps in the sub most likely controls the sub (instead of a shuttle or some other system)
|
||||
if (steeringValue > selectedSteeringValue)
|
||||
{
|
||||
neutralBallastLevel = steering.NeutralBallastLevel;
|
||||
}
|
||||
}
|
||||
|
||||
HashSet<Hull> ballastHulls = new HashSet<Hull>();
|
||||
|
||||
@@ -146,7 +146,7 @@ namespace Barotrauma
|
||||
|
||||
foreach (Hull hull in Hull.hullList)
|
||||
{
|
||||
if (hull.Submarine != submarine) { continue; }
|
||||
if (hull.Submarine != submarine || hull.IdFreed) { continue; }
|
||||
|
||||
Rectangle rect = hull.Rect;
|
||||
farseerBody.CreateRectangle(
|
||||
|
||||
@@ -914,7 +914,6 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
if (!HasPassword) return true;
|
||||
byte[] saltedPw = SaltPassword(Encoding.UTF8.GetBytes(password), salt);
|
||||
DebugConsole.NewMessage(ToolBox.ByteArrayToString(input) + " " + ToolBox.ByteArrayToString(saltedPw));
|
||||
if (input.Length != saltedPw.Length) return false;
|
||||
for (int i = 0; i < input.Length; i++)
|
||||
{
|
||||
|
||||
@@ -284,6 +284,11 @@ namespace Barotrauma
|
||||
// Currently only used for OnDamaged. TODO: is there a better, more generic way to do this?
|
||||
public readonly bool OnlyPlayerTriggered;
|
||||
|
||||
/// <summary>
|
||||
/// Can the StatusEffect be applied when the item applying it is broken
|
||||
/// </summary>
|
||||
public readonly bool AllowWhenBroken = false;
|
||||
|
||||
public HashSet<string> TargetIdentifiers
|
||||
{
|
||||
get { return targetIdentifiers; }
|
||||
@@ -356,6 +361,7 @@ namespace Barotrauma
|
||||
OnlyInside = element.GetAttributeBool("onlyinside", false);
|
||||
OnlyOutside = element.GetAttributeBool("onlyoutside", false);
|
||||
OnlyPlayerTriggered = element.GetAttributeBool("onlyplayertriggered", false);
|
||||
AllowWhenBroken = element.GetAttributeBool("allowwhenbroken", false);
|
||||
|
||||
Range = element.GetAttributeFloat("range", 0.0f);
|
||||
Offset = element.GetAttributeVector2("offset", Vector2.Zero);
|
||||
|
||||
Reference in New Issue
Block a user