(3a5d98b) v0.9.6.0
This commit is contained in:
@@ -31,5 +31,5 @@ using System.Runtime.InteropServices;
|
|||||||
// You can specify all the values or you can default the Build and Revision Numbers
|
// You can specify all the values or you can default the Build and Revision Numbers
|
||||||
// by using the '*' as shown below:
|
// by using the '*' as shown below:
|
||||||
// [assembly: AssemblyVersion("1.0.*")]
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
[assembly: AssemblyVersion("0.9.5.1")]
|
[assembly: AssemblyVersion("0.9.6.0")]
|
||||||
[assembly: AssemblyFileVersion("0.9.5.1")]
|
[assembly: AssemblyFileVersion("0.9.6.0")]
|
||||||
|
|||||||
@@ -85,8 +85,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (character.Inventory != null)
|
if (character.Inventory != null)
|
||||||
{
|
{
|
||||||
if (!character.LockHands && character.Stun < 0.1f &&
|
if (!LockInventory(character))
|
||||||
(character.SelectedConstruction == null || character.SelectedConstruction?.GetComponent<Controller>()?.User != character))
|
|
||||||
{
|
{
|
||||||
character.Inventory.Update(deltaTime, cam);
|
character.Inventory.Update(deltaTime, cam);
|
||||||
}
|
}
|
||||||
@@ -325,7 +324,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
if (character.Inventory != null && !character.LockHands)
|
if (character.Inventory != null && !character.LockHands)
|
||||||
{
|
{
|
||||||
character.Inventory.Locked = (character.SelectedConstruction?.GetComponent<Controller>()?.User == character);
|
character.Inventory.Locked = LockInventory(character);
|
||||||
character.Inventory.DrawOwn(spriteBatch);
|
character.Inventory.DrawOwn(spriteBatch);
|
||||||
character.Inventory.CurrentLayout = CharacterHealth.OpenHealthWindow == null && character.SelectedCharacter == null ?
|
character.Inventory.CurrentLayout = CharacterHealth.OpenHealthWindow == null && character.SelectedCharacter == null ?
|
||||||
CharacterInventory.Layout.Default :
|
CharacterInventory.Layout.Default :
|
||||||
@@ -368,6 +367,17 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static bool LockInventory(Character character)
|
||||||
|
{
|
||||||
|
if (character?.Inventory == null || !character.AllowInput || character.LockHands) { return true; }
|
||||||
|
|
||||||
|
//lock if using a controller, except if we're also using a connection panel in the same item
|
||||||
|
return
|
||||||
|
character.SelectedConstruction != null &&
|
||||||
|
character.SelectedConstruction?.GetComponent<Controller>()?.User == character &&
|
||||||
|
character.SelectedConstruction?.GetComponent<ConnectionPanel>()?.User != character;
|
||||||
|
}
|
||||||
|
|
||||||
private static void DrawOrderIndicator(SpriteBatch spriteBatch, Camera cam, Character character, Order order, float iconAlpha = 1.0f)
|
private static void DrawOrderIndicator(SpriteBatch spriteBatch, Camera cam, Character character, Order order, float iconAlpha = 1.0f)
|
||||||
{
|
{
|
||||||
if (order.TargetAllCharacters)
|
if (order.TargetAllCharacters)
|
||||||
|
|||||||
@@ -2041,6 +2041,16 @@ namespace Barotrauma
|
|||||||
|
|
||||||
commands.Add(new Command("spawnsub", "spawnsub [subname]: Spawn a submarine at the position of the cursor", (string[] args) =>
|
commands.Add(new Command("spawnsub", "spawnsub [subname]: Spawn a submarine at the position of the cursor", (string[] args) =>
|
||||||
{
|
{
|
||||||
|
if (GameMain.NetworkMember != null)
|
||||||
|
{
|
||||||
|
ThrowError("Cannot spawn additional submarines during a multiplayer session.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (args.Length == 0)
|
||||||
|
{
|
||||||
|
ThrowError("Please enter the name of the submarine.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Submarine spawnedSub = Submarine.Load(args[0], false);
|
Submarine spawnedSub = Submarine.Load(args[0], false);
|
||||||
|
|||||||
@@ -220,6 +220,7 @@ namespace Barotrauma
|
|||||||
msgHolder.RectTransform.Resize(new Point(msgHolder.Rect.Width, msgHolder.Children.Sum(c => c.Rect.Height) + (int)(10 * GUI.Scale)), resizeChildren: false);
|
msgHolder.RectTransform.Resize(new Point(msgHolder.Rect.Width, msgHolder.Children.Sum(c => c.Rect.Height) + (int)(10 * GUI.Scale)), resizeChildren: false);
|
||||||
msgHolder.RectTransform.SizeChanged += Recalculate;
|
msgHolder.RectTransform.SizeChanged += Recalculate;
|
||||||
chatBox.RecalculateChildren();
|
chatBox.RecalculateChildren();
|
||||||
|
chatBox.UpdateScrollBarSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
CoroutineManager.StartCoroutine(UpdateMessageAnimation(msgHolder, 0.5f));
|
CoroutineManager.StartCoroutine(UpdateMessageAnimation(msgHolder, 0.5f));
|
||||||
|
|||||||
@@ -435,12 +435,30 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public void SelectNext(bool force = false, bool autoScroll = true)
|
public void SelectNext(bool force = false, bool autoScroll = true)
|
||||||
{
|
{
|
||||||
Select(Math.Min(Content.CountChildren - 1, SelectedIndex + 1), force, autoScroll);
|
int index = SelectedIndex + 1;
|
||||||
|
while (index < Content.CountChildren)
|
||||||
|
{
|
||||||
|
if (Content.GetChild(index).Visible)
|
||||||
|
{
|
||||||
|
Select(index, force, autoScroll);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
index++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SelectPrevious(bool force = false, bool autoScroll = true)
|
public void SelectPrevious(bool force = false, bool autoScroll = true)
|
||||||
{
|
{
|
||||||
Select(Math.Max(0, SelectedIndex - 1), force, autoScroll);
|
int index = SelectedIndex - 1;
|
||||||
|
while (index >= 0)
|
||||||
|
{
|
||||||
|
if (Content.GetChild(index).Visible)
|
||||||
|
{
|
||||||
|
Select(index, force, autoScroll);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
index--;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Select(int childIndex, bool force = false, bool autoScroll = true)
|
public void Select(int childIndex, bool force = false, bool autoScroll = true)
|
||||||
|
|||||||
@@ -233,7 +233,7 @@ namespace Barotrauma
|
|||||||
switch (InputType)
|
switch (InputType)
|
||||||
{
|
{
|
||||||
case NumberType.Int:
|
case NumberType.Int:
|
||||||
TextBox.textFilterFunction = text => new string(text.Where(c => char.IsNumber(c)).ToArray());
|
TextBox.textFilterFunction = text => new string(text.Where(c => char.IsNumber(c) || c == '-').ToArray());
|
||||||
break;
|
break;
|
||||||
case NumberType.Float:
|
case NumberType.Float:
|
||||||
TextBox.textFilterFunction = text => new string(text.Where(c => char.IsDigit(c) || c == '.' || c == '-').ToArray());
|
TextBox.textFilterFunction = text => new string(text.Where(c => char.IsDigit(c) || c == '.' || c == '-').ToArray());
|
||||||
|
|||||||
@@ -126,6 +126,11 @@ namespace Barotrauma
|
|||||||
set { text.Text = value; }
|
set { text.Text = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Color? DefaultTextColor
|
||||||
|
{
|
||||||
|
get { return defaultTextColor; }
|
||||||
|
}
|
||||||
|
|
||||||
public GUITickBox(RectTransform rectT, string label, ScalableFont font = null, string style = "") : base(null, rectT)
|
public GUITickBox(RectTransform rectT, string label, ScalableFont font = null, string style = "") : base(null, rectT)
|
||||||
{
|
{
|
||||||
CanBeFocused = true;
|
CanBeFocused = true;
|
||||||
|
|||||||
@@ -318,6 +318,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private void InitUserStats()
|
private void InitUserStats()
|
||||||
{
|
{
|
||||||
|
return;
|
||||||
|
|
||||||
if (GameSettings.ShowUserStatisticsPrompt)
|
if (GameSettings.ShowUserStatisticsPrompt)
|
||||||
{
|
{
|
||||||
if (TextManager.ContainsTag("statisticspromptheader") && TextManager.ContainsTag("statisticsprompttext"))
|
if (TextManager.ContainsTag("statisticspromptheader") && TextManager.ContainsTag("statisticsprompttext"))
|
||||||
@@ -404,14 +406,18 @@ namespace Barotrauma
|
|||||||
GUI.Init(Window, Config.SelectedContentPackages, GraphicsDevice);
|
GUI.Init(Window, Config.SelectedContentPackages, GraphicsDevice);
|
||||||
DebugConsole.Init();
|
DebugConsole.Init();
|
||||||
|
|
||||||
if (Config.AutoUpdateWorkshopItems)
|
CrossThread.RequestExecutionOnMainThread(() =>
|
||||||
{
|
{
|
||||||
if (SteamManager.AutoUpdateWorkshopItems())
|
if (Config.AutoUpdateWorkshopItems)
|
||||||
{
|
{
|
||||||
ContentPackage.LoadAll();
|
if (SteamManager.AutoUpdateWorkshopItems())
|
||||||
Config.ReloadContentPackages();
|
{
|
||||||
|
ContentPackage.LoadAll();
|
||||||
|
Config.ReloadContentPackages();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
|
|
||||||
if (SelectedPackages.None())
|
if (SelectedPackages.None())
|
||||||
{
|
{
|
||||||
@@ -844,6 +850,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
SteamManager.Update((float)Timing.Step);
|
SteamManager.Update((float)Timing.Step);
|
||||||
|
|
||||||
|
TaskPool.Update();
|
||||||
|
|
||||||
SoundManager?.Update();
|
SoundManager?.Update();
|
||||||
|
|
||||||
Timing.Accumulator -= Timing.Step;
|
Timing.Accumulator -= Timing.Step;
|
||||||
|
|||||||
@@ -431,7 +431,6 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
characterArea.CanBeFocused = false;
|
|
||||||
characterArea.CanBeSelected = false;
|
characterArea.CanBeSelected = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -204,9 +204,14 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
campaign.SuppressStateSending = true;
|
campaign.SuppressStateSending = true;
|
||||||
|
|
||||||
campaign.Map.SetLocation(currentLocIndex == UInt16.MaxValue ? -1 : currentLocIndex);
|
//we need to have the latest save file to display location/mission/store
|
||||||
campaign.Map.SelectLocation(selectedLocIndex == UInt16.MaxValue ? -1 : selectedLocIndex);
|
if (campaign.LastSaveID == saveID)
|
||||||
campaign.Map.SelectMission(selectedMissionIndex);
|
{
|
||||||
|
campaign.Map.SetLocation(currentLocIndex == UInt16.MaxValue ? -1 : currentLocIndex);
|
||||||
|
campaign.Map.SelectLocation(selectedLocIndex == UInt16.MaxValue ? -1 : selectedLocIndex);
|
||||||
|
campaign.Map.SelectMission(selectedMissionIndex);
|
||||||
|
campaign.CargoManager.SetPurchasedItems(purchasedItems);
|
||||||
|
}
|
||||||
|
|
||||||
campaign.startWatchmanID = startWatchmanID;
|
campaign.startWatchmanID = startWatchmanID;
|
||||||
campaign.endWatchmanID = endWatchmanID;
|
campaign.endWatchmanID = endWatchmanID;
|
||||||
@@ -215,7 +220,6 @@ namespace Barotrauma
|
|||||||
campaign.PurchasedHullRepairs = purchasedHullRepairs;
|
campaign.PurchasedHullRepairs = purchasedHullRepairs;
|
||||||
campaign.PurchasedItemRepairs = purchasedItemRepairs;
|
campaign.PurchasedItemRepairs = purchasedItemRepairs;
|
||||||
campaign.PurchasedLostShuttles = purchasedLostShuttles;
|
campaign.PurchasedLostShuttles = purchasedLostShuttles;
|
||||||
campaign.CargoManager.SetPurchasedItems(purchasedItems);
|
|
||||||
|
|
||||||
if (myCharacterInfo != null)
|
if (myCharacterInfo != null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ namespace Barotrauma.Items.Components
|
|||||||
if (brokenSprite == null)
|
if (brokenSprite == null)
|
||||||
{
|
{
|
||||||
//broken doors turn black if no broken sprite has been configured
|
//broken doors turn black if no broken sprite has been configured
|
||||||
color = color * (item.Condition / item.Prefab.Health);
|
color *= (item.Condition / item.Prefab.Health);
|
||||||
color.A = 255;
|
color.A = 255;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -184,7 +184,7 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
partial void SetState(bool open, bool isNetworkMessage, bool sendNetworkMessage, bool forcedOpen)
|
partial void SetState(bool open, bool isNetworkMessage, bool sendNetworkMessage, bool forcedOpen)
|
||||||
{
|
{
|
||||||
if (isStuck ||
|
if ((IsStuck && !isNetworkMessage) ||
|
||||||
(PredictedState == null && isOpen == open) ||
|
(PredictedState == null && isOpen == open) ||
|
||||||
(PredictedState != null && isOpen == PredictedState.Value && isOpen == open))
|
(PredictedState != null && isOpen == PredictedState.Value && isOpen == open))
|
||||||
{
|
{
|
||||||
@@ -211,10 +211,6 @@ namespace Barotrauma.Items.Components
|
|||||||
PlaySound(forcedOpen ? ActionType.OnPicked : ActionType.OnUse, item.WorldPosition);
|
PlaySound(forcedOpen ? ActionType.OnPicked : ActionType.OnUse, item.WorldPosition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//opening a partially stuck door makes it less stuck
|
|
||||||
if (isOpen) stuck = MathHelper.Clamp(stuck - 30.0f, 0.0f, 100.0f);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
public override void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
||||||
@@ -225,7 +221,7 @@ namespace Barotrauma.Items.Components
|
|||||||
bool forcedOpen = msg.ReadBoolean();
|
bool forcedOpen = msg.ReadBoolean();
|
||||||
SetState(open, isNetworkMessage: true, sendNetworkMessage: false, forcedOpen: forcedOpen);
|
SetState(open, isNetworkMessage: true, sendNetworkMessage: false, forcedOpen: forcedOpen);
|
||||||
Stuck = msg.ReadRangedSingle(0.0f, 100.0f, 8);
|
Stuck = msg.ReadRangedSingle(0.0f, 100.0f, 8);
|
||||||
|
if (isStuck) { OpenState = 0.0f; }
|
||||||
PredictedState = null;
|
PredictedState = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,19 @@ namespace Barotrauma.Items.Components
|
|||||||
get { return light; }
|
get { return light; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void OnScaleChanged()
|
||||||
|
{
|
||||||
|
light.SpriteScale = Vector2.One * item.Scale;
|
||||||
|
light.Position = ParentBody != null ? ParentBody.Position : item.Position;
|
||||||
|
}
|
||||||
|
|
||||||
|
partial void SetLightSourceState(bool enabled, float brightness)
|
||||||
|
{
|
||||||
|
if (light == null) { return; }
|
||||||
|
light.Enabled = enabled;
|
||||||
|
light.Color = LightColor * brightness;
|
||||||
|
}
|
||||||
|
|
||||||
public void Draw(SpriteBatch spriteBatch, bool editing = false, float itemDepth = -1)
|
public void Draw(SpriteBatch spriteBatch, bool editing = false, float itemDepth = -1)
|
||||||
{
|
{
|
||||||
if (light.LightSprite != null && (item.body == null || item.body.Enabled) && lightBrightness > 0.0f)
|
if (light.LightSprite != null && (item.body == null || item.body.Enabled) && lightBrightness > 0.0f)
|
||||||
@@ -28,7 +41,7 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
public override void FlipX(bool relativeToSub)
|
public override void FlipX(bool relativeToSub)
|
||||||
{
|
{
|
||||||
if (light?.LightSprite != null && item.Prefab.CanSpriteFlipX)
|
if (light?.LightSprite != null && item.Prefab.CanSpriteFlipX && item.body == null)
|
||||||
{
|
{
|
||||||
light.LightSpriteEffect = light.LightSpriteEffect == SpriteEffects.None ?
|
light.LightSpriteEffect = light.LightSpriteEffect == SpriteEffects.None ?
|
||||||
SpriteEffects.FlipHorizontally : SpriteEffects.None;
|
SpriteEffects.FlipHorizontally : SpriteEffects.None;
|
||||||
@@ -39,5 +52,11 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
IsOn = msg.ReadBoolean();
|
IsOn = msg.ReadBoolean();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void RemoveComponentSpecific()
|
||||||
|
{
|
||||||
|
base.RemoveComponentSpecific();
|
||||||
|
light.Remove();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,6 +77,26 @@ namespace Barotrauma.Items.Components
|
|||||||
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
||||||
{
|
{
|
||||||
state = msg.ReadBoolean();
|
state = msg.ReadBoolean();
|
||||||
|
ushort userID = msg.ReadUInt16();
|
||||||
|
if (userID == 0)
|
||||||
|
{
|
||||||
|
if (user != null)
|
||||||
|
{
|
||||||
|
IsActive = false;
|
||||||
|
CancelUsing(user);
|
||||||
|
user = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Character newUser = Entity.FindEntityByID(userID) as Character;
|
||||||
|
if (newUser != user)
|
||||||
|
{
|
||||||
|
CancelUsing(user);
|
||||||
|
}
|
||||||
|
user = newUser;
|
||||||
|
IsActive = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,18 +23,23 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
Enabled = false
|
Enabled = false
|
||||||
};
|
};
|
||||||
|
powerIndicator.TextColor = powerIndicator.DefaultTextColor.Value;
|
||||||
|
|
||||||
highVoltageIndicator = new GUITickBox(new RectTransform(indicatorSize, paddedFrame.RectTransform) { AbsoluteOffset = new Point(0, (int)(40 * GUI.yScale)) },
|
highVoltageIndicator = new GUITickBox(new RectTransform(indicatorSize, paddedFrame.RectTransform) { AbsoluteOffset = new Point(0, (int)(40 * GUI.yScale)) },
|
||||||
TextManager.Get("PowerTransferHighVoltage"), style: "IndicatorLightRed")
|
TextManager.Get("PowerTransferHighVoltage"), style: "IndicatorLightRed")
|
||||||
{
|
{
|
||||||
ToolTip = TextManager.Get("PowerTransferTipOvervoltage"),
|
ToolTip = TextManager.Get("PowerTransferTipOvervoltage"),
|
||||||
Enabled = false
|
Enabled = false
|
||||||
};
|
};
|
||||||
|
highVoltageIndicator.TextColor = highVoltageIndicator.DefaultTextColor.Value;
|
||||||
|
|
||||||
lowVoltageIndicator = new GUITickBox(new RectTransform(indicatorSize, paddedFrame.RectTransform) { AbsoluteOffset = new Point(0, (int)(80 * GUI.yScale)) },
|
lowVoltageIndicator = new GUITickBox(new RectTransform(indicatorSize, paddedFrame.RectTransform) { AbsoluteOffset = new Point(0, (int)(80 * GUI.yScale)) },
|
||||||
TextManager.Get("PowerTransferLowVoltage"), style: "IndicatorLightRed")
|
TextManager.Get("PowerTransferLowVoltage"), style: "IndicatorLightRed")
|
||||||
{
|
{
|
||||||
ToolTip = TextManager.Get("PowerTransferTipLowvoltage"),
|
ToolTip = TextManager.Get("PowerTransferTipLowvoltage"),
|
||||||
Enabled = false
|
Enabled = false
|
||||||
};
|
};
|
||||||
|
lowVoltageIndicator.TextColor = lowVoltageIndicator.DefaultTextColor.Value;
|
||||||
|
|
||||||
var textContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.5f, 1.0f), paddedFrame.RectTransform, Anchor.TopRight));
|
var textContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.5f, 1.0f), paddedFrame.RectTransform, Anchor.TopRight));
|
||||||
|
|
||||||
|
|||||||
@@ -142,7 +142,7 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
if (repairSoundChannel == null || !repairSoundChannel.IsPlaying)
|
if (repairSoundChannel == null || !repairSoundChannel.IsPlaying)
|
||||||
{
|
{
|
||||||
repairSoundChannel = SoundPlayer.PlaySound("repair", item.WorldPosition, hullGuess: item.CurrentHull);
|
repairSoundChannel = SoundPlayer.PlaySound("repair", item.WorldPosition, hullGuess: item.CurrentHull);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -221,8 +221,17 @@ namespace Barotrauma.Items.Components
|
|||||||
deteriorationTimer = msg.ReadSingle();
|
deteriorationTimer = msg.ReadSingle();
|
||||||
deteriorateAlwaysResetTimer = msg.ReadSingle();
|
deteriorateAlwaysResetTimer = msg.ReadSingle();
|
||||||
DeteriorateAlways = msg.ReadBoolean();
|
DeteriorateAlways = msg.ReadBoolean();
|
||||||
CurrentFixer = msg.ReadBoolean() ? Character.Controlled : null;
|
ushort currentFixerID = msg.ReadUInt16();
|
||||||
currentFixerAction = (FixActions)msg.ReadRangedInteger(0, 2);
|
currentFixerAction = (FixActions)msg.ReadRangedInteger(0, 2);
|
||||||
|
|
||||||
|
if (currentFixerID == 0)
|
||||||
|
{
|
||||||
|
CurrentFixer = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CurrentFixer = Entity.FindEntityByID(currentFixerID) as Character;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientWrite(IWriteMessage msg, object[] extraData = null)
|
public void ClientWrite(IWriteMessage msg, object[] extraData = null)
|
||||||
|
|||||||
@@ -119,6 +119,7 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
DrawWire(spriteBatch, draggingConnected, PlayerInput.MousePosition, new Vector2(x + width / 2, y + height - 10), null, panel, "");
|
DrawWire(spriteBatch, draggingConnected, PlayerInput.MousePosition, new Vector2(x + width / 2, y + height - 10), null, panel, "");
|
||||||
}
|
}
|
||||||
|
panel.TriggerRewiringSound();
|
||||||
|
|
||||||
if (!PlayerInput.LeftButtonHeld())
|
if (!PlayerInput.LeftButtonHeld())
|
||||||
{
|
{
|
||||||
@@ -129,7 +130,11 @@ namespace Barotrauma.Items.Components
|
|||||||
panel.DisconnectedWires.Add(draggingConnected);
|
panel.DisconnectedWires.Add(draggingConnected);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GameMain.Client != null) { panel.Item.CreateClientEvent(panel); }
|
if (GameMain.Client != null)
|
||||||
|
{
|
||||||
|
panel.Item.CreateClientEvent(panel);
|
||||||
|
}
|
||||||
|
|
||||||
draggingConnected = null;
|
draggingConnected = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -205,7 +210,10 @@ namespace Barotrauma.Items.Components
|
|||||||
SetWire(index, draggingConnected);
|
SetWire(index, draggingConnected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (GameMain.Client != null) { panel.Item.CreateClientEvent(panel); }
|
if (GameMain.Client != null)
|
||||||
|
{
|
||||||
|
panel.Item.CreateClientEvent(panel);
|
||||||
|
}
|
||||||
draggingConnected = null;
|
draggingConnected = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,19 +11,28 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
partial class ConnectionPanel : ItemComponent, IServerSerializable, IClientSerializable
|
partial class ConnectionPanel : ItemComponent, IServerSerializable, IClientSerializable
|
||||||
{
|
{
|
||||||
|
//how long the rewiring sound plays after doing changes to the wiring
|
||||||
|
const float RewireSoundDuration = 5.0f;
|
||||||
|
|
||||||
public static Wire HighlightedWire;
|
public static Wire HighlightedWire;
|
||||||
|
|
||||||
private SoundChannel rewireSoundChannel;
|
private SoundChannel rewireSoundChannel;
|
||||||
|
private float rewireSoundTimer;
|
||||||
|
|
||||||
partial void InitProjSpecific(XElement element)
|
partial void InitProjSpecific(XElement element)
|
||||||
{
|
{
|
||||||
if (GuiFrame == null) return;
|
if (GuiFrame == null) { return; }
|
||||||
new GUICustomComponent(new RectTransform(Vector2.One, GuiFrame.RectTransform), DrawConnections, null)
|
new GUICustomComponent(new RectTransform(Vector2.One, GuiFrame.RectTransform), DrawConnections, null)
|
||||||
{
|
{
|
||||||
UserData = this
|
UserData = this
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void TriggerRewiringSound()
|
||||||
|
{
|
||||||
|
rewireSoundTimer = RewireSoundDuration;
|
||||||
|
}
|
||||||
|
|
||||||
partial void UpdateProjSpecific(float deltaTime)
|
partial void UpdateProjSpecific(float deltaTime)
|
||||||
{
|
{
|
||||||
foreach (Wire wire in DisconnectedWires)
|
foreach (Wire wire in DisconnectedWires)
|
||||||
@@ -40,7 +49,9 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (user != null && user.SelectedConstruction == item && HasRequiredItems(user, addMessage: false))
|
|
||||||
|
rewireSoundTimer -= deltaTime;
|
||||||
|
if (user != null && user.SelectedConstruction == item && rewireSoundTimer > 0.0f)
|
||||||
{
|
{
|
||||||
if (rewireSoundChannel == null || !rewireSoundChannel.IsPlaying)
|
if (rewireSoundChannel == null || !rewireSoundChannel.IsPlaying)
|
||||||
{
|
{
|
||||||
@@ -51,12 +62,13 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
rewireSoundChannel?.FadeOutAndDispose();
|
rewireSoundChannel?.FadeOutAndDispose();
|
||||||
rewireSoundChannel = null;
|
rewireSoundChannel = null;
|
||||||
|
rewireSoundTimer = 0.0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Move(Vector2 amount)
|
public override void Move(Vector2 amount)
|
||||||
{
|
{
|
||||||
if (item.Submarine == null || item.Submarine.Loading || Screen.Selected != GameMain.SubEditorScreen) return;
|
if (item.Submarine == null || item.Submarine.Loading || Screen.Selected != GameMain.SubEditorScreen) { return; }
|
||||||
MoveConnectedWires(amount);
|
MoveConnectedWires(amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,6 +115,7 @@ namespace Barotrauma.Items.Components
|
|||||||
//delay reading the state until midround syncing is done
|
//delay reading the state until midround syncing is done
|
||||||
//because some of the wires connected to the panel may not exist yet
|
//because some of the wires connected to the panel may not exist yet
|
||||||
long msgStartPos = msg.BitPosition;
|
long msgStartPos = msg.BitPosition;
|
||||||
|
msg.ReadUInt16(); //user ID
|
||||||
foreach (Connection connection in Connections)
|
foreach (Connection connection in Connections)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < Connection.MaxLinked; i++)
|
for (int i = 0; i < Connection.MaxLinked; i++)
|
||||||
@@ -121,6 +134,8 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
//don't trigger rewiring sounds if the rewiring is being done by the local user (in that case we'll trigger it locally)
|
||||||
|
if (Character.Controlled == null || user != Character.Controlled) { TriggerRewiringSound(); }
|
||||||
ApplyRemoteState(msg);
|
ApplyRemoteState(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -130,6 +145,17 @@ namespace Barotrauma.Items.Components
|
|||||||
List<Wire> prevWires = Connections.SelectMany(c => c.Wires.Where(w => w != null)).ToList();
|
List<Wire> prevWires = Connections.SelectMany(c => c.Wires.Where(w => w != null)).ToList();
|
||||||
List<Wire> newWires = new List<Wire>();
|
List<Wire> newWires = new List<Wire>();
|
||||||
|
|
||||||
|
ushort userID = msg.ReadUInt16();
|
||||||
|
|
||||||
|
if (userID == 0)
|
||||||
|
{
|
||||||
|
user = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
user = Entity.FindEntityByID(userID) as Character;
|
||||||
|
}
|
||||||
|
|
||||||
foreach (Connection connection in Connections)
|
foreach (Connection connection in Connections)
|
||||||
{
|
{
|
||||||
connection.ClearConnections();
|
connection.ClearConnections();
|
||||||
|
|||||||
@@ -145,6 +145,21 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
|
|
||||||
Dock(DockingTarget);
|
Dock(DockingTarget);
|
||||||
|
if (joint == null)
|
||||||
|
{
|
||||||
|
string errorMsg = "Error while reading a docking port network event (Dock method did not create a joint between the ports)." +
|
||||||
|
" Submarine: " + (item.Submarine?.Name ?? "null") +
|
||||||
|
", target submarine: " + (DockingTarget.item.Submarine?.Name ?? "null");
|
||||||
|
if (item.Submarine?.DockedTo.Contains(DockingTarget.item.Submarine) ?? false)
|
||||||
|
{
|
||||||
|
errorMsg += "\nAlready docked.";
|
||||||
|
}
|
||||||
|
if (item.Submarine == DockingTarget.item.Submarine)
|
||||||
|
{
|
||||||
|
errorMsg += "\nTrying to dock the submarine to itself.";
|
||||||
|
}
|
||||||
|
GameAnalyticsManager.AddErrorEventOnce("DockingPort.ClientRead:JointNotCreated", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||||
|
}
|
||||||
|
|
||||||
if (isLocked)
|
if (isLocked)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -916,21 +916,30 @@ namespace Barotrauma
|
|||||||
case NetEntityEvent.Type.ApplyStatusEffect:
|
case NetEntityEvent.Type.ApplyStatusEffect:
|
||||||
{
|
{
|
||||||
ActionType actionType = (ActionType)msg.ReadRangedInteger(0, Enum.GetValues(typeof(ActionType)).Length - 1);
|
ActionType actionType = (ActionType)msg.ReadRangedInteger(0, Enum.GetValues(typeof(ActionType)).Length - 1);
|
||||||
byte componentIndex = msg.ReadByte();
|
byte componentIndex = msg.ReadByte();
|
||||||
ushort targetID = msg.ReadUInt16();
|
ushort targetCharacterID = msg.ReadUInt16();
|
||||||
byte targetLimbID = msg.ReadByte();
|
byte targetLimbID = msg.ReadByte();
|
||||||
|
ushort useTargetID = msg.ReadUInt16();
|
||||||
|
Vector2? worldPosition = null;
|
||||||
|
bool hasPosition = msg.ReadBoolean();
|
||||||
|
if (hasPosition)
|
||||||
|
{
|
||||||
|
worldPosition = new Vector2(msg.ReadSingle(), msg.ReadSingle());
|
||||||
|
}
|
||||||
|
|
||||||
ItemComponent targetComponent = componentIndex < components.Count ? components[componentIndex] : null;
|
ItemComponent targetComponent = componentIndex < components.Count ? components[componentIndex] : null;
|
||||||
Character target = FindEntityByID(targetID) as Character;
|
Character targetCharacter = FindEntityByID(targetCharacterID) as Character;
|
||||||
Limb targetLimb = target != null && targetLimbID < target.AnimController.Limbs.Length ? target.AnimController.Limbs[targetLimbID] : null;
|
Limb targetLimb = targetCharacter != null && targetLimbID < targetCharacter.AnimController.Limbs.Length ?
|
||||||
|
targetCharacter.AnimController.Limbs[targetLimbID] : null;
|
||||||
|
Entity useTarget = FindEntityByID(useTargetID);
|
||||||
|
|
||||||
if (targetComponent == null)
|
if (targetComponent == null)
|
||||||
{
|
{
|
||||||
ApplyStatusEffects(actionType, 1.0f, target, targetLimb, true);
|
ApplyStatusEffects(actionType, 1.0f, targetCharacter, targetLimb, useTarget, true, worldPosition: worldPosition);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
targetComponent.ApplyStatusEffects(actionType, 1.0f, target, targetLimb);
|
targetComponent.ApplyStatusEffects(actionType, 1.0f, targetCharacter, targetLimb, useTarget, worldPosition: worldPosition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -228,12 +228,12 @@ namespace Barotrauma.Lights
|
|||||||
activeLights.Clear();
|
activeLights.Clear();
|
||||||
foreach (LightSource light in lights)
|
foreach (LightSource light in lights)
|
||||||
{
|
{
|
||||||
if (light.Color.A < 1 || light.Range < 1.0f || !light.Enabled) continue;
|
if (!light.Enabled) { continue; }
|
||||||
if (!MathUtils.CircleIntersectsRectangle(light.WorldPosition, light.Range, viewRect)) continue;
|
if ((light.Color.A < 1 || light.Range < 1.0f) && !light.LightSourceParams.OverrideLightSpriteAlpha.HasValue) { continue; }
|
||||||
|
if (!MathUtils.CircleIntersectsRectangle(light.WorldPosition, light.LightSourceParams.TextureRange, viewRect)) { continue; }
|
||||||
activeLights.Add(light);
|
activeLights.Add(light);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//clear the lightmap
|
//clear the lightmap
|
||||||
graphics.Clear(Color.Black);
|
graphics.Clear(Color.Black);
|
||||||
graphics.BlendState = BlendState.Additive;
|
graphics.BlendState = BlendState.Additive;
|
||||||
@@ -244,9 +244,9 @@ namespace Barotrauma.Lights
|
|||||||
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Additive, transformMatrix: spriteBatchTransform);
|
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Additive, transformMatrix: spriteBatchTransform);
|
||||||
foreach (LightSource light in activeLights)
|
foreach (LightSource light in activeLights)
|
||||||
{
|
{
|
||||||
if (!light.IsBackground) continue;
|
if (!light.IsBackground) { continue; }
|
||||||
light.DrawSprite(spriteBatch, cam);
|
light.DrawSprite(spriteBatch, cam);
|
||||||
light.DrawLightVolume(spriteBatch, lightEffect, transform);
|
if (light.Color.A > 0 && light.Range > 0.0f) { light.DrawLightVolume(spriteBatch, lightEffect, transform); }
|
||||||
backgroundSpritesDrawn = true;
|
backgroundSpritesDrawn = true;
|
||||||
}
|
}
|
||||||
GameMain.ParticleManager.Draw(spriteBatch, true, null, Particles.ParticleBlendState.Additive);
|
GameMain.ParticleManager.Draw(spriteBatch, true, null, Particles.ParticleBlendState.Additive);
|
||||||
@@ -288,7 +288,7 @@ namespace Barotrauma.Lights
|
|||||||
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Additive, transformMatrix: spriteBatchTransform);
|
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Additive, transformMatrix: spriteBatchTransform);
|
||||||
foreach (LightSource light in activeLights)
|
foreach (LightSource light in activeLights)
|
||||||
{
|
{
|
||||||
if (light.IsBackground) continue;
|
if (light.IsBackground) { continue; }
|
||||||
light.DrawSprite(spriteBatch, cam);
|
light.DrawSprite(spriteBatch, cam);
|
||||||
}
|
}
|
||||||
spriteBatch.End();
|
spriteBatch.End();
|
||||||
@@ -303,6 +303,8 @@ namespace Barotrauma.Lights
|
|||||||
//draw characters to obstruct the highlighted items/characters and light sprites
|
//draw characters to obstruct the highlighted items/characters and light sprites
|
||||||
//---------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
SolidColorEffect.CurrentTechnique = SolidColorEffect.Techniques["SolidColor"];
|
||||||
|
SolidColorEffect.Parameters["color"].SetValue(Color.Black.ToVector4());
|
||||||
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, effect: SolidColorEffect, transformMatrix: spriteBatchTransform);
|
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, effect: SolidColorEffect, transformMatrix: spriteBatchTransform);
|
||||||
foreach (Character character in Character.CharacterList)
|
foreach (Character character in Character.CharacterList)
|
||||||
{
|
{
|
||||||
@@ -347,8 +349,8 @@ namespace Barotrauma.Lights
|
|||||||
|
|
||||||
foreach (LightSource light in activeLights)
|
foreach (LightSource light in activeLights)
|
||||||
{
|
{
|
||||||
if (light.IsBackground) continue;
|
if (light.IsBackground) { continue; }
|
||||||
light.DrawLightVolume(spriteBatch, lightEffect, transform);
|
if (light.Color.A > 0 && light.Range > 0.0f) { light.DrawLightVolume(spriteBatch, lightEffect, transform); }
|
||||||
}
|
}
|
||||||
Vector3 offset = Vector3.Zero;// new Vector3(Submarine.MainSub.DrawPosition.X, Submarine.MainSub.DrawPosition.Y, 0.0f);
|
Vector3 offset = Vector3.Zero;// new Vector3(Submarine.MainSub.DrawPosition.X, Submarine.MainSub.DrawPosition.Y, 0.0f);
|
||||||
lightEffect.World = Matrix.CreateTranslation(Vector3.Zero) * transform;
|
lightEffect.World = Matrix.CreateTranslation(Vector3.Zero) * transform;
|
||||||
|
|||||||
@@ -31,11 +31,23 @@ namespace Barotrauma.Lights
|
|||||||
get { return range; }
|
get { return range; }
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
|
|
||||||
range = MathHelper.Clamp(value, 0.0f, 2048.0f);
|
range = MathHelper.Clamp(value, 0.0f, 2048.0f);
|
||||||
|
TextureRange = range;
|
||||||
|
if (OverrideLightTexture != null)
|
||||||
|
{
|
||||||
|
TextureRange += Math.Max(
|
||||||
|
Math.Abs(OverrideLightTexture.RelativeOrigin.X - 0.5f) * OverrideLightTexture.size.X,
|
||||||
|
Math.Abs(OverrideLightTexture.RelativeOrigin.Y - 0.5f) * OverrideLightTexture.size.Y);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public float TextureRange
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
private set;
|
||||||
|
}
|
||||||
|
|
||||||
public Sprite OverrideLightTexture
|
public Sprite OverrideLightTexture
|
||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
@@ -89,6 +101,8 @@ namespace Barotrauma.Lights
|
|||||||
break;
|
break;
|
||||||
case "lighttexture":
|
case "lighttexture":
|
||||||
OverrideLightTexture = new Sprite(subElement, preMultiplyAlpha: false);
|
OverrideLightTexture = new Sprite(subElement, preMultiplyAlpha: false);
|
||||||
|
//refresh TextureRange
|
||||||
|
Range = range;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -115,8 +129,16 @@ namespace Barotrauma.Lights
|
|||||||
|
|
||||||
class LightSource
|
class LightSource
|
||||||
{
|
{
|
||||||
|
//how many pixels the position of the light needs to change for the light volume to be recalculated
|
||||||
|
const float MovementRecalculationThreshold = 10.0f;
|
||||||
|
//how many radians the light needs to rotate for the light volume to be recalculated
|
||||||
|
const float RotationRecalculationThreshold = 0.02f;
|
||||||
|
|
||||||
private static Texture2D lightTexture;
|
private static Texture2D lightTexture;
|
||||||
|
|
||||||
|
private VertexPositionColorTexture[] vertices;
|
||||||
|
private short[] indices;
|
||||||
|
|
||||||
private List<ConvexHullList> hullsInRange;
|
private List<ConvexHullList> hullsInRange;
|
||||||
|
|
||||||
public Texture2D texture;
|
public Texture2D texture;
|
||||||
@@ -167,6 +189,9 @@ namespace Barotrauma.Lights
|
|||||||
private int vertexCount;
|
private int vertexCount;
|
||||||
private int indexCount;
|
private int indexCount;
|
||||||
|
|
||||||
|
private Vector2 translateVertices;
|
||||||
|
private float rotateVertices;
|
||||||
|
|
||||||
private readonly LightSourceParams lightSourceParams;
|
private readonly LightSourceParams lightSourceParams;
|
||||||
|
|
||||||
public LightSourceParams LightSourceParams => lightSourceParams;
|
public LightSourceParams LightSourceParams => lightSourceParams;
|
||||||
@@ -177,26 +202,38 @@ namespace Barotrauma.Lights
|
|||||||
get { return position; }
|
get { return position; }
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (Math.Abs(position.X - value.X) < 0.1f && Math.Abs(position.Y - value.Y) < 0.1f) return;
|
Vector2 moveAmount = value - position;
|
||||||
|
if (Math.Abs(moveAmount.X) < 0.1f && Math.Abs(moveAmount.Y) < 0.1f) { return; }
|
||||||
position = value;
|
position = value;
|
||||||
|
|
||||||
if (Vector2.DistanceSquared(prevCalculatedPosition, position) < 5.0f * 5.0f) return;
|
//translate light volume manually instead of doing a full recalculation when moving by a small amount
|
||||||
|
if (Vector2.DistanceSquared(prevCalculatedPosition, position) < MovementRecalculationThreshold * MovementRecalculationThreshold && vertices != null)
|
||||||
|
{
|
||||||
|
translateVertices = position - prevCalculatedPosition;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
NeedsHullCheck = true;
|
NeedsHullCheck = true;
|
||||||
NeedsRecalculation = true;
|
NeedsRecalculation = true;
|
||||||
prevCalculatedPosition = position;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private float prevCalculatedRotation;
|
||||||
private float rotation;
|
private float rotation;
|
||||||
public float Rotation
|
public float Rotation
|
||||||
{
|
{
|
||||||
get { return rotation; }
|
get { return rotation; }
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (Math.Abs(rotation - value) < 0.01f) return;
|
if (Math.Abs(value - rotation) < 0.001f) { return; }
|
||||||
rotation = value;
|
rotation = value;
|
||||||
|
|
||||||
|
if (Math.Abs(rotation - prevCalculatedRotation) < RotationRecalculationThreshold && vertices != null)
|
||||||
|
{
|
||||||
|
rotateVertices = rotation - prevCalculatedRotation;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
NeedsHullCheck = true;
|
NeedsHullCheck = true;
|
||||||
NeedsRecalculation = true;
|
NeedsRecalculation = true;
|
||||||
}
|
}
|
||||||
@@ -711,12 +748,21 @@ namespace Barotrauma.Lights
|
|||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void CalculateLightVertices(List<Vector2> rayCastHits)
|
private void CalculateLightVertices(List<Vector2> rayCastHits)
|
||||||
{
|
{
|
||||||
List<VertexPositionColorTexture> vertices = new List<VertexPositionColorTexture>();
|
vertexCount = rayCastHits.Count * 2 + 1;
|
||||||
|
indexCount = (rayCastHits.Count) * 9;
|
||||||
|
|
||||||
|
//recreate arrays if they're too small or excessively large
|
||||||
|
if (vertices == null || vertices.Length < vertexCount || vertices.Length > vertexCount * 3)
|
||||||
|
{
|
||||||
|
vertices = new VertexPositionColorTexture[vertexCount];
|
||||||
|
indices = new short[indexCount];
|
||||||
|
}
|
||||||
|
|
||||||
Vector2 drawPos = position;
|
Vector2 drawPos = position;
|
||||||
if (ParentSub != null) drawPos += ParentSub.DrawPosition;
|
if (ParentSub != null) { drawPos += ParentSub.DrawPosition; }
|
||||||
|
|
||||||
float cosAngle = (float)Math.Cos(Rotation);
|
float cosAngle = (float)Math.Cos(Rotation);
|
||||||
float sinAngle = -(float)Math.Sin(Rotation);
|
float sinAngle = -(float)Math.Sin(Rotation);
|
||||||
@@ -728,14 +774,14 @@ namespace Barotrauma.Lights
|
|||||||
overrideTextureDims = new Vector2(OverrideLightTexture.SourceRect.Width, OverrideLightTexture.SourceRect.Height);
|
overrideTextureDims = new Vector2(OverrideLightTexture.SourceRect.Width, OverrideLightTexture.SourceRect.Height);
|
||||||
|
|
||||||
Vector2 origin = OverrideLightTexture.Origin;
|
Vector2 origin = OverrideLightTexture.Origin;
|
||||||
if (LightSpriteEffect == SpriteEffects.FlipHorizontally) origin.X = OverrideLightTexture.SourceRect.Width - origin.X;
|
if (LightSpriteEffect == SpriteEffects.FlipHorizontally) { origin.X = OverrideLightTexture.SourceRect.Width - origin.X; }
|
||||||
if (LightSpriteEffect == SpriteEffects.FlipVertically) origin.Y = (OverrideLightTexture.SourceRect.Height - origin.Y);
|
if (LightSpriteEffect == SpriteEffects.FlipVertically) { origin.Y = OverrideLightTexture.SourceRect.Height - origin.Y; }
|
||||||
uvOffset = (origin / overrideTextureDims) - new Vector2(0.5f, 0.5f);
|
uvOffset = (origin / overrideTextureDims) - new Vector2(0.5f, 0.5f);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a vertex for the center of the mesh
|
// Add a vertex for the center of the mesh
|
||||||
vertices.Add(new VertexPositionColorTexture(new Vector3(position.X, position.Y, 0),
|
vertices[0] = new VertexPositionColorTexture(new Vector3(position.X, position.Y, 0),
|
||||||
Color.White, new Vector2(0.5f, 0.5f) + uvOffset));
|
Color.White, GetUV(new Vector2(0.5f, 0.5f) + uvOffset, LightSpriteEffect));
|
||||||
|
|
||||||
//hacky fix to exc excessively large light volumes (they used to be up to 4x the range of the light if there was nothing to block the rays).
|
//hacky fix to exc excessively large light volumes (they used to be up to 4x the range of the light if there was nothing to block the rays).
|
||||||
//might want to tweak the raycast logic in a way that this isn't necessary
|
//might want to tweak the raycast logic in a way that this isn't necessary
|
||||||
@@ -800,68 +846,88 @@ namespace Barotrauma.Lights
|
|||||||
|
|
||||||
//finally, create the vertices
|
//finally, create the vertices
|
||||||
VertexPositionColorTexture fullVert = new VertexPositionColorTexture(new Vector3(position.X + rawDiff.X, position.Y + rawDiff.Y, 0),
|
VertexPositionColorTexture fullVert = new VertexPositionColorTexture(new Vector3(position.X + rawDiff.X, position.Y + rawDiff.Y, 0),
|
||||||
Color.White, new Vector2(0.5f, 0.5f) + diff);
|
Color.White, GetUV(new Vector2(0.5f, 0.5f) + diff, LightSpriteEffect));
|
||||||
VertexPositionColorTexture fadeVert = new VertexPositionColorTexture(new Vector3(position.X + rawDiff.X + nDiff.X, position.Y + rawDiff.Y + nDiff.Y, 0),
|
VertexPositionColorTexture fadeVert = new VertexPositionColorTexture(new Vector3(position.X + rawDiff.X + nDiff.X, position.Y + rawDiff.Y + nDiff.Y, 0),
|
||||||
Color.White * 0.0f, new Vector2(0.5f, 0.5f) + diff);
|
Color.White * 0.0f, GetUV(new Vector2(0.5f, 0.5f) + diff, LightSpriteEffect));
|
||||||
|
|
||||||
vertices.Add(fullVert);
|
vertices[1 + i * 2] = fullVert;
|
||||||
vertices.Add(fadeVert);
|
vertices[1 + i * 2 + 1] = fadeVert;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute the indices to form triangles
|
// Compute the indices to form triangles
|
||||||
List<short> indices = new List<short>();
|
for (int i = 0; i < rayCastHits.Count - 1; i++)
|
||||||
for (int i = 0; i < rayCastHits.Count-1; i++)
|
|
||||||
{
|
{
|
||||||
//main light body
|
//main light body
|
||||||
indices.Add(0);
|
indices[i * 9] = 0;
|
||||||
indices.Add((short)((i*2 + 3) % vertices.Count));
|
indices[i * 9 + 1] = (short)((i * 2 + 3) % vertexCount);
|
||||||
indices.Add((short)((i*2 + 1) % vertices.Count));
|
indices[i * 9 + 2] = (short)((i * 2 + 1) % vertexCount);
|
||||||
|
|
||||||
//faded light
|
//faded light
|
||||||
indices.Add((short)((i*2 + 1) % vertices.Count));
|
indices[i * 9 + 3] = (short)((i * 2 + 1) % vertexCount);
|
||||||
indices.Add((short)((i*2 + 3) % vertices.Count));
|
indices[i * 9 + 4] = (short)((i * 2 + 3) % vertexCount);
|
||||||
indices.Add((short)((i*2 + 4) % vertices.Count));
|
indices[i * 9 + 5] = (short)((i * 2 + 4) % vertexCount);
|
||||||
|
|
||||||
indices.Add((short)((i*2 + 2) % vertices.Count));
|
indices[i * 9 + 6] = (short)((i * 2 + 2) % vertexCount);
|
||||||
indices.Add((short)((i*2 + 1) % vertices.Count));
|
indices[i * 9 + 7] = (short)((i * 2 + 1) % vertexCount);
|
||||||
indices.Add((short)((i*2 + 4) % vertices.Count));
|
indices[i * 9 + 8] = (short)((i * 2 + 4) % vertexCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
//main light body
|
//main light body
|
||||||
indices.Add(0);
|
indices[(rayCastHits.Count - 1) * 9] = 0;
|
||||||
indices.Add((short)(1));
|
indices[(rayCastHits.Count - 1) * 9 + 1] = (short)(1);
|
||||||
indices.Add((short)(vertices.Count - 2));
|
indices[(rayCastHits.Count - 1) * 9 + 2] = (short)(vertexCount - 2);
|
||||||
|
|
||||||
//faded light
|
//faded light
|
||||||
indices.Add((short)(1));
|
indices[(rayCastHits.Count - 1) * 9 + 3] = (short)(1);
|
||||||
indices.Add((short)(vertices.Count-1));
|
indices[(rayCastHits.Count - 1) * 9 + 4] = (short)(vertexCount - 1);
|
||||||
indices.Add((short)(vertices.Count-2));
|
indices[(rayCastHits.Count - 1) * 9 + 5] = (short)(vertexCount - 2);
|
||||||
|
|
||||||
indices.Add((short)(1));
|
indices[(rayCastHits.Count - 1) * 9 + 6] = (short)(1);
|
||||||
indices.Add((short)(2));
|
indices[(rayCastHits.Count - 1) * 9 + 7] = (short)(2);
|
||||||
indices.Add((short)(vertices.Count-1));
|
indices[(rayCastHits.Count - 1) * 9 + 8] = (short)(vertexCount - 1);
|
||||||
|
|
||||||
vertexCount = vertices.Count;
|
|
||||||
indexCount = indices.Count;
|
|
||||||
|
|
||||||
//TODO: a better way to determine the size of the vertex buffer and handle changes in size?
|
//TODO: a better way to determine the size of the vertex buffer and handle changes in size?
|
||||||
//now we just create a buffer for 64 verts and make it larger if needed
|
//now we just create a buffer for 64 verts and make it larger if needed
|
||||||
if (lightVolumeBuffer == null)
|
if (lightVolumeBuffer == null)
|
||||||
{
|
{
|
||||||
lightVolumeBuffer = new DynamicVertexBuffer(GameMain.Instance.GraphicsDevice, VertexPositionColorTexture.VertexDeclaration, Math.Max(64, (int)(vertexCount*1.5)), BufferUsage.None);
|
lightVolumeBuffer = new DynamicVertexBuffer(GameMain.Instance.GraphicsDevice, VertexPositionColorTexture.VertexDeclaration, Math.Max(64, (int)(vertexCount * 1.5)), BufferUsage.None);
|
||||||
lightVolumeIndexBuffer = new DynamicIndexBuffer(GameMain.Instance.GraphicsDevice, typeof(short), Math.Max(64*3, (int)(indexCount * 1.5)), BufferUsage.None);
|
lightVolumeIndexBuffer = new DynamicIndexBuffer(GameMain.Instance.GraphicsDevice, typeof(short), Math.Max(64 * 3, (int)(indexCount * 1.5)), BufferUsage.None);
|
||||||
}
|
}
|
||||||
else if (vertexCount > lightVolumeBuffer.VertexCount || indexCount > lightVolumeIndexBuffer.IndexCount)
|
else if (vertexCount > lightVolumeBuffer.VertexCount || indexCount > lightVolumeIndexBuffer.IndexCount)
|
||||||
{
|
{
|
||||||
lightVolumeBuffer.Dispose();
|
lightVolumeBuffer.Dispose();
|
||||||
lightVolumeIndexBuffer.Dispose();
|
lightVolumeIndexBuffer.Dispose();
|
||||||
|
|
||||||
lightVolumeBuffer = new DynamicVertexBuffer(GameMain.Instance.GraphicsDevice, VertexPositionColorTexture.VertexDeclaration, (int)(vertexCount*1.5), BufferUsage.None);
|
lightVolumeBuffer = new DynamicVertexBuffer(GameMain.Instance.GraphicsDevice, VertexPositionColorTexture.VertexDeclaration, (int)(vertexCount * 1.5), BufferUsage.None);
|
||||||
lightVolumeIndexBuffer = new DynamicIndexBuffer(GameMain.Instance.GraphicsDevice, typeof(short), (int)(indexCount * 1.5), BufferUsage.None);
|
lightVolumeIndexBuffer = new DynamicIndexBuffer(GameMain.Instance.GraphicsDevice, typeof(short), (int)(indexCount * 1.5), BufferUsage.None);
|
||||||
}
|
}
|
||||||
|
|
||||||
lightVolumeBuffer.SetData<VertexPositionColorTexture>(vertices.ToArray());
|
lightVolumeBuffer.SetData<VertexPositionColorTexture>(vertices, 0, vertexCount);
|
||||||
lightVolumeIndexBuffer.SetData<short>(indices.ToArray());
|
lightVolumeIndexBuffer.SetData<short>(indices, 0, indexCount);
|
||||||
|
|
||||||
|
Vector2 GetUV(Vector2 vert, SpriteEffects effects)
|
||||||
|
{
|
||||||
|
if (effects == SpriteEffects.FlipHorizontally)
|
||||||
|
{
|
||||||
|
vert.X = 1.0f - vert.X;
|
||||||
|
}
|
||||||
|
else if (effects == SpriteEffects.FlipVertically)
|
||||||
|
{
|
||||||
|
vert.Y = 1.0f - vert.Y;
|
||||||
|
}
|
||||||
|
else if (effects == (SpriteEffects.FlipHorizontally | SpriteEffects.FlipVertically))
|
||||||
|
{
|
||||||
|
vert.X = 1.0f - vert.X;
|
||||||
|
vert.Y = 1.0f - vert.Y;
|
||||||
|
}
|
||||||
|
vert.Y = 1.0f - vert.Y;
|
||||||
|
return vert;
|
||||||
|
}
|
||||||
|
|
||||||
|
translateVertices = Vector2.Zero;
|
||||||
|
rotateVertices = 0.0f;
|
||||||
|
prevCalculatedPosition = position;
|
||||||
|
prevCalculatedRotation = rotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -950,9 +1016,6 @@ namespace Barotrauma.Lights
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3 offset = ParentSub == null ?
|
|
||||||
Vector3.Zero : new Vector3(ParentSub.DrawPosition.X, ParentSub.DrawPosition.Y, 0.0f);
|
|
||||||
lightEffect.World = Matrix.CreateTranslation(offset) * transform;
|
|
||||||
|
|
||||||
if (NeedsRecalculation)
|
if (NeedsRecalculation)
|
||||||
{
|
{
|
||||||
@@ -963,7 +1026,15 @@ namespace Barotrauma.Lights
|
|||||||
NeedsRecalculation = false;
|
NeedsRecalculation = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vertexCount == 0) return;
|
|
||||||
|
Vector2 offset = ParentSub == null ? Vector2.Zero : ParentSub.DrawPosition;
|
||||||
|
lightEffect.World =
|
||||||
|
Matrix.CreateTranslation(-new Vector3(position, 0.0f)) *
|
||||||
|
Matrix.CreateRotationZ(rotateVertices) *
|
||||||
|
Matrix.CreateTranslation(new Vector3(position + offset + translateVertices, 0.0f)) *
|
||||||
|
transform;
|
||||||
|
|
||||||
|
if (vertexCount == 0) { return; }
|
||||||
|
|
||||||
lightEffect.DiffuseColor = (new Vector3(Color.R, Color.G, Color.B) * (Color.A / 255.0f)) / 255.0f;
|
lightEffect.DiffuseColor = (new Vector3(Color.R, Color.G, Color.B) * (Color.A / 255.0f)) / 255.0f;
|
||||||
if (OverrideLightTexture != null)
|
if (OverrideLightTexture != null)
|
||||||
|
|||||||
@@ -483,6 +483,8 @@ namespace Barotrauma.Networking
|
|||||||
if (DateTime.Now > timeOut)
|
if (DateTime.Now > timeOut)
|
||||||
{
|
{
|
||||||
clientPeer?.Close(Lidgren.Network.NetConnection.NoResponseMessage);
|
clientPeer?.Close(Lidgren.Network.NetConnection.NoResponseMessage);
|
||||||
|
var msgBox = new GUIMessageBox(TextManager.Get("ConnectionFailed"), TextManager.Get("CouldNotConnectToServer"));
|
||||||
|
msgBox.Buttons[0].OnClicked += ReturnToPreviousMenu;
|
||||||
reconnectBox?.Close(); reconnectBox = null;
|
reconnectBox?.Close(); reconnectBox = null;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1232,7 +1234,9 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
if (Level.Loaded.EqualityCheckVal != levelEqualityCheckVal)
|
if (Level.Loaded.EqualityCheckVal != levelEqualityCheckVal)
|
||||||
{
|
{
|
||||||
string errorMsg = "Level equality check failed. The level generated at your end doesn't match the level generated by the server (seed " + Level.Loaded.Seed + ").";
|
string errorMsg = "Level equality check failed. The level generated at your end doesn't match the level generated by the server (seed: " + Level.Loaded.Seed +
|
||||||
|
", sub: " + Submarine.MainSub.Name + " (" + Submarine.MainSub.MD5Hash.ShortHash + ")" +
|
||||||
|
", mirrored: " + Level.Loaded.Mirrored + ").";
|
||||||
DebugConsole.ThrowError(errorMsg, createMessageBox: true);
|
DebugConsole.ThrowError(errorMsg, createMessageBox: true);
|
||||||
GameAnalyticsManager.AddErrorEventOnce("GameClient.StartGame:LevelsDontMatch" + levelSeed, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
GameAnalyticsManager.AddErrorEventOnce("GameClient.StartGame:LevelsDontMatch" + levelSeed, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||||
CoroutineManager.StartCoroutine(EndGame(""));
|
CoroutineManager.StartCoroutine(EndGame(""));
|
||||||
@@ -1274,6 +1278,7 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
gameStarted = false;
|
gameStarted = false;
|
||||||
Character.Controlled = null;
|
Character.Controlled = null;
|
||||||
|
SpawnAsTraitor = false;
|
||||||
GameMain.GameScreen.Cam.TargetPos = Vector2.Zero;
|
GameMain.GameScreen.Cam.TargetPos = Vector2.Zero;
|
||||||
GameMain.LightManager.LosEnabled = false;
|
GameMain.LightManager.LosEnabled = false;
|
||||||
respawnManager = null;
|
respawnManager = null;
|
||||||
@@ -1432,6 +1437,8 @@ namespace Barotrauma.Networking
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool initialUpdateReceived;
|
||||||
|
|
||||||
private void ReadLobbyUpdate(IReadMessage inc)
|
private void ReadLobbyUpdate(IReadMessage inc)
|
||||||
{
|
{
|
||||||
ServerNetObject objHeader;
|
ServerNetObject objHeader;
|
||||||
@@ -1452,13 +1459,15 @@ namespace Barotrauma.Networking
|
|||||||
UInt16 settingsLen = inc.ReadUInt16();
|
UInt16 settingsLen = inc.ReadUInt16();
|
||||||
byte[] settingsData = inc.ReadBytes(settingsLen);
|
byte[] settingsData = inc.ReadBytes(settingsLen);
|
||||||
|
|
||||||
if (inc.ReadBoolean())
|
bool isInitialUpdate = inc.ReadBoolean();
|
||||||
|
if (isInitialUpdate)
|
||||||
{
|
{
|
||||||
if (GameSettings.VerboseLogging)
|
if (GameSettings.VerboseLogging)
|
||||||
{
|
{
|
||||||
DebugConsole.NewMessage("Received initial lobby update, ID: " + updateID + ", last ID: " + GameMain.NetLobbyScreen.LastUpdateID, Color.Gray);
|
DebugConsole.NewMessage("Received initial lobby update, ID: " + updateID + ", last ID: " + GameMain.NetLobbyScreen.LastUpdateID, Color.Gray);
|
||||||
}
|
}
|
||||||
ReadInitialUpdate(inc);
|
ReadInitialUpdate(inc);
|
||||||
|
initialUpdateReceived = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
string selectSubName = inc.ReadString();
|
string selectSubName = inc.ReadString();
|
||||||
@@ -1489,7 +1498,9 @@ namespace Barotrauma.Networking
|
|||||||
float autoRestartTimer = autoRestartEnabled ? inc.ReadSingle() : 0.0f;
|
float autoRestartTimer = autoRestartEnabled ? inc.ReadSingle() : 0.0f;
|
||||||
|
|
||||||
//ignore the message if we already a more up-to-date one
|
//ignore the message if we already a more up-to-date one
|
||||||
if (NetIdUtils.IdMoreRecent(updateID, GameMain.NetLobbyScreen.LastUpdateID))
|
//or if we're still waiting for the initial update
|
||||||
|
if (NetIdUtils.IdMoreRecent(updateID, GameMain.NetLobbyScreen.LastUpdateID) &&
|
||||||
|
(isInitialUpdate || initialUpdateReceived))
|
||||||
{
|
{
|
||||||
ReadWriteMessage settingsBuf = new ReadWriteMessage();
|
ReadWriteMessage settingsBuf = new ReadWriteMessage();
|
||||||
settingsBuf.Write(settingsData, 0, settingsLen); settingsBuf.BitPosition = 0;
|
settingsBuf.Write(settingsData, 0, settingsLen); settingsBuf.BitPosition = 0;
|
||||||
@@ -2248,12 +2259,10 @@ namespace Barotrauma.Networking
|
|||||||
{
|
{
|
||||||
if (gameStarted)
|
if (gameStarted)
|
||||||
{
|
{
|
||||||
tickBox.Visible = false;
|
tickBox.Parent.Visible = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vote(VoteType.StartRound, tickBox.Selected);
|
Vote(VoteType.StartRound, tickBox.Selected);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -200,6 +200,7 @@ namespace Barotrauma.Networking
|
|||||||
}
|
}
|
||||||
|
|
||||||
msg.BitPosition += msgLength * 8;
|
msg.BitPosition += msgLength * 8;
|
||||||
|
msg.ReadPadBits();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -213,6 +214,20 @@ namespace Barotrauma.Networking
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
ReadEvent(msg, entity, sendingTime);
|
ReadEvent(msg, entity, sendingTime);
|
||||||
|
msg.ReadPadBits();
|
||||||
|
|
||||||
|
if (msg.BitPosition != msgPosition + msgLength * 8)
|
||||||
|
{
|
||||||
|
string errorMsg = "Message byte position incorrect after reading an event for the entity \"" + entity.ToString()
|
||||||
|
+ "\". Read " + (msg.BitPosition - msgPosition) + " bits, expected message length was " + (msgLength * 8) + " bits.";
|
||||||
|
#if DEBUG
|
||||||
|
DebugConsole.ThrowError(errorMsg);
|
||||||
|
#endif
|
||||||
|
GameAnalyticsManager.AddErrorEventOnce("ClientEntityEventManager.Read:BitPosMismatch", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||||
|
|
||||||
|
//TODO: force the BitPosition to correct place? Having some entity in a potentially incorrect state is not as bad as a desync kick
|
||||||
|
//msg.BitPosition = (int)(msgPosition + msgLength * 8);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
@@ -231,9 +246,9 @@ namespace Barotrauma.Networking
|
|||||||
GameAnalyticsManager.AddErrorEventOnce("ClientEntityEventManager.Read:ReadFailed" + entity.ToString(),
|
GameAnalyticsManager.AddErrorEventOnce("ClientEntityEventManager.Read:ReadFailed" + entity.ToString(),
|
||||||
GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||||
msg.BitPosition = (int)(msgPosition + msgLength * 8);
|
msg.BitPosition = (int)(msgPosition + msgLength * 8);
|
||||||
|
msg.ReadPadBits();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
msg.ReadPadBits();
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -275,6 +275,7 @@ namespace Barotrauma.Networking
|
|||||||
#if DEBUG
|
#if DEBUG
|
||||||
CoroutineManager.InvokeAfter(() =>
|
CoroutineManager.InvokeAfter(() =>
|
||||||
{
|
{
|
||||||
|
if (GameMain.Client == null) { return; }
|
||||||
if (Rand.Range(0.0f, 1.0f) < GameMain.Client.SimulatedLoss && sendType != Facepunch.Steamworks.Networking.SendType.Reliable) { return; }
|
if (Rand.Range(0.0f, 1.0f) < GameMain.Client.SimulatedLoss && sendType != Facepunch.Steamworks.Networking.SendType.Reliable) { return; }
|
||||||
int count = Rand.Range(0.0f, 1.0f) < GameMain.Client.SimulatedDuplicatesChance ? 2 : 1;
|
int count = Rand.Range(0.0f, 1.0f) < GameMain.Client.SimulatedDuplicatesChance ? 2 : 1;
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
|
|||||||
@@ -18,7 +18,17 @@ namespace Barotrauma.Networking
|
|||||||
public UInt64 OwnerID;
|
public UInt64 OwnerID;
|
||||||
public bool OwnerVerified;
|
public bool OwnerVerified;
|
||||||
|
|
||||||
public string ServerName;
|
private string serverName;
|
||||||
|
public string ServerName
|
||||||
|
{
|
||||||
|
get { return serverName; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
serverName = value;
|
||||||
|
if (serverName.Length > NetConfig.ServerNameMaxLength) { ServerName = ServerName.Substring(0, NetConfig.ServerNameMaxLength); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public string ServerMessage;
|
public string ServerMessage;
|
||||||
public bool GameStarted;
|
public bool GameStarted;
|
||||||
public int PlayerCount;
|
public int PlayerCount;
|
||||||
@@ -455,38 +465,7 @@ namespace Barotrauma.Networking
|
|||||||
if (SteamFriend.IsPlayingThisGame && SteamFriend.ServerLobbyId != 0)
|
if (SteamFriend.IsPlayingThisGame && SteamFriend.ServerLobbyId != 0)
|
||||||
{
|
{
|
||||||
LobbyID = SteamFriend.ServerLobbyId;
|
LobbyID = SteamFriend.ServerLobbyId;
|
||||||
SteamManager.Instance.LobbyList.SetManualLobbyDataCallback(LobbyID, (lobby) =>
|
|
||||||
{
|
|
||||||
SteamManager.Instance.LobbyList.SetManualLobbyDataCallback(LobbyID, null);
|
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(lobby.GetData("haspassword"))) { return; }
|
|
||||||
bool.TryParse(lobby.GetData("haspassword"), out bool hasPassword);
|
|
||||||
int.TryParse(lobby.GetData("playercount"), out int currPlayers);
|
|
||||||
int.TryParse(lobby.GetData("maxplayernum"), out int maxPlayers);
|
|
||||||
//UInt64.TryParse(lobby.GetData("connectsteamid"), out ulong connectSteamId);
|
|
||||||
string ip = lobby.GetData("hostipaddress");
|
|
||||||
UInt64 ownerId = SteamManager.SteamIDStringToUInt64(lobby.GetData("lobbyowner"));
|
|
||||||
|
|
||||||
if (OwnerID != ownerId) { return; }
|
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(ip)) { ip = ""; }
|
|
||||||
|
|
||||||
ServerName = lobby.Name;
|
|
||||||
Port = "";
|
|
||||||
QueryPort = "";
|
|
||||||
IP = ip;
|
|
||||||
PlayerCount = currPlayers;
|
|
||||||
MaxPlayers = maxPlayers;
|
|
||||||
HasPassword = hasPassword;
|
|
||||||
RespondedToSteamQuery = true;
|
|
||||||
LobbyID = lobby.LobbyID;
|
|
||||||
OwnerID = ownerId;
|
|
||||||
PingChecked = false;
|
|
||||||
OwnerVerified = true;
|
|
||||||
SteamManager.AssignLobbyDataToServerInfo(lobby, this);
|
|
||||||
|
|
||||||
onServerRulesReceived?.Invoke(this);
|
|
||||||
});
|
|
||||||
SteamManager.Instance.LobbyList.RequestLobbyData(LobbyID);
|
SteamManager.Instance.LobbyList.RequestLobbyData(LobbyID);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -326,8 +326,8 @@ namespace Barotrauma.Steam
|
|||||||
localQuery.OnFinished = onFinished;
|
localQuery.OnFinished = onFinished;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
instance.client.LobbyList.OnLobbiesUpdated = () => { UpdateLobbyQuery(onServerFound, onServerRulesReceived, onFinished); };
|
|
||||||
instance.client.LobbyList.Refresh();
|
instance.client.LobbyList.Request();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -382,42 +382,6 @@ namespace Barotrauma.Steam
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void UpdateLobbyQuery(Action<Networking.ServerInfo> onServerFound, Action<Networking.ServerInfo> onServerRulesReceived, Action onFinished)
|
|
||||||
{
|
|
||||||
foreach (LobbyList.Lobby lobby in instance.client.LobbyList.Lobbies)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrWhiteSpace(lobby.GetData("haspassword"))) { continue; }
|
|
||||||
bool.TryParse(lobby.GetData("haspassword"), out bool hasPassword);
|
|
||||||
int.TryParse(lobby.GetData("playercount"), out int currPlayers);
|
|
||||||
int.TryParse(lobby.GetData("maxplayernum"), out int maxPlayers);
|
|
||||||
UInt64 ownerId = SteamIDStringToUInt64(lobby.GetData("lobbyowner"));
|
|
||||||
//UInt64.TryParse(lobby.GetData("connectsteamid"), out ulong connectSteamId);
|
|
||||||
string ip = lobby.GetData("hostipaddress");
|
|
||||||
if (string.IsNullOrWhiteSpace(ip)) { ip = ""; }
|
|
||||||
|
|
||||||
var serverInfo = new ServerInfo()
|
|
||||||
{
|
|
||||||
ServerName = lobby.Name,
|
|
||||||
Port = "",
|
|
||||||
QueryPort = "",
|
|
||||||
IP = ip,
|
|
||||||
PlayerCount = currPlayers,
|
|
||||||
MaxPlayers = maxPlayers,
|
|
||||||
HasPassword = hasPassword,
|
|
||||||
RespondedToSteamQuery = true,
|
|
||||||
LobbyID = lobby.LobbyID,
|
|
||||||
OwnerID = ownerId
|
|
||||||
};
|
|
||||||
serverInfo.PingChecked = false;
|
|
||||||
AssignLobbyDataToServerInfo(lobby, serverInfo);
|
|
||||||
|
|
||||||
onServerFound(serverInfo);
|
|
||||||
//onServerRulesReceived(serverInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
onFinished();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void AssignLobbyDataToServerInfo(LobbyList.Lobby lobby, ServerInfo serverInfo)
|
public static void AssignLobbyDataToServerInfo(LobbyList.Lobby lobby, ServerInfo serverInfo)
|
||||||
{
|
{
|
||||||
serverInfo.ServerMessage = lobby.GetData("message");
|
serverInfo.ServerMessage = lobby.GetData("message");
|
||||||
@@ -495,6 +459,7 @@ namespace Barotrauma.Steam
|
|||||||
serverInfo.PingChecked = true;
|
serverInfo.PingChecked = true;
|
||||||
serverInfo.Ping = s.Ping;
|
serverInfo.Ping = s.Ping;
|
||||||
serverInfo.LobbyID = 0;
|
serverInfo.LobbyID = 0;
|
||||||
|
serverInfo.OwnerVerified = true;
|
||||||
if (responded)
|
if (responded)
|
||||||
{
|
{
|
||||||
s.FetchRules();
|
s.FetchRules();
|
||||||
|
|||||||
@@ -249,7 +249,9 @@ namespace Barotrauma
|
|||||||
if (newCategory != selectedItemCategory)
|
if (newCategory != selectedItemCategory)
|
||||||
{
|
{
|
||||||
searchBox.Text = "";
|
searchBox.Text = "";
|
||||||
|
storeItemList.ScrollBar.BarScroll = 0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
FilterStoreItems((MapEntityCategory)userdata, searchBox.Text);
|
FilterStoreItems((MapEntityCategory)userdata, searchBox.Text);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -947,7 +949,9 @@ namespace Barotrauma
|
|||||||
var itemFrame = myItemList.Content.GetChildByUserData(pi);
|
var itemFrame = myItemList.Content.GetChildByUserData(pi);
|
||||||
if (itemFrame == null)
|
if (itemFrame == null)
|
||||||
{
|
{
|
||||||
itemFrame = CreateItemFrame(pi, pi.ItemPrefab.GetPrice(Campaign.Map.CurrentLocation), myItemList);
|
var priceInfo = pi.ItemPrefab.GetPrice(Campaign.Map.CurrentLocation);
|
||||||
|
if (priceInfo == null) { continue; }
|
||||||
|
itemFrame = CreateItemFrame(pi, priceInfo, myItemList);
|
||||||
}
|
}
|
||||||
itemFrame.GetChild(0).GetChild<GUINumberInput>().IntValue = pi.Quantity;
|
itemFrame.GetChild(0).GetChild<GUINumberInput>().IntValue = pi.Quantity;
|
||||||
existingItemFrames.Add(itemFrame);
|
existingItemFrames.Add(itemFrame);
|
||||||
|
|||||||
@@ -99,6 +99,7 @@ namespace Barotrauma.CharacterEditor
|
|||||||
private Rectangle spriteSheetRect;
|
private Rectangle spriteSheetRect;
|
||||||
|
|
||||||
private Rectangle CalculateSpritesheetRectangle() =>
|
private Rectangle CalculateSpritesheetRectangle() =>
|
||||||
|
Textures == null || Textures.None() ? Rectangle.Empty :
|
||||||
new Rectangle(
|
new Rectangle(
|
||||||
spriteSheetOffsetX,
|
spriteSheetOffsetX,
|
||||||
spriteSheetOffsetY,
|
spriteSheetOffsetY,
|
||||||
@@ -656,12 +657,6 @@ namespace Barotrauma.CharacterEditor
|
|||||||
}
|
}
|
||||||
if (!isFrozen)
|
if (!isFrozen)
|
||||||
{
|
{
|
||||||
if (character.AnimController.Invalid)
|
|
||||||
{
|
|
||||||
Reset(new Character[] { character });
|
|
||||||
SpawnCharacter(currentCharacterConfig);
|
|
||||||
}
|
|
||||||
|
|
||||||
Submarine.MainSub.SetPrevTransform(Submarine.MainSub.Position);
|
Submarine.MainSub.SetPrevTransform(Submarine.MainSub.Position);
|
||||||
Submarine.MainSub.Update((float)deltaTime);
|
Submarine.MainSub.Update((float)deltaTime);
|
||||||
|
|
||||||
@@ -722,6 +717,7 @@ namespace Barotrauma.CharacterEditor
|
|||||||
foreach (Limb limb in character.AnimController.Limbs)
|
foreach (Limb limb in character.AnimController.Limbs)
|
||||||
{
|
{
|
||||||
if (limb == null || limb.ActiveSprite == null) { continue; }
|
if (limb == null || limb.ActiveSprite == null) { continue; }
|
||||||
|
if (selectedJoints.Any(j => j.LimbA == limb || j.LimbB == limb)) { continue; }
|
||||||
// Select limbs on ragdoll
|
// Select limbs on ragdoll
|
||||||
if (editLimbs && !spriteSheetRect.Contains(PlayerInput.MousePosition) && MathUtils.RectangleContainsPoint(GetLimbPhysicRect(limb), PlayerInput.MousePosition))
|
if (editLimbs && !spriteSheetRect.Contains(PlayerInput.MousePosition) && MathUtils.RectangleContainsPoint(GetLimbPhysicRect(limb), PlayerInput.MousePosition))
|
||||||
{
|
{
|
||||||
@@ -2727,11 +2723,19 @@ namespace Barotrauma.CharacterEditor
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
character.Params.Save();
|
if (!string.IsNullOrEmpty(RagdollParams.Texture) && !File.Exists(RagdollParams.Texture))
|
||||||
GUI.AddMessage(GetCharacterEditorTranslation("CharacterSavedTo").Replace("[path]", CharacterParams.FullPath), Color.Green, font: GUI.Font, lifeTime: 5);
|
{
|
||||||
character.AnimController.SaveRagdoll();
|
DebugConsole.ThrowError($"Invalid texture path: {RagdollParams.Texture}");
|
||||||
GUI.AddMessage(GetCharacterEditorTranslation("RagdollSavedTo").Replace("[path]", RagdollParams.FullPath), Color.Green, font: GUI.Font, lifeTime: 5);
|
return false;
|
||||||
AnimParams.ForEach(p => p.Save());
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
character.Params.Save();
|
||||||
|
GUI.AddMessage(GetCharacterEditorTranslation("CharacterSavedTo").Replace("[path]", CharacterParams.FullPath), Color.Green, font: GUI.Font, lifeTime: 5);
|
||||||
|
character.AnimController.SaveRagdoll();
|
||||||
|
GUI.AddMessage(GetCharacterEditorTranslation("RagdollSavedTo").Replace("[path]", RagdollParams.FullPath), Color.Green, font: GUI.Font, lifeTime: 5);
|
||||||
|
AnimParams.ForEach(p => p.Save());
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
// Spacing
|
// Spacing
|
||||||
|
|||||||
@@ -40,6 +40,10 @@ namespace Barotrauma.CharacterEditor
|
|||||||
canEnterSubmarine = ragdoll.CanEnterSubmarine;
|
canEnterSubmarine = ragdoll.CanEnterSubmarine;
|
||||||
canWalk = ragdoll.CanWalk;
|
canWalk = ragdoll.CanWalk;
|
||||||
texturePath = ragdoll.Texture;
|
texturePath = ragdoll.Texture;
|
||||||
|
if (string.IsNullOrEmpty(texturePath) && !name.Equals(Character.HumanSpeciesName, StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
texturePath = ragdoll.Limbs.FirstOrDefault()?.GetSprite().Texture;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Wizard instance;
|
public static Wizard instance;
|
||||||
@@ -265,8 +269,30 @@ namespace Barotrauma.CharacterEditor
|
|||||||
};
|
};
|
||||||
if (ofd.ShowDialog() == DialogResult.OK)
|
if (ofd.ShowDialog() == DialogResult.OK)
|
||||||
{
|
{
|
||||||
|
string file = ofd.FileName;
|
||||||
|
string relativePath = UpdaterUtil.GetRelativePath(Path.GetFullPath(file), Environment.CurrentDirectory);
|
||||||
|
string destinationPath = relativePath;
|
||||||
|
|
||||||
|
//copy file to XML path if it's not located relative to the game's files
|
||||||
|
if (relativePath.StartsWith("..") ||
|
||||||
|
Path.GetPathRoot(Environment.CurrentDirectory) != Path.GetPathRoot(file))
|
||||||
|
{
|
||||||
|
destinationPath = Path.Combine(Path.GetDirectoryName(XMLPath), Path.GetFileName(file));
|
||||||
|
|
||||||
|
string destinationDir = Path.GetDirectoryName(destinationPath);
|
||||||
|
if (!Directory.Exists(destinationDir))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(destinationDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!File.Exists(destinationPath))
|
||||||
|
{
|
||||||
|
File.Copy(file, Path.GetFullPath(destinationPath), overwrite: true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
isTextureSelected = true;
|
isTextureSelected = true;
|
||||||
texturePathElement.Text = ToolBox.ConvertAbsoluteToRelativePath(ofd.FileName);
|
texturePathElement.Text = destinationPath;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ using Microsoft.Xna.Framework;
|
|||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
using RestSharp;
|
using RestSharp;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -84,7 +85,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
FetchRemoteContent(Frame.RectTransform);
|
FetchRemoteContent();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@@ -753,12 +754,20 @@ namespace Barotrauma
|
|||||||
exeName = "DedicatedServer.exe";
|
exeName = "DedicatedServer.exe";
|
||||||
}
|
}
|
||||||
|
|
||||||
string arguments = "-name \"" + name.Replace("\\", "\\\\").Replace("\"", "\\\"") + "\"" +
|
string arguments = "-name \"" + ToolBox.EscapeCharacters(name) + "\"" +
|
||||||
" -public " + isPublicBox.Selected.ToString() +
|
" -public " + isPublicBox.Selected.ToString() +
|
||||||
" -playstyle " + ((PlayStyle)playstyleBanner.UserData).ToString() +
|
" -playstyle " + ((PlayStyle)playstyleBanner.UserData).ToString() +
|
||||||
" -password \"" + passwordBox.Text.Replace("\\", "\\\\").Replace("\"", "\\\"") + "\"" +
|
|
||||||
" -maxplayers " + maxPlayersBox.Text;
|
" -maxplayers " + maxPlayersBox.Text;
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(passwordBox.Text))
|
||||||
|
{
|
||||||
|
arguments += " -password \"" + ToolBox.EscapeCharacters(passwordBox.Text) + "\"";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
arguments += " -nopassword";
|
||||||
|
}
|
||||||
|
|
||||||
int ownerKey = 0;
|
int ownerKey = 0;
|
||||||
|
|
||||||
if (Steam.SteamManager.GetSteamID()!=0)
|
if (Steam.SteamManager.GetSteamID()!=0)
|
||||||
@@ -774,6 +783,7 @@ namespace Barotrauma
|
|||||||
string filename = exeName;
|
string filename = exeName;
|
||||||
#if LINUX || OSX
|
#if LINUX || OSX
|
||||||
filename = "./" + Path.GetFileNameWithoutExtension(exeName);
|
filename = "./" + Path.GetFileNameWithoutExtension(exeName);
|
||||||
|
arguments = ToolBox.EscapeCharacters(arguments);
|
||||||
#endif
|
#endif
|
||||||
var processInfo = new ProcessStartInfo
|
var processInfo = new ProcessStartInfo
|
||||||
{
|
{
|
||||||
@@ -1149,34 +1159,15 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
private void FetchRemoteContent(RectTransform parent)
|
private void FetchRemoteContent()
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(GameMain.Config.RemoteContentUrl)) { return; }
|
if (string.IsNullOrEmpty(GameMain.Config.RemoteContentUrl)) { return; }
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var client = new RestClient(GameMain.Config.RemoteContentUrl);
|
var client = new RestClient(GameMain.Config.RemoteContentUrl);
|
||||||
var request = new RestRequest("MenuContent.xml", Method.GET);
|
var request = new RestRequest("MenuContent.xml", Method.GET);
|
||||||
|
client.ExecuteAsync(request, RemoteContentReceived);
|
||||||
IRestResponse response = client.Execute(request);
|
CoroutineManager.StartCoroutine(WairForRemoteContentReceived());
|
||||||
if (response.ResponseStatus != ResponseStatus.Completed)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (response.StatusCode != HttpStatusCode.OK)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
string xml = response.Content;
|
|
||||||
int index = xml.IndexOf('<');
|
|
||||||
if (index > 0) { xml = xml.Substring(index, xml.Length - index); }
|
|
||||||
if (string.IsNullOrWhiteSpace(xml)) { return; }
|
|
||||||
|
|
||||||
XElement element = XDocument.Parse(xml)?.Root;
|
|
||||||
foreach (XElement subElement in element.Elements())
|
|
||||||
{
|
|
||||||
GUIComponent.FromXML(subElement, parent);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
@@ -1189,5 +1180,60 @@ namespace Barotrauma
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private IEnumerable<object> WairForRemoteContentReceived()
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
lock (remoteContentLock)
|
||||||
|
{
|
||||||
|
if (remoteContentResponse != null) { break; }
|
||||||
|
}
|
||||||
|
yield return new WaitForSeconds(0.1f);
|
||||||
|
}
|
||||||
|
lock (remoteContentLock)
|
||||||
|
{
|
||||||
|
if (remoteContentResponse.ResponseStatus != ResponseStatus.Completed || remoteContentResponse.StatusCode != HttpStatusCode.OK)
|
||||||
|
{
|
||||||
|
yield return CoroutineStatus.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string xml = remoteContentResponse.Content;
|
||||||
|
int index = xml.IndexOf('<');
|
||||||
|
if (index > 0) { xml = xml.Substring(index, xml.Length - index); }
|
||||||
|
if (!string.IsNullOrWhiteSpace(xml))
|
||||||
|
{
|
||||||
|
XElement element = XDocument.Parse(xml)?.Root;
|
||||||
|
foreach (XElement subElement in element.Elements())
|
||||||
|
{
|
||||||
|
GUIComponent.FromXML(subElement, Frame.RectTransform);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
DebugConsole.ThrowError("Reading received remote main menu content failed.", e);
|
||||||
|
#endif
|
||||||
|
GameAnalyticsManager.AddErrorEventOnce("MainMenuScreen.WairForRemoteContentReceived:Exception", GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||||
|
"Reading received remote main menu content failed. " + e.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
yield return CoroutineStatus.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly object remoteContentLock = new object();
|
||||||
|
private IRestResponse remoteContentResponse;
|
||||||
|
|
||||||
|
private void RemoteContentReceived(IRestResponse response, RestRequestAsyncHandle handle)
|
||||||
|
{
|
||||||
|
lock (remoteContentLock)
|
||||||
|
{
|
||||||
|
remoteContentResponse = response;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -319,6 +319,14 @@ namespace Barotrauma
|
|||||||
RelativeSpacing = panelSpacing
|
RelativeSpacing = panelSpacing
|
||||||
};
|
};
|
||||||
|
|
||||||
|
GameMain.Instance.OnResolutionChanged += () =>
|
||||||
|
{
|
||||||
|
if (innerFrame != null)
|
||||||
|
{
|
||||||
|
innerFrame.RectTransform.MaxSize = new Point(int.MaxValue, GameMain.GraphicsHeight - 50);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
var panelContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f), innerFrame.RectTransform, Anchor.Center), isHorizontal: true)
|
var panelContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f), innerFrame.RectTransform, Anchor.Center), isHorizontal: true)
|
||||||
{
|
{
|
||||||
Stretch = true,
|
Stretch = true,
|
||||||
@@ -440,6 +448,14 @@ namespace Barotrauma
|
|||||||
Stretch = true
|
Stretch = true
|
||||||
};
|
};
|
||||||
|
|
||||||
|
GameMain.Instance.OnResolutionChanged += () =>
|
||||||
|
{
|
||||||
|
if (panelContainer != null && sideBar != null)
|
||||||
|
{
|
||||||
|
sideBar.RectTransform.MaxSize = new Point(650, panelContainer.RectTransform.Rect.Height);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
//player info panel ------------------------------------------------------------
|
//player info panel ------------------------------------------------------------
|
||||||
|
|
||||||
myCharacterFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.5f), sideBar.RectTransform));
|
myCharacterFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.5f), sideBar.RectTransform));
|
||||||
@@ -1781,24 +1797,23 @@ namespace Barotrauma
|
|||||||
RelativeSpacing = 0.03f
|
RelativeSpacing = 0.03f
|
||||||
};
|
};
|
||||||
|
|
||||||
var headerContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.1f), paddedPlayerFrame.RectTransform), isHorizontal: true)
|
var headerContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.1f), paddedPlayerFrame.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft)
|
||||||
{
|
{
|
||||||
Stretch = true
|
Stretch = true
|
||||||
};
|
};
|
||||||
|
|
||||||
var nameText = new GUITextBlock(new RectTransform(new Vector2(0.75f, 1.0f), headerContainer.RectTransform),
|
var nameText = new GUITextBlock(new RectTransform(new Vector2(0.6f, 1.0f), headerContainer.RectTransform),
|
||||||
text: selectedClient.Name, font: GUI.LargeFont);
|
text: selectedClient.Name, font: GUI.LargeFont);
|
||||||
|
nameText.Text = ToolBox.LimitString(nameText.Text, nameText.Font, nameText.Rect.Width);
|
||||||
|
|
||||||
if (selectedClient.SteamID != 0 && Steam.SteamManager.IsInitialized)
|
if (selectedClient.SteamID != 0 && Steam.SteamManager.IsInitialized)
|
||||||
{
|
{
|
||||||
var viewSteamProfileButton = new GUIButton(new RectTransform(new Vector2(0.25f, 1.0f), headerContainer.RectTransform, Anchor.TopCenter),
|
var viewSteamProfileButton = new GUIButton(new RectTransform(new Vector2(0.4f, 1.0f), headerContainer.RectTransform, Anchor.TopCenter) { MaxSize = new Point(int.MaxValue, (int)(40 * GUI.Scale)) },
|
||||||
TextManager.Get("ViewSteamProfile"))
|
TextManager.Get("ViewSteamProfile"))
|
||||||
{
|
{
|
||||||
UserData = selectedClient
|
UserData = selectedClient
|
||||||
};
|
};
|
||||||
|
viewSteamProfileButton.TextBlock.AutoScale = true;
|
||||||
GUITextBlock.AutoScaleAndNormalize(nameText, viewSteamProfileButton.TextBlock);
|
|
||||||
|
|
||||||
viewSteamProfileButton.OnClicked = (bt, userdata) =>
|
viewSteamProfileButton.OnClicked = (bt, userdata) =>
|
||||||
{
|
{
|
||||||
Steam.SteamManager.Instance.Overlay.OpenUrl("https://steamcommunity.com/profiles/" + selectedClient.SteamID.ToString());
|
Steam.SteamManager.Instance.Overlay.OpenUrl("https://steamcommunity.com/profiles/" + selectedClient.SteamID.ToString());
|
||||||
@@ -2054,7 +2069,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
var closeButton = new GUIButton(new RectTransform(new Vector2(0.3f, 1.0f), buttonAreaLower.RectTransform, Anchor.BottomRight),
|
var closeButton = new GUIButton(new RectTransform(new Vector2(0.3f, 1.0f), buttonAreaLower.RectTransform, Anchor.BottomRight),
|
||||||
TextManager.Get("Close"))
|
TextManager.Get("Close"), style: "GUIButtonLarge")
|
||||||
{
|
{
|
||||||
IgnoreLayoutGroups = true,
|
IgnoreLayoutGroups = true,
|
||||||
OnClicked = ClosePlayerFrame
|
OnClicked = ClosePlayerFrame
|
||||||
@@ -2409,6 +2424,13 @@ namespace Barotrauma
|
|||||||
AbsoluteOffset = new Point(characterInfoFrame.Rect.Right - characterInfoFrame.Rect.Width, button.Rect.Bottom)
|
AbsoluteOffset = new Point(characterInfoFrame.Rect.Right - characterInfoFrame.Rect.Width, button.Rect.Bottom)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
characterInfoFrame.RectTransform.SizeChanged += () =>
|
||||||
|
{
|
||||||
|
if (characterInfoFrame == null || HeadSelectionList?.RectTransform == null || button == null) { return; }
|
||||||
|
HeadSelectionList.RectTransform.Resize(new Point(characterInfoFrame.Rect.Width, (characterInfoFrame.Rect.Bottom - button.Rect.Bottom) + characterInfoFrame.Rect.Height * 2));
|
||||||
|
HeadSelectionList.RectTransform.AbsoluteOffset = new Point(characterInfoFrame.Rect.Right - characterInfoFrame.Rect.Width, button.Rect.Bottom);
|
||||||
|
};
|
||||||
|
|
||||||
new GUIFrame(new RectTransform(new Vector2(1.25f, 1.25f), HeadSelectionList.RectTransform, Anchor.Center), style: "OuterGlow", color: Color.Black)
|
new GUIFrame(new RectTransform(new Vector2(1.25f, 1.25f), HeadSelectionList.RectTransform, Anchor.Center), style: "OuterGlow", color: Color.Black)
|
||||||
{
|
{
|
||||||
UserData = "outerglow",
|
UserData = "outerglow",
|
||||||
@@ -2446,7 +2468,7 @@ namespace Barotrauma
|
|||||||
headSprite.SourceRect = new Rectangle(CharacterInfo.CalculateOffset(headSprite, head.Value.ToPoint()), headSprite.SourceRect.Size);
|
headSprite.SourceRect = new Rectangle(CharacterInfo.CalculateOffset(headSprite, head.Value.ToPoint()), headSprite.SourceRect.Size);
|
||||||
characterSprites.Add(headSprite);
|
characterSprites.Add(headSprite);
|
||||||
|
|
||||||
if (row == null || itemsInRow >= 4)
|
if (itemsInRow >= 4 || row == null || gender != (Gender)row.UserData)
|
||||||
{
|
{
|
||||||
row = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.333f), HeadSelectionList.Content.RectTransform), true)
|
row = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.333f), HeadSelectionList.Content.RectTransform), true)
|
||||||
{
|
{
|
||||||
@@ -2536,6 +2558,14 @@ namespace Barotrauma
|
|||||||
JobSelectionFrame = new GUIFrame(new RectTransform(frameSize, GUI.Canvas, Anchor.TopLeft)
|
JobSelectionFrame = new GUIFrame(new RectTransform(frameSize, GUI.Canvas, Anchor.TopLeft)
|
||||||
{ AbsoluteOffset = new Point(characterInfoFrame.Rect.Right - frameSize.X, characterInfoFrame.Rect.Bottom) }, "GUIFrameListBox");
|
{ AbsoluteOffset = new Point(characterInfoFrame.Rect.Right - frameSize.X, characterInfoFrame.Rect.Bottom) }, "GUIFrameListBox");
|
||||||
|
|
||||||
|
characterInfoFrame.RectTransform.SizeChanged += () =>
|
||||||
|
{
|
||||||
|
if (characterInfoFrame == null || JobSelectionFrame?.RectTransform == null) { return; }
|
||||||
|
Point size = new Point(characterInfoFrame.Rect.Width, characterInfoFrame.Rect.Height * 2);
|
||||||
|
JobSelectionFrame.RectTransform.Resize(size);
|
||||||
|
JobSelectionFrame.RectTransform.AbsoluteOffset = new Point(characterInfoFrame.Rect.Right - size.X, characterInfoFrame.Rect.Bottom);
|
||||||
|
};
|
||||||
|
|
||||||
new GUIFrame(new RectTransform(new Vector2(1.25f, 1.25f), JobSelectionFrame.RectTransform, Anchor.Center), style: "OuterGlow", color: Color.Black)
|
new GUIFrame(new RectTransform(new Vector2(1.25f, 1.25f), JobSelectionFrame.RectTransform, Anchor.Center), style: "OuterGlow", color: Color.Black)
|
||||||
{
|
{
|
||||||
UserData = "outerglow",
|
UserData = "outerglow",
|
||||||
@@ -2600,32 +2630,24 @@ namespace Barotrauma
|
|||||||
image.Visible = currVisible == (variantIndex + 1);
|
image.Visible = currVisible == (variantIndex + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
var variantButton = new GUIButton(new RectTransform(new Vector2(0.15f), jobButton.RectTransform, scaleBasis: ScaleBasis.BothWidth) { RelativeOffset = new Vector2(0.05f, 0.05f + 0.2f * variantIndex) }, (variantIndex + 1).ToString(), style: null)
|
var variantButton = CreateJobVariantButton(jobPrefab, variantIndex, images.Length, jobButton);
|
||||||
|
variantButton.OnClicked = (btn, obj) =>
|
||||||
{
|
{
|
||||||
Color = new Color(50, 50, 50, 200),
|
currSelected.Selected = false;
|
||||||
HoverColor = Color.Gray * 0.75f,
|
int k = ((Pair<JobPrefab, int>)obj).Second;
|
||||||
PressedColor = Color.Black * 0.75f,
|
btn.Parent.UserData = obj;
|
||||||
SelectedColor = new Color(45, 70, 100, 200),
|
for (int j = 0; j < images.Length; j++)
|
||||||
UserData = new Pair<JobPrefab, int>(jobPrefab.First, variantIndex+1),
|
|
||||||
OnClicked = (btn, obj) =>
|
|
||||||
{
|
{
|
||||||
currSelected.Selected = false;
|
foreach (GUIImage image in images[j])
|
||||||
int k = ((Pair<JobPrefab, int>)obj).Second;
|
|
||||||
btn.Parent.UserData = obj;
|
|
||||||
for (int j = 0; j < images.Length; j++)
|
|
||||||
{
|
{
|
||||||
foreach (GUIImage image in images[j])
|
image.Visible = k == (j + 1);
|
||||||
{
|
|
||||||
image.Visible = k == (j + 1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
currSelected = btn;
|
|
||||||
currSelected.Selected = true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
};
|
currSelected = btn;
|
||||||
|
currSelected.Selected = true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
if (currVisible == (variantIndex + 1))
|
if (currVisible == (variantIndex + 1))
|
||||||
{
|
{
|
||||||
currSelected = variantButton;
|
currSelected = variantButton;
|
||||||
@@ -2818,7 +2840,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
subList.Enabled = !enabled && AllowSubSelection;
|
subList.Enabled = !enabled && AllowSubSelection;
|
||||||
shuttleList.Enabled = !enabled && GameMain.Client.HasPermission(ClientPermissions.SelectSub);
|
shuttleList.Enabled = !enabled && GameMain.Client.HasPermission(ClientPermissions.SelectSub);
|
||||||
StartButton.Visible = GameMain.Client.HasPermission(ClientPermissions.ManageRound) && GameMain.Client.GameStarted && !enabled;
|
StartButton.Visible = GameMain.Client.HasPermission(ClientPermissions.ManageRound) && !GameMain.Client.GameStarted && !enabled;
|
||||||
|
|
||||||
if (campaignViewButton != null) { campaignViewButton.Visible = enabled; }
|
if (campaignViewButton != null) { campaignViewButton.Visible = enabled; }
|
||||||
|
|
||||||
@@ -2943,34 +2965,28 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
if (images.Length > 1)
|
if (images.Length > 1)
|
||||||
{
|
{
|
||||||
var variantButton = new GUIButton(new RectTransform(new Vector2(0.15f), slot.RectTransform, scaleBasis: ScaleBasis.BothWidth) { RelativeOffset = new Vector2(0.05f, 0.25f + 0.2f * variantIndex) }, (variantIndex + 1).ToString(), style: null)
|
var variantButton = CreateJobVariantButton(jobPrefab, variantIndex, images.Length, slot);
|
||||||
|
variantButton.OnClicked = (btn, obj) =>
|
||||||
{
|
{
|
||||||
Color = new Color(50, 50, 50, 200),
|
int k = ((Pair<JobPrefab, int>)obj).Second;
|
||||||
HoverColor = Color.Gray * 0.75f,
|
btn.Parent.UserData = obj;
|
||||||
PressedColor = Color.Black * 0.75f,
|
UpdateJobPreferences(listBox);
|
||||||
SelectedColor = new Color(45, 70, 100, 200),
|
return false;
|
||||||
Selected = jobPrefab.Second == (variantIndex + 1),
|
|
||||||
UserData = new Pair<JobPrefab, int>(jobPrefab.First, variantIndex + 1),
|
|
||||||
OnClicked = (btn, obj) =>
|
|
||||||
{
|
|
||||||
int k = ((Pair<JobPrefab, int>)obj).Second;
|
|
||||||
btn.Parent.UserData = obj;
|
|
||||||
UpdateJobPreferences(listBox);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//info button
|
//info button
|
||||||
new GUIButton(new RectTransform(new Vector2(0.15f), slot.RectTransform, Anchor.TopLeft, scaleBasis: ScaleBasis.BothWidth) { RelativeOffset = new Vector2(0.05f) }, style: "GUIButtonInfo")
|
new GUIButton(new RectTransform(new Vector2(0.2f), slot.RectTransform, Anchor.TopLeft, scaleBasis: ScaleBasis.BothHeight)
|
||||||
|
{ RelativeOffset = new Vector2(0.05f) },
|
||||||
|
style: "GUIButtonInfo")
|
||||||
{
|
{
|
||||||
UserData = jobPrefab.First,
|
UserData = jobPrefab.First,
|
||||||
OnClicked = ViewJobInfo
|
OnClicked = ViewJobInfo
|
||||||
};
|
};
|
||||||
|
|
||||||
//remove button
|
//remove button
|
||||||
new GUIButton(new RectTransform(new Vector2(0.15f), slot.RectTransform, Anchor.TopRight, scaleBasis: ScaleBasis.BothWidth) { RelativeOffset = new Vector2(0.05f) }, style: "GUICancelButton")
|
new GUIButton(new RectTransform(new Vector2(0.2f), slot.RectTransform, Anchor.TopRight, scaleBasis: ScaleBasis.BothHeight) { RelativeOffset = new Vector2(0.05f) }, style: "GUICancelButton")
|
||||||
{
|
{
|
||||||
UserData = i,
|
UserData = i,
|
||||||
OnClicked = (btn, obj) =>
|
OnClicked = (btn, obj) =>
|
||||||
@@ -3013,6 +3029,24 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private GUIButton CreateJobVariantButton(Pair<JobPrefab, int> jobPrefab, int variantIndex, int variantCount, GUIComponent slot)
|
||||||
|
{
|
||||||
|
float relativeHeight = Math.Min(0.7f / variantCount, 0.2f);
|
||||||
|
|
||||||
|
var btn = new GUIButton(new RectTransform(new Vector2(relativeHeight), slot.RectTransform, scaleBasis: ScaleBasis.BothHeight)
|
||||||
|
{ RelativeOffset = new Vector2(0.05f, 0.25f + relativeHeight * 1.05f * variantIndex) },
|
||||||
|
(variantIndex + 1).ToString(), style: null)
|
||||||
|
{
|
||||||
|
Color = new Color(50, 50, 50, 200),
|
||||||
|
HoverColor = Color.Gray * 0.75f,
|
||||||
|
PressedColor = Color.Black * 0.75f,
|
||||||
|
SelectedColor = new Color(45, 70, 100, 200),
|
||||||
|
Selected = jobPrefab.Second == (variantIndex + 1),
|
||||||
|
UserData = new Pair<JobPrefab, int>(jobPrefab.First, variantIndex + 1),
|
||||||
|
};
|
||||||
|
return btn;
|
||||||
|
}
|
||||||
|
|
||||||
public Pair<string, string> FailedSelectedSub;
|
public Pair<string, string> FailedSelectedSub;
|
||||||
public Pair<string, string> FailedSelectedShuttle;
|
public Pair<string, string> FailedSelectedShuttle;
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ using System.Net.NetworkInformation;
|
|||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
@@ -426,7 +427,7 @@ namespace Barotrauma
|
|||||||
ToolTip = mode.Name,
|
ToolTip = mode.Name,
|
||||||
Selected = true,
|
Selected = true,
|
||||||
OnSelected = (tickBox) => { FilterServers(); return true; },
|
OnSelected = (tickBox) => { FilterServers(); return true; },
|
||||||
UserData = mode.Name
|
UserData = mode.Identifier
|
||||||
};
|
};
|
||||||
gameModeTickBoxes.Add(selectionTick);
|
gameModeTickBoxes.Add(selectionTick);
|
||||||
filterTextList.Add(selectionTick.TextBlock);
|
filterTextList.Add(selectionTick.TextBlock);
|
||||||
@@ -736,6 +737,7 @@ namespace Barotrauma
|
|||||||
info.PlayerCount = GameMain.Client.ConnectedClients.Count;
|
info.PlayerCount = GameMain.Client.ConnectedClients.Count;
|
||||||
info.PingChecked = false;
|
info.PingChecked = false;
|
||||||
info.HasPassword = serverSettings.HasPassword;
|
info.HasPassword = serverSettings.HasPassword;
|
||||||
|
info.OwnerVerified = true;
|
||||||
|
|
||||||
if (isInfoNew)
|
if (isInfoNew)
|
||||||
{
|
{
|
||||||
@@ -747,6 +749,12 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public void AddToRecentServers(ServerInfo info)
|
public void AddToRecentServers(ServerInfo info)
|
||||||
{
|
{
|
||||||
|
if (!string.IsNullOrEmpty(info.IP))
|
||||||
|
{
|
||||||
|
//don't add localhost to recent servers
|
||||||
|
if (IPAddress.TryParse(info.IP, out IPAddress ip) && IPAddress.IsLoopback(ip)) { return; }
|
||||||
|
}
|
||||||
|
|
||||||
info.Recent = true;
|
info.Recent = true;
|
||||||
ServerInfo existingInfo = recentServers.Find(serverInfo => info.OwnerID == serverInfo.OwnerID && (info.OwnerID != 0 ? true : (info.IP == serverInfo.IP && info.Port == serverInfo.Port)));
|
ServerInfo existingInfo = recentServers.Find(serverInfo => info.OwnerID == serverInfo.OwnerID && (info.OwnerID != 0 ? true : (info.IP == serverInfo.IP && info.Port == serverInfo.Port)));
|
||||||
if (existingInfo == null)
|
if (existingInfo == null)
|
||||||
@@ -898,6 +906,11 @@ namespace Barotrauma
|
|||||||
base.Select();
|
base.Select();
|
||||||
SelectedTab = ServerListTab.All;
|
SelectedTab = ServerListTab.All;
|
||||||
RefreshServers();
|
RefreshServers();
|
||||||
|
|
||||||
|
if (SteamManager.IsInitialized && SteamManager.Instance.LobbyList != null)
|
||||||
|
{
|
||||||
|
SteamManager.Instance.LobbyList.OnLobbyDataReceived = OnLobbyDataReceived;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Deselect()
|
public override void Deselect()
|
||||||
@@ -905,7 +918,7 @@ namespace Barotrauma
|
|||||||
base.Deselect();
|
base.Deselect();
|
||||||
if (SteamManager.IsInitialized && SteamManager.Instance.LobbyList != null)
|
if (SteamManager.IsInitialized && SteamManager.Instance.LobbyList != null)
|
||||||
{
|
{
|
||||||
SteamManager.Instance.LobbyList.OnLobbiesUpdated = null;
|
SteamManager.Instance.LobbyList.OnLobbyDataReceived = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -947,6 +960,7 @@ namespace Barotrauma
|
|||||||
(remoteVersion != null && !NetworkMember.IsCompatible(GameMain.Version, remoteVersion));
|
(remoteVersion != null && !NetworkMember.IsCompatible(GameMain.Version, remoteVersion));
|
||||||
|
|
||||||
child.Visible =
|
child.Visible =
|
||||||
|
serverInfo.OwnerVerified &&
|
||||||
serverInfo.ServerName.ToLowerInvariant().Contains(searchBox.Text.ToLowerInvariant()) &&
|
serverInfo.ServerName.ToLowerInvariant().Contains(searchBox.Text.ToLowerInvariant()) &&
|
||||||
(!filterSameVersion.Selected || (remoteVersion != null && NetworkMember.IsCompatible(remoteVersion, GameMain.Version))) &&
|
(!filterSameVersion.Selected || (remoteVersion != null && NetworkMember.IsCompatible(remoteVersion, GameMain.Version))) &&
|
||||||
(!filterPassword.Selected || !serverInfo.HasPassword) &&
|
(!filterPassword.Selected || !serverInfo.HasPassword) &&
|
||||||
@@ -1406,6 +1420,7 @@ namespace Barotrauma
|
|||||||
yield return new WaitForSeconds((float)(refreshDisableTimer - DateTime.Now).TotalSeconds);
|
yield return new WaitForSeconds((float)(refreshDisableTimer - DateTime.Now).TotalSeconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
recentServers.Concat(favoriteServers).ForEach(si => si.OwnerVerified = false);
|
||||||
if (GameMain.Config.UseSteamMatchmaking)
|
if (GameMain.Config.UseSteamMatchmaking)
|
||||||
{
|
{
|
||||||
serverList.ClearChildren();
|
serverList.ClearChildren();
|
||||||
@@ -1479,7 +1494,8 @@ namespace Barotrauma
|
|||||||
PlayerCount = playerCount,
|
PlayerCount = playerCount,
|
||||||
MaxPlayers = maxPlayers,
|
MaxPlayers = maxPlayers,
|
||||||
HasPassword = hasPassWord,
|
HasPassword = hasPassWord,
|
||||||
GameVersion = gameVersion
|
GameVersion = gameVersion,
|
||||||
|
OwnerVerified = true
|
||||||
};
|
};
|
||||||
foreach (string contentPackageName in contentPackageNames.Split(','))
|
foreach (string contentPackageName in contentPackageNames.Split(','))
|
||||||
{
|
{
|
||||||
@@ -1511,6 +1527,37 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnLobbyDataReceived(Facepunch.Steamworks.LobbyList.Lobby lobby)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(lobby.GetData("haspassword"))) { return; }
|
||||||
|
bool.TryParse(lobby.GetData("haspassword"), out bool hasPassword);
|
||||||
|
int.TryParse(lobby.GetData("playercount"), out int currPlayers);
|
||||||
|
int.TryParse(lobby.GetData("maxplayernum"), out int maxPlayers);
|
||||||
|
//UInt64.TryParse(lobby.GetData("connectsteamid"), out ulong connectSteamId);
|
||||||
|
string ip = lobby.GetData("hostipaddress");
|
||||||
|
UInt64 ownerId = SteamManager.SteamIDStringToUInt64(lobby.GetData("lobbyowner"));
|
||||||
|
|
||||||
|
ServerInfo newInfo = new ServerInfo();
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(ip)) { ip = ""; }
|
||||||
|
|
||||||
|
newInfo.ServerName = lobby.Name;
|
||||||
|
newInfo.Port = "";
|
||||||
|
newInfo.QueryPort = "";
|
||||||
|
newInfo.IP = ip;
|
||||||
|
newInfo.PlayerCount = currPlayers;
|
||||||
|
newInfo.MaxPlayers = maxPlayers;
|
||||||
|
newInfo.HasPassword = hasPassword;
|
||||||
|
newInfo.RespondedToSteamQuery = true;
|
||||||
|
newInfo.LobbyID = lobby.LobbyID;
|
||||||
|
newInfo.OwnerID = ownerId;
|
||||||
|
newInfo.PingChecked = false;
|
||||||
|
newInfo.OwnerVerified = true;
|
||||||
|
SteamManager.AssignLobbyDataToServerInfo(lobby, newInfo);
|
||||||
|
|
||||||
|
AddToServerList(newInfo);
|
||||||
|
}
|
||||||
|
|
||||||
private void AddToServerList(ServerInfo serverInfo)
|
private void AddToServerList(ServerInfo serverInfo)
|
||||||
{
|
{
|
||||||
var serverFrame = serverList.Content.FindChild(d => (d.UserData is ServerInfo info) &&
|
var serverFrame = serverList.Content.FindChild(d => (d.UserData is ServerInfo info) &&
|
||||||
@@ -1552,7 +1599,8 @@ namespace Barotrauma
|
|||||||
if (serverInfo.OwnerVerified)
|
if (serverInfo.OwnerVerified)
|
||||||
{
|
{
|
||||||
DebugConsole.NewMessage(serverInfo.OwnerID + " verified!");
|
DebugConsole.NewMessage(serverInfo.OwnerID + " verified!");
|
||||||
var childrenToRemove = serverList.Content.FindChildren(c => (c.UserData is ServerInfo info) && info != serverInfo && info.OwnerID == serverInfo.OwnerID).ToList();
|
var childrenToRemove = serverList.Content.FindChildren(c => (c.UserData is ServerInfo info) && info != serverInfo &&
|
||||||
|
(serverInfo.OwnerID != 0 ? info.OwnerID == serverInfo.OwnerID : info.IP == serverInfo.IP)).ToList();
|
||||||
foreach (var child in childrenToRemove)
|
foreach (var child in childrenToRemove)
|
||||||
{
|
{
|
||||||
serverList.Content.RemoveChild(child);
|
serverList.Content.RemoveChild(child);
|
||||||
@@ -1594,7 +1642,13 @@ namespace Barotrauma
|
|||||||
UserData = "password"
|
UserData = "password"
|
||||||
};
|
};
|
||||||
|
|
||||||
var serverName = new GUITextBlock(new RectTransform(new Vector2(columnRelativeWidth[2] * 1.1f, 1.0f), serverContent.RectTransform), serverInfo.ServerName, style: "GUIServerListTextBox");
|
var serverName = new GUITextBlock(new RectTransform(new Vector2(columnRelativeWidth[2] * 1.1f, 1.0f), serverContent.RectTransform),
|
||||||
|
#if !DEBUG
|
||||||
|
serverInfo.ServerName,
|
||||||
|
#else
|
||||||
|
((serverInfo.OwnerID != 0 || serverInfo.LobbyID != 0) ? "[STEAMP2P] " : "[LIDGREN] ") + serverInfo.ServerName,
|
||||||
|
#endif
|
||||||
|
style: "GUIServerListTextBox");
|
||||||
|
|
||||||
new GUITickBox(new RectTransform(new Vector2(columnRelativeWidth[3], 0.9f), serverContent.RectTransform, Anchor.Center), label: "")
|
new GUITickBox(new RectTransform(new Vector2(columnRelativeWidth[3], 0.9f), serverContent.RectTransform, Anchor.Center), label: "")
|
||||||
{
|
{
|
||||||
@@ -1793,7 +1847,7 @@ namespace Barotrauma
|
|||||||
GameMain.Config.PlayerName = clientNameBox.Text;
|
GameMain.Config.PlayerName = clientNameBox.Text;
|
||||||
GameMain.Config.SaveNewPlayerConfig();
|
GameMain.Config.SaveNewPlayerConfig();
|
||||||
|
|
||||||
CoroutineManager.StartCoroutine(ConnectToServer(endpoint, serverName));
|
CoroutineManager.StartCoroutine(ConnectToServer(endpoint, serverName), "ConnectToServer");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1822,40 +1876,31 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public void GetServerPing(ServerInfo serverInfo, GUITextBlock serverPingText)
|
public void GetServerPing(ServerInfo serverInfo, GUITextBlock serverPingText)
|
||||||
{
|
{
|
||||||
if (activePings.Contains(serverInfo.IP)) { return; }
|
if (CoroutineManager.IsCoroutineRunning("ConnectToServer")) { return; }
|
||||||
activePings.Add(serverInfo.IP);
|
|
||||||
|
lock (activePings)
|
||||||
|
{
|
||||||
|
if (activePings.Contains(serverInfo.IP)) { return; }
|
||||||
|
activePings.Add(serverInfo.IP);
|
||||||
|
}
|
||||||
|
|
||||||
serverInfo.PingChecked = false;
|
serverInfo.PingChecked = false;
|
||||||
serverInfo.Ping = -1;
|
serverInfo.Ping = -1;
|
||||||
|
|
||||||
var pingThread = new Thread(() => { PingServer(serverInfo, 1000); })
|
TaskPool.Add(PingServerAsync(serverInfo?.IP, 1000),
|
||||||
{
|
new Tuple<ServerInfo, GUITextBlock>(serverInfo, serverPingText),
|
||||||
IsBackground = true
|
(rtt, obj) =>
|
||||||
};
|
|
||||||
pingThread.Start();
|
|
||||||
|
|
||||||
CoroutineManager.StartCoroutine(UpdateServerPingText(serverInfo, serverPingText, 1000));
|
|
||||||
}
|
|
||||||
|
|
||||||
private IEnumerable<object> UpdateServerPingText(ServerInfo serverInfo, GUITextBlock serverPingText, int timeOut)
|
|
||||||
{
|
|
||||||
DateTime timeOutTime = DateTime.Now + new TimeSpan(0, 0, 0, 0, milliseconds: timeOut);
|
|
||||||
while (DateTime.Now < timeOutTime)
|
|
||||||
{
|
|
||||||
if (serverInfo.PingChecked)
|
|
||||||
{
|
{
|
||||||
if (serverInfo.Ping != -1)
|
var info = obj.Item1;
|
||||||
|
var text = obj.Item2;
|
||||||
|
info.Ping = rtt.Result; info.PingChecked = true;
|
||||||
|
text.TextColor = GetPingTextColor(info.Ping);
|
||||||
|
text.Text = info.Ping > -1 ? info.Ping.ToString() : "?";
|
||||||
|
lock (activePings)
|
||||||
{
|
{
|
||||||
serverPingText.TextColor = GetPingTextColor(serverInfo.Ping);
|
activePings.Remove(serverInfo.IP);
|
||||||
}
|
}
|
||||||
serverPingText.Text = serverInfo.Ping > -1 ? serverInfo.Ping.ToString() : "?";
|
});
|
||||||
activePings.Remove(serverInfo.IP);
|
|
||||||
yield return CoroutineStatus.Success;
|
|
||||||
}
|
|
||||||
|
|
||||||
yield return CoroutineStatus.Running;
|
|
||||||
}
|
|
||||||
yield return CoroutineStatus.Success;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Color GetPingTextColor(int ping)
|
private Color GetPingTextColor(int ping)
|
||||||
@@ -1864,18 +1909,27 @@ namespace Barotrauma
|
|||||||
return ToolBox.GradientLerp(ping / 200.0f, Color.LightGreen, Color.Yellow * 0.8f, Color.Red * 0.75f);
|
return ToolBox.GradientLerp(ping / 200.0f, Color.LightGreen, Color.Yellow * 0.8f, Color.Red * 0.75f);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PingServer(ServerInfo serverInfo, int timeOut)
|
public async Task<int> PingServerAsync(string ip, int timeOut)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(serverInfo?.IP))
|
await Task.Yield();
|
||||||
|
int activePingCount = 100;
|
||||||
|
while (activePingCount > 25)
|
||||||
{
|
{
|
||||||
serverInfo.PingChecked = true;
|
lock (activePings)
|
||||||
serverInfo.Ping = -1;
|
{
|
||||||
return;
|
activePingCount = activePings.Count;
|
||||||
|
}
|
||||||
|
await Task.Delay(25);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(ip))
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
long rtt = -1;
|
long rtt = -1;
|
||||||
IPAddress address = null;
|
IPAddress address = null;
|
||||||
IPAddress.TryParse(serverInfo.IP, out address);
|
IPAddress.TryParse(ip, out address);
|
||||||
if (address != null)
|
if (address != null)
|
||||||
{
|
{
|
||||||
//don't attempt to ping if the address is IPv6 and it's not supported
|
//don't attempt to ping if the address is IPv6 and it's not supported
|
||||||
@@ -1902,8 +1956,8 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
catch (PingException ex)
|
catch (PingException ex)
|
||||||
{
|
{
|
||||||
string errorMsg = "Failed to ping a server (" + serverInfo.ServerName + ", " + serverInfo.IP + ") - " + (ex?.InnerException?.Message ?? ex.Message);
|
string errorMsg = "Failed to ping a server (" + ip + ") - " + (ex?.InnerException?.Message ?? ex.Message);
|
||||||
GameAnalyticsManager.AddErrorEventOnce("ServerListScreen.PingServer:PingException" + serverInfo.IP, GameAnalyticsSDK.Net.EGAErrorSeverity.Warning, errorMsg);
|
GameAnalyticsManager.AddErrorEventOnce("ServerListScreen.PingServer:PingException" + ip, GameAnalyticsSDK.Net.EGAErrorSeverity.Warning, errorMsg);
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
DebugConsole.NewMessage(errorMsg, Color.Red);
|
DebugConsole.NewMessage(errorMsg, Color.Red);
|
||||||
#endif
|
#endif
|
||||||
@@ -1911,8 +1965,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
serverInfo.PingChecked = true;
|
return (int)rtt;
|
||||||
serverInfo.Ping = (int)rtt;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Draw(double deltaTime, GraphicsDevice graphics, SpriteBatch spriteBatch)
|
public override void Draw(double deltaTime, GraphicsDevice graphics, SpriteBatch spriteBatch)
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private List<GUIButton> tabButtons = new List<GUIButton>();
|
private List<GUIButton> tabButtons = new List<GUIButton>();
|
||||||
|
|
||||||
private HashSet<string> pendingPreviewImageDownloads = new HashSet<string>();
|
private readonly HashSet<string> pendingPreviewImageDownloads = new HashSet<string>();
|
||||||
private Dictionary<string, Sprite> itemPreviewSprites = new Dictionary<string, Sprite>();
|
private Dictionary<string, Sprite> itemPreviewSprites = new Dictionary<string, Sprite>();
|
||||||
|
|
||||||
private enum Tab
|
private enum Tab
|
||||||
@@ -379,10 +379,16 @@ namespace Barotrauma
|
|||||||
if (!string.IsNullOrEmpty(item.PreviewImageUrl))
|
if (!string.IsNullOrEmpty(item.PreviewImageUrl))
|
||||||
{
|
{
|
||||||
string imagePreviewPath = Path.Combine(SteamManager.WorkshopItemPreviewImageFolder, item.Id + ".png");
|
string imagePreviewPath = Path.Combine(SteamManager.WorkshopItemPreviewImageFolder, item.Id + ".png");
|
||||||
if (!pendingPreviewImageDownloads.Contains(item.PreviewImageUrl))
|
|
||||||
{
|
|
||||||
pendingPreviewImageDownloads.Add(item.PreviewImageUrl);
|
|
||||||
|
|
||||||
|
bool isNewImage;
|
||||||
|
lock (pendingPreviewImageDownloads)
|
||||||
|
{
|
||||||
|
isNewImage = !pendingPreviewImageDownloads.Contains(item.PreviewImageUrl);
|
||||||
|
if (isNewImage) { pendingPreviewImageDownloads.Add(item.PreviewImageUrl); }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isNewImage)
|
||||||
|
{
|
||||||
if (File.Exists(imagePreviewPath))
|
if (File.Exists(imagePreviewPath))
|
||||||
{
|
{
|
||||||
File.Delete(imagePreviewPath);
|
File.Delete(imagePreviewPath);
|
||||||
@@ -397,7 +403,10 @@ namespace Barotrauma
|
|||||||
var request = new RestRequest(fileName, Method.GET);
|
var request = new RestRequest(fileName, Method.GET);
|
||||||
client.ExecuteAsync(request, response =>
|
client.ExecuteAsync(request, response =>
|
||||||
{
|
{
|
||||||
pendingPreviewImageDownloads.Remove(item.PreviewImageUrl);
|
lock (pendingPreviewImageDownloads)
|
||||||
|
{
|
||||||
|
pendingPreviewImageDownloads.Remove(item.PreviewImageUrl);
|
||||||
|
}
|
||||||
OnPreviewImageDownloaded(response, imagePreviewPath);
|
OnPreviewImageDownloaded(response, imagePreviewPath);
|
||||||
CoroutineManager.StartCoroutine(WaitForItemPreviewDownloaded(item, listBox, imagePreviewPath));
|
CoroutineManager.StartCoroutine(WaitForItemPreviewDownloaded(item, listBox, imagePreviewPath));
|
||||||
});
|
});
|
||||||
@@ -410,7 +419,10 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
pendingPreviewImageDownloads.Remove(item.PreviewImageUrl);
|
lock (pendingPreviewImageDownloads)
|
||||||
|
{
|
||||||
|
pendingPreviewImageDownloads.Remove(item.PreviewImageUrl);
|
||||||
|
}
|
||||||
DebugConsole.ThrowError("Downloading the preview image of the Workshop item \"" + TextManager.EnsureUTF8(item.Title) + "\" failed.", e);
|
DebugConsole.ThrowError("Downloading the preview image of the Workshop item \"" + TextManager.EnsureUTF8(item.Title) + "\" failed.", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -595,8 +607,13 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private IEnumerable<object> WaitForItemPreviewDownloaded(Facepunch.Steamworks.Workshop.Item item, GUIListBox listBox, string previewImagePath)
|
private IEnumerable<object> WaitForItemPreviewDownloaded(Facepunch.Steamworks.Workshop.Item item, GUIListBox listBox, string previewImagePath)
|
||||||
{
|
{
|
||||||
while (pendingPreviewImageDownloads.Contains(item.PreviewImageUrl))
|
while (true)
|
||||||
{
|
{
|
||||||
|
lock (pendingPreviewImageDownloads)
|
||||||
|
{
|
||||||
|
if (!pendingPreviewImageDownloads.Contains(item.PreviewImageUrl)) { break; }
|
||||||
|
}
|
||||||
|
|
||||||
yield return CoroutineStatus.Running;
|
yield return CoroutineStatus.Running;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -522,11 +522,6 @@ namespace Barotrauma
|
|||||||
OnSelected = (GUITickBox obj) => { Gap.ShowGaps = obj.Selected; return true; },
|
OnSelected = (GUITickBox obj) => { Gap.ShowGaps = obj.Selected; return true; },
|
||||||
};
|
};
|
||||||
|
|
||||||
tickBoxHolder.Children.ForEach(c =>
|
|
||||||
{
|
|
||||||
if (c is GUITickBox tb) { tb.RectTransform.MinSize = new Point(0, 32); }
|
|
||||||
});
|
|
||||||
|
|
||||||
GUITextBlock.AutoScaleAndNormalize(tickBoxHolder.Children.Where(c => c is GUITickBox).Select(c => ((GUITickBox)c).TextBlock));
|
GUITextBlock.AutoScaleAndNormalize(tickBoxHolder.Children.Where(c => c is GUITickBox).Select(c => ((GUITickBox)c).TextBlock));
|
||||||
|
|
||||||
//spacing
|
//spacing
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ namespace Barotrauma.SpriteDeformations
|
|||||||
/// A positive value means that this deformation is or could be used for multiple sprites.
|
/// A positive value means that this deformation is or could be used for multiple sprites.
|
||||||
/// This behaviour is not automatic, and has to be implemented for any particular case separately (currently only used in Limbs).
|
/// This behaviour is not automatic, and has to be implemented for any particular case separately (currently only used in Limbs).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Serialize(-1, true), Editable]
|
[Serialize(-1, true), Editable(minValue: -1, maxValue: 100)]
|
||||||
public int Sync
|
public int Sync
|
||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
foreach (RoundSound sound in sounds)
|
foreach (RoundSound sound in sounds)
|
||||||
{
|
{
|
||||||
if (sound.Sound == null)
|
if (sound?.Sound == null)
|
||||||
{
|
{
|
||||||
string errorMsg = $"Error in StatusEffect.ApplyProjSpecific1 (sound \"{sound.Filename ?? "unknown"}\" was null)\n" + Environment.StackTrace;
|
string errorMsg = $"Error in StatusEffect.ApplyProjSpecific1 (sound \"{sound.Filename ?? "unknown"}\" was null)\n" + Environment.StackTrace;
|
||||||
GameAnalyticsManager.AddErrorEventOnce("StatusEffect.ApplyProjSpecific:SoundNull1" + Environment.StackTrace, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
GameAnalyticsManager.AddErrorEventOnce("StatusEffect.ApplyProjSpecific:SoundNull1" + Environment.StackTrace, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||||
@@ -90,7 +90,7 @@ namespace Barotrauma
|
|||||||
selectedSoundIndex = Rand.Int(sounds.Count);
|
selectedSoundIndex = Rand.Int(sounds.Count);
|
||||||
}
|
}
|
||||||
var selectedSound = sounds[selectedSoundIndex];
|
var selectedSound = sounds[selectedSoundIndex];
|
||||||
if (selectedSound.Sound == null)
|
if (selectedSound?.Sound == null)
|
||||||
{
|
{
|
||||||
string errorMsg = $"Error in StatusEffect.ApplyProjSpecific2 (sound \"{selectedSound.Filename ?? "unknown"}\" was null)\n" + Environment.StackTrace;
|
string errorMsg = $"Error in StatusEffect.ApplyProjSpecific2 (sound \"{selectedSound.Filename ?? "unknown"}\" was null)\n" + Environment.StackTrace;
|
||||||
GameAnalyticsManager.AddErrorEventOnce("StatusEffect.ApplyProjSpecific:SoundNull2" + Environment.StackTrace, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
GameAnalyticsManager.AddErrorEventOnce("StatusEffect.ApplyProjSpecific:SoundNull2" + Environment.StackTrace, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||||
|
|||||||
@@ -31,5 +31,5 @@ using System.Runtime.InteropServices;
|
|||||||
// You can specify all the values or you can default the Build and Revision Numbers
|
// You can specify all the values or you can default the Build and Revision Numbers
|
||||||
// by using the '*' as shown below:
|
// by using the '*' as shown below:
|
||||||
// [assembly: AssemblyVersion("1.0.*")]
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
[assembly: AssemblyVersion("0.9.5.1")]
|
[assembly: AssemblyVersion("0.9.6.0")]
|
||||||
[assembly: AssemblyFileVersion("0.9.5.1")]
|
[assembly: AssemblyFileVersion("0.9.6.0")]
|
||||||
|
|||||||
@@ -268,8 +268,8 @@ namespace Barotrauma
|
|||||||
break;
|
break;
|
||||||
case NetEntityEvent.Type.Control:
|
case NetEntityEvent.Type.Control:
|
||||||
msg.WriteRangedInteger(1, 0, 3);
|
msg.WriteRangedInteger(1, 0, 3);
|
||||||
Client owner = ((Client)extraData[1]);
|
Client owner = (Client)extraData[1];
|
||||||
msg.Write(owner == null ? (byte)0 : owner.ID);
|
msg.Write(owner != null && owner.Character == this && GameMain.Server.ConnectedClients.Contains(owner) ? owner.ID : (byte)0);
|
||||||
break;
|
break;
|
||||||
case NetEntityEvent.Type.Status:
|
case NetEntityEvent.Type.Status:
|
||||||
msg.WriteRangedInteger(2, 0, 3);
|
msg.WriteRangedInteger(2, 0, 3);
|
||||||
@@ -445,14 +445,14 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void WriteSpawnData(IWriteMessage msg)
|
public void WriteSpawnData(IWriteMessage msg, UInt16 entityId)
|
||||||
{
|
{
|
||||||
if (GameMain.Server == null) return;
|
if (GameMain.Server == null) return;
|
||||||
|
|
||||||
int msgLength = msg.LengthBytes;
|
int msgLength = msg.LengthBytes;
|
||||||
|
|
||||||
msg.Write(Info == null);
|
msg.Write(Info == null);
|
||||||
msg.Write(ID);
|
msg.Write(entityId);
|
||||||
msg.Write(SpeciesName);
|
msg.Write(SpeciesName);
|
||||||
msg.Write(seed);
|
msg.Write(seed);
|
||||||
|
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
Instance = this;
|
Instance = this;
|
||||||
|
|
||||||
CommandLineArgs = args;
|
CommandLineArgs = ToolBox.MergeArguments(args);
|
||||||
|
|
||||||
World = new World(new Vector2(0, -9.82f));
|
World = new World(new Vector2(0, -9.82f));
|
||||||
FarseerPhysics.Settings.AllowSleep = true;
|
FarseerPhysics.Settings.AllowSleep = true;
|
||||||
@@ -189,6 +189,13 @@ namespace Barotrauma
|
|||||||
ownerKey = 0;
|
ownerKey = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
foreach (string s in CommandLineArgs)
|
||||||
|
{
|
||||||
|
Console.WriteLine(s);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
for (int i = 0; i < CommandLineArgs.Length; i++)
|
for (int i = 0; i < CommandLineArgs.Length; i++)
|
||||||
{
|
{
|
||||||
switch (CommandLineArgs[i].Trim())
|
switch (CommandLineArgs[i].Trim())
|
||||||
@@ -213,6 +220,9 @@ namespace Barotrauma
|
|||||||
password = CommandLineArgs[i + 1];
|
password = CommandLineArgs[i + 1];
|
||||||
i++;
|
i++;
|
||||||
break;
|
break;
|
||||||
|
case "-nopassword":
|
||||||
|
password = "";
|
||||||
|
break;
|
||||||
case "-upnp":
|
case "-upnp":
|
||||||
case "-enableupnp":
|
case "-enableupnp":
|
||||||
bool.TryParse(CommandLineArgs[i + 1], out enableUpnp);
|
bool.TryParse(CommandLineArgs[i + 1], out enableUpnp);
|
||||||
@@ -303,6 +313,7 @@ namespace Barotrauma
|
|||||||
Server.Update((float)Timing.Step);
|
Server.Update((float)Timing.Step);
|
||||||
if (Server == null) { break; }
|
if (Server == null) { break; }
|
||||||
SteamManager.Update((float)Timing.Step);
|
SteamManager.Update((float)Timing.Step);
|
||||||
|
TaskPool.Update();
|
||||||
CoroutineManager.Update((float)Timing.Step, (float)Timing.Step);
|
CoroutineManager.Update((float)Timing.Step, (float)Timing.Step);
|
||||||
|
|
||||||
Timing.Accumulator -= Timing.Step;
|
Timing.Accumulator -= Timing.Step;
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
partial void SetState(bool open, bool isNetworkMessage, bool sendNetworkMessage, bool forcedOpen)
|
partial void SetState(bool open, bool isNetworkMessage, bool sendNetworkMessage, bool forcedOpen)
|
||||||
{
|
{
|
||||||
if (isStuck || isOpen == open)
|
if (IsStuck || isOpen == open)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ namespace Barotrauma.Items.Components
|
|||||||
public void ServerWrite(IWriteMessage msg, Client c, object[] extraData = null)
|
public void ServerWrite(IWriteMessage msg, Client c, object[] extraData = null)
|
||||||
{
|
{
|
||||||
msg.Write(state);
|
msg.Write(state);
|
||||||
|
msg.Write(user == null ? (ushort)0 : user.ID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ namespace Barotrauma.Items.Components
|
|||||||
msg.Write(deteriorationTimer);
|
msg.Write(deteriorationTimer);
|
||||||
msg.Write(deteriorateAlwaysResetTimer);
|
msg.Write(deteriorateAlwaysResetTimer);
|
||||||
msg.Write(DeteriorateAlways);
|
msg.Write(DeteriorateAlways);
|
||||||
msg.Write(CurrentFixer == c.Character);
|
msg.Write(CurrentFixer == null ? (ushort)0 : CurrentFixer.ID);
|
||||||
msg.WriteRangedInteger((int)currentFixerAction, 0, 2);
|
msg.WriteRangedInteger((int)currentFixerAction, 0, 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
List<Wire> clientSideDisconnectedWires = new List<Wire>();
|
List<Wire> clientSideDisconnectedWires = new List<Wire>();
|
||||||
ushort disconnectedWireCount = msg.ReadUInt16();
|
ushort disconnectedWireCount = msg.ReadUInt16();
|
||||||
for (int i = 0; i < disconnectedWireCount; i++)
|
for (int i = 0; i < disconnectedWireCount; i++)
|
||||||
@@ -179,6 +178,7 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
public void ServerWrite(IWriteMessage msg, Client c, object[] extraData = null)
|
public void ServerWrite(IWriteMessage msg, Client c, object[] extraData = null)
|
||||||
{
|
{
|
||||||
|
msg.Write(user == null ? (ushort)0 : user.ID);
|
||||||
ClientWrite(msg, extraData);
|
ClientWrite(msg, extraData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -100,16 +100,26 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
ActionType actionType = (ActionType)extraData[1];
|
ActionType actionType = (ActionType)extraData[1];
|
||||||
ItemComponent targetComponent = extraData.Length > 2 ? (ItemComponent)extraData[2] : null;
|
ItemComponent targetComponent = extraData.Length > 2 ? (ItemComponent)extraData[2] : null;
|
||||||
ushort targetID = extraData.Length > 3 ? (ushort)extraData[3] : (ushort)0;
|
ushort characterID = extraData.Length > 3 ? (ushort)extraData[3] : (ushort)0;
|
||||||
Limb targetLimb = extraData.Length > 4 ? (Limb)extraData[4] : null;
|
Limb targetLimb = extraData.Length > 4 ? (Limb)extraData[4] : null;
|
||||||
|
ushort useTargetID = extraData.Length > 5 ? (ushort)extraData[5] : (ushort)0;
|
||||||
|
Vector2? worldPosition = null;
|
||||||
|
if (extraData.Length > 6) { worldPosition = (Vector2)extraData[6]; }
|
||||||
|
|
||||||
Character targetCharacter = FindEntityByID(targetID) as Character;
|
Character targetCharacter = FindEntityByID(characterID) as Character;
|
||||||
byte targetLimbIndex = targetLimb != null && targetCharacter != null ? (byte)Array.IndexOf(targetCharacter.AnimController.Limbs, targetLimb) : (byte)255;
|
byte targetLimbIndex = targetLimb != null && targetCharacter != null ? (byte)Array.IndexOf(targetCharacter.AnimController.Limbs, targetLimb) : (byte)255;
|
||||||
|
|
||||||
msg.WriteRangedInteger((int)actionType, 0, Enum.GetValues(typeof(ActionType)).Length - 1);
|
msg.WriteRangedInteger((int)actionType, 0, Enum.GetValues(typeof(ActionType)).Length - 1);
|
||||||
msg.Write((byte)(targetComponent == null ? 255 : components.IndexOf(targetComponent)));
|
msg.Write((byte)(targetComponent == null ? 255 : components.IndexOf(targetComponent)));
|
||||||
msg.Write(targetID);
|
msg.Write(characterID);
|
||||||
msg.Write(targetLimbIndex);
|
msg.Write(targetLimbIndex);
|
||||||
|
msg.Write(useTargetID);
|
||||||
|
msg.Write(worldPosition.HasValue);
|
||||||
|
if (worldPosition.HasValue)
|
||||||
|
{
|
||||||
|
msg.Write(worldPosition.Value.X);
|
||||||
|
msg.Write(worldPosition.Value.Y);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case NetEntityEvent.Type.ChangeProperty:
|
case NetEntityEvent.Type.ChangeProperty:
|
||||||
@@ -197,7 +207,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void WriteSpawnData(IWriteMessage msg)
|
public void WriteSpawnData(IWriteMessage msg, UInt16 entityID)
|
||||||
{
|
{
|
||||||
if (GameMain.Server == null) return;
|
if (GameMain.Server == null) return;
|
||||||
|
|
||||||
@@ -209,7 +219,7 @@ namespace Barotrauma
|
|||||||
msg.Write(Description);
|
msg.Write(Description);
|
||||||
}
|
}
|
||||||
|
|
||||||
msg.Write(ID);
|
msg.Write(entityID);
|
||||||
|
|
||||||
if (ParentInventory == null || ParentInventory.Owner == null)
|
if (ParentInventory == null || ParentInventory.Owner == null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -25,24 +25,23 @@ namespace Barotrauma
|
|||||||
SpawnOrRemove entities = (SpawnOrRemove)extraData[0];
|
SpawnOrRemove entities = (SpawnOrRemove)extraData[0];
|
||||||
|
|
||||||
message.Write(entities.Remove);
|
message.Write(entities.Remove);
|
||||||
|
|
||||||
if (entities.Remove)
|
if (entities.Remove)
|
||||||
{
|
{
|
||||||
message.Write(entities.Entity.ID);
|
message.Write(entities.OriginalID);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (entities.Entity is Item)
|
if (entities.Entity is Item)
|
||||||
{
|
{
|
||||||
message.Write((byte)SpawnableType.Item);
|
message.Write((byte)SpawnableType.Item);
|
||||||
DebugConsole.Log("Writing item spawn data " + entities.Entity.ToString() + " (ID: " + entities.Entity.ID + ")");
|
DebugConsole.Log("Writing item spawn data " + entities.Entity.ToString() + " (original ID: " + entities.OriginalID + ", current ID: " + entities.Entity.ID + ")");
|
||||||
((Item)entities.Entity).WriteSpawnData(message);
|
((Item)entities.Entity).WriteSpawnData(message, entities.OriginalID);
|
||||||
}
|
}
|
||||||
else if (entities.Entity is Character)
|
else if (entities.Entity is Character)
|
||||||
{
|
{
|
||||||
message.Write((byte)SpawnableType.Character);
|
message.Write((byte)SpawnableType.Character);
|
||||||
DebugConsole.Log("Writing character spawn data: " + entities.Entity.ToString() + " (ID: " + entities.Entity.ID + ")");
|
DebugConsole.Log("Writing character spawn data: " + entities.Entity.ToString() + " (original ID: " + entities.OriginalID + ", current ID: " + entities.Entity.ID + ")");
|
||||||
((Character)entities.Entity).WriteSpawnData(message);
|
((Character)entities.Entity).WriteSpawnData(message, entities.OriginalID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -134,10 +134,7 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
serverSettings = new ServerSettings(this, name, port, queryPort, maxPlayers, isPublic, attemptUPnP);
|
serverSettings = new ServerSettings(this, name, port, queryPort, maxPlayers, isPublic, attemptUPnP);
|
||||||
KarmaManager.SelectPreset(serverSettings.KarmaPreset);
|
KarmaManager.SelectPreset(serverSettings.KarmaPreset);
|
||||||
if (!string.IsNullOrEmpty(password))
|
serverSettings.SetPassword(password);
|
||||||
{
|
|
||||||
serverSettings.SetPassword(password);
|
|
||||||
}
|
|
||||||
|
|
||||||
ownerKey = ownKey;
|
ownerKey = ownKey;
|
||||||
|
|
||||||
@@ -874,7 +871,9 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
if (Level.Loaded != null && levelEqualityCheckVal != Level.Loaded.EqualityCheckVal)
|
if (Level.Loaded != null && levelEqualityCheckVal != Level.Loaded.EqualityCheckVal)
|
||||||
{
|
{
|
||||||
errorStr += " Level equality check failed. The level generated at your end doesn't match the level generated by the server (seed " + Level.Loaded.Seed + ").";
|
errorStr += " Level equality check failed. The level generated at your end doesn't match the level generated by the server(seed: " + Level.Loaded.Seed +
|
||||||
|
", sub: " + Submarine.MainSub.Name + " (" + Submarine.MainSub.MD5Hash.ShortHash + ")" +
|
||||||
|
", mirrored: " + Level.Loaded.Mirrored + ").";
|
||||||
}
|
}
|
||||||
|
|
||||||
Log(c.Name + " has reported an error: " + errorStr, ServerLog.MessageType.Error);
|
Log(c.Name + " has reported an error: " + errorStr, ServerLog.MessageType.Error);
|
||||||
|
|||||||
@@ -306,6 +306,7 @@ namespace Barotrauma.Networking
|
|||||||
}
|
}
|
||||||
|
|
||||||
ServerName = doc.Root.GetAttributeString("name", "");
|
ServerName = doc.Root.GetAttributeString("name", "");
|
||||||
|
if (ServerName.Length > NetConfig.ServerNameMaxLength) { ServerName = ServerName.Substring(0, NetConfig.ServerNameMaxLength); }
|
||||||
ServerMessageText = doc.Root.GetAttributeString("ServerMessage", "");
|
ServerMessageText = doc.Root.GetAttributeString("ServerMessage", "");
|
||||||
|
|
||||||
GameMain.NetLobbyScreen.SelectedModeIdentifier = GameModeIdentifier;
|
GameMain.NetLobbyScreen.SelectedModeIdentifier = GameModeIdentifier;
|
||||||
|
|||||||
@@ -283,6 +283,7 @@
|
|||||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Utils\MTRandom.cs" />
|
<Compile Include="$(MSBuildThisFileDirectory)Source\Utils\MTRandom.cs" />
|
||||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Utils\Rand.cs" />
|
<Compile Include="$(MSBuildThisFileDirectory)Source\Utils\Rand.cs" />
|
||||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Utils\SaveUtil.cs" />
|
<Compile Include="$(MSBuildThisFileDirectory)Source\Utils\SaveUtil.cs" />
|
||||||
|
<Compile Include="$(MSBuildThisFileDirectory)Source\Utils\TaskPool.cs" />
|
||||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Utils\ToolBox.cs" />
|
<Compile Include="$(MSBuildThisFileDirectory)Source\Utils\ToolBox.cs" />
|
||||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Utils\UpdaterUtil.cs" />
|
<Compile Include="$(MSBuildThisFileDirectory)Source\Utils\UpdaterUtil.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ namespace Barotrauma
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// How long does it take for the ai target to fade out if not kept alive.
|
/// How long does it take for the ai target to fade out if not kept alive.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public float FadeOutTime { get; private set; }
|
public float FadeOutTime { get; private set; } = 1;
|
||||||
|
|
||||||
public bool Static { get; private set; }
|
public bool Static { get; private set; }
|
||||||
|
|
||||||
|
|||||||
@@ -611,6 +611,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool canAttack = true;
|
bool canAttack = true;
|
||||||
|
bool pursue = false;
|
||||||
if (IsCoolDownRunning)
|
if (IsCoolDownRunning)
|
||||||
{
|
{
|
||||||
switch (AttackingLimb.attack.AfterAttack)
|
switch (AttackingLimb.attack.AfterAttack)
|
||||||
@@ -623,6 +624,7 @@ namespace Barotrauma
|
|||||||
if (AttackingLimb.attack.AfterAttack == AIBehaviorAfterAttack.Pursue)
|
if (AttackingLimb.attack.AfterAttack == AIBehaviorAfterAttack.Pursue)
|
||||||
{
|
{
|
||||||
canAttack = false;
|
canAttack = false;
|
||||||
|
pursue = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -661,6 +663,7 @@ namespace Barotrauma
|
|||||||
if (AttackingLimb.attack.AfterAttack == AIBehaviorAfterAttack.Pursue)
|
if (AttackingLimb.attack.AfterAttack == AIBehaviorAfterAttack.Pursue)
|
||||||
{
|
{
|
||||||
canAttack = false;
|
canAttack = false;
|
||||||
|
pursue = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -853,32 +856,35 @@ namespace Barotrauma
|
|||||||
if (pathSteering.CurrentPath != null)
|
if (pathSteering.CurrentPath != null)
|
||||||
{
|
{
|
||||||
// Attack doors
|
// Attack doors
|
||||||
if (canAttackSub && pathSteering.CurrentPath.CurrentNode?.ConnectedDoor != null && SelectedAiTarget != pathSteering.CurrentPath.CurrentNode.ConnectedDoor.Item.AiTarget)
|
if (canAttackSub)
|
||||||
{
|
{
|
||||||
SelectTarget(pathSteering.CurrentPath.CurrentNode.ConnectedDoor.Item.AiTarget);
|
// If the target is in the same hull, there shouldn't be any doors blocking the path
|
||||||
return;
|
if (targetCharacter == null || targetCharacter.CurrentHull != Character.CurrentHull)
|
||||||
|
{
|
||||||
|
var door = pathSteering.CurrentPath.CurrentNode?.ConnectedDoor ?? pathSteering.CurrentPath.NextNode?.ConnectedDoor;
|
||||||
|
if (door != null && !door.IsOpen && door.Item.Condition > 0)
|
||||||
|
{
|
||||||
|
if (SelectedAiTarget != door.Item.AiTarget)
|
||||||
|
{
|
||||||
|
SelectTarget(door.Item.AiTarget, selectedTargetMemory.Priority);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (canAttackSub && pathSteering.CurrentPath.NextNode?.ConnectedDoor != null && SelectedAiTarget != pathSteering.CurrentPath.NextNode.ConnectedDoor.Item.AiTarget)
|
// Steer towards the target if in the same room and swimming
|
||||||
|
if ((Character.AnimController.InWater || pursue) && targetCharacter != null && VisibleHulls.Contains(targetCharacter.CurrentHull))
|
||||||
{
|
{
|
||||||
SelectTarget(pathSteering.CurrentPath.NextNode.ConnectedDoor.Item.AiTarget);
|
SteeringManager.SteeringManual(deltaTime, Vector2.Normalize(attackSimPos - steeringLimb.SimPosition));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Steer towards the target if in the same room and swimming
|
SteeringManager.SteeringSeek(steerPos, 2);
|
||||||
if (Character.AnimController.InWater && targetCharacter != null && VisibleHulls.Contains(targetCharacter.CurrentHull))
|
// Switch to Idle when cannot reach the target and if cannot damage the walls
|
||||||
|
if ((!canAttackSub || wallTarget == null) && !pathSteering.IsPathDirty && pathSteering.CurrentPath.Unreachable)
|
||||||
{
|
{
|
||||||
SteeringManager.SteeringManual(deltaTime, Vector2.Normalize(attackSimPos - steeringLimb.SimPosition));
|
State = AIState.Idle;
|
||||||
}
|
return;
|
||||||
else
|
|
||||||
{
|
|
||||||
SteeringManager.SteeringSeek(steerPos, 2);
|
|
||||||
// Switch to Idle when cannot reach the target and if cannot damage the walls
|
|
||||||
if ((!canAttackSub || wallTarget == null) && !pathSteering.IsPathDirty && pathSteering.CurrentPath.Unreachable)
|
|
||||||
{
|
|
||||||
State = AIState.Idle;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1148,8 +1154,8 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
selectedTargetMemory.Priority = 0;
|
selectedTargetMemory.Priority = 0;
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -525,6 +525,7 @@ namespace Barotrauma
|
|||||||
protected void ReportProblems()
|
protected void ReportProblems()
|
||||||
{
|
{
|
||||||
Order newOrder = null;
|
Order newOrder = null;
|
||||||
|
Hull targetHull = null;
|
||||||
if (Character.CurrentHull != null)
|
if (Character.CurrentHull != null)
|
||||||
{
|
{
|
||||||
foreach (var hull in VisibleHulls)
|
foreach (var hull in VisibleHulls)
|
||||||
@@ -534,21 +535,21 @@ namespace Barotrauma
|
|||||||
if (c.CurrentHull != hull || !c.Enabled) { continue; }
|
if (c.CurrentHull != hull || !c.Enabled) { continue; }
|
||||||
if (AIObjectiveFightIntruders.IsValidTarget(c, Character))
|
if (AIObjectiveFightIntruders.IsValidTarget(c, Character))
|
||||||
{
|
{
|
||||||
AddTargets<AIObjectiveFightIntruders, Character>(Character, c);
|
if (AddTargets<AIObjectiveFightIntruders, Character>(Character, c) && newOrder == null)
|
||||||
if (newOrder == null)
|
|
||||||
{
|
{
|
||||||
var orderPrefab = Order.GetPrefab("reportintruders");
|
var orderPrefab = Order.GetPrefab("reportintruders");
|
||||||
newOrder = new Order(orderPrefab, c.CurrentHull, null, orderGiver: Character);
|
newOrder = new Order(orderPrefab, hull, null, orderGiver: Character);
|
||||||
|
targetHull = hull;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (AIObjectiveExtinguishFires.IsValidTarget(hull, Character))
|
if (AIObjectiveExtinguishFires.IsValidTarget(hull, Character))
|
||||||
{
|
{
|
||||||
AddTargets<AIObjectiveExtinguishFires, Hull>(Character, hull);
|
if (AddTargets<AIObjectiveExtinguishFires, Hull>(Character, hull) && newOrder == null)
|
||||||
if (newOrder == null)
|
|
||||||
{
|
{
|
||||||
var orderPrefab = Order.GetPrefab("reportfire");
|
var orderPrefab = Order.GetPrefab("reportfire");
|
||||||
newOrder = new Order(orderPrefab, hull, null, orderGiver: Character);
|
newOrder = new Order(orderPrefab, hull, null, orderGiver: Character);
|
||||||
|
targetHull = hull;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
foreach (Character c in Character.CharacterList)
|
foreach (Character c in Character.CharacterList)
|
||||||
@@ -556,13 +557,11 @@ namespace Barotrauma
|
|||||||
if (c.CurrentHull != hull) { continue; }
|
if (c.CurrentHull != hull) { continue; }
|
||||||
if (AIObjectiveRescueAll.IsValidTarget(c, Character))
|
if (AIObjectiveRescueAll.IsValidTarget(c, Character))
|
||||||
{
|
{
|
||||||
if (AddTargets<AIObjectiveRescueAll, Character>(c, Character))
|
if (AddTargets<AIObjectiveRescueAll, Character>(c, Character) && newOrder == null && !ObjectiveManager.HasActiveObjective<AIObjectiveRescue>())
|
||||||
{
|
{
|
||||||
if (newOrder == null)
|
var orderPrefab = Order.GetPrefab("requestfirstaid");
|
||||||
{
|
newOrder = new Order(orderPrefab, hull, null, orderGiver: Character);
|
||||||
var orderPrefab = Order.GetPrefab("requestfirstaid");
|
targetHull = hull;
|
||||||
newOrder = new Order(orderPrefab, c.CurrentHull, null, orderGiver: Character);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -570,11 +569,11 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (AIObjectiveFixLeaks.IsValidTarget(gap, Character))
|
if (AIObjectiveFixLeaks.IsValidTarget(gap, Character))
|
||||||
{
|
{
|
||||||
AddTargets<AIObjectiveFixLeaks, Gap>(Character, gap);
|
if (AddTargets<AIObjectiveFixLeaks, Gap>(Character, gap) && newOrder == null && !gap.IsRoomToRoom)
|
||||||
if (newOrder == null && !gap.IsRoomToRoom)
|
|
||||||
{
|
{
|
||||||
var orderPrefab = Order.GetPrefab("reportbreach");
|
var orderPrefab = Order.GetPrefab("reportbreach");
|
||||||
newOrder = new Order(orderPrefab, hull, null, orderGiver: Character);
|
newOrder = new Order(orderPrefab, hull, null, orderGiver: Character);
|
||||||
|
targetHull = hull;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -584,11 +583,11 @@ namespace Barotrauma
|
|||||||
if (AIObjectiveRepairItems.IsValidTarget(item, Character))
|
if (AIObjectiveRepairItems.IsValidTarget(item, Character))
|
||||||
{
|
{
|
||||||
if (item.Repairables.All(r => item.ConditionPercentage > r.ShowRepairUIThreshold)) { continue; }
|
if (item.Repairables.All(r => item.ConditionPercentage > r.ShowRepairUIThreshold)) { continue; }
|
||||||
AddTargets<AIObjectiveRepairItems, Item>(Character, item);
|
if (AddTargets<AIObjectiveRepairItems, Item>(Character, item) && newOrder == null && !ObjectiveManager.HasActiveObjective<AIObjectiveRepairItem>())
|
||||||
if (newOrder == null)
|
|
||||||
{
|
{
|
||||||
var orderPrefab = Order.GetPrefab("reportbrokendevices");
|
var orderPrefab = Order.GetPrefab("reportbrokendevices");
|
||||||
newOrder = new Order(orderPrefab, item.CurrentHull, item.Repairables?.FirstOrDefault(), orderGiver: Character);
|
newOrder = new Order(orderPrefab, hull, item.Repairables?.FirstOrDefault(), orderGiver: Character);
|
||||||
|
targetHull = hull;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -598,9 +597,9 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (GameMain.GameSession?.CrewManager != null && GameMain.GameSession.CrewManager.AddOrder(newOrder, newOrder.FadeOutTime))
|
if (GameMain.GameSession?.CrewManager != null && GameMain.GameSession.CrewManager.AddOrder(newOrder, newOrder.FadeOutTime))
|
||||||
{
|
{
|
||||||
Character.Speak(newOrder.GetChatMessage("", Character.CurrentHull?.DisplayName, givingOrderToSelf: false), ChatMessageType.Order);
|
Character.Speak(newOrder.GetChatMessage("", targetHull?.DisplayName, givingOrderToSelf: false), ChatMessageType.Order);
|
||||||
#if SERVER
|
#if SERVER
|
||||||
GameMain.Server.SendOrderChatMessage(new OrderChatMessage(newOrder, "", Character.CurrentHull, null, Character));
|
GameMain.Server.SendOrderChatMessage(new OrderChatMessage(newOrder, "", targetHull, null, Character));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -191,7 +191,8 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
diff.Y = 0.0f;
|
diff.Y = 0.0f;
|
||||||
}
|
}
|
||||||
if (diff.LengthSquared() < 0.001f) { return -host.Steering; }
|
//if (diff.LengthSquared() < 0.001f) { return -host.Steering; }
|
||||||
|
if (diff == Vector2.Zero) { return Vector2.Zero; }
|
||||||
return Vector2.Normalize(diff) * weight;
|
return Vector2.Normalize(diff) * weight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ namespace Barotrauma
|
|||||||
foreach (FireSource fs in targetHull.FireSources)
|
foreach (FireSource fs in targetHull.FireSources)
|
||||||
{
|
{
|
||||||
bool inRange = fs.IsInDamageRange(character, MathHelper.Clamp(fs.DamageRange * 1.5f, extinguisher.Range * 0.5f, extinguisher.Range));
|
bool inRange = fs.IsInDamageRange(character, MathHelper.Clamp(fs.DamageRange * 1.5f, extinguisher.Range * 0.5f, extinguisher.Range));
|
||||||
bool move = !inRange;
|
bool move = !inRange || !HumanAIController.VisibleHulls.Contains(fs.Hull);
|
||||||
if (inRange || useExtinquisherTimer > 0.0f)
|
if (inRange || useExtinquisherTimer > 0.0f)
|
||||||
{
|
{
|
||||||
useExtinquisherTimer += deltaTime;
|
useExtinquisherTimer += deltaTime;
|
||||||
@@ -79,7 +79,6 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
useExtinquisherTimer = 0.0f;
|
useExtinquisherTimer = 0.0f;
|
||||||
}
|
}
|
||||||
character.AIController.SteeringManager.Reset();
|
|
||||||
character.CursorPosition = fs.Position;
|
character.CursorPosition = fs.Position;
|
||||||
if (extinguisher.Item.RequireAimToUse)
|
if (extinguisher.Item.RequireAimToUse)
|
||||||
{
|
{
|
||||||
@@ -106,20 +105,19 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
sightLimb = character.AnimController.GetLimb(LimbType.LeftHand);
|
sightLimb = character.AnimController.GetLimb(LimbType.LeftHand);
|
||||||
}
|
}
|
||||||
if (!character.CanSeeTarget(fs, sightLimb))
|
if (character.CanSeeTarget(fs, sightLimb))
|
||||||
{
|
{
|
||||||
move = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
move = false;
|
|
||||||
character.SetInput(extinguisher.Item.IsShootable ? InputType.Shoot : InputType.Use, false, true);
|
character.SetInput(extinguisher.Item.IsShootable ? InputType.Shoot : InputType.Use, false, true);
|
||||||
extinguisher.Use(deltaTime, character);
|
extinguisher.Use(deltaTime, character);
|
||||||
if (!targetHull.FireSources.Contains(fs))
|
if (!targetHull.FireSources.Contains(fs))
|
||||||
{
|
{
|
||||||
character.Speak(TextManager.GetWithVariable("DialogPutOutFire", "[roomname]", targetHull.Name, true), null, 0, "putoutfire", 10.0f);
|
character.Speak(TextManager.GetWithVariable("DialogPutOutFire", "[roomname]", targetHull.RoomName, true), null, 0, "putoutfire", 10.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
move = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (move)
|
if (move)
|
||||||
{
|
{
|
||||||
@@ -128,6 +126,10 @@ namespace Barotrauma
|
|||||||
onAbandon: () => Abandon = true,
|
onAbandon: () => Abandon = true,
|
||||||
onCompleted: () => RemoveSubObjective(ref gotoObjective));
|
onCompleted: () => RemoveSubObjective(ref gotoObjective));
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
character.AIController.SteeringManager.Reset();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
public override string DebugTag => "fight intruders";
|
public override string DebugTag => "fight intruders";
|
||||||
protected override float IgnoreListClearInterval => 30;
|
protected override float IgnoreListClearInterval => 30;
|
||||||
public virtual bool IgnoreUnsafeHulls => true;
|
public override bool IgnoreUnsafeHulls => true;
|
||||||
|
|
||||||
public AIObjectiveFightIntruders(Character character, AIObjectiveManager objectiveManager, float priorityModifier = 1)
|
public AIObjectiveFightIntruders(Character character, AIObjectiveManager objectiveManager, float priorityModifier = 1)
|
||||||
: base(character, objectiveManager, priorityModifier) { }
|
: base(character, objectiveManager, priorityModifier) { }
|
||||||
|
|||||||
@@ -200,7 +200,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
SteeringManager.SteeringSeek(character.GetRelativeSimPosition(Target), 10);
|
SteeringManager.SteeringSeek(character.GetRelativeSimPosition(Target), 10);
|
||||||
}
|
}
|
||||||
if (!insideSteering)
|
if (!insideSteering && character.CurrentHull == null)
|
||||||
{
|
{
|
||||||
SteeringManager.SteeringAvoid(deltaTime, lookAheadDistance: 5, weight: 1);
|
SteeringManager.SteeringAvoid(deltaTime, lookAheadDistance: 5, weight: 1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -293,7 +293,7 @@ namespace Barotrauma
|
|||||||
newObjective = new AIObjectiveOperateItem(order.TargetItemComponent, character, this, option, requireEquip: false, useController: order.UseController, priorityModifier: priorityModifier)
|
newObjective = new AIObjectiveOperateItem(order.TargetItemComponent, character, this, option, requireEquip: false, useController: order.UseController, priorityModifier: priorityModifier)
|
||||||
{
|
{
|
||||||
IsLoop = true,
|
IsLoop = true,
|
||||||
// Don't override auto pilot unless it's an order by a player
|
// Don't override unless it's an order by a player
|
||||||
Override = orderGiver == Character.Controlled || orderGiver.IsRemotePlayer
|
Override = orderGiver == Character.Controlled || orderGiver.IsRemotePlayer
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
@@ -302,7 +302,7 @@ namespace Barotrauma
|
|||||||
newObjective = new AIObjectiveOperateItem(order.TargetItemComponent, character, this, option, requireEquip: false, useController: order.UseController, priorityModifier: priorityModifier)
|
newObjective = new AIObjectiveOperateItem(order.TargetItemComponent, character, this, option, requireEquip: false, useController: order.UseController, priorityModifier: priorityModifier)
|
||||||
{
|
{
|
||||||
IsLoop = true,
|
IsLoop = true,
|
||||||
// Don't override auto control unless it's an order by a player
|
// Don't override unless it's an order by a player
|
||||||
Override = orderGiver == Character.Controlled || orderGiver.IsRemotePlayer
|
Override = orderGiver == Character.Controlled || orderGiver.IsRemotePlayer
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ namespace Barotrauma
|
|||||||
public Entity OperateTarget => operateTarget;
|
public Entity OperateTarget => operateTarget;
|
||||||
public ItemComponent Component => component;
|
public ItemComponent Component => component;
|
||||||
|
|
||||||
|
public ItemComponent GetTarget() => useController ? controller : component;
|
||||||
|
|
||||||
public Func<bool> completionCondition;
|
public Func<bool> completionCondition;
|
||||||
|
|
||||||
public override float GetPriority()
|
public override float GetPriority()
|
||||||
@@ -35,6 +37,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
if (component.Item.CurrentHull == null) { return 0; }
|
if (component.Item.CurrentHull == null) { return 0; }
|
||||||
if (component.Item.CurrentHull.FireSources.Count > 0) { return 0; }
|
if (component.Item.CurrentHull.FireSources.Count > 0) { return 0; }
|
||||||
|
if (IsOperatedByAnother(GetTarget())) { return 0; }
|
||||||
if (Character.CharacterList.Any(c => c.CurrentHull == component.Item.CurrentHull && !HumanAIController.IsFriendly(c) && HumanAIController.IsActive(c))) { return 0; }
|
if (Character.CharacterList.Any(c => c.CurrentHull == component.Item.CurrentHull && !HumanAIController.IsFriendly(c) && HumanAIController.IsActive(c))) { return 0; }
|
||||||
float devotion = MathHelper.Min(10, Priority);
|
float devotion = MathHelper.Min(10, Priority);
|
||||||
float value = devotion + AIObjectiveManager.OrderPriority * PriorityModifier;
|
float value = devotion + AIObjectiveManager.OrderPriority * PriorityModifier;
|
||||||
@@ -58,6 +61,45 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool IsOperatedByAnother(ItemComponent target)
|
||||||
|
{
|
||||||
|
foreach (var c in Character.CharacterList)
|
||||||
|
{
|
||||||
|
if (c == character) { continue; }
|
||||||
|
if (!HumanAIController.IsFriendly(c)) { continue; }
|
||||||
|
if (c.SelectedConstruction != target.Item) { continue; }
|
||||||
|
// If the other character is player, don't try to operate
|
||||||
|
if (c.IsRemotePlayer || Character.Controlled == c) { return true; }
|
||||||
|
if (c.AIController is HumanAIController humanAi)
|
||||||
|
{
|
||||||
|
// If the other character is ordered to operate the item, let him do it
|
||||||
|
if (humanAi.ObjectiveManager.IsCurrentOrder<AIObjectiveOperateItem>())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (target is Steering)
|
||||||
|
{
|
||||||
|
// Steering is hard-coded -> cannot use the required skills collection defined in the xml
|
||||||
|
return character.GetSkillLevel("helm") <= c.GetSkillLevel("helm");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return target.DegreeOfSuccess(character) <= target.DegreeOfSuccess(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Shouldn't go here, unless we allow non-humans to operate items
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
protected override void Act(float deltaTime)
|
protected override void Act(float deltaTime)
|
||||||
{
|
{
|
||||||
if (character.LockHands)
|
if (character.LockHands)
|
||||||
@@ -65,24 +107,24 @@ namespace Barotrauma
|
|||||||
Abandon = true;
|
Abandon = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ItemComponent target = useController ? controller : component;
|
ItemComponent target = GetTarget();
|
||||||
if (useController && controller == null)
|
if (useController && controller == null)
|
||||||
{
|
{
|
||||||
character.Speak(TextManager.GetWithVariable("DialogCantFindController", "[item]", component.Item.Name, true), null, 2.0f, "cantfindcontroller", 30.0f);
|
character.Speak(TextManager.GetWithVariable("DialogCantFindController", "[item]", component.Item.Name, true), null, 2.0f, "cantfindcontroller", 30.0f);
|
||||||
Abandon = true;
|
Abandon = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// Don't allow to operate an item that someone with a better skills already operates, unless this is an order
|
||||||
|
if (objectiveManager.CurrentOrder != this && IsOperatedByAnother(target))
|
||||||
|
{
|
||||||
|
// Don't abandon
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (target.CanBeSelected)
|
if (target.CanBeSelected)
|
||||||
{
|
{
|
||||||
if (character.CanInteractWith(target.Item, out _, checkLinked: false))
|
if (character.CanInteractWith(target.Item, out _, checkLinked: false))
|
||||||
{
|
{
|
||||||
HumanAIController.FaceTarget(target.Item);
|
HumanAIController.FaceTarget(target.Item);
|
||||||
// Don't allow to operate an item that someone already operates, unless this objective is an order
|
|
||||||
if (objectiveManager.CurrentOrder != this && Character.CharacterList.Any(c => c.SelectedConstruction == target.Item && c != character && HumanAIController.IsFriendly(c) && HumanAIController.IsActive(c)))
|
|
||||||
{
|
|
||||||
// Don't abandon
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (character.SelectedConstruction != target.Item)
|
if (character.SelectedConstruction != target.Item)
|
||||||
{
|
{
|
||||||
target.Item.TryInteract(character, false, true);
|
target.Item.TryInteract(character, false, true);
|
||||||
|
|||||||
@@ -764,12 +764,17 @@ namespace Barotrauma
|
|||||||
.Where(p => p.AfflictionType == "huskinfection")
|
.Where(p => p.AfflictionType == "huskinfection")
|
||||||
.Select(p => p as AfflictionPrefabHusk)
|
.Select(p => p as AfflictionPrefabHusk)
|
||||||
.FirstOrDefault(p => p.TargetSpecies.Any(t => t.Equals(AfflictionHusk.GetNonHuskedSpeciesName(speciesName, p), StringComparison.InvariantCultureIgnoreCase)));
|
.FirstOrDefault(p => p.TargetSpecies.Any(t => t.Equals(AfflictionHusk.GetNonHuskedSpeciesName(speciesName, p), StringComparison.InvariantCultureIgnoreCase)));
|
||||||
|
string nonHuskedSpeciesName = string.Empty;
|
||||||
if (matchingAffliction == null)
|
if (matchingAffliction == null)
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError("Cannot find a husk infection that matches this species! Please add the speciesnames as 'targets' in the husk affliction prefab definition!");
|
DebugConsole.ThrowError("Cannot find a husk infection that matches this species! Please add the speciesnames as 'targets' in the husk affliction prefab definition!");
|
||||||
return;
|
// Crashes if we fail to create a ragdoll -> Let's just use some ragdoll so that the user sees the error msg.
|
||||||
|
nonHuskedSpeciesName = IsHumanoid ? HumanSpeciesName : "crawler";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nonHuskedSpeciesName = AfflictionHusk.GetNonHuskedSpeciesName(speciesName, matchingAffliction);
|
||||||
}
|
}
|
||||||
string nonHuskedSpeciesName = AfflictionHusk.GetNonHuskedSpeciesName(speciesName, matchingAffliction);
|
|
||||||
ragdollParams = IsHumanoid ? RagdollParams.GetDefaultRagdollParams<HumanRagdollParams>(nonHuskedSpeciesName) : RagdollParams.GetDefaultRagdollParams<FishRagdollParams>(nonHuskedSpeciesName) as RagdollParams;
|
ragdollParams = IsHumanoid ? RagdollParams.GetDefaultRagdollParams<HumanRagdollParams>(nonHuskedSpeciesName) : RagdollParams.GetDefaultRagdollParams<FishRagdollParams>(nonHuskedSpeciesName) as RagdollParams;
|
||||||
if (info == null)
|
if (info == null)
|
||||||
{
|
{
|
||||||
@@ -1912,7 +1917,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (findFocusedTimer <= 0.0f || Screen.Selected == GameMain.SubEditorScreen)
|
if (findFocusedTimer <= 0.0f || Screen.Selected == GameMain.SubEditorScreen)
|
||||||
{
|
{
|
||||||
focusedCharacter = FindCharacterAtPosition(mouseSimPos);
|
focusedCharacter = CanInteract ? FindCharacterAtPosition(mouseSimPos) : null;
|
||||||
focusedItem = CanInteract ?
|
focusedItem = CanInteract ?
|
||||||
FindItemAtPosition(mouseSimPos, GameMain.Config.AimAssistAmount * (AnimController.InWater ? 1.5f : 1.0f)) : null;
|
FindItemAtPosition(mouseSimPos, GameMain.Config.AimAssistAmount * (AnimController.InWater ? 1.5f : 1.0f)) : null;
|
||||||
findFocusedTimer = 0.05f;
|
findFocusedTimer = 0.05f;
|
||||||
@@ -1972,11 +1977,11 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
DeselectCharacter();
|
DeselectCharacter();
|
||||||
}
|
}
|
||||||
else if (focusedCharacter != null && IsKeyHit(InputType.Grab) && FocusedCharacter.CanBeDragged)
|
else if (focusedCharacter != null && IsKeyHit(InputType.Grab) && FocusedCharacter.CanBeDragged && CanInteract)
|
||||||
{
|
{
|
||||||
SelectCharacter(focusedCharacter);
|
SelectCharacter(focusedCharacter);
|
||||||
}
|
}
|
||||||
else if (focusedCharacter != null && IsKeyHit(InputType.Health) && focusedCharacter.CharacterHealth.UseHealthWindow && CanInteractWith(focusedCharacter, 160f, false))
|
else if (focusedCharacter != null && IsKeyHit(InputType.Health) && focusedCharacter.CharacterHealth.UseHealthWindow && CanInteract && CanInteractWith(focusedCharacter, 160f, false))
|
||||||
{
|
{
|
||||||
if (focusedCharacter == SelectedCharacter)
|
if (focusedCharacter == SelectedCharacter)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -289,7 +289,7 @@ namespace Barotrauma
|
|||||||
public static string GetNonHuskedSpeciesName(string huskedSpeciesName, AfflictionPrefabHusk prefab)
|
public static string GetNonHuskedSpeciesName(string huskedSpeciesName, AfflictionPrefabHusk prefab)
|
||||||
{
|
{
|
||||||
string nonTag = prefab.HuskedSpeciesName.Remove(AfflictionPrefabHusk.Tag);
|
string nonTag = prefab.HuskedSpeciesName.Remove(AfflictionPrefabHusk.Tag);
|
||||||
return huskedSpeciesName.Remove(nonTag);
|
return huskedSpeciesName.ToLowerInvariant().Remove(nonTag);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
public AfflictionPrefabHusk(XElement element, Type type = null) : base(element, type)
|
public AfflictionPrefabHusk(XElement element, Type type = null) : base(element, type)
|
||||||
{
|
{
|
||||||
HuskedSpeciesName = element.GetAttributeString("huskedspeciesname", null);
|
HuskedSpeciesName = element.GetAttributeString("huskedspeciesname", null).ToLowerInvariant();
|
||||||
if (HuskedSpeciesName == null)
|
if (HuskedSpeciesName == null)
|
||||||
{
|
{
|
||||||
DebugConsole.NewMessage($"No 'huskedspeciesname' defined for the husk affliction ({Identifier}) in {element.ToString()}", Color.Orange);
|
DebugConsole.NewMessage($"No 'huskedspeciesname' defined for the husk affliction ({Identifier}) in {element.ToString()}", Color.Orange);
|
||||||
|
|||||||
@@ -85,7 +85,11 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public override void Update(float deltaTime)
|
public override void Update(float deltaTime)
|
||||||
{
|
{
|
||||||
if (IsClient) { return; }
|
if (IsClient)
|
||||||
|
{
|
||||||
|
if (item.ParentInventory != null) { item.body.FarseerBody.IsKinematic = false; }
|
||||||
|
return;
|
||||||
|
}
|
||||||
switch (State)
|
switch (State)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
|
|||||||
@@ -296,10 +296,11 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
#if DEBUG
|
return false;
|
||||||
|
/*#if DEBUG
|
||||||
return false;
|
return false;
|
||||||
#endif
|
#endif
|
||||||
return sendUserStatistics;
|
return sendUserStatistics;*/
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -25,7 +25,18 @@ namespace Barotrauma.Items.Components
|
|||||||
private readonly bool autoOrientGap;
|
private readonly bool autoOrientGap;
|
||||||
|
|
||||||
private bool isStuck;
|
private bool isStuck;
|
||||||
public bool IsStuck => isStuck;
|
public bool IsStuck
|
||||||
|
{
|
||||||
|
get { return isStuck; }
|
||||||
|
private set
|
||||||
|
{
|
||||||
|
if (isStuck == value) { return; }
|
||||||
|
isStuck = value;
|
||||||
|
#if SERVER
|
||||||
|
item.CreateServerEvent(this);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private float resetPredictionTimer;
|
private float resetPredictionTimer;
|
||||||
|
|
||||||
@@ -69,8 +80,8 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
if (isOpen || isBroken || !CanBeWelded) return;
|
if (isOpen || isBroken || !CanBeWelded) return;
|
||||||
stuck = MathHelper.Clamp(value, 0.0f, 100.0f);
|
stuck = MathHelper.Clamp(value, 0.0f, 100.0f);
|
||||||
if (stuck <= 0.0f) isStuck = false;
|
if (stuck <= 0.0f) { IsStuck = false; }
|
||||||
if (stuck >= 100.0f) isStuck = true;
|
if (stuck >= 100.0f) { IsStuck = true; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -296,7 +307,7 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool isClosing = false;
|
bool isClosing = false;
|
||||||
if (!isStuck)
|
if (!IsStuck)
|
||||||
{
|
{
|
||||||
if (PredictedState == null)
|
if (PredictedState == null)
|
||||||
{
|
{
|
||||||
@@ -541,7 +552,7 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0.0f, float signalStrength = 1.0f)
|
public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0.0f, float signalStrength = 1.0f)
|
||||||
{
|
{
|
||||||
if (isStuck) return;
|
if (IsStuck) return;
|
||||||
|
|
||||||
bool wasOpen = PredictedState == null ? isOpen : PredictedState.Value;
|
bool wasOpen = PredictedState == null ? isOpen : PredictedState.Value;
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
partial class ElectricalDischarger : Powered
|
partial class ElectricalDischarger : Powered
|
||||||
{
|
{
|
||||||
private static List<ElectricalDischarger> list = new List<ElectricalDischarger>();
|
private static readonly List<ElectricalDischarger> list = new List<ElectricalDischarger>();
|
||||||
public static IEnumerable<ElectricalDischarger> List
|
public static IEnumerable<ElectricalDischarger> List
|
||||||
{
|
{
|
||||||
get { return list; }
|
get { return list; }
|
||||||
@@ -48,14 +48,14 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Serialize(100.0f, true, description: "How far the discharge can travel from the item."), Editable(MinValueFloat = 0.0f, MaxValueFloat = 5000.0f)]
|
[Serialize(500.0f, true, description: "How far the discharge can travel from the item."), Editable(MinValueFloat = 0.0f, MaxValueFloat = 5000.0f)]
|
||||||
public float Range
|
public float Range
|
||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
set;
|
set;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Serialize(10.0f, true, description: "How much further can the discharge be carried when moving across walls."), Editable(MinValueFloat = 0.0f, MaxValueFloat = 1000.0f)]
|
[Serialize(25.0f, true, description: "How much further can the discharge be carried when moving across walls."), Editable(MinValueFloat = 0.0f, MaxValueFloat = 1000.0f)]
|
||||||
public float RangeMultiplierInWalls
|
public float RangeMultiplierInWalls
|
||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
@@ -127,20 +127,42 @@ namespace Barotrauma.Items.Components
|
|||||||
#if CLIENT
|
#if CLIENT
|
||||||
frameOffset = Rand.Int(electricitySprite.FrameCount);
|
frameOffset = Rand.Int(electricitySprite.FrameCount);
|
||||||
#endif
|
#endif
|
||||||
if (timer > 0.0f)
|
if (timer <= 0.0f)
|
||||||
{
|
|
||||||
if (charging)
|
|
||||||
{
|
|
||||||
if (Voltage > MinVoltage)
|
|
||||||
{
|
|
||||||
Discharge();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
timer -= deltaTime;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
IsActive = false;
|
IsActive = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
timer -= deltaTime;
|
||||||
|
if (charging)
|
||||||
|
{
|
||||||
|
if (GetAvailableBatteryPower() >= powerConsumption)
|
||||||
|
{
|
||||||
|
var batteries = item.GetConnectedComponents<PowerContainer>();
|
||||||
|
float neededPower = powerConsumption;
|
||||||
|
while (neededPower > 0.0001f && batteries.Count > 0)
|
||||||
|
{
|
||||||
|
batteries.RemoveAll(b => b.Charge <= 0.0001f || b.MaxOutPut <= 0.0001f);
|
||||||
|
float takePower = neededPower / batteries.Count;
|
||||||
|
takePower = Math.Min(takePower, batteries.Min(b => Math.Min(b.Charge * 3600.0f, b.MaxOutPut)));
|
||||||
|
foreach (PowerContainer battery in batteries)
|
||||||
|
{
|
||||||
|
neededPower -= takePower;
|
||||||
|
battery.Charge -= takePower / 3600.0f;
|
||||||
|
#if SERVER
|
||||||
|
if (GameMain.Server != null)
|
||||||
|
{
|
||||||
|
battery.Item.CreateServerEvent(battery);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Discharge();
|
||||||
|
}
|
||||||
|
else if (Voltage > MinVoltage)
|
||||||
|
{
|
||||||
|
Discharge();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ namespace Barotrauma.Items.Components
|
|||||||
//TODO: refactor the hitting logic (get rid of the magic numbers, make it possible to use different kinds of animations for different items)
|
//TODO: refactor the hitting logic (get rid of the magic numbers, make it possible to use different kinds of animations for different items)
|
||||||
if (!hitting)
|
if (!hitting)
|
||||||
{
|
{
|
||||||
bool aim = picker.IsKeyDown(InputType.Aim) && reloadTimer <= 0 && (picker.SelectedConstruction == null || picker.SelectedConstruction.GetComponent<Ladder>() != null);
|
bool aim = picker.AllowInput && picker.IsKeyDown(InputType.Aim) && reloadTimer <= 0 && (picker.SelectedConstruction == null || picker.SelectedConstruction.GetComponent<Ladder>() != null);
|
||||||
if (aim)
|
if (aim)
|
||||||
{
|
{
|
||||||
hitPos = MathUtils.WrapAnglePi(Math.Min(hitPos + deltaTime * 5f, MathHelper.PiOver4));
|
hitPos = MathUtils.WrapAnglePi(Math.Min(hitPos + deltaTime * 5f, MathHelper.PiOver4));
|
||||||
|
|||||||
@@ -96,11 +96,14 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
useState -= deltaTime;
|
useState -= deltaTime;
|
||||||
|
|
||||||
if (useState <= 0.0f) IsActive = false;
|
if (useState <= 0.0f)
|
||||||
|
|
||||||
if (item.AiTarget != null)
|
|
||||||
{
|
{
|
||||||
item.AiTarget.SoundRange = IsActive ? item.AiTarget.MaxSoundRange : item.AiTarget.MinSoundRange;
|
IsActive = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.AiTarget != null && IsActive)
|
||||||
|
{
|
||||||
|
item.AiTarget.SoundRange = item.AiTarget.MaxSoundRange;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -399,7 +399,7 @@ namespace Barotrauma.Items.Components
|
|||||||
case "activate":
|
case "activate":
|
||||||
case "use":
|
case "use":
|
||||||
case "trigger_in":
|
case "trigger_in":
|
||||||
item.Use(1.0f);
|
item.Use(1.0f, sender);
|
||||||
break;
|
break;
|
||||||
case "toggle":
|
case "toggle":
|
||||||
if (signal != "0")
|
if (signal != "0")
|
||||||
@@ -669,7 +669,7 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ApplyStatusEffects(ActionType type, float deltaTime, Character character = null, Limb targetLimb = null, Character user = null)
|
public void ApplyStatusEffects(ActionType type, float deltaTime, Character character = null, Limb targetLimb = null, Entity useTarget = null, Character user = null, Vector2? worldPosition = null)
|
||||||
{
|
{
|
||||||
if (statusEffectLists == null) return;
|
if (statusEffectLists == null) return;
|
||||||
|
|
||||||
@@ -680,20 +680,24 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
if (broken && effect.type != ActionType.OnBroken) { continue; }
|
if (broken && effect.type != ActionType.OnBroken) { continue; }
|
||||||
if (user != null) { effect.SetUser(user); }
|
if (user != null) { effect.SetUser(user); }
|
||||||
item.ApplyStatusEffect(effect, type, deltaTime, character, targetLimb, false, false);
|
item.ApplyStatusEffect(effect, type, deltaTime, character, targetLimb, useTarget, false, false, worldPosition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void Load(XElement componentElement, bool usePrefabValues)
|
public virtual void Load(XElement componentElement, bool usePrefabValues)
|
||||||
{
|
{
|
||||||
if (componentElement == null || usePrefabValues) { return; }
|
if (componentElement != null && !usePrefabValues)
|
||||||
foreach (XAttribute attribute in componentElement.Attributes())
|
|
||||||
{
|
{
|
||||||
if (!SerializableProperties.TryGetValue(attribute.Name.ToString().ToLowerInvariant(), out SerializableProperty property)) continue;
|
foreach (XAttribute attribute in componentElement.Attributes())
|
||||||
property.TrySetValue(this, attribute.Value);
|
{
|
||||||
|
if (!SerializableProperties.TryGetValue(attribute.Name.ToString().ToLowerInvariant(), out SerializableProperty property)) continue;
|
||||||
|
property.TrySetValue(this, attribute.Value);
|
||||||
|
}
|
||||||
|
ParseMsg();
|
||||||
|
OverrideRequiredItems(componentElement);
|
||||||
}
|
}
|
||||||
ParseMsg();
|
|
||||||
OverrideRequiredItems(componentElement);
|
if (item.Submarine != null) { SerializableProperty.UpgradeGameVersion(this, originalElement, item.Submarine.GameVersion); }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -123,9 +123,9 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
if (user.AnimController.InWater)
|
if (user.AnimController.InWater)
|
||||||
{
|
{
|
||||||
if (diff.Length() > 30.0f)
|
if (diff.LengthSquared() > 30.0f * 30.0f)
|
||||||
{
|
{
|
||||||
user.AnimController.TargetMovement = Vector2.Clamp(diff*0.01f, -Vector2.One, Vector2.One);
|
user.AnimController.TargetMovement = Vector2.Clamp(diff * 0.01f, -Vector2.One, Vector2.One);
|
||||||
user.AnimController.TargetDir = diff.X > 0.0f ? Direction.Right : Direction.Left;
|
user.AnimController.TargetDir = diff.X > 0.0f ? Direction.Right : Direction.Left;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -136,11 +136,29 @@ namespace Barotrauma.Items.Components
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
diff.Y = 0.0f;
|
diff.Y = 0.0f;
|
||||||
if (diff != Vector2.Zero && diff.LengthSquared() > 10.0f * 10.0f)
|
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient && user != Character.Controlled)
|
||||||
{
|
{
|
||||||
user.AnimController.TargetMovement = Vector2.Normalize(diff);
|
if (Math.Abs(diff.X) > 20.0f)
|
||||||
user.AnimController.TargetDir = diff.X > 0.0f ? Direction.Right : Direction.Left;
|
{
|
||||||
return;
|
//wait for the character to walk to the correct position
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (Math.Abs(diff.X) > 0.1f)
|
||||||
|
{
|
||||||
|
//aim to keep the collider at the correct position once close enough
|
||||||
|
user.AnimController.Collider.LinearVelocity = new Vector2(
|
||||||
|
diff.X * 0.1f,
|
||||||
|
user.AnimController.Collider.LinearVelocity.Y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (Math.Abs(diff.X) > 10.0f)
|
||||||
|
{
|
||||||
|
user.AnimController.TargetMovement = Vector2.Normalize(diff);
|
||||||
|
user.AnimController.TargetDir = diff.X > 0.0f ? Direction.Right : Direction.Left;
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
user.AnimController.TargetMovement = Vector2.Zero;
|
user.AnimController.TargetMovement = Vector2.Zero;
|
||||||
}
|
}
|
||||||
@@ -293,7 +311,7 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
private void CancelUsing(Character character)
|
private void CancelUsing(Character character)
|
||||||
{
|
{
|
||||||
if (character == null || character.Removed) return;
|
if (character == null || character.Removed) { return; }
|
||||||
|
|
||||||
foreach (LimbPos lb in limbPositions)
|
foreach (LimbPos lb in limbPositions)
|
||||||
{
|
{
|
||||||
@@ -304,18 +322,21 @@ namespace Barotrauma.Items.Components
|
|||||||
limb.PullJointEnabled = false;
|
limb.PullJointEnabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (character.SelectedConstruction == this.item) character.SelectedConstruction = null;
|
if (character.SelectedConstruction == this.item) { character.SelectedConstruction = null; }
|
||||||
|
|
||||||
character.AnimController.Anim = AnimController.Animation.None;
|
character.AnimController.Anim = AnimController.Animation.None;
|
||||||
if (character == Character.Controlled)
|
if (character == Character.Controlled)
|
||||||
{
|
{
|
||||||
HideHUDs(false);
|
HideHUDs(false);
|
||||||
}
|
}
|
||||||
|
#if SERVER
|
||||||
|
item.CreateServerEvent(this);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Select(Character activator)
|
public override bool Select(Character activator)
|
||||||
{
|
{
|
||||||
if (activator == null || activator.Removed) return false;
|
if (activator == null || activator.Removed) { return false; }
|
||||||
|
|
||||||
//someone already using the item
|
//someone already using the item
|
||||||
if (user != null && !user.Removed)
|
if (user != null && !user.Removed)
|
||||||
@@ -333,7 +354,9 @@ namespace Barotrauma.Items.Components
|
|||||||
user = activator;
|
user = activator;
|
||||||
IsActive = true;
|
IsActive = true;
|
||||||
}
|
}
|
||||||
|
#if SERVER
|
||||||
|
item.CreateServerEvent(this);
|
||||||
|
#endif
|
||||||
item.SendSignal(0, "1", "signal_out", user);
|
item.SendSignal(0, "1", "signal_out", user);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
if (item.CurrentHull == null) { return; }
|
if (item.CurrentHull == null) { return; }
|
||||||
|
|
||||||
float powerFactor = currPowerConsumption <= 0.0f ? 1.0f : Voltage;
|
float powerFactor = Math.Min(currPowerConsumption <= 0.0f ? 1.0f : Voltage, 1.0f);
|
||||||
|
|
||||||
currFlow = flowPercentage / 100.0f * maxFlow * powerFactor;
|
currFlow = flowPercentage / 100.0f * maxFlow * powerFactor;
|
||||||
//less effective when in a bad condition
|
//less effective when in a bad condition
|
||||||
|
|||||||
@@ -640,9 +640,15 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lastUser != character && lastUser != null && lastUser.SelectedConstruction == item)
|
if (objective.Override)
|
||||||
{
|
{
|
||||||
character.Speak(TextManager.Get("DialogReactorTaken"), null, 0.0f, "reactortaken", 10.0f);
|
if (lastUser != null && lastUser != character && lastUser != lastAIUser)
|
||||||
|
{
|
||||||
|
if (lastUser.SelectedConstruction == item)
|
||||||
|
{
|
||||||
|
character.Speak(TextManager.Get("DialogReactorTaken"), null, 0.0f, "reactortaken", 10.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LastUser = lastAIUser = character;
|
LastUser = lastAIUser = character;
|
||||||
|
|||||||
@@ -479,9 +479,12 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
public override bool AIOperate(float deltaTime, Character character, AIObjectiveOperateItem objective)
|
public override bool AIOperate(float deltaTime, Character character, AIObjectiveOperateItem objective)
|
||||||
{
|
{
|
||||||
if (user != character && user != null && user.SelectedConstruction == item)
|
if (objective.Override)
|
||||||
{
|
{
|
||||||
character.Speak(TextManager.Get("DialogSteeringTaken"), null, 0.0f, "steeringtaken", 10.0f);
|
if (user != character && user != null && user.SelectedConstruction == item)
|
||||||
|
{
|
||||||
|
character.Speak(TextManager.Get("DialogSteeringTaken"), null, 0.0f, "steeringtaken", 10.0f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
user = character;
|
user = character;
|
||||||
if (!AutoPilot)
|
if (!AutoPilot)
|
||||||
|
|||||||
@@ -175,10 +175,9 @@ namespace Barotrauma.Items.Components
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
currPowerConsumption = MathHelper.Lerp(currPowerConsumption, rechargeSpeed, 0.05f);
|
currPowerConsumption = MathHelper.Lerp(currPowerConsumption, rechargeSpeed, 0.05f);
|
||||||
Charge += currPowerConsumption * Voltage / 3600.0f;
|
Charge += currPowerConsumption * Math.Min(Voltage, 1.0f) / 3600.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (charge <= 0.0f)
|
if (charge <= 0.0f)
|
||||||
{
|
{
|
||||||
CurrPowerOutput = 0.0f;
|
CurrPowerOutput = 0.0f;
|
||||||
|
|||||||
@@ -280,6 +280,8 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
//we've already received this signal
|
//we've already received this signal
|
||||||
if (lastPowerProbeRecipients.Contains(this)) { return; }
|
if (lastPowerProbeRecipients.Contains(this)) { return; }
|
||||||
|
if (item.Condition <= 0.0f) { return; }
|
||||||
|
|
||||||
lastPowerProbeRecipients.Add(this);
|
lastPowerProbeRecipients.Add(this);
|
||||||
|
|
||||||
if (power < 0.0f)
|
if (power < 0.0f)
|
||||||
@@ -306,15 +308,15 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
foreach (ItemComponent ic in recipient.Item.Components)
|
foreach (ItemComponent ic in recipient.Item.Components)
|
||||||
{
|
{
|
||||||
//powertransfer components don't need to receive the signal in the pass-through signal connections
|
//other junction boxes don't need to receive the signal in the pass-through signal connections
|
||||||
//because we relay it straight to the connected items without going through the whole chain of junction boxes
|
//because we relay it straight to the connected items without going through the whole chain of junction boxes
|
||||||
if (ic is PowerTransfer && connection.Name.Contains("signal")) { continue; }
|
if (ic is PowerTransfer && !(ic is RelayComponent) && connection.Name.Contains("signal")) { continue; }
|
||||||
ic.ReceiveSignal(stepsTaken, signal, recipient, source, sender, 0.0f, signalStrength);
|
ic.ReceiveSignal(stepsTaken, signal, recipient, source, sender, 0.0f, signalStrength);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (StatusEffect effect in recipient.Effects)
|
foreach (StatusEffect effect in recipient.Effects)
|
||||||
{
|
{
|
||||||
recipient.Item.ApplyStatusEffect(effect, ActionType.OnUse, 1.0f, null, null, false, false);
|
recipient.Item.ApplyStatusEffect(effect, ActionType.OnUse, 1.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -279,13 +279,30 @@ namespace Barotrauma.Items.Components
|
|||||||
var pc = powerSource.Item.GetComponent<PowerContainer>();
|
var pc = powerSource.Item.GetComponent<PowerContainer>();
|
||||||
if (pc != null)
|
if (pc != null)
|
||||||
{
|
{
|
||||||
float voltage = -pc.CurrPowerOutput / Math.Max(powered.CurrPowerConsumption, 1.0f);
|
float voltage = pc.CurrPowerOutput / Math.Max(powered.CurrPowerConsumption, 1.0f);
|
||||||
powered.voltage += voltage;
|
powered.voltage += voltage;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the amount of power that can be supplied by batteries directly connected to the item
|
||||||
|
/// </summary>
|
||||||
|
protected float GetAvailableBatteryPower()
|
||||||
|
{
|
||||||
|
var batteries = item.GetConnectedComponents<PowerContainer>();
|
||||||
|
|
||||||
|
float availablePower = 0.0f;
|
||||||
|
foreach (PowerContainer battery in batteries)
|
||||||
|
{
|
||||||
|
float batteryPower = Math.Min(battery.Charge * 3600.0f, battery.MaxOutPut);
|
||||||
|
availablePower += batteryPower;
|
||||||
|
}
|
||||||
|
|
||||||
|
return availablePower;
|
||||||
|
}
|
||||||
|
|
||||||
protected override void RemoveComponentSpecific()
|
protected override void RemoveComponentSpecific()
|
||||||
{
|
{
|
||||||
poweredList.Remove(this);
|
poweredList.Remove(this);
|
||||||
|
|||||||
@@ -458,6 +458,11 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
if (character != null) { character.LastDamageSource = item; }
|
if (character != null) { character.LastDamageSource = item; }
|
||||||
|
|
||||||
|
#if CLIENT
|
||||||
|
PlaySound(ActionType.OnUse, item.WorldPosition, user: user);
|
||||||
|
PlaySound(ActionType.OnImpact, item.WorldPosition, user: user);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (GameMain.NetworkMember == null || GameMain.NetworkMember.IsServer)
|
if (GameMain.NetworkMember == null || GameMain.NetworkMember.IsServer)
|
||||||
{
|
{
|
||||||
if (target.Body.UserData is Limb targetLimb)
|
if (target.Body.UserData is Limb targetLimb)
|
||||||
@@ -489,14 +494,26 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
#if SERVER
|
#if SERVER
|
||||||
if (GameMain.NetworkMember.IsServer)
|
if (GameMain.NetworkMember.IsServer)
|
||||||
{
|
{
|
||||||
GameMain.Server?.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.ApplyStatusEffect, ActionType.OnUse });
|
GameMain.Server?.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.ApplyStatusEffect, ActionType.OnUse, this, targetLimb.character.ID, targetLimb, (ushort)0, item.WorldPosition });
|
||||||
GameMain.Server?.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.ApplyStatusEffect, ActionType.OnImpact });
|
GameMain.Server?.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.ApplyStatusEffect, ActionType.OnImpact, this, targetLimb.character.ID, targetLimb, (ushort)0, item.WorldPosition });
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ApplyStatusEffects(ActionType.OnUse, 1.0f, useTarget: target.Body.UserData as Entity, user: user);
|
||||||
|
ApplyStatusEffects(ActionType.OnImpact, 1.0f, useTarget: target.Body.UserData as Entity, user: user);
|
||||||
|
#if SERVER
|
||||||
|
if (GameMain.NetworkMember.IsServer)
|
||||||
|
{
|
||||||
|
GameMain.Server?.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.ApplyStatusEffect, ActionType.OnUse, this, (ushort)0, null, (target.Body.UserData as Entity)?.ID ?? 0, item.WorldPosition });
|
||||||
|
GameMain.Server?.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.ApplyStatusEffect, ActionType.OnImpact, this, (ushort)0, null, (target.Body.UserData as Entity)?.ID ?? 0, item.WorldPosition });
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
item.body.FarseerBody.OnCollision -= OnProjectileCollision;
|
item.body.FarseerBody.OnCollision -= OnProjectileCollision;
|
||||||
|
|||||||
@@ -130,6 +130,12 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
#if SERVER
|
||||||
|
if (CurrentFixer != character || currentFixerAction != action)
|
||||||
|
{
|
||||||
|
item.CreateServerEvent(this);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
CurrentFixer = character;
|
CurrentFixer = character;
|
||||||
CurrentFixerAction = action;
|
CurrentFixerAction = action;
|
||||||
return true;
|
return true;
|
||||||
@@ -140,12 +146,15 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
if (CurrentFixer == character)
|
if (CurrentFixer == character)
|
||||||
{
|
{
|
||||||
|
#if SERVER
|
||||||
|
if (CurrentFixer != character || currentFixerAction != FixActions.None)
|
||||||
|
{
|
||||||
|
item.CreateServerEvent(this);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
CurrentFixer.AnimController.Anim = AnimController.Animation.None;
|
CurrentFixer.AnimController.Anim = AnimController.Animation.None;
|
||||||
CurrentFixer = null;
|
CurrentFixer = null;
|
||||||
currentFixerAction = FixActions.None;
|
currentFixerAction = FixActions.None;
|
||||||
#if SERVER
|
|
||||||
item.CreateServerEvent(this);
|
|
||||||
#endif
|
|
||||||
#if CLIENT
|
#if CLIENT
|
||||||
repairSoundChannel?.FadeOutAndDispose();
|
repairSoundChannel?.FadeOutAndDispose();
|
||||||
repairSoundChannel = null;
|
repairSoundChannel = null;
|
||||||
@@ -214,16 +223,16 @@ namespace Barotrauma.Items.Components
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UpdateFixAnimation(CurrentFixer);
|
||||||
|
|
||||||
|
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) { return; }
|
||||||
|
|
||||||
if (CurrentFixer != null && (CurrentFixer.SelectedConstruction != item || !CurrentFixer.CanInteractWith(item) || CurrentFixer.IsDead))
|
if (CurrentFixer != null && (CurrentFixer.SelectedConstruction != item || !CurrentFixer.CanInteractWith(item) || CurrentFixer.IsDead))
|
||||||
{
|
{
|
||||||
StopRepairing(CurrentFixer);
|
StopRepairing(CurrentFixer);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateFixAnimation(CurrentFixer);
|
|
||||||
|
|
||||||
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) { return; }
|
|
||||||
|
|
||||||
float successFactor = requiredSkills.Count == 0 ? 1.0f : DegreeOfSuccess(CurrentFixer, requiredSkills);
|
float successFactor = requiredSkills.Count == 0 ? 1.0f : DegreeOfSuccess(CurrentFixer, requiredSkills);
|
||||||
|
|
||||||
//item must have been below the repair threshold 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
|
||||||
|
|||||||
@@ -258,7 +258,7 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
foreach (StatusEffect effect in recipient.Effects)
|
foreach (StatusEffect effect in recipient.Effects)
|
||||||
{
|
{
|
||||||
recipient.Item.ApplyStatusEffect(effect, ActionType.OnUse, (float)Timing.Step, null, null, false, false);
|
recipient.Item.ApplyStatusEffect(effect, ActionType.OnUse, (float)Timing.Step);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,11 @@ namespace Barotrauma.Items.Components
|
|||||||
set { /*do nothing*/ }
|
set { /*do nothing*/ }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Character User
|
||||||
|
{
|
||||||
|
get { return user; }
|
||||||
|
}
|
||||||
|
|
||||||
public ConnectionPanel(Item item, XElement element)
|
public ConnectionPanel(Item item, XElement element)
|
||||||
: base(item, element)
|
: base(item, element)
|
||||||
{
|
{
|
||||||
@@ -126,6 +131,9 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
if (user == null || user.SelectedConstruction != item)
|
if (user == null || user.SelectedConstruction != item)
|
||||||
{
|
{
|
||||||
|
#if SERVER
|
||||||
|
if (user != null) { item.CreateServerEvent(this); }
|
||||||
|
#endif
|
||||||
user = null;
|
user = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -135,6 +143,11 @@ namespace Barotrauma.Items.Components
|
|||||||
user.AnimController.UpdateUseItem(true, item.WorldPosition + new Vector2(0.0f, 100.0f) * (((float)Timing.TotalTime / 10.0f) % 0.1f));
|
user.AnimController.UpdateUseItem(true, item.WorldPosition + new Vector2(0.0f, 100.0f) * (((float)Timing.TotalTime / 10.0f) % 0.1f));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void UpdateBroken(float deltaTime, Camera cam)
|
||||||
|
{
|
||||||
|
Update(deltaTime, cam);
|
||||||
|
}
|
||||||
|
|
||||||
partial void UpdateProjSpecific(float deltaTime);
|
partial void UpdateProjSpecific(float deltaTime);
|
||||||
|
|
||||||
public override bool Select(Character picker)
|
public override bool Select(Character picker)
|
||||||
@@ -147,13 +160,16 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
|
|
||||||
user = picker;
|
user = picker;
|
||||||
|
#if SERVER
|
||||||
|
if (user != null) { item.CreateServerEvent(this); }
|
||||||
|
#endif
|
||||||
IsActive = true;
|
IsActive = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Use(float deltaTime, Character character = null)
|
public override bool Use(float deltaTime, Character character = null)
|
||||||
{
|
{
|
||||||
if (character == null || character != user) return false;
|
if (character == null || character != user) { return false; }
|
||||||
|
|
||||||
var powered = item.GetComponent<Powered>();
|
var powered = item.GetComponent<Powered>();
|
||||||
if (powered != null)
|
if (powered != null)
|
||||||
@@ -257,6 +273,10 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
public void ClientWrite(IWriteMessage msg, object[] extraData = null)
|
public void ClientWrite(IWriteMessage msg, object[] extraData = null)
|
||||||
{
|
{
|
||||||
|
#if CLIENT
|
||||||
|
TriggerRewiringSound();
|
||||||
|
#endif
|
||||||
|
|
||||||
foreach (Connection connection in Connections)
|
foreach (Connection connection in Connections)
|
||||||
{
|
{
|
||||||
foreach (Wire wire in connection.Wires)
|
foreach (Wire wire in connection.Wires)
|
||||||
|
|||||||
@@ -172,7 +172,7 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
foreach (StatusEffect effect in ciElement.StatusEffects)
|
foreach (StatusEffect effect in ciElement.StatusEffects)
|
||||||
{
|
{
|
||||||
item.ApplyStatusEffect(effect, ciElement.State ? ActionType.OnUse : ActionType.OnSecondaryUse, 1.0f, null, null, true, false);
|
item.ApplyStatusEffect(effect, ciElement.State ? ActionType.OnUse : ActionType.OnSecondaryUse, 1.0f, null, null, null, true, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
range = MathHelper.Clamp(value, 0.0f, 4096.0f);
|
range = MathHelper.Clamp(value, 0.0f, 4096.0f);
|
||||||
#if CLIENT
|
#if CLIENT
|
||||||
if (light != null) light.Range = range;
|
if (light != null) { light.Range = range; }
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -75,7 +75,7 @@ namespace Barotrauma.Items.Components
|
|||||||
get { return IsActive; }
|
get { return IsActive; }
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (IsActive == value) return;
|
if (IsActive == value) { return; }
|
||||||
|
|
||||||
IsActive = value;
|
IsActive = value;
|
||||||
#if SERVER
|
#if SERVER
|
||||||
@@ -135,11 +135,8 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
if (base.IsActive == value) { return; }
|
if (base.IsActive == value) { return; }
|
||||||
base.IsActive = value;
|
base.IsActive = value;
|
||||||
#if CLIENT
|
|
||||||
if (light == null) return;
|
SetLightSourceState(value, value ? lightBrightness : 0.0f);
|
||||||
light.Color = value ? lightColor : Color.Transparent;
|
|
||||||
if (!value) lightBrightness = 0.0f;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,7 +150,8 @@ namespace Barotrauma.Items.Components
|
|||||||
Position = item.Position,
|
Position = item.Position,
|
||||||
CastShadows = castShadows,
|
CastShadows = castShadows,
|
||||||
IsBackground = drawBehindSubs,
|
IsBackground = drawBehindSubs,
|
||||||
SpriteScale = Vector2.One * item.Scale
|
SpriteScale = Vector2.One * item.Scale,
|
||||||
|
Range = range
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -161,40 +159,34 @@ namespace Barotrauma.Items.Components
|
|||||||
item.AddTag("light");
|
item.AddTag("light");
|
||||||
}
|
}
|
||||||
|
|
||||||
#if CLIENT
|
|
||||||
public override void OnScaleChanged()
|
|
||||||
{
|
|
||||||
light.SpriteScale = Vector2.One * item.Scale;
|
|
||||||
light.Position = ParentBody != null ? ParentBody.Position : item.Position;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
public override void OnItemLoaded()
|
public override void OnItemLoaded()
|
||||||
{
|
{
|
||||||
base.OnItemLoaded();
|
base.OnItemLoaded();
|
||||||
itemLoaded = true;
|
itemLoaded = true;
|
||||||
#if CLIENT
|
SetLightSourceState(IsActive, lightBrightness);
|
||||||
light.Color = IsActive ? lightColor : Color.Transparent;
|
|
||||||
if (!IsActive) lightBrightness = 0.0f;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Update(float deltaTime, Camera cam)
|
public override void Update(float deltaTime, Camera cam)
|
||||||
{
|
{
|
||||||
|
if (item.AiTarget != null)
|
||||||
|
{
|
||||||
|
UpdateAITarget(item.AiTarget);
|
||||||
|
}
|
||||||
UpdateOnActiveEffects(deltaTime);
|
UpdateOnActiveEffects(deltaTime);
|
||||||
|
|
||||||
#if CLIENT
|
#if CLIENT
|
||||||
light.ParentSub = item.Submarine;
|
light.ParentSub = item.Submarine;
|
||||||
|
#endif
|
||||||
if (item.Container != null)
|
if (item.Container != null)
|
||||||
{
|
{
|
||||||
light.Color = Color.Transparent;
|
SetLightSourceState(false, 0.0f);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#if CLIENT
|
||||||
light.Position = ParentBody != null ? ParentBody.Position : item.Position;
|
light.Position = ParentBody != null ? ParentBody.Position : item.Position;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
PhysicsBody body = ParentBody ?? item.body;
|
PhysicsBody body = ParentBody ?? item.body;
|
||||||
|
|
||||||
if (body != null)
|
if (body != null)
|
||||||
{
|
{
|
||||||
#if CLIENT
|
#if CLIENT
|
||||||
@@ -203,9 +195,7 @@ namespace Barotrauma.Items.Components
|
|||||||
#endif
|
#endif
|
||||||
if (!body.Enabled)
|
if (!body.Enabled)
|
||||||
{
|
{
|
||||||
#if CLIENT
|
SetLightSourceState(false, 0.0f);
|
||||||
light.Color = Color.Transparent;
|
|
||||||
#endif
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -217,7 +207,6 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
|
|
||||||
currPowerConsumption = powerConsumption;
|
currPowerConsumption = powerConsumption;
|
||||||
|
|
||||||
if (Rand.Range(0.0f, 1.0f) < 0.05f && Voltage < Rand.Range(0.0f, MinVoltage))
|
if (Rand.Range(0.0f, 1.0f) < 0.05f && Voltage < Rand.Range(0.0f, MinVoltage))
|
||||||
{
|
{
|
||||||
#if CLIENT
|
#if CLIENT
|
||||||
@@ -240,36 +229,21 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
if (blinkTimer > 0.5f)
|
if (blinkTimer > 0.5f)
|
||||||
{
|
{
|
||||||
#if CLIENT
|
SetLightSourceState(false, lightBrightness);
|
||||||
light.Color = Color.Transparent;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#if CLIENT
|
SetLightSourceState(true, lightBrightness * (1.0f - Rand.Range(0.0f, flicker)));
|
||||||
light.Color = lightColor * lightBrightness * (1.0f - Rand.Range(0.0f, Flicker));
|
|
||||||
light.Range = range;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
if (item.AiTarget != null)
|
|
||||||
{
|
|
||||||
UpdateAITarget(item.AiTarget);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (powerIn == null && powerConsumption > 0.0f) { Voltage -= deltaTime; }
|
||||||
}
|
}
|
||||||
|
|
||||||
#if CLIENT
|
|
||||||
public override void UpdateBroken(float deltaTime, Camera cam)
|
public override void UpdateBroken(float deltaTime, Camera cam)
|
||||||
{
|
{
|
||||||
light.Color = Color.Transparent;
|
SetLightSourceState(false, 0.0f);
|
||||||
lightBrightness = 0.0f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void RemoveComponentSpecific()
|
|
||||||
{
|
|
||||||
base.RemoveComponentSpecific();
|
|
||||||
light.Remove();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
public override bool Use(float deltaTime, Character character = null)
|
public override bool Use(float deltaTime, Character character = null)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
@@ -277,8 +251,6 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0.0f, float signalStrength = 1.0f)
|
public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0.0f, float signalStrength = 1.0f)
|
||||||
{
|
{
|
||||||
base.ReceiveSignal(stepsTaken, signal, connection, source, sender, power, signalStrength);
|
|
||||||
|
|
||||||
switch (connection.Name)
|
switch (connection.Name)
|
||||||
{
|
{
|
||||||
case "toggle":
|
case "toggle":
|
||||||
@@ -300,13 +272,14 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
private void UpdateAITarget(AITarget target)
|
private void UpdateAITarget(AITarget target)
|
||||||
{
|
{
|
||||||
//voltage > minVoltage || powerConsumption <= 0.0f; <- ?
|
if (!IsActive) { return; }
|
||||||
target.Enabled = IsActive;
|
|
||||||
if (target.MaxSightRange <= 0)
|
if (target.MaxSightRange <= 0)
|
||||||
{
|
{
|
||||||
target.MaxSightRange = Range * 5;
|
target.MaxSightRange = Range * 5;
|
||||||
}
|
}
|
||||||
target.SightRange = IsActive ? target.MaxSightRange * lightBrightness : 0;
|
target.SightRange = target.MaxSightRange * lightBrightness;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
partial void SetLightSourceState(bool enabled, float brightness);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
public override void ReceivePowerProbeSignal(Connection connection, Item source, float power)
|
public override void ReceivePowerProbeSignal(Connection connection, Item source, float power)
|
||||||
{
|
{
|
||||||
if (!IsOn) { return; }
|
if (!IsOn || item.Condition <= 0.0f) { return; }
|
||||||
|
|
||||||
//we've already received this signal
|
//we've already received this signal
|
||||||
if (lastPowerProbeRecipients.Contains(this)) { return; }
|
if (lastPowerProbeRecipients.Contains(this)) { return; }
|
||||||
|
|||||||
@@ -276,7 +276,7 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
if (reload > 0.0f) return false;
|
if (reload > 0.0f) return false;
|
||||||
|
|
||||||
if (GetAvailablePower() < powerConsumption)
|
if (GetAvailableBatteryPower() < powerConsumption)
|
||||||
{
|
{
|
||||||
#if CLIENT
|
#if CLIENT
|
||||||
if (!flashLowPower && character != null && character == Character.Controlled)
|
if (!flashLowPower && character != null && character == Character.Controlled)
|
||||||
@@ -410,7 +410,7 @@ namespace Barotrauma.Items.Components
|
|||||||
character.AIController.SelectTarget(null);
|
character.AIController.SelectTarget(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GetAvailablePower() < powerConsumption)
|
if (GetAvailableBatteryPower() < powerConsumption)
|
||||||
{
|
{
|
||||||
var batteries = item.GetConnectedComponents<PowerContainer>();
|
var batteries = item.GetConnectedComponents<PowerContainer>();
|
||||||
|
|
||||||
@@ -540,21 +540,6 @@ namespace Barotrauma.Items.Components
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private float GetAvailablePower()
|
|
||||||
{
|
|
||||||
var batteries = item.GetConnectedComponents<PowerContainer>();
|
|
||||||
|
|
||||||
float availablePower = 0.0f;
|
|
||||||
foreach (PowerContainer battery in batteries)
|
|
||||||
{
|
|
||||||
float batteryPower = Math.Min(battery.Charge*3600.0f, battery.MaxOutPut);
|
|
||||||
|
|
||||||
availablePower += batteryPower;
|
|
||||||
}
|
|
||||||
|
|
||||||
return availablePower;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void GetAvailablePower(out float availableCharge, out float availableCapacity)
|
private void GetAvailablePower(out float availableCharge, out float availableCapacity)
|
||||||
{
|
{
|
||||||
var batteries = item.GetConnectedComponents<PowerContainer>();
|
var batteries = item.GetConnectedComponents<PowerContainer>();
|
||||||
|
|||||||
@@ -425,7 +425,7 @@ namespace Barotrauma
|
|||||||
string[] splitTags = value.Split(',');
|
string[] splitTags = value.Split(',');
|
||||||
foreach (string tag in splitTags)
|
foreach (string tag in splitTags)
|
||||||
{
|
{
|
||||||
string[] splitTag = tag.Split(':');
|
string[] splitTag = tag.Trim().Split(':');
|
||||||
splitTag[0] = splitTag[0].ToLowerInvariant();
|
splitTag[0] = splitTag[0].ToLowerInvariant();
|
||||||
tags.Add(string.Join(":", splitTag));
|
tags.Add(string.Join(":", splitTag));
|
||||||
}
|
}
|
||||||
@@ -1060,18 +1060,18 @@ namespace Barotrauma
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ApplyStatusEffects(ActionType type, float deltaTime, Character character = null, Limb limb = null, bool isNetworkEvent = false)
|
public void ApplyStatusEffects(ActionType type, float deltaTime, Character character = null, Limb limb = null, Entity useTarget = null, bool isNetworkEvent = false, Vector2? worldPosition = null)
|
||||||
{
|
{
|
||||||
if (!hasStatusEffectsOfType[(int)type]) { return; }
|
if (!hasStatusEffectsOfType[(int)type]) { return; }
|
||||||
foreach (StatusEffect effect in statusEffectLists[type])
|
foreach (StatusEffect effect in statusEffectLists[type])
|
||||||
{
|
{
|
||||||
ApplyStatusEffect(effect, type, deltaTime, character, limb, isNetworkEvent, false);
|
ApplyStatusEffect(effect, type, deltaTime, character, limb, useTarget, isNetworkEvent, false, worldPosition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly List<ISerializableEntity> targets = new List<ISerializableEntity>();
|
readonly List<ISerializableEntity> targets = new List<ISerializableEntity>();
|
||||||
|
|
||||||
public void ApplyStatusEffect(StatusEffect effect, ActionType type, float deltaTime, Character character = null, Limb limb = null, bool isNetworkEvent = false, bool checkCondition = true)
|
public void ApplyStatusEffect(StatusEffect effect, ActionType type, float deltaTime, Character character = null, Limb limb = null, Entity useTarget = null, bool isNetworkEvent = false, bool checkCondition = true, Vector2? worldPosition = null)
|
||||||
{
|
{
|
||||||
if (!isNetworkEvent && checkCondition)
|
if (!isNetworkEvent && checkCondition)
|
||||||
{
|
{
|
||||||
@@ -1110,6 +1110,12 @@ namespace Barotrauma
|
|||||||
if (targets.Count > 0) { hasTargets = true; }
|
if (targets.Count > 0) { hasTargets = true; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (effect.HasTargetType(StatusEffect.TargetType.UseTarget) && useTarget is ISerializableEntity serializableTarget)
|
||||||
|
{
|
||||||
|
hasTargets = true;
|
||||||
|
targets.Add(serializableTarget);
|
||||||
|
}
|
||||||
|
|
||||||
if (!hasTargets) { return; }
|
if (!hasTargets) { return; }
|
||||||
|
|
||||||
if (effect.HasTargetType(StatusEffect.TargetType.Hull) && CurrentHull != null)
|
if (effect.HasTargetType(StatusEffect.TargetType.Hull) && CurrentHull != null)
|
||||||
@@ -1125,30 +1131,32 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (effect.HasTargetType(StatusEffect.TargetType.Character))
|
if (character != null)
|
||||||
{
|
{
|
||||||
if (type == ActionType.OnContained && ParentInventory is CharacterInventory characterInventory)
|
if (effect.HasTargetType(StatusEffect.TargetType.Character))
|
||||||
{
|
{
|
||||||
targets.Add(characterInventory.Owner as ISerializableEntity);
|
if (type == ActionType.OnContained && ParentInventory is CharacterInventory characterInventory)
|
||||||
|
{
|
||||||
|
targets.Add(characterInventory.Owner as ISerializableEntity);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
targets.Add(character);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
if (effect.HasTargetType(StatusEffect.TargetType.AllLimbs))
|
||||||
{
|
{
|
||||||
targets.Add(character);
|
targets.AddRange(character.AnimController.Limbs.ToList());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (effect.HasTargetType(StatusEffect.TargetType.Limb))
|
if (effect.HasTargetType(StatusEffect.TargetType.Limb))
|
||||||
{
|
{
|
||||||
targets.Add(limb);
|
targets.Add(limb);
|
||||||
}
|
}
|
||||||
if (effect.HasTargetType(StatusEffect.TargetType.AllLimbs))
|
|
||||||
{
|
|
||||||
targets.AddRange(character.AnimController.Limbs.ToList());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Container != null && effect.HasTargetType(StatusEffect.TargetType.Parent)) targets.Add(Container);
|
if (Container != null && effect.HasTargetType(StatusEffect.TargetType.Parent)) targets.Add(Container);
|
||||||
|
|
||||||
effect.Apply(type, deltaTime, this, targets);
|
effect.Apply(type, deltaTime, this, targets, worldPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1360,7 +1368,8 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (transformDirty) { return false; }
|
if (transformDirty) { return false; }
|
||||||
|
|
||||||
Vector2 normal = contact.Manifold.LocalNormal;
|
contact.GetWorldManifold(out Vector2 normal, out _);
|
||||||
|
if (contact.FixtureA.Body == f1.Body) { normal = -normal; }
|
||||||
float impact = Vector2.Dot(f1.Body.LinearVelocity, -normal);
|
float impact = Vector2.Dot(f1.Body.LinearVelocity, -normal);
|
||||||
|
|
||||||
OnCollisionProjSpecific(f1, f2, contact, impact);
|
OnCollisionProjSpecific(f1, f2, contact, impact);
|
||||||
@@ -1568,7 +1577,7 @@ namespace Barotrauma
|
|||||||
foreach (StatusEffect effect in connection.Effects)
|
foreach (StatusEffect effect in connection.Effects)
|
||||||
{
|
{
|
||||||
if (condition <= 0.0f && effect.type != ActionType.OnBroken) { continue; }
|
if (condition <= 0.0f && effect.type != ActionType.OnBroken) { continue; }
|
||||||
if (signal != "0" && !string.IsNullOrEmpty(signal)) { ApplyStatusEffect(effect, ActionType.OnUse, (float)Timing.Step, null, null, false, false); }
|
if (signal != "0" && !string.IsNullOrEmpty(signal)) { ApplyStatusEffect(effect, ActionType.OnUse, (float)Timing.Step); }
|
||||||
}
|
}
|
||||||
connection.SendSignal(stepsTaken, signal, source ?? this, sender, power, signalStrength);
|
connection.SendSignal(stepsTaken, signal, source ?? this, sender, power, signalStrength);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -575,6 +575,10 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public void ApplyFlowForces(float deltaTime, Item item)
|
public void ApplyFlowForces(float deltaTime, Item item)
|
||||||
{
|
{
|
||||||
|
if (item.body.Mass <= 0.0f)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
foreach (var gap in ConnectedGaps.Where(gap => gap.Open > 0))
|
foreach (var gap in ConnectedGaps.Where(gap => gap.Open > 0))
|
||||||
{
|
{
|
||||||
var distance = MathHelper.Max(Vector2.DistanceSquared(item.Position, gap.Position) / 1000, 1f);
|
var distance = MathHelper.Max(Vector2.DistanceSquared(item.Position, gap.Position) / 1000, 1f);
|
||||||
|
|||||||
@@ -184,10 +184,18 @@ namespace Barotrauma
|
|||||||
for (int i = 0; i < linkedToIds.Length; i++)
|
for (int i = 0; i < linkedToIds.Length; i++)
|
||||||
{
|
{
|
||||||
linkedSub.linkedToID.Add((ushort)linkedToIds[i]);
|
linkedSub.linkedToID.Add((ushort)linkedToIds[i]);
|
||||||
|
if (Screen.Selected == GameMain.SubEditorScreen)
|
||||||
|
{
|
||||||
|
if (FindEntityByID((ushort)linkedToIds[i]) is MapEntity linked)
|
||||||
|
{
|
||||||
|
linkedSub.linkedTo.Add(linked);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
linkedSub.originalLinkedToID = (ushort)element.GetAttributeInt("originallinkedto", 0);
|
linkedSub.originalLinkedToID = (ushort)element.GetAttributeInt("originallinkedto", 0);
|
||||||
linkedSub.originalMyPortID = (ushort)element.GetAttributeInt("originalmyport", 0);
|
linkedSub.originalMyPortID = (ushort)element.GetAttributeInt("originalmyport", 0);
|
||||||
|
|
||||||
|
|
||||||
return linkedSub.loadSub ? linkedSub : null;
|
return linkedSub.loadSub ? linkedSub : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -107,11 +107,14 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
public readonly Entity Entity;
|
public readonly Entity Entity;
|
||||||
|
|
||||||
|
public readonly UInt16 OriginalID;
|
||||||
|
|
||||||
public readonly bool Remove = false;
|
public readonly bool Remove = false;
|
||||||
|
|
||||||
public SpawnOrRemove(Entity entity, bool remove)
|
public SpawnOrRemove(Entity entity, bool remove)
|
||||||
{
|
{
|
||||||
Entity = entity;
|
Entity = entity;
|
||||||
|
OriginalID = entity.ID;
|
||||||
Remove = remove;
|
Remove = remove;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -328,7 +328,16 @@ namespace Barotrauma.Networking
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string ServerName;
|
private string serverName;
|
||||||
|
public string ServerName
|
||||||
|
{
|
||||||
|
get { return serverName; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
serverName = value;
|
||||||
|
if (serverName.Length > NetConfig.ServerNameMaxLength) { ServerName = ServerName.Substring(0, NetConfig.ServerNameMaxLength); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private string serverMessageText;
|
private string serverMessageText;
|
||||||
public string ServerMessageText
|
public string ServerMessageText
|
||||||
|
|||||||
@@ -177,7 +177,7 @@ namespace Barotrauma
|
|||||||
string[] readTags = valStr.Split(',');
|
string[] readTags = valStr.Split(',');
|
||||||
int matches = 0;
|
int matches = 0;
|
||||||
foreach (string tag in readTags)
|
foreach (string tag in readTags)
|
||||||
if (((Item)target).HasTag(tag)) matches++;
|
if (target is Item item && item.HasTag(tag)) matches++;
|
||||||
|
|
||||||
//If operator is == then it needs to match everything, otherwise if its != there must be zero matches.
|
//If operator is == then it needs to match everything, otherwise if its != there must be zero matches.
|
||||||
return Operator == OperatorType.Equals ? matches >= readTags.Length : matches <= 0;
|
return Operator == OperatorType.Equals ? matches >= readTags.Length : matches <= 0;
|
||||||
@@ -225,8 +225,7 @@ namespace Barotrauma
|
|||||||
return success;
|
return success;
|
||||||
case ConditionType.SpeciesName:
|
case ConditionType.SpeciesName:
|
||||||
if (target == null) { return Operator == OperatorType.NotEquals; }
|
if (target == null) { return Operator == OperatorType.NotEquals; }
|
||||||
Character targetCharacter = target as Character;
|
if (!(target is Character targetCharacter)) { return false; }
|
||||||
if (targetCharacter == null) { return false; }
|
|
||||||
return (Operator == OperatorType.Equals) == (targetCharacter.SpeciesName == valStr);
|
return (Operator == OperatorType.Equals) == (targetCharacter.SpeciesName == valStr);
|
||||||
case ConditionType.EntityType:
|
case ConditionType.EntityType:
|
||||||
switch (valStr)
|
switch (valStr)
|
||||||
|
|||||||
@@ -12,8 +12,10 @@ namespace Barotrauma
|
|||||||
//only used if none of the selected content packages contain any text files
|
//only used if none of the selected content packages contain any text files
|
||||||
const string VanillaTextFilePath = "Content/Texts/EnglishVanilla.xml";
|
const string VanillaTextFilePath = "Content/Texts/EnglishVanilla.xml";
|
||||||
|
|
||||||
|
private static readonly object mutex = new object();
|
||||||
|
|
||||||
//key = language
|
//key = language
|
||||||
private static Dictionary<string, List<TextPack>> textPacks = new Dictionary<string, List<TextPack>>();
|
private static Dictionary<string, List<TextPack>> textPacks;
|
||||||
|
|
||||||
private static readonly string[] serverMessageCharacters = new string[] { "~", "[", "]", "=" };
|
private static readonly string[] serverMessageCharacters = new string[] { "~", "[", "]", "=" };
|
||||||
|
|
||||||
@@ -25,10 +27,16 @@ namespace Barotrauma
|
|||||||
private set;
|
private set;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly HashSet<string> availableLanguages = new HashSet<string>();
|
private static HashSet<string> availableLanguages;
|
||||||
public static IEnumerable<string> AvailableLanguages
|
public static IEnumerable<string> AvailableLanguages
|
||||||
{
|
{
|
||||||
get { return availableLanguages; }
|
get
|
||||||
|
{
|
||||||
|
lock (mutex)
|
||||||
|
{
|
||||||
|
return new HashSet<string>(availableLanguages);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<string> GetTextFiles()
|
public static List<string> GetTextFiles()
|
||||||
@@ -55,25 +63,29 @@ namespace Barotrauma
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static string GetTranslatedLanguageName(string language)
|
public static string GetTranslatedLanguageName(string language)
|
||||||
{
|
{
|
||||||
if (!textPacks.ContainsKey(language))
|
lock (mutex)
|
||||||
{
|
{
|
||||||
|
if (!textPacks.ContainsKey(language))
|
||||||
|
{
|
||||||
|
return language;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var textPack in textPacks[language])
|
||||||
|
{
|
||||||
|
if (textPack.Language == language)
|
||||||
|
{
|
||||||
|
return textPack.TranslatedName;
|
||||||
|
}
|
||||||
|
}
|
||||||
return language;
|
return language;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var textPack in textPacks[language])
|
|
||||||
{
|
|
||||||
if (textPack.Language == language)
|
|
||||||
{
|
|
||||||
return textPack.TranslatedName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return language;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void LoadTextPacks(IEnumerable<ContentPackage> selectedContentPackages)
|
public static void LoadTextPacks(IEnumerable<ContentPackage> selectedContentPackages)
|
||||||
{
|
{
|
||||||
availableLanguages.Clear();
|
HashSet<string> newLanguages = new HashSet<string>();
|
||||||
textPacks.Clear();
|
Dictionary<string, List<TextPack>> newTextPacks = new Dictionary<string, List<TextPack>>();
|
||||||
|
|
||||||
var textFiles = ContentPackage.GetFilesOfType(selectedContentPackages, ContentType.Text);
|
var textFiles = ContentPackage.GetFilesOfType(selectedContentPackages, ContentType.Text);
|
||||||
|
|
||||||
foreach (string file in textFiles)
|
foreach (string file in textFiles)
|
||||||
@@ -81,12 +93,12 @@ namespace Barotrauma
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var textPack = new TextPack(file);
|
var textPack = new TextPack(file);
|
||||||
availableLanguages.Add(textPack.Language);
|
newLanguages.Add(textPack.Language);
|
||||||
if (!textPacks.ContainsKey(textPack.Language))
|
if (!newTextPacks.ContainsKey(textPack.Language))
|
||||||
{
|
{
|
||||||
textPacks.Add(textPack.Language, new List<TextPack>());
|
newTextPacks.Add(textPack.Language, new List<TextPack>());
|
||||||
}
|
}
|
||||||
textPacks[textPack.Language].Add(textPack);
|
newTextPacks[textPack.Language].Add(textPack);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@@ -94,7 +106,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (textPacks.Count == 0)
|
if (newTextPacks.Count == 0)
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError("No text files available in any of the selected content packages. Attempting to find a vanilla English text file...");
|
DebugConsole.ThrowError("No text files available in any of the selected content packages. Attempting to find a vanilla English text file...");
|
||||||
if (!File.Exists(VanillaTextFilePath))
|
if (!File.Exists(VanillaTextFilePath))
|
||||||
@@ -102,9 +114,21 @@ namespace Barotrauma
|
|||||||
throw new Exception("No text files found in any of the selected content packages or in the default text path!");
|
throw new Exception("No text files found in any of the selected content packages or in the default text path!");
|
||||||
}
|
}
|
||||||
var textPack = new TextPack(VanillaTextFilePath);
|
var textPack = new TextPack(VanillaTextFilePath);
|
||||||
availableLanguages.Add(textPack.Language);
|
newLanguages.Add(textPack.Language);
|
||||||
textPacks.Add(textPack.Language, new List<TextPack>() { textPack });
|
newTextPacks.Add(textPack.Language, new List<TextPack>() { textPack });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (newTextPacks.Count == 0)
|
||||||
|
{
|
||||||
|
throw new Exception("Failed to load text packs!");
|
||||||
|
}
|
||||||
|
|
||||||
|
lock (mutex)
|
||||||
|
{
|
||||||
|
textPacks = newTextPacks;
|
||||||
|
availableLanguages = newLanguages;
|
||||||
|
}
|
||||||
|
|
||||||
Initialized = true;
|
Initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,74 +136,81 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(textTag)) { return false; }
|
if (string.IsNullOrEmpty(textTag)) { return false; }
|
||||||
|
|
||||||
if (!textPacks.ContainsKey(Language))
|
lock (mutex)
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError("No text packs available for the selected language (" + Language + ")! Switching to English...");
|
|
||||||
Language = "English";
|
|
||||||
if (!textPacks.ContainsKey(Language))
|
if (!textPacks.ContainsKey(Language))
|
||||||
{
|
{
|
||||||
throw new Exception("No text packs available in English!");
|
DebugConsole.ThrowError("No text packs available for the selected language (" + Language + ")! Switching to English...");
|
||||||
|
Language = "English";
|
||||||
|
if (!textPacks.ContainsKey(Language))
|
||||||
|
{
|
||||||
|
throw new Exception("No text packs available in English!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach (TextPack textPack in textPacks[Language])
|
||||||
|
{
|
||||||
|
if (textPack.Get(textTag) != null) { return true; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
foreach (TextPack textPack in textPacks[Language])
|
|
||||||
{
|
|
||||||
if (textPack.Get(textTag) != null) { return true; }
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string Get(string textTag, bool returnNull = false, string fallBackTag = null)
|
public static string Get(string textTag, bool returnNull = false, string fallBackTag = null)
|
||||||
{
|
{
|
||||||
if (!textPacks.ContainsKey(Language))
|
lock (mutex)
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError("No text packs available for the selected language (" + Language + ")! Switching to English...");
|
|
||||||
Language = "English";
|
|
||||||
if (!textPacks.ContainsKey(Language))
|
if (!textPacks.ContainsKey(Language))
|
||||||
{
|
{
|
||||||
throw new Exception("No text packs available in English!");
|
DebugConsole.ThrowError("No text packs available for the selected language (" + Language + ")! Switching to English...");
|
||||||
}
|
Language = "English";
|
||||||
}
|
if (!textPacks.ContainsKey(Language))
|
||||||
|
|
||||||
foreach (TextPack textPack in textPacks[Language])
|
|
||||||
{
|
|
||||||
string text = textPack.Get(textTag);
|
|
||||||
if (text != null) { return text; }
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(fallBackTag))
|
|
||||||
{
|
|
||||||
foreach (TextPack textPack in textPacks[Language])
|
|
||||||
{
|
|
||||||
string text = textPack.Get(fallBackTag);
|
|
||||||
if (text != null) { return text; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//if text was not found and we're using a language other than English, see if we can find an English version
|
|
||||||
//may happen, for example, if a user has selected another language and using mods that haven't been translated to that language
|
|
||||||
if (Language != "English" && textPacks.ContainsKey("English"))
|
|
||||||
{
|
|
||||||
foreach (TextPack textPack in textPacks["English"])
|
|
||||||
{
|
|
||||||
string text = textPack.Get(textTag);
|
|
||||||
if (text != null)
|
|
||||||
{
|
{
|
||||||
#if DEBUG
|
throw new Exception("No text packs available in English!");
|
||||||
DebugConsole.NewMessage("Text \"" + textTag + "\" not found for the language \"" + Language + "\". Using the English text \"" + text + "\" instead.");
|
|
||||||
#endif
|
|
||||||
return text;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (returnNull)
|
foreach (TextPack textPack in textPacks[Language])
|
||||||
{
|
{
|
||||||
return null;
|
string text = textPack.Get(textTag);
|
||||||
}
|
if (text != null) { return text; }
|
||||||
else
|
}
|
||||||
{
|
|
||||||
DebugConsole.ThrowError("Text \"" + textTag + "\" not found.");
|
if (!string.IsNullOrEmpty(fallBackTag))
|
||||||
return textTag;
|
{
|
||||||
|
foreach (TextPack textPack in textPacks[Language])
|
||||||
|
{
|
||||||
|
string text = textPack.Get(fallBackTag);
|
||||||
|
if (text != null) { return text; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//if text was not found and we're using a language other than English, see if we can find an English version
|
||||||
|
//may happen, for example, if a user has selected another language and using mods that haven't been translated to that language
|
||||||
|
if (Language != "English" && textPacks.ContainsKey("English"))
|
||||||
|
{
|
||||||
|
foreach (TextPack textPack in textPacks["English"])
|
||||||
|
{
|
||||||
|
string text = textPack.Get(textTag);
|
||||||
|
if (text != null)
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
DebugConsole.NewMessage("Text \"" + textTag + "\" not found for the language \"" + Language + "\". Using the English text \"" + text + "\" instead.");
|
||||||
|
#endif
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (returnNull)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DebugConsole.ThrowError("Text \"" + textTag + "\" not found.");
|
||||||
|
return textTag;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -418,13 +449,16 @@ namespace Barotrauma
|
|||||||
// And: replacement=formatter(value)
|
// And: replacement=formatter(value)
|
||||||
public static string GetServerMessage(string serverMessage)
|
public static string GetServerMessage(string serverMessage)
|
||||||
{
|
{
|
||||||
if (!textPacks.ContainsKey(Language))
|
lock (mutex)
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError("No text packs available for the selected language (" + Language + ")! Switching to English...");
|
|
||||||
Language = "English";
|
|
||||||
if (!textPacks.ContainsKey(Language))
|
if (!textPacks.ContainsKey(Language))
|
||||||
{
|
{
|
||||||
throw new Exception("No text packs available in English!");
|
DebugConsole.ThrowError("No text packs available for the selected language (" + Language + ")! Switching to English...");
|
||||||
|
Language = "English";
|
||||||
|
if (!textPacks.ContainsKey(Language))
|
||||||
|
{
|
||||||
|
throw new Exception("No text packs available in English!");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -588,58 +622,64 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public static List<string> GetAll(string textTag)
|
public static List<string> GetAll(string textTag)
|
||||||
{
|
{
|
||||||
if (!textPacks.ContainsKey(Language))
|
lock (mutex)
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError("No text packs available for the selected language (" + Language + ")! Switching to English...");
|
|
||||||
Language = "English";
|
|
||||||
if (!textPacks.ContainsKey(Language))
|
if (!textPacks.ContainsKey(Language))
|
||||||
{
|
{
|
||||||
throw new Exception("No text packs available in English!");
|
DebugConsole.ThrowError("No text packs available for the selected language (" + Language + ")! Switching to English...");
|
||||||
|
Language = "English";
|
||||||
|
if (!textPacks.ContainsKey(Language))
|
||||||
|
{
|
||||||
|
throw new Exception("No text packs available in English!");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
List<string> allText;
|
List<string> allText;
|
||||||
|
|
||||||
foreach (TextPack textPack in textPacks[Language])
|
foreach (TextPack textPack in textPacks[Language])
|
||||||
{
|
|
||||||
allText = textPack.GetAll(textTag);
|
|
||||||
if (allText != null) return allText;
|
|
||||||
}
|
|
||||||
|
|
||||||
//if text was not found and we're using a language other than English, see if we can find an English version
|
|
||||||
//may happen, for example, if a user has selected another language and using mods that haven't been translated to that language
|
|
||||||
if (Language != "English" && textPacks.ContainsKey("English"))
|
|
||||||
{
|
|
||||||
foreach (TextPack textPack in textPacks["English"])
|
|
||||||
{
|
{
|
||||||
allText = textPack.GetAll(textTag);
|
allText = textPack.GetAll(textTag);
|
||||||
if (allText != null) return allText;
|
if (allText != null) return allText;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
//if text was not found and we're using a language other than English, see if we can find an English version
|
||||||
|
//may happen, for example, if a user has selected another language and using mods that haven't been translated to that language
|
||||||
|
if (Language != "English" && textPacks.ContainsKey("English"))
|
||||||
|
{
|
||||||
|
foreach (TextPack textPack in textPacks["English"])
|
||||||
|
{
|
||||||
|
allText = textPack.GetAll(textTag);
|
||||||
|
if (allText != null) return allText;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<KeyValuePair<string, string>> GetAllTagTextPairs()
|
public static List<KeyValuePair<string, string>> GetAllTagTextPairs()
|
||||||
{
|
{
|
||||||
if (!textPacks.ContainsKey(Language))
|
lock (mutex)
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError("No text packs available for the selected language (" + Language + ")! Switching to English...");
|
|
||||||
Language = "English";
|
|
||||||
if (!textPacks.ContainsKey(Language))
|
if (!textPacks.ContainsKey(Language))
|
||||||
{
|
{
|
||||||
throw new Exception("No text packs available in English!");
|
DebugConsole.ThrowError("No text packs available for the selected language (" + Language + ")! Switching to English...");
|
||||||
|
Language = "English";
|
||||||
|
if (!textPacks.ContainsKey(Language))
|
||||||
|
{
|
||||||
|
throw new Exception("No text packs available in English!");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<KeyValuePair<string, string>> allText = new List<KeyValuePair<string, string>>();
|
||||||
|
|
||||||
|
foreach (TextPack textPack in textPacks[Language])
|
||||||
|
{
|
||||||
|
allText.AddRange(textPack.GetAllTagTextPairs());
|
||||||
|
}
|
||||||
|
|
||||||
|
return allText;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<KeyValuePair<string, string>> allText = new List<KeyValuePair<string, string>>();
|
|
||||||
|
|
||||||
foreach (TextPack textPack in textPacks[Language])
|
|
||||||
{
|
|
||||||
allText.AddRange(textPack.GetAllTagTextPairs());
|
|
||||||
}
|
|
||||||
|
|
||||||
return allText;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string ReplaceGenderPronouns(string text, Gender gender)
|
public static string ReplaceGenderPronouns(string text, Gender gender)
|
||||||
@@ -689,35 +729,41 @@ namespace Barotrauma
|
|||||||
#if DEBUG
|
#if DEBUG
|
||||||
public static void CheckForDuplicates(string lang)
|
public static void CheckForDuplicates(string lang)
|
||||||
{
|
{
|
||||||
if (!textPacks.ContainsKey(lang))
|
lock (mutex)
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError("No text packs available for the selected language (" + lang + ")!");
|
if (!textPacks.ContainsKey(lang))
|
||||||
return;
|
{
|
||||||
}
|
DebugConsole.ThrowError("No text packs available for the selected language (" + lang + ")!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int packIndex = 0;
|
int packIndex = 0;
|
||||||
foreach (TextPack textPack in textPacks[lang])
|
foreach (TextPack textPack in textPacks[lang])
|
||||||
{
|
{
|
||||||
textPack.CheckForDuplicates(packIndex);
|
textPack.CheckForDuplicates(packIndex);
|
||||||
packIndex++;
|
packIndex++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void WriteToCSV()
|
public static void WriteToCSV()
|
||||||
{
|
{
|
||||||
string lang = "English";
|
lock (mutex)
|
||||||
|
|
||||||
if (!textPacks.ContainsKey(lang))
|
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError("No text packs available for the selected language (" + lang + ")!");
|
string lang = "English";
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int packIndex = 0;
|
if (!textPacks.ContainsKey(lang))
|
||||||
foreach (TextPack textPack in textPacks[lang])
|
{
|
||||||
{
|
DebugConsole.ThrowError("No text packs available for the selected language (" + lang + ")!");
|
||||||
textPack.WriteToCSV(packIndex);
|
return;
|
||||||
packIndex++;
|
}
|
||||||
|
|
||||||
|
int packIndex = 0;
|
||||||
|
foreach (TextPack textPack in textPacks[lang])
|
||||||
|
{
|
||||||
|
textPack.WriteToCSV(packIndex);
|
||||||
|
packIndex++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
72
Barotrauma/BarotraumaShared/Source/Utils/TaskPool.cs
Normal file
72
Barotrauma/BarotraumaShared/Source/Utils/TaskPool.cs
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Barotrauma
|
||||||
|
{
|
||||||
|
public static class TaskPool
|
||||||
|
{
|
||||||
|
private struct TaskAction
|
||||||
|
{
|
||||||
|
public Task Task;
|
||||||
|
public Action<Task, object> OnCompletion;
|
||||||
|
public object UserData;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<TaskAction> taskActions = new List<TaskAction>();
|
||||||
|
|
||||||
|
private static void AddInternal(Task task, Action<Task, object> onCompletion, object userdata)
|
||||||
|
{
|
||||||
|
lock (taskActions)
|
||||||
|
{
|
||||||
|
taskActions.Add(new TaskAction() { Task = task, OnCompletion = onCompletion, UserData = userdata });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Add(Task task, Action<Task> onCompletion)
|
||||||
|
{
|
||||||
|
AddInternal(task, (Task t, object obj) => { onCompletion(t); }, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Add<U>(Task task, U userdata, Action<Task, U> onCompletion) where U : class
|
||||||
|
{
|
||||||
|
AddInternal(task, (Task t, object obj) => { onCompletion(t, (U)obj); }, userdata);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Add<T>(Task<T> task, Action<Task<T>> onCompletion)
|
||||||
|
{
|
||||||
|
AddInternal(task, (Task t, object obj) => { onCompletion((Task<T>)t); }, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Add<T,U>(Task<T> task, U userdata, Action<Task<T>, U> onCompletion) where U : class
|
||||||
|
{
|
||||||
|
AddInternal(task, (Task t, object obj) => { onCompletion((Task<T>)t, (U)obj); }, userdata);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Update()
|
||||||
|
{
|
||||||
|
lock (taskActions)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < taskActions.Count; i++)
|
||||||
|
{
|
||||||
|
if (taskActions[i].Task.IsCompleted)
|
||||||
|
{
|
||||||
|
taskActions[i].OnCompletion?.Invoke(taskActions[i].Task, taskActions[i].UserData);
|
||||||
|
taskActions.RemoveAt(i);
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void PrintTaskExceptions(Task task, string msg)
|
||||||
|
{
|
||||||
|
DebugConsole.ThrowError(msg);
|
||||||
|
foreach (Exception e in task.Exception.InnerExceptions)
|
||||||
|
{
|
||||||
|
DebugConsole.ThrowError(e.Message + "\n" + e.StackTrace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -437,5 +437,90 @@ namespace Barotrauma
|
|||||||
IEnumerable<string> filtered = splitted.SkipWhile(part => part != currentFolder).Skip(1);
|
IEnumerable<string> filtered = splitted.SkipWhile(part => part != currentFolder).Skip(1);
|
||||||
return string.Join("/", filtered);
|
return string.Join("/", filtered);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string EscapeCharacters(string str)
|
||||||
|
{
|
||||||
|
return str.Replace("\\", "\\\\").Replace("\"", "\\\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string UnescapeCharacters(string str)
|
||||||
|
{
|
||||||
|
string retVal = "";
|
||||||
|
for (int i=0;i<str.Length;i++)
|
||||||
|
{
|
||||||
|
if (str[i] != '\\')
|
||||||
|
{
|
||||||
|
retVal += str[i];
|
||||||
|
}
|
||||||
|
else if (i+1<str.Length)
|
||||||
|
{
|
||||||
|
if (str[i+1] == '\\')
|
||||||
|
{
|
||||||
|
retVal += "\\";
|
||||||
|
}
|
||||||
|
else if (str[i+1] == '\"')
|
||||||
|
{
|
||||||
|
retVal += "\"";
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ParseQuotedArgument(string[] arguments, int startIndex, out int endIndex)
|
||||||
|
{
|
||||||
|
#if WINDOWS
|
||||||
|
endIndex = startIndex + 1;
|
||||||
|
return arguments[startIndex];
|
||||||
|
#else
|
||||||
|
string retVal = "";
|
||||||
|
int currIndex = startIndex;
|
||||||
|
bool escaped = false;
|
||||||
|
if (arguments[startIndex][0] != '\"')
|
||||||
|
{
|
||||||
|
endIndex = startIndex+1;
|
||||||
|
return UnescapeCharacters(arguments[startIndex]);
|
||||||
|
}
|
||||||
|
while (currIndex < arguments.Length)
|
||||||
|
{
|
||||||
|
for (int i=currIndex == startIndex ? 1 : 0;i<arguments[currIndex].Length;i++)
|
||||||
|
{
|
||||||
|
if (!escaped)
|
||||||
|
{
|
||||||
|
if (arguments[currIndex][i] == '\\')
|
||||||
|
{
|
||||||
|
escaped = true;
|
||||||
|
}
|
||||||
|
else if (arguments[currIndex][i] == '\"')
|
||||||
|
{
|
||||||
|
endIndex = currIndex+1;
|
||||||
|
return UnescapeCharacters(retVal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
escaped = false;
|
||||||
|
}
|
||||||
|
retVal += arguments[currIndex][i];
|
||||||
|
}
|
||||||
|
retVal += " ";
|
||||||
|
currIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
endIndex = arguments.Length;
|
||||||
|
return retVal;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string[] MergeArguments(string[] arguments)
|
||||||
|
{
|
||||||
|
List<string> mergedArgs = new List<string>();
|
||||||
|
for (int i=0;i<arguments.Length;)
|
||||||
|
{
|
||||||
|
mergedArgs.Add(ParseQuotedArgument(arguments, i, out i));
|
||||||
|
}
|
||||||
|
return mergedArgs.ToArray();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,3 +1,61 @@
|
|||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
v0.9.6.0
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Networking/multiplayer fixes:
|
||||||
|
- Fixed the game occasionally freezing when joining a server.
|
||||||
|
- Fixed a bug that occasionally caused clients to disconnect with an "entity not found" error in the multiplayer. In technical terms, the issue occurred when the server spawned an entity with a given ID, sent a network event for that entity, and then spawned another entity that took up the ID of the previous entity. This could happen, for example, if in the multiplayer campaign a player happens to get an item with the same ID as an item in the inventory of another player who isn't currently present, and the other player joins the server. There are still most likely additional bugs that can cause similar error messages, so this fix will probably not get rid of the errors entirely.
|
||||||
|
- Fixed start button staying disabled in the server lobby when switching from the campaign mode to another game mode.
|
||||||
|
- Fixed clients occasionally getting disconnected due to the campaign store. Happened if a location had changed from one type to another (for example, natural formation to outpost), the players had bought something that wasn't originally available from the location and a new client joined.
|
||||||
|
- Fixed clients occasionally being prompted to download subs from the server even if they already have a matching sub.
|
||||||
|
- Fixed server having a password even if the password box is left empty in the in-game "host server" menu when hosting with the Linux version.
|
||||||
|
- Fixed server name being shortened to one word when hosting from the in-game "host server" menu with the Linux version.
|
||||||
|
- Fixed server name length not being restricted when set from serversettings.xml or using console commands.
|
||||||
|
- Fixed "ready to start" tickbox disappearing if a client joins while a round is running.
|
||||||
|
- Fixed traitors remaining as traitors client-side after restarting the round, allowing them to access the sabotage interface despite not having a traitor objective.
|
||||||
|
- Fixed characters occasionally not selecting/deselecting a periscope client-side, causing them to walk in place or not grab the periscope.
|
||||||
|
- Fixed male asian heads not appearing in the server lobby.
|
||||||
|
- Fixed campaign servers never being filtered out from the server browser when filtering based on game mode.
|
||||||
|
- Fixed clients not displaying the "could not connect" popup if the initial connection to a server times out.
|
||||||
|
- Fixed door weld state occasionally getting desynced, causing the door to be welded server-side but possible to open client-side.
|
||||||
|
|
||||||
|
Electricity fixes:
|
||||||
|
- Fixed junction boxes not passing signals to relays.
|
||||||
|
- Fixed broken junction boxes and relays carrying power.
|
||||||
|
- Fixed devices not receiving power if they're connected directly to batteries/supercapacitors with no relays or junction boxes in between.
|
||||||
|
- Fixed light components that receive power from somewhere else than a power input connection not going out when they lose power (e.g. lights on the diving suits).
|
||||||
|
- Fixed pumps and batteries operating/recharging faster when receiving overvoltage, with no upper limit, making it possible to for example operate pumps at 10x the speed by connecting them to a relay that's receiving 10x more power than is being drawn from it.
|
||||||
|
- Fixed LightComponents being toggled twice when they receive a signal to the toggle connection.
|
||||||
|
|
||||||
|
Misc fixes:
|
||||||
|
- Fixed "last used" listbox overlapping with the entity visibility tickboxes in the submarine editor on low resolutions.
|
||||||
|
- Fixed misaligned colliders on the "Shell A Cap 0 deg A/B" wall pieces.
|
||||||
|
- Fixed links disappearing between linked subs and docking ports when loading in the sub editor.
|
||||||
|
- Fixed loading freezing for up to 10 seconds if the game cannot fetch the remote content for the main menu (update notifications, changelogs, etc).
|
||||||
|
- Fixed lights on devices (junction boxes, nav terminals, reactor) being rendered on top of characters.
|
||||||
|
- Fixed lights lagging a little behind moving objects (e.g. diving suit light).
|
||||||
|
- Fixed characters being able to grab/heal others when handcuffed.
|
||||||
|
- Character editor: don't switch to the limb mode when clicking a limb in the joint edit mode. Fixes difficulties in using the joint angle widgets when the widgets are interloping limb source rects.
|
||||||
|
- Character editor: Fixed the texture path field not being copied if the source character has no texture path defined. In this case, we can use a texture path found in one of the limbs.
|
||||||
|
- Fixed bots incorrectly reporting problems in the room they are in instead of the room the issues is spotted at.
|
||||||
|
- Fixed bots reporting broken devices or asking medical attendance even if they are taking care of those things.
|
||||||
|
- Fixed bots saying "put out a fire in hull" instead of using the name of the room when they extinguish a fire.
|
||||||
|
- Fixed AITargets staing active even if the entity is not active (for example, the sonar could still be heard by monsters after it's turned off).
|
||||||
|
- The bots now only report about issues that have not been already been reported.
|
||||||
|
- Fixed monsters attacking doors that are open.
|
||||||
|
- Monsters keep pursuing the target if the behavior is "pursue" even when they cannot attack.
|
||||||
|
- Bots stop operating devices if a player starts operating them (unless they have been ordered to operate the device).
|
||||||
|
- Fixed bots playing the rewiring sound when repairing an item with a screwdriver.
|
||||||
|
- Fixed bots sometimes stopping behind a closed door when trying to extinguish a fire.
|
||||||
|
- Fixed chat messages occasionally extending below the lower bound of the chatbox.
|
||||||
|
- Fixed searchlight and turret lights disappearing before the light is fully off-screen.
|
||||||
|
- Waypoint fixes in Kastrull and the drone.
|
||||||
|
- Fixed Kastrull flooding when the drone is undocked.
|
||||||
|
- Fixed ballast pumps in Kastrull's drone being off by default.
|
||||||
|
- Fixed enormous in-game ballistic helmet sprite.
|
||||||
|
- Fire extinguishers can't be placed inside toolboxes anymore.
|
||||||
|
- Fixed lobby screen not scaling correctly after changing to a bigger resolution.
|
||||||
|
|
||||||
---------------------------------------------------------------------------------------------------------
|
---------------------------------------------------------------------------------------------------------
|
||||||
v0.9.5.1
|
v0.9.5.1
|
||||||
---------------------------------------------------------------------------------------------------------
|
---------------------------------------------------------------------------------------------------------
|
||||||
@@ -8,8 +66,7 @@ v0.9.5.1
|
|||||||
- Nerfed Hammerhead Spawns.
|
- Nerfed Hammerhead Spawns.
|
||||||
- Fixed occasional disconnections when the Hammerhead Matriarch releases her spawns.
|
- Fixed occasional disconnections when the Hammerhead Matriarch releases her spawns.
|
||||||
- Fixed Hammerhead Matriarch exploding twice when it attacks.
|
- Fixed Hammerhead Matriarch exploding twice when it attacks.
|
||||||
- Fixed bots sometimes getting stuck in an objective loop, causing them to repeatedly drop and pick up
|
- Fixed bots sometimes getting stuck in an objective loop, causing them to repeatedly drop and pick up diving suits or spam doors.
|
||||||
diving suits or spam doors.
|
|
||||||
- Fixed bots being allowed to go outside without a diving suit.
|
- Fixed bots being allowed to go outside without a diving suit.
|
||||||
- Fixed characters with a rectangular main collider being unable to use path finding.
|
- Fixed characters with a rectangular main collider being unable to use path finding.
|
||||||
- Fixed microphone volume scrollbar resetting to the maximum value when opening the settings menu.
|
- Fixed microphone volume scrollbar resetting to the maximum value when opening the settings menu.
|
||||||
|
|||||||
Reference in New Issue
Block a user