(98ad00fa2) v0.9.1.0
This commit is contained in:
@@ -1295,15 +1295,6 @@
|
||||
<Content Include="$(MSBuildThisFileDirectory)Content\Characters\Fractalguardian\fractalguardian.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="$(MSBuildThisFileDirectory)Content\Characters\Human\damagedhead.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="$(MSBuildThisFileDirectory)Content\Characters\Human\damagedlegs.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="$(MSBuildThisFileDirectory)Content\Characters\Human\damagedtorso.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="$(MSBuildThisFileDirectory)Content\Characters\Human\firstnames_female.txt">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
@@ -2174,6 +2165,9 @@
|
||||
<None Include="$(MSBuildThisFileDirectory)Content\Items\Alien\AlienTurret2.ogg">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="$(MSBuildThisFileDirectory)Content\Items\Command\SonarPingFar.ogg">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="$(MSBuildThisFileDirectory)Content\Items\Misc\GuitarClown.ogg">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
|
||||
@@ -218,6 +218,35 @@ namespace Barotrauma
|
||||
if (run || speedMultiplier <= 0.0f) targetMovement *= speedMultiplier;
|
||||
Character.ResetSpeedMultiplier(); // Reset, items will set the value before the next update
|
||||
Character.AnimController.TargetMovement = targetMovement;
|
||||
|
||||
if (!Character.LockHands)
|
||||
{
|
||||
DropUnnecessaryItems();
|
||||
}
|
||||
|
||||
if (Character.IsKeyDown(InputType.Aim))
|
||||
{
|
||||
var cursorDiffX = Character.CursorPosition.X - Character.Position.X;
|
||||
if (cursorDiffX > 10.0f)
|
||||
{
|
||||
Character.AnimController.TargetDir = Direction.Right;
|
||||
}
|
||||
else if (cursorDiffX < -10.0f)
|
||||
{
|
||||
Character.AnimController.TargetDir = Direction.Left;
|
||||
}
|
||||
|
||||
if (Character.SelectedConstruction != null) Character.SelectedConstruction.SecondaryUse(deltaTime, Character);
|
||||
|
||||
}
|
||||
else if (Math.Abs(Character.AnimController.TargetMovement.X) > 0.1f && !Character.AnimController.InWater)
|
||||
{
|
||||
Character.AnimController.TargetDir = Character.AnimController.TargetMovement.X > 0.0f ? Direction.Right : Direction.Left;
|
||||
}
|
||||
}
|
||||
|
||||
private void DropUnnecessaryItems()
|
||||
{
|
||||
if (!NeedsDivingGear(Character.CurrentHull))
|
||||
{
|
||||
bool oxygenLow = Character.OxygenAvailable < CharacterHealth.LowOxygenThreshold;
|
||||
@@ -278,26 +307,6 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Character.IsKeyDown(InputType.Aim))
|
||||
{
|
||||
var cursorDiffX = Character.CursorPosition.X - Character.Position.X;
|
||||
if (cursorDiffX > 10.0f)
|
||||
{
|
||||
Character.AnimController.TargetDir = Direction.Right;
|
||||
}
|
||||
else if (cursorDiffX < -10.0f)
|
||||
{
|
||||
Character.AnimController.TargetDir = Direction.Left;
|
||||
}
|
||||
|
||||
if (Character.SelectedConstruction != null) Character.SelectedConstruction.SecondaryUse(deltaTime, Character);
|
||||
|
||||
}
|
||||
else if (Math.Abs(Character.AnimController.TargetMovement.X) > 0.1f && !Character.AnimController.InWater)
|
||||
{
|
||||
Character.AnimController.TargetDir = Character.AnimController.TargetMovement.X > 0.0f ? Direction.Right : Direction.Left;
|
||||
}
|
||||
}
|
||||
|
||||
protected void ReportProblems()
|
||||
@@ -428,16 +437,24 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
float currentVitality = Character.CharacterHealth.Vitality;
|
||||
float dmgPercentage = damage / currentVitality * 100;
|
||||
if (dmgPercentage < currentVitality / 10)
|
||||
// If not on the same team, always stay defensive
|
||||
if (attacker.TeamID != Character.TeamID)
|
||||
{
|
||||
// Don't retaliate on minor (accidental) dmg done by friendly characters
|
||||
AddCombatObjective(AIObjectiveCombat.CombatMode.Retreat, Rand.Range(0.5f, 1f, Rand.RandSync.Unsynced));
|
||||
AddCombatObjective(AIObjectiveCombat.CombatMode.Defensive, Rand.Range(0.5f, 1f, Rand.RandSync.Unsynced));
|
||||
}
|
||||
else
|
||||
{
|
||||
AddCombatObjective(AIObjectiveCombat.CombatMode.Defensive, Rand.Range(0.5f, 1f, Rand.RandSync.Unsynced));
|
||||
float currentVitality = Character.CharacterHealth.Vitality;
|
||||
float dmgPercentage = damage / currentVitality * 100;
|
||||
if (dmgPercentage < currentVitality / 10)
|
||||
{
|
||||
// Don't retaliate on minor (accidental) dmg done by characters that are in the same team
|
||||
AddCombatObjective(AIObjectiveCombat.CombatMode.Retreat, Rand.Range(0.5f, 1f, Rand.RandSync.Unsynced));
|
||||
}
|
||||
else
|
||||
{
|
||||
AddCombatObjective(AIObjectiveCombat.CombatMode.Defensive, Rand.Range(0.5f, 1f, Rand.RandSync.Unsynced));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -448,24 +465,25 @@ namespace Barotrauma
|
||||
|
||||
void AddCombatObjective(AIObjectiveCombat.CombatMode mode, float delay = 0)
|
||||
{
|
||||
bool holdPosition = Character.Info?.Job?.Prefab.Identifier == "watchman";
|
||||
if (ObjectiveManager.CurrentObjective is AIObjectiveCombat combatObjective)
|
||||
{
|
||||
if (combatObjective.Enemy != attacker || (combatObjective.Enemy == null && attacker == null))
|
||||
{
|
||||
// Replace the old objective with the new.
|
||||
ObjectiveManager.Objectives.Remove(combatObjective);
|
||||
objectiveManager.AddObjective(new AIObjectiveCombat(Character, attacker, mode, objectiveManager));
|
||||
objectiveManager.AddObjective(new AIObjectiveCombat(Character, attacker, mode, objectiveManager) { HoldPosition = holdPosition});
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (delay > 0)
|
||||
{
|
||||
objectiveManager.AddObjective(new AIObjectiveCombat(Character, attacker, mode, objectiveManager), delay);
|
||||
objectiveManager.AddObjective(new AIObjectiveCombat(Character, attacker, mode, objectiveManager) { HoldPosition = holdPosition }, delay);
|
||||
}
|
||||
else
|
||||
{
|
||||
objectiveManager.AddObjective(new AIObjectiveCombat(Character, attacker, mode, objectiveManager));
|
||||
objectiveManager.AddObjective(new AIObjectiveCombat(Character, attacker, mode, objectiveManager) { HoldPosition = holdPosition });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,8 @@ namespace Barotrauma
|
||||
const float coolDown = 10.0f;
|
||||
|
||||
public Character Enemy { get; private set; }
|
||||
|
||||
public bool HoldPosition { get; set; }
|
||||
|
||||
private Item _weapon;
|
||||
private Item Weapon
|
||||
{
|
||||
@@ -125,7 +126,10 @@ namespace Barotrauma
|
||||
TryArm();
|
||||
if (seekAmmunition == null || !subObjectives.Contains(seekAmmunition))
|
||||
{
|
||||
Move();
|
||||
if (!HoldPosition)
|
||||
{
|
||||
Move();
|
||||
}
|
||||
if (WeaponComponent != null)
|
||||
{
|
||||
OperateWeapon(deltaTime);
|
||||
@@ -151,6 +155,8 @@ namespace Barotrauma
|
||||
|
||||
private bool TryArm()
|
||||
{
|
||||
if (character.LockHands) { return false; }
|
||||
|
||||
if (Weapon != null)
|
||||
{
|
||||
if (!character.Inventory.Items.Contains(Weapon) || WeaponComponent == null)
|
||||
@@ -160,7 +166,7 @@ namespace Barotrauma
|
||||
else if (!WeaponComponent.HasRequiredContainedItems(false))
|
||||
{
|
||||
// Seek ammunition only if cannot find a new weapon
|
||||
if (!Reload(true, () => GetWeapon(out _) == null))
|
||||
if (!Reload(!HoldPosition, () => GetWeapon(out _) == null))
|
||||
{
|
||||
if (seekAmmunition != null && subObjectives.Contains(seekAmmunition))
|
||||
{
|
||||
@@ -266,7 +272,7 @@ namespace Barotrauma
|
||||
|
||||
private void Unequip()
|
||||
{
|
||||
if (character.SelectedItems.Contains(Weapon))
|
||||
if (!character.LockHands && character.SelectedItems.Contains(Weapon))
|
||||
{
|
||||
if (!Weapon.AllowedSlots.Contains(InvSlotType.Any) || !character.Inventory.TryPutItem(Weapon, character, new List<InvSlotType>() { InvSlotType.Any }))
|
||||
{
|
||||
@@ -277,6 +283,7 @@ namespace Barotrauma
|
||||
|
||||
private bool Equip()
|
||||
{
|
||||
if (character.LockHands) { return false; }
|
||||
if (!WeaponComponent.HasRequiredContainedItems(false))
|
||||
{
|
||||
Mode = CombatMode.Retreat;
|
||||
@@ -322,6 +329,13 @@ namespace Barotrauma
|
||||
|
||||
private void Engage()
|
||||
{
|
||||
if (character.LockHands)
|
||||
{
|
||||
Mode = CombatMode.Retreat;
|
||||
SteeringManager.Reset();
|
||||
return;
|
||||
}
|
||||
|
||||
retreatTarget = null;
|
||||
RemoveSubObjective(ref retreatObjective);
|
||||
RemoveSubObjective(ref seekAmmunition);
|
||||
|
||||
+2
-1
@@ -186,13 +186,14 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public Hull FindBestHull(IEnumerable<Hull> ignoredHulls = null)
|
||||
public Hull FindBestHull(IEnumerable<Hull> ignoredHulls = null, bool allowChangingTheSubmarine = true)
|
||||
{
|
||||
Hull bestHull = null;
|
||||
float bestValue = 0;
|
||||
foreach (Hull hull in Hull.hullList)
|
||||
{
|
||||
if (hull.Submarine == null) { continue; }
|
||||
if (!allowChangingTheSubmarine && hull.Submarine != character.Submarine) { continue; }
|
||||
if (ignoredHulls != null && ignoredHulls.Contains(hull)) { continue; }
|
||||
if (unreachable.Contains(hull)) { continue; }
|
||||
float hullSafety = 0;
|
||||
|
||||
@@ -96,6 +96,12 @@ namespace Barotrauma
|
||||
|
||||
protected override void Act(float deltaTime)
|
||||
{
|
||||
if (character.LockHands)
|
||||
{
|
||||
abandon = true;
|
||||
return;
|
||||
}
|
||||
|
||||
FindTargetItem();
|
||||
if (targetItem == null || moveToTarget == null)
|
||||
{
|
||||
|
||||
+9
-2
@@ -37,14 +37,21 @@ namespace Barotrauma
|
||||
float isSelected = character.SelectedConstruction == Item ? 50 : 0;
|
||||
float devotion = (Math.Min(Priority, 10) + isSelected) / 100;
|
||||
float max = MathHelper.Min(AIObjectiveManager.OrderPriority - 1, 90);
|
||||
|
||||
bool isCompleted = Item.IsFullCondition;
|
||||
if (isCompleted && character.SelectedConstruction == Item)
|
||||
{
|
||||
character?.Speak(TextManager.GetWithVariable("DialogItemRepaired", "[itemname]", Item.Name, true), null, 0.0f, "itemrepaired", 10.0f);
|
||||
}
|
||||
|
||||
return MathHelper.Lerp(0, max, MathHelper.Clamp(devotion + damagePriority * distanceFactor * successFactor * PriorityModifier, 0, 1));
|
||||
}
|
||||
|
||||
public override bool IsCompleted()
|
||||
{
|
||||
bool isCompleted = Item.IsFullCondition;
|
||||
if (isCompleted)
|
||||
{
|
||||
if (isCompleted && character.SelectedConstruction == Item)
|
||||
{
|
||||
character?.Speak(TextManager.GetWithVariable("DialogItemRepaired", "[itemname]", Item.Name, true), null, 0.0f, "itemrepaired", 10.0f);
|
||||
}
|
||||
return isCompleted;
|
||||
|
||||
@@ -97,7 +97,7 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
string[] splitOptionNames = translatedOptionNames.Split(',');
|
||||
string[] splitOptionNames = translatedOptionNames.Split(',', ',');
|
||||
OptionNames = new string[Options.Length];
|
||||
for (int i = 0; i < Options.Length && i < splitOptionNames.Length; i++)
|
||||
{
|
||||
|
||||
+13
-9
@@ -30,11 +30,13 @@ namespace Barotrauma
|
||||
[Serialize(0f, true), Editable(-360, 360, ToolTip = "Rotation offset (in degrees) used for animations and widgets. If the sprites in the sheet are in different orientations, use the orientation of the torso for the final version of your character (while editing the character in the editor, you can change the orientation freely).")]
|
||||
public float SpritesheetOrientation { get; set; }
|
||||
|
||||
private float limbScale;
|
||||
[Serialize(1.0f, true), Editable(MIN_SCALE, MAX_SCALE, DecimalCount = 3)]
|
||||
public float LimbScale { get; set; }
|
||||
public float LimbScale { get { return limbScale; } set { limbScale = MathHelper.Clamp(value, MIN_SCALE, MAX_SCALE); } }
|
||||
|
||||
private float jointScale;
|
||||
[Serialize(1.0f, true), Editable(MIN_SCALE, MAX_SCALE, DecimalCount = 3)]
|
||||
public float JointScale { get; set; }
|
||||
public float JointScale { get { return jointScale; } set { jointScale = MathHelper.Clamp(value, MIN_SCALE, MAX_SCALE); } }
|
||||
|
||||
// Don't show in the editor, because shouldn't be edited in runtime. Requires that the limb scale and the collider sizes are adjusted. TODO: automatize.
|
||||
[Serialize(1f, false)]
|
||||
@@ -368,16 +370,18 @@ namespace Barotrauma
|
||||
#endregion
|
||||
|
||||
#if CLIENT
|
||||
public override void AddToEditor(ParamsEditor editor)
|
||||
public void AddToEditor(ParamsEditor editor, bool alsoChildren = true)
|
||||
{
|
||||
base.AddToEditor(editor);
|
||||
var subParams = GetAllSubParams();
|
||||
foreach (var subParam in subParams)
|
||||
if (alsoChildren)
|
||||
{
|
||||
subParam.AddToEditor(editor);
|
||||
//TODO: divider sprite
|
||||
new GUIFrame(new RectTransform(new Point(editor.EditorBox.Rect.Width, 10), editor.EditorBox.Content.RectTransform),
|
||||
style: "ConnectionPanelWire");
|
||||
var subParams = GetAllSubParams();
|
||||
foreach (var subParam in subParams)
|
||||
{
|
||||
subParam.AddToEditor(editor);
|
||||
new GUIFrame(new RectTransform(new Point(editor.EditorBox.Rect.Width, 10), editor.EditorBox.Content.RectTransform),
|
||||
style: null, color: Color.Black);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1427,7 +1427,7 @@ namespace Barotrauma
|
||||
|
||||
Vector2 rayEnd = rayStart - new Vector2(0.0f, height);
|
||||
|
||||
var lowestLimb = FindLowestLimb();
|
||||
//var lowestLimb = FindLowestLimb();
|
||||
|
||||
float closestFraction = 1;
|
||||
GameMain.World.RayCast((fixture, point, normal, fraction) =>
|
||||
@@ -1440,7 +1440,7 @@ namespace Barotrauma
|
||||
break;
|
||||
case Physics.CollisionPlatform:
|
||||
Structure platform = fixture.Body.UserData as Structure;
|
||||
if (IgnorePlatforms || lowestLimb.Position.Y < platform.Rect.Y) return -1;
|
||||
if (IgnorePlatforms && TargetMovement.Y < -0.5f || Collider.Position.Y < platform.Rect.Y) return -1;
|
||||
break;
|
||||
case Physics.CollisionWall:
|
||||
case Physics.CollisionLevel:
|
||||
|
||||
@@ -130,16 +130,20 @@ namespace Barotrauma
|
||||
{
|
||||
get
|
||||
{
|
||||
if (ViewTarget == null) return AnimController.AimSourcePos;
|
||||
if (ViewTarget == null) { return AnimController.AimSourcePos; }
|
||||
|
||||
Vector2 viewTargetWorldPos = ViewTarget.WorldPosition;
|
||||
if (ViewTarget is Item targetItem)
|
||||
{
|
||||
Turret turret = targetItem.GetComponent<Turret>();
|
||||
if (turret != null)
|
||||
{
|
||||
return new Vector2(targetItem.Rect.X + turret.TransformedBarrelPos.X, targetItem.Rect.Y - turret.TransformedBarrelPos.Y);
|
||||
viewTargetWorldPos = new Vector2(
|
||||
targetItem.WorldRect.X + turret.TransformedBarrelPos.X,
|
||||
targetItem.WorldRect.Y - turret.TransformedBarrelPos.Y);
|
||||
}
|
||||
}
|
||||
return ViewTarget.Position;
|
||||
return Position + (viewTargetWorldPos - WorldPosition);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1517,7 +1521,7 @@ namespace Barotrauma
|
||||
|
||||
public bool CanAccessInventory(Inventory inventory)
|
||||
{
|
||||
if (!CanInteract) return false;
|
||||
if (!CanInteract || inventory.Locked) { return false; }
|
||||
|
||||
//the inventory belongs to some other character
|
||||
if (inventory.Owner is Character && inventory.Owner != this)
|
||||
@@ -1558,7 +1562,11 @@ namespace Barotrauma
|
||||
{
|
||||
distanceToItem = -1.0f;
|
||||
|
||||
if (!CanInteract || item.HiddenInGame) return false;
|
||||
bool hidden = item.HiddenInGame;
|
||||
#if CLIENT
|
||||
if (Screen.Selected == GameMain.SubEditorScreen) { hidden = false; }
|
||||
#endif
|
||||
if (!CanInteract || hidden) return false;
|
||||
|
||||
if (item.ParentInventory != null)
|
||||
{
|
||||
@@ -1802,7 +1810,7 @@ namespace Barotrauma
|
||||
{
|
||||
SelectCharacter(focusedCharacter);
|
||||
}
|
||||
else if (focusedCharacter != null && IsKeyHit(InputType.Health) && focusedCharacter.CharacterHealth.UseHealthWindow)
|
||||
else if (focusedCharacter != null && IsKeyHit(InputType.Health) && focusedCharacter.CharacterHealth.UseHealthWindow && CanInteractWith(focusedCharacter, 160f, false))
|
||||
{
|
||||
if (focusedCharacter == SelectedCharacter)
|
||||
{
|
||||
|
||||
@@ -105,7 +105,7 @@ namespace Barotrauma
|
||||
public static bool CheatsEnabled;
|
||||
|
||||
private static List<ColoredText> unsavedMessages = new List<ColoredText>();
|
||||
private static int messagesPerFile = 800;
|
||||
private static int messagesPerFile = 5000;
|
||||
public const string SavePath = "ConsoleLogs";
|
||||
|
||||
private static void AssignOnExecute(string names, Action<string[]> onExecute)
|
||||
@@ -648,6 +648,20 @@ namespace Barotrauma
|
||||
},null));
|
||||
|
||||
#if DEBUG
|
||||
commands.Add(new Command("teleportsub", "teleportsub [start/end]: Teleport the submarine to the start or end of the level. WARNING: does not take outposts into account, so often leads to physics glitches. Only use for debugging.", (string[] args) =>
|
||||
{
|
||||
if (Submarine.MainSub == null || Level.Loaded == null) return;
|
||||
|
||||
if (args.Length > 0 && args[0].ToLowerInvariant() == "start")
|
||||
{
|
||||
Submarine.MainSub.SetPosition(Level.Loaded.StartPosition);
|
||||
}
|
||||
else
|
||||
{
|
||||
Submarine.MainSub.SetPosition(Level.Loaded.EndPosition);
|
||||
}
|
||||
}, isCheat: true));
|
||||
|
||||
commands.Add(new Command("waterphysicsparams", "waterphysicsparams [stiffness] [spread] [damping]: defaults 0.02, 0.05, 0.05", (string[] args) =>
|
||||
{
|
||||
Vector2 explosionPos = GameMain.GameScreen.Cam.ScreenToWorld(PlayerInput.MousePosition);
|
||||
@@ -1582,7 +1596,14 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
string fileName = "DebugConsoleLog_" + DateTime.Now.ToShortDateString() + "_" + DateTime.Now.ToShortTimeString();
|
||||
string fileName = "DebugConsoleLog_";
|
||||
#if SERVER
|
||||
fileName += "Server_";
|
||||
#else
|
||||
fileName += "Client_";
|
||||
#endif
|
||||
|
||||
fileName += DateTime.Now.ToShortDateString() + "_" + DateTime.Now.ToShortTimeString();
|
||||
var invalidChars = Path.GetInvalidFileNameChars();
|
||||
foreach (char invalidChar in invalidChars)
|
||||
{
|
||||
|
||||
@@ -79,6 +79,7 @@ namespace Barotrauma
|
||||
|
||||
public int GetTotalItemCost()
|
||||
{
|
||||
if (purchasedItems == null) return 0;
|
||||
return purchasedItems.Sum(i => i.ItemPrefab.GetPrice(campaign.Map.CurrentLocation).BuyPrice * i.Quantity);
|
||||
}
|
||||
|
||||
|
||||
@@ -267,7 +267,13 @@ namespace Barotrauma
|
||||
private static bool sendUserStatistics = true;
|
||||
public static bool SendUserStatistics
|
||||
{
|
||||
get { return sendUserStatistics; }
|
||||
get
|
||||
{
|
||||
#if DEBUG
|
||||
return false;
|
||||
#endif
|
||||
return sendUserStatistics;
|
||||
}
|
||||
set
|
||||
{
|
||||
sendUserStatistics = value;
|
||||
|
||||
@@ -178,29 +178,35 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
private void SetUser(Character character)
|
||||
{
|
||||
if (user == character) return;
|
||||
if (user != null && user.Removed) user = null;
|
||||
if (user == character) { return; }
|
||||
if (user != null && user.Removed) { user = null; }
|
||||
|
||||
user = character;
|
||||
|
||||
if (item.body?.FarseerBody == null || item.Removed ||
|
||||
!GameMain.World.BodyList.Contains(item.body.FarseerBody))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (user != null)
|
||||
{
|
||||
foreach (Limb limb in user.AnimController.Limbs)
|
||||
{
|
||||
if (limb.body.FarseerBody != null)
|
||||
if (limb.body.FarseerBody != null && GameMain.World.BodyList.Contains(limb.body.FarseerBody))
|
||||
{
|
||||
if (GameMain.World.BodyList.Contains(limb.body.FarseerBody))
|
||||
{
|
||||
item.body.FarseerBody.RestoreCollisionWith(limb.body.FarseerBody);
|
||||
}
|
||||
item.body.FarseerBody.RestoreCollisionWith(limb.body.FarseerBody);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (Limb limb in character.AnimController.Limbs)
|
||||
{
|
||||
item.body.FarseerBody.IgnoreCollisionWith(limb.body.FarseerBody);
|
||||
if (limb.body.FarseerBody != null && GameMain.World.BodyList.Contains(limb.body.FarseerBody))
|
||||
{
|
||||
item.body.FarseerBody.IgnoreCollisionWith(limb.body.FarseerBody);
|
||||
}
|
||||
}
|
||||
|
||||
user = character;
|
||||
}
|
||||
|
||||
private void RestoreCollision()
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
private UsableIn usableIn;
|
||||
|
||||
[Serialize(0.0f, false), Editable(MinValueFloat = 0.0f, MaxValueFloat = 1000.0f)]
|
||||
[Serialize(0.0f, false), Editable(MinValueFloat = -1000.0f, MaxValueFloat = 1000.0f)]
|
||||
public float Force
|
||||
{
|
||||
get { return force; }
|
||||
|
||||
@@ -11,6 +11,8 @@ namespace Barotrauma.Items.Components
|
||||
private float progressTimer;
|
||||
private float progressState;
|
||||
|
||||
private bool hasPower;
|
||||
|
||||
private ItemContainer inputContainer, outputContainer;
|
||||
|
||||
public ItemContainer InputContainer
|
||||
@@ -58,7 +60,8 @@ namespace Barotrauma.Items.Components
|
||||
return;
|
||||
}
|
||||
|
||||
if (voltage < minVoltage) { return; }
|
||||
hasPower = voltage >= minVoltage;
|
||||
if (!hasPower) { return; }
|
||||
|
||||
var repairable = item.GetComponent<Repairable>();
|
||||
if (repairable != null)
|
||||
@@ -68,7 +71,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
ApplyStatusEffects(ActionType.OnActive, deltaTime, null);
|
||||
|
||||
if (powerConsumption == 0.0f) voltage = 1.0f;
|
||||
if (powerConsumption == 0.0f) { voltage = 1.0f; }
|
||||
|
||||
progressTimer += deltaTime * voltage;
|
||||
Voltage -= deltaTime * 10.0f;
|
||||
@@ -107,28 +110,41 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
if (targetItem.Prefab.DeconstructItems.Any())
|
||||
if (GameMain.NetworkMember == null || GameMain.NetworkMember.IsServer)
|
||||
{
|
||||
inputContainer.Inventory.RemoveItem(targetItem);
|
||||
Entity.Spawner.AddToRemoveQueue(targetItem);
|
||||
MoveInputQueue();
|
||||
PutItemsToLinkedContainer();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (outputContainer.Inventory.Items.All(i => i != null))
|
||||
if (targetItem.Prefab.DeconstructItems.Any())
|
||||
{
|
||||
targetItem.Drop(dropper: null);
|
||||
//drop all items that are inside the deconstructed item
|
||||
foreach (ItemContainer ic in targetItem.GetComponents<ItemContainer>())
|
||||
{
|
||||
if (ic?.Inventory?.Items == null) { continue; }
|
||||
foreach (Item containedItem in ic.Inventory.Items)
|
||||
{
|
||||
containedItem?.Drop(dropper: null, createNetworkEvent: true);
|
||||
}
|
||||
}
|
||||
|
||||
inputContainer.Inventory.RemoveItem(targetItem);
|
||||
Entity.Spawner.AddToRemoveQueue(targetItem);
|
||||
MoveInputQueue();
|
||||
PutItemsToLinkedContainer();
|
||||
}
|
||||
else
|
||||
{
|
||||
outputContainer.Inventory.TryPutItem(targetItem, user: null, createNetworkEvent: true);
|
||||
if (outputContainer.Inventory.Items.All(i => i != null))
|
||||
{
|
||||
targetItem.Drop(dropper: null);
|
||||
}
|
||||
else
|
||||
{
|
||||
outputContainer.Inventory.TryPutItem(targetItem, user: null, createNetworkEvent: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (inputContainer.Inventory.Items.Any(i => i != null))
|
||||
{
|
||||
#if SERVER
|
||||
item.CreateServerEvent(this);
|
||||
#endif
|
||||
progressTimer = 0.0f;
|
||||
progressState = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,21 +204,17 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!IsActive) { progressState = 0.0f; }
|
||||
|
||||
#if CLIENT
|
||||
if (!IsActive)
|
||||
{
|
||||
progressTimer = 0.0f;
|
||||
activateButton.Text = TextManager.Get("DeconstructorDeconstruct");
|
||||
}
|
||||
else
|
||||
{
|
||||
activateButton.Text = TextManager.Get("DeconstructorCancel");
|
||||
progressState = 0.0f;
|
||||
}
|
||||
|
||||
#if CLIENT
|
||||
activateButton.Text = TextManager.Get(IsActive ? "DeconstructorCancel" : "DeconstructorDeconstruct");
|
||||
#endif
|
||||
|
||||
inputContainer.Inventory.Locked = IsActive;
|
||||
inputContainer.Inventory.Locked = IsActive;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,8 @@ namespace Barotrauma.Items.Components
|
||||
private float timeUntilReady;
|
||||
private float requiredTime;
|
||||
|
||||
private bool hasPower;
|
||||
|
||||
private Character user;
|
||||
|
||||
private ItemContainer inputContainer, outputContainer;
|
||||
@@ -198,8 +200,9 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
progressState = fabricatedItem == null ? 0.0f : (requiredTime - timeUntilReady) / requiredTime;
|
||||
|
||||
if (voltage < minVoltage) { return; }
|
||||
|
||||
hasPower = voltage >= minVoltage;
|
||||
if (!hasPower) { return; }
|
||||
|
||||
var repairable = item.GetComponent<Repairable>();
|
||||
if (repairable != null)
|
||||
{
|
||||
@@ -215,43 +218,50 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
if (timeUntilReady > 0.0f) { return; }
|
||||
|
||||
var availableIngredients = GetAvailableIngredients();
|
||||
foreach (FabricationRecipe.RequiredItem ingredient in fabricatedItem.RequiredItems)
|
||||
if (GameMain.NetworkMember == null || GameMain.NetworkMember.IsServer)
|
||||
{
|
||||
for (int i = 0; i < ingredient.Amount; i++)
|
||||
var availableIngredients = GetAvailableIngredients();
|
||||
foreach (FabricationRecipe.RequiredItem ingredient in fabricatedItem.RequiredItems)
|
||||
{
|
||||
var requiredItem = inputContainer.Inventory.Items.FirstOrDefault(it => it != null && it.Prefab == ingredient.ItemPrefab && it.Condition >= ingredient.ItemPrefab.Health * ingredient.MinCondition);
|
||||
if (requiredItem == null) continue;
|
||||
|
||||
//Item4 = use condition bool
|
||||
if (ingredient.UseCondition && requiredItem.Condition - ingredient.ItemPrefab.Health * ingredient.MinCondition > 0.0f) //Leave it behind with reduced condition if it has enough to stay above 0
|
||||
for (int i = 0; i < ingredient.Amount; i++)
|
||||
{
|
||||
requiredItem.Condition -= ingredient.ItemPrefab.Health * ingredient.MinCondition;
|
||||
continue;
|
||||
var availableItem = availableIngredients.FirstOrDefault(it => it != null && it.Prefab == ingredient.ItemPrefab && it.Condition >= ingredient.ItemPrefab.Health * ingredient.MinCondition);
|
||||
if (availableItem == null) { continue; }
|
||||
|
||||
//Item4 = use condition bool
|
||||
if (ingredient.UseCondition && availableItem.Condition - ingredient.ItemPrefab.Health * ingredient.MinCondition > 0.0f) //Leave it behind with reduced condition if it has enough to stay above 0
|
||||
{
|
||||
availableItem.Condition -= ingredient.ItemPrefab.Health * ingredient.MinCondition;
|
||||
continue;
|
||||
}
|
||||
availableIngredients.Remove(availableItem);
|
||||
Entity.Spawner.AddToRemoveQueue(availableItem);
|
||||
inputContainer.Inventory.RemoveItem(availableItem);
|
||||
}
|
||||
Entity.Spawner.AddToRemoveQueue(requiredItem);
|
||||
inputContainer.Inventory.RemoveItem(requiredItem);
|
||||
}
|
||||
}
|
||||
|
||||
if (outputContainer.Inventory.Items.All(i => i != null))
|
||||
{
|
||||
Entity.Spawner.AddToSpawnQueue(fabricatedItem.TargetItem, item.Position, item.Submarine, fabricatedItem.TargetItem.Health * fabricatedItem.OutCondition);
|
||||
}
|
||||
else
|
||||
{
|
||||
Entity.Spawner.AddToSpawnQueue(fabricatedItem.TargetItem, outputContainer.Inventory, fabricatedItem.TargetItem.Health * fabricatedItem.OutCondition);
|
||||
}
|
||||
|
||||
if ((GameMain.NetworkMember == null || GameMain.NetworkMember.IsServer) && user != null && !user.Removed)
|
||||
{
|
||||
foreach (Skill skill in fabricatedItem.RequiredSkills)
|
||||
if (outputContainer.Inventory.Items.All(i => i != null))
|
||||
{
|
||||
user.Info.IncreaseSkillLevel(skill.Identifier, skill.Level / 100.0f * SkillIncreaseMultiplier, user.WorldPosition + Vector2.UnitY * 150.0f);
|
||||
Entity.Spawner.AddToSpawnQueue(fabricatedItem.TargetItem, item.Position, item.Submarine, fabricatedItem.TargetItem.Health * fabricatedItem.OutCondition);
|
||||
}
|
||||
else
|
||||
{
|
||||
Entity.Spawner.AddToSpawnQueue(fabricatedItem.TargetItem, outputContainer.Inventory, fabricatedItem.TargetItem.Health * fabricatedItem.OutCondition);
|
||||
}
|
||||
|
||||
if (user != null && !user.Removed)
|
||||
{
|
||||
foreach (Skill skill in fabricatedItem.RequiredSkills)
|
||||
{
|
||||
user.Info.IncreaseSkillLevel(skill.Identifier, skill.Level / 100.0f * SkillIncreaseMultiplier, user.WorldPosition + Vector2.UnitY * 150.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CancelFabricating(null);
|
||||
CancelFabricating(null);
|
||||
#if SERVER
|
||||
item.CreateServerEvent(this);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
private bool CanBeFabricated(FabricationRecipe fabricableItem)
|
||||
@@ -328,6 +338,8 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
var matchingItem = availableIngredients.Find(it => !usedItems.Contains(it) && IsItemValidIngredient(it, requiredItem));
|
||||
if (matchingItem == null) { continue; }
|
||||
|
||||
availableIngredients.Remove(matchingItem);
|
||||
|
||||
if (matchingItem.ParentInventory == inputContainer.Inventory)
|
||||
{
|
||||
|
||||
@@ -254,15 +254,19 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
foreach (Connection connection in connections)
|
||||
{
|
||||
if (!connection.IsPower) continue;
|
||||
if (!connection.IsPower) { continue; }
|
||||
foreach (Connection recipient in connection.Recipients)
|
||||
{
|
||||
if (!(recipient.Item is Item it)) continue;
|
||||
if (!(recipient.Item is Item it)) { continue; }
|
||||
|
||||
PowerTransfer pt = it.GetComponent<PowerTransfer>();
|
||||
if (pt == null) continue;
|
||||
if (pt == null) { continue; }
|
||||
|
||||
load = Math.Max(load, pt.PowerLoad);
|
||||
//calculate how much external power there is in the grid
|
||||
//(power coming from somewhere else than this reactor, e.g. batteries)
|
||||
float externalPower = CurrPowerConsumption - pt.CurrPowerConsumption;
|
||||
//reduce the external power from the load to prevent overloading the grid
|
||||
load = Math.Max(load, pt.PowerLoad - externalPower);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,7 +176,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
float successFactor = requiredSkills.Count == 0 ? 1.0f : 0.0f;
|
||||
|
||||
//item must have been below 50% condition for the player to get an achievement or XP for repairing it
|
||||
//item must have been below the repair threshold for the player to get an achievement or XP for repairing it
|
||||
if (item.Condition < ShowRepairUIThreshold)
|
||||
{
|
||||
wasBroken = true;
|
||||
|
||||
@@ -61,6 +61,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
get
|
||||
{
|
||||
if (GameMain.NetworkMember?.ServerSettings != null && !GameMain.NetworkMember.ServerSettings.AllowRewiring) { return false; }
|
||||
return locked || connections.Any(c => c != null && c.ConnectionPanel.Locked);
|
||||
}
|
||||
set { locked = value; }
|
||||
|
||||
@@ -152,13 +152,12 @@ namespace Barotrauma
|
||||
get { return description ?? prefab.Description; }
|
||||
set { description = value; }
|
||||
}
|
||||
|
||||
private bool hiddenInGame;
|
||||
|
||||
[Editable, Serialize(false, true)]
|
||||
public bool HiddenInGame
|
||||
{
|
||||
get { return hiddenInGame; }
|
||||
set { hiddenInGame = value; }
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public float ImpactTolerance
|
||||
@@ -262,7 +261,26 @@ namespace Barotrauma
|
||||
/// </summary>
|
||||
public string ContainerIdentifier
|
||||
{
|
||||
get { return Container?.prefab.Identifier ?? ""; }
|
||||
get
|
||||
{
|
||||
return
|
||||
Container?.prefab.Identifier ??
|
||||
ParentInventory?.Owner?.ToString() ??
|
||||
"";
|
||||
}
|
||||
set { /*do nothing*/ }
|
||||
}
|
||||
|
||||
[Serialize(false, false)]
|
||||
/// <summary>
|
||||
/// Can be used by status effects or conditionals to check if the physics body of the item is active
|
||||
/// </summary>
|
||||
public bool PhysicsBodyActive
|
||||
{
|
||||
get
|
||||
{
|
||||
return body != null && body.Enabled;
|
||||
}
|
||||
set { /*do nothing*/ }
|
||||
}
|
||||
|
||||
@@ -315,7 +333,7 @@ namespace Barotrauma
|
||||
get { return spriteColor; }
|
||||
}
|
||||
|
||||
public bool IsFullCondition => Condition >= MaxCondition;
|
||||
public bool IsFullCondition => MathUtils.NearlyEqual(Condition, MaxCondition);
|
||||
public float MaxCondition => Prefab.Health;
|
||||
public float ConditionPercentage => MathUtils.Percentage(Condition, MaxCondition);
|
||||
|
||||
@@ -334,6 +352,8 @@ namespace Barotrauma
|
||||
if (Indestructible) return;
|
||||
|
||||
float prev = condition;
|
||||
bool wasInFullCondition = IsFullCondition;
|
||||
|
||||
condition = MathHelper.Clamp(value, 0.0f, Prefab.Health);
|
||||
if (condition == 0.0f && prev > 0.0f)
|
||||
{
|
||||
@@ -349,9 +369,17 @@ namespace Barotrauma
|
||||
|
||||
SetActiveSprite();
|
||||
|
||||
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsServer && !MathUtils.NearlyEqual(lastSentCondition, condition))
|
||||
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsServer)
|
||||
{
|
||||
if (Math.Abs(lastSentCondition - condition) > 1.0f || condition == 0.0f || condition == Prefab.Health)
|
||||
if (Math.Abs(lastSentCondition - condition) > 1.0f)
|
||||
{
|
||||
conditionUpdatePending = true;
|
||||
}
|
||||
else if (wasInFullCondition != IsFullCondition)
|
||||
{
|
||||
conditionUpdatePending = true;
|
||||
}
|
||||
else if (!MathUtils.NearlyEqual(lastSentCondition, condition) && (condition <= 0.0f || condition >= Prefab.Health))
|
||||
{
|
||||
conditionUpdatePending = true;
|
||||
}
|
||||
@@ -2086,11 +2114,13 @@ namespace Barotrauma
|
||||
System.Diagnostics.Debug.Assert(Submarine != null || rootContainer.ParentInventory?.Owner is Character);
|
||||
|
||||
Vector2 subPosition = Submarine == null ? Vector2.Zero : Submarine.HiddenSubPosition;
|
||||
|
||||
|
||||
int width = ResizeHorizontal ? rect.Width : defaultRect.Width;
|
||||
int height = ResizeVertical ? rect.Height : defaultRect.Height;
|
||||
element.Add(new XAttribute("rect",
|
||||
(int)(rect.X - subPosition.X) + "," +
|
||||
(int)(rect.Y - subPosition.Y) + "," +
|
||||
defaultRect.Width + "," + defaultRect.Height));
|
||||
width + "," + height));
|
||||
|
||||
if (linkedTo != null && linkedTo.Count > 0)
|
||||
{
|
||||
|
||||
@@ -17,7 +17,8 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
public bool IsOptional { get; set; }
|
||||
|
||||
public bool MatchOnEmpty { get; set; }
|
||||
|
||||
public bool IgnoreInEditor { get; set; }
|
||||
|
||||
private string[] excludedIdentifiers;
|
||||
@@ -99,6 +100,11 @@ namespace Barotrauma
|
||||
var containedItems = parentItem.ContainedItems;
|
||||
if (containedItems == null) return false;
|
||||
|
||||
if (MatchOnEmpty && !containedItems.Any(ci => ci != null))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
foreach (Item contained in containedItems)
|
||||
{
|
||||
if (contained.Condition > 0.0f && MatchesItem(contained)) return true;
|
||||
@@ -222,6 +228,7 @@ namespace Barotrauma
|
||||
|
||||
ri.IsOptional = element.GetAttributeBool("optional", false);
|
||||
ri.IgnoreInEditor = element.GetAttributeBool("ignoreineditor", false);
|
||||
ri.MatchOnEmpty = element.GetAttributeBool("matchonempty", false);
|
||||
return ri;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -627,7 +627,8 @@ namespace Barotrauma
|
||||
|
||||
if (IsHorizontal)
|
||||
{
|
||||
if (Math.Max(hull1.Surface + hull1.WaveY[hull1.WaveY.Length - 1], hull2.Surface + hull2.WaveY[0]) > rect.Y) return;
|
||||
//if the water level is above the gap, oxygen doesn't circulate
|
||||
if (Math.Max(hull1.WorldSurface + hull1.WaveY[hull1.WaveY.Length - 1], hull2.WorldSurface + hull2.WaveY[0]) > WorldRect.Y) { return; }
|
||||
}
|
||||
|
||||
float totalOxygen = hull1.Oxygen + hull2.Oxygen;
|
||||
|
||||
@@ -1548,13 +1548,13 @@ namespace Barotrauma
|
||||
|
||||
Point? minSize = null;
|
||||
DockingPort subPort = null;
|
||||
float closestDistance = float.MaxValue;
|
||||
if (Submarine.MainSub != null)
|
||||
{
|
||||
Point subSize = Submarine.MainSub.GetDockedBorders().Size;
|
||||
Point outpostSize = outpost.GetDockedBorders().Size;
|
||||
minSize = new Point(Math.Max(subSize.X, outpostSize.X), subSize.Y + outpostSize.Y);
|
||||
|
||||
float closestDistance = float.MaxValue;
|
||||
foreach (DockingPort port in DockingPort.List)
|
||||
{
|
||||
if (port.IsHorizontal || port.Docked) { continue; }
|
||||
@@ -1570,17 +1570,43 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
DockingPort outpostPort = null;
|
||||
closestDistance = float.MaxValue;
|
||||
foreach (DockingPort port in DockingPort.List)
|
||||
{
|
||||
if (port.IsHorizontal || port.Docked) { continue; }
|
||||
if (port.Item.Submarine != outpost) { continue; }
|
||||
//the outpost port has to be at the bottom of the outpost
|
||||
if (port.Item.WorldPosition.Y > outpost.WorldPosition.Y) { continue; }
|
||||
float dist = Math.Abs(port.Item.WorldPosition.X - outpost.WorldPosition.X);
|
||||
if (dist < closestDistance)
|
||||
{
|
||||
outpostPort = port;
|
||||
closestDistance = dist;
|
||||
}
|
||||
}
|
||||
|
||||
float subDockingPortOffset = subPort == null ? 0.0f : subPort.Item.WorldPosition.X - Submarine.MainSub.WorldPosition.X;
|
||||
//don't try to compensate if the port is very far from the sub's center of mass
|
||||
if (Math.Abs(subDockingPortOffset) > 2000.0f)
|
||||
if (Math.Abs(subDockingPortOffset) > 5000.0f)
|
||||
{
|
||||
subDockingPortOffset = MathHelper.Clamp(subDockingPortOffset, -2000.0f, 2000.0f);
|
||||
subDockingPortOffset = MathHelper.Clamp(subDockingPortOffset, -5000.0f, 5000.0f);
|
||||
string warningMsg = "Docking port very far from the sub's center of mass (submarine: " + Submarine.MainSub.Name + ", dist: " + subDockingPortOffset + "). The level generator may not be able to place the outpost so that docking is possible.";
|
||||
DebugConsole.NewMessage(warningMsg, Color.Orange);
|
||||
GameAnalyticsManager.AddErrorEventOnce("Lever.CreateOutposts:DockingPortVeryFar" + Submarine.MainSub.Name, GameAnalyticsSDK.Net.EGAErrorSeverity.Warning, warningMsg);
|
||||
}
|
||||
|
||||
outpost.SetPosition(outpost.FindSpawnPos(i == 0 ? StartPosition : EndPosition, minSize, subDockingPortOffset));
|
||||
float outpostDockingPortOffset = subPort == null ? 0.0f : outpostPort.Item.WorldPosition.X - outpost.WorldPosition.X;
|
||||
//don't try to compensate if the port is very far from the outpost's center of mass
|
||||
if (Math.Abs(outpostDockingPortOffset) > 5000.0f)
|
||||
{
|
||||
outpostDockingPortOffset = MathHelper.Clamp(outpostDockingPortOffset, -5000.0f, 5000.0f);
|
||||
string warningMsg = "Docking port very far from the outpost's center of mass (outpost: " + outpost.Name + ", dist: " + outpostDockingPortOffset + "). The level generator may not be able to place the outpost so that docking is possible.";
|
||||
DebugConsole.NewMessage(warningMsg, Color.Orange);
|
||||
GameAnalyticsManager.AddErrorEventOnce("Lever.CreateOutposts:OutpostDockingPortVeryFar" + outpost.Name, GameAnalyticsSDK.Net.EGAErrorSeverity.Warning, warningMsg);
|
||||
}
|
||||
|
||||
outpost.SetPosition(outpost.FindSpawnPos(i == 0 ? StartPosition : EndPosition, minSize, subDockingPortOffset - outpostDockingPortOffset));
|
||||
if ((i == 0) == !Mirrored)
|
||||
{
|
||||
StartOutpost = outpost;
|
||||
|
||||
@@ -308,18 +308,24 @@ namespace Barotrauma
|
||||
if (ResizeHorizontal) placeSize.X = position.X - placePosition.X;
|
||||
if (ResizeVertical) placeSize.Y = placePosition.Y - position.Y;
|
||||
|
||||
newRect = Submarine.AbsRect(placePosition, placeSize);
|
||||
|
||||
if (PlayerInput.LeftButtonReleased())
|
||||
//don't allow resizing width/height to less than the grid size
|
||||
if (ResizeHorizontal && Math.Abs(placeSize.X) < Submarine.GridSize.X)
|
||||
{
|
||||
//don't allow resizing width/height to zero
|
||||
if ((!ResizeHorizontal || placeSize.X != 0.0f) && (!ResizeVertical || placeSize.Y != 0.0f))
|
||||
{
|
||||
newRect.Location -= MathUtils.ToPoint(Submarine.MainSub.Position);
|
||||
placeSize.X = Submarine.GridSize.X;
|
||||
}
|
||||
if (ResizeVertical && Math.Abs(placeSize.Y) < Submarine.GridSize.Y)
|
||||
{
|
||||
placeSize.X = Submarine.GridSize.Y;
|
||||
}
|
||||
|
||||
var structure = new Structure(newRect, this, Submarine.MainSub);
|
||||
structure.Submarine = Submarine.MainSub;
|
||||
}
|
||||
newRect = Submarine.AbsRect(placePosition, placeSize);
|
||||
if (PlayerInput.LeftButtonReleased())
|
||||
{
|
||||
newRect.Location -= MathUtils.ToPoint(Submarine.MainSub.Position);
|
||||
var structure = new Structure(newRect, this, Submarine.MainSub)
|
||||
{
|
||||
Submarine = Submarine.MainSub
|
||||
};
|
||||
|
||||
selected = null;
|
||||
return;
|
||||
|
||||
@@ -297,6 +297,12 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsFileCorrupted
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
//constructors & generation ----------------------------------------------------
|
||||
|
||||
public Submarine(string filePath, string hash = "", bool tryLoad = true) : base(null)
|
||||
@@ -322,12 +328,17 @@ namespace Barotrauma
|
||||
int maxLoadRetries = 4;
|
||||
for (int i = 0; i <= maxLoadRetries; i++)
|
||||
{
|
||||
doc = OpenFile(filePath);
|
||||
doc = OpenFile(filePath, out Exception e);
|
||||
if (e != null && !(e is IOException)) { break; }
|
||||
if (doc != null || i == maxLoadRetries || !File.Exists(filePath)) { break; }
|
||||
DebugConsole.NewMessage("Opening submarine file \"" + filePath + "\" failed, retrying in 250 ms...");
|
||||
Thread.Sleep(250);
|
||||
}
|
||||
if (doc == null || doc.Root == null) { return; }
|
||||
if (doc == null || doc.Root == null)
|
||||
{
|
||||
IsFileCorrupted = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (doc != null && doc.Root != null)
|
||||
{
|
||||
@@ -1139,7 +1150,11 @@ namespace Barotrauma
|
||||
savedSubmarines[i].Dispose();
|
||||
}
|
||||
}
|
||||
savedSubmarines.Add(new Submarine(filePath));
|
||||
var sub = new Submarine(filePath);
|
||||
if (!sub.IsFileCorrupted)
|
||||
{
|
||||
savedSubmarines.Add(sub);
|
||||
}
|
||||
savedSubmarines = savedSubmarines.OrderBy(s => s.filePath ?? "").ToList();
|
||||
}
|
||||
|
||||
@@ -1193,16 +1208,26 @@ namespace Barotrauma
|
||||
|
||||
foreach (string path in filePaths)
|
||||
{
|
||||
savedSubmarines.Add(new Submarine(path));
|
||||
var sub = new Submarine(path);
|
||||
if (!sub.IsFileCorrupted)
|
||||
{
|
||||
savedSubmarines.Add(sub);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static readonly string TempFolder = Path.Combine("Submarine", "Temp");
|
||||
|
||||
public static XDocument OpenFile(string file)
|
||||
{
|
||||
return OpenFile(file, out _);
|
||||
}
|
||||
|
||||
public static XDocument OpenFile(string file, out Exception exception)
|
||||
{
|
||||
XDocument doc = null;
|
||||
string extension = "";
|
||||
exception = null;
|
||||
|
||||
try
|
||||
{
|
||||
@@ -1229,6 +1254,7 @@ namespace Barotrauma
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
exception = e;
|
||||
DebugConsole.ThrowError("Loading submarine \"" + file + "\" failed!", e);
|
||||
return null;
|
||||
}
|
||||
@@ -1243,6 +1269,7 @@ namespace Barotrauma
|
||||
|
||||
catch (Exception e)
|
||||
{
|
||||
exception = e;
|
||||
DebugConsole.ThrowError("Loading submarine \"" + file + "\" failed! (" + e.Message + ")");
|
||||
return null;
|
||||
}
|
||||
@@ -1257,6 +1284,7 @@ namespace Barotrauma
|
||||
|
||||
catch (Exception e)
|
||||
{
|
||||
exception = e;
|
||||
DebugConsole.ThrowError("Loading submarine \"" + file + "\" failed! (" + e.Message + ")");
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@ namespace Barotrauma.Networking
|
||||
|
||||
public const int MaxPlayers = 16;
|
||||
|
||||
public const int ServerNameMaxLength = 60;
|
||||
|
||||
public static string MasterServerUrl = GameMain.Config.MasterServerUrl;
|
||||
|
||||
//if a Character is further than this from the sub and the players, the server will disable it
|
||||
|
||||
@@ -21,16 +21,28 @@ namespace Barotrauma.Networking
|
||||
public readonly Entity Entity;
|
||||
public readonly UInt16 ID;
|
||||
|
||||
public UInt16 EntityID
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
//arbitrary extra data that will be passed to the Write method of the serializable entity
|
||||
//(the index of an itemcomponent for example)
|
||||
protected object[] Data;
|
||||
|
||||
public bool Sent;
|
||||
|
||||
protected NetEntityEvent(INetSerializable entity, UInt16 id)
|
||||
protected NetEntityEvent(INetSerializable serializableEntity, UInt16 id)
|
||||
{
|
||||
this.ID = id;
|
||||
this.Entity = entity as Entity;
|
||||
this.Entity = serializableEntity as Entity;
|
||||
RefreshEntityID();
|
||||
}
|
||||
|
||||
public void RefreshEntityID()
|
||||
{
|
||||
this.EntityID = this.Entity is Entity entity ? entity.ID : Entity.NullEntityID;
|
||||
}
|
||||
|
||||
public void SetData(object[] data)
|
||||
|
||||
+1
-1
@@ -65,7 +65,7 @@ namespace Barotrauma.Networking
|
||||
break;
|
||||
}
|
||||
|
||||
tempBuffer.Write((UInt16)e.Entity.ID);
|
||||
tempBuffer.Write(e.EntityID);
|
||||
tempBuffer.Write((byte)tempEventBuffer.LengthBytes);
|
||||
tempBuffer.Write(tempEventBuffer);
|
||||
tempBuffer.WritePadBits();
|
||||
|
||||
@@ -241,6 +241,32 @@ namespace Barotrauma.Networking
|
||||
public virtual void Update(float deltaTime) { }
|
||||
|
||||
public virtual void Disconnect() { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if the two version are compatible (= if they can play together in multiplayer).
|
||||
/// Returns null if compatibility could not be determined (invalid/unknown version number).
|
||||
/// </summary>
|
||||
public static bool? IsCompatible(string myVersion, string remoteVersion)
|
||||
{
|
||||
if (string.IsNullOrEmpty(myVersion) || string.IsNullOrEmpty(remoteVersion)) { return null; }
|
||||
|
||||
if (!Version.TryParse(myVersion, out Version myVersionNumber)) { return null; }
|
||||
if (!Version.TryParse(remoteVersion, out Version remoteVersionNumber)) { return null; }
|
||||
|
||||
return IsCompatible(myVersionNumber, remoteVersionNumber);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if the two version are compatible (= if they can play together in multiplayer).
|
||||
/// </summary>
|
||||
public static bool IsCompatible(Version myVersion, Version remoteVersion)
|
||||
{
|
||||
//major.minor.build.revision
|
||||
//revision number is ignored, other values have to match
|
||||
return
|
||||
myVersion.Major == remoteVersion.Major &&
|
||||
myVersion.Minor == remoteVersion.Minor &&
|
||||
myVersion.Build == remoteVersion.Build;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,8 @@ namespace Barotrauma.Networking
|
||||
|
||||
partial class ServerSettings : ISerializableEntity
|
||||
{
|
||||
public const string SettingsFile = "serversettings.xml";
|
||||
|
||||
[Flags]
|
||||
public enum NetFlags : byte
|
||||
{
|
||||
@@ -539,7 +541,14 @@ namespace Barotrauma.Networking
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
|
||||
[Serialize(true, true)]
|
||||
public bool AllowRewiring
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
private YesNoMaybe traitorsEnabled;
|
||||
public YesNoMaybe TraitorsEnabled
|
||||
{
|
||||
|
||||
@@ -21,7 +21,11 @@ namespace Barotrauma.Steam
|
||||
{ "monster", 8 },
|
||||
{ "art", 8 },
|
||||
{ "mission", 8 },
|
||||
{ "environment", 5 }
|
||||
{ "event set", 8 },
|
||||
{ "total conversion", 5 },
|
||||
{ "environment", 5 },
|
||||
{ "item assembly", 5 },
|
||||
{ "language", 5 }
|
||||
};
|
||||
|
||||
private List<string> popularTags = new List<string>();
|
||||
|
||||
@@ -375,7 +375,7 @@ namespace Barotrauma
|
||||
//Enum.TryParse(element.GetAttributeString("bodytype", "Dynamic"), out BodyType bodyType);
|
||||
body.BodyType = BodyType.Dynamic;
|
||||
body.CollisionCategories = Physics.CollisionItem;
|
||||
body.CollidesWith = Physics.CollisionWall | Physics.CollisionLevel;
|
||||
body.CollidesWith = Physics.CollisionWall | Physics.CollisionLevel | Physics.CollisionPlatform;
|
||||
body.Friction = element.GetAttributeFloat("friction", 0.3f);
|
||||
body.Restitution = element.GetAttributeFloat("restitution", 0.05f);
|
||||
body.UserData = this;
|
||||
|
||||
@@ -414,9 +414,6 @@ namespace Barotrauma
|
||||
{
|
||||
switch (Name)
|
||||
{
|
||||
case "Condition":
|
||||
if (parentObject is Item item) { return item.Condition; }
|
||||
break;
|
||||
case "Voltage":
|
||||
if (parentObject is Powered powered) { return powered.Voltage; }
|
||||
break;
|
||||
@@ -460,6 +457,21 @@ namespace Barotrauma
|
||||
case "IsOn":
|
||||
{ if (parentObject is LightComponent lightComponent) { return lightComponent.IsOn; } }
|
||||
break;
|
||||
case "Condition":
|
||||
{
|
||||
if (parentObject is Item item) { return item.Condition; }
|
||||
}
|
||||
break;
|
||||
case "ContainerIdentifier":
|
||||
{
|
||||
if (parentObject is Item item) { return item.ContainerIdentifier; }
|
||||
}
|
||||
break;
|
||||
case "PhysicsBodyActive":
|
||||
{
|
||||
if (parentObject is Item item) { return item.PhysicsBodyActive; }
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
@@ -114,7 +114,7 @@ namespace Barotrauma
|
||||
string stringValue = element.Attribute(name).Value;
|
||||
if (string.IsNullOrEmpty(stringValue)) return defaultValue;
|
||||
|
||||
string[] splitValue = stringValue.Split(',');
|
||||
string[] splitValue = stringValue.Split(',', ',');
|
||||
|
||||
if (convertToLowerInvariant)
|
||||
{
|
||||
|
||||
@@ -277,7 +277,7 @@ namespace Barotrauma
|
||||
case OperatorType.Equals:
|
||||
if (type == typeof(bool))
|
||||
{
|
||||
return ((bool)propertyValue) == (AttributeValue == "true");
|
||||
return ((bool)propertyValue) == (AttributeValue == "true" || AttributeValue == "True");
|
||||
}
|
||||
else if (FloatValue == null)
|
||||
{
|
||||
@@ -290,7 +290,7 @@ namespace Barotrauma
|
||||
case OperatorType.NotEquals:
|
||||
if (type == typeof(bool))
|
||||
{
|
||||
return ((bool)propertyValue) != (AttributeValue == "true");
|
||||
return ((bool)propertyValue) != (AttributeValue == "true" || AttributeValue == "True");
|
||||
}
|
||||
else if (FloatValue == null)
|
||||
{
|
||||
|
||||
@@ -424,6 +424,7 @@ namespace Barotrauma
|
||||
public virtual bool HasRequiredConditions(List<ISerializableEntity> targets)
|
||||
{
|
||||
if (!propertyConditionals.Any()) return true;
|
||||
if (requiredItems.All(ri => ri.MatchOnEmpty) && targets.Count == 0) return true;
|
||||
switch (conditionalComparison)
|
||||
{
|
||||
case PropertyConditional.Comparison.Or:
|
||||
|
||||
@@ -145,7 +145,7 @@ namespace Barotrauma
|
||||
UnlockAchievement(c, "clowncostume");
|
||||
}
|
||||
|
||||
if (Submarine.MainSub != null && c.Submarine == null)
|
||||
if (Submarine.MainSub != null && c.Submarine == null && c.ConfigPath == Character.HumanConfigFile)
|
||||
{
|
||||
float dist = 500 / Physics.DisplayToRealWorldRatio;
|
||||
if (Vector2.DistanceSquared(c.WorldPosition, Submarine.MainSub.WorldPosition) >
|
||||
|
||||
@@ -322,6 +322,8 @@ namespace Barotrauma
|
||||
|
||||
string[] messages = serverMessage.Split('/');
|
||||
|
||||
bool translationsFound = false;
|
||||
|
||||
try
|
||||
{
|
||||
for (int i = 0; i < messages.Length; i++)
|
||||
@@ -333,6 +335,7 @@ namespace Barotrauma
|
||||
if (msg != null) // If a translation was found, otherwise use the original
|
||||
{
|
||||
messages[i] = msg;
|
||||
translationsFound = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -343,6 +346,7 @@ namespace Barotrauma
|
||||
if (msg != null) // If a translation was found, otherwise use the original
|
||||
{
|
||||
messages[i] = msg;
|
||||
translationsFound = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -358,12 +362,19 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
string translatedServerMessage = string.Empty;
|
||||
for (int i = 0; i < messages.Length; i++)
|
||||
if (translationsFound)
|
||||
{
|
||||
translatedServerMessage += messages[i];
|
||||
string translatedServerMessage = string.Empty;
|
||||
for (int i = 0; i < messages.Length; i++)
|
||||
{
|
||||
translatedServerMessage += messages[i];
|
||||
}
|
||||
return translatedServerMessage;
|
||||
}
|
||||
else
|
||||
{
|
||||
return serverMessage;
|
||||
}
|
||||
return translatedServerMessage;
|
||||
}
|
||||
|
||||
catch (IndexOutOfRangeException exception)
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,3 +1,110 @@
|
||||
---------------------------------------------------------------------------------------------------------
|
||||
v0.9.1.0
|
||||
---------------------------------------------------------------------------------------------------------
|
||||
|
||||
Additions and changes:
|
||||
- Disabled riot shields for now (too much griefing potential).
|
||||
- Toolboxes can be fabricated and decontructed.
|
||||
- Nerfed nitroglycerin's structure damage and increased the impact tolerance from 4 to 6.
|
||||
- Made alien pistols a little less underwhelming (sounds, recoil, particle effects).
|
||||
- Deconstructors drop all items that are inside the deconstructed item. Previously they would just get destroyed,
|
||||
making it a potential exploit to destroy items that should not be possible to deconstruct.
|
||||
- Modified welding fuel tank and oxygen tank sprites a bit to differentiate them from each other a bit more.
|
||||
- Modified plasma cutter and welding tool sprites a bit to differentiate them from each other a bit more.
|
||||
- Diving suits play the warning beep when there's no tank in the suit (not just when the tank is running out).
|
||||
- Server list can be sorted according to ping, name, compatibility or any of the other property in the list.
|
||||
- Docking ports of the enemy submarine are not shown on the sonar during combat missions.
|
||||
- Recharge headset batteries between rounds in single player.
|
||||
- Disable status monitor displays when out of power.
|
||||
- Reduce server CPU usage.
|
||||
- Update ladder and gap references if a waypoint is moved around in the editor.
|
||||
- More descriptive error messages when publishing a Workshop item fails.
|
||||
- Allow selecting multiple files at once when adding files to a Workshop item.
|
||||
- Made the autogenerated submarine preview pictures larger.
|
||||
- The "Host server" menu remembers the previously used port numbers and the player count.
|
||||
- Restrict server names to a maximum of 60 characters.
|
||||
- Items now collide with platforms.
|
||||
- The game automatically opens the generated crash report when it crashes.
|
||||
- Added "setmaxplayers" command to the dedicated server.
|
||||
- Clients can change the server password using the command "setpassword" if they have a permission from the host.
|
||||
- Reduced the range of the sonar ping sound and added a more subtle ping sound that can be heard further away.
|
||||
- Watchmen now hold position when attacked.
|
||||
- Added a subtle glow to alien buttons to make them a bit more noticeable.
|
||||
- Items that are set to be hidden in-game can still be interacted with in the sub editor.
|
||||
- EXPERIMENTAL: option to disable rewiring items in multiplayer. At the moment the setting can only be
|
||||
changed by editing a parameter called "allowrewiring" in serversettings.xml.
|
||||
|
||||
Misc bugfixes:
|
||||
- Fixed the position of an outpost's docking port not being taken into account when determining how to
|
||||
place it in the level. Caused large submarines sometimes to collide with walls when docked to outposts
|
||||
where the port is offset from the center.
|
||||
- Fixed corrupted sub files causing crashes.
|
||||
- Fixed item editing HUD not appearing on any other item after one item has been selected in-game
|
||||
(e.g. editing the channel on a wifi component prevented editing other items).
|
||||
- Fixed ladders and other resizeable items reverting to their original size if they're resized and
|
||||
the sub is saved and reloaded.
|
||||
- Fixed inability to resize gaps in the sub editor after they've been placed.
|
||||
- Reactors take other power sources into account when calculating how much power they need to generate.
|
||||
Fixes overloads on Humpback when turning on the backup batteries and operating the reactor normally.
|
||||
- Fixed watchmen not retaliating when a character does very small amounts of damage to them.
|
||||
- Fixed bots being able to take handcuffs off from themselves.
|
||||
- Fixed waypoint and spawnpoints being selectable in the sub editor even if they're hidden.
|
||||
- Fixed deconstructing coilgun ammo boxes giving out more materials than the materials required to fabricate them.
|
||||
- Scrollbars can only be dragged if the mouse button is pressed down while the cursor is on the scrollbar,
|
||||
not by holding the button and moving it on the scrollbar. Fixes accidentally switching from slider
|
||||
to another (often happens in the reactor interface).
|
||||
- Fixed crashing when setting limb or joint scale to 0 using console commands.
|
||||
- Fixed dropdowns in the Workshop item publish menu being draw behind the buttons below them.
|
||||
- Fixes bots being unable to exit ladders if some part of their body is below the platform.
|
||||
- Ignore keyboard inputs (delete, arrow keys, copy/paste) in the sub editor when a textbox is selected.
|
||||
Prevents accidentally deleting items/structures when attempting to delete text from a textbox.
|
||||
- Toolboxes can't be put inside other toolboxes or in the doctor's clothes.
|
||||
- Fixed items bought from the store during a singleplayer campaign session being deducted from the credits
|
||||
when save & quitting from the map.
|
||||
- Flares stop emitting particles when inside an inventory.
|
||||
- Fixed oxygen not flowing through horizontal gaps between subs (e.g. between Remora and the drone).
|
||||
- Decreased the size of the mountain in the RidgeBasic level type to prevent it from blocking the main path.
|
||||
- Fixed too small collider sizes on a bunch of crafting materials.
|
||||
- Fixed order options ("hold fire"/"fire at will" etc) being displayed in one button instead of
|
||||
being split into separate buttons when playing the game in Chinese.
|
||||
- Fixed "Text Self_CauseOfDeathDescription.Unknown not found" console error if a character gets killed
|
||||
by being inside a respawn shuttle when it despawns.
|
||||
- Fixed sonar not scaling properly when resolution is changed mid-round.
|
||||
- Fixed fabricators & deconstructors displaying the "insufficient power" warning when power is low
|
||||
(but still high enough for the devices to run).
|
||||
|
||||
Networking fixes:
|
||||
- Fixed another ID mismatch problem that occasionally caused clients to get kicked out in multiplayer,
|
||||
usually with an error message warning about a missing item.
|
||||
- Fixed players always getting range banned when banned by a client.
|
||||
- Fixed turrets not being aimed correctly in multiplayer if they're in another sub (e.g. the coilgun in
|
||||
Remora's drone).
|
||||
- More reliable fabricator and deconstructor syncing. Should fix items disappearing when multiple players
|
||||
attempt to use the device at the same time and strange timing inconsistencies when deconstructing
|
||||
multiple items in succession.
|
||||
- Fixed all servers showing "unknown" as the game mode in the server list.
|
||||
- Fixed server not allowing forward slashes in host messages.
|
||||
- Fixed repair interface sometimes getting stuck close to 100% in multiplayer.
|
||||
|
||||
Character editor fixes and improvements:
|
||||
- Nicer layout, made the panels hideable.
|
||||
- Added buttons for creating joints, duplicating limbs, and deleting limbs/joints.
|
||||
- A dropdown for selecting which content package to add the character to.
|
||||
- Allow creating a new content package during character creation.
|
||||
- Added hotkeys 1, 2, 3 for limb, joint, and animation modes respectively.
|
||||
- Change the logic of deciding on which parameters are shown and when. In the ragdoll mode you can now
|
||||
see the ragdoll, but also scale it and see the main parameters. Source rects are now longer shown on the
|
||||
sprite sheet if limbs mode is disabled.
|
||||
- Automatically select edit limbs mode when a new character is created.
|
||||
- Option to create multiple limbs in the character creation wizard.
|
||||
- Disallow deleting the main limb because it often causes crashes.
|
||||
- Only allow selecting PNG files as the texture.
|
||||
- The spritesheet is shown by default.
|
||||
- Fixed deleted joints not being saved properly.
|
||||
- Only lock the axis for torso/head position when alt is down.
|
||||
- Disable test pose if the character is not a humanoid.
|
||||
- Clamp camera offset so that the character is always at least partially visible.
|
||||
|
||||
---------------------------------------------------------------------------------------------------------
|
||||
v0.9.0.7
|
||||
---------------------------------------------------------------------------------------------------------
|
||||
@@ -52,7 +159,6 @@ the reactor behave as if it had two rods in it.
|
||||
to working like buttons which send out a pulse when interacted with).
|
||||
- Fixed an issue that occasionally caused the main menu to look distorted when launching the game on Mac.
|
||||
- Fixed crash after opening the file browser from the Workshop menu more than once on Linux.
|
||||
- Fixed deconstructing coilgun ammo boxes giving out more materials than the materials required to fabricate them.
|
||||
- Fixed combat mission achievements being impossible to unlock.
|
||||
- Fixed item scales not being saved when the scale is modified in the sub editor.
|
||||
- Fixed incorrect physicorium shell description.
|
||||
@@ -61,7 +167,7 @@ to working like buttons which send out a pulse when interacted with).
|
||||
AI characters to let go of ladders when holding RMB.
|
||||
- Fixed explosion damage bypassing armor (both creature shells and wearable items).
|
||||
- Fixed OverrideSaveFolder and OverrideMultiplayerSaveFolder settings not being saved.
|
||||
- Fixed order/report icons "twitching" when the sub moves.
|
||||
- Fixed order/rept icons "twitching" when the sub moves. or
|
||||
- Fixed players being able to repair submerged electrical items indefinitely.
|
||||
- Fixed a "attempted to access a removed ragdoll" console error when a character wearing the health
|
||||
scanner HUD is removed.
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
startwhenclientsready="False"
|
||||
startwhenclientsreadyratio="0.8"
|
||||
allowspectating="True"
|
||||
voipenabled="True"
|
||||
endroundatlevelend="True"
|
||||
saveserverlogs="True"
|
||||
allowragdollbutton="True"
|
||||
@@ -22,6 +21,7 @@
|
||||
botcount="0"
|
||||
maxbotcount="16"
|
||||
allowdisguises="True"
|
||||
allowrewiring="True"
|
||||
subselectionmode="Manual"
|
||||
modeselectionmode="Manual"
|
||||
endvoterequiredratio="0.6"
|
||||
@@ -48,5 +48,5 @@
|
||||
TraitorsEnabled="No"
|
||||
BotSpawnMode="Normal"
|
||||
AllowedRandomMissionTypes="Random,Salvage,Monster,Cargo,Combat"
|
||||
AllowedClientNameChars="32-33,38-46,48-57,65-90,91,93,95-122,192-255,384-591,1024-1279"
|
||||
AllowedClientNameChars="32-33,38-46,48-57,65-90,91-91,93-93,95-122,192-255,384-591,1024-1279"
|
||||
ServerMessage="" />
|
||||
Reference in New Issue
Block a user