(98ad00fa2) v0.9.1.0
This commit is contained in:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user