@@ -0,0 +1,4 @@
|
|||||||
|
# Declare files that will always have CRLF line endings on checkout.
|
||||||
|
*.sln text eol=crlf
|
||||||
|
*.cs text eol=crlf
|
||||||
|
*.xml text eol=crlf
|
||||||
@@ -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.8.1.5")]
|
[assembly: AssemblyVersion("0.8.2.0")]
|
||||||
[assembly: AssemblyFileVersion("0.8.1.5")]
|
[assembly: AssemblyFileVersion("0.8.2.0")]
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public Camera()
|
public Camera()
|
||||||
{
|
{
|
||||||
zoom = 1.0f;
|
zoom = prevZoom = 1.0f;
|
||||||
rotation = 0.0f;
|
rotation = 0.0f;
|
||||||
position = Vector2.Zero;
|
position = Vector2.Zero;
|
||||||
|
|
||||||
@@ -112,7 +112,7 @@ namespace Barotrauma
|
|||||||
viewMatrix =
|
viewMatrix =
|
||||||
Matrix.CreateTranslation(new Vector3(GameMain.GraphicsWidth / 2.0f, GameMain.GraphicsHeight / 2.0f, 0));
|
Matrix.CreateTranslation(new Vector3(GameMain.GraphicsWidth / 2.0f, GameMain.GraphicsHeight / 2.0f, 0));
|
||||||
|
|
||||||
UpdateTransform();
|
UpdateTransform(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vector2 TargetPos
|
public Vector2 TargetPos
|
||||||
|
|||||||
@@ -81,6 +81,9 @@ namespace Barotrauma
|
|||||||
if (Limbs == null)
|
if (Limbs == null)
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError("Failed to draw a ragdoll, limbs have been removed. Character: \"" + character.Name + "\", removed: " + character.Removed + "\n" + Environment.StackTrace);
|
DebugConsole.ThrowError("Failed to draw a ragdoll, limbs have been removed. Character: \"" + character.Name + "\", removed: " + character.Removed + "\n" + Environment.StackTrace);
|
||||||
|
GameAnalyticsManager.AddErrorEventOnce("Ragdoll.Draw:LimbsRemoved",
|
||||||
|
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||||
|
"Failed to draw a ragdoll, limbs have been removed. Character: \"" + character.Name + "\", removed: " + character.Removed + "\n" + Environment.StackTrace);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,7 +100,6 @@ namespace Barotrauma
|
|||||||
|
|
||||||
foreach (Limb limb in Limbs)
|
foreach (Limb limb in Limbs)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (limb.pullJoint != null)
|
if (limb.pullJoint != null)
|
||||||
{
|
{
|
||||||
Vector2 pos = ConvertUnits.ToDisplayUnits(limb.pullJoint.WorldAnchorA);
|
Vector2 pos = ConvertUnits.ToDisplayUnits(limb.pullJoint.WorldAnchorA);
|
||||||
@@ -134,6 +136,16 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (outsideCollisionBlocker.Enabled && currentHull.Submarine != null)
|
||||||
|
{
|
||||||
|
var edgeShape = outsideCollisionBlocker.FixtureList[0].Shape as FarseerPhysics.Collision.Shapes.EdgeShape;
|
||||||
|
Vector2 startPos = ConvertUnits.ToDisplayUnits(outsideCollisionBlocker.GetWorldPoint(edgeShape.Vertex1)) + currentHull.Submarine.Position;
|
||||||
|
Vector2 endPos = ConvertUnits.ToDisplayUnits(outsideCollisionBlocker.GetWorldPoint(edgeShape.Vertex2)) + currentHull.Submarine.Position;
|
||||||
|
startPos.Y = -startPos.Y;
|
||||||
|
endPos.Y = -endPos.Y;
|
||||||
|
GUI.DrawLine(spriteBatch, startPos, endPos, Color.Gray, 0, 5);
|
||||||
|
}
|
||||||
|
|
||||||
if (character.MemState.Count > 1)
|
if (character.MemState.Count > 1)
|
||||||
{
|
{
|
||||||
Vector2 prevPos = ConvertUnits.ToDisplayUnits(character.MemState[0].Position);
|
Vector2 prevPos = ConvertUnits.ToDisplayUnits(character.MemState[0].Position);
|
||||||
|
|||||||
@@ -207,7 +207,7 @@ namespace Barotrauma
|
|||||||
GameMain.GameSession.CrewManager.RemoveCharacter(this);
|
GameMain.GameSession.CrewManager.RemoveCharacter(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GameMain.Client != null && GameMain.Client.Character == this) GameMain.Client.Character = null;
|
if (GameMain.NetworkMember?.Character == this) GameMain.NetworkMember.Character = null;
|
||||||
|
|
||||||
if (Lights.LightManager.ViewTarget == this) Lights.LightManager.ViewTarget = null;
|
if (Lights.LightManager.ViewTarget == this) Lights.LightManager.ViewTarget = null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public static void TakeDamage(float amount)
|
public static void TakeDamage(float amount)
|
||||||
{
|
{
|
||||||
healthBar.Flash();
|
healthBar?.Flash();
|
||||||
|
|
||||||
damageOverlayTimer = MathHelper.Clamp(amount * 0.1f, 0.2f, 1.0f);
|
damageOverlayTimer = MathHelper.Clamp(amount * 0.1f, 0.2f, 1.0f);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -150,7 +150,7 @@ namespace Barotrauma
|
|||||||
msg.ReadPadBits();
|
msg.ReadPadBits();
|
||||||
|
|
||||||
int index = 0;
|
int index = 0;
|
||||||
if (GameMain.NetworkMember.Character == this)
|
if (GameMain.NetworkMember.Character == this && AllowInput)
|
||||||
{
|
{
|
||||||
var posInfo = new CharacterStateInfo(pos, rotation, networkUpdateID, facingRight ? Direction.Right : Direction.Left, selectedEntity, animation);
|
var posInfo = new CharacterStateInfo(pos, rotation, networkUpdateID, facingRight ? Direction.Right : Direction.Left, selectedEntity, animation);
|
||||||
while (index < memState.Count && NetIdUtils.IdMoreRecent(posInfo.ID, memState[index].ID))
|
while (index < memState.Count && NetIdUtils.IdMoreRecent(posInfo.ID, memState[index].ID))
|
||||||
@@ -188,6 +188,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
controlled = this;
|
controlled = this;
|
||||||
IsRemotePlayer = false;
|
IsRemotePlayer = false;
|
||||||
|
GameMain.Client.HasSpawned = true;
|
||||||
GameMain.Client.Character = this;
|
GameMain.Client.Character = this;
|
||||||
GameMain.LightManager.LosEnabled = true;
|
GameMain.LightManager.LosEnabled = true;
|
||||||
}
|
}
|
||||||
@@ -286,6 +287,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (GameMain.Client.ID == ownerId)
|
if (GameMain.Client.ID == ownerId)
|
||||||
{
|
{
|
||||||
|
GameMain.Client.HasSpawned = true;
|
||||||
GameMain.Client.Character = character;
|
GameMain.Client.Character = character;
|
||||||
Controlled = character;
|
Controlled = character;
|
||||||
|
|
||||||
@@ -342,7 +344,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
this.isDead = false;
|
if (this.isDead) Revive();
|
||||||
|
|
||||||
health = msg.ReadRangedSingle(minHealth, maxHealth, 8);
|
health = msg.ReadRangedSingle(minHealth, maxHealth, 8);
|
||||||
|
|
||||||
|
|||||||
@@ -194,10 +194,11 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Color wearableColor = wearable.WearableComponent.Item.GetSpriteColor();
|
||||||
wearable.Sprite.Draw(spriteBatch,
|
wearable.Sprite.Draw(spriteBatch,
|
||||||
new Vector2(body.DrawPosition.X, -body.DrawPosition.Y),
|
new Vector2(body.DrawPosition.X, -body.DrawPosition.Y),
|
||||||
color, origin,
|
new Color((color.R * wearableColor.R) / (255.0f * 255.0f), (color.G * wearableColor.G) / (255.0f * 255.0f), (color.B * wearableColor.B) / (255.0f * 255.0f)) * ((color.A * wearableColor.A) / (255.0f * 255.0f)),
|
||||||
-body.DrawRotation,
|
origin, -body.DrawRotation,
|
||||||
Scale, spriteEffect, depth);
|
Scale, spriteEffect, depth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -355,9 +355,9 @@ namespace Barotrauma
|
|||||||
NewMessage("Removed " + me.Name + " (simposition " + me.SimPosition + ")", Color.Orange);
|
NewMessage("Removed " + me.Name + " (simposition " + me.SimPosition + ")", Color.Orange);
|
||||||
MapEntity.mapEntityList.RemoveAt(i);
|
MapEntity.mapEntityList.RemoveAt(i);
|
||||||
}
|
}
|
||||||
else if (me.MoveWithLevel)
|
else if (!me.ShouldBeSaved)
|
||||||
{
|
{
|
||||||
NewMessage("Removed " + me.Name + " (MoveWithLevel==true)", Color.Orange);
|
NewMessage("Removed " + me.Name + " (!ShouldBeSaved)", Color.Orange);
|
||||||
MapEntity.mapEntityList.RemoveAt(i);
|
MapEntity.mapEntityList.RemoveAt(i);
|
||||||
}
|
}
|
||||||
else if (me is Item)
|
else if (me is Item)
|
||||||
@@ -438,6 +438,8 @@ namespace Barotrauma
|
|||||||
NewMessage("Resolution set to 0 x 0 (screen resolution will be used)", Color.Green);
|
NewMessage("Resolution set to 0 x 0 (screen resolution will be used)", Color.Green);
|
||||||
NewMessage("Fullscreen enabled", Color.Green);
|
NewMessage("Fullscreen enabled", Color.Green);
|
||||||
|
|
||||||
|
GameSettings.ShowUserStatisticsPrompt = true;
|
||||||
|
|
||||||
GameSettings.VerboseLogging = false;
|
GameSettings.VerboseLogging = false;
|
||||||
|
|
||||||
if (GameMain.Config.MasterServerUrl != "http://www.undertowgames.com/baromaster")
|
if (GameMain.Config.MasterServerUrl != "http://www.undertowgames.com/baromaster")
|
||||||
|
|||||||
@@ -214,12 +214,9 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (GameMain.GameSession != null)
|
if (GameMain.GameSession != null)
|
||||||
{
|
{
|
||||||
if (GameSettings.SendUserStatistics)
|
Mission mission = GameMain.GameSession.Mission;
|
||||||
{
|
GameAnalyticsManager.AddDesignEvent("QuitRound:" + (save ? "Save" : "NoSave"));
|
||||||
Mission mission = GameMain.GameSession.Mission;
|
GameAnalyticsManager.AddDesignEvent("EndRound:" + (mission == null ? "NoMission" : (mission.Completed ? "MissionCompleted" : "MissionFailed")));
|
||||||
GameAnalyticsSDK.Net.GameAnalytics.AddDesignEvent("QuitRound:" + (save ? "Save" : "NoSave"));
|
|
||||||
GameAnalyticsSDK.Net.GameAnalytics.AddDesignEvent("EndRound:" + (mission == null ? "NoMission" : (mission.Completed ? "MissionCompleted" : "MissionFailed")));
|
|
||||||
}
|
|
||||||
GameMain.GameSession = null;
|
GameMain.GameSession = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ using System.Collections.Generic;
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using GameAnalyticsSDK.Net;
|
using GameAnalyticsSDK.Net;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
@@ -74,6 +75,7 @@ namespace Barotrauma
|
|||||||
get;
|
get;
|
||||||
private set;
|
private set;
|
||||||
}
|
}
|
||||||
|
private static bool FullscreenOnTabIn;
|
||||||
|
|
||||||
public static WindowMode WindowMode
|
public static WindowMode WindowMode
|
||||||
{
|
{
|
||||||
@@ -231,8 +233,37 @@ namespace Barotrauma
|
|||||||
TitleScreen = new LoadingScreen(GraphicsDevice);
|
TitleScreen = new LoadingScreen(GraphicsDevice);
|
||||||
|
|
||||||
loadingCoroutine = CoroutineManager.StartCoroutine(Load());
|
loadingCoroutine = CoroutineManager.StartCoroutine(Load());
|
||||||
|
|
||||||
|
var myForm = (System.Windows.Forms.Form)System.Windows.Forms.Form.FromHandle(Window.Handle);
|
||||||
|
myForm.Deactivate += new EventHandler(HandleDefocus);
|
||||||
|
myForm.Activated += new EventHandler(HandleFocus);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void HandleDefocus(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (GraphicsDeviceManager.IsFullScreen && GraphicsDeviceManager.HardwareModeSwitch)
|
||||||
|
{
|
||||||
|
GraphicsDeviceManager.IsFullScreen = false;
|
||||||
|
GraphicsDeviceManager.ApplyChanges();
|
||||||
|
FullscreenOnTabIn = true;
|
||||||
|
Thread.Sleep(500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HandleFocus(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (FullscreenOnTabIn)
|
||||||
|
{
|
||||||
|
GraphicsDeviceManager.HardwareModeSwitch = true;
|
||||||
|
GraphicsDeviceManager.IsFullScreen = true;
|
||||||
|
GraphicsDeviceManager.ApplyChanges();
|
||||||
|
FullscreenOnTabIn = false;
|
||||||
|
Thread.Sleep(500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private void InitUserStats()
|
private void InitUserStats()
|
||||||
{
|
{
|
||||||
if (GameSettings.ShowUserStatisticsPrompt)
|
if (GameSettings.ShowUserStatisticsPrompt)
|
||||||
@@ -244,12 +275,18 @@ namespace Barotrauma
|
|||||||
new string[] { "Yes", "No" });
|
new string[] { "Yes", "No" });
|
||||||
userStatsPrompt.Buttons[0].OnClicked += (btn, userdata) =>
|
userStatsPrompt.Buttons[0].OnClicked += (btn, userdata) =>
|
||||||
{
|
{
|
||||||
|
GameSettings.ShowUserStatisticsPrompt = false;
|
||||||
GameSettings.SendUserStatistics = true;
|
GameSettings.SendUserStatistics = true;
|
||||||
GameAnalyticsManager.Init();
|
GameAnalyticsManager.Init();
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
userStatsPrompt.Buttons[0].OnClicked += userStatsPrompt.Close;
|
userStatsPrompt.Buttons[0].OnClicked += userStatsPrompt.Close;
|
||||||
userStatsPrompt.Buttons[1].OnClicked += (btn, userdata) => { GameSettings.SendUserStatistics = false; return true; };
|
userStatsPrompt.Buttons[1].OnClicked += (btn, userdata) =>
|
||||||
|
{
|
||||||
|
GameSettings.ShowUserStatisticsPrompt = false;
|
||||||
|
GameSettings.SendUserStatistics = false;
|
||||||
|
return true;
|
||||||
|
};
|
||||||
userStatsPrompt.Buttons[1].OnClicked += userStatsPrompt.Close;
|
userStatsPrompt.Buttons[1].OnClicked += userStatsPrompt.Close;
|
||||||
}
|
}
|
||||||
else if (GameSettings.SendUserStatistics)
|
else if (GameSettings.SendUserStatistics)
|
||||||
|
|||||||
@@ -92,9 +92,10 @@ namespace Barotrauma
|
|||||||
msg.Write(map.SelectedLocationIndex == -1 ? UInt16.MaxValue : (UInt16)map.SelectedLocationIndex);
|
msg.Write(map.SelectedLocationIndex == -1 ? UInt16.MaxValue : (UInt16)map.SelectedLocationIndex);
|
||||||
|
|
||||||
msg.Write((UInt16)CargoManager.PurchasedItems.Count);
|
msg.Write((UInt16)CargoManager.PurchasedItems.Count);
|
||||||
foreach (ItemPrefab ip in CargoManager.PurchasedItems)
|
foreach (PurchasedItem pi in CargoManager.PurchasedItems)
|
||||||
{
|
{
|
||||||
msg.Write((UInt16)MapEntityPrefab.List.IndexOf(ip));
|
msg.Write((UInt16)MapEntityPrefab.List.IndexOf(pi.itemPrefab));
|
||||||
|
msg.Write((UInt16)pi.quantity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,11 +112,12 @@ namespace Barotrauma
|
|||||||
int money = msg.ReadInt32();
|
int money = msg.ReadInt32();
|
||||||
|
|
||||||
UInt16 purchasedItemCount = msg.ReadUInt16();
|
UInt16 purchasedItemCount = msg.ReadUInt16();
|
||||||
List<ItemPrefab> purchasedItems = new List<ItemPrefab>();
|
List<PurchasedItem> purchasedItems = new List<PurchasedItem>();
|
||||||
for (int i = 0; i < purchasedItemCount; i++)
|
for (int i = 0; i < purchasedItemCount; i++)
|
||||||
{
|
{
|
||||||
UInt16 itemPrefabIndex = msg.ReadUInt16();
|
UInt16 itemPrefabIndex = msg.ReadUInt16();
|
||||||
purchasedItems.Add(MapEntityPrefab.List[itemPrefabIndex] as ItemPrefab);
|
UInt16 itemQuantity = msg.ReadUInt16();
|
||||||
|
purchasedItems.Add(new PurchasedItem(MapEntityPrefab.List[itemPrefabIndex] as ItemPrefab, itemQuantity));
|
||||||
}
|
}
|
||||||
|
|
||||||
MultiPlayerCampaign campaign = GameMain.GameSession?.GameMode as MultiPlayerCampaign;
|
MultiPlayerCampaign campaign = GameMain.GameSession?.GameMode as MultiPlayerCampaign;
|
||||||
|
|||||||
@@ -269,7 +269,7 @@ namespace Barotrauma.Tutorials
|
|||||||
}
|
}
|
||||||
yield return new WaitForSeconds(0.5f);
|
yield return new WaitForSeconds(0.5f);
|
||||||
|
|
||||||
infoBox = CreateInfoFrame("The green rectangle in the middle is the submarine, and the flickering shapes outside it are the walls of an underwater cavern. "
|
infoBox = CreateInfoFrame("The blue rectangle in the middle is the submarine, and the flickering shapes outside it are the walls of an underwater cavern. "
|
||||||
+ "Try moving the submarine by clicking somewhere on the monitor and dragging the pointer to the direction you want to go to.");
|
+ "Try moving the submarine by clicking somewhere on the monitor and dragging the pointer to the direction you want to go to.");
|
||||||
|
|
||||||
while (steering.TargetVelocity == Vector2.Zero && steering.TargetVelocity.Length() < 50.0f)
|
while (steering.TargetVelocity == Vector2.Zero && steering.TargetVelocity.Length() < 50.0f)
|
||||||
|
|||||||
@@ -224,21 +224,27 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Starts a coroutine that will read the correct state of the component from the NetBuffer when correctionTimer reaches zero.
|
//Starts a coroutine that will read the correct state of the component from the NetBuffer when correctionTimer reaches zero.
|
||||||
protected void StartDelayedCorrection(ServerNetObject type, NetBuffer buffer, float sendingTime)
|
protected void StartDelayedCorrection(ServerNetObject type, NetBuffer buffer, float sendingTime, bool waitForMidRoundSync = false)
|
||||||
{
|
{
|
||||||
if (delayedCorrectionCoroutine != null) CoroutineManager.StopCoroutines(delayedCorrectionCoroutine);
|
if (delayedCorrectionCoroutine != null) CoroutineManager.StopCoroutines(delayedCorrectionCoroutine);
|
||||||
|
|
||||||
delayedCorrectionCoroutine = CoroutineManager.StartCoroutine(DoDelayedCorrection(type, buffer, sendingTime));
|
delayedCorrectionCoroutine = CoroutineManager.StartCoroutine(DoDelayedCorrection(type, buffer, sendingTime, waitForMidRoundSync));
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerable<object> DoDelayedCorrection(ServerNetObject type, NetBuffer buffer, float sendingTime)
|
private IEnumerable<object> DoDelayedCorrection(ServerNetObject type, NetBuffer buffer, float sendingTime, bool waitForMidRoundSync)
|
||||||
{
|
{
|
||||||
while (correctionTimer > 0.0f)
|
while (GameMain.Client != null &&
|
||||||
|
(correctionTimer > 0.0f || (waitForMidRoundSync && GameMain.Client.MidRoundSyncing)))
|
||||||
{
|
{
|
||||||
correctionTimer -= CoroutineManager.DeltaTime;
|
correctionTimer -= CoroutineManager.DeltaTime;
|
||||||
yield return CoroutineStatus.Running;
|
yield return CoroutineStatus.Running;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (item.Removed || GameMain.Client == null)
|
||||||
|
{
|
||||||
|
yield return CoroutineStatus.Success;
|
||||||
|
}
|
||||||
|
|
||||||
((IServerSerializable)this).ClientRead(type, buffer, sendingTime);
|
((IServerSerializable)this).ClientRead(type, buffer, sendingTime);
|
||||||
|
|
||||||
correctionTimer = 0.0f;
|
correctionTimer = 0.0f;
|
||||||
|
|||||||
@@ -6,9 +6,7 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
|
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
|
||||||
{
|
{
|
||||||
var focusTarget = GetFocusTarget();
|
if (focusTarget != null && character.ViewTarget == focusTarget)
|
||||||
if (focusTarget == null) return;
|
|
||||||
if (character.ViewTarget == focusTarget)
|
|
||||||
{
|
{
|
||||||
foreach (ItemComponent ic in focusTarget.components)
|
foreach (ItemComponent ic in focusTarget.components)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ namespace Barotrauma.Items.Components
|
|||||||
if (selectedItemFrame != null) GuiFrame.RemoveChild(selectedItemFrame);
|
if (selectedItemFrame != null) GuiFrame.RemoveChild(selectedItemFrame);
|
||||||
|
|
||||||
//int width = 200, height = 150;
|
//int width = 200, height = 150;
|
||||||
selectedItemFrame = new GUIFrame(new Rectangle(0, 0, (int)(GuiFrame.Rect.Width * 0.4f), 300), Color.Black * 0.8f, Alignment.CenterY | Alignment.Right, null, GuiFrame);
|
selectedItemFrame = new GUIFrame(new Rectangle(0, 0, (int)(GuiFrame.Rect.Width * 0.4f), 350), Color.Black * 0.8f, Alignment.CenterY | Alignment.Right, null, GuiFrame);
|
||||||
|
|
||||||
selectedItemFrame.Padding = new Vector4(10.0f, 10.0f, 10.0f, 10.0f);
|
selectedItemFrame.Padding = new Vector4(10.0f, 10.0f, 10.0f, 10.0f);
|
||||||
|
|
||||||
@@ -106,35 +106,40 @@ namespace Barotrauma.Items.Components
|
|||||||
inadequateSkills = targetItem.RequiredSkills.FindAll(skill => Character.Controlled.GetSkillLevel(skill.Name) < skill.Level);
|
inadequateSkills = targetItem.RequiredSkills.FindAll(skill => Character.Controlled.GetSkillLevel(skill.Name) < skill.Level);
|
||||||
}
|
}
|
||||||
|
|
||||||
Color textColor = Color.White;
|
string text = TextManager.Get("FabricatorRequiredItems")+ ":\n";
|
||||||
string text;
|
foreach (Tuple<ItemPrefab, int, float, bool> ip in targetItem.RequiredItems)
|
||||||
if (!inadequateSkills.Any())
|
|
||||||
{
|
{
|
||||||
text = TextManager.Get("FabricatorRequiredItems")+ ":\n";
|
text += " - " + ip.Item1.Name + " x" + ip.Item2 + (ip.Item3 < 1.0f ? ", " + ip.Item3 * 100 + "% " + TextManager.Get("FabricatorRequiredCondition") + "\n" : "\n");
|
||||||
foreach (Tuple<ItemPrefab, int, float, bool> ip in targetItem.RequiredItems)
|
|
||||||
{
|
|
||||||
text += " - " + ip.Item1.Name + " x" + ip.Item2 + (ip.Item3 < 1.0f ? ", " + ip.Item3 * 100 + "% " + TextManager.Get("FabricatorRequiredCondition") + "\n" : "\n");
|
|
||||||
}
|
|
||||||
text += TextManager.Get("FabricatorRequiredTime") + ": " + targetItem.RequiredTime + " s";
|
|
||||||
}
|
}
|
||||||
else
|
text += TextManager.Get("FabricatorRequiredTime") + ": " + targetItem.RequiredTime + " s\n";
|
||||||
|
|
||||||
|
var requiredItemsText = new GUITextBlock(
|
||||||
|
new Rectangle(0, y, 0, 0),
|
||||||
|
text,
|
||||||
|
Color.Transparent, Color.White,
|
||||||
|
Alignment.TopLeft,
|
||||||
|
Alignment.TopLeft, null,
|
||||||
|
selectedItemFrame,
|
||||||
|
font: GUI.SmallFont);
|
||||||
|
|
||||||
|
|
||||||
|
if (targetItem.RequiredSkills.Any())
|
||||||
{
|
{
|
||||||
text = TextManager.Get("FabricatorRequiredSkills") + ":\n";
|
text = TextManager.Get("FabricatorRequiredSkills") + ":\n";
|
||||||
foreach (Skill skill in inadequateSkills)
|
foreach (Skill skill in inadequateSkills)
|
||||||
{
|
{
|
||||||
text += " - " + skill.Name + " " + TextManager.Get("Lvl").ToLower() + " " + skill.Level + "\n";
|
text += " - " + skill.Name + " " + TextManager.Get("Lvl").ToLower() + " " + skill.Level + "\n";
|
||||||
}
|
}
|
||||||
|
new GUITextBlock(
|
||||||
textColor = Color.Red;
|
new Rectangle(0, y + requiredItemsText.Rect.Height, 0, 0),
|
||||||
|
text,
|
||||||
|
Color.Transparent, inadequateSkills.Any() ? Color.Red : Color.White,
|
||||||
|
Alignment.TopLeft,
|
||||||
|
Alignment.TopLeft, null,
|
||||||
|
selectedItemFrame,
|
||||||
|
font: GUI.SmallFont);
|
||||||
}
|
}
|
||||||
|
|
||||||
new GUITextBlock(
|
|
||||||
new Rectangle(0, y, 0, 25),
|
|
||||||
text,
|
|
||||||
Color.Transparent, textColor,
|
|
||||||
Alignment.TopLeft,
|
|
||||||
Alignment.TopLeft, null,
|
|
||||||
selectedItemFrame);
|
|
||||||
|
|
||||||
activateButton = new GUIButton(new Rectangle(0, -30, 100, 20), TextManager.Get("FabricatorCreate"), Color.White, Alignment.CenterX | Alignment.Bottom, "", selectedItemFrame);
|
activateButton = new GUIButton(new Rectangle(0, -30, 100, 20), TextManager.Get("FabricatorCreate"), Color.White, Alignment.CenterX | Alignment.Bottom, "", selectedItemFrame);
|
||||||
activateButton.OnClicked = StartButtonClicked;
|
activateButton.OnClicked = StartButtonClicked;
|
||||||
|
|||||||
@@ -46,14 +46,14 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
levelStartTickBox = new GUITickBox(
|
levelStartTickBox = new GUITickBox(
|
||||||
new Rectangle(5, 70, 15, 15),
|
new Rectangle(5, 70, 15, 15),
|
||||||
GameMain.GameSession == null ? "" : ToolBox.LimitString(GameMain.GameSession.StartLocation.Name, 20),
|
GameMain.GameSession?.StartLocation == null ? "" : ToolBox.LimitString(GameMain.GameSession.StartLocation.Name, 20),
|
||||||
Alignment.TopLeft, GUI.SmallFont, GuiFrame);
|
Alignment.TopLeft, GUI.SmallFont, GuiFrame);
|
||||||
levelStartTickBox.Enabled = false;
|
levelStartTickBox.Enabled = false;
|
||||||
levelStartTickBox.OnSelected = SelectDestination;
|
levelStartTickBox.OnSelected = SelectDestination;
|
||||||
|
|
||||||
levelEndTickBox = new GUITickBox(
|
levelEndTickBox = new GUITickBox(
|
||||||
new Rectangle(5, 90, 15, 15),
|
new Rectangle(5, 90, 15, 15),
|
||||||
GameMain.GameSession == null ? "" : ToolBox.LimitString(GameMain.GameSession.EndLocation.Name, 20),
|
GameMain.GameSession?.EndLocation == null ? "" : ToolBox.LimitString(GameMain.GameSession.EndLocation.Name, 20),
|
||||||
Alignment.TopLeft, GUI.SmallFont, GuiFrame);
|
Alignment.TopLeft, GUI.SmallFont, GuiFrame);
|
||||||
levelEndTickBox.Enabled = false;
|
levelEndTickBox.Enabled = false;
|
||||||
levelEndTickBox.OnSelected = SelectDestination;
|
levelEndTickBox.OnSelected = SelectDestination;
|
||||||
|
|||||||
@@ -34,16 +34,19 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
Wire equippedWire = null;
|
Wire equippedWire = null;
|
||||||
|
|
||||||
//if the Character using the panel has a wire item equipped
|
if (!panel.Locked || Screen.Selected == GameMain.SubEditorScreen)
|
||||||
//and the wire hasn't been connected yet, draw it on the panel
|
|
||||||
for (int i = 0; i < character.SelectedItems.Length; i++)
|
|
||||||
{
|
{
|
||||||
Item selectedItem = character.SelectedItems[i];
|
//if the Character using the panel has a wire item equipped
|
||||||
|
//and the wire hasn't been connected yet, draw it on the panel
|
||||||
|
for (int i = 0; i < character.SelectedItems.Length; i++)
|
||||||
|
{
|
||||||
|
Item selectedItem = character.SelectedItems[i];
|
||||||
|
|
||||||
if (selectedItem == null) continue;
|
if (selectedItem == null) continue;
|
||||||
|
|
||||||
Wire wireComponent = selectedItem.GetComponent<Wire>();
|
Wire wireComponent = selectedItem.GetComponent<Wire>();
|
||||||
if (wireComponent != null) equippedWire = wireComponent;
|
if (wireComponent != null) equippedWire = wireComponent;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector2 rightPos = new Vector2(x + width - 130, y + 50);
|
Vector2 rightPos = new Vector2(x + width - 130, y + 50);
|
||||||
@@ -71,7 +74,7 @@ namespace Barotrauma.Items.Components
|
|||||||
//outputs are drawn at the right side of the panel, inputs at the left
|
//outputs are drawn at the right side of the panel, inputs at the left
|
||||||
if (c.IsOutput)
|
if (c.IsOutput)
|
||||||
{
|
{
|
||||||
c.Draw(spriteBatch, panel.Item, rightPos,
|
c.Draw(spriteBatch, panel, rightPos,
|
||||||
new Vector2(rightPos.X - GUI.SmallFont.MeasureString(c.Name).X - 20, rightPos.Y + 3),
|
new Vector2(rightPos.X - GUI.SmallFont.MeasureString(c.Name).X - 20, rightPos.Y + 3),
|
||||||
rightWirePos,
|
rightWirePos,
|
||||||
mouseInRect, equippedWire,
|
mouseInRect, equippedWire,
|
||||||
@@ -82,7 +85,7 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
c.Draw(spriteBatch, panel.Item, leftPos,
|
c.Draw(spriteBatch, panel, leftPos,
|
||||||
new Vector2(leftPos.X + 20, leftPos.Y - 12),
|
new Vector2(leftPos.X + 20, leftPos.Y - 12),
|
||||||
leftWirePos,
|
leftWirePos,
|
||||||
mouseInRect, equippedWire,
|
mouseInRect, equippedWire,
|
||||||
@@ -96,7 +99,7 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
if (draggingConnected != null)
|
if (draggingConnected != null)
|
||||||
{
|
{
|
||||||
DrawWire(spriteBatch, draggingConnected, draggingConnected.Item, PlayerInput.MousePosition, new Vector2(x + width / 2, y + height), mouseInRect, null);
|
DrawWire(spriteBatch, draggingConnected, draggingConnected.Item, PlayerInput.MousePosition, new Vector2(x + width / 2, y + height), mouseInRect, null, panel);
|
||||||
|
|
||||||
if (!PlayerInput.LeftButtonHeld())
|
if (!PlayerInput.LeftButtonHeld())
|
||||||
{
|
{
|
||||||
@@ -121,7 +124,7 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
DrawWire(spriteBatch, equippedWire, equippedWire.Item,
|
DrawWire(spriteBatch, equippedWire, equippedWire.Item,
|
||||||
new Vector2(x + width / 2, y + height - 100),
|
new Vector2(x + width / 2, y + height - 100),
|
||||||
new Vector2(x + width / 2, y + height), mouseInRect, null);
|
new Vector2(x + width / 2, y + height), mouseInRect, null, panel);
|
||||||
|
|
||||||
if (draggingConnected == equippedWire) Inventory.draggingItem = equippedWire.Item;
|
if (draggingConnected == equippedWire) Inventory.draggingItem = equippedWire.Item;
|
||||||
}
|
}
|
||||||
@@ -135,7 +138,7 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Draw(SpriteBatch spriteBatch, Item item, Vector2 position, Vector2 labelPos, Vector2 wirePosition, bool mouseIn, Wire equippedWire, float wireInterval)
|
private void Draw(SpriteBatch spriteBatch, ConnectionPanel panel, Vector2 position, Vector2 labelPos, Vector2 wirePosition, bool mouseIn, Wire equippedWire, float wireInterval)
|
||||||
{
|
{
|
||||||
//spriteBatch.DrawString(GUI.SmallFont, Name, new Vector2(labelPos.X, labelPos.Y-10), Color.White);
|
//spriteBatch.DrawString(GUI.SmallFont, Name, new Vector2(labelPos.X, labelPos.Y-10), Color.White);
|
||||||
GUI.DrawString(spriteBatch, labelPos, Name, IsPower ? Color.Red : Color.White, Color.Black, 0, GUI.SmallFont);
|
GUI.DrawString(spriteBatch, labelPos, Name, IsPower ? Color.Red : Color.White, Color.Black, 0, GUI.SmallFont);
|
||||||
@@ -149,7 +152,7 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
Connection recipient = Wires[i].OtherConnection(this);
|
Connection recipient = Wires[i].OtherConnection(this);
|
||||||
|
|
||||||
DrawWire(spriteBatch, Wires[i], (recipient == null) ? Wires[i].Item : recipient.item, position, wirePosition, mouseIn, equippedWire);
|
DrawWire(spriteBatch, Wires[i], (recipient == null) ? Wires[i].Item : recipient.item, position, wirePosition, mouseIn, equippedWire, panel);
|
||||||
|
|
||||||
wirePosition.Y += wireInterval;
|
wirePosition.Y += wireInterval;
|
||||||
}
|
}
|
||||||
@@ -165,9 +168,9 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
if (index > -1 && !Wires.Contains(draggingConnected))
|
if (index > -1 && !Wires.Contains(draggingConnected))
|
||||||
{
|
{
|
||||||
bool alreadyConnected = draggingConnected.IsConnectedTo(item);
|
bool alreadyConnected = draggingConnected.IsConnectedTo(panel.Item);
|
||||||
|
|
||||||
draggingConnected.RemoveConnection(item);
|
draggingConnected.RemoveConnection(panel.Item);
|
||||||
|
|
||||||
if (draggingConnected.Connect(this, !alreadyConnected, true))
|
if (draggingConnected.Connect(this, !alreadyConnected, true))
|
||||||
{
|
{
|
||||||
@@ -198,7 +201,7 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void DrawWire(SpriteBatch spriteBatch, Wire wire, Item item, Vector2 end, Vector2 start, bool mouseIn, Wire equippedWire)
|
private static void DrawWire(SpriteBatch spriteBatch, Wire wire, Item item, Vector2 end, Vector2 start, bool mouseIn, Wire equippedWire, ConnectionPanel panel)
|
||||||
{
|
{
|
||||||
if (draggingConnected == wire)
|
if (draggingConnected == wire)
|
||||||
{
|
{
|
||||||
@@ -225,7 +228,7 @@ namespace Barotrauma.Items.Components
|
|||||||
Vector2.Distance(end, PlayerInput.MousePosition) < 20.0f ||
|
Vector2.Distance(end, PlayerInput.MousePosition) < 20.0f ||
|
||||||
new Rectangle((start.X < end.X) ? textX - 100 : textX, (int)start.Y - 5, 100, 14).Contains(PlayerInput.MousePosition));
|
new Rectangle((start.X < end.X) ? textX - 100 : textX, (int)start.Y - 5, 100, 14).Contains(PlayerInput.MousePosition));
|
||||||
|
|
||||||
string label = wire.Locked ? item.Name + "\n" + TextManager.Get("ConnectionLocked") : item.Name;
|
string label = wire.Locked || panel.Locked ? item.Name + "\n" + TextManager.Get("ConnectionLocked") : item.Name;
|
||||||
|
|
||||||
GUI.DrawString(spriteBatch,
|
GUI.DrawString(spriteBatch,
|
||||||
new Vector2(start.X < end.X ? textX - GUI.SmallFont.MeasureString(label).X : textX, start.Y - 5.0f),
|
new Vector2(start.X < end.X ? textX - GUI.SmallFont.MeasureString(label).X : textX, start.Y - 5.0f),
|
||||||
@@ -261,7 +264,7 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
ConnectionPanel.HighlightedWire = wire;
|
ConnectionPanel.HighlightedWire = wire;
|
||||||
|
|
||||||
if (!wire.Locked)
|
if (!wire.Locked && (!panel.Locked || Screen.Selected == GameMain.SubEditorScreen))
|
||||||
{
|
{
|
||||||
//start dragging the wire
|
//start dragging the wire
|
||||||
if (PlayerInput.LeftButtonHeld()) draggingConnected = wire;
|
if (PlayerInput.LeftButtonHeld()) draggingConnected = wire;
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
using Barotrauma.Networking;
|
using Barotrauma.Networking;
|
||||||
|
using Lidgren.Network;
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace Barotrauma.Items.Components
|
namespace Barotrauma.Items.Components
|
||||||
{
|
{
|
||||||
@@ -24,5 +28,66 @@ namespace Barotrauma.Items.Components
|
|||||||
HighlightedWire = null;
|
HighlightedWire = null;
|
||||||
Connection.DrawConnections(spriteBatch, this, character);
|
Connection.DrawConnections(spriteBatch, this, character);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void ClientRead(ServerNetObject type, NetBuffer msg, float sendingTime)
|
||||||
|
{
|
||||||
|
if (GameMain.Client.MidRoundSyncing)
|
||||||
|
{
|
||||||
|
//delay reading the state until midround syncing is done
|
||||||
|
//because some of the wires connected to the panel may not exist yet
|
||||||
|
int bitsToRead = Connections.Count * Connection.MaxLinked * 16;
|
||||||
|
StartDelayedCorrection(type, msg.ExtractBits(bitsToRead), sendingTime, waitForMidRoundSync: true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ApplyRemoteState(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ApplyRemoteState(NetBuffer msg)
|
||||||
|
{
|
||||||
|
List<Wire> prevWires = Connections.SelectMany(c => Array.FindAll(c.Wires, w => w != null)).ToList();
|
||||||
|
List<Wire> newWires = new List<Wire>();
|
||||||
|
|
||||||
|
foreach (Connection connection in Connections)
|
||||||
|
{
|
||||||
|
connection.ClearConnections();
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (Connection connection in Connections)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < Connection.MaxLinked; i++)
|
||||||
|
{
|
||||||
|
ushort wireId = msg.ReadUInt16();
|
||||||
|
|
||||||
|
Item wireItem = Entity.FindEntityByID(wireId) as Item;
|
||||||
|
if (wireItem == null) continue;
|
||||||
|
|
||||||
|
Wire wireComponent = wireItem.GetComponent<Wire>();
|
||||||
|
if (wireComponent == null) continue;
|
||||||
|
|
||||||
|
newWires.Add(wireComponent);
|
||||||
|
|
||||||
|
connection.Wires[i] = wireComponent;
|
||||||
|
wireComponent.Connect(connection, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (Wire wire in prevWires)
|
||||||
|
{
|
||||||
|
if (wire.Connections[0] == null && wire.Connections[1] == null)
|
||||||
|
{
|
||||||
|
wire.Item.Drop(null);
|
||||||
|
}
|
||||||
|
//wires that are not in anyone's inventory (i.e. not currently being rewired) can never be connected to only one connection
|
||||||
|
// -> someone must have dropped the wire from the connection panel
|
||||||
|
else if (wire.Item.ParentInventory == null &&
|
||||||
|
(wire.Connections[0] != null ^ wire.Connections[1] != null))
|
||||||
|
{
|
||||||
|
wire.Item.Drop(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,9 +52,16 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
|
|
||||||
Vector2 drawOffset = Vector2.Zero;
|
Vector2 drawOffset = Vector2.Zero;
|
||||||
if (item.Submarine != null)
|
Submarine sub = item.Submarine;
|
||||||
|
if (IsActive && sub == null) // currently being rewired, we need to get the sub from the connections in case the wire has been taken outside
|
||||||
{
|
{
|
||||||
drawOffset = item.Submarine.DrawPosition + item.Submarine.HiddenSubPosition;
|
if (connections[0] != null && connections[0].Item.Submarine != null) sub = connections[0].Item.Submarine;
|
||||||
|
if (connections[1] != null && connections[1].Item.Submarine != null) sub = connections[1].Item.Submarine;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sub != null)
|
||||||
|
{
|
||||||
|
drawOffset = sub.DrawPosition + sub.HiddenSubPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
float depth = item.IsSelected ? 0.0f : wireSprite.Depth + ((item.ID % 100) * 0.00001f);
|
float depth = item.IsSelected ? 0.0f : wireSprite.Depth + ((item.ID % 100) * 0.00001f);
|
||||||
@@ -76,7 +83,7 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
foreach (WireSection section in sections)
|
foreach (WireSection section in sections)
|
||||||
{
|
{
|
||||||
section.Draw(spriteBatch, item.Submarine == null ? Color.Green : item.Color, drawOffset, depth, 0.3f);
|
section.Draw(spriteBatch, item.Color, drawOffset, depth, 0.3f);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsActive && nodes.Count > 0 && Vector2.Distance(newNodePos, nodes[nodes.Count - 1]) > nodeDistance)
|
if (IsActive && nodes.Count > 0 && Vector2.Distance(newNodePos, nodes[nodes.Count - 1]) > nodeDistance)
|
||||||
|
|||||||
@@ -148,8 +148,10 @@ namespace Barotrauma.Items.Components
|
|||||||
public void ClientRead(ServerNetObject type, NetBuffer msg, float sendingTime)
|
public void ClientRead(ServerNetObject type, NetBuffer msg, float sendingTime)
|
||||||
{
|
{
|
||||||
UInt16 projectileID = msg.ReadUInt16();
|
UInt16 projectileID = msg.ReadUInt16();
|
||||||
Item projectile = Entity.FindEntityByID(projectileID) as Item;
|
//projectile removed, do nothing
|
||||||
|
if (projectileID == 0) return;
|
||||||
|
|
||||||
|
Item projectile = Entity.FindEntityByID(projectileID) as Item;
|
||||||
if (projectile == null)
|
if (projectile == null)
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError("Failed to launch a projectile - item with the ID \"" + projectileID + " not found");
|
DebugConsole.ThrowError("Failed to launch a projectile - item with the ID \"" + projectileID + " not found");
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
using Barotrauma.Networking;
|
using Barotrauma.Networking;
|
||||||
|
using FarseerPhysics;
|
||||||
|
using FarseerPhysics.Collision;
|
||||||
|
using FarseerPhysics.Dynamics;
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
|
||||||
@@ -58,6 +61,43 @@ namespace Barotrauma.Items.Components
|
|||||||
rect.Width, (int)(rect.Height / 2 * dockingState)), Color.White);
|
rect.Width, (int)(rect.Height / 2 * dockingState)), Color.White);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!GameMain.DebugDraw) return;
|
||||||
|
|
||||||
|
if (bodies != null)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < bodies.Length; i++)
|
||||||
|
{
|
||||||
|
var body = bodies[i];
|
||||||
|
if (body == null) continue;
|
||||||
|
|
||||||
|
body.FixtureList[0].GetAABB(out AABB aabb, 0);
|
||||||
|
|
||||||
|
Vector2 bodyDrawPos = ConvertUnits.ToDisplayUnits(new Vector2(aabb.LowerBound.X, aabb.UpperBound.Y));
|
||||||
|
if ((i == 1 || i == 3) && dockingTarget?.item?.Submarine != null) bodyDrawPos += dockingTarget.item.Submarine.Position;
|
||||||
|
if ((i == 0 || i == 2) && item.Submarine != null) bodyDrawPos += item.Submarine.Position;
|
||||||
|
bodyDrawPos.Y = -bodyDrawPos.Y;
|
||||||
|
|
||||||
|
GUI.DrawRectangle(spriteBatch,
|
||||||
|
bodyDrawPos,
|
||||||
|
ConvertUnits.ToDisplayUnits(aabb.Extents * 2),
|
||||||
|
Color.Gray, false, 0.0f, 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (doorBody != null && doorBody.Enabled)
|
||||||
|
{
|
||||||
|
doorBody.FixtureList[0].GetAABB(out AABB aabb, 0);
|
||||||
|
|
||||||
|
Vector2 bodyDrawPos = ConvertUnits.ToDisplayUnits(new Vector2(aabb.LowerBound.X, aabb.UpperBound.Y));
|
||||||
|
if (item?.Submarine != null) bodyDrawPos += item.Submarine.Position;
|
||||||
|
bodyDrawPos.Y = -bodyDrawPos.Y;
|
||||||
|
|
||||||
|
GUI.DrawRectangle(spriteBatch,
|
||||||
|
bodyDrawPos,
|
||||||
|
ConvertUnits.ToDisplayUnits(aabb.Extents * 2),
|
||||||
|
Color.Gray, false, 0, 8);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
using Barotrauma.Items.Components;
|
using Barotrauma.Items.Components;
|
||||||
|
using Barotrauma.Networking;
|
||||||
|
using Lidgren.Network;
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
using System;
|
using System;
|
||||||
@@ -464,5 +466,75 @@ namespace Barotrauma
|
|||||||
|
|
||||||
item.Sprite.Draw(spriteBatch, new Vector2(rect.X + rect.Width / 2, rect.Y + rect.Height / 2), item.GetSpriteColor());
|
item.Sprite.Draw(spriteBatch, new Vector2(rect.X + rect.Width / 2, rect.Y + rect.Height / 2), item.GetSpriteColor());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ClientRead(ServerNetObject type, NetBuffer msg, float sendingTime)
|
||||||
|
{
|
||||||
|
receivedItemIDs = new ushort[capacity];
|
||||||
|
|
||||||
|
for (int i = 0; i < capacity; i++)
|
||||||
|
{
|
||||||
|
receivedItemIDs[i] = msg.ReadUInt16();
|
||||||
|
}
|
||||||
|
|
||||||
|
//delay applying the new state if less than 1 second has passed since this client last sent a state to the server
|
||||||
|
//prevents the inventory from briefly reverting to an old state if items are moved around in quick succession
|
||||||
|
|
||||||
|
//also delay if we're still midround syncing, some of the items in the inventory may not exist yet
|
||||||
|
if (syncItemsDelay > 0.0f || GameMain.Client.MidRoundSyncing)
|
||||||
|
{
|
||||||
|
if (syncItemsCoroutine != null) CoroutineManager.StopCoroutines(syncItemsCoroutine);
|
||||||
|
syncItemsCoroutine = CoroutineManager.StartCoroutine(SyncItemsAfterDelay());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (syncItemsCoroutine != null)
|
||||||
|
{
|
||||||
|
CoroutineManager.StopCoroutines(syncItemsCoroutine);
|
||||||
|
syncItemsCoroutine = null;
|
||||||
|
}
|
||||||
|
ApplyReceivedState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<object> SyncItemsAfterDelay()
|
||||||
|
{
|
||||||
|
while (syncItemsDelay > 0.0f || (GameMain.Client != null && GameMain.Client.MidRoundSyncing))
|
||||||
|
{
|
||||||
|
yield return CoroutineStatus.Running;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Owner.Removed || GameMain.Client == null)
|
||||||
|
{
|
||||||
|
yield return CoroutineStatus.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
ApplyReceivedState();
|
||||||
|
|
||||||
|
yield return CoroutineStatus.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ApplyReceivedState()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < capacity; i++)
|
||||||
|
{
|
||||||
|
if (receivedItemIDs[i] == 0 || (Entity.FindEntityByID(receivedItemIDs[i]) as Item != Items[i]))
|
||||||
|
{
|
||||||
|
if (Items[i] != null) Items[i].Drop();
|
||||||
|
System.Diagnostics.Debug.Assert(Items[i] == null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < capacity; i++)
|
||||||
|
{
|
||||||
|
if (receivedItemIDs[i] > 0)
|
||||||
|
{
|
||||||
|
var item = Entity.FindEntityByID(receivedItemIDs[i]) as Item;
|
||||||
|
if (item == null || item == Items[i]) continue;
|
||||||
|
TryPutItem(item, i, true, true, null, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
receivedItemIDs = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -377,11 +377,11 @@ namespace Barotrauma
|
|||||||
(components[componentIndex] as IServerSerializable).ClientRead(type, msg, sendingTime);
|
(components[componentIndex] as IServerSerializable).ClientRead(type, msg, sendingTime);
|
||||||
break;
|
break;
|
||||||
case NetEntityEvent.Type.InventoryState:
|
case NetEntityEvent.Type.InventoryState:
|
||||||
ownInventory.ClientRead(type, msg, sendingTime);
|
int containerIndex = msg.ReadRangedInteger(0, components.Count - 1);
|
||||||
|
(components[containerIndex] as ItemContainer).Inventory.ClientRead(type, msg, sendingTime);
|
||||||
break;
|
break;
|
||||||
case NetEntityEvent.Type.Status:
|
case NetEntityEvent.Type.Status:
|
||||||
condition = msg.ReadRangedSingle(0.0f, prefab.Health, 8);
|
condition = msg.ReadSingle();
|
||||||
|
|
||||||
if (FixRequirements.Count > 0)
|
if (FixRequirements.Count > 0)
|
||||||
{
|
{
|
||||||
if (Condition <= 0.0f)
|
if (Condition <= 0.0f)
|
||||||
@@ -401,10 +401,13 @@ namespace Barotrauma
|
|||||||
ushort targetID = msg.ReadUInt16();
|
ushort targetID = msg.ReadUInt16();
|
||||||
|
|
||||||
Character target = FindEntityByID(targetID) as Character;
|
Character target = FindEntityByID(targetID) as Character;
|
||||||
ApplyStatusEffects(actionType, (float)Timing.Step, target, true);
|
//ignore deltatime - using an item with the useOnSelf buttons is instantaneous
|
||||||
|
ApplyStatusEffects(actionType, 1.0f, target, true);
|
||||||
break;
|
break;
|
||||||
case NetEntityEvent.Type.ChangeProperty:
|
case NetEntityEvent.Type.ChangeProperty:
|
||||||
ReadPropertyChange(msg);
|
ReadPropertyChange(msg, false);
|
||||||
|
break;
|
||||||
|
case NetEntityEvent.Type.Invalid:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -423,11 +426,12 @@ namespace Barotrauma
|
|||||||
case NetEntityEvent.Type.ComponentState:
|
case NetEntityEvent.Type.ComponentState:
|
||||||
int componentIndex = (int)extraData[1];
|
int componentIndex = (int)extraData[1];
|
||||||
msg.WriteRangedInteger(0, components.Count - 1, componentIndex);
|
msg.WriteRangedInteger(0, components.Count - 1, componentIndex);
|
||||||
|
|
||||||
(components[componentIndex] as IClientSerializable).ClientWrite(msg, extraData);
|
(components[componentIndex] as IClientSerializable).ClientWrite(msg, extraData);
|
||||||
break;
|
break;
|
||||||
case NetEntityEvent.Type.InventoryState:
|
case NetEntityEvent.Type.InventoryState:
|
||||||
ownInventory.ClientWrite(msg, extraData);
|
int containerIndex = (int)extraData[1];
|
||||||
|
msg.WriteRangedInteger(0, components.Count - 1, containerIndex);
|
||||||
|
(components[containerIndex] as ItemContainer).Inventory.ClientWrite(msg, extraData);
|
||||||
break;
|
break;
|
||||||
case NetEntityEvent.Type.Repair:
|
case NetEntityEvent.Type.Repair:
|
||||||
if (FixRequirements.Count > 0)
|
if (FixRequirements.Count > 0)
|
||||||
@@ -441,7 +445,7 @@ namespace Barotrauma
|
|||||||
//on the character of the client who sent the message
|
//on the character of the client who sent the message
|
||||||
break;
|
break;
|
||||||
case NetEntityEvent.Type.ChangeProperty:
|
case NetEntityEvent.Type.ChangeProperty:
|
||||||
WritePropertyChange(msg, extraData);
|
WritePropertyChange(msg, extraData, true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
msg.WritePadBits();
|
msg.WritePadBits();
|
||||||
@@ -461,6 +465,19 @@ namespace Barotrauma
|
|||||||
msg.ReadRangedSingle(-MaxVel, MaxVel, 12));
|
msg.ReadRangedSingle(-MaxVel, MaxVel, 12));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!MathUtils.IsValid(newPosition) || !MathUtils.IsValid(newRotation) || !MathUtils.IsValid(newVelocity))
|
||||||
|
{
|
||||||
|
string errorMsg = "Received invalid position data for the item \"" + Name
|
||||||
|
+ "\" (position: " + newPosition + ", rotation: " + newRotation + ", velocity: " + newVelocity + ")";
|
||||||
|
#if DEBUG
|
||||||
|
DebugConsole.ThrowError(errorMsg);
|
||||||
|
#endif
|
||||||
|
GameAnalyticsManager.AddErrorEventOnce("Item.ClientReadPosition:InvalidData" + ID,
|
||||||
|
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||||
|
errorMsg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (body == null)
|
if (body == null)
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError("Received a position update for an item with no physics body (" + Name + ")");
|
DebugConsole.ThrowError("Received a position update for an item with no physics body (" + Name + ")");
|
||||||
@@ -470,7 +487,7 @@ namespace Barotrauma
|
|||||||
body.FarseerBody.Awake = awake;
|
body.FarseerBody.Awake = awake;
|
||||||
if (body.FarseerBody.Awake)
|
if (body.FarseerBody.Awake)
|
||||||
{
|
{
|
||||||
if ((newVelocity - body.LinearVelocity).Length() > 8.0f) body.LinearVelocity = newVelocity;
|
if ((newVelocity - body.LinearVelocity).LengthSquared() > 8.0f * 8.0f) body.LinearVelocity = newVelocity;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -490,11 +507,12 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if ((newPosition - SimPosition).Length() > body.LinearVelocity.Length() * 2.0f)
|
if ((newPosition - SimPosition).Length() > body.LinearVelocity.Length() * 2.0f)
|
||||||
{
|
{
|
||||||
body.SetTransform(newPosition, newRotation);
|
if (body.SetTransform(newPosition, newRotation))
|
||||||
|
{
|
||||||
Vector2 displayPos = ConvertUnits.ToDisplayUnits(body.SimPosition);
|
Vector2 displayPos = ConvertUnits.ToDisplayUnits(body.SimPosition);
|
||||||
rect.X = (int)(displayPos.X - rect.Width / 2.0f);
|
rect.X = (int)(displayPos.X - rect.Width / 2.0f);
|
||||||
rect.Y = (int)(displayPos.Y + rect.Height / 2.0f);
|
rect.Y = (int)(displayPos.Y + rect.Height / 2.0f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ namespace Barotrauma
|
|||||||
return verticeList;
|
return verticeList;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static VertexPositionTexture[] GenerateWallShapes(List<VoronoiCell> cells)
|
public static VertexPositionTexture[] GenerateWallShapes(List<VoronoiCell> cells, Level level)
|
||||||
{
|
{
|
||||||
float inwardThickness = 500.0f, outWardThickness = 30.0f;
|
float inwardThickness = 500.0f, outWardThickness = 30.0f;
|
||||||
|
|
||||||
@@ -80,6 +80,10 @@ namespace Barotrauma
|
|||||||
#if DEBUG
|
#if DEBUG
|
||||||
DebugConsole.ThrowError("Invalid left normal");
|
DebugConsole.ThrowError("Invalid left normal");
|
||||||
#endif
|
#endif
|
||||||
|
GameAnalyticsManager.AddErrorEventOnce("CaveGenerator.GenerateWallShapes:InvalidLeftNormal:" + level.Seed,
|
||||||
|
GameAnalyticsSDK.Net.EGAErrorSeverity.Warning,
|
||||||
|
"Invalid left normal (leftedge: " + leftEdge + ", rightedge: " + rightEdge + ", normal: " + leftNormal + ", seed: " + level.Seed + ")");
|
||||||
|
|
||||||
if (cell.body != null)
|
if (cell.body != null)
|
||||||
{
|
{
|
||||||
GameMain.World.RemoveBody(cell.body);
|
GameMain.World.RemoveBody(cell.body);
|
||||||
@@ -106,6 +110,10 @@ namespace Barotrauma
|
|||||||
#if DEBUG
|
#if DEBUG
|
||||||
DebugConsole.ThrowError("Invalid right normal");
|
DebugConsole.ThrowError("Invalid right normal");
|
||||||
#endif
|
#endif
|
||||||
|
GameAnalyticsManager.AddErrorEventOnce("CaveGenerator.GenerateWallShapes:InvalidRightNormal:" + level.Seed,
|
||||||
|
GameAnalyticsSDK.Net.EGAErrorSeverity.Warning,
|
||||||
|
"Invalid right normal (leftedge: " + leftEdge + ", rightedge: " + rightEdge + ", normal: " + rightNormal + ", seed: " + level.Seed + ")");
|
||||||
|
|
||||||
if (cell.body != null)
|
if (cell.body != null)
|
||||||
{
|
{
|
||||||
GameMain.World.RemoveBody(cell.body);
|
GameMain.World.RemoveBody(cell.body);
|
||||||
|
|||||||
@@ -28,9 +28,16 @@ namespace Barotrauma
|
|||||||
color = Color.LightGray;
|
color = Color.LightGray;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
GUI.DrawRectangle(spriteBatch, new Vector2(pos.Position.X - 15.0f, -pos.Position.Y - 15.0f), new Vector2(30.0f, 30.0f), color, true);
|
GUI.DrawRectangle(spriteBatch, new Vector2(pos.Position.X - 15.0f, -pos.Position.Y - 15.0f), new Vector2(30.0f, 30.0f), color, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach (RuinGeneration.Ruin ruin in ruins)
|
||||||
|
{
|
||||||
|
Rectangle ruinArea = ruin.Area;
|
||||||
|
ruinArea.Y = -ruinArea.Y - ruinArea.Height;
|
||||||
|
|
||||||
|
GUI.DrawRectangle(spriteBatch, ruinArea, Color.DarkSlateBlue, false, 0, 5);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Barotrauma.Networking;
|
using Barotrauma.Networking;
|
||||||
using FarseerPhysics;
|
using FarseerPhysics;
|
||||||
|
using Lidgren.Network;
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
using System;
|
using System;
|
||||||
@@ -145,7 +146,7 @@ namespace Barotrauma
|
|||||||
"", frame, GUI.SmallFont);
|
"", frame, GUI.SmallFont);
|
||||||
|
|
||||||
new GUITextBlock(new Rectangle(246, 100, 100, 20),
|
new GUITextBlock(new Rectangle(246, 100, 100, 20),
|
||||||
TextManager.Get("RecommendedCrewExperience") + ": " + (string.IsNullOrEmpty(RecommendedCrewExperience) ? TextManager.Get("unknown") : RecommendedCrewExperience),
|
TextManager.Get("RecommendedCrewExperience") + ": " + (string.IsNullOrEmpty(RecommendedCrewExperience) ? TextManager.Get("unknown") : TextManager.Get(RecommendedCrewExperience)),
|
||||||
"", frame, GUI.SmallFont);
|
"", frame, GUI.SmallFont);
|
||||||
|
|
||||||
new GUITextBlock(new Rectangle(246, 120, 0, 20),
|
new GUITextBlock(new Rectangle(246, 120, 0, 20),
|
||||||
@@ -179,7 +180,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (WayPoint.WayPointList.Find(wp => !wp.MoveWithLevel && wp.SpawnType == SpawnType.Path) == null)
|
if (!WayPoint.WayPointList.Any(wp => wp.ShouldBeSaved && wp.SpawnType == SpawnType.Path))
|
||||||
{
|
{
|
||||||
errorMsgs.Add(TextManager.Get("NoWaypointsWarning"));
|
errorMsgs.Add(TextManager.Get("NoWaypointsWarning"));
|
||||||
}
|
}
|
||||||
@@ -217,5 +218,32 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ClientRead(ServerNetObject type, NetBuffer msg, float sendingTime)
|
||||||
|
{
|
||||||
|
var newTargetPosition = new Vector2(
|
||||||
|
msg.ReadFloat(),
|
||||||
|
msg.ReadFloat());
|
||||||
|
|
||||||
|
//already interpolating with more up-to-date data -> ignore
|
||||||
|
if (subBody.MemPos.Count > 1 && subBody.MemPos[0].Timestamp > sendingTime)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int index = 0;
|
||||||
|
while (index < subBody.MemPos.Count && sendingTime > subBody.MemPos[index].Timestamp)
|
||||||
|
{
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
//position with the same timestamp already in the buffer (duplicate packet?)
|
||||||
|
// -> no need to add again
|
||||||
|
if (index < subBody.MemPos.Count && sendingTime == subBody.MemPos[index].Timestamp)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
subBody.MemPos.Insert(index, new PosInfo(newTargetPosition, 0.0f, sendingTime));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,18 +32,26 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
if (NetIdUtils.IdMoreRecent(ID, LastID))
|
if (NetIdUtils.IdMoreRecent(ID, LastID))
|
||||||
{
|
{
|
||||||
if (type == ChatMessageType.MessageBox)
|
switch (type)
|
||||||
{
|
{
|
||||||
new GUIMessageBox("", txt);
|
case ChatMessageType.MessageBox:
|
||||||
}
|
new GUIMessageBox("", txt);
|
||||||
else if (type == ChatMessageType.Console)
|
break;
|
||||||
{
|
case ChatMessageType.Console:
|
||||||
DebugConsole.NewMessage(txt, MessageColor[(int)ChatMessageType.Console]);
|
DebugConsole.NewMessage(txt, MessageColor[(int)ChatMessageType.Console]);
|
||||||
}
|
break;
|
||||||
else
|
case ChatMessageType.ServerLog:
|
||||||
{
|
if (!Enum.TryParse(senderName, out ServerLog.MessageType messageType))
|
||||||
GameMain.Client.AddChatMessage(txt, type, senderName, senderCharacter);
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
GameMain.Client.ServerLog?.WriteLine(txt, messageType);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
GameMain.Client.AddChatMessage(txt, type, senderName, senderCharacter);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
LastID = ID;
|
LastID = ID;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,6 +44,9 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
private FileReceiver fileReceiver;
|
private FileReceiver fileReceiver;
|
||||||
|
|
||||||
|
//has the client been given a character to control this round
|
||||||
|
public bool HasSpawned;
|
||||||
|
|
||||||
public byte ID
|
public byte ID
|
||||||
{
|
{
|
||||||
get { return myID; }
|
get { return myID; }
|
||||||
@@ -62,6 +65,17 @@ namespace Barotrauma.Networking
|
|||||||
get { return fileReceiver; }
|
get { return fileReceiver; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool MidRoundSyncing
|
||||||
|
{
|
||||||
|
get { return entityEventManager.MidRoundSyncing; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AllowDisguises
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
private set;
|
||||||
|
}
|
||||||
|
|
||||||
public GameClient(string newName)
|
public GameClient(string newName)
|
||||||
{
|
{
|
||||||
endVoteTickBox = new GUITickBox(new Rectangle(GameMain.GraphicsWidth - 170, 20, 20, 20), "End round", Alignment.TopLeft, inGameHUD);
|
endVoteTickBox = new GUITickBox(new Rectangle(GameMain.GraphicsWidth - 170, 20, 20, 20), "End round", Alignment.TopLeft, inGameHUD);
|
||||||
@@ -99,6 +113,8 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
otherClients = new List<Client>();
|
otherClients = new List<Client>();
|
||||||
|
|
||||||
|
ServerLog = new ServerLog("");
|
||||||
|
|
||||||
ChatMessage.LastID = 0;
|
ChatMessage.LastID = 0;
|
||||||
GameMain.NetLobbyScreen = new NetLobbyScreen();
|
GameMain.NetLobbyScreen = new NetLobbyScreen();
|
||||||
}
|
}
|
||||||
@@ -456,6 +472,9 @@ namespace Barotrauma.Networking
|
|||||||
#if DEBUG
|
#if DEBUG
|
||||||
if (PlayerInput.GetKeyboardState.IsKeyDown(Microsoft.Xna.Framework.Input.Keys.P)) return;
|
if (PlayerInput.GetKeyboardState.IsKeyDown(Microsoft.Xna.Framework.Input.Keys.P)) return;
|
||||||
#endif
|
#endif
|
||||||
|
#if CLIENT
|
||||||
|
if (ServerLog.LogFrame != null) ServerLog.LogFrame.Update(deltaTime);
|
||||||
|
#endif
|
||||||
|
|
||||||
base.Update(deltaTime);
|
base.Update(deltaTime);
|
||||||
|
|
||||||
@@ -480,7 +499,7 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
if (gameStarted && Screen.Selected == GameMain.GameScreen)
|
if (gameStarted && Screen.Selected == GameMain.GameScreen)
|
||||||
{
|
{
|
||||||
endVoteTickBox.Visible = Voting.AllowEndVoting && myCharacter != null;
|
endVoteTickBox.Visible = Voting.AllowEndVoting && HasSpawned;
|
||||||
|
|
||||||
if (respawnManager != null)
|
if (respawnManager != null)
|
||||||
{
|
{
|
||||||
@@ -659,6 +678,8 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
GameMain.NetLobbyScreen.SubList.Enabled = Voting.AllowSubVoting || HasPermission(ClientPermissions.SelectSub);
|
GameMain.NetLobbyScreen.SubList.Enabled = Voting.AllowSubVoting || HasPermission(ClientPermissions.SelectSub);
|
||||||
GameMain.NetLobbyScreen.ModeList.Enabled = Voting.AllowModeVoting || HasPermission(ClientPermissions.SelectMode);
|
GameMain.NetLobbyScreen.ModeList.Enabled = Voting.AllowModeVoting || HasPermission(ClientPermissions.SelectMode);
|
||||||
|
GameMain.NetLobbyScreen.InfoFrame.FindChild("showlog").Visible = HasPermission(ClientPermissions.ServerLog);
|
||||||
|
showLogButton.Visible = HasPermission(ClientPermissions.ServerLog);
|
||||||
|
|
||||||
endRoundButton.Visible = HasPermission(ClientPermissions.EndRound);
|
endRoundButton.Visible = HasPermission(ClientPermissions.EndRound);
|
||||||
}
|
}
|
||||||
@@ -666,6 +687,7 @@ namespace Barotrauma.Networking
|
|||||||
private IEnumerable<object> StartGame(NetIncomingMessage inc)
|
private IEnumerable<object> StartGame(NetIncomingMessage inc)
|
||||||
{
|
{
|
||||||
if (Character != null) Character.Remove();
|
if (Character != null) Character.Remove();
|
||||||
|
HasSpawned = false;
|
||||||
|
|
||||||
GameMain.LightManager.LightingEnabled = true;
|
GameMain.LightManager.LightingEnabled = true;
|
||||||
|
|
||||||
@@ -696,6 +718,7 @@ namespace Barotrauma.Networking
|
|||||||
bool respawnAllowed = inc.ReadBoolean();
|
bool respawnAllowed = inc.ReadBoolean();
|
||||||
bool loadSecondSub = inc.ReadBoolean();
|
bool loadSecondSub = inc.ReadBoolean();
|
||||||
|
|
||||||
|
bool disguisesAllowed = inc.ReadBoolean();
|
||||||
bool isTraitor = inc.ReadBoolean();
|
bool isTraitor = inc.ReadBoolean();
|
||||||
string traitorTargetName = isTraitor ? inc.ReadString() : null;
|
string traitorTargetName = isTraitor ? inc.ReadString() : null;
|
||||||
|
|
||||||
@@ -734,6 +757,8 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
GameMain.NetLobbyScreen.UsingShuttle = usingShuttle;
|
GameMain.NetLobbyScreen.UsingShuttle = usingShuttle;
|
||||||
|
|
||||||
|
AllowDisguises = disguisesAllowed;
|
||||||
|
|
||||||
if (campaign == null)
|
if (campaign == null)
|
||||||
{
|
{
|
||||||
if (!GameMain.NetLobbyScreen.TrySelectSub(subName, subHash, GameMain.NetLobbyScreen.SubList))
|
if (!GameMain.NetLobbyScreen.TrySelectSub(subName, subHash, GameMain.NetLobbyScreen.SubList))
|
||||||
@@ -757,7 +782,10 @@ namespace Barotrauma.Networking
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (GameMain.GameSession?.CrewManager != null) GameMain.GameSession.CrewManager.Reset();
|
if (GameMain.GameSession?.CrewManager != null) GameMain.GameSession.CrewManager.Reset();
|
||||||
GameMain.GameSession.StartRound(campaign.Map.SelectedConnection.Level, true, false);
|
GameMain.GameSession.StartRound(campaign.Map.SelectedConnection.Level,
|
||||||
|
reloadSub: true,
|
||||||
|
loadSecondSub: false,
|
||||||
|
mirrorLevel: campaign.Map.CurrentLocation != campaign.Map.SelectedConnection.Locations[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (respawnAllowed) respawnManager = new RespawnManager(this, GameMain.NetLobbyScreen.UsingShuttle ? GameMain.NetLobbyScreen.SelectedShuttle : null);
|
if (respawnAllowed) respawnManager = new RespawnManager(this, GameMain.NetLobbyScreen.UsingShuttle ? GameMain.NetLobbyScreen.SelectedShuttle : null);
|
||||||
@@ -815,7 +843,7 @@ namespace Barotrauma.Networking
|
|||||||
string subName = inc.ReadString();
|
string subName = inc.ReadString();
|
||||||
string subHash = inc.ReadString();
|
string subHash = inc.ReadString();
|
||||||
|
|
||||||
var matchingSub = Submarine.SavedSubmarines.Find(s => s.Name == subName && s.MD5Hash.Hash == subHash);
|
var matchingSub = Submarine.SavedSubmarines.FirstOrDefault(s => s.Name == subName && s.MD5Hash.Hash == subHash);
|
||||||
if (matchingSub != null)
|
if (matchingSub != null)
|
||||||
{
|
{
|
||||||
submarines.Add(matchingSub);
|
submarines.Add(matchingSub);
|
||||||
@@ -908,6 +936,8 @@ namespace Barotrauma.Networking
|
|||||||
{
|
{
|
||||||
GameMain.NetLobbyScreen.LastUpdateID = updateID;
|
GameMain.NetLobbyScreen.LastUpdateID = updateID;
|
||||||
|
|
||||||
|
ServerLog.ServerName = serverName;
|
||||||
|
|
||||||
GameMain.NetLobbyScreen.ServerName = serverName;
|
GameMain.NetLobbyScreen.ServerName = serverName;
|
||||||
GameMain.NetLobbyScreen.ServerMessage.Text = serverText;
|
GameMain.NetLobbyScreen.ServerMessage.Text = serverText;
|
||||||
|
|
||||||
@@ -982,6 +1012,9 @@ namespace Barotrauma.Networking
|
|||||||
long prevBitPos = 0;
|
long prevBitPos = 0;
|
||||||
long prevBytePos = 0;
|
long prevBytePos = 0;
|
||||||
|
|
||||||
|
long prevBitLength = 0;
|
||||||
|
long prevByteLength = 0;
|
||||||
|
|
||||||
ServerNetObject objHeader;
|
ServerNetObject objHeader;
|
||||||
while ((objHeader = (ServerNetObject)inc.ReadByte()) != ServerNetObject.END_OF_MESSAGE)
|
while ((objHeader = (ServerNetObject)inc.ReadByte()) != ServerNetObject.END_OF_MESSAGE)
|
||||||
{
|
{
|
||||||
@@ -1016,41 +1049,53 @@ namespace Barotrauma.Networking
|
|||||||
ChatMessage.ClientRead(inc);
|
ChatMessage.ClientRead(inc);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
DebugConsole.ThrowError("Error while reading update from server (unknown object header \""+objHeader+"\"!)");
|
List<string> errorLines = new List<string>
|
||||||
if (prevObjHeader != null)
|
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError("Previous object type: " + prevObjHeader.ToString());
|
"Error while reading update from server (unknown object header \"" + objHeader + "\"!)",
|
||||||
}
|
"Message length: " + inc.LengthBits + " (" + inc.LengthBytes + " bytes)",
|
||||||
else
|
prevObjHeader != null ? "Previous object type: " + prevObjHeader.ToString() : "Error occurred on the very first object!",
|
||||||
{
|
"Previous object was " + (prevBitLength) + " bits long (" + (prevByteLength) + " bytes)"
|
||||||
DebugConsole.ThrowError("Error occurred on the very first object!");
|
};
|
||||||
}
|
|
||||||
DebugConsole.ThrowError("Previous object was " + (inc.Position - prevBitPos) + " bits long (" + (inc.PositionInBytes - prevBytePos) + " bytes)");
|
|
||||||
if (prevObjHeader == ServerNetObject.ENTITY_EVENT || prevObjHeader == ServerNetObject.ENTITY_EVENT_INITIAL)
|
if (prevObjHeader == ServerNetObject.ENTITY_EVENT || prevObjHeader == ServerNetObject.ENTITY_EVENT_INITIAL)
|
||||||
{
|
{
|
||||||
foreach (IServerSerializable ent in entities)
|
foreach (IServerSerializable ent in entities)
|
||||||
{
|
{
|
||||||
if (ent == null)
|
if (ent == null)
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError(" - NULL");
|
errorLines.Add(" - NULL");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Entity e = ent as Entity;
|
Entity e = ent as Entity;
|
||||||
DebugConsole.ThrowError(" - "+e.ToString());
|
errorLines.Add(" - " + e.ToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach (string line in errorLines)
|
||||||
|
{
|
||||||
|
DebugConsole.ThrowError(line);
|
||||||
|
}
|
||||||
|
errorLines.Add("Last console messages:");
|
||||||
|
for (int i = DebugConsole.Messages.Count - 1; i > Math.Max(0, DebugConsole.Messages.Count - 20); i--)
|
||||||
|
{
|
||||||
|
errorLines.Add("[" + DebugConsole.Messages[i].Time + "] " + DebugConsole.Messages[i].Text);
|
||||||
|
}
|
||||||
|
GameAnalyticsManager.AddErrorEventOnce("GameClient.ReadInGameUpdate", GameAnalyticsSDK.Net.EGAErrorSeverity.Critical, string.Join("\n", errorLines));
|
||||||
|
|
||||||
DebugConsole.ThrowError("Writing object data to \"crashreport_object.bin\", please send this file to us at http://github.com/Regalis11/Barotrauma/issues");
|
DebugConsole.ThrowError("Writing object data to \"crashreport_object.bin\", please send this file to us at http://github.com/Regalis11/Barotrauma/issues");
|
||||||
|
|
||||||
FileStream fl = File.Open("crashreport_object.bin", FileMode.Create);
|
FileStream fl = File.Open("crashreport_object.bin", FileMode.Create);
|
||||||
BinaryWriter sw = new BinaryWriter(fl);
|
BinaryWriter sw = new BinaryWriter(fl);
|
||||||
|
|
||||||
sw.Write(inc.Data, (int)prevBytePos, (int)(inc.LengthBytes - prevBytePos));
|
sw.Write(inc.Data, (int)(prevBytePos - prevByteLength), (int)(prevByteLength));
|
||||||
|
|
||||||
sw.Close();
|
sw.Close();
|
||||||
fl.Close();
|
fl.Close();
|
||||||
|
|
||||||
throw new Exception("Error while reading update from server: please send us \"crashreport_object.bin\"!");
|
throw new Exception("Error while reading update from server: please send us \"crashreport_object.bin\"!");
|
||||||
}
|
}
|
||||||
|
prevBitLength = inc.Position - prevBitPos;
|
||||||
|
prevByteLength = inc.PositionInBytes - prevByteLength;
|
||||||
|
|
||||||
prevObjHeader = objHeader;
|
prevObjHeader = objHeader;
|
||||||
prevBitPos = inc.Position;
|
prevBitPos = inc.Position;
|
||||||
prevBytePos = inc.PositionInBytes;
|
prevBytePos = inc.PositionInBytes;
|
||||||
@@ -1181,8 +1226,12 @@ namespace Barotrauma.Networking
|
|||||||
case FileTransferType.Submarine:
|
case FileTransferType.Submarine:
|
||||||
new GUIMessageBox("Download finished", "File \"" + transfer.FileName + "\" was downloaded succesfully.");
|
new GUIMessageBox("Download finished", "File \"" + transfer.FileName + "\" was downloaded succesfully.");
|
||||||
var newSub = new Submarine(transfer.FilePath);
|
var newSub = new Submarine(transfer.FilePath);
|
||||||
Submarine.SavedSubmarines.RemoveAll(s => s.Name == newSub.Name && s.MD5Hash.Hash == newSub.MD5Hash.Hash);
|
var existingSubs = Submarine.SavedSubmarines.Where(s => s.Name == newSub.Name && s.MD5Hash.Hash == newSub.MD5Hash.Hash).ToList();
|
||||||
Submarine.SavedSubmarines.Add(newSub);
|
foreach (Submarine existingSub in existingSubs)
|
||||||
|
{
|
||||||
|
existingSub.Dispose();
|
||||||
|
}
|
||||||
|
Submarine.AddToSavedSubs(newSub);
|
||||||
|
|
||||||
for (int i = 0; i < 2; i++)
|
for (int i = 0; i < 2; i++)
|
||||||
{
|
{
|
||||||
@@ -1277,6 +1326,23 @@ namespace Barotrauma.Networking
|
|||||||
{
|
{
|
||||||
base.Draw(spriteBatch);
|
base.Draw(spriteBatch);
|
||||||
|
|
||||||
|
if (Screen.Selected == GameMain.GameScreen && !GUI.DisableHUD)
|
||||||
|
{
|
||||||
|
if (EndVoteCount > 0)
|
||||||
|
{
|
||||||
|
if (!HasSpawned)
|
||||||
|
{
|
||||||
|
GUI.DrawString(spriteBatch, new Vector2(GameMain.GraphicsWidth - 180.0f, 40),
|
||||||
|
"Votes to end the round (y/n): " + EndVoteCount + "/" + (EndVoteMax - EndVoteCount), Color.White, null, 0, GUI.SmallFont);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GUI.DrawString(spriteBatch, new Vector2(GameMain.GraphicsWidth - 140.0f, 40),
|
||||||
|
"Votes (y/n): " + EndVoteCount + "/" + (EndVoteMax - EndVoteCount), Color.White, null, 0, GUI.SmallFont);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (fileReceiver != null && fileReceiver.ActiveTransfers.Count > 0)
|
if (fileReceiver != null && fileReceiver.ActiveTransfers.Count > 0)
|
||||||
{
|
{
|
||||||
Vector2 pos = new Vector2(GameMain.NetLobbyScreen.InfoFrame.Rect.X, GameMain.GraphicsHeight - 35);
|
Vector2 pos = new Vector2(GameMain.NetLobbyScreen.InfoFrame.Rect.X, GameMain.GraphicsHeight - 35);
|
||||||
@@ -1341,6 +1407,17 @@ namespace Barotrauma.Networking
|
|||||||
public override void Disconnect()
|
public override void Disconnect()
|
||||||
{
|
{
|
||||||
client.Shutdown("");
|
client.Shutdown("");
|
||||||
|
|
||||||
|
foreach (var fileTransfer in FileReceiver.ActiveTransfers)
|
||||||
|
{
|
||||||
|
fileTransfer.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (HasPermission(ClientPermissions.ServerLog))
|
||||||
|
{
|
||||||
|
ServerLog?.Save();
|
||||||
|
}
|
||||||
|
|
||||||
GameMain.NetworkMember = null;
|
GameMain.NetworkMember = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1560,14 +1637,13 @@ namespace Barotrauma.Networking
|
|||||||
{
|
{
|
||||||
if (!gameStarted) return false;
|
if (!gameStarted) return false;
|
||||||
|
|
||||||
if (!Voting.AllowEndVoting || myCharacter==null)
|
if (!Voting.AllowEndVoting || !HasSpawned)
|
||||||
{
|
{
|
||||||
tickBox.Visible = false;
|
tickBox.Visible = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vote(VoteType.EndRound, tickBox.Selected);
|
Vote(VoteType.EndRound, tickBox.Selected);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,45 +9,22 @@ namespace Barotrauma.Networking
|
|||||||
{
|
{
|
||||||
private NetStats netStats;
|
private NetStats netStats;
|
||||||
|
|
||||||
private GUIButton showLogButton;
|
|
||||||
|
|
||||||
private GUIScrollBar clientListScrollBar;
|
private GUIScrollBar clientListScrollBar;
|
||||||
|
|
||||||
void InitProjSpecific()
|
void InitProjSpecific()
|
||||||
{
|
{
|
||||||
//----------------------------------------
|
|
||||||
|
|
||||||
var endRoundButton = new GUIButton(new Rectangle(GameMain.GraphicsWidth - 170, 20, 150, 20), "End round", Alignment.TopLeft, "", inGameHUD);
|
var endRoundButton = new GUIButton(new Rectangle(GameMain.GraphicsWidth - 170, 20, 150, 20), "End round", Alignment.TopLeft, "", inGameHUD);
|
||||||
endRoundButton.OnClicked = (btn, userdata) => { EndGame(); return true; };
|
endRoundButton.OnClicked = (btn, userdata) => { EndGame(); return true; };
|
||||||
|
|
||||||
showLogButton = new GUIButton(new Rectangle(GameMain.GraphicsWidth - 170 - 170, 20, 150, 20), "Server Log", Alignment.TopLeft, "", inGameHUD);
|
|
||||||
showLogButton.OnClicked = (GUIButton button, object userData) =>
|
|
||||||
{
|
|
||||||
if (log.LogFrame == null)
|
|
||||||
{
|
|
||||||
log.CreateLogFrame();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
log.LogFrame = null;
|
|
||||||
GUIComponent.KeyboardDispatcher.Subscriber = null;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
GUIButton settingsButton = new GUIButton(new Rectangle(GameMain.GraphicsWidth - 170 - 170 - 170, 20, 150, 20), "Settings", Alignment.TopLeft, "", inGameHUD);
|
GUIButton settingsButton = new GUIButton(new Rectangle(GameMain.GraphicsWidth - 170 - 170 - 170, 20, 150, 20), "Settings", Alignment.TopLeft, "", inGameHUD);
|
||||||
settingsButton.OnClicked = ToggleSettingsFrame;
|
settingsButton.OnClicked = ToggleSettingsFrame;
|
||||||
settingsButton.UserData = "settingsButton";
|
settingsButton.UserData = "settingsButton";
|
||||||
|
|
||||||
//----------------------------------------
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void AddToGUIUpdateList()
|
public override void AddToGUIUpdateList()
|
||||||
{
|
{
|
||||||
if (started) base.AddToGUIUpdateList();
|
base.AddToGUIUpdateList();
|
||||||
|
|
||||||
if (settingsFrame != null) settingsFrame.AddToGUIUpdateList();
|
if (settingsFrame != null) settingsFrame.AddToGUIUpdateList();
|
||||||
if (log.LogFrame != null) log.LogFrame.AddToGUIUpdateList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Draw(Microsoft.Xna.Framework.Graphics.SpriteBatch spriteBatch)
|
public override void Draw(Microsoft.Xna.Framework.Graphics.SpriteBatch spriteBatch)
|
||||||
@@ -58,9 +35,18 @@ namespace Barotrauma.Networking
|
|||||||
{
|
{
|
||||||
settingsFrame.Draw(spriteBatch);
|
settingsFrame.Draw(spriteBatch);
|
||||||
}
|
}
|
||||||
else if (log.LogFrame != null)
|
else if (ServerLog.LogFrame != null)
|
||||||
{
|
{
|
||||||
log.LogFrame.Draw(spriteBatch);
|
ServerLog.LogFrame.Draw(spriteBatch);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Screen.Selected == GameMain.GameScreen && !GUI.DisableHUD)
|
||||||
|
{
|
||||||
|
if (EndVoteCount > 0)
|
||||||
|
{
|
||||||
|
GUI.DrawString(spriteBatch, new Vector2(GameMain.GraphicsWidth - 180.0f, 40),
|
||||||
|
"Votes to end the round (y/n): " + EndVoteCount + "/" + (EndVoteMax - EndVoteCount), Color.White, null, 0, GUI.SmallFont);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ShowNetStats) return;
|
if (!ShowNetStats) return;
|
||||||
|
|||||||
+30
-9
@@ -23,6 +23,11 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
private UInt16 lastReceivedID;
|
private UInt16 lastReceivedID;
|
||||||
|
|
||||||
|
public bool MidRoundSyncing
|
||||||
|
{
|
||||||
|
get { return firstNewID.HasValue; }
|
||||||
|
}
|
||||||
|
|
||||||
public ClientEntityEventManager(GameClient client)
|
public ClientEntityEventManager(GameClient client)
|
||||||
{
|
{
|
||||||
events = new List<ClientEntityEvent>();
|
events = new List<ClientEntityEvent>();
|
||||||
@@ -140,7 +145,13 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
if (entityID == 0)
|
if (entityID == 0)
|
||||||
{
|
{
|
||||||
|
if (GameSettings.VerboseLogging)
|
||||||
|
{
|
||||||
|
DebugConsole.NewMessage("received msg " + thisEventID + " (null entity)",
|
||||||
|
Microsoft.Xna.Framework.Color.Orange);
|
||||||
|
}
|
||||||
msg.ReadPadBits();
|
msg.ReadPadBits();
|
||||||
|
entities.Add(null);
|
||||||
if (thisEventID == (UInt16)(lastReceivedID + 1)) lastReceivedID++;
|
if (thisEventID == (UInt16)(lastReceivedID + 1)) lastReceivedID++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -153,23 +164,24 @@ namespace Barotrauma.Networking
|
|||||||
//skip the event if we've already received it or if the entity isn't found
|
//skip the event if we've already received it or if the entity isn't found
|
||||||
if (thisEventID != (UInt16)(lastReceivedID + 1) || entity == null)
|
if (thisEventID != (UInt16)(lastReceivedID + 1) || entity == null)
|
||||||
{
|
{
|
||||||
if (GameSettings.VerboseLogging)
|
if (thisEventID != (UInt16) (lastReceivedID + 1))
|
||||||
{
|
{
|
||||||
if (thisEventID != (UInt16) (lastReceivedID + 1))
|
if (GameSettings.VerboseLogging)
|
||||||
{
|
{
|
||||||
DebugConsole.NewMessage(
|
DebugConsole.NewMessage(
|
||||||
"received msg " + thisEventID + " (waiting for " + (lastReceivedID + 1) + ")",
|
"Received msg " + thisEventID + " (waiting for " + (lastReceivedID + 1) + ")",
|
||||||
thisEventID < lastReceivedID + 1
|
thisEventID < lastReceivedID + 1
|
||||||
? Microsoft.Xna.Framework.Color.Yellow
|
? Microsoft.Xna.Framework.Color.Yellow
|
||||||
: Microsoft.Xna.Framework.Color.Red);
|
: Microsoft.Xna.Framework.Color.Red);
|
||||||
}
|
}
|
||||||
else if (entity == null)
|
|
||||||
{
|
|
||||||
DebugConsole.NewMessage(
|
|
||||||
"received msg " + thisEventID + ", entity " + entityID + " not found",
|
|
||||||
Microsoft.Xna.Framework.Color.Red);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else if (entity == null)
|
||||||
|
{
|
||||||
|
DebugConsole.NewMessage(
|
||||||
|
"Received msg " + thisEventID + ", entity " + entityID + " not found",
|
||||||
|
Microsoft.Xna.Framework.Color.Red);
|
||||||
|
}
|
||||||
|
|
||||||
msg.Position += msgLength * 8;
|
msg.Position += msgLength * 8;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -188,10 +200,19 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
string errorMsg = "Failed to read event for entity \"" + entity.ToString() + "\" (" + e.Message + ")! (MidRoundSyncing: " + thisClient.MidRoundSyncing + ")\n" + e.StackTrace;
|
||||||
|
errorMsg += "\nPrevious entities:";
|
||||||
|
for (int j = entities.Count - 2; j >= 0; j--)
|
||||||
|
{
|
||||||
|
errorMsg += "\n" + (entities[j] == null ? "NULL" : entities[j].ToString());
|
||||||
|
}
|
||||||
|
|
||||||
if (GameSettings.VerboseLogging)
|
if (GameSettings.VerboseLogging)
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError("Failed to read event for entity \"" + entity.ToString() + "\"!", e);
|
DebugConsole.ThrowError("Failed to read event for entity \"" + entity.ToString() + "\"!", e);
|
||||||
}
|
}
|
||||||
|
GameAnalyticsManager.AddErrorEventOnce("ClientEntityEventManager.Read:ReadFailed" + entity.ToString(),
|
||||||
|
GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||||
msg.Position = msgPosition + msgLength * 8;
|
msg.Position = msgPosition + msgLength * 8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ namespace Barotrauma.Networking
|
|||||||
protected GUIFrame inGameHUD;
|
protected GUIFrame inGameHUD;
|
||||||
protected GUIListBox chatBox;
|
protected GUIListBox chatBox;
|
||||||
protected GUITextBox chatMsgBox;
|
protected GUITextBox chatMsgBox;
|
||||||
|
protected GUIButton showLogButton;
|
||||||
|
|
||||||
public GUIFrame InGameHUD
|
public GUIFrame InGameHUD
|
||||||
{
|
{
|
||||||
@@ -35,6 +36,23 @@ namespace Barotrauma.Networking
|
|||||||
inGameHUD = new GUIFrame(new Rectangle(0, 0, 0, 0), null, null);
|
inGameHUD = new GUIFrame(new Rectangle(0, 0, 0, 0), null, null);
|
||||||
inGameHUD.CanBeFocused = false;
|
inGameHUD.CanBeFocused = false;
|
||||||
|
|
||||||
|
showLogButton = new GUIButton(new Rectangle(GameMain.GraphicsWidth - 170 - 170, 20, 150, 20), "Server Log", Alignment.TopLeft, "", inGameHUD)
|
||||||
|
{
|
||||||
|
OnClicked = (GUIButton button, object userData) =>
|
||||||
|
{
|
||||||
|
if (ServerLog.LogFrame == null)
|
||||||
|
{
|
||||||
|
ServerLog.CreateLogFrame();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ServerLog.LogFrame = null;
|
||||||
|
GUIComponent.KeyboardDispatcher.Subscriber = null;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
int width = (int)MathHelper.Clamp(GameMain.GraphicsWidth * 0.35f, 350, 500);
|
int width = (int)MathHelper.Clamp(GameMain.GraphicsWidth * 0.35f, 350, 500);
|
||||||
int height = (int)MathHelper.Clamp(GameMain.GraphicsHeight * 0.15f, 100, 200);
|
int height = (int)MathHelper.Clamp(GameMain.GraphicsHeight * 0.15f, 100, 200);
|
||||||
chatBox = new GUIListBox(new Rectangle(
|
chatBox = new GUIListBox(new Rectangle(
|
||||||
@@ -109,53 +127,44 @@ namespace Barotrauma.Networking
|
|||||||
{
|
{
|
||||||
inGameHUD.AddToGUIUpdateList();
|
inGameHUD.AddToGUIUpdateList();
|
||||||
}
|
}
|
||||||
|
if (ServerLog.LogFrame != null) ServerLog.LogFrame.AddToGUIUpdateList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void Draw(Microsoft.Xna.Framework.Graphics.SpriteBatch spriteBatch)
|
public virtual void Draw(Microsoft.Xna.Framework.Graphics.SpriteBatch spriteBatch)
|
||||||
{
|
{
|
||||||
if (!gameStarted || Screen.Selected != GameMain.GameScreen || GUI.DisableHUD) return;
|
if (GUI.DisableHUD) return;
|
||||||
|
|
||||||
GameMain.GameSession.CrewManager.Draw(spriteBatch);
|
if (gameStarted && Screen.Selected == GameMain.GameScreen)
|
||||||
|
|
||||||
inGameHUD.Draw(spriteBatch);
|
|
||||||
|
|
||||||
if (EndVoteCount > 0)
|
|
||||||
{
|
{
|
||||||
if (GameMain.NetworkMember.myCharacter == null)
|
GameMain.GameSession.CrewManager.Draw(spriteBatch);
|
||||||
|
|
||||||
|
inGameHUD.Draw(spriteBatch);
|
||||||
|
|
||||||
|
if (respawnManager != null)
|
||||||
{
|
{
|
||||||
GUI.DrawString(spriteBatch, new Vector2(GameMain.GraphicsWidth - 180.0f, 40),
|
string respawnInfo = "";
|
||||||
"Votes to end the round (y/n): " + EndVoteCount + "/" + (EndVoteMax - EndVoteCount), Color.White, null, 0, GUI.SmallFont);
|
|
||||||
}
|
if (respawnManager.CurrentState == RespawnManager.State.Waiting &&
|
||||||
else
|
respawnManager.CountdownStarted)
|
||||||
{
|
{
|
||||||
GUI.DrawString(spriteBatch, new Vector2(GameMain.GraphicsWidth - 140.0f, 40),
|
respawnInfo = respawnManager.UsingShuttle ? "Respawn Shuttle dispatching in " : "Respawning players in ";
|
||||||
"Votes (y/n): " + EndVoteCount + "/" + (EndVoteMax - EndVoteCount), Color.White, null, 0, GUI.SmallFont);
|
respawnInfo = respawnManager.RespawnTimer <= 0.0f ? "" : respawnInfo + ToolBox.SecondsToReadableTime(respawnManager.RespawnTimer);
|
||||||
|
}
|
||||||
|
else if (respawnManager.CurrentState == RespawnManager.State.Transporting)
|
||||||
|
{
|
||||||
|
respawnInfo = respawnManager.TransportTimer <= 0.0f ? "" : "Shuttle leaving in " + ToolBox.SecondsToReadableTime(respawnManager.TransportTimer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(respawnInfo))
|
||||||
|
{
|
||||||
|
GUI.DrawString(spriteBatch,
|
||||||
|
new Vector2(120.0f, 10),
|
||||||
|
respawnInfo, Color.White, null, 0, GUI.SmallFont);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (respawnManager != null)
|
ServerLog.LogFrame?.Draw(spriteBatch);
|
||||||
{
|
|
||||||
string respawnInfo = "";
|
|
||||||
|
|
||||||
if (respawnManager.CurrentState == RespawnManager.State.Waiting &&
|
|
||||||
respawnManager.CountdownStarted)
|
|
||||||
{
|
|
||||||
respawnInfo = respawnManager.UsingShuttle ? "Respawn Shuttle dispatching in " : "Respawning players in ";
|
|
||||||
respawnInfo = respawnManager.RespawnTimer <= 0.0f ? "" : respawnInfo + ToolBox.SecondsToReadableTime(respawnManager.RespawnTimer);
|
|
||||||
}
|
|
||||||
else if (respawnManager.CurrentState == RespawnManager.State.Transporting)
|
|
||||||
{
|
|
||||||
respawnInfo = respawnManager.TransportTimer <= 0.0f ? "" : "Shuttle leaving in " + ToolBox.SecondsToReadableTime(respawnManager.TransportTimer);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(respawnInfo))
|
|
||||||
{
|
|
||||||
GUI.DrawString(spriteBatch,
|
|
||||||
new Vector2(120.0f, 10),
|
|
||||||
respawnInfo, Color.White, null, 0, GUI.SmallFont);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual bool SelectCrewCharacter(Character character, GUIComponent characterFrame)
|
public virtual bool SelectCrewCharacter(Character character, GUIComponent characterFrame)
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
using Lidgren.Network;
|
using Lidgren.Network;
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
@@ -151,7 +152,12 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
int votes = inc.ReadByte();
|
int votes = inc.ReadByte();
|
||||||
string subName = inc.ReadString();
|
string subName = inc.ReadString();
|
||||||
Submarine sub = Submarine.SavedSubmarines.Find(sm => sm.Name == subName);
|
List<Submarine> serversubs = new List<Submarine>();
|
||||||
|
foreach (GUIComponent item in GameMain.NetLobbyScreen?.SubList?.children)
|
||||||
|
{
|
||||||
|
if (item.UserData != null && item.UserData is Submarine) serversubs.Add(item.UserData as Submarine);
|
||||||
|
}
|
||||||
|
Submarine sub = serversubs.FirstOrDefault(sm => sm.Name == subName);
|
||||||
SetVoteText(GameMain.NetLobbyScreen.SubList, sub, votes);
|
SetVoteText(GameMain.NetLobbyScreen.SubList, sub, votes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -203,7 +203,7 @@ namespace Barotrauma
|
|||||||
if (GameSettings.SendUserStatistics)
|
if (GameSettings.SendUserStatistics)
|
||||||
{
|
{
|
||||||
CrashMessageBox( "A crash report (\"crashreport.log\") was saved in the root folder of the game and sent to the developers.");
|
CrashMessageBox( "A crash report (\"crashreport.log\") was saved in the root folder of the game and sent to the developers.");
|
||||||
GameAnalytics.AddErrorEvent(EGAErrorSeverity.Error, crashReport);
|
GameAnalytics.AddErrorEvent(EGAErrorSeverity.Critical, crashReport);
|
||||||
GameAnalytics.OnStop();
|
GameAnalytics.OnStop();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -58,6 +58,14 @@ namespace Barotrauma
|
|||||||
Submarine selectedSub = subList.SelectedData as Submarine;
|
Submarine selectedSub = subList.SelectedData as Submarine;
|
||||||
if (selectedSub == null) return false;
|
if (selectedSub == null) return false;
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(selectedSub.MD5Hash.Hash))
|
||||||
|
{
|
||||||
|
((GUITextBlock)subList.Selected).TextColor = Color.DarkRed * 0.8f;
|
||||||
|
subList.Selected.CanBeFocused = false;
|
||||||
|
subList.Deselect();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
string savePath = SaveUtil.CreateSavePath(isMultiplayer ? SaveUtil.SaveType.Multiplayer : SaveUtil.SaveType.Singleplayer, saveNameBox.Text);
|
string savePath = SaveUtil.CreateSavePath(isMultiplayer ? SaveUtil.SaveType.Multiplayer : SaveUtil.SaveType.Singleplayer, saveNameBox.Text);
|
||||||
if (selectedSub.HasTag(SubmarineTag.Shuttle) || !selectedSub.CompatibleContentPackages.Contains(GameMain.SelectedPackage.Name))
|
if (selectedSub.HasTag(SubmarineTag.Shuttle) || !selectedSub.CompatibleContentPackages.Contains(GameMain.SelectedPackage.Name))
|
||||||
{
|
{
|
||||||
@@ -144,7 +152,7 @@ namespace Barotrauma
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (Submarine.SavedSubmarines.Count > 0) subList.Select(Submarine.SavedSubmarines[0]);
|
if (Submarine.SavedSubmarines.Any()) subList.Select(Submarine.SavedSubmarines.First());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateLoadMenu()
|
public void UpdateLoadMenu()
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ namespace Barotrauma
|
|||||||
int sellColumnWidth = (tabs[(int)Tab.Store].Rect.Width - 40) / 2 - 20;
|
int sellColumnWidth = (tabs[(int)Tab.Store].Rect.Width - 40) / 2 - 20;
|
||||||
|
|
||||||
selectedItemList = new GUIListBox(new Rectangle(0, 30, sellColumnWidth, tabs[(int)Tab.Store].Rect.Height - 80), Color.White * 0.7f, "", tabs[(int)Tab.Store]);
|
selectedItemList = new GUIListBox(new Rectangle(0, 30, sellColumnWidth, tabs[(int)Tab.Store].Rect.Height - 80), Color.White * 0.7f, "", tabs[(int)Tab.Store]);
|
||||||
selectedItemList.OnSelected = SellItem;
|
//selectedItemList.OnSelected = SellItem;
|
||||||
|
|
||||||
storeItemList = new GUIListBox(new Rectangle(0, 30, sellColumnWidth, tabs[(int)Tab.Store].Rect.Height - 80), Color.White * 0.7f, Alignment.TopRight, "", tabs[(int)Tab.Store]);
|
storeItemList = new GUIListBox(new Rectangle(0, 30, sellColumnWidth, tabs[(int)Tab.Store].Rect.Height - 80), Color.White * 0.7f, Alignment.TopRight, "", tabs[(int)Tab.Store]);
|
||||||
storeItemList.OnSelected = BuyItem;
|
storeItemList.OnSelected = BuyItem;
|
||||||
@@ -149,6 +149,8 @@ namespace Barotrauma
|
|||||||
null, null,
|
null, null,
|
||||||
Alignment.TopRight, "", frame);
|
Alignment.TopRight, "", frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RefreshItemTab();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Update(float deltaTime)
|
public void Update(float deltaTime)
|
||||||
@@ -216,55 +218,92 @@ namespace Barotrauma
|
|||||||
OnLocationSelected?.Invoke(location, connection);
|
OnLocationSelected?.Invoke(location, connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CreateItemFrame(MapEntityPrefab ep, GUIListBox listBox, int width)
|
private void CreateItemFrame(PurchasedItem pi, GUIListBox listBox, int width)
|
||||||
{
|
{
|
||||||
GUIFrame frame = new GUIFrame(new Rectangle(0, 0, 0, 50), "ListBoxElement", listBox);
|
GUIFrame frame = new GUIFrame(new Rectangle(0, 0, 0, 50), "ListBoxElement", listBox);
|
||||||
frame.UserData = ep;
|
frame.UserData = pi;
|
||||||
frame.Padding = new Vector4(5.0f, 5.0f, 5.0f, 5.0f);
|
frame.Padding = new Vector4(5.0f, 5.0f, 5.0f, 5.0f);
|
||||||
|
|
||||||
frame.ToolTip = ep.Description;
|
frame.ToolTip = pi.itemPrefab.Description;
|
||||||
|
|
||||||
ScalableFont font = listBox.Rect.Width < 280 ? GUI.SmallFont : GUI.Font;
|
ScalableFont font = listBox.Rect.Width < 280 ? GUI.SmallFont : GUI.Font;
|
||||||
|
|
||||||
GUITextBlock textBlock = new GUITextBlock(
|
GUITextBlock textBlock = new GUITextBlock(
|
||||||
new Rectangle(50, 0, 0, 25),
|
new Rectangle(50, 0, 0, 25),
|
||||||
ep.Name,
|
pi.itemPrefab.Name,
|
||||||
null, null,
|
null, null,
|
||||||
Alignment.Left, Alignment.CenterX | Alignment.Left,
|
Alignment.Left, Alignment.CenterX | Alignment.Left,
|
||||||
"", frame);
|
"", frame);
|
||||||
textBlock.Font = font;
|
textBlock.Font = font;
|
||||||
textBlock.Padding = new Vector4(5.0f, 0.0f, 5.0f, 0.0f);
|
textBlock.Padding = new Vector4(5.0f, 0.0f, 5.0f, 0.0f);
|
||||||
textBlock.ToolTip = ep.Description;
|
textBlock.ToolTip = pi.itemPrefab.Description;
|
||||||
|
|
||||||
if (ep.sprite != null)
|
if (pi.itemPrefab.sprite != null)
|
||||||
{
|
{
|
||||||
GUIImage img = new GUIImage(new Rectangle(0, 0, 40, 40), ep.sprite, Alignment.CenterLeft, frame);
|
GUIImage img = new GUIImage(new Rectangle(0, 0, 40, 40), pi.itemPrefab.sprite, Alignment.CenterLeft, frame);
|
||||||
img.Color = ep.SpriteColor;
|
img.Color = pi.itemPrefab.SpriteColor;
|
||||||
img.Scale = Math.Min(Math.Min(40.0f / img.SourceRect.Width, 40.0f / img.SourceRect.Height), 1.0f);
|
img.Scale = Math.Min(Math.Min(40.0f / img.SourceRect.Width, 40.0f / img.SourceRect.Height), 1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
textBlock = new GUITextBlock(
|
textBlock = new GUITextBlock(
|
||||||
new Rectangle(width - 80, 0, 80, 25),
|
new Rectangle(width - 160, 0, 80, 25),
|
||||||
ep.Price.ToString(),
|
pi.itemPrefab.Price.ToString(),
|
||||||
null, null, Alignment.TopLeft,
|
null, null, Alignment.TopLeft,
|
||||||
Alignment.TopLeft, "", frame);
|
Alignment.TopLeft, "", frame);
|
||||||
textBlock.Font = font;
|
textBlock.Font = font;
|
||||||
textBlock.ToolTip = ep.Description;
|
textBlock.ToolTip = pi.itemPrefab.Description;
|
||||||
|
|
||||||
|
//If its the store menu, quantity will always be 0
|
||||||
|
if (pi.quantity > 0)
|
||||||
|
{
|
||||||
|
var amountInput = new GUINumberInput(new Rectangle(width - 80, 0, 50, 40), "", GUINumberInput.NumberType.Int, frame);
|
||||||
|
amountInput.MinValueInt = 0;
|
||||||
|
amountInput.MaxValueInt = 1000;
|
||||||
|
amountInput.UserData = pi;
|
||||||
|
amountInput.IntValue = pi.quantity;
|
||||||
|
amountInput.OnValueChanged += (numberInput) =>
|
||||||
|
{
|
||||||
|
PurchasedItem purchasedItem = numberInput.UserData as PurchasedItem;
|
||||||
|
|
||||||
|
//Attempting to buy
|
||||||
|
if (numberInput.IntValue > purchasedItem.quantity)
|
||||||
|
{
|
||||||
|
int quantity = numberInput.IntValue - purchasedItem.quantity;
|
||||||
|
//Cap the numberbox based on the amount we can afford.
|
||||||
|
quantity = campaign.Money <= 0 ?
|
||||||
|
0 : Math.Min((int)(Campaign.Money / (float)purchasedItem.itemPrefab.Price), quantity);
|
||||||
|
for (int i = 0; i < quantity; i++)
|
||||||
|
{
|
||||||
|
BuyItem(numberInput, purchasedItem);
|
||||||
|
}
|
||||||
|
numberInput.IntValue = purchasedItem.quantity;
|
||||||
|
}
|
||||||
|
//Attempting to sell
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int quantity = purchasedItem.quantity - numberInput.IntValue;
|
||||||
|
for (int i = 0; i < quantity; i++)
|
||||||
|
{
|
||||||
|
SellItem(numberInput, purchasedItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool BuyItem(GUIComponent component, object obj)
|
private bool BuyItem(GUIComponent component, object obj)
|
||||||
{
|
{
|
||||||
ItemPrefab prefab = obj as ItemPrefab;
|
PurchasedItem pi = obj as PurchasedItem;
|
||||||
if (prefab == null) return false;
|
if (pi == null || pi.itemPrefab == null) return false;
|
||||||
|
|
||||||
if (GameMain.Client != null && !GameMain.Client.HasPermission(Networking.ClientPermissions.ManageCampaign))
|
if (GameMain.Client != null && !GameMain.Client.HasPermission(Networking.ClientPermissions.ManageCampaign))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prefab.Price > campaign.Money) return false;
|
if (pi.itemPrefab.Price > campaign.Money) return false;
|
||||||
|
|
||||||
campaign.CargoManager.PurchaseItem(prefab);
|
campaign.CargoManager.PurchaseItem(pi.itemPrefab, 1);
|
||||||
GameMain.Client?.SendCampaignState();
|
GameMain.Client?.SendCampaignState();
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -272,15 +311,15 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private bool SellItem(GUIComponent component, object obj)
|
private bool SellItem(GUIComponent component, object obj)
|
||||||
{
|
{
|
||||||
ItemPrefab prefab = obj as ItemPrefab;
|
PurchasedItem pi = obj as PurchasedItem;
|
||||||
if (prefab == null) return false;
|
if (pi == null || pi.itemPrefab == null) return false;
|
||||||
|
|
||||||
if (GameMain.Client != null && !GameMain.Client.HasPermission(Networking.ClientPermissions.ManageCampaign))
|
if (GameMain.Client != null && !GameMain.Client.HasPermission(Networking.ClientPermissions.ManageCampaign))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
campaign.CargoManager.SellItem(prefab);
|
campaign.CargoManager.SellItem(pi.itemPrefab,1);
|
||||||
GameMain.Client?.SendCampaignState();
|
GameMain.Client?.SendCampaignState();
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -289,10 +328,13 @@ namespace Barotrauma
|
|||||||
private void RefreshItemTab()
|
private void RefreshItemTab()
|
||||||
{
|
{
|
||||||
selectedItemList.ClearChildren();
|
selectedItemList.ClearChildren();
|
||||||
foreach (ItemPrefab ip in campaign.CargoManager.PurchasedItems)
|
foreach (PurchasedItem pi in campaign.CargoManager.PurchasedItems)
|
||||||
{
|
{
|
||||||
CreateItemFrame(ip, selectedItemList, selectedItemList.Rect.Width);
|
CreateItemFrame(pi, selectedItemList, selectedItemList.Rect.Width);
|
||||||
}
|
}
|
||||||
|
selectedItemList.children.Sort((x, y) => (x.UserData as PurchasedItem).itemPrefab.Name.CompareTo((y.UserData as PurchasedItem).itemPrefab.Name));
|
||||||
|
selectedItemList.children.Sort((x, y) => (x.UserData as PurchasedItem).itemPrefab.Category.CompareTo((y.UserData as PurchasedItem).itemPrefab.Category));
|
||||||
|
selectedItemList.UpdateScrollBarSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SelectTab(Tab tab)
|
public void SelectTab(Tab tab)
|
||||||
@@ -311,16 +353,16 @@ namespace Barotrauma
|
|||||||
storeItemList.ClearChildren();
|
storeItemList.ClearChildren();
|
||||||
|
|
||||||
MapEntityCategory category = (MapEntityCategory)selection;
|
MapEntityCategory category = (MapEntityCategory)selection;
|
||||||
var items = MapEntityPrefab.List.FindAll(ep => ep.Price > 0.0f && ep.Category.HasFlag(category));
|
var items = MapEntityPrefab.List.FindAll(ep => ep.Price > 0.0f && ep.Category.HasFlag(category) && ep is ItemPrefab);
|
||||||
|
|
||||||
int width = storeItemList.Rect.Width;
|
int width = storeItemList.Rect.Width;
|
||||||
|
|
||||||
foreach (MapEntityPrefab ep in items)
|
foreach (ItemPrefab ep in items)
|
||||||
{
|
{
|
||||||
CreateItemFrame(ep, storeItemList, width);
|
CreateItemFrame(new PurchasedItem((ItemPrefab)ep,0), storeItemList, width);
|
||||||
}
|
}
|
||||||
|
|
||||||
storeItemList.children.Sort((x, y) => (x.UserData as MapEntityPrefab).Name.CompareTo((y.UserData as MapEntityPrefab).Name));
|
storeItemList.children.Sort((x, y) => (x.UserData as PurchasedItem).itemPrefab.Name.CompareTo((y.UserData as PurchasedItem).itemPrefab.Name));
|
||||||
|
|
||||||
foreach (GUIComponent child in button.Parent.children)
|
foreach (GUIComponent child in button.Parent.children)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -244,13 +244,12 @@ namespace Barotrauma
|
|||||||
GameMain.LightManager.LosEffect.Parameters["xTexture"].SetValue(renderTargetBackground);
|
GameMain.LightManager.LosEffect.Parameters["xTexture"].SetValue(renderTargetBackground);
|
||||||
GameMain.LightManager.LosEffect.Parameters["xLosTexture"].SetValue(GameMain.LightManager.losTexture);
|
GameMain.LightManager.LosEffect.Parameters["xLosTexture"].SetValue(GameMain.LightManager.losTexture);
|
||||||
#endif
|
#endif
|
||||||
|
//convert the los color to HLS and make sure the luminance of the color is always the same
|
||||||
|
//as the luminance of the ambient light color
|
||||||
//convert the los color to HLS and make sure the luminance of the color is always the same regardless
|
|
||||||
//of the ambient light color and the luminance of the damage overlight color
|
|
||||||
float r = Math.Min(CharacterHUD.damageOverlayTimer * 0.5f, 0.5f);
|
float r = Math.Min(CharacterHUD.damageOverlayTimer * 0.5f, 0.5f);
|
||||||
|
Vector3 ambientLightHls = GameMain.LightManager.AmbientLight.RgbToHLS();
|
||||||
Vector3 losColorHls = Color.Lerp(GameMain.LightManager.AmbientLight, Color.Red, r).RgbToHLS();
|
Vector3 losColorHls = Color.Lerp(GameMain.LightManager.AmbientLight, Color.Red, r).RgbToHLS();
|
||||||
losColorHls.Y = 0.1f;
|
losColorHls.Y = ambientLightHls.Y;
|
||||||
Color losColor = ToolBox.HLSToRGB(losColorHls);
|
Color losColor = ToolBox.HLSToRGB(losColorHls);
|
||||||
|
|
||||||
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, SamplerState.PointClamp, null, null, GameMain.LightManager.LosEffect, null);
|
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, SamplerState.PointClamp, null, null, GameMain.LightManager.LosEffect, null);
|
||||||
|
|||||||
@@ -82,13 +82,15 @@ namespace Barotrauma
|
|||||||
|
|
||||||
locationTitle.Text = TextManager.Get("Location") + ": " + campaign.Map.CurrentLocation.Name;
|
locationTitle.Text = TextManager.Get("Location") + ": " + campaign.Map.CurrentLocation.Name;
|
||||||
|
|
||||||
|
campaign.Map.SelectLocation(-1);
|
||||||
|
|
||||||
bottomPanel.ClearChildren();
|
bottomPanel.ClearChildren();
|
||||||
campaignUI = new CampaignUI(campaign, bottomPanel);
|
campaignUI = new CampaignUI(campaign, bottomPanel);
|
||||||
campaignUI.StartRound = StartRound;
|
campaignUI.StartRound = StartRound;
|
||||||
campaignUI.OnLocationSelected = SelectLocation;
|
campaignUI.OnLocationSelected = SelectLocation;
|
||||||
campaignUI.UpdateCharacterLists();
|
campaignUI.UpdateCharacterLists();
|
||||||
|
|
||||||
if (GameSettings.SendUserStatistics) GameAnalyticsSDK.Net.GameAnalytics.SetCustomDimension01("singleplayer");
|
GameAnalyticsManager.SetCustomDimension01("singleplayer");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void AddToGUIUpdateList()
|
public override void AddToGUIUpdateList()
|
||||||
@@ -190,7 +192,10 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private IEnumerable<object> LoadRound()
|
private IEnumerable<object> LoadRound()
|
||||||
{
|
{
|
||||||
GameMain.GameSession.StartRound(campaignUI.SelectedLevel, true);
|
GameMain.GameSession.StartRound(campaignUI.SelectedLevel,
|
||||||
|
reloadSub: true,
|
||||||
|
loadSecondSub: false,
|
||||||
|
mirrorLevel: GameMain.GameSession.Map.CurrentLocation != GameMain.GameSession.Map.SelectedConnection.Locations[0]);
|
||||||
GameMain.GameScreen.Select();
|
GameMain.GameScreen.Select();
|
||||||
|
|
||||||
yield return CoroutineStatus.Success;
|
yield return CoroutineStatus.Success;
|
||||||
|
|||||||
@@ -143,7 +143,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
SelectTab(null, 0);
|
SelectTab(null, 0);
|
||||||
|
|
||||||
if (GameSettings.SendUserStatistics) GameAnalyticsSDK.Net.GameAnalytics.SetCustomDimension01("");
|
GameAnalyticsManager.SetCustomDimension01("");
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool SelectTab(GUIButton button, object obj)
|
public bool SelectTab(GUIButton button, object obj)
|
||||||
@@ -368,7 +368,19 @@ namespace Barotrauma
|
|||||||
Directory.CreateDirectory(SaveUtil.TempPath);
|
Directory.CreateDirectory(SaveUtil.TempPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
File.Copy(selectedSub.FilePath, Path.Combine(SaveUtil.TempPath, selectedSub.Name + ".sub"), true);
|
try
|
||||||
|
{
|
||||||
|
File.Copy(selectedSub.FilePath, Path.Combine(SaveUtil.TempPath, selectedSub.Name + ".sub"), true);
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
DebugConsole.ThrowError("Copying the file \"" + selectedSub.FilePath + "\" failed. The file may have been deleted or in use by another process. Try again or select another submarine.", e);
|
||||||
|
GameAnalyticsManager.AddErrorEventOnce(
|
||||||
|
"MainMenuScreen.StartGame:IOException" + selectedSub.Name,
|
||||||
|
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||||
|
"Copying the file \"" + selectedSub.FilePath + "\" failed.\n" + e.Message + "\n" + Environment.StackTrace);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
selectedSub = new Submarine(Path.Combine(SaveUtil.TempPath, selectedSub.Name + ".sub"), "");
|
selectedSub = new Submarine(Path.Combine(SaveUtil.TempPath, selectedSub.Name + ".sub"), "");
|
||||||
|
|
||||||
|
|||||||
@@ -177,7 +177,7 @@ namespace Barotrauma
|
|||||||
if (levelSeed == value) return;
|
if (levelSeed == value) return;
|
||||||
|
|
||||||
levelSeed = value;
|
levelSeed = value;
|
||||||
backgroundSprite = LocationType.Random(levelSeed).Background;
|
backgroundSprite = LocationType.Random(levelSeed)?.Background;
|
||||||
seedBox.Text = levelSeed;
|
seedBox.Text = levelSeed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -379,13 +379,13 @@ namespace Barotrauma
|
|||||||
showLogButton.UserData = "showlog";
|
showLogButton.UserData = "showlog";
|
||||||
showLogButton.OnClicked = (GUIButton button, object userData) =>
|
showLogButton.OnClicked = (GUIButton button, object userData) =>
|
||||||
{
|
{
|
||||||
if (GameMain.Server.ServerLog.LogFrame == null)
|
if (GameMain.NetworkMember.ServerLog.LogFrame == null)
|
||||||
{
|
{
|
||||||
GameMain.Server.ServerLog.CreateLogFrame();
|
GameMain.NetworkMember.ServerLog.CreateLogFrame();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GameMain.Server.ServerLog.LogFrame = null;
|
GameMain.NetworkMember.ServerLog.LogFrame = null;
|
||||||
GUIComponent.KeyboardDispatcher.Subscriber = null;
|
GUIComponent.KeyboardDispatcher.Subscriber = null;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -435,7 +435,9 @@ namespace Barotrauma
|
|||||||
infoFrame.RemoveChild(infoFrame.children.Find(c => c.UserData as string == "settingsButton"));
|
infoFrame.RemoveChild(infoFrame.children.Find(c => c.UserData as string == "settingsButton"));
|
||||||
infoFrame.RemoveChild(infoFrame.children.Find(c => c.UserData as string == "spectateButton"));
|
infoFrame.RemoveChild(infoFrame.children.Find(c => c.UserData as string == "spectateButton"));
|
||||||
|
|
||||||
InfoFrame.FindChild("showlog").Visible = GameMain.Server != null;
|
InfoFrame.FindChild("showlog").Visible =
|
||||||
|
GameMain.Server != null ||
|
||||||
|
(GameMain.Client != null && GameMain.Client.HasPermission(ClientPermissions.ServerLog));
|
||||||
|
|
||||||
if (campaignViewButton == null)
|
if (campaignViewButton == null)
|
||||||
{
|
{
|
||||||
@@ -501,7 +503,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GameSettings.SendUserStatistics) GameAnalyticsSDK.Net.GameAnalytics.SetCustomDimension01("multiplayer");
|
GameAnalyticsManager.SetCustomDimension01("multiplayer");
|
||||||
|
|
||||||
if (GameModePreset.list.Count > 0 && modeList.Selected == null) modeList.Select(0);
|
if (GameModePreset.list.Count > 0 && modeList.Selected == null) modeList.Select(0);
|
||||||
|
|
||||||
@@ -737,8 +739,21 @@ namespace Barotrauma
|
|||||||
//hash will be null if opening the sub file failed -> don't select the sub
|
//hash will be null if opening the sub file failed -> don't select the sub
|
||||||
if (string.IsNullOrWhiteSpace(hash))
|
if (string.IsNullOrWhiteSpace(hash))
|
||||||
{
|
{
|
||||||
(component as GUITextBlock).TextColor = Color.DarkRed * 0.8f;
|
GUITextBlock submarineTextBlock = component.GetChild<GUITextBlock>();
|
||||||
component.CanBeFocused = false;
|
if (submarineTextBlock != null)
|
||||||
|
{
|
||||||
|
submarineTextBlock.TextColor = Color.DarkRed * 0.8f;
|
||||||
|
submarineTextBlock.CanBeFocused = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DebugConsole.ThrowError("Failed to select submarine. Selected GUIComponent was of the type \"" + (component == null ? "null" : component.GetType().ToString()) + "\".");
|
||||||
|
GameAnalyticsManager.AddErrorEventOnce(
|
||||||
|
"NetLobbyScreen.SelectSub:InvalidComponent",
|
||||||
|
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||||
|
"Failed to select submarine. Selected GUIComponent was of the type \"" + (component == null ? "null" : component.GetType().ToString()) + "\".");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
StartButton.Enabled = false;
|
StartButton.Enabled = false;
|
||||||
|
|
||||||
@@ -782,8 +797,8 @@ namespace Barotrauma
|
|||||||
CanBeFocused = false
|
CanBeFocused = false
|
||||||
};
|
};
|
||||||
|
|
||||||
var matchingSub = Submarine.SavedSubmarines.Find(s => s.Name == sub.Name && s.MD5Hash.Hash == sub.MD5Hash.Hash);
|
var matchingSub = Submarine.SavedSubmarines.FirstOrDefault(s => s.Name == sub.Name && s.MD5Hash.Hash == sub.MD5Hash.Hash);
|
||||||
if (matchingSub == null) matchingSub = Submarine.SavedSubmarines.Find(s => s.Name == sub.Name);
|
if (matchingSub == null) matchingSub = Submarine.SavedSubmarines.FirstOrDefault(s => s.Name == sub.Name);
|
||||||
|
|
||||||
if (matchingSub == null)
|
if (matchingSub == null)
|
||||||
{
|
{
|
||||||
@@ -1467,8 +1482,8 @@ namespace Barotrauma
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Submarine sub = Submarine.SavedSubmarines.Find(m => m.Name == subName && m.MD5Hash.Hash == md5Hash);
|
Submarine sub = Submarine.SavedSubmarines.FirstOrDefault(m => m.Name == subName && m.MD5Hash.Hash == md5Hash);
|
||||||
if (sub == null) sub = Submarine.SavedSubmarines.Find(m => m.Name == subName);
|
if (sub == null) sub = Submarine.SavedSubmarines.FirstOrDefault(m => m.Name == subName);
|
||||||
|
|
||||||
var matchingListSub = subList.children.Find(c => c.UserData == sub);
|
var matchingListSub = subList.children.Find(c => c.UserData == sub);
|
||||||
if (matchingListSub != null)
|
if (matchingListSub != null)
|
||||||
@@ -1520,7 +1535,7 @@ namespace Barotrauma
|
|||||||
requestFileBox.Buttons[0].OnClicked += (GUIButton button, object userdata) =>
|
requestFileBox.Buttons[0].OnClicked += (GUIButton button, object userdata) =>
|
||||||
{
|
{
|
||||||
string[] fileInfo = (string[])userdata;
|
string[] fileInfo = (string[])userdata;
|
||||||
GameMain.Client.RequestFile(FileTransferType.Submarine, fileInfo[0], fileInfo[1]);
|
GameMain.Client?.RequestFile(FileTransferType.Submarine, fileInfo[0], fileInfo[1]);
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
requestFileBox.Buttons[1].OnClicked += requestFileBox.Close;
|
requestFileBox.Buttons[1].OnClicked += requestFileBox.Close;
|
||||||
|
|||||||
@@ -15,9 +15,9 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
private static string[] crewExperienceLevels = new string[]
|
private static string[] crewExperienceLevels = new string[]
|
||||||
{
|
{
|
||||||
TextManager.Get("CrewExperienceLow"),
|
"CrewExperienceLow",
|
||||||
TextManager.Get("CrewExperienceMid"),
|
"CrewExperienceMid",
|
||||||
TextManager.Get("CrewExperienceHigh")
|
"CrewExperienceHigh"
|
||||||
};
|
};
|
||||||
|
|
||||||
private Camera cam;
|
private Camera cam;
|
||||||
@@ -349,7 +349,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
cam.UpdateTransform();
|
cam.UpdateTransform();
|
||||||
|
|
||||||
if (GameSettings.SendUserStatistics) GameAnalyticsSDK.Net.GameAnalytics.SetCustomDimension01("editor");
|
GameAnalyticsManager.SetCustomDimension01("editor");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Deselect()
|
public override void Deselect()
|
||||||
@@ -587,23 +587,26 @@ namespace Barotrauma
|
|||||||
var toggleExpRight = new GUIButton(new Rectangle(350, y, 20, 20), ">", "", saveFrame);
|
var toggleExpRight = new GUIButton(new Rectangle(350, y, 20, 20), ">", "", saveFrame);
|
||||||
var experienceText = new GUITextBlock(new Rectangle(250, y, 100, 20), crewExperienceLevels[0], "", Alignment.TopLeft, Alignment.Center, saveFrame);
|
var experienceText = new GUITextBlock(new Rectangle(250, y, 100, 20), crewExperienceLevels[0], "", Alignment.TopLeft, Alignment.Center, saveFrame);
|
||||||
|
|
||||||
|
|
||||||
toggleExpLeft.OnClicked += (btn, userData) =>
|
toggleExpLeft.OnClicked += (btn, userData) =>
|
||||||
{
|
{
|
||||||
int currentIndex = Array.IndexOf(crewExperienceLevels, experienceText.Text);
|
int currentIndex = Array.IndexOf(crewExperienceLevels, (string)experienceText.UserData);
|
||||||
currentIndex--;
|
currentIndex--;
|
||||||
if (currentIndex < 0) currentIndex = crewExperienceLevels.Length - 1;
|
if (currentIndex < 0) currentIndex = crewExperienceLevels.Length - 1;
|
||||||
experienceText.Text = crewExperienceLevels[currentIndex];
|
experienceText.UserData = crewExperienceLevels[currentIndex];
|
||||||
Submarine.MainSub.RecommendedCrewExperience = experienceText.Text;
|
experienceText.Text = TextManager.Get(crewExperienceLevels[currentIndex]);
|
||||||
|
Submarine.MainSub.RecommendedCrewExperience = (string)experienceText.UserData;
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
toggleExpRight.OnClicked += (btn, userData) =>
|
toggleExpRight.OnClicked += (btn, userData) =>
|
||||||
{
|
{
|
||||||
int currentIndex = Array.IndexOf(crewExperienceLevels, experienceText.Text);
|
int currentIndex = Array.IndexOf(crewExperienceLevels, (string)experienceText.UserData);
|
||||||
currentIndex++;
|
currentIndex++;
|
||||||
if (currentIndex >= crewExperienceLevels.Length) currentIndex = 0;
|
if (currentIndex >= crewExperienceLevels.Length) currentIndex = 0;
|
||||||
experienceText.Text = crewExperienceLevels[currentIndex];
|
experienceText.UserData = crewExperienceLevels[currentIndex];
|
||||||
Submarine.MainSub.RecommendedCrewExperience = experienceText.Text;
|
experienceText.Text = TextManager.Get(crewExperienceLevels[currentIndex]);
|
||||||
|
Submarine.MainSub.RecommendedCrewExperience = (string)experienceText.UserData;
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -613,8 +616,9 @@ namespace Barotrauma
|
|||||||
int max = Submarine.MainSub.RecommendedCrewSizeMax;
|
int max = Submarine.MainSub.RecommendedCrewSizeMax;
|
||||||
crewSizeMin.IntValue = min;
|
crewSizeMin.IntValue = min;
|
||||||
crewSizeMax.IntValue = max;
|
crewSizeMax.IntValue = max;
|
||||||
experienceText.Text = string.IsNullOrEmpty(Submarine.MainSub.RecommendedCrewExperience) ?
|
experienceText.UserData = string.IsNullOrEmpty(Submarine.MainSub.RecommendedCrewExperience) ?
|
||||||
crewExperienceLevels[0] : Submarine.MainSub.RecommendedCrewExperience;
|
crewExperienceLevels[0] : Submarine.MainSub.RecommendedCrewExperience;
|
||||||
|
experienceText.Text = TextManager.Get((string)experienceText.UserData);
|
||||||
}
|
}
|
||||||
|
|
||||||
var saveButton = new GUIButton(new Rectangle(-90, 0, 80, 20), TextManager.Get("SaveSubButton"), Alignment.Right | Alignment.Bottom, "", saveFrame);
|
var saveButton = new GUIButton(new Rectangle(-90, 0, 80, 20), TextManager.Get("SaveSubButton"), Alignment.Right | Alignment.Bottom, "", saveFrame);
|
||||||
@@ -1082,6 +1086,12 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (wallPoints.Count < 4)
|
||||||
|
{
|
||||||
|
DebugConsole.ThrowError("Generating hulls for the submarine failed. Not enough wall structures to generate hulls.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
min = wallPoints[0];
|
min = wallPoints[0];
|
||||||
max = wallPoints[0];
|
max = wallPoints[0];
|
||||||
for (int i = 0; i < wallPoints.Count; i++)
|
for (int i = 0; i < wallPoints.Count; i++)
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ namespace Barotrauma.Sounds
|
|||||||
|
|
||||||
using (VorbisReader reader = new VorbisReader(oggFile))
|
using (VorbisReader reader = new VorbisReader(oggFile))
|
||||||
{
|
{
|
||||||
int bufferSize = (int)reader.TotalSamples;
|
int bufferSize = (int)reader.TotalSamples * reader.Channels;
|
||||||
|
|
||||||
float[] buffer = new float[bufferSize];
|
float[] buffer = new float[bufferSize];
|
||||||
sound.castBuffer = new short[bufferSize];
|
sound.castBuffer = new short[bufferSize];
|
||||||
@@ -52,11 +52,13 @@ namespace Barotrauma.Sounds
|
|||||||
sound.format = reader.Channels == 1 ? ALFormat.Mono16 : ALFormat.Stereo16;
|
sound.format = reader.Channels == 1 ? ALFormat.Mono16 : ALFormat.Stereo16;
|
||||||
sound.sampleRate = reader.SampleRate;
|
sound.sampleRate = reader.SampleRate;
|
||||||
|
|
||||||
|
ALHelper.Check();
|
||||||
|
|
||||||
//alSourceId = AL.GenSource();
|
//alSourceId = AL.GenSource();
|
||||||
AL.BufferData(sound.alBufferId, reader.Channels == 1 ? ALFormat.Mono16 : ALFormat.Stereo16, sound.castBuffer,
|
AL.BufferData(sound.alBufferId, reader.Channels == 1 ? ALFormat.Mono16 : ALFormat.Stereo16, sound.castBuffer,
|
||||||
readSamples * sizeof(short), reader.SampleRate);
|
readSamples * sizeof(short), reader.SampleRate);
|
||||||
|
|
||||||
ALHelper.Check();
|
ALHelper.Check(oggFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
//AL.Source(alSourceId, ALSourcei.Buffer, alBufferId);
|
//AL.Source(alSourceId, ALSourcei.Buffer, alBufferId);
|
||||||
@@ -100,12 +102,12 @@ namespace Barotrauma.Sounds
|
|||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
//var state = AL.GetSourceState(alSourceId);
|
|
||||||
//if (state == ALSourceState.Playing || state == ALSourceState.Paused)
|
|
||||||
// Stop();
|
|
||||||
System.Diagnostics.Debug.WriteLine(alBufferId);
|
System.Diagnostics.Debug.WriteLine(alBufferId);
|
||||||
//AL.DeleteSource(alSourceId);
|
if (alBufferId > 0)
|
||||||
AL.DeleteBuffer(alBufferId);
|
{
|
||||||
|
AL.DeleteBuffer(alBufferId);
|
||||||
|
alBufferId = 0;
|
||||||
|
}
|
||||||
|
|
||||||
//if (ALHelper.Efx.IsInitialized)
|
//if (ALHelper.Efx.IsInitialized)
|
||||||
// ALHelper.Efx.DeleteFilter(alFilterId);
|
// ALHelper.Efx.DeleteFilter(alFilterId);
|
||||||
|
|||||||
@@ -45,16 +45,24 @@ namespace Barotrauma.Sounds
|
|||||||
//logHandler(String.Format("Total memory : {0:0.###} {1} ", usedHeap, sizes[order]), 0, 6);
|
//logHandler(String.Format("Total memory : {0:0.###} {1} ", usedHeap, sizes[order]), 0, 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Check()
|
public static void Check(string extraErrorMsg = "")
|
||||||
{
|
{
|
||||||
ALError error;
|
ALError error;
|
||||||
if ((error = AL.GetError()) != ALError.NoError)
|
if ((error = AL.GetError()) != ALError.NoError)
|
||||||
{
|
{
|
||||||
|
string errorMsg = "OpenAL error: " + AL.GetErrorString(error);
|
||||||
|
if (!string.IsNullOrEmpty(extraErrorMsg)) errorMsg += " {" + extraErrorMsg + "} ";
|
||||||
|
errorMsg += "\n" + Environment.StackTrace;
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
DebugConsole.ThrowError("OpenAL error: " + AL.GetErrorString(error) + "\n" + Environment.StackTrace);
|
DebugConsole.ThrowError(errorMsg);
|
||||||
#else
|
#else
|
||||||
DebugConsole.NewMessage("OpenAL error: " + AL.GetErrorString(error) + "\n" + Environment.StackTrace, Microsoft.Xna.Framework.Color.Red);
|
DebugConsole.NewMessage(errorMsg, Microsoft.Xna.Framework.Color.Red);
|
||||||
#endif
|
#endif
|
||||||
|
GameAnalyticsManager.AddErrorEventOnce(
|
||||||
|
"OggStream.Check:" + AL.GetErrorString(error) + extraErrorMsg,
|
||||||
|
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||||
|
errorMsg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -83,9 +91,17 @@ namespace Barotrauma.Sounds
|
|||||||
public Action<string, int, int> LogHandler;
|
public Action<string, int, int> LogHandler;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public OggStream(string filename, int bufferCount = DefaultBufferCount) : this(File.OpenRead(filename), bufferCount) { }
|
public string FileName
|
||||||
public OggStream(Stream stream, int bufferCount = DefaultBufferCount)
|
|
||||||
{
|
{
|
||||||
|
get;
|
||||||
|
private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OggStream(string filename, int bufferCount = DefaultBufferCount) : this(File.OpenRead(filename), filename, bufferCount) { }
|
||||||
|
public OggStream(Stream stream, string fileName, int bufferCount = DefaultBufferCount)
|
||||||
|
{
|
||||||
|
this.FileName = fileName;
|
||||||
|
|
||||||
BufferCount = bufferCount;
|
BufferCount = bufferCount;
|
||||||
|
|
||||||
alBufferIds = AL.GenBuffers(bufferCount);
|
alBufferIds = AL.GenBuffers(bufferCount);
|
||||||
@@ -94,7 +110,7 @@ namespace Barotrauma.Sounds
|
|||||||
if (ALHelper.XRam.IsInitialized)
|
if (ALHelper.XRam.IsInitialized)
|
||||||
{
|
{
|
||||||
ALHelper.XRam.SetBufferMode(BufferCount, ref alBufferIds[0], XRamExtension.XRamStorage.Hardware);
|
ALHelper.XRam.SetBufferMode(BufferCount, ref alBufferIds[0], XRamExtension.XRamStorage.Hardware);
|
||||||
ALHelper.Check();
|
ALHelper.Check(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ALHelper.Efx.IsInitialized)
|
if (ALHelper.Efx.IsInitialized)
|
||||||
@@ -163,7 +179,7 @@ namespace Barotrauma.Sounds
|
|||||||
|
|
||||||
AL.SourcePlay(alSourceId);
|
AL.SourcePlay(alSourceId);
|
||||||
this.Volume = volume;
|
this.Volume = volume;
|
||||||
ALHelper.Check();
|
ALHelper.Check(FileName);
|
||||||
|
|
||||||
Preparing = false;
|
Preparing = false;
|
||||||
|
|
||||||
@@ -177,7 +193,7 @@ namespace Barotrauma.Sounds
|
|||||||
|
|
||||||
OggStreamer.Instance.RemoveStream(this);
|
OggStreamer.Instance.RemoveStream(this);
|
||||||
AL.SourcePause(alSourceId);
|
AL.SourcePause(alSourceId);
|
||||||
ALHelper.Check();
|
ALHelper.Check(FileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Resume()
|
public void Resume()
|
||||||
@@ -187,7 +203,7 @@ namespace Barotrauma.Sounds
|
|||||||
|
|
||||||
OggStreamer.Instance.AddStream(this);
|
OggStreamer.Instance.AddStream(this);
|
||||||
AL.SourcePlay(alSourceId);
|
AL.SourcePlay(alSourceId);
|
||||||
ALHelper.Check();
|
ALHelper.Check(FileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Stop()
|
public void Stop()
|
||||||
@@ -226,7 +242,7 @@ namespace Barotrauma.Sounds
|
|||||||
set
|
set
|
||||||
{
|
{
|
||||||
AL.Source(alSourceId, ALSourcef.Gain, volume = value);
|
AL.Source(alSourceId, ALSourcef.Gain, volume = value);
|
||||||
ALHelper.Check();
|
ALHelper.Check(FileName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -256,20 +272,20 @@ namespace Barotrauma.Sounds
|
|||||||
/*if (ALHelper.Efx.IsInitialized)
|
/*if (ALHelper.Efx.IsInitialized)
|
||||||
ALHelper.Efx.DeleteFilter(alFilterId);*/
|
ALHelper.Efx.DeleteFilter(alFilterId);*/
|
||||||
|
|
||||||
ALHelper.Check();
|
ALHelper.Check(FileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StopPlayback()
|
void StopPlayback()
|
||||||
{
|
{
|
||||||
AL.SourceStop(alSourceId);
|
AL.SourceStop(alSourceId);
|
||||||
ALHelper.Check();
|
ALHelper.Check(FileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Empty()
|
void Empty()
|
||||||
{
|
{
|
||||||
int queued;
|
int queued;
|
||||||
AL.GetSource(alSourceId, ALGetSourcei.BuffersQueued, out queued);
|
AL.GetSource(alSourceId, ALGetSourcei.BuffersQueued, out queued);
|
||||||
ALHelper.Check();
|
ALHelper.Check(FileName);
|
||||||
|
|
||||||
if (queued > 0)
|
if (queued > 0)
|
||||||
{
|
{
|
||||||
@@ -292,12 +308,12 @@ namespace Barotrauma.Sounds
|
|||||||
if (processed > 0)
|
if (processed > 0)
|
||||||
{
|
{
|
||||||
AL.SourceUnqueueBuffers(alSourceId, processed, salvaged);
|
AL.SourceUnqueueBuffers(alSourceId, processed, salvaged);
|
||||||
ALHelper.Check();
|
ALHelper.Check(FileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try turning it off again?
|
// Try turning it off again?
|
||||||
AL.SourceStop(alSourceId);
|
AL.SourceStop(alSourceId);
|
||||||
ALHelper.Check();
|
ALHelper.Check(FileName);
|
||||||
|
|
||||||
Empty();
|
Empty();
|
||||||
}
|
}
|
||||||
@@ -314,7 +330,7 @@ namespace Barotrauma.Sounds
|
|||||||
// Fill first buffer synchronously
|
// Fill first buffer synchronously
|
||||||
OggStreamer.Instance.FillBuffer(this, alBufferIds[0]);
|
OggStreamer.Instance.FillBuffer(this, alBufferIds[0]);
|
||||||
AL.SourceQueueBuffer(alSourceId, alBufferIds[0]);
|
AL.SourceQueueBuffer(alSourceId, alBufferIds[0]);
|
||||||
ALHelper.Check();
|
ALHelper.Check(FileName);
|
||||||
|
|
||||||
// Schedule the others asynchronously
|
// Schedule the others asynchronously
|
||||||
OggStreamer.Instance.AddStream(this);
|
OggStreamer.Instance.AddStream(this);
|
||||||
@@ -429,7 +445,7 @@ namespace Barotrauma.Sounds
|
|||||||
}
|
}
|
||||||
AL.BufferData(bufferId, stream.Reader.Channels == 1 ? ALFormat.Mono16 : ALFormat.Stereo16, castBuffer,
|
AL.BufferData(bufferId, stream.Reader.Channels == 1 ? ALFormat.Mono16 : ALFormat.Stereo16, castBuffer,
|
||||||
readSamples * sizeof(short), stream.Reader.SampleRate);
|
readSamples * sizeof(short), stream.Reader.SampleRate);
|
||||||
ALHelper.Check();
|
ALHelper.Check(stream.FileName);
|
||||||
|
|
||||||
return readSamples != BufferSize;
|
return readSamples != BufferSize;
|
||||||
}
|
}
|
||||||
@@ -466,10 +482,10 @@ namespace Barotrauma.Sounds
|
|||||||
|
|
||||||
int queued;
|
int queued;
|
||||||
AL.GetSource(stream.alSourceId, ALGetSourcei.BuffersQueued, out queued);
|
AL.GetSource(stream.alSourceId, ALGetSourcei.BuffersQueued, out queued);
|
||||||
ALHelper.Check();
|
ALHelper.Check(stream.FileName);
|
||||||
int processed;
|
int processed;
|
||||||
AL.GetSource(stream.alSourceId, ALGetSourcei.BuffersProcessed, out processed);
|
AL.GetSource(stream.alSourceId, ALGetSourcei.BuffersProcessed, out processed);
|
||||||
ALHelper.Check();
|
ALHelper.Check(stream.FileName);
|
||||||
|
|
||||||
if (processed == 0 && queued == stream.BufferCount) continue;
|
if (processed == 0 && queued == stream.BufferCount) continue;
|
||||||
|
|
||||||
@@ -496,7 +512,7 @@ namespace Barotrauma.Sounds
|
|||||||
}
|
}
|
||||||
|
|
||||||
AL.SourceQueueBuffers(stream.alSourceId, tempBuffers.Length, tempBuffers);
|
AL.SourceQueueBuffers(stream.alSourceId, tempBuffers.Length, tempBuffers);
|
||||||
ALHelper.Check();
|
ALHelper.Check(stream.FileName);
|
||||||
|
|
||||||
if (finished && !stream.IsLooped)
|
if (finished && !stream.IsLooped)
|
||||||
continue;
|
continue;
|
||||||
@@ -514,7 +530,7 @@ namespace Barotrauma.Sounds
|
|||||||
if (state == ALSourceState.Stopped)
|
if (state == ALSourceState.Stopped)
|
||||||
{
|
{
|
||||||
AL.SourcePlay(stream.alSourceId);
|
AL.SourcePlay(stream.alSourceId);
|
||||||
ALHelper.Check();
|
ALHelper.Check(stream.FileName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
DebugConsole.ThrowError("Failed to load sound "+file+"!", e);
|
DebugConsole.ThrowError("Failed to load sound "+file+"!", e);
|
||||||
}
|
}
|
||||||
ALHelper.Check();
|
ALHelper.Check(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
baseVolume = 1.0f;
|
baseVolume = 1.0f;
|
||||||
@@ -219,7 +219,7 @@ namespace Barotrauma
|
|||||||
(SoundManager.IsPlaying(alSourceId) || SoundManager.IsPaused(alSourceId)))
|
(SoundManager.IsPlaying(alSourceId) || SoundManager.IsPaused(alSourceId)))
|
||||||
{
|
{
|
||||||
SoundManager.Stop(alSourceId);
|
SoundManager.Stop(alSourceId);
|
||||||
ALHelper.Check();
|
ALHelper.Check(filePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (Sound s in loadedSounds)
|
foreach (Sound s in loadedSounds)
|
||||||
@@ -228,7 +228,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
SoundManager.ClearAlSource(AlBufferId);
|
SoundManager.ClearAlSource(AlBufferId);
|
||||||
ALHelper.Check();
|
ALHelper.Check(filePath);
|
||||||
|
|
||||||
if (oggSound != null)
|
if (oggSound != null)
|
||||||
{
|
{
|
||||||
@@ -246,7 +246,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public static void StreamVolume(float volume = 1.0f)
|
public static void StreamVolume(float volume = 1.0f)
|
||||||
{
|
{
|
||||||
if (SoundManager.Disabled) return;
|
if (SoundManager.Disabled || stream == null) return;
|
||||||
stream.Volume = volume;
|
stream.Volume = volume;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -143,7 +143,7 @@ namespace Barotrauma.Sounds
|
|||||||
volume = 0.0f;
|
volume = 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sourceIndex<1 || soundsPlaying[sourceIndex] != sound)
|
if (sourceIndex < 1 || soundsPlaying[sourceIndex] != sound)
|
||||||
{
|
{
|
||||||
sourceIndex = Play(sound, position, volume, 0.0f, true);
|
sourceIndex = Play(sound, position, volume, 0.0f, true);
|
||||||
}
|
}
|
||||||
@@ -153,7 +153,7 @@ namespace Barotrauma.Sounds
|
|||||||
AL.Source(alSources[sourceIndex], ALSourceb.Looping, true);
|
AL.Source(alSources[sourceIndex], ALSourceb.Looping, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
ALHelper.Check();
|
ALHelper.Check(sound?.FilePath);
|
||||||
return sourceIndex;
|
return sourceIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,7 +165,7 @@ namespace Barotrauma.Sounds
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
AL.SourcePause(alSources[sourceIndex]);
|
AL.SourcePause(alSources[sourceIndex]);
|
||||||
ALHelper.Check();
|
ALHelper.Check(soundsPlaying[sourceIndex]?.FilePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Resume(int sourceIndex)
|
public static void Resume(int sourceIndex)
|
||||||
@@ -176,7 +176,7 @@ namespace Barotrauma.Sounds
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
AL.SourcePlay(alSources[sourceIndex]);
|
AL.SourcePlay(alSources[sourceIndex]);
|
||||||
ALHelper.Check();
|
ALHelper.Check(soundsPlaying[sourceIndex]?.FilePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Stop(int sourceIndex)
|
public static void Stop(int sourceIndex)
|
||||||
@@ -291,7 +291,7 @@ namespace Barotrauma.Sounds
|
|||||||
|
|
||||||
ALHelper.Efx.Filter(lowpassFilterId, OpenTK.Audio.OpenAL.EfxFilterf.LowpassGainHF, lowPassHfGain = value);
|
ALHelper.Efx.Filter(lowpassFilterId, OpenTK.Audio.OpenAL.EfxFilterf.LowpassGainHF, lowPassHfGain = value);
|
||||||
ALHelper.Efx.BindFilterToSource(alSources[i], lowpassFilterId);
|
ALHelper.Efx.BindFilterToSource(alSources[i], lowpassFilterId);
|
||||||
ALHelper.Check();
|
ALHelper.Check(soundsPlaying[i]?.FilePath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -316,7 +316,7 @@ namespace Barotrauma.Sounds
|
|||||||
|
|
||||||
ALHelper.Efx.Filter(lowpassFilterId, OpenTK.Audio.OpenAL.EfxFilterf.LowpassGainHF, lowPassGain);
|
ALHelper.Efx.Filter(lowpassFilterId, OpenTK.Audio.OpenAL.EfxFilterf.LowpassGainHF, lowPassGain);
|
||||||
ALHelper.Efx.BindFilterToSource(alSources[sourceIndex], lowpassFilterId);
|
ALHelper.Efx.BindFilterToSource(alSources[sourceIndex], lowpassFilterId);
|
||||||
ALHelper.Check();
|
ALHelper.Check(soundsPlaying[sourceIndex]?.FilePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static OggStream StartStream(string file, float volume = 1.0f)
|
public static OggStream StartStream(string file, float volume = 1.0f)
|
||||||
@@ -331,7 +331,7 @@ namespace Barotrauma.Sounds
|
|||||||
|
|
||||||
oggStream.Play(volume);
|
oggStream.Play(volume);
|
||||||
|
|
||||||
ALHelper.Check();
|
ALHelper.Check(file);
|
||||||
|
|
||||||
return oggStream;
|
return oggStream;
|
||||||
}
|
}
|
||||||
@@ -361,6 +361,7 @@ namespace Barotrauma.Sounds
|
|||||||
|
|
||||||
for (int i = 0; i < DefaultSourceCount; i++)
|
for (int i = 0; i < DefaultSourceCount; i++)
|
||||||
{
|
{
|
||||||
|
string soundPath = soundsPlaying[i]?.FilePath;
|
||||||
var state = OpenTK.Audio.OpenAL.AL.GetSourceState(alSources[i]);
|
var state = OpenTK.Audio.OpenAL.AL.GetSourceState(alSources[i]);
|
||||||
if (state == OpenTK.Audio.OpenAL.ALSourceState.Playing || state == OpenTK.Audio.OpenAL.ALSourceState.Paused)
|
if (state == OpenTK.Audio.OpenAL.ALSourceState.Playing || state == OpenTK.Audio.OpenAL.ALSourceState.Paused)
|
||||||
{
|
{
|
||||||
@@ -368,8 +369,7 @@ namespace Barotrauma.Sounds
|
|||||||
}
|
}
|
||||||
|
|
||||||
OpenTK.Audio.OpenAL.AL.DeleteSource(alSources[i]);
|
OpenTK.Audio.OpenAL.AL.DeleteSource(alSources[i]);
|
||||||
|
ALHelper.Check(soundPath);
|
||||||
ALHelper.Check();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (oggStream != null)
|
if (oggStream != null)
|
||||||
|
|||||||
@@ -254,9 +254,12 @@ namespace Barotrauma
|
|||||||
partial void DisposeTexture()
|
partial void DisposeTexture()
|
||||||
{
|
{
|
||||||
//check if another sprite is using the same texture
|
//check if another sprite is using the same texture
|
||||||
foreach (Sprite s in list)
|
if (!string.IsNullOrEmpty(file)) //file can be empty if the sprite is created directly from a Texture2D instance
|
||||||
{
|
{
|
||||||
if (s.file == file) return;
|
foreach (Sprite s in list)
|
||||||
|
{
|
||||||
|
if (s.file == file) return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//if not, free the texture
|
//if not, free the texture
|
||||||
@@ -267,6 +270,5 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ namespace Barotrauma
|
|||||||
using (Stream fileStream = File.OpenRead(path))
|
using (Stream fileStream = File.OpenRead(path))
|
||||||
{
|
{
|
||||||
var texture = Texture2D.FromStream(_graphicsDevice, fileStream);
|
var texture = Texture2D.FromStream(_graphicsDevice, fileStream);
|
||||||
texture = PreMultiplyAlpha(texture);
|
PreMultiplyAlpha(texture);
|
||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,7 +63,7 @@ namespace Barotrauma
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var texture = Texture2D.FromStream(_graphicsDevice, fileStream);
|
var texture = Texture2D.FromStream(_graphicsDevice, fileStream);
|
||||||
texture = PreMultiplyAlpha(texture);
|
PreMultiplyAlpha(texture);
|
||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
@@ -73,7 +73,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Texture2D PreMultiplyAlpha(Texture2D texture)
|
private static void PreMultiplyAlpha(Texture2D texture)
|
||||||
{
|
{
|
||||||
// Setup a render target to hold our final texture which will have premulitplied alpha values
|
// Setup a render target to hold our final texture which will have premulitplied alpha values
|
||||||
using (RenderTarget2D renderTarget = new RenderTarget2D(_graphicsDevice, texture.Width, texture.Height))
|
using (RenderTarget2D renderTarget = new RenderTarget2D(_graphicsDevice, texture.Width, texture.Height))
|
||||||
@@ -104,8 +104,6 @@ namespace Barotrauma
|
|||||||
_graphicsDevice.Textures[0] = null;
|
_graphicsDevice.Textures[0] = null;
|
||||||
texture.SetData(data);
|
texture.SetData(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
return texture;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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.8.1.5")]
|
[assembly: AssemblyVersion("0.8.2.0")]
|
||||||
[assembly: AssemblyFileVersion("0.8.1.5")]
|
[assembly: AssemblyFileVersion("0.8.2.0")]
|
||||||
|
|||||||
@@ -124,7 +124,6 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public void CloseServer()
|
public void CloseServer()
|
||||||
{
|
{
|
||||||
if (GameSettings.SendUserStatistics) GameAnalytics.OnStop();
|
|
||||||
Server.Disconnect();
|
Server.Disconnect();
|
||||||
Server = null;
|
Server = null;
|
||||||
}
|
}
|
||||||
@@ -171,7 +170,6 @@ namespace Barotrauma
|
|||||||
stopwatch.Stop();
|
stopwatch.Stop();
|
||||||
|
|
||||||
CloseServer();
|
CloseServer();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ProcessInput()
|
public void ProcessInput()
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ namespace Barotrauma
|
|||||||
inputThread.Start();
|
inputThread.Start();
|
||||||
game.Run();
|
game.Run();
|
||||||
inputThread.Abort(); inputThread.Join();
|
inputThread.Abort(); inputThread.Join();
|
||||||
|
if (GameSettings.SendUserStatistics) GameAnalytics.OnStop();
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
subs = Submarine.SavedSubmarines.Where(s => !s.HasTag(SubmarineTag.HideInMenus)).ToList();
|
subs = Submarine.SavedSubmarines.Where(s => !s.HasTag(SubmarineTag.HideInMenus)).ToList();
|
||||||
|
|
||||||
if (subs == null || subs.Count()==0)
|
if (subs == null || subs.Count() == 0)
|
||||||
{
|
{
|
||||||
throw new Exception("No submarines are available.");
|
throw new Exception("No submarines are available.");
|
||||||
}
|
}
|
||||||
@@ -187,7 +187,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (GameMain.Server.SubSelectionMode == SelectionMode.Random)
|
if (GameMain.Server.SubSelectionMode == SelectionMode.Random)
|
||||||
{
|
{
|
||||||
var nonShuttles = Submarine.SavedSubmarines.FindAll(c => !c.HasTag(SubmarineTag.Shuttle) && !c.HasTag(SubmarineTag.HideInMenus));
|
var nonShuttles = Submarine.SavedSubmarines.Where(c => !c.HasTag(SubmarineTag.Shuttle) && !c.HasTag(SubmarineTag.HideInMenus)).ToList();
|
||||||
SelectedSub = nonShuttles[Rand.Range(0, nonShuttles.Count)];
|
SelectedSub = nonShuttles[Rand.Range(0, nonShuttles.Count)];
|
||||||
}
|
}
|
||||||
if (GameMain.Server.ModeSelectionMode == SelectionMode.Random)
|
if (GameMain.Server.ModeSelectionMode == SelectionMode.Random)
|
||||||
|
|||||||
@@ -325,12 +325,6 @@
|
|||||||
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Electricity\lightsprite.png">
|
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Electricity\lightsprite.png">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Electricity\monitor.png">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</Content>
|
|
||||||
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Electricity\monitors.xml">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</Content>
|
|
||||||
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Electricity\poweritems.xml">
|
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Electricity\poweritems.xml">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
|
|||||||
@@ -26,7 +26,8 @@
|
|||||||
<Item
|
<Item
|
||||||
name="Medicine Cabinet"
|
name="Medicine Cabinet"
|
||||||
linkable="true"
|
linkable="true"
|
||||||
pickdistance ="150">
|
pickdistance="150"
|
||||||
|
waterproof="true">
|
||||||
|
|
||||||
<Sprite texture ="cabinets.png" depth="0.84" sourcerect="0,0,48,64" canflipx="false"/>
|
<Sprite texture ="cabinets.png" depth="0.84" sourcerect="0,0,48,64" canflipx="false"/>
|
||||||
|
|
||||||
@@ -37,9 +38,10 @@
|
|||||||
</Item>
|
</Item>
|
||||||
|
|
||||||
<Item
|
<Item
|
||||||
name="Toxic Cabinet"
|
name="Toxic Cabinet"
|
||||||
linkable="true"
|
linkable="true"
|
||||||
pickdistance ="150">
|
pickdistance="150"
|
||||||
|
waterproof="true">
|
||||||
|
|
||||||
<Sprite texture ="cabinets.png" depth="0.84" sourcerect="0,64,48,64" canflipx="false"/>
|
<Sprite texture ="cabinets.png" depth="0.84" sourcerect="0,64,48,64" canflipx="false"/>
|
||||||
|
|
||||||
@@ -52,7 +54,7 @@
|
|||||||
<Item
|
<Item
|
||||||
name="Metal Crate"
|
name="Metal Crate"
|
||||||
linkable="true"
|
linkable="true"
|
||||||
pickdistance ="150">
|
pickdistance="150">
|
||||||
|
|
||||||
<Deconstruct time="20">
|
<Deconstruct time="20">
|
||||||
<Item name="Steel Bar"/>
|
<Item name="Steel Bar"/>
|
||||||
@@ -74,7 +76,7 @@
|
|||||||
<Item
|
<Item
|
||||||
name="Explosive Crate"
|
name="Explosive Crate"
|
||||||
linkable="true"
|
linkable="true"
|
||||||
pickdistance ="150">
|
pickdistance="150">
|
||||||
|
|
||||||
<Deconstruct time="20">
|
<Deconstruct time="20">
|
||||||
<Item name="Steel Bar"/>
|
<Item name="Steel Bar"/>
|
||||||
|
|||||||
@@ -139,6 +139,8 @@
|
|||||||
<sprite texture="DivingSuit.png" limb="RightFoot" sound="footstep_armor" sourcerect="30,100,20,25" origin="0.5,0.5" depth="0.013" inheritlimbdepth="false" hidelimb="true"/>
|
<sprite texture="DivingSuit.png" limb="RightFoot" sound="footstep_armor" sourcerect="30,100,20,25" origin="0.5,0.5" depth="0.013" inheritlimbdepth="false" hidelimb="true"/>
|
||||||
<sprite texture="DivingSuit.png" limb="LeftFoot" sound="footstep_armor" sourcerect="30,100,20,25" origin="0.5,0.5" depth="0.013" inheritlimbdepth="false" hidelimb="true"/>
|
<sprite texture="DivingSuit.png" limb="LeftFoot" sound="footstep_armor" sourcerect="30,100,20,25" origin="0.5,0.5" depth="0.013" inheritlimbdepth="false" hidelimb="true"/>
|
||||||
|
|
||||||
|
<sprite texture="DivingSuit.png" limb="Waist" sourcerect="0,0,1,1" origin="0.5,0.5" depth="0.0" inheritlimbdepth="false" hidelimb="true"/>
|
||||||
|
|
||||||
<StatusEffect type="OnWearing" target="Character" HideFace="true" ObstructVision="true" PressureProtection="100.0" SpeedMultiplier="0.6" LowPassMultiplier="0.2" setvalue="true" disabledeltatime="true"/>
|
<StatusEffect type="OnWearing" target="Character" HideFace="true" ObstructVision="true" PressureProtection="100.0" SpeedMultiplier="0.6" LowPassMultiplier="0.2" setvalue="true" disabledeltatime="true"/>
|
||||||
<StatusEffect type="OnWearing" target="Contained,Character" OxygenAvailable="1000.0" Condition="-0.5">
|
<StatusEffect type="OnWearing" target="Contained,Character" OxygenAvailable="1000.0" Condition="-0.5">
|
||||||
<RequiredItem type="Contained" name="Oxygen Tank"/>
|
<RequiredItem type="Contained" name="Oxygen Tank"/>
|
||||||
|
|||||||
@@ -103,8 +103,7 @@
|
|||||||
|
|
||||||
<Item
|
<Item
|
||||||
name="Docking Port"
|
name="Docking Port"
|
||||||
linkable="true"
|
linkable="true">
|
||||||
>
|
|
||||||
|
|
||||||
<Sprite texture ="dockingport.png" sourcerect="0,0,112,208" depth="0.94" origin="0.5,0.5"/>
|
<Sprite texture ="dockingport.png" sourcerect="0,0,112,208" depth="0.94" origin="0.5,0.5"/>
|
||||||
|
|
||||||
@@ -117,13 +116,7 @@
|
|||||||
</StatusEffect>
|
</StatusEffect>
|
||||||
</DockingPort>
|
</DockingPort>
|
||||||
|
|
||||||
<fixrequirement name="Electrical repairs">
|
<PowerTransfer CanBeOverloaded="false" FireProbability="0.0"/>
|
||||||
<skill name="Electrical Engineering" level="40"/>
|
|
||||||
<item name="Wire"/>
|
|
||||||
<item name="Screwdriver"/>
|
|
||||||
</fixrequirement>
|
|
||||||
|
|
||||||
<PowerTransfer/>
|
|
||||||
<Wire/>
|
<Wire/>
|
||||||
|
|
||||||
<fixrequirement name="Mechanical repairs">
|
<fixrequirement name="Mechanical repairs">
|
||||||
@@ -143,8 +136,7 @@
|
|||||||
|
|
||||||
<Item
|
<Item
|
||||||
name="Docking Hatch"
|
name="Docking Hatch"
|
||||||
linkable="true"
|
linkable="true">
|
||||||
>
|
|
||||||
|
|
||||||
<Sprite texture ="dockingport2.png" sourcerect="0,0,128,112" depth="0.94" origin="0.5,0.5"/>
|
<Sprite texture ="dockingport2.png" sourcerect="0,0,128,112" depth="0.94" origin="0.5,0.5"/>
|
||||||
|
|
||||||
@@ -157,13 +149,7 @@
|
|||||||
</StatusEffect>
|
</StatusEffect>
|
||||||
</DockingPort>
|
</DockingPort>
|
||||||
|
|
||||||
<fixrequirement name="Electrical repairs">
|
<PowerTransfer CanBeOverloaded="false" FireProbability="0.0"/>
|
||||||
<skill name="Electrical Engineering" level="40"/>
|
|
||||||
<item name="Wire"/>
|
|
||||||
<item name="Screwdriver"/>
|
|
||||||
</fixrequirement>
|
|
||||||
|
|
||||||
<PowerTransfer/>
|
|
||||||
<Wire/>
|
<Wire/>
|
||||||
|
|
||||||
<fixrequirement name="Mechanical repairs">
|
<fixrequirement name="Mechanical repairs">
|
||||||
@@ -183,8 +169,7 @@
|
|||||||
|
|
||||||
<Item
|
<Item
|
||||||
name="Duct Block"
|
name="Duct Block"
|
||||||
linkable="true"
|
linkable="true">
|
||||||
>
|
|
||||||
|
|
||||||
<Sprite texture ="duct.png" sourcerect="0,0,33,33" depth="0.01" origin="0.5,0.5"/>
|
<Sprite texture ="duct.png" sourcerect="0,0,33,33" depth="0.01" origin="0.5,0.5"/>
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 216 B |
@@ -1,18 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8" ?>
|
|
||||||
<Item
|
|
||||||
name="Monitor"
|
|
||||||
linkable="true">
|
|
||||||
|
|
||||||
<Sprite texture ="monitor.png" depth="0.85" sourcerect="0,0,16,16"/>
|
|
||||||
|
|
||||||
<Body width="16" height="16" density="30"/>
|
|
||||||
|
|
||||||
<Holdable slots="Any,RightHand,LeftHand" msg="Detach [Wrench]"
|
|
||||||
aimpos="35,-10" handle1="0,0" attachable="true" aimable="true">
|
|
||||||
<requireditem name="Wrench" type="Equipped"/>
|
|
||||||
</Holdable>
|
|
||||||
|
|
||||||
<Label canbeselected = "true">
|
|
||||||
<GuiFrame rect="0,0,0.4,0.4" alignment="Center" style="ItemUI"/>
|
|
||||||
</Label>
|
|
||||||
</Item>
|
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
name="Red Wire"
|
name="Red Wire"
|
||||||
category="Electrical"
|
category="Electrical"
|
||||||
Tags="smallitem,wire"
|
Tags="smallitem,wire"
|
||||||
spritecolor="1.0,0.0,0.0,1.0"
|
spritecolor="0.7,0.06,0.06,1.0"
|
||||||
linkable="true"
|
linkable="true"
|
||||||
canbepicked="true"
|
canbepicked="true"
|
||||||
cargocontainername="Metal Crate"
|
cargocontainername="Metal Crate"
|
||||||
@@ -50,7 +50,7 @@
|
|||||||
name="Blue Wire"
|
name="Blue Wire"
|
||||||
category="Electrical"
|
category="Electrical"
|
||||||
Tags="smallitem,wire"
|
Tags="smallitem,wire"
|
||||||
spritecolor="0.0,0.6,1.0,1.0"
|
spritecolor="0.1,0.4,0.9,1.0"
|
||||||
linkable="true"
|
linkable="true"
|
||||||
canbepicked="true"
|
canbepicked="true"
|
||||||
cargocontainername="Metal Crate"
|
cargocontainername="Metal Crate"
|
||||||
@@ -72,7 +72,51 @@
|
|||||||
name="Orange Wire"
|
name="Orange Wire"
|
||||||
category="Electrical"
|
category="Electrical"
|
||||||
Tags="smallitem,wire"
|
Tags="smallitem,wire"
|
||||||
spritecolor="1.0,0.5,0.0,1.0"
|
spritecolor="0.9,0.58,0.07,1.0"
|
||||||
|
linkable="true"
|
||||||
|
canbepicked="true"
|
||||||
|
cargocontainername="Metal Crate"
|
||||||
|
price="10">
|
||||||
|
|
||||||
|
<Deconstruct time="5">
|
||||||
|
<Item name="Copper Bar"/>
|
||||||
|
</Deconstruct>
|
||||||
|
|
||||||
|
<Sprite texture ="signalcomp.png" depth="0.55" sourcerect="83,105,44,22"/>
|
||||||
|
|
||||||
|
<Body radius="7" width="25" density="30"/>
|
||||||
|
<Holdable slots="Any,RightHand,LeftHand" handle1="0,0"/>
|
||||||
|
|
||||||
|
<Wire/>
|
||||||
|
</Item>
|
||||||
|
|
||||||
|
<Item
|
||||||
|
name="Green Wire"
|
||||||
|
category="Electrical"
|
||||||
|
Tags="smallitem,wire"
|
||||||
|
spritecolor="0.17,0.45,0.05,1.0"
|
||||||
|
linkable="true"
|
||||||
|
canbepicked="true"
|
||||||
|
cargocontainername="Metal Crate"
|
||||||
|
price="10">
|
||||||
|
|
||||||
|
<Deconstruct time="5">
|
||||||
|
<Item name="Copper Bar"/>
|
||||||
|
</Deconstruct>
|
||||||
|
|
||||||
|
<Sprite texture ="signalcomp.png" depth="0.55" sourcerect="83,105,44,22"/>
|
||||||
|
|
||||||
|
<Body radius="7" width="25" density="30"/>
|
||||||
|
<Holdable slots="Any,RightHand,LeftHand" handle1="0,0"/>
|
||||||
|
|
||||||
|
<Wire/>
|
||||||
|
</Item>
|
||||||
|
|
||||||
|
<Item
|
||||||
|
name="Black Wire"
|
||||||
|
category="Electrical"
|
||||||
|
Tags="smallitem,wire"
|
||||||
|
spritecolor="0.1,0.1,0.1,1.0"
|
||||||
linkable="true"
|
linkable="true"
|
||||||
canbepicked="true"
|
canbepicked="true"
|
||||||
cargocontainername="Metal Crate"
|
cargocontainername="Metal Crate"
|
||||||
@@ -261,7 +305,7 @@
|
|||||||
|
|
||||||
<Sprite texture="signalcomp.png" depth="0.8" sourcerect="48,16,16,16"/>
|
<Sprite texture="signalcomp.png" depth="0.8" sourcerect="48,16,16,16"/>
|
||||||
|
|
||||||
<RelayComponent canbeselected = "true">
|
<RelayComponent canbeselected="true" vulnerabletoemp="false">
|
||||||
<GuiFrame rect="0,0,200,160" alignment="Center" style="ItemUI"/>
|
<GuiFrame rect="0,0,200,160" alignment="Center" style="ItemUI"/>
|
||||||
</RelayComponent>
|
</RelayComponent>
|
||||||
|
|
||||||
|
|||||||
@@ -65,7 +65,7 @@
|
|||||||
</Deconstruct>
|
</Deconstruct>
|
||||||
|
|
||||||
<Wearable slots="Any,Torso+Legs">
|
<Wearable slots="Any,Torso+Legs">
|
||||||
<sprite texture="clownshirt.png" limb="Torso" sourcerect="0,3,30,58" origin="0.5,0.48" depth="0.02"/>
|
<sprite texture="clownshirt.png" limb="Torso" sourcerect="0,3,30,58" origin="0.5,0.48" depth="0.02" hidelimb="true"/>
|
||||||
|
|
||||||
<sprite texture="clownshirt.png" limb="RightHand" sourcerect="47,0,15,49" origin="0.45,0.6" hidelimb="true"/>
|
<sprite texture="clownshirt.png" limb="RightHand" sourcerect="47,0,15,49" origin="0.45,0.6" hidelimb="true"/>
|
||||||
<sprite texture="clownshirt.png" limb="LeftHand" sourcerect="47,0,15,49" origin="0.45,0.6" depth="0.14" hidelimb="true"/>
|
<sprite texture="clownshirt.png" limb="LeftHand" sourcerect="47,0,15,49" origin="0.45,0.6" depth="0.14" hidelimb="true"/>
|
||||||
|
|||||||
@@ -423,10 +423,13 @@
|
|||||||
<Body width="8" height="16" density="10"/>
|
<Body width="8" height="16" density="10"/>
|
||||||
|
|
||||||
<Throwable characterusable="true" canBeCombined="true" slots="Any,RightHand,LeftHand" throwforce="4.0" aimpos="35,-10">
|
<Throwable characterusable="true" canBeCombined="true" slots="Any,RightHand,LeftHand" throwforce="4.0" aimpos="35,-10">
|
||||||
<StatusEffect type="OnUse" target="Character" HuskInfectionState="-0.2">
|
<StatusEffect type="OnUse" target="Character" HuskInfectionState="-0.4">
|
||||||
<Conditional HuskInfectionState="lt 1.0"/>
|
<Conditional HuskInfectionState="lt 1.0"/>
|
||||||
<RequiredItem name="Medical Syringe" type="Container"/>
|
<RequiredItem name="Medical Syringe" type="Container"/>
|
||||||
</StatusEffect>
|
</StatusEffect>
|
||||||
|
<StatusEffect type="OnUse" target="Character" HuskInfectionState="-0.1">
|
||||||
|
<Conditional HuskInfectionState="lt 1.0"/>
|
||||||
|
</StatusEffect>
|
||||||
<StatusEffect tags="poison,calyxanide" type="OnUse" target="Character" Health="-3.0" duration="10.0">
|
<StatusEffect tags="poison,calyxanide" type="OnUse" target="Character" Health="-3.0" duration="10.0">
|
||||||
<!-- Injecting a still-conscious Husk will only piss it off and kill the "conscious" faster -->
|
<!-- Injecting a still-conscious Husk will only piss it off and kill the "conscious" faster -->
|
||||||
<Conditional HuskInfectionState="eq 1.0"/>
|
<Conditional HuskInfectionState="eq 1.0"/>
|
||||||
|
|||||||
@@ -13,16 +13,13 @@
|
|||||||
</fixrequirement>
|
</fixrequirement>
|
||||||
|
|
||||||
<OxygenGenerator powerconsumption="1000.0" minvoltage="0.5" canbeselected = "true">
|
<OxygenGenerator powerconsumption="1000.0" minvoltage="0.5" canbeselected = "true">
|
||||||
|
|
||||||
<StatusEffect type="OnFire" target="This" Condition="-0.5"/>
|
<StatusEffect type="OnFire" target="This" Condition="-0.5"/>
|
||||||
<StatusEffect type="OnActive" target="Contained" targetnames="Oxygen Tank" Condition="2.0"/>
|
<StatusEffect type="OnActive" target="Contained" targetnames="Oxygen Tank" Condition="2.0"/>
|
||||||
<StatusEffect type="OnActive" target="Contained" targetnames="Oxygenite Tank" Condition="0.0"/>
|
|
||||||
<sound file="Content/Items/OxygenGenerator/oxygengenerator.ogg" type="OnActive" range="1000.0" volume="CurrFlow" volumemultiplier="0.001f" loop="true"/>
|
<sound file="Content/Items/OxygenGenerator/oxygengenerator.ogg" type="OnActive" range="1000.0" volume="CurrFlow" volumemultiplier="0.001f" loop="true"/>
|
||||||
|
<StatusEffect type="OnBroken" target="This" disabledeltatime="true">
|
||||||
<StatusEffect type="OnBroken" target="This" disabledeltatime="true">
|
<sound file="Content/Items/Reactor/explosion.ogg"/>
|
||||||
<sound file="Content/Items/Reactor/explosion.ogg"/>
|
<Explosion range="50" damage="0" stun="0" force="3.0" flames="false" shockwave="false" sparks="true"/>
|
||||||
<Explosion range="50" damage="0" stun="0" force="3.0" flames="false" shockwave="false" sparks="true"/>
|
</StatusEffect>
|
||||||
</StatusEffect>
|
|
||||||
</OxygenGenerator>
|
</OxygenGenerator>
|
||||||
|
|
||||||
<trigger/>
|
<trigger/>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
<Sprite texture = "reactor.png" sourcerect="0,0,321,192" depth="0.8"/>
|
<Sprite texture = "reactor.png" sourcerect="0,0,321,192" depth="0.8"/>
|
||||||
|
|
||||||
<Reactor canbeselected = "true">
|
<Reactor canbeselected="true" vulnerabletoemp="false">
|
||||||
<GuiFrame rect="0,0,760,460" alignment="Center" style="ItemUI"/>
|
<GuiFrame rect="0,0,760,460" alignment="Center" style="ItemUI"/>
|
||||||
<RequiredSkill name="Construction" level="30"/>
|
<RequiredSkill name="Construction" level="30"/>
|
||||||
<StatusEffect type="InWater" target="This" Temperature="-500.0"/>
|
<StatusEffect type="InWater" target="This" Temperature="-500.0"/>
|
||||||
|
|||||||
@@ -286,12 +286,12 @@
|
|||||||
|
|
||||||
<Holdable slots="Any,RightHand,LeftHand,Face" holdpos="30,-15" aimpos="100,0" handle1="-13,0" handle2="-13,0">
|
<Holdable slots="Any,RightHand,LeftHand,Face" holdpos="30,-15" aimpos="100,0" handle1="-13,0" handle2="-13,0">
|
||||||
<StatusEffect type="OnActive" target="Contained" Condition="-0.2"/>
|
<StatusEffect type="OnActive" target="Contained" Condition="-0.2"/>
|
||||||
|
<!-- the child LightComponent is only active when the Holdable is active, i.e. when the item is being held -->
|
||||||
|
<LightComponent LightColor="1.0,1.0,1.0,1.0" Flicker="0.1" range="800" powerconsumption="10" IsOn="true">
|
||||||
|
<LightTexture texture="Content/Lights/lightcone.png" origin="0.0, 0.5" size="2.0,1.0"/>
|
||||||
|
</LightComponent>
|
||||||
</Holdable>
|
</Holdable>
|
||||||
|
|
||||||
<LightComponent LightColor="1.0,1.0,1.0,1.0" Flicker="0.1" range="800" powerconsumption="10" IsOn="true">
|
|
||||||
<LightTexture texture="Content/Lights/lightcone.png" origin="0.0, 0.5" size="2.0,1.0"/>
|
|
||||||
</LightComponent>
|
|
||||||
|
|
||||||
<ItemContainer capacity="1" hideitems="true">
|
<ItemContainer capacity="1" hideitems="true">
|
||||||
<Containable name="Battery Cell, Fulgurium Battery Cell">
|
<Containable name="Battery Cell, Fulgurium Battery Cell">
|
||||||
<StatusEffect type="OnContaining" target="This" Voltage="1.0" setvalue="true"/>
|
<StatusEffect type="OnContaining" target="This" Voltage="1.0" setvalue="true"/>
|
||||||
|
|||||||
@@ -9,11 +9,12 @@
|
|||||||
|
|
||||||
<Sprite texture ="railgunetc.png" depth="0.01" sourcerect="64,180,47,76"/>
|
<Sprite texture ="railgunetc.png" depth="0.01" sourcerect="64,180,47,76"/>
|
||||||
|
|
||||||
<Turret canbeselected = "true" linkable="true" barrelpos="23, 76"
|
<Turret canbeselected="false" linkable="true" characterusable="false"
|
||||||
|
barrelpos="23, 76"
|
||||||
rotationlimits="90,90"
|
rotationlimits="90,90"
|
||||||
powerconsumption="0.0"/>
|
powerconsumption="0.0"/>
|
||||||
|
|
||||||
<ConnectionPanel selectkey="Action" canbeselected = "true" msg="Rewire [Screwdriver]">
|
<ConnectionPanel selectkey="Action" canbeselected="true" msg="Rewire [Screwdriver]">
|
||||||
<requireditem name="Screwdriver,Wire" type="Equipped"/>
|
<requireditem name="Screwdriver,Wire" type="Equipped"/>
|
||||||
<input name="trigger_in"/>
|
<input name="trigger_in"/>
|
||||||
</ConnectionPanel>
|
</ConnectionPanel>
|
||||||
|
|||||||
@@ -2,13 +2,18 @@
|
|||||||
<Item
|
<Item
|
||||||
name="Railgun"
|
name="Railgun"
|
||||||
category="Machine"
|
category="Machine"
|
||||||
|
interactthroughwalls="true"
|
||||||
|
interactdistance="10"
|
||||||
focusonselected="true"
|
focusonselected="true"
|
||||||
offsetonselected="700"
|
offsetonselected="700"
|
||||||
linkable="true">
|
linkable="true">
|
||||||
|
|
||||||
<Sprite texture="railgunbase.png" depth="0.01" sourcerect="0,0,256,256"/>
|
<Sprite texture="railgunbase.png" depth="0.01" sourcerect="0,0,256,256"/>
|
||||||
|
|
||||||
<Turret barrelsprite="railgunbarrel.png" canbeselected = "true" linkable="true" origin="0.5, 0.85" barrelpos="128, 128"
|
<StaticBody width="80" radius="80"/>
|
||||||
|
|
||||||
|
<Turret barrelsprite="railgunbarrel.png" canbeselected="false" characterusable="false" linkable="true"
|
||||||
|
origin="0.5, 0.85" barrelpos="128, 128"
|
||||||
rotationlimits="180,360"
|
rotationlimits="180,360"
|
||||||
powerconsumption="20000.0"
|
powerconsumption="20000.0"
|
||||||
showchargeindicator="true"
|
showchargeindicator="true"
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 17 KiB |
@@ -40,7 +40,7 @@
|
|||||||
<Body width="90" height="30" density="50"/>
|
<Body width="90" height="30" density="50"/>
|
||||||
|
|
||||||
<Holdable slots="Any,RightHand+LeftHand" controlpose="true"
|
<Holdable slots="Any,RightHand+LeftHand" controlpose="true"
|
||||||
holdpos="35,-10" aimpos="35,-10" handle1="-15,-6" handle2="26,7"/>
|
holdpos="35,-10" aimpos="35,-10" handle1="-15,-6" handle2="26,7" holdangle="-40"/>
|
||||||
|
|
||||||
<RangedWeapon barrelpos="49,10" spread="1" unskilledspread="10">
|
<RangedWeapon barrelpos="49,10" spread="1" unskilledspread="10">
|
||||||
<Sound file="Content/Items/Weapons/harpoon1.ogg" type="OnUse"/>
|
<Sound file="Content/Items/Weapons/harpoon1.ogg" type="OnUse"/>
|
||||||
@@ -120,14 +120,14 @@
|
|||||||
<Item name="Polycarbonate Bar"/>
|
<Item name="Polycarbonate Bar"/>
|
||||||
</Deconstruct>
|
</Deconstruct>
|
||||||
|
|
||||||
<Sprite texture="weapons.png" sourcerect="24,102,37,19" depth="0.55"/>
|
<Sprite texture="weapons.png" sourcerect="26,97,25,19" depth="0.55"/>
|
||||||
|
|
||||||
<Body width="37" height="18" density="50"/>
|
<Body width="25" height="15" density="50"/>
|
||||||
|
|
||||||
<Holdable slots="Any,RightHand,LeftHand" controlpose="true"
|
<Holdable slots="Any,RightHand,LeftHand" controlpose="true"
|
||||||
aimpos="75,18" handle1="-10,-5"/>
|
aimpos="90,10" handle1="-11,-7"/>
|
||||||
|
|
||||||
<RangedWeapon barrelpos="37,3" spread="0" unskilledspread="2">
|
<RangedWeapon barrelpos="14,6" spread="0" unskilledspread="2">
|
||||||
<Sound file="Content/Items/Weapons/revolver.ogg" type="OnUse" range="3000"/>
|
<Sound file="Content/Items/Weapons/revolver.ogg" type="OnUse" range="3000"/>
|
||||||
<StatusEffect type="OnUse">
|
<StatusEffect type="OnUse">
|
||||||
<Explosion range="150.0" force="5" shockwave="false" smoke="false" flames="false" sparks="false" camerashake="5.0"/>
|
<Explosion range="150.0" force="5" shockwave="false" smoke="false" flames="false" sparks="false" camerashake="5.0"/>
|
||||||
|
|||||||
@@ -16,11 +16,11 @@
|
|||||||
<Item name="Headset" equip="true">
|
<Item name="Headset" equip="true">
|
||||||
<Item name="Battery Cell"/>
|
<Item name="Battery Cell"/>
|
||||||
</Item>
|
</Item>
|
||||||
<Item name="Revolver" equip="false">
|
<Item name="Revolver" equip="false">
|
||||||
<Item name="Revolver Round"/>
|
<Item name="Revolver Round"/>
|
||||||
<Item name="Revolver Round"/>
|
<Item name="Revolver Round"/>
|
||||||
<Item name="Revolver Round"/>
|
<Item name="Revolver Round"/>
|
||||||
</Item>
|
</Item>
|
||||||
</Items>
|
</Items>
|
||||||
</Job>
|
</Job>
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,6 @@
|
|||||||
<Item file="Content/Items/Diving/divinggear.xml" />
|
<Item file="Content/Items/Diving/divinggear.xml" />
|
||||||
<Item file="Content/Items/Door/doors.xml" />
|
<Item file="Content/Items/Door/doors.xml" />
|
||||||
<Item file="Content/Items/Electricity/lights.xml" />
|
<Item file="Content/Items/Electricity/lights.xml" />
|
||||||
<Item file="Content/Items/Electricity/monitors.xml" />
|
|
||||||
<Item file="Content/Items/Electricity/poweritems.xml" />
|
<Item file="Content/Items/Electricity/poweritems.xml" />
|
||||||
<Item file="Content/Items/Electricity/signalitems.xml" />
|
<Item file="Content/Items/Electricity/signalitems.xml" />
|
||||||
<Item file="Content/Items/Engine/engine.xml" />
|
<Item file="Content/Items/Engine/engine.xml" />
|
||||||
|
|||||||
@@ -7,8 +7,8 @@
|
|||||||
|
|
||||||
<Preset
|
<Preset
|
||||||
name="Moderator"
|
name="Moderator"
|
||||||
description="Allowed to manage round settings and kick players."
|
description="Allowed to manage round settings, kick players and access server logs."
|
||||||
permissions="EndRound,Kick,SelectSub,SelectMode,ManageCampaign,ConsoleCommands">
|
permissions="EndRound,Kick,SelectSub,SelectMode,ManageCampaign,ConsoleCommands,ServerLog">
|
||||||
<Command name="clientlist"/>
|
<Command name="clientlist"/>
|
||||||
<Command name="autorestart"/>
|
<Command name="autorestart"/>
|
||||||
<Command name="autorestartinterval"/>
|
<Command name="autorestartinterval"/>
|
||||||
@@ -21,8 +21,8 @@
|
|||||||
|
|
||||||
<Preset
|
<Preset
|
||||||
name="Admin"
|
name="Admin"
|
||||||
description="Allowed to ban and kick players, manage round settings and use nearly all console commands."
|
description="Allowed to ban and kick players, manage round settings, access server logs and use nearly all console commands."
|
||||||
permissions="EndRound,Kick,Ban,SelectSub,SelectMode,ManageCampaign,ConsoleCommands">
|
permissions="EndRound,Kick,Ban,SelectSub,SelectMode,ManageCampaign,ConsoleCommands,ServerLog">
|
||||||
<Command name="clientlist"/>
|
<Command name="clientlist"/>
|
||||||
<Command name="autorestart"/>
|
<Command name="autorestart"/>
|
||||||
<Command name="autorestartinterval"/>
|
<Command name="autorestartinterval"/>
|
||||||
|
|||||||
@@ -38,6 +38,9 @@ namespace Barotrauma
|
|||||||
#if DEBUG
|
#if DEBUG
|
||||||
DebugConsole.ThrowError("Attempted to access a removed AITarget\n" + Environment.StackTrace);
|
DebugConsole.ThrowError("Attempted to access a removed AITarget\n" + Environment.StackTrace);
|
||||||
#endif
|
#endif
|
||||||
|
GameAnalyticsManager.AddErrorEventOnce("AITarget.WorldPosition:EntityRemoved",
|
||||||
|
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||||
|
"Attempted to access a removed AITarget\n" + Environment.StackTrace);
|
||||||
return Vector2.Zero;
|
return Vector2.Zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,6 +57,9 @@ namespace Barotrauma
|
|||||||
#if DEBUG
|
#if DEBUG
|
||||||
DebugConsole.ThrowError("Attempted to access a removed AITarget\n" + Environment.StackTrace);
|
DebugConsole.ThrowError("Attempted to access a removed AITarget\n" + Environment.StackTrace);
|
||||||
#endif
|
#endif
|
||||||
|
GameAnalyticsManager.AddErrorEventOnce("AITarget.WorldPosition:EntityRemoved",
|
||||||
|
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||||
|
"Attempted to access a removed AITarget\n" + Environment.StackTrace);
|
||||||
return Vector2.Zero;
|
return Vector2.Zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -274,7 +274,15 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private void UpdateEscape(float deltaTime)
|
private void UpdateEscape(float deltaTime)
|
||||||
{
|
{
|
||||||
SteeringManager.SteeringManual(deltaTime, Vector2.Normalize(SimPosition - selectedAiTarget.SimPosition) * 5);
|
if (selectedAiTarget == null || selectedAiTarget.Entity == null || selectedAiTarget.Entity.Removed)
|
||||||
|
{
|
||||||
|
state = AIState.None;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2 escapeDir = Vector2.Normalize(SimPosition - selectedAiTarget.SimPosition);
|
||||||
|
if (!MathUtils.IsValid(escapeDir)) escapeDir = Vector2.UnitY;
|
||||||
|
SteeringManager.SteeringManual(deltaTime, escapeDir * 5);
|
||||||
SteeringManager.SteeringWander(1.0f);
|
SteeringManager.SteeringWander(1.0f);
|
||||||
SteeringManager.SteeringAvoid(deltaTime, 2f);
|
SteeringManager.SteeringAvoid(deltaTime, 2f);
|
||||||
}
|
}
|
||||||
@@ -484,8 +492,10 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (dist < ConvertUnits.ToSimUnits(500.0f))
|
if (dist < ConvertUnits.ToSimUnits(500.0f))
|
||||||
{
|
{
|
||||||
|
Vector2 attackDir = Vector2.Normalize(Character.SimPosition - attackPosition);
|
||||||
|
if (!MathUtils.IsValid(attackDir)) attackDir = Vector2.UnitY;
|
||||||
steeringManager.SteeringSeek(attackPosition, -0.8f);
|
steeringManager.SteeringSeek(attackPosition, -0.8f);
|
||||||
steeringManager.SteeringManual(deltaTime, Vector2.Normalize(Character.SimPosition - attackPosition) * (1.0f - (dist / 500.0f)));
|
steeringManager.SteeringManual(deltaTime, attackDir * (1.0f - (dist / 500.0f)));
|
||||||
}
|
}
|
||||||
|
|
||||||
steeringManager.SteeringAvoid(deltaTime, 1.0f);
|
steeringManager.SteeringAvoid(deltaTime, 1.0f);
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ namespace Barotrauma
|
|||||||
character.SetInput(InputType.Aim, false, true);
|
character.SetInput(InputType.Aim, false, true);
|
||||||
|
|
||||||
Vector2 enemyDiff = Vector2.Normalize(enemy.Position - character.Position);
|
Vector2 enemyDiff = Vector2.Normalize(enemy.Position - character.Position);
|
||||||
|
if (!MathUtils.IsValid(enemyDiff)) enemyDiff = Rand.Vector(1.0f);
|
||||||
float weaponAngle = ((weapon.body.Dir == 1.0f) ? weapon.body.Rotation : weapon.body.Rotation - MathHelper.Pi);
|
float weaponAngle = ((weapon.body.Dir == 1.0f) ? weapon.body.Rotation : weapon.body.Rotation - MathHelper.Pi);
|
||||||
Vector2 weaponDir = new Vector2((float)Math.Cos(weaponAngle), (float)Math.Sin(weaponAngle));
|
Vector2 weaponDir = new Vector2((float)Math.Cos(weaponAngle), (float)Math.Sin(weaponAngle));
|
||||||
|
|
||||||
|
|||||||
@@ -30,13 +30,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
protected override void Act(float deltaTime)
|
protected override void Act(float deltaTime)
|
||||||
{
|
{
|
||||||
|
|
||||||
var pathSteering = character.AIController.SteeringManager as IndoorsSteeringManager;
|
var pathSteering = character.AIController.SteeringManager as IndoorsSteeringManager;
|
||||||
|
if (pathSteering == null) return;
|
||||||
if (pathSteering==null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (character.AnimController.InWater)
|
if (character.AnimController.InWater)
|
||||||
{
|
{
|
||||||
@@ -72,11 +67,11 @@ namespace Barotrauma
|
|||||||
// - if reached the end of the path
|
// - if reached the end of the path
|
||||||
// - if the target is unreachable
|
// - if the target is unreachable
|
||||||
// - if the path requires going outside
|
// - if the path requires going outside
|
||||||
if (pathSteering==null || (pathSteering.CurrentPath != null &&
|
if (pathSteering == null || (pathSteering.CurrentPath != null &&
|
||||||
(pathSteering.CurrentPath.NextNode == null || pathSteering.CurrentPath.Unreachable || pathSteering.CurrentPath.HasOutdoorsNodes)))
|
(pathSteering.CurrentPath.NextNode == null || pathSteering.CurrentPath.Unreachable || pathSteering.CurrentPath.HasOutdoorsNodes)))
|
||||||
{
|
{
|
||||||
//steer away from edges of the hull
|
//steer away from edges of the hull
|
||||||
if (character.AnimController.CurrentHull!=null)
|
if (character.AnimController.CurrentHull != null)
|
||||||
{
|
{
|
||||||
float leftDist = character.Position.X - character.AnimController.CurrentHull.Rect.X;
|
float leftDist = character.Position.X - character.AnimController.CurrentHull.Rect.X;
|
||||||
float rightDist = character.AnimController.CurrentHull.Rect.Right - character.Position.X;
|
float rightDist = character.AnimController.CurrentHull.Rect.Right - character.Position.X;
|
||||||
@@ -114,7 +109,12 @@ namespace Barotrauma
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentTarget == null) return;
|
if (currentTarget?.Entity == null) return;
|
||||||
|
if (currentTarget.Entity.Removed)
|
||||||
|
{
|
||||||
|
currentTarget = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
character.AIController.SteeringManager.SteeringSeek(currentTarget.SimPosition, 2.0f);
|
character.AIController.SteeringManager.SteeringSeek(currentTarget.SimPosition, 2.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public PathFinder(List<WayPoint> wayPoints, bool insideSubmarine = false)
|
public PathFinder(List<WayPoint> wayPoints, bool insideSubmarine = false)
|
||||||
{
|
{
|
||||||
nodes = PathNode.GenerateNodes(wayPoints.FindAll(w => w.MoveWithLevel != insideSubmarine));
|
nodes = PathNode.GenerateNodes(wayPoints.FindAll(w => (w.Submarine != null) == insideSubmarine));
|
||||||
|
|
||||||
foreach (WayPoint wp in wayPoints)
|
foreach (WayPoint wp in wayPoints)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -80,9 +80,9 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
float steeringSpeed = steering.Length();
|
float steeringSpeed = steering.Length();
|
||||||
if (steeringSpeed>speed)
|
if (steeringSpeed > speed)
|
||||||
{
|
{
|
||||||
steering = Vector2.Normalize(steering) * Math.Abs(speed);
|
steering = Vector2.Normalize(steering) * Math.Abs(speed);
|
||||||
}
|
}
|
||||||
|
|
||||||
host.Steering = steering;
|
host.Steering = steering;
|
||||||
@@ -97,12 +97,12 @@ namespace Barotrauma
|
|||||||
targetVel = Vector2.Normalize(targetVel) * speed;
|
targetVel = Vector2.Normalize(targetVel) * speed;
|
||||||
Vector2 newSteering = targetVel - host.Steering;
|
Vector2 newSteering = targetVel - host.Steering;
|
||||||
|
|
||||||
if (newSteering==Vector2.Zero) return Vector2.Zero;
|
if (newSteering == Vector2.Zero) return Vector2.Zero;
|
||||||
|
|
||||||
float steeringSpeed = (newSteering + host.Steering).Length();
|
float steeringSpeed = (newSteering + host.Steering).Length();
|
||||||
if (steeringSpeed > Math.Abs(speed))
|
if (steeringSpeed > Math.Abs(speed))
|
||||||
{
|
{
|
||||||
newSteering = Vector2.Normalize(newSteering)*Math.Abs(speed);
|
newSteering = Vector2.Normalize(newSteering) * Math.Abs(speed);
|
||||||
}
|
}
|
||||||
|
|
||||||
return newSteering;
|
return newSteering;
|
||||||
@@ -151,8 +151,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Structure closestStructure = closestBody.UserData as Structure;
|
if (closestBody.UserData is Structure closestStructure)
|
||||||
if (closestStructure != null)
|
|
||||||
{
|
{
|
||||||
Vector2 obstaclePosition = Submarine.LastPickedPosition;
|
Vector2 obstaclePosition = Submarine.LastPickedPosition;
|
||||||
if (closestStructure.IsHorizontal)
|
if (closestStructure.IsHorizontal)
|
||||||
@@ -166,15 +165,17 @@ namespace Barotrauma
|
|||||||
|
|
||||||
avoidSteering = Vector2.Normalize(Submarine.LastPickedPosition - obstaclePosition);
|
avoidSteering = Vector2.Normalize(Submarine.LastPickedPosition - obstaclePosition);
|
||||||
}
|
}
|
||||||
else if (closestBody.UserData is Item)
|
else if (closestBody.UserData is Item item)
|
||||||
{
|
{
|
||||||
Item item = (Item)closestBody.UserData;
|
|
||||||
avoidSteering = Vector2.Normalize(Submarine.LastPickedPosition - item.SimPosition);
|
avoidSteering = Vector2.Normalize(Submarine.LastPickedPosition - item.SimPosition);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
avoidSteering = Vector2.Normalize(host.SimPosition - Submarine.LastPickedPosition);
|
avoidSteering = Vector2.Normalize(host.SimPosition - Submarine.LastPickedPosition);
|
||||||
}
|
}
|
||||||
|
//failed to normalize (the obstacle to avoid is at the same position as the character?)
|
||||||
|
// -> move to a random direction
|
||||||
|
if (!MathUtils.IsValid(avoidSteering)) avoidSteering = Rand.Vector(1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public virtual void DragCharacter(Character target) { }
|
public virtual void DragCharacter(Character target) { }
|
||||||
|
|
||||||
|
public virtual void UpdateUseItem(bool allowMovement, Vector2 handPos) { }
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,8 +64,16 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Collider.LinearVelocity = (MainLimb.SimPosition - Collider.SimPosition) * 60.0f;
|
Vector2 diff = (MainLimb.SimPosition - Collider.SimPosition);
|
||||||
Collider.SmoothRotate(MainLimb.Rotation);
|
if (diff.LengthSquared() > 10.0f * 10.0f)
|
||||||
|
{
|
||||||
|
Collider.SetTransform(MainLimb.SimPosition, MainLimb.Rotation);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Collider.LinearVelocity = diff * 60.0f;
|
||||||
|
Collider.SmoothRotate(MainLimb.Rotation);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (character.IsDead && deathAnimTimer < deathAnimDuration)
|
if (character.IsDead && deathAnimTimer < deathAnimDuration)
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ namespace Barotrauma
|
|||||||
private float inWaterTimer;
|
private float inWaterTimer;
|
||||||
private bool swimming;
|
private bool swimming;
|
||||||
|
|
||||||
|
private float useItemTimer;
|
||||||
|
|
||||||
protected override float TorsoPosition
|
protected override float TorsoPosition
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@@ -93,13 +95,21 @@ namespace Barotrauma
|
|||||||
levitatingCollider = false;
|
levitatingCollider = false;
|
||||||
Collider.FarseerBody.FixedRotation = false;
|
Collider.FarseerBody.FixedRotation = false;
|
||||||
|
|
||||||
if (Math.Abs(Collider.Rotation-GetLimb(LimbType.Torso).Rotation)>Math.PI*0.6f)
|
if (Math.Abs(Collider.Rotation - GetLimb(LimbType.Torso).Rotation) > Math.PI * 0.6f)
|
||||||
{
|
{
|
||||||
Collider.SetTransform(Collider.SimPosition, MathHelper.WrapAngle(Collider.Rotation + (float)Math.PI));
|
Collider.SetTransform(Collider.SimPosition, MathHelper.WrapAngle(Collider.Rotation + (float)Math.PI));
|
||||||
}
|
}
|
||||||
Collider.SmoothRotate(GetLimb(LimbType.Torso).Rotation);
|
|
||||||
Collider.LinearVelocity = (GetLimb(LimbType.Waist).SimPosition - Collider.SimPosition) * 20.0f;
|
|
||||||
|
|
||||||
|
Vector2 diff = GetLimb(LimbType.Waist).SimPosition - Collider.SimPosition;
|
||||||
|
if (diff.LengthSquared() > 10.0f * 10.0f)
|
||||||
|
{
|
||||||
|
Collider.SetTransform(GetLimb(LimbType.Waist).SimPosition, GetLimb(LimbType.Torso).Rotation);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Collider.LinearVelocity = diff * 20.0f;
|
||||||
|
Collider.SmoothRotate(GetLimb(LimbType.Torso).Rotation);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,6 +190,12 @@ namespace Barotrauma
|
|||||||
case Animation.UsingConstruction:
|
case Animation.UsingConstruction:
|
||||||
default:
|
default:
|
||||||
|
|
||||||
|
if (Anim == Animation.UsingConstruction)
|
||||||
|
{
|
||||||
|
useItemTimer -= deltaTime;
|
||||||
|
if (useItemTimer <= 0.0f) Anim = Animation.None;
|
||||||
|
}
|
||||||
|
|
||||||
if (character.SelectedCharacter != null) DragCharacter(character.SelectedCharacter);
|
if (character.SelectedCharacter != null) DragCharacter(character.SelectedCharacter);
|
||||||
|
|
||||||
//0.5 second delay for switching between swimming and walking
|
//0.5 second delay for switching between swimming and walking
|
||||||
@@ -1067,8 +1083,31 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Limb pullLimb = i == 0 ? leftHand : rightHand;
|
Limb pullLimb = i == 0 ? leftHand : rightHand;
|
||||||
|
|
||||||
|
if (GameMain.Client == null)
|
||||||
|
{
|
||||||
|
//stop dragging if there's something between the pull limb and the target limb
|
||||||
|
Vector2 sourceSimPos = pullLimb.SimPosition;
|
||||||
|
Vector2 targetSimPos = targetLimb.SimPosition;
|
||||||
|
if (character.Submarine != null && character.SelectedCharacter.Submarine == null)
|
||||||
|
{
|
||||||
|
targetSimPos -= character.Submarine.SimPosition;
|
||||||
|
}
|
||||||
|
else if (character.Submarine == null && character.SelectedCharacter.Submarine != null)
|
||||||
|
{
|
||||||
|
sourceSimPos -= character.SelectedCharacter.Submarine.SimPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
var body = Submarine.CheckVisibility(sourceSimPos, targetSimPos, ignoreSubs: true);
|
||||||
|
if (body != null)
|
||||||
|
{
|
||||||
|
character.DeselectCharacter();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (i == 1 && inWater)
|
if (i == 1 && inWater)
|
||||||
{
|
{
|
||||||
targetLimb.pullJoint.Enabled = false;
|
targetLimb.pullJoint.Enabled = false;
|
||||||
@@ -1204,25 +1243,29 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (itemPos == Vector2.Zero || Anim == Animation.Climbing || usingController)
|
if (itemPos == Vector2.Zero || Anim == Animation.Climbing || usingController)
|
||||||
{
|
{
|
||||||
if (character.SelectedItems[1] == item)
|
|
||||||
{
|
|
||||||
transformedHoldPos = leftHand.pullJoint.WorldAnchorA - transformedHandlePos[1];
|
|
||||||
itemAngle = (leftHand.Rotation + (holdAngle - MathHelper.PiOver2) * Dir);
|
|
||||||
}
|
|
||||||
if (character.SelectedItems[0] == item)
|
if (character.SelectedItems[0] == item)
|
||||||
{
|
{
|
||||||
|
if (rightHand.IsSevered) return;
|
||||||
transformedHoldPos = rightHand.pullJoint.WorldAnchorA - transformedHandlePos[0];
|
transformedHoldPos = rightHand.pullJoint.WorldAnchorA - transformedHandlePos[0];
|
||||||
itemAngle = (rightHand.Rotation + (holdAngle - MathHelper.PiOver2) * Dir);
|
itemAngle = (rightHand.Rotation + (holdAngle - MathHelper.PiOver2) * Dir);
|
||||||
}
|
}
|
||||||
|
else if (character.SelectedItems[1] == item)
|
||||||
|
{
|
||||||
|
if (leftHand.IsSevered) return;
|
||||||
|
transformedHoldPos = leftHand.pullJoint.WorldAnchorA - transformedHandlePos[1];
|
||||||
|
itemAngle = (leftHand.Rotation + (holdAngle - MathHelper.PiOver2) * Dir);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (character.SelectedItems[0] == item)
|
if (character.SelectedItems[0] == item)
|
||||||
{
|
{
|
||||||
|
if (rightHand.IsSevered) return;
|
||||||
rightHand.Disabled = true;
|
rightHand.Disabled = true;
|
||||||
}
|
}
|
||||||
if (character.SelectedItems[1] == item)
|
if (character.SelectedItems[1] == item)
|
||||||
{
|
{
|
||||||
|
if (leftHand.IsSevered) return;
|
||||||
leftHand.Disabled = true;
|
leftHand.Disabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1235,6 +1278,24 @@ namespace Barotrauma
|
|||||||
Vector2 currItemPos = (character.SelectedItems[0] == item) ?
|
Vector2 currItemPos = (character.SelectedItems[0] == item) ?
|
||||||
rightHand.pullJoint.WorldAnchorA - transformedHandlePos[0] :
|
rightHand.pullJoint.WorldAnchorA - transformedHandlePos[0] :
|
||||||
leftHand.pullJoint.WorldAnchorA - transformedHandlePos[1];
|
leftHand.pullJoint.WorldAnchorA - transformedHandlePos[1];
|
||||||
|
|
||||||
|
if (!MathUtils.IsValid(currItemPos))
|
||||||
|
{
|
||||||
|
string errorMsg = "Attempted to move the item \"" + item + "\" to an invalid position in HumanidAnimController.HoldItem: " +
|
||||||
|
currItemPos + ", rightHandPos: " + rightHand.pullJoint.WorldAnchorA + ", leftHandPos: " + leftHand.pullJoint.WorldAnchorA +
|
||||||
|
", handlePos[0]: " + handlePos[0] + ", handlePos[1]: " + handlePos[1] +
|
||||||
|
", transformedHandlePos[0]: " + transformedHandlePos[0] + ", transformedHandlePos[1]:" + transformedHandlePos[1] +
|
||||||
|
", item pos: " + item.SimPosition + ", itemAngle: " + itemAngle +
|
||||||
|
", collider pos: " + character.SimPosition;
|
||||||
|
DebugConsole.Log(errorMsg);
|
||||||
|
GameAnalyticsManager.AddErrorEventOnce(
|
||||||
|
"HumanoidAnimController.HoldItem:InvalidPos:" + character.Name + item.Name,
|
||||||
|
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||||
|
errorMsg);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
item.SetTransform(currItemPos, itemAngle);
|
item.SetTransform(currItemPos, itemAngle);
|
||||||
|
|
||||||
//item.SetTransform(MathUtils.SmoothStep(item.body.SimPosition, transformedHoldPos + bodyVelocity, 0.5f), itemAngle);
|
//item.SetTransform(MathUtils.SmoothStep(item.body.SimPosition, transformedHoldPos + bodyVelocity, 0.5f), itemAngle);
|
||||||
@@ -1277,6 +1338,33 @@ namespace Barotrauma
|
|||||||
hand.body.SmoothRotate((ang2 + handAngle * Dir), 100.0f * force);
|
hand.body.SmoothRotate((ang2 + handAngle * Dir), 100.0f * force);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void UpdateUseItem(bool allowMovement, Vector2 handPos)
|
||||||
|
{
|
||||||
|
var leftHand = GetLimb(LimbType.LeftHand);
|
||||||
|
var rightHand = GetLimb(LimbType.RightHand);
|
||||||
|
|
||||||
|
useItemTimer = 0.5f;
|
||||||
|
Anim = Animation.UsingConstruction;
|
||||||
|
|
||||||
|
if (!allowMovement)
|
||||||
|
{
|
||||||
|
TargetMovement = Vector2.Zero;
|
||||||
|
TargetDir = handPos.X > character.SimPosition.X ? Direction.Right : Direction.Left;
|
||||||
|
if (Vector2.Distance(character.SimPosition, handPos) > 1.0f)
|
||||||
|
{
|
||||||
|
TargetMovement = Vector2.Normalize(handPos - character.SimPosition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
leftHand.Disabled = true;
|
||||||
|
leftHand.pullJoint.Enabled = true;
|
||||||
|
leftHand.pullJoint.WorldAnchorB = handPos;
|
||||||
|
|
||||||
|
rightHand.Disabled = true;
|
||||||
|
rightHand.pullJoint.Enabled = true;
|
||||||
|
rightHand.pullJoint.WorldAnchorB = handPos;
|
||||||
|
}
|
||||||
|
|
||||||
public override void Flip()
|
public override void Flip()
|
||||||
{
|
{
|
||||||
base.Flip();
|
base.Flip();
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using FarseerPhysics;
|
|||||||
using FarseerPhysics.Dynamics;
|
using FarseerPhysics.Dynamics;
|
||||||
using FarseerPhysics.Dynamics.Contacts;
|
using FarseerPhysics.Dynamics.Contacts;
|
||||||
using FarseerPhysics.Dynamics.Joints;
|
using FarseerPhysics.Dynamics.Joints;
|
||||||
|
using FarseerPhysics.Factories;
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@@ -25,6 +26,11 @@ namespace Barotrauma
|
|||||||
if (limbs == null)
|
if (limbs == null)
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError("Attempted to access a potentially removed ragdoll. Character: " + character.Name + ", id: " + character.ID + ", removed: " + character.Removed + ", ragdoll removed: " + !list.Contains(this));
|
DebugConsole.ThrowError("Attempted to access a potentially removed ragdoll. Character: " + character.Name + ", id: " + character.ID + ", removed: " + character.Removed + ", ragdoll removed: " + !list.Contains(this));
|
||||||
|
GameAnalyticsManager.AddErrorEventOnce(
|
||||||
|
"Ragdoll.Limbs:AccessRemoved",
|
||||||
|
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||||
|
"Attempted to access a potentially removed ragdoll. Character: " + character.Name + ", id: " + character.ID + ", removed: " + character.Removed + ", ragdoll removed: " + !list.Contains(this) + "\n" + Environment.StackTrace);
|
||||||
|
|
||||||
return new Limb[0];
|
return new Limb[0];
|
||||||
}
|
}
|
||||||
return limbs;
|
return limbs;
|
||||||
@@ -42,6 +48,7 @@ namespace Barotrauma
|
|||||||
frozen = value;
|
frozen = value;
|
||||||
|
|
||||||
Collider.PhysEnabled = !frozen;
|
Collider.PhysEnabled = !frozen;
|
||||||
|
if (frozen && MainLimb != null) MainLimb.pullJoint.WorldAnchorB = MainLimb.SimPosition;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,6 +95,10 @@ namespace Barotrauma
|
|||||||
protected List<PhysicsBody> collider;
|
protected List<PhysicsBody> collider;
|
||||||
protected int colliderIndex = 0;
|
protected int colliderIndex = 0;
|
||||||
|
|
||||||
|
private Category prevCollisionCategory = Category.None;
|
||||||
|
|
||||||
|
private Body outsideCollisionBlocker;
|
||||||
|
|
||||||
public PhysicsBody Collider
|
public PhysicsBody Collider
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@@ -269,11 +280,7 @@ namespace Barotrauma
|
|||||||
get { return ignorePlatforms; }
|
get { return ignorePlatforms; }
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (ignorePlatforms == value) return;
|
|
||||||
ignorePlatforms = value;
|
ignorePlatforms = value;
|
||||||
|
|
||||||
UpdateCollisionCategories();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -352,21 +359,29 @@ namespace Barotrauma
|
|||||||
if (collider[0] == null)
|
if (collider[0] == null)
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError("No collider configured for \"" + character.Name + "\"!");
|
DebugConsole.ThrowError("No collider configured for \"" + character.Name + "\"!");
|
||||||
collider[0] = new PhysicsBody(0.0f, 0.0f, 0.5f, 5.0f);
|
collider[0] = new PhysicsBody(0.0f, 0.0f, 0.5f, 5.0f)
|
||||||
collider[0].UserData = character;
|
{
|
||||||
collider[0].BodyType = BodyType.Dynamic;
|
UserData = character,
|
||||||
collider[0].CollisionCategories = Physics.CollisionCharacter;
|
BodyType = BodyType.Dynamic,
|
||||||
|
CollisionCategories = Physics.CollisionCharacter
|
||||||
|
};
|
||||||
collider[0].FarseerBody.AngularDamping = 5.0f;
|
collider[0].FarseerBody.AngularDamping = 5.0f;
|
||||||
collider[0].FarseerBody.FixedRotation = true;
|
collider[0].FarseerBody.FixedRotation = true;
|
||||||
collider[0].FarseerBody.OnCollision += OnLimbCollision;
|
collider[0].FarseerBody.OnCollision += OnLimbCollision;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
outsideCollisionBlocker = BodyFactory.CreateEdge(GameMain.World, -Vector2.UnitX * 2.0f, Vector2.UnitX * 2.0f, "blocker");
|
||||||
|
outsideCollisionBlocker.BodyType = BodyType.Static;
|
||||||
|
outsideCollisionBlocker.CollisionCategories = Physics.CollisionWall;
|
||||||
|
outsideCollisionBlocker.CollidesWith = Physics.CollisionCharacter;
|
||||||
|
outsideCollisionBlocker.Enabled = false;
|
||||||
|
|
||||||
UpdateCollisionCategories();
|
UpdateCollisionCategories();
|
||||||
|
|
||||||
foreach (var joint in LimbJoints)
|
foreach (var joint in LimbJoints)
|
||||||
{
|
{
|
||||||
joint.BodyB.SetTransform(
|
joint.LimbB?.body?.SetTransform(
|
||||||
joint.BodyA.Position + (joint.LocalAnchorA - joint.LocalAnchorB)*0.1f,
|
joint.BodyA.Position + (joint.LocalAnchorA - joint.LocalAnchorB) * 0.1f,
|
||||||
(joint.LowerLimit + joint.UpperLimit) / 2.0f);
|
(joint.LowerLimit + joint.UpperLimit) / 2.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -391,7 +406,7 @@ namespace Barotrauma
|
|||||||
Limb torso = GetLimb(LimbType.Torso);
|
Limb torso = GetLimb(LimbType.Torso);
|
||||||
Limb head = GetLimb(LimbType.Head);
|
Limb head = GetLimb(LimbType.Head);
|
||||||
|
|
||||||
MainLimb = torso == null ? head : torso;
|
MainLimb = torso ?? head;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddJoint(XElement subElement, float scale = 1.0f)
|
public void AddJoint(XElement subElement, float scale = 1.0f)
|
||||||
@@ -489,6 +504,9 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (f2.Body.UserData is Submarine && character.Submarine == (Submarine)f2.Body.UserData) return false;
|
if (f2.Body.UserData is Submarine && character.Submarine == (Submarine)f2.Body.UserData) return false;
|
||||||
|
|
||||||
|
//only collide with the ragdoll's own blocker
|
||||||
|
if (f2.Body.UserData as string == "blocker" && f2.Body != outsideCollisionBlocker) return false;
|
||||||
|
|
||||||
//always collides with bodies other than structures
|
//always collides with bodies other than structures
|
||||||
if (structure == null)
|
if (structure == null)
|
||||||
{
|
{
|
||||||
@@ -739,7 +757,15 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public void FindHull(Vector2? worldPosition = null, bool setSubmarine = true)
|
public void FindHull(Vector2? worldPosition = null, bool setSubmarine = true)
|
||||||
{
|
{
|
||||||
Vector2 findPos = worldPosition==null ? this.WorldPosition : (Vector2)worldPosition;
|
Vector2 findPos = worldPosition == null ? this.WorldPosition : (Vector2)worldPosition;
|
||||||
|
if (!MathUtils.IsValid(findPos))
|
||||||
|
{
|
||||||
|
GameAnalyticsManager.AddErrorEventOnce(
|
||||||
|
"Ragdoll.FindHull:InvalidPosition",
|
||||||
|
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||||
|
"Attempted to find a hull at an invalid position (" + findPos + ")\n" + Environment.StackTrace);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Hull newHull = Hull.FindHull(findPos, currentHull);
|
Hull newHull = Hull.FindHull(findPos, currentHull);
|
||||||
|
|
||||||
@@ -754,10 +780,13 @@ namespace Barotrauma
|
|||||||
//this is preferable to the cost of using continuous collision detection for the character collider
|
//this is preferable to the cost of using continuous collision detection for the character collider
|
||||||
if (newHull != null)
|
if (newHull != null)
|
||||||
{
|
{
|
||||||
|
Vector2 hullDiff = WorldPosition - newHull.WorldPosition;
|
||||||
|
Vector2 moveDir = hullDiff.LengthSquared() < 0.001f ? Vector2.UnitY : Vector2.Normalize(hullDiff);
|
||||||
|
|
||||||
//find a position 32 units away from the hull
|
//find a position 32 units away from the hull
|
||||||
Vector2? intersection = MathUtils.GetLineRectangleIntersection(
|
Vector2? intersection = MathUtils.GetLineRectangleIntersection(
|
||||||
newHull.WorldPosition,
|
newHull.WorldPosition,
|
||||||
newHull.WorldPosition + Vector2.Normalize(WorldPosition - newHull.WorldPosition) * Math.Max(newHull.Rect.Width, newHull.Rect.Height),
|
newHull.WorldPosition + moveDir * Math.Max(newHull.Rect.Width, newHull.Rect.Height),
|
||||||
new Rectangle(newHull.WorldRect.X - 32, newHull.WorldRect.Y + 32, newHull.WorldRect.Width + 64, newHull.Rect.Height + 64));
|
new Rectangle(newHull.WorldRect.X - 32, newHull.WorldRect.Y + 32, newHull.WorldRect.Width + 64, newHull.Rect.Height + 64));
|
||||||
|
|
||||||
if (intersection != null)
|
if (intersection != null)
|
||||||
@@ -774,15 +803,7 @@ namespace Barotrauma
|
|||||||
//in -> out
|
//in -> out
|
||||||
if (newHull == null && currentHull.Submarine != null)
|
if (newHull == null && currentHull.Submarine != null)
|
||||||
{
|
{
|
||||||
for (int i = -1; i < 2; i += 2)
|
|
||||||
{
|
|
||||||
//don't teleport outside the sub if right next to a hull
|
|
||||||
if (Hull.FindHull(findPos + new Vector2(Submarine.GridSize.X * 4.0f * i, 0.0f), currentHull) != null) return;
|
|
||||||
if (Hull.FindHull(findPos + new Vector2(0.0f, Submarine.GridSize.Y * 4.0f * i), currentHull) != null) return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Gap.FindAdjacent(currentHull.ConnectedGaps, findPos, 150.0f) != null) return;
|
if (Gap.FindAdjacent(currentHull.ConnectedGaps, findPos, 150.0f) != null) return;
|
||||||
|
|
||||||
Teleport(ConvertUnits.ToSimUnits(currentHull.Submarine.Position), currentHull.Submarine.Velocity);
|
Teleport(ConvertUnits.ToSimUnits(currentHull.Submarine.Position), currentHull.Submarine.Velocity);
|
||||||
}
|
}
|
||||||
//out -> in
|
//out -> in
|
||||||
@@ -799,10 +820,49 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
CurrentHull = newHull;
|
CurrentHull = newHull;
|
||||||
|
character.Submarine = currentHull?.Submarine;
|
||||||
|
}
|
||||||
|
|
||||||
character.Submarine = currentHull == null ? null : currentHull.Submarine;
|
private void PreventOutsideCollision()
|
||||||
|
{
|
||||||
|
if (currentHull?.Submarine == null)
|
||||||
|
{
|
||||||
|
outsideCollisionBlocker.Enabled = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
UpdateCollisionCategories();
|
var connectedGaps = currentHull.ConnectedGaps.Where(g => !g.IsRoomToRoom);
|
||||||
|
foreach (Gap gap in connectedGaps)
|
||||||
|
{
|
||||||
|
if (gap.IsHorizontal)
|
||||||
|
{
|
||||||
|
if (character.Position.Y > gap.Rect.Y || character.Position.Y < gap.Rect.Y - gap.Rect.Height) continue;
|
||||||
|
if (Math.Sign(gap.Rect.Center.X - currentHull.Rect.Center.X) !=
|
||||||
|
Math.Sign(character.Position.X - currentHull.Rect.Center.X))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (character.Position.X < gap.Rect.X || character.Position.X > gap.Rect.Right) continue;
|
||||||
|
if (Math.Sign((gap.Rect.Y - gap.Rect.Height / 2) - (currentHull.Rect.Center.X - currentHull.Rect.Height / 2)) !=
|
||||||
|
Math.Sign(character.Position.X - (currentHull.Rect.Center.X - currentHull.Rect.Height / 2)))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!gap.GetOutsideCollider(out Vector2? outsideColliderPos, out Vector2? outsideColliderNormal)) continue;
|
||||||
|
|
||||||
|
outsideCollisionBlocker.SetTransform(
|
||||||
|
outsideColliderPos.Value - currentHull.Submarine.SimPosition,
|
||||||
|
MathUtils.VectorToAngle(outsideColliderNormal.Value) - MathHelper.PiOver2);
|
||||||
|
outsideCollisionBlocker.Enabled = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
outsideCollisionBlocker.Enabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Teleport(Vector2 moveAmount, Vector2 velocityChange)
|
public void Teleport(Vector2 moveAmount, Vector2 velocityChange)
|
||||||
@@ -843,6 +903,9 @@ namespace Barotrauma
|
|||||||
wall | Physics.CollisionProjectile | Physics.CollisionStairs
|
wall | Physics.CollisionProjectile | Physics.CollisionStairs
|
||||||
: wall | Physics.CollisionProjectile | Physics.CollisionPlatform | Physics.CollisionStairs;
|
: wall | Physics.CollisionProjectile | Physics.CollisionPlatform | Physics.CollisionStairs;
|
||||||
|
|
||||||
|
if (collisionCategory == prevCollisionCategory) return;
|
||||||
|
prevCollisionCategory = collisionCategory;
|
||||||
|
|
||||||
Collider.CollidesWith = collisionCategory;
|
Collider.CollidesWith = collisionCategory;
|
||||||
|
|
||||||
foreach (Limb limb in Limbs)
|
foreach (Limb limb in Limbs)
|
||||||
@@ -868,10 +931,12 @@ namespace Barotrauma
|
|||||||
|
|
||||||
UpdateNetPlayerPosition(deltaTime);
|
UpdateNetPlayerPosition(deltaTime);
|
||||||
CheckDistFromCollider();
|
CheckDistFromCollider();
|
||||||
|
UpdateCollisionCategories();
|
||||||
|
|
||||||
Vector2 flowForce = Vector2.Zero;
|
Vector2 flowForce = Vector2.Zero;
|
||||||
|
|
||||||
FindHull();
|
FindHull();
|
||||||
|
PreventOutsideCollision();
|
||||||
|
|
||||||
splashSoundTimer -= deltaTime;
|
splashSoundTimer -= deltaTime;
|
||||||
|
|
||||||
@@ -1090,20 +1155,17 @@ namespace Barotrauma
|
|||||||
float tfloorY = rayStart.Y + (rayEnd.Y - rayStart.Y) * closestFraction;
|
float tfloorY = rayStart.Y + (rayEnd.Y - rayStart.Y) * closestFraction;
|
||||||
float targetY = tfloorY + Collider.height * 0.5f + Collider.radius + colliderHeightFromFloor;
|
float targetY = tfloorY + Collider.height * 0.5f + Collider.radius + colliderHeightFromFloor;
|
||||||
|
|
||||||
if (Math.Abs(Collider.SimPosition.Y - targetY) > 0.01f && Collider.SimPosition.Y<targetY && !forceImmediate)
|
if (Math.Abs(Collider.SimPosition.Y - targetY) > 0.01f)
|
||||||
{
|
{
|
||||||
Vector2 newSpeed = Collider.LinearVelocity;
|
if (forceImmediate)
|
||||||
newSpeed.Y = (targetY - Collider.SimPosition.Y)*5.0f;
|
{
|
||||||
Collider.LinearVelocity = newSpeed;
|
Collider.LinearVelocity = new Vector2(Collider.LinearVelocity.X, 0);
|
||||||
}
|
Collider.SetTransform(new Vector2(Collider.SimPosition.X, targetY), Collider.Rotation);
|
||||||
else
|
}
|
||||||
{
|
else
|
||||||
Vector2 newSpeed = Collider.LinearVelocity;
|
{
|
||||||
newSpeed.Y = 0.0f;
|
Collider.LinearVelocity = new Vector2(Collider.LinearVelocity.X, (targetY - Collider.SimPosition.Y) * 5.0f);
|
||||||
Collider.LinearVelocity = newSpeed;
|
}
|
||||||
Vector2 newPos = Collider.SimPosition;
|
|
||||||
newPos.Y = targetY;
|
|
||||||
Collider.SetTransform(newPos, Collider.Rotation);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1165,6 +1227,16 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public void SetPosition(Vector2 simPosition, bool lerp = false)
|
public void SetPosition(Vector2 simPosition, bool lerp = false)
|
||||||
{
|
{
|
||||||
|
if (!MathUtils.IsValid(simPosition))
|
||||||
|
{
|
||||||
|
DebugConsole.ThrowError("Attempted to move a ragdoll (" + character.Name + ") to an invalid position (" + simPosition + "). " + Environment.StackTrace);
|
||||||
|
GameAnalyticsManager.AddErrorEventOnce(
|
||||||
|
"Ragdoll.SetPosition:InvalidPosition",
|
||||||
|
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||||
|
"Attempted to move a ragdoll (" + character.Name + ") to an invalid position (" + simPosition + "). " + Environment.StackTrace);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Vector2 limbMoveAmount = simPosition - MainLimb.SimPosition;
|
Vector2 limbMoveAmount = simPosition - MainLimb.SimPosition;
|
||||||
|
|
||||||
Collider.SetTransform(simPosition, Collider.Rotation);
|
Collider.SetTransform(simPosition, Collider.Rotation);
|
||||||
@@ -1245,9 +1317,9 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
//set the position of the ragdoll to make sure limbs don't get stuck inside walls when re-enabling collisions
|
//set the position of the ragdoll to make sure limbs don't get stuck inside walls when re-enabling collisions
|
||||||
SetPosition(Collider.SimPosition, true);
|
SetPosition(Collider.SimPosition, true);
|
||||||
|
|
||||||
UpdateCollisionCategories();
|
|
||||||
collisionsDisabled = false;
|
collisionsDisabled = false;
|
||||||
|
//force collision categories to be updated
|
||||||
|
prevCollisionCategory = Category.None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1312,8 +1384,24 @@ namespace Barotrauma
|
|||||||
character.AnimController.Anim = AnimController.Animation.None;
|
character.AnimController.Anim = AnimController.Animation.None;
|
||||||
}
|
}
|
||||||
|
|
||||||
Collider.LinearVelocity = Vector2.Zero;
|
Vector2 newVelocity = Vector2.Zero;
|
||||||
Collider.CorrectPosition(character.MemState, deltaTime, out overrideTargetMovement);
|
Vector2 newPosition = Collider.SimPosition;
|
||||||
|
Collider.CorrectPosition(character.MemState, deltaTime, out newVelocity, out newPosition);
|
||||||
|
|
||||||
|
newVelocity = newVelocity.ClampLength(100.0f);
|
||||||
|
if (!MathUtils.IsValid(newVelocity)) newVelocity = Vector2.Zero;
|
||||||
|
overrideTargetMovement = newVelocity;
|
||||||
|
Collider.LinearVelocity = newVelocity;
|
||||||
|
|
||||||
|
float distSqrd = Vector2.DistanceSquared(newPosition, Collider.SimPosition);
|
||||||
|
if (distSqrd > 10.0f)
|
||||||
|
{
|
||||||
|
SetPosition(newPosition);
|
||||||
|
}
|
||||||
|
else if (distSqrd > 0.01f)
|
||||||
|
{
|
||||||
|
Collider.SetTransform(newPosition, Collider.Rotation);
|
||||||
|
}
|
||||||
|
|
||||||
//unconscious/dead characters can't correct their position using AnimController movement
|
//unconscious/dead characters can't correct their position using AnimController movement
|
||||||
// -> we need to correct it manually
|
// -> we need to correct it manually
|
||||||
@@ -1431,10 +1519,18 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Collider.SetTransform(Collider.SimPosition + positionError, Collider.Rotation + rotationError);
|
float errorMagnitude = positionError.Length();
|
||||||
foreach (Limb limb in Limbs)
|
if (errorMagnitude > 0.01f)
|
||||||
{
|
{
|
||||||
limb.body.SetTransform(limb.body.SimPosition + positionError, limb.body.Rotation);
|
Collider.SetTransform(Collider.SimPosition + positionError, Collider.Rotation + rotationError);
|
||||||
|
if (errorMagnitude > 0.5f)
|
||||||
|
{
|
||||||
|
character.MemLocalState.Clear();
|
||||||
|
foreach (Limb limb in Limbs)
|
||||||
|
{
|
||||||
|
limb.body.SetTransform(limb.body.SimPosition + positionError, limb.body.Rotation);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1445,22 +1541,17 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private Vector2 GetFlowForce()
|
private Vector2 GetFlowForce()
|
||||||
{
|
{
|
||||||
Vector2 limbPos = ConvertUnits.ToDisplayUnits(Limbs[0].SimPosition);
|
Vector2 limbPos = Limbs[0].Position;
|
||||||
|
|
||||||
Vector2 force = Vector2.Zero;
|
Vector2 force = Vector2.Zero;
|
||||||
foreach (MapEntity e in MapEntity.mapEntityList)
|
foreach (Gap gap in Gap.GapList)
|
||||||
{
|
{
|
||||||
Gap gap = e as Gap;
|
if (gap.Open <= 0.0f || gap.FlowTargetHull != currentHull || gap.LerpedFlowForce.LengthSquared() < 0.01f) continue;
|
||||||
if (gap == null || gap.FlowTargetHull != currentHull || gap.LerpedFlowForce == Vector2.Zero) continue;
|
|
||||||
|
|
||||||
Vector2 gapPos = gap.SimPosition;
|
Vector2 gapPos = gap.SimPosition;
|
||||||
|
|
||||||
float dist = Vector2.Distance(limbPos, gapPos);
|
float dist = Vector2.Distance(limbPos, gapPos);
|
||||||
|
|
||||||
force += Vector2.Normalize(gap.LerpedFlowForce) * (Math.Max(gap.LerpedFlowForce.Length() - dist, 0.0f) / 500.0f);
|
force += Vector2.Normalize(gap.LerpedFlowForce) * (Math.Max(gap.LerpedFlowForce.Length() - dist, 0.0f) / 500.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (force.Length() > 20.0f) return force;
|
|
||||||
return force;
|
return force;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1526,6 +1617,12 @@ namespace Barotrauma
|
|||||||
b.Remove();
|
b.Remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (outsideCollisionBlocker != null)
|
||||||
|
{
|
||||||
|
GameMain.World.RemoveBody(outsideCollisionBlocker);
|
||||||
|
outsideCollisionBlocker = null;
|
||||||
|
}
|
||||||
|
|
||||||
if (LimbJoints != null)
|
if (LimbJoints != null)
|
||||||
{
|
{
|
||||||
foreach (RevoluteJoint joint in LimbJoints)
|
foreach (RevoluteJoint joint in LimbJoints)
|
||||||
|
|||||||
@@ -144,6 +144,10 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
if (GameMain.Server != null && !GameMain.Server.AllowDisguises) return Name;
|
||||||
|
#if CLIENT
|
||||||
|
if (GameMain.Client != null && !GameMain.Client.AllowDisguises) return Name;
|
||||||
|
#endif
|
||||||
return info != null && !string.IsNullOrWhiteSpace(info.Name) ? info.Name + (info.DisplayName != info.Name ? " (as " + info.DisplayName + ")" : "") : SpeciesName;
|
return info != null && !string.IsNullOrWhiteSpace(info.Name) ? info.Name + (info.DisplayName != info.Name ? " (as " + info.DisplayName + ")" : "") : SpeciesName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1611,12 +1615,20 @@ namespace Barotrauma
|
|||||||
//Health effects
|
//Health effects
|
||||||
if (needsAir) UpdateOxygen(deltaTime);
|
if (needsAir) UpdateOxygen(deltaTime);
|
||||||
|
|
||||||
Health -= bleeding * deltaTime;
|
if (DoesBleed)
|
||||||
Bleeding -= BleedingDecreaseSpeed * deltaTime;
|
{
|
||||||
|
Health -= bleeding * deltaTime;
|
||||||
|
Bleeding -= BleedingDecreaseSpeed * deltaTime;
|
||||||
|
}
|
||||||
|
|
||||||
if (health <= minHealth) Kill(CauseOfDeath.Bloodloss);
|
if (health <= minHealth) Kill(CauseOfDeath.Bloodloss);
|
||||||
|
|
||||||
if (!IsDead) LockHands = false;
|
UpdateSightRange();
|
||||||
|
if (aiTarget != null) aiTarget.SoundRange = 0.0f;
|
||||||
|
|
||||||
|
lowPassMultiplier = MathHelper.Lerp(lowPassMultiplier, 1.0f, 0.1f);
|
||||||
|
|
||||||
|
if (health <= minHealth) Kill(CauseOfDeath.Bloodloss);
|
||||||
|
|
||||||
//ragdoll button
|
//ragdoll button
|
||||||
if (IsRagdolled)
|
if (IsRagdolled)
|
||||||
@@ -1643,21 +1655,7 @@ namespace Barotrauma
|
|||||||
selectedConstruction = null;
|
selectedConstruction = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateSightRange();
|
|
||||||
if (aiTarget != null) aiTarget.SoundRange = 0.0f;
|
|
||||||
|
|
||||||
lowPassMultiplier = MathHelper.Lerp(lowPassMultiplier, 1.0f, 0.1f);
|
|
||||||
|
|
||||||
if (DoesBleed)
|
|
||||||
{
|
|
||||||
Health -= bleeding * deltaTime;
|
|
||||||
Bleeding -= BleedingDecreaseSpeed * deltaTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (health <= minHealth) Kill(CauseOfDeath.Bloodloss);
|
|
||||||
|
|
||||||
if (!IsDead) LockHands = false;
|
if (!IsDead) LockHands = false;
|
||||||
//CPR stuff is handled in the UpdateCPR function in HumanoidAnimController
|
|
||||||
}
|
}
|
||||||
|
|
||||||
partial void UpdateControlled(float deltaTime, Camera cam);
|
partial void UpdateControlled(float deltaTime, Camera cam);
|
||||||
@@ -1960,7 +1958,7 @@ namespace Barotrauma
|
|||||||
characterType = "Enemy";
|
characterType = "Enemy";
|
||||||
else if (AIController is HumanAIController)
|
else if (AIController is HumanAIController)
|
||||||
characterType = "AICrew";
|
characterType = "AICrew";
|
||||||
GameAnalyticsSDK.Net.GameAnalytics.AddDesignEvent("Kill:" + characterType + ":" + SpeciesName + ":" + causeOfDeath);
|
GameAnalyticsManager.AddDesignEvent("Kill:" + characterType + ":" + SpeciesName + ":" + causeOfDeath);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (OnDeath != null) OnDeath(this, causeOfDeath);
|
if (OnDeath != null) OnDeath(this, causeOfDeath);
|
||||||
@@ -1997,7 +1995,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
partial void KillProjSpecific();
|
partial void KillProjSpecific();
|
||||||
|
|
||||||
public void Revive(bool isNetworkMessage)
|
public void Revive()
|
||||||
{
|
{
|
||||||
if (Removed)
|
if (Removed)
|
||||||
{
|
{
|
||||||
@@ -2024,6 +2022,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
foreach (Limb limb in AnimController.Limbs)
|
foreach (Limb limb in AnimController.Limbs)
|
||||||
{
|
{
|
||||||
|
limb.body.Enabled = true;
|
||||||
limb.IsSevered = false;
|
limb.IsSevered = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2044,6 +2043,9 @@ namespace Barotrauma
|
|||||||
|
|
||||||
base.Remove();
|
base.Remove();
|
||||||
|
|
||||||
|
if (selectedItems[0] != null) selectedItems[0].Drop(this);
|
||||||
|
if (selectedItems[1] != null) selectedItems[1].Drop(this);
|
||||||
|
|
||||||
if (info != null) info.Remove();
|
if (info != null) info.Remove();
|
||||||
|
|
||||||
CharacterList.Remove(this);
|
CharacterList.Remove(this);
|
||||||
@@ -2054,9 +2056,6 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (AnimController != null) AnimController.Remove();
|
if (AnimController != null) AnimController.Remove();
|
||||||
|
|
||||||
if (selectedItems[0] != null) selectedItems[0].Drop(this);
|
|
||||||
if (selectedItems[1] != null) selectedItems[1].Drop(this);
|
|
||||||
|
|
||||||
foreach (Character c in CharacterList)
|
foreach (Character c in CharacterList)
|
||||||
{
|
{
|
||||||
if (c.focusedCharacter == this) c.focusedCharacter = null;
|
if (c.focusedCharacter == this) c.focusedCharacter = null;
|
||||||
|
|||||||
@@ -17,11 +17,16 @@ namespace Barotrauma
|
|||||||
get
|
get
|
||||||
{
|
{
|
||||||
string disguiseName = "?";
|
string disguiseName = "?";
|
||||||
if (Character == null || !Character.HideFace)
|
if (Character == null || !Character.HideFace || (GameMain.Server != null && !GameMain.Server.AllowDisguises))
|
||||||
{
|
{
|
||||||
return Name;
|
return Name;
|
||||||
}
|
}
|
||||||
|
#if CLIENT
|
||||||
|
if (GameMain.Client != null && !GameMain.Client.AllowDisguises)
|
||||||
|
{
|
||||||
|
return Name;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
if (Character.Inventory != null)
|
if (Character.Inventory != null)
|
||||||
{
|
{
|
||||||
int cardSlotIndex = Character.Inventory.FindLimbSlot(InvSlotType.Card);
|
int cardSlotIndex = Character.Inventory.FindLimbSlot(InvSlotType.Card);
|
||||||
|
|||||||
@@ -84,6 +84,11 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public bool isSynced = false;
|
public bool isSynced = false;
|
||||||
|
|
||||||
|
public string OwnerClientIP;
|
||||||
|
public string OwnerClientName;
|
||||||
|
public bool ClientDisconnected;
|
||||||
|
public float KillDisconnectedTimer;
|
||||||
|
|
||||||
public List<CharacterStateInfo> MemState
|
public List<CharacterStateInfo> MemState
|
||||||
{
|
{
|
||||||
get { return memState; }
|
get { return memState; }
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Collections.Generic;
|
using Barotrauma.Items.Components;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
|
|
||||||
@@ -136,6 +137,11 @@ namespace Barotrauma
|
|||||||
item.Description = spawnPoint.IdCardDesc;
|
item.Description = spawnPoint.IdCardDesc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach (WifiComponent wifiComponent in item.GetComponents<WifiComponent>())
|
||||||
|
{
|
||||||
|
wifiComponent.TeamID = character.TeamID;
|
||||||
|
}
|
||||||
|
|
||||||
if (parentItem != null) parentItem.Combine(item);
|
if (parentItem != null) parentItem.Combine(item);
|
||||||
|
|
||||||
foreach (XElement childItemElement in itemElement.Elements())
|
foreach (XElement childItemElement in itemElement.Elements())
|
||||||
|
|||||||
@@ -85,6 +85,7 @@ namespace Barotrauma
|
|||||||
set
|
set
|
||||||
{
|
{
|
||||||
isSevered = value;
|
isSevered = value;
|
||||||
|
if (!isSevered) severedFadeOutTimer = 0.0f;
|
||||||
#if CLIENT
|
#if CLIENT
|
||||||
if (isSevered) damage = 100.0f;
|
if (isSevered) damage = 100.0f;
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -190,6 +190,17 @@ namespace Barotrauma
|
|||||||
NewMessage("- Traitor " + t.Character.Name + "'s target is " + t.TargetCharacter.Name + ".", Color.Cyan);
|
NewMessage("- Traitor " + t.Character.Name + "'s target is " + t.TargetCharacter.Name + ".", Color.Cyan);
|
||||||
}
|
}
|
||||||
NewMessage("The code words are: " + traitorManager.codeWords + ", response: " + traitorManager.codeResponse + ".", Color.Cyan);
|
NewMessage("The code words are: " + traitorManager.codeWords + ", response: " + traitorManager.codeResponse + ".", Color.Cyan);
|
||||||
|
},
|
||||||
|
null,
|
||||||
|
(Client client, Vector2 cursorPos, string[] args) =>
|
||||||
|
{
|
||||||
|
TraitorManager traitorManager = GameMain.Server.TraitorManager;
|
||||||
|
if (traitorManager == null) return;
|
||||||
|
foreach (Traitor t in traitorManager.TraitorList)
|
||||||
|
{
|
||||||
|
GameMain.Server.SendConsoleMessage("- Traitor " + t.Character.Name + "'s target is " + t.TargetCharacter.Name + ".", client);
|
||||||
|
}
|
||||||
|
GameMain.Server.SendConsoleMessage("The code words are: " + traitorManager.codeWords + ", response: " + traitorManager.codeResponse + ".", client);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
commands.Add(new Command("itemlist", "itemlist: List all the item prefabs available for spawning.", (string[] args) =>
|
commands.Add(new Command("itemlist", "itemlist: List all the item prefabs available for spawning.", (string[] args) =>
|
||||||
@@ -249,7 +260,7 @@ namespace Barotrauma
|
|||||||
};
|
};
|
||||||
}));
|
}));
|
||||||
|
|
||||||
commands.Add(new Command("spawnitem", "spawnitem [itemname] [cursor/inventory/random/[name]]: Spawn an item at the position of the cursor, in the inventory of the controlled character, in the inventory of the client with the given name, or at a random spawnpoint if the last parameter is omitted or \"random\".",
|
commands.Add(new Command("spawnitem", "spawnitem [itemname] [cursor/inventory/cargo/random/[name]]: Spawn an item at the position of the cursor, in the inventory of the controlled character, in the inventory of the client with the given name, or at a random spawnpoint if the last parameter is omitted or \"random\".",
|
||||||
(string[] args) =>
|
(string[] args) =>
|
||||||
{
|
{
|
||||||
SpawnItem(args, GameMain.GameScreen.Cam.ScreenToWorld(PlayerInput.MousePosition), Character.Controlled, out string errorMsg);
|
SpawnItem(args, GameMain.GameScreen.Cam.ScreenToWorld(PlayerInput.MousePosition), Character.Controlled, out string errorMsg);
|
||||||
@@ -1323,7 +1334,7 @@ namespace Barotrauma
|
|||||||
Character revivedCharacter = (args.Length == 0) ? Character.Controlled : FindMatchingCharacter(args);
|
Character revivedCharacter = (args.Length == 0) ? Character.Controlled : FindMatchingCharacter(args);
|
||||||
if (revivedCharacter == null) return;
|
if (revivedCharacter == null) return;
|
||||||
|
|
||||||
revivedCharacter.Revive(false);
|
revivedCharacter.Revive();
|
||||||
if (GameMain.Server != null)
|
if (GameMain.Server != null)
|
||||||
{
|
{
|
||||||
foreach (Client c in GameMain.Server.ConnectedClients)
|
foreach (Client c in GameMain.Server.ConnectedClients)
|
||||||
@@ -1342,7 +1353,7 @@ namespace Barotrauma
|
|||||||
Character revivedCharacter = (args.Length == 0) ? client.Character : FindMatchingCharacter(args);
|
Character revivedCharacter = (args.Length == 0) ? client.Character : FindMatchingCharacter(args);
|
||||||
if (revivedCharacter == null) return;
|
if (revivedCharacter == null) return;
|
||||||
|
|
||||||
revivedCharacter.Revive(false);
|
revivedCharacter.Revive();
|
||||||
if (GameMain.Server != null)
|
if (GameMain.Server != null)
|
||||||
{
|
{
|
||||||
foreach (Client c in GameMain.Server.ConnectedClients)
|
foreach (Client c in GameMain.Server.ConnectedClients)
|
||||||
@@ -1502,6 +1513,13 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
Character killedCharacter = (args.Length == 0) ? client.Character : FindMatchingCharacter(args);
|
Character killedCharacter = (args.Length == 0) ? client.Character : FindMatchingCharacter(args);
|
||||||
killedCharacter?.AddDamage(CauseOfDeath.Damage, killedCharacter.MaxHealth * 2, null);
|
killedCharacter?.AddDamage(CauseOfDeath.Damage, killedCharacter.MaxHealth * 2, null);
|
||||||
|
},
|
||||||
|
() =>
|
||||||
|
{
|
||||||
|
return new string[][]
|
||||||
|
{
|
||||||
|
Character.CharacterList.Select(c => c.Name).Distinct().ToArray()
|
||||||
|
};
|
||||||
}));
|
}));
|
||||||
|
|
||||||
commands.Add(new Command("killmonsters", "killmonsters: Immediately kills all AI-controlled enemies in the level.", (string[] args) =>
|
commands.Add(new Command("killmonsters", "killmonsters: Immediately kills all AI-controlled enemies in the level.", (string[] args) =>
|
||||||
@@ -1712,7 +1730,7 @@ namespace Barotrauma
|
|||||||
var itemContainer = item.GetComponent<ItemContainer>();
|
var itemContainer = item.GetComponent<ItemContainer>();
|
||||||
if (itemContainer != null)
|
if (itemContainer != null)
|
||||||
{
|
{
|
||||||
GameMain.Server.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.InventoryState });
|
GameMain.Server.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.InventoryState, 0 });
|
||||||
}
|
}
|
||||||
|
|
||||||
GameMain.Server.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.Status });
|
GameMain.Server.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.Status });
|
||||||
@@ -1895,9 +1913,18 @@ namespace Barotrauma
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(command)) return;
|
if (string.IsNullOrWhiteSpace(command) || command == "\\" || command == "\n") return;
|
||||||
|
|
||||||
string[] splitCommand = SplitCommand(command);
|
string[] splitCommand = SplitCommand(command);
|
||||||
|
if (splitCommand.Length == 0)
|
||||||
|
{
|
||||||
|
ThrowError("Failed to execute command \"" + command + "\"!");
|
||||||
|
GameAnalyticsManager.AddErrorEventOnce(
|
||||||
|
"DebugConsole.ExecuteCommand:LengthZero",
|
||||||
|
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||||
|
"Failed to execute command \"" + command + "\"!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!splitCommand[0].ToLowerInvariant().Equals("admin"))
|
if (!splitCommand[0].ToLowerInvariant().Equals("admin"))
|
||||||
{
|
{
|
||||||
@@ -1976,6 +2003,13 @@ namespace Barotrauma
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!MathUtils.IsValid(cursorWorldPos))
|
||||||
|
{
|
||||||
|
GameMain.Server.SendConsoleMessage("Could not execute command \"" + command + "\" - invalid cursor position.", client);
|
||||||
|
NewMessage(client.Name + " attempted to execute the console command \"" + command + "\" with invalid cursor position.", Color.White);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
matchingCommand.ServerExecuteOnClientRequest(client, cursorWorldPos, splitCommand.Skip(1).ToArray());
|
matchingCommand.ServerExecuteOnClientRequest(client, cursorWorldPos, splitCommand.Skip(1).ToArray());
|
||||||
@@ -2139,57 +2173,55 @@ namespace Barotrauma
|
|||||||
Vector2? spawnPos = null;
|
Vector2? spawnPos = null;
|
||||||
Inventory spawnInventory = null;
|
Inventory spawnInventory = null;
|
||||||
|
|
||||||
if (args.Length > 1)
|
int extraParams = 0;
|
||||||
|
switch (args.Last().ToLowerInvariant())
|
||||||
{
|
{
|
||||||
switch (args[1])
|
case "cursor":
|
||||||
{
|
extraParams = 1;
|
||||||
case "cursor":
|
spawnPos = cursorPos;
|
||||||
spawnPos = cursorPos;
|
break;
|
||||||
break;
|
case "inventory":
|
||||||
case "inventory":
|
extraParams = 1;
|
||||||
spawnInventory = controlledCharacter?.Inventory;
|
spawnInventory = controlledCharacter == null ? null : controlledCharacter.Inventory;
|
||||||
break;
|
break;
|
||||||
default:
|
case "cargo":
|
||||||
//Check if last arg matches the name of an in-game player
|
var wp = WayPoint.GetRandom(SpawnType.Cargo, null, Submarine.MainSub);
|
||||||
if (GameMain.Server != null)
|
spawnPos = wp == null ? Vector2.Zero : wp.WorldPosition;
|
||||||
{
|
break;
|
||||||
var client = GameMain.Server.ConnectedClients.Find(c => c.Name.ToLower() == args.Last().ToLower());
|
//Dont do a thing, random is basically Human points anyways - its in the help description.
|
||||||
if (client == null)
|
case "random":
|
||||||
{
|
extraParams = 1;
|
||||||
NewMessage("No player found with the name \"" + args.Last() + "\". Spawning item at random location. If the player you want to give the item to has a space in their name, try surrounding their name with quotes (\").", Color.Red);
|
return;
|
||||||
break;
|
default:
|
||||||
}
|
extraParams = 0;
|
||||||
else if (client.Character == null)
|
break;
|
||||||
{
|
|
||||||
errorMsg = "The player \"" + args.Last() + "\" is connected, but hasn't spawned yet.";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//If the last arg matches the name of an in-game player, set the destination to their inventory.
|
|
||||||
spawnInventory = client.Character.Inventory;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var matchingCharacter = FindMatchingCharacter(args.Skip(1).ToArray());
|
|
||||||
if (matchingCharacter?.Inventory != null) spawnInventory = matchingCharacter.Inventory;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
string itemName = args[0];
|
string itemName = string.Join(" ", args.Take(args.Length - extraParams)).ToLowerInvariant();
|
||||||
|
|
||||||
var itemPrefab = MapEntityPrefab.Find(itemName) as ItemPrefab;
|
ItemPrefab itemPrefab = MapEntityPrefab.Find(itemName) as ItemPrefab;
|
||||||
|
if (itemPrefab == null && extraParams == 0)
|
||||||
|
{
|
||||||
|
if (GameMain.Server != null)
|
||||||
|
{
|
||||||
|
var client = GameMain.Server.ConnectedClients.Find(c => c.Name.ToLower() == args.Last().ToLower());
|
||||||
|
if (client != null)
|
||||||
|
{
|
||||||
|
extraParams += 1;
|
||||||
|
itemName = string.Join(" ", args.Take(args.Length - extraParams)).ToLowerInvariant();
|
||||||
|
if (client.Character != null && client.Character.Name == args.Last().ToLower()) spawnInventory = client.Character.Inventory;
|
||||||
|
itemPrefab = MapEntityPrefab.Find(itemName) as ItemPrefab;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Check again if the item can be found again after having checked for a character
|
||||||
if (itemPrefab == null)
|
if (itemPrefab == null)
|
||||||
{
|
{
|
||||||
errorMsg = "Item \"" + itemName + "\" not found!";
|
errorMsg = "Item \"" + itemName + "\" not found!";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (spawnPos == null && spawnInventory == null)
|
if ((spawnPos == null || spawnPos == Vector2.Zero) && spawnInventory == null)
|
||||||
{
|
{
|
||||||
var wp = WayPoint.GetRandom(SpawnType.Human, null, Submarine.MainSub);
|
var wp = WayPoint.GetRandom(SpawnType.Human, null, Submarine.MainSub);
|
||||||
spawnPos = wp == null ? Vector2.Zero : wp.WorldPosition;
|
spawnPos = wp == null ? Vector2.Zero : wp.WorldPosition;
|
||||||
@@ -2198,6 +2230,7 @@ namespace Barotrauma
|
|||||||
if (spawnPos != null)
|
if (spawnPos != null)
|
||||||
{
|
{
|
||||||
Entity.Spawner.AddToSpawnQueue(itemPrefab, (Vector2)spawnPos);
|
Entity.Spawner.AddToSpawnQueue(itemPrefab, (Vector2)spawnPos);
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (spawnInventory != null)
|
else if (spawnInventory != null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -37,7 +37,6 @@ namespace Barotrauma
|
|||||||
Level.PositionType.Cave | Level.PositionType.MainPath | Level.PositionType.Ruin, 500.0f, 10000.0f, 30.0f);
|
Level.PositionType.Cave | Level.PositionType.MainPath | Level.PositionType.Ruin, 500.0f, 10000.0f, 30.0f);
|
||||||
|
|
||||||
item = new Item(itemPrefab, position, null);
|
item = new Item(itemPrefab, position, null);
|
||||||
item.MoveWithLevel = true;
|
|
||||||
item.body.FarseerBody.IsKinematic = true;
|
item.body.FarseerBody.IsKinematic = true;
|
||||||
|
|
||||||
//try to find a nearby artifact holder (or any alien itemcontainer) and place the artifact inside it
|
//try to find a nearby artifact holder (or any alien itemcontainer) and place the artifact inside it
|
||||||
@@ -66,7 +65,7 @@ namespace Barotrauma
|
|||||||
switch (state)
|
switch (state)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
if (item.ParentInventory!=null) item.body.FarseerBody.IsKinematic = false;
|
if (item.ParentInventory != null) item.body.FarseerBody.IsKinematic = false;
|
||||||
if (item.CurrentHull == null) return;
|
if (item.CurrentHull == null) return;
|
||||||
|
|
||||||
state = 1;
|
state = 1;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Barotrauma.Networking;
|
using Barotrauma.Items.Components;
|
||||||
|
using Barotrauma.Networking;
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -145,6 +146,23 @@ namespace Barotrauma
|
|||||||
subs[1].SetPosition(Level.Loaded.EndPosition - new Vector2(0.0f, 2000.0f));
|
subs[1].SetPosition(Level.Loaded.EndPosition - new Vector2(0.0f, 2000.0f));
|
||||||
subs[1].FlipX();
|
subs[1].FlipX();
|
||||||
|
|
||||||
|
//prevent wifi components from communicating between subs
|
||||||
|
List<WifiComponent> wifiComponents = new List<WifiComponent>();
|
||||||
|
foreach (Item item in Item.ItemList)
|
||||||
|
{
|
||||||
|
wifiComponents.AddRange(item.GetComponents<WifiComponent>());
|
||||||
|
}
|
||||||
|
foreach (WifiComponent wifiComponent in wifiComponents)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 2; i++)
|
||||||
|
{
|
||||||
|
if (wifiComponent.Item.Submarine == subs[i] || subs[i].DockedTo.Contains(wifiComponent.Item.Submarine))
|
||||||
|
{
|
||||||
|
wifiComponent.TeamID = subs[i].TeamID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
crews = new List<Character>[] { new List<Character>(), new List<Character>() };
|
crews = new List<Character>[] { new List<Character>(), new List<Character>() };
|
||||||
|
|
||||||
foreach (Submarine submarine in Submarine.Loaded)
|
foreach (Submarine submarine in Submarine.Loaded)
|
||||||
@@ -208,7 +226,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (winner>=0 && subs[winner] != null &&
|
if (winner >= 0 && subs[winner] != null &&
|
||||||
(winner == 0 && subs[winner].AtStartPosition) || (winner == 1 && subs[winner].AtEndPosition) &&
|
(winner == 0 && subs[winner].AtStartPosition) || (winner == 1 && subs[winner].AtEndPosition) &&
|
||||||
crews[winner].Any(c => !c.IsDead && c.Submarine == subs[winner]))
|
crews[winner].Any(c => !c.IsDead && c.Submarine == subs[winner]))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -50,7 +50,6 @@ namespace Barotrauma
|
|||||||
Vector2 position = Level.Loaded.GetRandomItemPos(spawnPositionType, 100.0f, minDistance, 30.0f);
|
Vector2 position = Level.Loaded.GetRandomItemPos(spawnPositionType, 100.0f, minDistance, 30.0f);
|
||||||
|
|
||||||
item = new Item(itemPrefab, position, null);
|
item = new Item(itemPrefab, position, null);
|
||||||
item.MoveWithLevel = true;
|
|
||||||
item.body.FarseerBody.IsKinematic = true;
|
item.body.FarseerBody.IsKinematic = true;
|
||||||
|
|
||||||
if (item.HasTag("alien"))
|
if (item.HasTag("alien"))
|
||||||
|
|||||||
@@ -1,16 +1,48 @@
|
|||||||
using GameAnalyticsSDK.Net;
|
using GameAnalyticsSDK.Net;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
public static class GameAnalyticsManager
|
public static class GameAnalyticsManager
|
||||||
{
|
{
|
||||||
|
private static HashSet<string> sentEventIdentifiers = new HashSet<string>();
|
||||||
|
|
||||||
public static void Init()
|
public static void Init()
|
||||||
{
|
{
|
||||||
#if DEBUB
|
#if DEBUG
|
||||||
GameAnalytics.SetEnabledInfoLog(true);
|
GameAnalytics.SetEnabledInfoLog(true);
|
||||||
#endif
|
#endif
|
||||||
GameAnalytics.ConfigureBuild(GameMain.Version.ToString());
|
|
||||||
|
string exePath = Assembly.GetEntryAssembly().Location;
|
||||||
|
string exeName = null;
|
||||||
|
Md5Hash exeHash = null;
|
||||||
|
exeName = Path.GetFileNameWithoutExtension(exePath).Replace(":", "");
|
||||||
|
var md5 = MD5.Create();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var stream = File.OpenRead(exePath))
|
||||||
|
{
|
||||||
|
exeHash = new Md5Hash(stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
DebugConsole.ThrowError("Error while calculating MD5 hash for the executable \"" + exePath + "\"", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
GameAnalytics.ConfigureBuild(GameMain.Version.ToString()
|
||||||
|
+ (string.IsNullOrEmpty(exeName) ? "Unknown" : exeName) + ":"
|
||||||
|
+ ((exeHash?.ShortHash == null) ? "Unknown" : exeHash.ShortHash));
|
||||||
|
|
||||||
|
GameAnalytics.AddDesignEvent("Executable:"
|
||||||
|
+ (string.IsNullOrEmpty(exeName) ? "Unknown" : exeName) + ":"
|
||||||
|
+ ((exeHash?.ShortHash == null) ? "Unknown" : exeHash.ShortHash));
|
||||||
|
|
||||||
GameAnalytics.ConfigureAvailableCustomDimensions01("singleplayer", "multiplayer", "editor");
|
GameAnalytics.ConfigureAvailableCustomDimensions01("singleplayer", "multiplayer", "editor");
|
||||||
GameAnalytics.Initialize("a3a073c20982de7c15d21e840e149122", "9010ad9a671233b8d9610d76cec8c897d9ff3ba7");
|
GameAnalytics.Initialize("a3a073c20982de7c15d21e840e149122", "9010ad9a671233b8d9610d76cec8c897d9ff3ba7");
|
||||||
|
|
||||||
@@ -21,5 +53,47 @@ namespace Barotrauma
|
|||||||
contentPackageName.Replace(":", "").Substring(0, Math.Min(32, contentPackageName.Length)));
|
contentPackageName.Replace(":", "").Substring(0, Math.Min(32, contentPackageName.Length)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds an error event to GameAnalytics if an event with the same identifier has not been added yet.
|
||||||
|
/// </summary>
|
||||||
|
public static void AddErrorEventOnce(string identifier, EGAErrorSeverity errorSeverity, string message)
|
||||||
|
{
|
||||||
|
if (!GameSettings.SendUserStatistics) return;
|
||||||
|
if (sentEventIdentifiers.Contains(identifier)) return;
|
||||||
|
|
||||||
|
GameAnalytics.AddErrorEvent(errorSeverity, message);
|
||||||
|
sentEventIdentifiers.Add(identifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void AddDesignEvent(string eventID)
|
||||||
|
{
|
||||||
|
if (!GameSettings.SendUserStatistics) return;
|
||||||
|
GameAnalytics.AddDesignEvent(eventID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void AddDesignEvent(string eventID, double value)
|
||||||
|
{
|
||||||
|
if (!GameSettings.SendUserStatistics) return;
|
||||||
|
GameAnalytics.AddDesignEvent(eventID, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void AddProgressionEvent(EGAProgressionStatus progressionStatus, string progression01)
|
||||||
|
{
|
||||||
|
if (!GameSettings.SendUserStatistics) return;
|
||||||
|
GameAnalytics.AddProgressionEvent(progressionStatus, progression01);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void AddProgressionEvent(EGAProgressionStatus progressionStatus, string progression01, string progression02)
|
||||||
|
{
|
||||||
|
if (!GameSettings.SendUserStatistics) return;
|
||||||
|
GameAnalytics.AddProgressionEvent(progressionStatus, progression01, progression02);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SetCustomDimension01(string dimension)
|
||||||
|
{
|
||||||
|
if (!GameSettings.SendUserStatistics) return;
|
||||||
|
GameAnalytics.SetCustomDimension01(dimension);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,26 +6,38 @@ using System.Linq;
|
|||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
|
class PurchasedItem
|
||||||
|
{
|
||||||
|
public ItemPrefab itemPrefab;
|
||||||
|
public int quantity;
|
||||||
|
|
||||||
|
public PurchasedItem(ItemPrefab itemPrefab, int quantity)
|
||||||
|
{
|
||||||
|
this.itemPrefab = itemPrefab;
|
||||||
|
this.quantity = quantity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class CargoManager
|
class CargoManager
|
||||||
{
|
{
|
||||||
private readonly List<ItemPrefab> purchasedItems;
|
private readonly List<PurchasedItem> purchasedItems;
|
||||||
|
|
||||||
private readonly CampaignMode campaign;
|
private readonly CampaignMode campaign;
|
||||||
|
|
||||||
public Action OnItemsChanged;
|
public Action OnItemsChanged;
|
||||||
|
|
||||||
public List<ItemPrefab> PurchasedItems
|
public List<PurchasedItem> PurchasedItems
|
||||||
{
|
{
|
||||||
get { return purchasedItems; }
|
get { return purchasedItems; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public CargoManager(CampaignMode campaign)
|
public CargoManager(CampaignMode campaign)
|
||||||
{
|
{
|
||||||
purchasedItems = new List<ItemPrefab>();
|
purchasedItems = new List<PurchasedItem>();
|
||||||
this.campaign = campaign;
|
this.campaign = campaign;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetPurchasedItems(List<ItemPrefab> items)
|
public void SetPurchasedItems(List<PurchasedItem> items)
|
||||||
{
|
{
|
||||||
purchasedItems.Clear();
|
purchasedItems.Clear();
|
||||||
purchasedItems.AddRange(items);
|
purchasedItems.AddRange(items);
|
||||||
@@ -33,33 +45,53 @@ namespace Barotrauma
|
|||||||
OnItemsChanged?.Invoke();
|
OnItemsChanged?.Invoke();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PurchaseItem(ItemPrefab item)
|
public void PurchaseItem(ItemPrefab item, int Quantity = 1)
|
||||||
{
|
{
|
||||||
campaign.Money -= item.Price;
|
PurchasedItem purchasedItem = PurchasedItems.Find(pi => pi.itemPrefab == item);
|
||||||
purchasedItems.Add(item);
|
|
||||||
|
if(purchasedItem != null && Quantity == 1)
|
||||||
|
{
|
||||||
|
campaign.Money -= item.Price;
|
||||||
|
purchasedItem.quantity += 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
campaign.Money -= (item.Price * Quantity);
|
||||||
|
purchasedItem = new PurchasedItem(item, Quantity);
|
||||||
|
purchasedItems.Add(purchasedItem);
|
||||||
|
}
|
||||||
|
|
||||||
OnItemsChanged?.Invoke();
|
OnItemsChanged?.Invoke();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SellItem(ItemPrefab item)
|
public void SellItem(ItemPrefab item, int quantity = 1)
|
||||||
{
|
{
|
||||||
campaign.Money += item.Price;
|
campaign.Money += (item.Price * quantity);
|
||||||
purchasedItems.Remove(item);
|
PurchasedItem purchasedItem = PurchasedItems.Find(pi => pi.itemPrefab == item);
|
||||||
|
if (purchasedItem != null && purchasedItem.quantity - quantity > 0)
|
||||||
|
{
|
||||||
|
purchasedItem.quantity -= quantity;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PurchasedItems.Remove(purchasedItem);
|
||||||
|
}
|
||||||
|
|
||||||
OnItemsChanged?.Invoke();
|
OnItemsChanged?.Invoke();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetTotalItemCost()
|
public int GetTotalItemCost()
|
||||||
{
|
{
|
||||||
return purchasedItems.Sum(i => i.Price);
|
return purchasedItems.Sum(i => (i.itemPrefab.Price * i.quantity));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CreateItems()
|
public void CreateItems()
|
||||||
{
|
{
|
||||||
CreateItems(purchasedItems);
|
CreateItems(purchasedItems);
|
||||||
|
OnItemsChanged?.Invoke();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void CreateItems(List<ItemPrefab> itemsToSpawn)
|
public static void CreateItems(List<PurchasedItem> itemsToSpawn)
|
||||||
{
|
{
|
||||||
WayPoint wp = WayPoint.GetRandom(SpawnType.Cargo, null, Submarine.MainSub);
|
WayPoint wp = WayPoint.GetRandom(SpawnType.Cargo, null, Submarine.MainSub);
|
||||||
|
|
||||||
@@ -78,24 +110,25 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
Dictionary<ItemContainer, int> availableContainers = new Dictionary<ItemContainer, int>();
|
Dictionary<ItemContainer, int> availableContainers = new Dictionary<ItemContainer, int>();
|
||||||
foreach (ItemPrefab prefab in itemsToSpawn)
|
ItemPrefab containerPrefab = null;
|
||||||
|
foreach (PurchasedItem pi in itemsToSpawn)
|
||||||
{
|
{
|
||||||
Vector2 position = new Vector2(
|
Vector2 position = new Vector2(
|
||||||
Rand.Range(cargoRoom.Rect.X + 20, cargoRoom.Rect.Right - 20),
|
Rand.Range(cargoRoom.Rect.X + 20, cargoRoom.Rect.Right - 20),
|
||||||
cargoRoom.Rect.Y - cargoRoom.Rect.Height + prefab.Size.Y / 2);
|
cargoRoom.Rect.Y - cargoRoom.Rect.Height + pi.itemPrefab.Size.Y / 2);
|
||||||
|
|
||||||
ItemContainer itemContainer = null;
|
ItemContainer itemContainer = null;
|
||||||
if (!string.IsNullOrEmpty(prefab.CargoContainerName))
|
if (!string.IsNullOrEmpty(pi.itemPrefab.CargoContainerName))
|
||||||
{
|
{
|
||||||
itemContainer = availableContainers.Keys.ToList().Find(ac =>
|
itemContainer = availableContainers.Keys.ToList().Find(ac =>
|
||||||
ac.Item.Prefab.NameMatches(prefab.CargoContainerName) ||
|
ac.Item.Prefab.NameMatches(pi.itemPrefab.CargoContainerName) ||
|
||||||
ac.Item.Prefab.Tags.Contains(prefab.CargoContainerName.ToLowerInvariant()));
|
ac.Item.Prefab.Tags.Contains(pi.itemPrefab.CargoContainerName.ToLowerInvariant()));
|
||||||
|
|
||||||
if (itemContainer == null)
|
if (itemContainer == null)
|
||||||
{
|
{
|
||||||
var containerPrefab = MapEntityPrefab.List.Find(ep =>
|
containerPrefab = MapEntityPrefab.List.Find(ep =>
|
||||||
ep.NameMatches(prefab.CargoContainerName) ||
|
ep.NameMatches(pi.itemPrefab.CargoContainerName) ||
|
||||||
(ep.Tags != null && ep.Tags.Contains(prefab.CargoContainerName.ToLowerInvariant()))) as ItemPrefab;
|
(ep.Tags != null && ep.Tags.Contains(pi.itemPrefab.CargoContainerName.ToLowerInvariant()))) as ItemPrefab;
|
||||||
|
|
||||||
if (containerPrefab == null)
|
if (containerPrefab == null)
|
||||||
{
|
{
|
||||||
@@ -117,41 +150,57 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (int i = 0; i < pi.quantity; i++)
|
||||||
|
{
|
||||||
|
if (itemContainer == null)
|
||||||
|
{
|
||||||
|
//no container, place at the waypoint
|
||||||
|
if (GameMain.Server != null)
|
||||||
|
{
|
||||||
|
Entity.Spawner.AddToSpawnQueue(pi.itemPrefab, position, wp.Submarine);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
new Item(pi.itemPrefab, position, wp.Submarine);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
//if the intial container has been removed due to it running out of space, add a new container
|
||||||
|
//of the same type and begin filling it
|
||||||
|
if (!availableContainers.ContainsKey(itemContainer))
|
||||||
|
{
|
||||||
|
Item containerItemOverFlow = new Item(containerPrefab, position, wp.Submarine);
|
||||||
|
itemContainer = containerItemOverFlow.GetComponent<ItemContainer>();
|
||||||
|
availableContainers.Add(itemContainer, itemContainer.Capacity);
|
||||||
|
if (GameMain.Server != null)
|
||||||
|
{
|
||||||
|
Entity.Spawner.CreateNetworkEvent(itemContainer.Item, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (itemContainer == null)
|
|
||||||
{
|
|
||||||
//no container, place at the waypoint
|
|
||||||
if (GameMain.Server != null)
|
|
||||||
{
|
|
||||||
Entity.Spawner.AddToSpawnQueue(prefab, position, wp.Submarine);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
new Item(prefab, position, wp.Submarine);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//place in the container
|
//place in the container
|
||||||
if (GameMain.Server != null)
|
if (GameMain.Server != null)
|
||||||
{
|
{
|
||||||
Entity.Spawner.AddToSpawnQueue(prefab, itemContainer.Inventory);
|
Entity.Spawner.AddToSpawnQueue(pi.itemPrefab, itemContainer.Inventory);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var item = new Item(prefab, position, wp.Submarine);
|
var item = new Item(pi.itemPrefab, position, wp.Submarine);
|
||||||
itemContainer.Inventory.TryPutItem(item, null);
|
itemContainer.Inventory.TryPutItem(item, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
//reduce the number of available slots in the container
|
//reduce the number of available slots in the container
|
||||||
availableContainers[itemContainer]--;
|
//if there is a container
|
||||||
if (availableContainers[itemContainer] <= 0)
|
if (availableContainers.ContainsKey(itemContainer))
|
||||||
|
{
|
||||||
|
availableContainers[itemContainer]--;
|
||||||
|
}
|
||||||
|
if (availableContainers.ContainsKey(itemContainer) && availableContainers[itemContainer] <= 0)
|
||||||
{
|
{
|
||||||
availableContainers.Remove(itemContainer);
|
availableContainers.Remove(itemContainer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
itemsToSpawn.Clear();
|
itemsToSpawn.Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -194,9 +194,10 @@ namespace Barotrauma
|
|||||||
msg.Write(Money);
|
msg.Write(Money);
|
||||||
|
|
||||||
msg.Write((UInt16)CargoManager.PurchasedItems.Count);
|
msg.Write((UInt16)CargoManager.PurchasedItems.Count);
|
||||||
foreach (ItemPrefab ip in CargoManager.PurchasedItems)
|
foreach (PurchasedItem pi in CargoManager.PurchasedItems)
|
||||||
{
|
{
|
||||||
msg.Write((UInt16)MapEntityPrefab.List.IndexOf(ip));
|
msg.Write((UInt16)MapEntityPrefab.List.IndexOf(pi.itemPrefab));
|
||||||
|
msg.Write((UInt16)pi.quantity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -205,11 +206,12 @@ namespace Barotrauma
|
|||||||
UInt16 selectedLocIndex = msg.ReadUInt16();
|
UInt16 selectedLocIndex = msg.ReadUInt16();
|
||||||
UInt16 purchasedItemCount = msg.ReadUInt16();
|
UInt16 purchasedItemCount = msg.ReadUInt16();
|
||||||
|
|
||||||
List<ItemPrefab> purchasedItems = new List<ItemPrefab>();
|
List<PurchasedItem> purchasedItems = new List<PurchasedItem>();
|
||||||
for (int i = 0; i < purchasedItemCount; i++)
|
for (int i = 0; i < purchasedItemCount; i++)
|
||||||
{
|
{
|
||||||
UInt16 itemPrefabIndex = msg.ReadUInt16();
|
UInt16 itemPrefabIndex = msg.ReadUInt16();
|
||||||
purchasedItems.Add(MapEntityPrefab.List[itemPrefabIndex] as ItemPrefab);
|
UInt16 itemQuantity = msg.ReadUInt16();
|
||||||
|
purchasedItems.Add(new PurchasedItem(MapEntityPrefab.List[itemPrefabIndex] as ItemPrefab, itemQuantity));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!sender.HasPermission(ClientPermissions.ManageCampaign))
|
if (!sender.HasPermission(ClientPermissions.ManageCampaign))
|
||||||
@@ -220,15 +222,15 @@ namespace Barotrauma
|
|||||||
|
|
||||||
Map.SelectLocation(selectedLocIndex == UInt16.MaxValue ? -1 : selectedLocIndex);
|
Map.SelectLocation(selectedLocIndex == UInt16.MaxValue ? -1 : selectedLocIndex);
|
||||||
|
|
||||||
List<ItemPrefab> currentItems = new List<ItemPrefab>(CargoManager.PurchasedItems);
|
List<PurchasedItem> currentItems = new List<PurchasedItem>(CargoManager.PurchasedItems);
|
||||||
foreach (ItemPrefab ip in currentItems)
|
foreach (PurchasedItem pi in currentItems)
|
||||||
{
|
{
|
||||||
CargoManager.SellItem(ip);
|
CargoManager.SellItem(pi.itemPrefab, pi.quantity);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (ItemPrefab ip in purchasedItems)
|
foreach (PurchasedItem pi in purchasedItems)
|
||||||
{
|
{
|
||||||
CargoManager.PurchaseItem(ip);
|
CargoManager.PurchaseItem(pi.itemPrefab, pi.quantity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -182,7 +182,7 @@ namespace Barotrauma
|
|||||||
StartRound(randomLevel, true, loadSecondSub);
|
StartRound(randomLevel, true, loadSecondSub);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void StartRound(Level level, bool reloadSub = true, bool loadSecondSub = false)
|
public void StartRound(Level level, bool reloadSub = true, bool loadSecondSub = false, bool mirrorLevel = false)
|
||||||
{
|
{
|
||||||
#if CLIENT
|
#if CLIENT
|
||||||
GameMain.LightManager.LosEnabled = GameMain.NetworkMember == null || GameMain.NetworkMember.CharacterInfo != null;
|
GameMain.LightManager.LosEnabled = GameMain.NetworkMember == null || GameMain.NetworkMember.CharacterInfo != null;
|
||||||
@@ -213,8 +213,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (level != null)
|
if (level != null)
|
||||||
{
|
{
|
||||||
level.Generate();
|
level.Generate(mirrorLevel);
|
||||||
|
|
||||||
submarine.SetPosition(submarine.FindSpawnPos(level.StartPosition - new Vector2(0.0f, 2000.0f)));
|
submarine.SetPosition(submarine.FindSpawnPos(level.StartPosition - new Vector2(0.0f, 2000.0f)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -229,18 +228,17 @@ namespace Barotrauma
|
|||||||
if (GameMode != null)
|
if (GameMode != null)
|
||||||
{
|
{
|
||||||
GameMode.MsgBox();
|
GameMode.MsgBox();
|
||||||
if (GameMode is MultiPlayerCampaign campaign && GameMain.Server != null)
|
if (GameMode is MultiPlayerCampaign mpCampaign && GameMain.Server != null)
|
||||||
{
|
{
|
||||||
campaign.CargoManager.CreateItems();
|
mpCampaign.CargoManager.CreateItems();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GameSettings.SendUserStatistics)
|
GameAnalyticsManager.AddDesignEvent("Submarine:" + submarine.Name);
|
||||||
{
|
GameAnalyticsManager.AddDesignEvent("Level", ToolBox.StringToInt(level.Seed));
|
||||||
GameAnalyticsSDK.Net.GameAnalytics.AddDesignEvent("Submarine:" + submarine.Name);
|
GameAnalyticsManager.AddProgressionEvent(GameAnalyticsSDK.Net.EGAProgressionStatus.Start,
|
||||||
GameAnalyticsSDK.Net.GameAnalytics.AddProgressionEvent(GameAnalyticsSDK.Net.EGAProgressionStatus.Start,
|
|
||||||
GameMode.Name, (Mission == null ? "None" : Mission.GetType().ToString()));
|
GameMode.Name, (Mission == null ? "None" : Mission.GetType().ToString()));
|
||||||
}
|
|
||||||
|
|
||||||
#if CLIENT
|
#if CLIENT
|
||||||
roundSummary = new RoundSummary(this);
|
roundSummary = new RoundSummary(this);
|
||||||
@@ -253,11 +251,10 @@ namespace Barotrauma
|
|||||||
public void EndRound(string endMessage)
|
public void EndRound(string endMessage)
|
||||||
{
|
{
|
||||||
if (Mission != null) Mission.End();
|
if (Mission != null) Mission.End();
|
||||||
if (GameSettings.SendUserStatistics)
|
GameAnalyticsManager.AddProgressionEvent(
|
||||||
{
|
(Mission == null || Mission.Completed) ? GameAnalyticsSDK.Net.EGAProgressionStatus.Complete : GameAnalyticsSDK.Net.EGAProgressionStatus.Fail,
|
||||||
GameAnalyticsSDK.Net.GameAnalytics.AddProgressionEvent((Mission == null || Mission.Completed) ? GameAnalyticsSDK.Net.EGAProgressionStatus.Complete : GameAnalyticsSDK.Net.EGAProgressionStatus.Fail,
|
GameMode.Name,
|
||||||
GameMode.Name, (Mission == null ? "None" : Mission.GetType().ToString()));
|
(Mission == null ? "None" : Mission.GetType().ToString()));
|
||||||
}
|
|
||||||
|
|
||||||
#if CLIENT
|
#if CLIENT
|
||||||
if (roundSummary != null)
|
if (roundSummary != null)
|
||||||
|
|||||||
@@ -164,7 +164,7 @@ namespace Barotrauma
|
|||||||
GameMain.Config.Save("config.xml");
|
GameMain.Config.Save("config.xml");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public static bool ShowUserStatisticsPrompt { get; private set; }
|
public static bool ShowUserStatisticsPrompt { get; set; }
|
||||||
|
|
||||||
public GameSettings(string filePath)
|
public GameSettings(string filePath)
|
||||||
{
|
{
|
||||||
@@ -334,8 +334,12 @@ namespace Barotrauma
|
|||||||
new XAttribute("soundvolume", soundVolume),
|
new XAttribute("soundvolume", soundVolume),
|
||||||
new XAttribute("verboselogging", VerboseLogging),
|
new XAttribute("verboselogging", VerboseLogging),
|
||||||
new XAttribute("savedebugconsolelogs", SaveDebugConsoleLogs),
|
new XAttribute("savedebugconsolelogs", SaveDebugConsoleLogs),
|
||||||
new XAttribute("enablesplashscreen", EnableSplashScreen),
|
new XAttribute("enablesplashscreen", EnableSplashScreen));
|
||||||
new XAttribute("senduserstatistics", sendUserStatistics));
|
|
||||||
|
if (!ShowUserStatisticsPrompt)
|
||||||
|
{
|
||||||
|
doc.Root.Add(new XAttribute("senduserstatistics", sendUserStatistics));
|
||||||
|
}
|
||||||
|
|
||||||
if (WasGameUpdated)
|
if (WasGameUpdated)
|
||||||
{
|
{
|
||||||
@@ -398,7 +402,16 @@ namespace Barotrauma
|
|||||||
new XAttribute("gender", characterGender));
|
new XAttribute("gender", characterGender));
|
||||||
doc.Root.Add(playerElement);
|
doc.Root.Add(playerElement);
|
||||||
|
|
||||||
doc.Save(filePath);
|
try
|
||||||
|
{
|
||||||
|
doc.Save(filePath);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
DebugConsole.ThrowError("Saving game settings failed.", e);
|
||||||
|
GameAnalyticsManager.AddErrorEventOnce("GameSettings.Save:SaveFailed", GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||||
|
"Saving game settings failed.\n" + e.Message + "\n" + e.StackTrace);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerable<object> ApplyUnsavedChanges()
|
private IEnumerable<object> ApplyUnsavedChanges()
|
||||||
|
|||||||
@@ -50,6 +50,10 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
Items[slotIndex].ApplyStatusEffects(ActionType.OnUse, 1.0f, character);
|
Items[slotIndex].ApplyStatusEffects(ActionType.OnUse, 1.0f, character);
|
||||||
|
|
||||||
|
//item may have been removed by a status effect
|
||||||
|
if (Items[slotIndex] == null) return true;
|
||||||
|
|
||||||
foreach (ItemComponent ic in Items[slotIndex].components)
|
foreach (ItemComponent ic in Items[slotIndex].components)
|
||||||
{
|
{
|
||||||
if (ic.DeleteOnUse)
|
if (ic.DeleteOnUse)
|
||||||
|
|||||||
@@ -27,18 +27,14 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
private Joint joint;
|
private Joint joint;
|
||||||
|
|
||||||
private Hull[] hulls;
|
private readonly Hull[] hulls = new Hull[2];
|
||||||
private ushort?[] hullIds;
|
private Gap gap;
|
||||||
|
|
||||||
private Door door;
|
private Door door;
|
||||||
|
|
||||||
private Body[] bodies;
|
private Body[] bodies;
|
||||||
|
|
||||||
private Body doorBody;
|
private Body doorBody;
|
||||||
|
|
||||||
private Gap gap;
|
|
||||||
private ushort? gapId;
|
|
||||||
|
|
||||||
private bool docked;
|
private bool docked;
|
||||||
|
|
||||||
public int DockingDir
|
public int DockingDir
|
||||||
@@ -115,8 +111,6 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
IsActive = true;
|
IsActive = true;
|
||||||
|
|
||||||
hullIds = new ushort?[2];
|
|
||||||
|
|
||||||
list.Add(this);
|
list.Add(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,7 +123,7 @@ namespace Barotrauma.Items.Components
|
|||||||
if (joint != null)
|
if (joint != null)
|
||||||
{
|
{
|
||||||
CreateJoint(joint is WeldJoint);
|
CreateJoint(joint is WeldJoint);
|
||||||
LinkHullsToGap();
|
LinkHullsToGaps();
|
||||||
}
|
}
|
||||||
else if (dockingTarget.joint != null)
|
else if (dockingTarget.joint != null)
|
||||||
{
|
{
|
||||||
@@ -138,7 +132,7 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
dockingTarget.CreateJoint(dockingTarget.joint is WeldJoint);
|
dockingTarget.CreateJoint(dockingTarget.joint is WeldJoint);
|
||||||
}
|
}
|
||||||
dockingTarget.LinkHullsToGap();
|
dockingTarget.LinkHullsToGaps();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -208,21 +202,15 @@ namespace Barotrauma.Items.Components
|
|||||||
Math.Sign(dockingTarget.item.WorldPosition.Y - item.WorldPosition.Y);
|
Math.Sign(dockingTarget.item.WorldPosition.Y - item.WorldPosition.Y);
|
||||||
dockingTarget.dockingDir = -dockingDir;
|
dockingTarget.dockingDir = -dockingDir;
|
||||||
|
|
||||||
|
if (door != null && dockingTarget.door != null)
|
||||||
foreach (WayPoint wp in WayPoint.WayPointList)
|
|
||||||
{
|
{
|
||||||
if (wp.Submarine != item.Submarine || wp.SpawnType != SpawnType.Path) continue;
|
WayPoint myWayPoint = WayPoint.WayPointList.Find(wp => door.LinkedGap == wp.ConnectedGap);
|
||||||
|
WayPoint targetWayPoint = WayPoint.WayPointList.Find(wp => dockingTarget.door.LinkedGap == wp.ConnectedGap);
|
||||||
|
|
||||||
if (!Submarine.RectContains(item.Rect, wp.Position)) continue;
|
if (myWayPoint != null && targetWayPoint != null)
|
||||||
|
|
||||||
foreach (WayPoint wp2 in WayPoint.WayPointList)
|
|
||||||
{
|
{
|
||||||
if (wp2.Submarine != dockingTarget.item.Submarine || wp2.SpawnType != SpawnType.Path) continue;
|
myWayPoint.linkedTo.Add(targetWayPoint);
|
||||||
|
targetWayPoint.linkedTo.Add(myWayPoint);
|
||||||
if (!Submarine.RectContains(dockingTarget.item.Rect, wp2.Position)) continue;
|
|
||||||
|
|
||||||
wp.linkedTo.Add(wp2);
|
|
||||||
wp2.linkedTo.Add(wp);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -238,35 +226,37 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
if (GameMain.Client != null && !isNetworkMessage) return;
|
if (GameMain.Client != null && !isNetworkMessage) return;
|
||||||
|
|
||||||
if (dockingTarget==null)
|
if (dockingTarget == null)
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError("Error - attempted to lock a docking port that's not connected to anything");
|
DebugConsole.ThrowError("Error - attempted to lock a docking port that's not connected to anything");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (joint is WeldJoint)
|
|
||||||
{
|
|
||||||
//DebugConsole.ThrowError("Error - attempted to lock a docking port that's already locked");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
dockingDir = IsHorizontal ?
|
if (!(joint is WeldJoint))
|
||||||
Math.Sign(dockingTarget.item.WorldPosition.X - item.WorldPosition.X) :
|
{
|
||||||
Math.Sign(dockingTarget.item.WorldPosition.Y - item.WorldPosition.Y);
|
|
||||||
dockingTarget.dockingDir = -dockingDir;
|
dockingDir = IsHorizontal ?
|
||||||
|
Math.Sign(dockingTarget.item.WorldPosition.X - item.WorldPosition.X) :
|
||||||
|
Math.Sign(dockingTarget.item.WorldPosition.Y - item.WorldPosition.Y);
|
||||||
|
dockingTarget.dockingDir = -dockingDir;
|
||||||
|
|
||||||
#if CLIENT
|
#if CLIENT
|
||||||
PlaySound(ActionType.OnSecondaryUse, item.WorldPosition);
|
PlaySound(ActionType.OnSecondaryUse, item.WorldPosition);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ConnectWireBetweenPorts();
|
ConnectWireBetweenPorts();
|
||||||
|
CreateJoint(true);
|
||||||
|
|
||||||
CreateJoint(true);
|
if (GameMain.Server != null)
|
||||||
|
{
|
||||||
if (GameMain.Server != null)
|
item.CreateServerEvent(this);
|
||||||
{
|
}
|
||||||
item.CreateServerEvent(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
List<MapEntity> removedEntities = item.linkedTo.Where(e => e.Removed).ToList();
|
||||||
|
foreach (MapEntity removed in removedEntities) item.linkedTo.Remove(removed);
|
||||||
|
|
||||||
if (!item.linkedTo.Any(e => e is Hull) && !dockingTarget.item.linkedTo.Any(e => e is Hull))
|
if (!item.linkedTo.Any(e => e is Hull) && !dockingTarget.item.linkedTo.Any(e => e is Hull))
|
||||||
{
|
{
|
||||||
CreateHull();
|
CreateHull();
|
||||||
@@ -345,17 +335,31 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
private void CreateDoorBody()
|
private void CreateDoorBody()
|
||||||
{
|
{
|
||||||
|
Vector2 position = ConvertUnits.ToSimUnits(item.Position + (dockingTarget.door.Item.WorldPosition - item.WorldPosition));
|
||||||
|
if (!MathUtils.IsValid(position))
|
||||||
|
{
|
||||||
|
string errorMsg =
|
||||||
|
"Attempted to create a door body at an invalid position (item pos: " + item.Position
|
||||||
|
+ ", item world pos: " + item.WorldPosition
|
||||||
|
+ ", docking target world pos: " + DockingTarget.door.Item.WorldPosition + ")\n" + Environment.StackTrace;
|
||||||
|
|
||||||
|
DebugConsole.ThrowError(errorMsg);
|
||||||
|
GameAnalyticsManager.AddErrorEventOnce(
|
||||||
|
"DockingPort.CreateDoorBody:InvalidPosition",
|
||||||
|
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||||
|
errorMsg);
|
||||||
|
position = Vector2.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
doorBody = BodyFactory.CreateRectangle(GameMain.World,
|
doorBody = BodyFactory.CreateRectangle(GameMain.World,
|
||||||
dockingTarget.door.Body.width,
|
dockingTarget.door.Body.width,
|
||||||
dockingTarget.door.Body.height,
|
dockingTarget.door.Body.height,
|
||||||
1.0f,
|
1.0f,
|
||||||
|
position,
|
||||||
dockingTarget.door);
|
dockingTarget.door);
|
||||||
|
|
||||||
doorBody.CollisionCategories = Physics.CollisionWall;
|
doorBody.CollisionCategories = Physics.CollisionWall;
|
||||||
doorBody.BodyType = BodyType.Static;
|
doorBody.BodyType = BodyType.Static;
|
||||||
doorBody.SetTransform(
|
|
||||||
ConvertUnits.ToSimUnits(item.Position + (dockingTarget.door.Item.WorldPosition - item.WorldPosition)),
|
|
||||||
0.0f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CreateHull()
|
private void CreateHull()
|
||||||
@@ -363,7 +367,6 @@ namespace Barotrauma.Items.Components
|
|||||||
var hullRects = new Rectangle[] { item.WorldRect, dockingTarget.item.WorldRect };
|
var hullRects = new Rectangle[] { item.WorldRect, dockingTarget.item.WorldRect };
|
||||||
var subs = new Submarine[] { item.Submarine, dockingTarget.item.Submarine };
|
var subs = new Submarine[] { item.Submarine, dockingTarget.item.Submarine };
|
||||||
|
|
||||||
hulls = new Hull[2];
|
|
||||||
bodies = new Body[4];
|
bodies = new Body[4];
|
||||||
|
|
||||||
if (dockingTarget.door != null)
|
if (dockingTarget.door != null)
|
||||||
@@ -392,6 +395,7 @@ namespace Barotrauma.Items.Components
|
|||||||
hullRects[i].Location -= MathUtils.ToPoint((subs[i].WorldPosition - subs[i].HiddenSubPosition));
|
hullRects[i].Location -= MathUtils.ToPoint((subs[i].WorldPosition - subs[i].HiddenSubPosition));
|
||||||
hulls[i] = new Hull(MapEntityPrefab.Find("Hull"), hullRects[i], subs[i]);
|
hulls[i] = new Hull(MapEntityPrefab.Find("Hull"), hullRects[i], subs[i]);
|
||||||
hulls[i].AddToGrid(subs[i]);
|
hulls[i].AddToGrid(subs[i]);
|
||||||
|
hulls[i].FreeID();
|
||||||
|
|
||||||
for (int j = 0; j < 2; j++)
|
for (int j = 0; j < 2; j++)
|
||||||
{
|
{
|
||||||
@@ -402,9 +406,6 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
|
|
||||||
gap = new Gap(new Rectangle(hullRects[0].Right - 2, hullRects[0].Y, 4, hullRects[0].Height), true, subs[0]);
|
gap = new Gap(new Rectangle(hullRects[0].Right - 2, hullRects[0].Y, 4, hullRects[0].Height), true, subs[0]);
|
||||||
if (gapId != null) gap.ID = (ushort)gapId;
|
|
||||||
|
|
||||||
LinkHullsToGap();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -422,25 +423,22 @@ namespace Barotrauma.Items.Components
|
|||||||
hullRects[i].Location -= MathUtils.ToPoint((subs[i].WorldPosition - subs[i].HiddenSubPosition));
|
hullRects[i].Location -= MathUtils.ToPoint((subs[i].WorldPosition - subs[i].HiddenSubPosition));
|
||||||
hulls[i] = new Hull(MapEntityPrefab.Find("Hull"), hullRects[i], subs[i]);
|
hulls[i] = new Hull(MapEntityPrefab.Find("Hull"), hullRects[i], subs[i]);
|
||||||
hulls[i].AddToGrid(subs[i]);
|
hulls[i].AddToGrid(subs[i]);
|
||||||
|
hulls[i].FreeID();
|
||||||
if (hullIds[i] != null) hulls[i].ID = (ushort)hullIds[i];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gap = new Gap(new Rectangle(hullRects[0].X, hullRects[0].Y+2, hullRects[0].Width, 4), false, subs[0]);
|
gap = new Gap(new Rectangle(hullRects[0].X, hullRects[0].Y+2, hullRects[0].Width, 4), false, subs[0]);
|
||||||
if (gapId != null) gap.ID = (ushort)gapId;
|
|
||||||
|
|
||||||
LinkHullsToGap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LinkHullsToGaps();
|
||||||
|
|
||||||
|
hulls[0].ShouldBeSaved = false;
|
||||||
|
hulls[1].ShouldBeSaved = false;
|
||||||
item.linkedTo.Add(hulls[0]);
|
item.linkedTo.Add(hulls[0]);
|
||||||
item.linkedTo.Add(hulls[1]);
|
item.linkedTo.Add(hulls[1]);
|
||||||
|
|
||||||
hullIds[0] = hulls[0].ID;
|
gap.FreeID();
|
||||||
hullIds[1] = hulls[1].ID;
|
|
||||||
|
|
||||||
gap.DisableHullRechecks = true;
|
gap.DisableHullRechecks = true;
|
||||||
gapId = gap.ID;
|
gap.ShouldBeSaved = false;
|
||||||
|
|
||||||
item.linkedTo.Add(gap);
|
item.linkedTo.Add(gap);
|
||||||
|
|
||||||
foreach (Body body in bodies)
|
foreach (Body body in bodies)
|
||||||
@@ -453,7 +451,7 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LinkHullsToGap()
|
private void LinkHullsToGaps()
|
||||||
{
|
{
|
||||||
if (gap == null || hulls == null || hulls[0] == null || hulls[1] == null)
|
if (gap == null || hulls == null || hulls[0] == null || hulls[1] == null)
|
||||||
{
|
{
|
||||||
@@ -491,6 +489,37 @@ namespace Barotrauma.Items.Components
|
|||||||
gap.linkedTo.Add(hulls[0]);
|
gap.linkedTo.Add(hulls[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 2; i++)
|
||||||
|
{
|
||||||
|
Gap doorGap = i == 0 ? door?.LinkedGap : dockingTarget?.door?.LinkedGap;
|
||||||
|
if (doorGap == null) continue;
|
||||||
|
doorGap.DisableHullRechecks = true;
|
||||||
|
if (doorGap.linkedTo.Count >= 2) continue;
|
||||||
|
|
||||||
|
if (IsHorizontal)
|
||||||
|
{
|
||||||
|
if (item.WorldPosition.X < dockingTarget.item.WorldPosition.X)
|
||||||
|
{
|
||||||
|
if (!doorGap.linkedTo.Contains(hulls[0])) doorGap.linkedTo.Add(hulls[0]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!doorGap.linkedTo.Contains(hulls[1])) doorGap.linkedTo.Add(hulls[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (item.WorldPosition.Y < dockingTarget.item.WorldPosition.Y)
|
||||||
|
{
|
||||||
|
if (!doorGap.linkedTo.Contains(hulls[0])) doorGap.linkedTo.Add(hulls[0]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!doorGap.linkedTo.Contains(hulls[1])) doorGap.linkedTo.Add(hulls[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Undock()
|
public void Undock()
|
||||||
@@ -504,21 +533,15 @@ namespace Barotrauma.Items.Components
|
|||||||
dockingTarget.item.Submarine.DockedTo.Remove(item.Submarine);
|
dockingTarget.item.Submarine.DockedTo.Remove(item.Submarine);
|
||||||
item.Submarine.DockedTo.Remove(dockingTarget.item.Submarine);
|
item.Submarine.DockedTo.Remove(dockingTarget.item.Submarine);
|
||||||
|
|
||||||
//remove all waypoint links between this sub and the dockingtarget
|
if (door != null && dockingTarget.door != null)
|
||||||
foreach (WayPoint wp in WayPoint.WayPointList)
|
|
||||||
{
|
{
|
||||||
if (wp.Submarine != item.Submarine || wp.SpawnType != SpawnType.Path) continue;
|
WayPoint myWayPoint = WayPoint.WayPointList.Find(wp => door.LinkedGap == wp.ConnectedGap);
|
||||||
|
WayPoint targetWayPoint = WayPoint.WayPointList.Find(wp => dockingTarget.door.LinkedGap == wp.ConnectedGap);
|
||||||
|
|
||||||
for (int i = wp.linkedTo.Count - 1; i >= 0; i--)
|
if (myWayPoint != null && targetWayPoint != null)
|
||||||
{
|
{
|
||||||
var wp2 = wp.linkedTo[i] as WayPoint;
|
myWayPoint.linkedTo.Remove(targetWayPoint);
|
||||||
if (wp2 == null) continue;
|
targetWayPoint.linkedTo.Remove(myWayPoint);
|
||||||
|
|
||||||
if (wp.Submarine == dockingTarget.item.Submarine)
|
|
||||||
{
|
|
||||||
wp.linkedTo.RemoveAt(i);
|
|
||||||
wp2.linkedTo.Remove(wp);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -547,12 +570,8 @@ namespace Barotrauma.Items.Components
|
|||||||
joint = null;
|
joint = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hulls != null)
|
hulls[0]?.Remove(); hulls[0] = null;
|
||||||
{
|
hulls[1]?.Remove(); hulls[1] = null;
|
||||||
hulls[0].Remove();
|
|
||||||
hulls[1].Remove();
|
|
||||||
hulls = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gap != null)
|
if (gap != null)
|
||||||
{
|
{
|
||||||
@@ -560,12 +579,7 @@ namespace Barotrauma.Items.Components
|
|||||||
gap = null;
|
gap = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
hullIds[0] = null;
|
if (bodies != null)
|
||||||
hullIds[1] = null;
|
|
||||||
|
|
||||||
gapId = null;
|
|
||||||
|
|
||||||
if (bodies!=null)
|
|
||||||
{
|
{
|
||||||
foreach (Body body in bodies)
|
foreach (Body body in bodies)
|
||||||
{
|
{
|
||||||
@@ -627,6 +641,9 @@ namespace Barotrauma.Items.Components
|
|||||||
protected override void RemoveComponentSpecific()
|
protected override void RemoveComponentSpecific()
|
||||||
{
|
{
|
||||||
list.Remove(this);
|
list.Remove(this);
|
||||||
|
hulls[0]?.Remove(); hulls[0] = null;
|
||||||
|
hulls[1]?.Remove(); hulls[1] = null;
|
||||||
|
gap?.Remove(); gap = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnMapLoaded()
|
public override void OnMapLoaded()
|
||||||
@@ -716,18 +733,7 @@ namespace Barotrauma.Items.Components
|
|||||||
if (docked)
|
if (docked)
|
||||||
{
|
{
|
||||||
msg.Write(dockingTarget.item.ID);
|
msg.Write(dockingTarget.item.ID);
|
||||||
|
msg.Write(hulls != null && hulls[0] != null && hulls[1] != null && gap != null);
|
||||||
if (hulls != null && hulls[0] != null && hulls[1] != null && gap != null)
|
|
||||||
{
|
|
||||||
msg.Write(true);
|
|
||||||
msg.Write(hulls[0].ID);
|
|
||||||
msg.Write(hulls[1].ID);
|
|
||||||
msg.Write(gap.ID);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
msg.Write(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -735,19 +741,27 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
bool isDocked = msg.ReadBoolean();
|
bool isDocked = msg.ReadBoolean();
|
||||||
|
|
||||||
|
for (int i = 0; i < 2; i++)
|
||||||
|
{
|
||||||
|
if (hulls[i] == null) continue;
|
||||||
|
item.linkedTo.Remove(hulls[i]);
|
||||||
|
hulls[i].Remove();
|
||||||
|
hulls[i] = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gap != null)
|
||||||
|
{
|
||||||
|
item.linkedTo.Remove(gap);
|
||||||
|
gap.Remove();
|
||||||
|
gap = null;
|
||||||
|
}
|
||||||
|
|
||||||
if (isDocked)
|
if (isDocked)
|
||||||
{
|
{
|
||||||
ushort dockingTargetID = msg.ReadUInt16();
|
ushort dockingTargetID = msg.ReadUInt16();
|
||||||
|
|
||||||
bool isLocked = msg.ReadBoolean();
|
bool isLocked = msg.ReadBoolean();
|
||||||
|
|
||||||
if (isLocked)
|
|
||||||
{
|
|
||||||
hullIds[0] = msg.ReadUInt16();
|
|
||||||
hullIds[1] = msg.ReadUInt16();
|
|
||||||
gapId = msg.ReadUInt16();
|
|
||||||
}
|
|
||||||
|
|
||||||
Entity targetEntity = Entity.FindEntityByID(dockingTargetID);
|
Entity targetEntity = Entity.FindEntityByID(dockingTargetID);
|
||||||
if (targetEntity == null || !(targetEntity is Item))
|
if (targetEntity == null || !(targetEntity is Item))
|
||||||
{
|
{
|
||||||
@@ -767,10 +781,6 @@ namespace Barotrauma.Items.Components
|
|||||||
if (isLocked)
|
if (isLocked)
|
||||||
{
|
{
|
||||||
Lock(true);
|
Lock(true);
|
||||||
|
|
||||||
hulls[0].ID = (ushort)hullIds[0];
|
|
||||||
hulls[1].ID = (ushort)hullIds[1];
|
|
||||||
gap.ID = (ushort)gapId;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -335,8 +335,12 @@ namespace Barotrauma.Items.Components
|
|||||||
body = null;
|
body = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//no need to remove the gap if we're unloading the whole submarine
|
||||||
if (linkedGap != null) linkedGap.Remove();
|
//otherwise the gap will be removed twice and cause console warnings
|
||||||
|
if (!Submarine.Unloading)
|
||||||
|
{
|
||||||
|
if (linkedGap != null) linkedGap.Remove();
|
||||||
|
}
|
||||||
|
|
||||||
doorSprite.Remove();
|
doorSprite.Remove();
|
||||||
if (weldedSprite != null) weldedSprite.Remove();
|
if (weldedSprite != null) weldedSprite.Remove();
|
||||||
@@ -349,6 +353,14 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
private void PushCharactersAway()
|
private void PushCharactersAway()
|
||||||
{
|
{
|
||||||
|
if (!MathUtils.IsValid(item.SimPosition))
|
||||||
|
{
|
||||||
|
DebugConsole.ThrowError("Failed to push a character out of a doorway - position of the door is not valid (" + item.SimPosition + ")");
|
||||||
|
GameAnalyticsManager.AddErrorEventOnce("PushCharactersAway:DoorPosInvalid", GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||||
|
"Failed to push a character out of a doorway - position of the door is not valid (" + item.SimPosition + ").");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
//push characters out of the doorway when the door is closing/opening
|
//push characters out of the doorway when the door is closing/opening
|
||||||
Vector2 simPos = ConvertUnits.ToSimUnits(new Vector2(item.Rect.X, item.Rect.Y));
|
Vector2 simPos = ConvertUnits.ToSimUnits(new Vector2(item.Rect.X, item.Rect.Y));
|
||||||
|
|
||||||
@@ -360,6 +372,16 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
foreach (Character c in Character.CharacterList)
|
foreach (Character c in Character.CharacterList)
|
||||||
{
|
{
|
||||||
|
if (!c.Enabled) continue;
|
||||||
|
if (!MathUtils.IsValid(c.SimPosition))
|
||||||
|
{
|
||||||
|
DebugConsole.ThrowError("Failed to push a character out of a doorway - position of the character \"" + c.Name + "\" is not valid (" + c.SimPosition + ")");
|
||||||
|
GameAnalyticsManager.AddErrorEventOnce("PushCharactersAway:CharacterPosInvalid", GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||||
|
"Failed to push a character out of a doorway - position of the character \"" + c.Name + "\" is not valid (" + c.SimPosition + ")." +
|
||||||
|
" Removed: " + c.Removed +
|
||||||
|
" Remoteplayer: " + c.IsRemotePlayer);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
int dir = isHorizontal ? Math.Sign(c.SimPosition.Y - item.SimPosition.Y) : Math.Sign(c.SimPosition.X - item.SimPosition.X);
|
int dir = isHorizontal ? Math.Sign(c.SimPosition.Y - item.SimPosition.Y) : Math.Sign(c.SimPosition.X - item.SimPosition.X);
|
||||||
|
|
||||||
List<PhysicsBody> bodies = c.AnimController.Limbs.Select(l => l.body).ToList();
|
List<PhysicsBody> bodies = c.AnimController.Limbs.Select(l => l.body).ToList();
|
||||||
@@ -368,17 +390,24 @@ namespace Barotrauma.Items.Components
|
|||||||
foreach (PhysicsBody body in bodies)
|
foreach (PhysicsBody body in bodies)
|
||||||
{
|
{
|
||||||
float diff = 0.0f;
|
float diff = 0.0f;
|
||||||
|
if (!MathUtils.IsValid(body.SimPosition))
|
||||||
|
{
|
||||||
|
DebugConsole.ThrowError("Failed to push a limb out of a doorway - position of the body (character \"" + c.Name + "\") is not valid (" + body.SimPosition + ")");
|
||||||
|
GameAnalyticsManager.AddErrorEventOnce("PushCharactersAway:LimbPosInvalid", GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||||
|
"Failed to push a character out of a doorway - position of the character \"" + c.Name + "\" is not valid (" + body.SimPosition + ")." +
|
||||||
|
" Removed: " + c.Removed +
|
||||||
|
" Remoteplayer: " + c.IsRemotePlayer);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (isHorizontal)
|
if (isHorizontal)
|
||||||
{
|
{
|
||||||
if (body.SimPosition.X < simPos.X || body.SimPosition.X > simPos.X + simSize.X) continue;
|
if (body.SimPosition.X < simPos.X || body.SimPosition.X > simPos.X + simSize.X) continue;
|
||||||
|
|
||||||
diff = body.SimPosition.Y - item.SimPosition.Y;
|
diff = body.SimPosition.Y - item.SimPosition.Y;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (body.SimPosition.Y > simPos.Y || body.SimPosition.Y < simPos.Y - simSize.Y) continue;
|
if (body.SimPosition.Y > simPos.Y || body.SimPosition.Y < simPos.Y - simSize.Y) continue;
|
||||||
|
|
||||||
diff = body.SimPosition.X - item.SimPosition.X;
|
diff = body.SimPosition.X - item.SimPosition.X;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -442,7 +471,9 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
public void SetState(bool open, bool isNetworkMessage, bool sendNetworkMessage = false)
|
public void SetState(bool open, bool isNetworkMessage, bool sendNetworkMessage = false)
|
||||||
{
|
{
|
||||||
if (isStuck || (predictedState == null && isOpen == open) || (predictedState != null && isOpen == predictedState.Value)) return;
|
if (isStuck ||
|
||||||
|
(predictedState == null && isOpen == open) ||
|
||||||
|
(predictedState != null && isOpen == predictedState.Value && isOpen == open)) return;
|
||||||
|
|
||||||
if (GameMain.Client != null && !isNetworkMessage)
|
if (GameMain.Client != null && !isNetworkMessage)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -124,6 +124,17 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void Load(XElement componentElement)
|
||||||
|
{
|
||||||
|
base.Load(componentElement);
|
||||||
|
if (attachable)
|
||||||
|
{
|
||||||
|
prevMsg = Msg;
|
||||||
|
prevPickKey = PickKey;
|
||||||
|
prevRequiredItems = new List<RelatedItem>(requiredItems);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override void Drop(Character dropper)
|
public override void Drop(Character dropper)
|
||||||
{
|
{
|
||||||
Drop(true, dropper);
|
Drop(true, dropper);
|
||||||
@@ -160,7 +171,24 @@ namespace Barotrauma.Items.Components
|
|||||||
if (item.body != null)
|
if (item.body != null)
|
||||||
{
|
{
|
||||||
item.body.ResetDynamics();
|
item.body.ResetDynamics();
|
||||||
item.SetTransform(picker.SimPosition, 0.0f);
|
Limb heldHand;
|
||||||
|
Limb arm;
|
||||||
|
if (picker.Inventory.IsInLimbSlot(item, InvSlotType.LeftHand))
|
||||||
|
{
|
||||||
|
heldHand = picker.AnimController.GetLimb(LimbType.LeftHand);
|
||||||
|
arm = picker.AnimController.GetLimb(LimbType.LeftArm);
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
heldHand = picker.AnimController.GetLimb(LimbType.RightHand);
|
||||||
|
arm = picker.AnimController.GetLimb(LimbType.RightArm);
|
||||||
|
}
|
||||||
|
|
||||||
|
float xDif = (heldHand.SimPosition.X - arm.SimPosition.X) / 2f;
|
||||||
|
float yDif = (heldHand.SimPosition.Y - arm.SimPosition.Y) / 2.5f;
|
||||||
|
//hand simPosition is actually in the wrist so need to move the item out from it slightly
|
||||||
|
item.SetTransform(heldHand.SimPosition + new Vector2(xDif,yDif), 0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
picker.DeselectItem(item);
|
picker.DeselectItem(item);
|
||||||
@@ -214,6 +242,14 @@ namespace Barotrauma.Items.Components
|
|||||||
IsActive = false;
|
IsActive = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool CanBeDeattached()
|
||||||
|
{
|
||||||
|
if (!attachable || !attached) return true;
|
||||||
|
|
||||||
|
//don't allow deattaching if outside hulls and not in sub editor
|
||||||
|
return item.CurrentHull != null || Screen.Selected == GameMain.SubEditorScreen;
|
||||||
|
}
|
||||||
|
|
||||||
public override bool Pick(Character picker)
|
public override bool Pick(Character picker)
|
||||||
{
|
{
|
||||||
if (!attachable)
|
if (!attachable)
|
||||||
@@ -221,6 +257,8 @@ namespace Barotrauma.Items.Components
|
|||||||
return base.Pick(picker);
|
return base.Pick(picker);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!CanBeDeattached()) return false;
|
||||||
|
|
||||||
if (Attached)
|
if (Attached)
|
||||||
{
|
{
|
||||||
return base.Pick(picker);
|
return base.Pick(picker);
|
||||||
@@ -330,7 +368,7 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
if (picker.HasSelectedItem(item))
|
if (picker.HasSelectedItem(item))
|
||||||
{
|
{
|
||||||
picker.AnimController.HoldItem(deltaTime, item, handlePos, holdPos, aimPos, picker.IsKeyDown(InputType.Aim), holdAngle);
|
picker.AnimController.HoldItem(deltaTime, item, handlePos, holdPos, aimPos, picker.IsKeyDown(InputType.Aim) && aimPos != Vector2.Zero, holdAngle);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -410,7 +448,7 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
public void ClientRead(ServerNetObject type, NetBuffer msg, float sendingTime)
|
public void ClientRead(ServerNetObject type, NetBuffer msg, float sendingTime)
|
||||||
{
|
{
|
||||||
bool isAttached = msg.ReadBoolean();
|
bool shouldBeAttached = msg.ReadBoolean();
|
||||||
Vector2 simPosition = new Vector2(msg.ReadFloat(), msg.ReadFloat());
|
Vector2 simPosition = new Vector2(msg.ReadFloat(), msg.ReadFloat());
|
||||||
|
|
||||||
if (!attachable)
|
if (!attachable)
|
||||||
@@ -419,7 +457,7 @@ namespace Barotrauma.Items.Components
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isAttached)
|
if (shouldBeAttached)
|
||||||
{
|
{
|
||||||
Drop(false, null);
|
Drop(false, null);
|
||||||
item.SetTransform(simPosition, 0.0f);
|
item.SetTransform(simPosition, 0.0f);
|
||||||
@@ -427,16 +465,19 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DropConnectedWires(null);
|
if (attached)
|
||||||
|
|
||||||
if (body != null)
|
|
||||||
{
|
{
|
||||||
item.body = body;
|
DropConnectedWires(null);
|
||||||
item.body.Enabled = true;
|
|
||||||
}
|
|
||||||
IsActive = false;
|
|
||||||
|
|
||||||
DeattachFromWall();
|
if (body != null)
|
||||||
|
{
|
||||||
|
item.body = body;
|
||||||
|
item.body.Enabled = true;
|
||||||
|
}
|
||||||
|
IsActive = false;
|
||||||
|
|
||||||
|
DeattachFromWall();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using FarseerPhysics.Dynamics;
|
|||||||
using FarseerPhysics.Dynamics.Contacts;
|
using FarseerPhysics.Dynamics.Contacts;
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
|
|
||||||
@@ -24,6 +25,8 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
private float reloadTimer;
|
private float reloadTimer;
|
||||||
|
|
||||||
|
private HashSet<Entity> hitTargets = new HashSet<Entity>();
|
||||||
|
|
||||||
[Serialize(0.0f, false)]
|
[Serialize(0.0f, false)]
|
||||||
public float Range
|
public float Range
|
||||||
{
|
{
|
||||||
@@ -94,6 +97,7 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
|
|
||||||
hitting = true;
|
hitting = true;
|
||||||
|
hitTargets.Clear();
|
||||||
|
|
||||||
IsActive = true;
|
IsActive = true;
|
||||||
return false;
|
return false;
|
||||||
@@ -131,8 +135,7 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
if (picker.IsKeyDown(InputType.Aim))
|
if (picker.IsKeyDown(InputType.Aim))
|
||||||
{
|
{
|
||||||
hitPos = Math.Min(hitPos+deltaTime*5.0f, MathHelper.Pi*0.7f);
|
hitPos = Math.Min(hitPos + deltaTime * 5.0f, MathHelper.Pi * 0.7f);
|
||||||
|
|
||||||
ac.HoldItem(deltaTime, item, handlePos, new Vector2(0.6f, -0.1f), new Vector2(-0.3f, 0.2f), false, hitPos);
|
ac.HoldItem(deltaTime, item, handlePos, new Vector2(0.6f, -0.1f), new Vector2(-0.3f, 0.2f), false, hitPos);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -142,28 +145,13 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//Vector2 diff = Vector2.Normalize(picker.CursorPosition - ac.RefLimb.Position);
|
hitPos -= deltaTime * 15.0f;
|
||||||
//diff.X = diff.X * ac.Dir;
|
|
||||||
|
|
||||||
hitPos -= deltaTime*15.0f;
|
|
||||||
|
|
||||||
//angl = -hitPos * 2.0f;
|
|
||||||
// System.Diagnostics.Debug.WriteLine("<1.0f "+hitPos);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ac.HoldItem(deltaTime, item, handlePos, new Vector2(0.6f, -0.1f), new Vector2(-0.3f, 0.2f), false, hitPos);
|
ac.HoldItem(deltaTime, item, handlePos, new Vector2(0.6f, -0.1f), new Vector2(-0.3f, 0.2f), false, hitPos);
|
||||||
//}
|
if (hitPos < -MathHelper.PiOver4 * 1.2f)
|
||||||
//else
|
|
||||||
//{
|
|
||||||
// System.Diagnostics.Debug.WriteLine(">1.0f " + hitPos);
|
|
||||||
// ac.HoldItem(deltaTime, item, handlePos, new Vector2(0.5f, 0.2f), new Vector2(1.0f, 0.2f), false, 0.0f);
|
|
||||||
//}
|
|
||||||
|
|
||||||
if (hitPos < -MathHelper.PiOver4*1.2f)
|
|
||||||
{
|
{
|
||||||
RestoreCollision();
|
RestoreCollision();
|
||||||
hitting = false;
|
hitting = false;
|
||||||
|
hitTargets.Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -230,15 +218,22 @@ namespace Barotrauma.Items.Components
|
|||||||
targetLimb = (Limb)f2.Body.UserData;
|
targetLimb = (Limb)f2.Body.UserData;
|
||||||
if (targetLimb.IsSevered || targetLimb.character == null) return false;
|
if (targetLimb.IsSevered || targetLimb.character == null) return false;
|
||||||
targetCharacter = targetLimb.character;
|
targetCharacter = targetLimb.character;
|
||||||
|
|
||||||
|
if (hitTargets.Contains(targetCharacter)) return false;
|
||||||
|
hitTargets.Add(targetCharacter);
|
||||||
}
|
}
|
||||||
else if (f2.Body.UserData is Character)
|
else if (f2.Body.UserData is Character)
|
||||||
{
|
{
|
||||||
targetCharacter = (Character)f2.Body.UserData;
|
targetCharacter = (Character)f2.Body.UserData;
|
||||||
targetLimb = targetCharacter.AnimController.GetLimb(LimbType.Torso); //Otherwise armor can be bypassed in strange ways
|
targetLimb = targetCharacter.AnimController.GetLimb(LimbType.Torso); //Otherwise armor can be bypassed in strange ways
|
||||||
|
if (hitTargets.Contains(targetCharacter)) return false;
|
||||||
|
hitTargets.Add(targetCharacter);
|
||||||
}
|
}
|
||||||
else if (f2.Body.UserData is Structure)
|
else if (f2.Body.UserData is Structure)
|
||||||
{
|
{
|
||||||
targetStructure = (Structure)f2.Body.UserData;
|
targetStructure = (Structure)f2.Body.UserData;
|
||||||
|
if (hitTargets.Contains(targetStructure)) return false;
|
||||||
|
hitTargets.Add(targetStructure);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -267,9 +262,6 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RestoreCollision();
|
|
||||||
hitting = false;
|
|
||||||
|
|
||||||
if (GameMain.Client != null) return true;
|
if (GameMain.Client != null) return true;
|
||||||
|
|
||||||
if (GameMain.Server != null && targetCharacter != null) //TODO: Log structure hits
|
if (GameMain.Server != null && targetCharacter != null) //TODO: Log structure hits
|
||||||
|
|||||||
@@ -127,17 +127,7 @@ namespace Barotrauma.Items.Components
|
|||||||
Color.Red, Color.Green);
|
Color.Red, Color.Green);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
picker.AnimController.Anim = AnimController.Animation.UsingConstruction;
|
picker.AnimController.UpdateUseItem(true, item.SimPosition + Vector2.UnitY * ((pickTimer / 10.0f) % 0.1f));
|
||||||
|
|
||||||
picker.AnimController.TargetMovement = Vector2.Zero;
|
|
||||||
|
|
||||||
leftHand.Disabled = true;
|
|
||||||
leftHand.pullJoint.Enabled = true;
|
|
||||||
leftHand.pullJoint.WorldAnchorB = item.SimPosition + Vector2.UnitY * ((pickTimer / 10.0f) % 0.1f);
|
|
||||||
|
|
||||||
rightHand.Disabled = true;
|
|
||||||
rightHand.pullJoint.Enabled = true;
|
|
||||||
rightHand.pullJoint.WorldAnchorB = item.SimPosition + Vector2.UnitY * ((pickTimer / 10.0f) % 0.1f);
|
|
||||||
|
|
||||||
pickTimer += CoroutineManager.DeltaTime;
|
pickTimer += CoroutineManager.DeltaTime;
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user