4
.gitattributes
vendored
Normal file
4
.gitattributes
vendored
Normal file
@@ -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
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("0.8.1.5")]
|
||||
[assembly: AssemblyFileVersion("0.8.1.5")]
|
||||
[assembly: AssemblyVersion("0.8.2.0")]
|
||||
[assembly: AssemblyFileVersion("0.8.2.0")]
|
||||
|
||||
@@ -99,7 +99,7 @@ namespace Barotrauma
|
||||
|
||||
public Camera()
|
||||
{
|
||||
zoom = 1.0f;
|
||||
zoom = prevZoom = 1.0f;
|
||||
rotation = 0.0f;
|
||||
position = Vector2.Zero;
|
||||
|
||||
@@ -112,7 +112,7 @@ namespace Barotrauma
|
||||
viewMatrix =
|
||||
Matrix.CreateTranslation(new Vector3(GameMain.GraphicsWidth / 2.0f, GameMain.GraphicsHeight / 2.0f, 0));
|
||||
|
||||
UpdateTransform();
|
||||
UpdateTransform(false);
|
||||
}
|
||||
|
||||
public Vector2 TargetPos
|
||||
|
||||
@@ -81,6 +81,9 @@ namespace Barotrauma
|
||||
if (Limbs == null)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -97,7 +100,6 @@ namespace Barotrauma
|
||||
|
||||
foreach (Limb limb in Limbs)
|
||||
{
|
||||
|
||||
if (limb.pullJoint != null)
|
||||
{
|
||||
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)
|
||||
{
|
||||
Vector2 prevPos = ConvertUnits.ToDisplayUnits(character.MemState[0].Position);
|
||||
|
||||
@@ -206,8 +206,8 @@ namespace Barotrauma
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace Barotrauma
|
||||
|
||||
public static void TakeDamage(float amount)
|
||||
{
|
||||
healthBar.Flash();
|
||||
healthBar?.Flash();
|
||||
|
||||
damageOverlayTimer = MathHelper.Clamp(amount * 0.1f, 0.2f, 1.0f);
|
||||
}
|
||||
|
||||
@@ -150,7 +150,7 @@ namespace Barotrauma
|
||||
msg.ReadPadBits();
|
||||
|
||||
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);
|
||||
while (index < memState.Count && NetIdUtils.IdMoreRecent(posInfo.ID, memState[index].ID))
|
||||
@@ -188,6 +188,7 @@ namespace Barotrauma
|
||||
|
||||
controlled = this;
|
||||
IsRemotePlayer = false;
|
||||
GameMain.Client.HasSpawned = true;
|
||||
GameMain.Client.Character = this;
|
||||
GameMain.LightManager.LosEnabled = true;
|
||||
}
|
||||
@@ -286,6 +287,7 @@ namespace Barotrauma
|
||||
|
||||
if (GameMain.Client.ID == ownerId)
|
||||
{
|
||||
GameMain.Client.HasSpawned = true;
|
||||
GameMain.Client.Character = character;
|
||||
Controlled = character;
|
||||
|
||||
@@ -342,7 +344,7 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
this.isDead = false;
|
||||
if (this.isDead) Revive();
|
||||
|
||||
health = msg.ReadRangedSingle(minHealth, maxHealth, 8);
|
||||
|
||||
|
||||
@@ -194,10 +194,11 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
Color wearableColor = wearable.WearableComponent.Item.GetSpriteColor();
|
||||
wearable.Sprite.Draw(spriteBatch,
|
||||
new Vector2(body.DrawPosition.X, -body.DrawPosition.Y),
|
||||
color, origin,
|
||||
-body.DrawRotation,
|
||||
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)),
|
||||
origin, -body.DrawRotation,
|
||||
Scale, spriteEffect, depth);
|
||||
}
|
||||
|
||||
|
||||
@@ -355,9 +355,9 @@ namespace Barotrauma
|
||||
NewMessage("Removed " + me.Name + " (simposition " + me.SimPosition + ")", Color.Orange);
|
||||
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);
|
||||
}
|
||||
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("Fullscreen enabled", Color.Green);
|
||||
|
||||
GameSettings.ShowUserStatisticsPrompt = true;
|
||||
|
||||
GameSettings.VerboseLogging = false;
|
||||
|
||||
if (GameMain.Config.MasterServerUrl != "http://www.undertowgames.com/baromaster")
|
||||
|
||||
@@ -214,12 +214,9 @@ namespace Barotrauma
|
||||
|
||||
if (GameMain.GameSession != null)
|
||||
{
|
||||
if (GameSettings.SendUserStatistics)
|
||||
{
|
||||
Mission mission = GameMain.GameSession.Mission;
|
||||
GameAnalyticsSDK.Net.GameAnalytics.AddDesignEvent("QuitRound:" + (save ? "Save" : "NoSave"));
|
||||
GameAnalyticsSDK.Net.GameAnalytics.AddDesignEvent("EndRound:" + (mission == null ? "NoMission" : (mission.Completed ? "MissionCompleted" : "MissionFailed")));
|
||||
}
|
||||
Mission mission = GameMain.GameSession.Mission;
|
||||
GameAnalyticsManager.AddDesignEvent("QuitRound:" + (save ? "Save" : "NoSave"));
|
||||
GameAnalyticsManager.AddDesignEvent("EndRound:" + (mission == null ? "NoMission" : (mission.Completed ? "MissionCompleted" : "MissionFailed")));
|
||||
GameMain.GameSession = null;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
using GameAnalyticsSDK.Net;
|
||||
using System.Threading;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -74,7 +75,8 @@ namespace Barotrauma
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
private static bool FullscreenOnTabIn;
|
||||
|
||||
public static WindowMode WindowMode
|
||||
{
|
||||
get;
|
||||
@@ -134,7 +136,7 @@ namespace Barotrauma
|
||||
Config.WasGameUpdated = false;
|
||||
Config.Save("config.xml");
|
||||
}
|
||||
|
||||
|
||||
ApplyGraphicsSettings();
|
||||
|
||||
Content.RootDirectory = "Content";
|
||||
@@ -231,8 +233,37 @@ namespace Barotrauma
|
||||
TitleScreen = new LoadingScreen(GraphicsDevice);
|
||||
|
||||
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()
|
||||
{
|
||||
if (GameSettings.ShowUserStatisticsPrompt)
|
||||
@@ -244,12 +275,18 @@ namespace Barotrauma
|
||||
new string[] { "Yes", "No" });
|
||||
userStatsPrompt.Buttons[0].OnClicked += (btn, userdata) =>
|
||||
{
|
||||
GameSettings.ShowUserStatisticsPrompt = false;
|
||||
GameSettings.SendUserStatistics = true;
|
||||
GameAnalyticsManager.Init();
|
||||
return true;
|
||||
};
|
||||
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;
|
||||
}
|
||||
else if (GameSettings.SendUserStatistics)
|
||||
|
||||
@@ -92,9 +92,10 @@ namespace Barotrauma
|
||||
msg.Write(map.SelectedLocationIndex == -1 ? UInt16.MaxValue : (UInt16)map.SelectedLocationIndex);
|
||||
|
||||
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();
|
||||
|
||||
UInt16 purchasedItemCount = msg.ReadUInt16();
|
||||
List<ItemPrefab> purchasedItems = new List<ItemPrefab>();
|
||||
List<PurchasedItem> purchasedItems = new List<PurchasedItem>();
|
||||
for (int i = 0; i < purchasedItemCount; i++)
|
||||
{
|
||||
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;
|
||||
|
||||
@@ -269,7 +269,7 @@ namespace Barotrauma.Tutorials
|
||||
}
|
||||
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.");
|
||||
|
||||
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.
|
||||
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);
|
||||
|
||||
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;
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
if (item.Removed || GameMain.Client == null)
|
||||
{
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
|
||||
((IServerSerializable)this).ClientRead(type, buffer, sendingTime);
|
||||
|
||||
correctionTimer = 0.0f;
|
||||
|
||||
@@ -6,9 +6,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
|
||||
{
|
||||
var focusTarget = GetFocusTarget();
|
||||
if (focusTarget == null) return;
|
||||
if (character.ViewTarget == focusTarget)
|
||||
if (focusTarget != null && character.ViewTarget == focusTarget)
|
||||
{
|
||||
foreach (ItemComponent ic in focusTarget.components)
|
||||
{
|
||||
|
||||
@@ -62,7 +62,7 @@ namespace Barotrauma.Items.Components
|
||||
if (selectedItemFrame != null) GuiFrame.RemoveChild(selectedItemFrame);
|
||||
|
||||
//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);
|
||||
|
||||
@@ -105,36 +105,41 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
inadequateSkills = targetItem.RequiredSkills.FindAll(skill => Character.Controlled.GetSkillLevel(skill.Name) < skill.Level);
|
||||
}
|
||||
|
||||
Color textColor = Color.White;
|
||||
string text;
|
||||
if (!inadequateSkills.Any())
|
||||
|
||||
string text = TextManager.Get("FabricatorRequiredItems")+ ":\n";
|
||||
foreach (Tuple<ItemPrefab, int, float, bool> ip in targetItem.RequiredItems)
|
||||
{
|
||||
text = TextManager.Get("FabricatorRequiredItems")+ ":\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";
|
||||
text += " - " + ip.Item1.Name + " x" + ip.Item2 + (ip.Item3 < 1.0f ? ", " + ip.Item3 * 100 + "% " + TextManager.Get("FabricatorRequiredCondition") + "\n" : "\n");
|
||||
}
|
||||
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";
|
||||
foreach (Skill skill in inadequateSkills)
|
||||
{
|
||||
text += " - " + skill.Name + " " + TextManager.Get("Lvl").ToLower() + " " + skill.Level + "\n";
|
||||
}
|
||||
|
||||
textColor = Color.Red;
|
||||
new GUITextBlock(
|
||||
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.OnClicked = StartButtonClicked;
|
||||
|
||||
@@ -46,14 +46,14 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
levelStartTickBox = new GUITickBox(
|
||||
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);
|
||||
levelStartTickBox.Enabled = false;
|
||||
levelStartTickBox.OnSelected = SelectDestination;
|
||||
|
||||
levelEndTickBox = new GUITickBox(
|
||||
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);
|
||||
levelEndTickBox.Enabled = false;
|
||||
levelEndTickBox.OnSelected = SelectDestination;
|
||||
|
||||
@@ -34,16 +34,19 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
Wire equippedWire = null;
|
||||
|
||||
//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++)
|
||||
if (!panel.Locked || Screen.Selected == GameMain.SubEditorScreen)
|
||||
{
|
||||
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>();
|
||||
if (wireComponent != null) equippedWire = wireComponent;
|
||||
Wire wireComponent = selectedItem.GetComponent<Wire>();
|
||||
if (wireComponent != null) equippedWire = wireComponent;
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
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),
|
||||
rightWirePos,
|
||||
mouseInRect, equippedWire,
|
||||
@@ -82,7 +85,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
else
|
||||
{
|
||||
c.Draw(spriteBatch, panel.Item, leftPos,
|
||||
c.Draw(spriteBatch, panel, leftPos,
|
||||
new Vector2(leftPos.X + 20, leftPos.Y - 12),
|
||||
leftWirePos,
|
||||
mouseInRect, equippedWire,
|
||||
@@ -96,7 +99,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
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())
|
||||
{
|
||||
@@ -121,7 +124,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
DrawWire(spriteBatch, equippedWire, equippedWire.Item,
|
||||
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;
|
||||
}
|
||||
@@ -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);
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -165,9 +168,9 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
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))
|
||||
{
|
||||
@@ -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)
|
||||
{
|
||||
@@ -225,7 +228,7 @@ namespace Barotrauma.Items.Components
|
||||
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));
|
||||
|
||||
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,
|
||||
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;
|
||||
|
||||
if (!wire.Locked)
|
||||
if (!wire.Locked && (!panel.Locked || Screen.Selected == GameMain.SubEditorScreen))
|
||||
{
|
||||
//start dragging the wire
|
||||
if (PlayerInput.LeftButtonHeld()) draggingConnected = wire;
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
using Barotrauma.Networking;
|
||||
using Lidgren.Network;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
@@ -24,5 +28,66 @@ namespace Barotrauma.Items.Components
|
||||
HighlightedWire = null;
|
||||
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;
|
||||
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);
|
||||
@@ -76,7 +83,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
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)
|
||||
|
||||
@@ -148,8 +148,10 @@ namespace Barotrauma.Items.Components
|
||||
public void ClientRead(ServerNetObject type, NetBuffer msg, float sendingTime)
|
||||
{
|
||||
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)
|
||||
{
|
||||
DebugConsole.ThrowError("Failed to launch a projectile - item with the ID \"" + projectileID + " not found");
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using Barotrauma.Networking;
|
||||
using FarseerPhysics;
|
||||
using FarseerPhysics.Collision;
|
||||
using FarseerPhysics.Dynamics;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
|
||||
@@ -58,6 +61,43 @@ namespace Barotrauma.Items.Components
|
||||
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.Networking;
|
||||
using Lidgren.Network;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
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());
|
||||
}
|
||||
|
||||
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);
|
||||
break;
|
||||
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;
|
||||
case NetEntityEvent.Type.Status:
|
||||
condition = msg.ReadRangedSingle(0.0f, prefab.Health, 8);
|
||||
|
||||
condition = msg.ReadSingle();
|
||||
if (FixRequirements.Count > 0)
|
||||
{
|
||||
if (Condition <= 0.0f)
|
||||
@@ -401,10 +401,13 @@ namespace Barotrauma
|
||||
ushort targetID = msg.ReadUInt16();
|
||||
|
||||
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;
|
||||
case NetEntityEvent.Type.ChangeProperty:
|
||||
ReadPropertyChange(msg);
|
||||
ReadPropertyChange(msg, false);
|
||||
break;
|
||||
case NetEntityEvent.Type.Invalid:
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -423,11 +426,12 @@ namespace Barotrauma
|
||||
case NetEntityEvent.Type.ComponentState:
|
||||
int componentIndex = (int)extraData[1];
|
||||
msg.WriteRangedInteger(0, components.Count - 1, componentIndex);
|
||||
|
||||
(components[componentIndex] as IClientSerializable).ClientWrite(msg, extraData);
|
||||
break;
|
||||
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;
|
||||
case NetEntityEvent.Type.Repair:
|
||||
if (FixRequirements.Count > 0)
|
||||
@@ -441,7 +445,7 @@ namespace Barotrauma
|
||||
//on the character of the client who sent the message
|
||||
break;
|
||||
case NetEntityEvent.Type.ChangeProperty:
|
||||
WritePropertyChange(msg, extraData);
|
||||
WritePropertyChange(msg, extraData, true);
|
||||
break;
|
||||
}
|
||||
msg.WritePadBits();
|
||||
@@ -453,7 +457,7 @@ namespace Barotrauma
|
||||
float newRotation = msg.ReadRangedSingle(0.0f, MathHelper.TwoPi, 7);
|
||||
bool awake = msg.ReadBoolean();
|
||||
Vector2 newVelocity = Vector2.Zero;
|
||||
|
||||
|
||||
if (awake)
|
||||
{
|
||||
newVelocity = new Vector2(
|
||||
@@ -461,6 +465,19 @@ namespace Barotrauma
|
||||
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)
|
||||
{
|
||||
DebugConsole.ThrowError("Received a position update for an item with no physics body (" + Name + ")");
|
||||
@@ -470,7 +487,7 @@ namespace Barotrauma
|
||||
body.FarseerBody.Awake = 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
|
||||
{
|
||||
@@ -490,11 +507,12 @@ namespace Barotrauma
|
||||
|
||||
if ((newPosition - SimPosition).Length() > body.LinearVelocity.Length() * 2.0f)
|
||||
{
|
||||
body.SetTransform(newPosition, newRotation);
|
||||
|
||||
Vector2 displayPos = ConvertUnits.ToDisplayUnits(body.SimPosition);
|
||||
rect.X = (int)(displayPos.X - rect.Width / 2.0f);
|
||||
rect.Y = (int)(displayPos.Y + rect.Height / 2.0f);
|
||||
if (body.SetTransform(newPosition, newRotation))
|
||||
{
|
||||
Vector2 displayPos = ConvertUnits.ToDisplayUnits(body.SimPosition);
|
||||
rect.X = (int)(displayPos.X - rect.Width / 2.0f);
|
||||
rect.Y = (int)(displayPos.Y + rect.Height / 2.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace Barotrauma
|
||||
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;
|
||||
|
||||
@@ -80,6 +80,10 @@ namespace Barotrauma
|
||||
#if DEBUG
|
||||
DebugConsole.ThrowError("Invalid left normal");
|
||||
#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)
|
||||
{
|
||||
GameMain.World.RemoveBody(cell.body);
|
||||
@@ -106,6 +110,10 @@ namespace Barotrauma
|
||||
#if DEBUG
|
||||
DebugConsole.ThrowError("Invalid right normal");
|
||||
#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)
|
||||
{
|
||||
GameMain.World.RemoveBody(cell.body);
|
||||
|
||||
@@ -27,10 +27,17 @@ namespace Barotrauma
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
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 FarseerPhysics;
|
||||
using Lidgren.Network;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
@@ -145,7 +146,7 @@ namespace Barotrauma
|
||||
"", frame, GUI.SmallFont);
|
||||
|
||||
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);
|
||||
|
||||
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"));
|
||||
}
|
||||
@@ -216,6 +217,33 @@ 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 (type == ChatMessageType.MessageBox)
|
||||
switch (type)
|
||||
{
|
||||
new GUIMessageBox("", txt);
|
||||
}
|
||||
else if (type == ChatMessageType.Console)
|
||||
{
|
||||
DebugConsole.NewMessage(txt, MessageColor[(int)ChatMessageType.Console]);
|
||||
}
|
||||
else
|
||||
{
|
||||
GameMain.Client.AddChatMessage(txt, type, senderName, senderCharacter);
|
||||
case ChatMessageType.MessageBox:
|
||||
new GUIMessageBox("", txt);
|
||||
break;
|
||||
case ChatMessageType.Console:
|
||||
DebugConsole.NewMessage(txt, MessageColor[(int)ChatMessageType.Console]);
|
||||
break;
|
||||
case ChatMessageType.ServerLog:
|
||||
if (!Enum.TryParse(senderName, out ServerLog.MessageType messageType))
|
||||
{
|
||||
return;
|
||||
}
|
||||
GameMain.Client.ServerLog?.WriteLine(txt, messageType);
|
||||
break;
|
||||
default:
|
||||
GameMain.Client.AddChatMessage(txt, type, senderName, senderCharacter);
|
||||
break;
|
||||
}
|
||||
|
||||
LastID = ID;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,6 +44,9 @@ namespace Barotrauma.Networking
|
||||
|
||||
private FileReceiver fileReceiver;
|
||||
|
||||
//has the client been given a character to control this round
|
||||
public bool HasSpawned;
|
||||
|
||||
public byte ID
|
||||
{
|
||||
get { return myID; }
|
||||
@@ -61,6 +64,17 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
get { return fileReceiver; }
|
||||
}
|
||||
|
||||
public bool MidRoundSyncing
|
||||
{
|
||||
get { return entityEventManager.MidRoundSyncing; }
|
||||
}
|
||||
|
||||
public bool AllowDisguises
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public GameClient(string newName)
|
||||
{
|
||||
@@ -99,6 +113,8 @@ namespace Barotrauma.Networking
|
||||
|
||||
otherClients = new List<Client>();
|
||||
|
||||
ServerLog = new ServerLog("");
|
||||
|
||||
ChatMessage.LastID = 0;
|
||||
GameMain.NetLobbyScreen = new NetLobbyScreen();
|
||||
}
|
||||
@@ -456,6 +472,9 @@ namespace Barotrauma.Networking
|
||||
#if DEBUG
|
||||
if (PlayerInput.GetKeyboardState.IsKeyDown(Microsoft.Xna.Framework.Input.Keys.P)) return;
|
||||
#endif
|
||||
#if CLIENT
|
||||
if (ServerLog.LogFrame != null) ServerLog.LogFrame.Update(deltaTime);
|
||||
#endif
|
||||
|
||||
base.Update(deltaTime);
|
||||
|
||||
@@ -480,7 +499,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
if (gameStarted && Screen.Selected == GameMain.GameScreen)
|
||||
{
|
||||
endVoteTickBox.Visible = Voting.AllowEndVoting && myCharacter != null;
|
||||
endVoteTickBox.Visible = Voting.AllowEndVoting && HasSpawned;
|
||||
|
||||
if (respawnManager != null)
|
||||
{
|
||||
@@ -656,9 +675,11 @@ namespace Barotrauma.Networking
|
||||
new GUITextBlock(new Rectangle(0, 0, 0, 15), permittedCommand, "", commandList, GUI.SmallFont).CanBeFocused = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
GameMain.NetLobbyScreen.SubList.Enabled = Voting.AllowSubVoting || HasPermission(ClientPermissions.SelectSub);
|
||||
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);
|
||||
}
|
||||
@@ -666,6 +687,7 @@ namespace Barotrauma.Networking
|
||||
private IEnumerable<object> StartGame(NetIncomingMessage inc)
|
||||
{
|
||||
if (Character != null) Character.Remove();
|
||||
HasSpawned = false;
|
||||
|
||||
GameMain.LightManager.LightingEnabled = true;
|
||||
|
||||
@@ -696,6 +718,7 @@ namespace Barotrauma.Networking
|
||||
bool respawnAllowed = inc.ReadBoolean();
|
||||
bool loadSecondSub = inc.ReadBoolean();
|
||||
|
||||
bool disguisesAllowed = inc.ReadBoolean();
|
||||
bool isTraitor = inc.ReadBoolean();
|
||||
string traitorTargetName = isTraitor ? inc.ReadString() : null;
|
||||
|
||||
@@ -734,6 +757,8 @@ namespace Barotrauma.Networking
|
||||
|
||||
GameMain.NetLobbyScreen.UsingShuttle = usingShuttle;
|
||||
|
||||
AllowDisguises = disguisesAllowed;
|
||||
|
||||
if (campaign == null)
|
||||
{
|
||||
if (!GameMain.NetLobbyScreen.TrySelectSub(subName, subHash, GameMain.NetLobbyScreen.SubList))
|
||||
@@ -757,7 +782,10 @@ namespace Barotrauma.Networking
|
||||
else
|
||||
{
|
||||
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);
|
||||
@@ -815,7 +843,7 @@ namespace Barotrauma.Networking
|
||||
string subName = 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)
|
||||
{
|
||||
submarines.Add(matchingSub);
|
||||
@@ -908,6 +936,8 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
GameMain.NetLobbyScreen.LastUpdateID = updateID;
|
||||
|
||||
ServerLog.ServerName = serverName;
|
||||
|
||||
GameMain.NetLobbyScreen.ServerName = serverName;
|
||||
GameMain.NetLobbyScreen.ServerMessage.Text = serverText;
|
||||
|
||||
@@ -982,6 +1012,9 @@ namespace Barotrauma.Networking
|
||||
long prevBitPos = 0;
|
||||
long prevBytePos = 0;
|
||||
|
||||
long prevBitLength = 0;
|
||||
long prevByteLength = 0;
|
||||
|
||||
ServerNetObject objHeader;
|
||||
while ((objHeader = (ServerNetObject)inc.ReadByte()) != ServerNetObject.END_OF_MESSAGE)
|
||||
{
|
||||
@@ -1016,41 +1049,53 @@ namespace Barotrauma.Networking
|
||||
ChatMessage.ClientRead(inc);
|
||||
break;
|
||||
default:
|
||||
DebugConsole.ThrowError("Error while reading update from server (unknown object header \""+objHeader+"\"!)");
|
||||
if (prevObjHeader != null)
|
||||
List<string> errorLines = new List<string>
|
||||
{
|
||||
DebugConsole.ThrowError("Previous object type: " + prevObjHeader.ToString());
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugConsole.ThrowError("Error occurred on the very first object!");
|
||||
}
|
||||
DebugConsole.ThrowError("Previous object was " + (inc.Position - prevBitPos) + " bits long (" + (inc.PositionInBytes - prevBytePos) + " bytes)");
|
||||
"Error while reading update from server (unknown object header \"" + objHeader + "\"!)",
|
||||
"Message length: " + inc.LengthBits + " (" + inc.LengthBytes + " bytes)",
|
||||
prevObjHeader != null ? "Previous object type: " + prevObjHeader.ToString() : "Error occurred on the very first object!",
|
||||
"Previous object was " + (prevBitLength) + " bits long (" + (prevByteLength) + " bytes)"
|
||||
};
|
||||
if (prevObjHeader == ServerNetObject.ENTITY_EVENT || prevObjHeader == ServerNetObject.ENTITY_EVENT_INITIAL)
|
||||
{
|
||||
foreach (IServerSerializable ent in entities)
|
||||
{
|
||||
if (ent == null)
|
||||
{
|
||||
DebugConsole.ThrowError(" - NULL");
|
||||
errorLines.Add(" - NULL");
|
||||
continue;
|
||||
}
|
||||
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");
|
||||
|
||||
FileStream fl = File.Open("crashreport_object.bin", FileMode.Create);
|
||||
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();
|
||||
fl.Close();
|
||||
|
||||
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;
|
||||
prevBitPos = inc.Position;
|
||||
prevBytePos = inc.PositionInBytes;
|
||||
@@ -1181,8 +1226,12 @@ namespace Barotrauma.Networking
|
||||
case FileTransferType.Submarine:
|
||||
new GUIMessageBox("Download finished", "File \"" + transfer.FileName + "\" was downloaded succesfully.");
|
||||
var newSub = new Submarine(transfer.FilePath);
|
||||
Submarine.SavedSubmarines.RemoveAll(s => s.Name == newSub.Name && s.MD5Hash.Hash == newSub.MD5Hash.Hash);
|
||||
Submarine.SavedSubmarines.Add(newSub);
|
||||
var existingSubs = Submarine.SavedSubmarines.Where(s => s.Name == newSub.Name && s.MD5Hash.Hash == newSub.MD5Hash.Hash).ToList();
|
||||
foreach (Submarine existingSub in existingSubs)
|
||||
{
|
||||
existingSub.Dispose();
|
||||
}
|
||||
Submarine.AddToSavedSubs(newSub);
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
@@ -1277,6 +1326,23 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
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)
|
||||
{
|
||||
Vector2 pos = new Vector2(GameMain.NetLobbyScreen.InfoFrame.Rect.X, GameMain.GraphicsHeight - 35);
|
||||
@@ -1341,6 +1407,17 @@ namespace Barotrauma.Networking
|
||||
public override void Disconnect()
|
||||
{
|
||||
client.Shutdown("");
|
||||
|
||||
foreach (var fileTransfer in FileReceiver.ActiveTransfers)
|
||||
{
|
||||
fileTransfer.Dispose();
|
||||
}
|
||||
|
||||
if (HasPermission(ClientPermissions.ServerLog))
|
||||
{
|
||||
ServerLog?.Save();
|
||||
}
|
||||
|
||||
GameMain.NetworkMember = null;
|
||||
}
|
||||
|
||||
@@ -1560,14 +1637,13 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
if (!gameStarted) return false;
|
||||
|
||||
if (!Voting.AllowEndVoting || myCharacter==null)
|
||||
if (!Voting.AllowEndVoting || !HasSpawned)
|
||||
{
|
||||
tickBox.Visible = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
Vote(VoteType.EndRound, tickBox.Selected);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,45 +9,22 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
private NetStats netStats;
|
||||
|
||||
private GUIButton showLogButton;
|
||||
|
||||
private GUIScrollBar clientListScrollBar;
|
||||
|
||||
void InitProjSpecific()
|
||||
{
|
||||
//----------------------------------------
|
||||
|
||||
var endRoundButton = new GUIButton(new Rectangle(GameMain.GraphicsWidth - 170, 20, 150, 20), "End round", Alignment.TopLeft, "", inGameHUD);
|
||||
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);
|
||||
settingsButton.OnClicked = ToggleSettingsFrame;
|
||||
settingsButton.UserData = "settingsButton";
|
||||
|
||||
//----------------------------------------
|
||||
}
|
||||
|
||||
public override void AddToGUIUpdateList()
|
||||
{
|
||||
if (started) base.AddToGUIUpdateList();
|
||||
|
||||
base.AddToGUIUpdateList();
|
||||
if (settingsFrame != null) settingsFrame.AddToGUIUpdateList();
|
||||
if (log.LogFrame != null) log.LogFrame.AddToGUIUpdateList();
|
||||
}
|
||||
|
||||
public override void Draw(Microsoft.Xna.Framework.Graphics.SpriteBatch spriteBatch)
|
||||
@@ -58,9 +35,18 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
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;
|
||||
|
||||
@@ -23,6 +23,11 @@ namespace Barotrauma.Networking
|
||||
|
||||
private UInt16 lastReceivedID;
|
||||
|
||||
public bool MidRoundSyncing
|
||||
{
|
||||
get { return firstNewID.HasValue; }
|
||||
}
|
||||
|
||||
public ClientEntityEventManager(GameClient client)
|
||||
{
|
||||
events = new List<ClientEntityEvent>();
|
||||
@@ -140,7 +145,13 @@ namespace Barotrauma.Networking
|
||||
|
||||
if (entityID == 0)
|
||||
{
|
||||
if (GameSettings.VerboseLogging)
|
||||
{
|
||||
DebugConsole.NewMessage("received msg " + thisEventID + " (null entity)",
|
||||
Microsoft.Xna.Framework.Color.Orange);
|
||||
}
|
||||
msg.ReadPadBits();
|
||||
entities.Add(null);
|
||||
if (thisEventID == (UInt16)(lastReceivedID + 1)) lastReceivedID++;
|
||||
continue;
|
||||
}
|
||||
@@ -153,23 +164,24 @@ namespace Barotrauma.Networking
|
||||
//skip the event if we've already received it or if the entity isn't found
|
||||
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(
|
||||
"received msg " + thisEventID + " (waiting for " + (lastReceivedID + 1) + ")",
|
||||
"Received msg " + thisEventID + " (waiting for " + (lastReceivedID + 1) + ")",
|
||||
thisEventID < lastReceivedID + 1
|
||||
? Microsoft.Xna.Framework.Color.Yellow
|
||||
: 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;
|
||||
}
|
||||
else
|
||||
@@ -188,10 +200,19 @@ namespace Barotrauma.Networking
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ namespace Barotrauma.Networking
|
||||
protected GUIFrame inGameHUD;
|
||||
protected GUIListBox chatBox;
|
||||
protected GUITextBox chatMsgBox;
|
||||
protected GUIButton showLogButton;
|
||||
|
||||
public GUIFrame InGameHUD
|
||||
{
|
||||
@@ -35,6 +36,23 @@ namespace Barotrauma.Networking
|
||||
inGameHUD = new GUIFrame(new Rectangle(0, 0, 0, 0), null, null);
|
||||
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 height = (int)MathHelper.Clamp(GameMain.GraphicsHeight * 0.15f, 100, 200);
|
||||
chatBox = new GUIListBox(new Rectangle(
|
||||
@@ -109,53 +127,44 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
inGameHUD.AddToGUIUpdateList();
|
||||
}
|
||||
if (ServerLog.LogFrame != null) ServerLog.LogFrame.AddToGUIUpdateList();
|
||||
}
|
||||
|
||||
public virtual void Draw(Microsoft.Xna.Framework.Graphics.SpriteBatch spriteBatch)
|
||||
{
|
||||
if (!gameStarted || Screen.Selected != GameMain.GameScreen || GUI.DisableHUD) return;
|
||||
|
||||
GameMain.GameSession.CrewManager.Draw(spriteBatch);
|
||||
|
||||
inGameHUD.Draw(spriteBatch);
|
||||
|
||||
if (EndVoteCount > 0)
|
||||
if (GUI.DisableHUD) return;
|
||||
|
||||
if (gameStarted && Screen.Selected == GameMain.GameScreen)
|
||||
{
|
||||
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),
|
||||
"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);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (respawnManager != null)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ServerLog.LogFrame?.Draw(spriteBatch);
|
||||
}
|
||||
|
||||
public virtual bool SelectCrewCharacter(Character character, GUIComponent characterFrame)
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using Lidgren.Network;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -151,7 +152,12 @@ namespace Barotrauma
|
||||
{
|
||||
int votes = inc.ReadByte();
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,7 +203,7 @@ namespace Barotrauma
|
||||
if (GameSettings.SendUserStatistics)
|
||||
{
|
||||
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();
|
||||
}
|
||||
else
|
||||
|
||||
@@ -57,6 +57,14 @@ namespace Barotrauma
|
||||
|
||||
Submarine selectedSub = subList.SelectedData as Submarine;
|
||||
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);
|
||||
if (selectedSub.HasTag(SubmarineTag.Shuttle) || !selectedSub.CompatibleContentPackages.Contains(GameMain.SelectedPackage.Name))
|
||||
@@ -144,7 +152,7 @@ namespace Barotrauma
|
||||
return true;
|
||||
};
|
||||
}
|
||||
if (Submarine.SavedSubmarines.Count > 0) subList.Select(Submarine.SavedSubmarines[0]);
|
||||
if (Submarine.SavedSubmarines.Any()) subList.Select(Submarine.SavedSubmarines.First());
|
||||
}
|
||||
|
||||
public void UpdateLoadMenu()
|
||||
|
||||
@@ -85,7 +85,7 @@ namespace Barotrauma
|
||||
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.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.OnSelected = BuyItem;
|
||||
@@ -149,6 +149,8 @@ namespace Barotrauma
|
||||
null, null,
|
||||
Alignment.TopRight, "", frame);
|
||||
}
|
||||
|
||||
RefreshItemTab();
|
||||
}
|
||||
|
||||
public void Update(float deltaTime)
|
||||
@@ -216,55 +218,92 @@ namespace Barotrauma
|
||||
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);
|
||||
frame.UserData = ep;
|
||||
frame.UserData = pi;
|
||||
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;
|
||||
|
||||
GUITextBlock textBlock = new GUITextBlock(
|
||||
new Rectangle(50, 0, 0, 25),
|
||||
ep.Name,
|
||||
pi.itemPrefab.Name,
|
||||
null, null,
|
||||
Alignment.Left, Alignment.CenterX | Alignment.Left,
|
||||
"", frame);
|
||||
textBlock.Font = font;
|
||||
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);
|
||||
img.Color = ep.SpriteColor;
|
||||
GUIImage img = new GUIImage(new Rectangle(0, 0, 40, 40), pi.itemPrefab.sprite, Alignment.CenterLeft, frame);
|
||||
img.Color = pi.itemPrefab.SpriteColor;
|
||||
img.Scale = Math.Min(Math.Min(40.0f / img.SourceRect.Width, 40.0f / img.SourceRect.Height), 1.0f);
|
||||
}
|
||||
|
||||
textBlock = new GUITextBlock(
|
||||
new Rectangle(width - 80, 0, 80, 25),
|
||||
ep.Price.ToString(),
|
||||
new Rectangle(width - 160, 0, 80, 25),
|
||||
pi.itemPrefab.Price.ToString(),
|
||||
null, null, Alignment.TopLeft,
|
||||
Alignment.TopLeft, "", frame);
|
||||
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)
|
||||
{
|
||||
ItemPrefab prefab = obj as ItemPrefab;
|
||||
if (prefab == null) return false;
|
||||
PurchasedItem pi = obj as PurchasedItem;
|
||||
if (pi == null || pi.itemPrefab == null) return false;
|
||||
|
||||
if (GameMain.Client != null && !GameMain.Client.HasPermission(Networking.ClientPermissions.ManageCampaign))
|
||||
{
|
||||
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();
|
||||
|
||||
return false;
|
||||
@@ -272,15 +311,15 @@ namespace Barotrauma
|
||||
|
||||
private bool SellItem(GUIComponent component, object obj)
|
||||
{
|
||||
ItemPrefab prefab = obj as ItemPrefab;
|
||||
if (prefab == null) return false;
|
||||
PurchasedItem pi = obj as PurchasedItem;
|
||||
if (pi == null || pi.itemPrefab == null) return false;
|
||||
|
||||
if (GameMain.Client != null && !GameMain.Client.HasPermission(Networking.ClientPermissions.ManageCampaign))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
campaign.CargoManager.SellItem(prefab);
|
||||
campaign.CargoManager.SellItem(pi.itemPrefab,1);
|
||||
GameMain.Client?.SendCampaignState();
|
||||
|
||||
return false;
|
||||
@@ -289,10 +328,13 @@ namespace Barotrauma
|
||||
private void RefreshItemTab()
|
||||
{
|
||||
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)
|
||||
@@ -311,16 +353,16 @@ namespace Barotrauma
|
||||
storeItemList.ClearChildren();
|
||||
|
||||
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;
|
||||
|
||||
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)
|
||||
{
|
||||
|
||||
@@ -244,13 +244,12 @@ namespace Barotrauma
|
||||
GameMain.LightManager.LosEffect.Parameters["xTexture"].SetValue(renderTargetBackground);
|
||||
GameMain.LightManager.LosEffect.Parameters["xLosTexture"].SetValue(GameMain.LightManager.losTexture);
|
||||
#endif
|
||||
|
||||
|
||||
//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
|
||||
//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
|
||||
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();
|
||||
losColorHls.Y = 0.1f;
|
||||
losColorHls.Y = ambientLightHls.Y;
|
||||
Color losColor = ToolBox.HLSToRGB(losColorHls);
|
||||
|
||||
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;
|
||||
|
||||
campaign.Map.SelectLocation(-1);
|
||||
|
||||
bottomPanel.ClearChildren();
|
||||
campaignUI = new CampaignUI(campaign, bottomPanel);
|
||||
campaignUI.StartRound = StartRound;
|
||||
campaignUI.OnLocationSelected = SelectLocation;
|
||||
campaignUI.OnLocationSelected = SelectLocation;
|
||||
campaignUI.UpdateCharacterLists();
|
||||
|
||||
if (GameSettings.SendUserStatistics) GameAnalyticsSDK.Net.GameAnalytics.SetCustomDimension01("singleplayer");
|
||||
GameAnalyticsManager.SetCustomDimension01("singleplayer");
|
||||
}
|
||||
|
||||
public override void AddToGUIUpdateList()
|
||||
@@ -190,7 +192,10 @@ namespace Barotrauma
|
||||
|
||||
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();
|
||||
|
||||
yield return CoroutineStatus.Success;
|
||||
|
||||
@@ -143,7 +143,7 @@ namespace Barotrauma
|
||||
|
||||
SelectTab(null, 0);
|
||||
|
||||
if (GameSettings.SendUserStatistics) GameAnalyticsSDK.Net.GameAnalytics.SetCustomDimension01("");
|
||||
GameAnalyticsManager.SetCustomDimension01("");
|
||||
}
|
||||
|
||||
public bool SelectTab(GUIButton button, object obj)
|
||||
@@ -368,7 +368,19 @@ namespace Barotrauma
|
||||
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"), "");
|
||||
|
||||
|
||||
@@ -177,7 +177,7 @@ namespace Barotrauma
|
||||
if (levelSeed == value) return;
|
||||
|
||||
levelSeed = value;
|
||||
backgroundSprite = LocationType.Random(levelSeed).Background;
|
||||
backgroundSprite = LocationType.Random(levelSeed)?.Background;
|
||||
seedBox.Text = levelSeed;
|
||||
}
|
||||
}
|
||||
@@ -379,13 +379,13 @@ namespace Barotrauma
|
||||
showLogButton.UserData = "showlog";
|
||||
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
|
||||
{
|
||||
GameMain.Server.ServerLog.LogFrame = null;
|
||||
GameMain.NetworkMember.ServerLog.LogFrame = null;
|
||||
GUIComponent.KeyboardDispatcher.Subscriber = null;
|
||||
}
|
||||
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 == "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)
|
||||
{
|
||||
@@ -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);
|
||||
|
||||
@@ -737,8 +739,21 @@ namespace Barotrauma
|
||||
//hash will be null if opening the sub file failed -> don't select the sub
|
||||
if (string.IsNullOrWhiteSpace(hash))
|
||||
{
|
||||
(component as GUITextBlock).TextColor = Color.DarkRed * 0.8f;
|
||||
component.CanBeFocused = false;
|
||||
GUITextBlock submarineTextBlock = component.GetChild<GUITextBlock>();
|
||||
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;
|
||||
|
||||
@@ -782,8 +797,8 @@ namespace Barotrauma
|
||||
CanBeFocused = false
|
||||
};
|
||||
|
||||
var matchingSub = Submarine.SavedSubmarines.Find(s => s.Name == sub.Name && s.MD5Hash.Hash == sub.MD5Hash.Hash);
|
||||
if (matchingSub == null) matchingSub = Submarine.SavedSubmarines.Find(s => s.Name == sub.Name);
|
||||
var matchingSub = Submarine.SavedSubmarines.FirstOrDefault(s => s.Name == sub.Name && s.MD5Hash.Hash == sub.MD5Hash.Hash);
|
||||
if (matchingSub == null) matchingSub = Submarine.SavedSubmarines.FirstOrDefault(s => s.Name == sub.Name);
|
||||
|
||||
if (matchingSub == null)
|
||||
{
|
||||
@@ -1467,8 +1482,8 @@ namespace Barotrauma
|
||||
return false;
|
||||
}
|
||||
|
||||
Submarine sub = Submarine.SavedSubmarines.Find(m => m.Name == subName && m.MD5Hash.Hash == md5Hash);
|
||||
if (sub == null) sub = Submarine.SavedSubmarines.Find(m => m.Name == subName);
|
||||
Submarine sub = Submarine.SavedSubmarines.FirstOrDefault(m => m.Name == subName && m.MD5Hash.Hash == md5Hash);
|
||||
if (sub == null) sub = Submarine.SavedSubmarines.FirstOrDefault(m => m.Name == subName);
|
||||
|
||||
var matchingListSub = subList.children.Find(c => c.UserData == sub);
|
||||
if (matchingListSub != null)
|
||||
@@ -1520,7 +1535,7 @@ namespace Barotrauma
|
||||
requestFileBox.Buttons[0].OnClicked += (GUIButton button, object 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;
|
||||
};
|
||||
requestFileBox.Buttons[1].OnClicked += requestFileBox.Close;
|
||||
|
||||
@@ -15,9 +15,9 @@ namespace Barotrauma
|
||||
{
|
||||
private static string[] crewExperienceLevels = new string[]
|
||||
{
|
||||
TextManager.Get("CrewExperienceLow"),
|
||||
TextManager.Get("CrewExperienceMid"),
|
||||
TextManager.Get("CrewExperienceHigh")
|
||||
"CrewExperienceLow",
|
||||
"CrewExperienceMid",
|
||||
"CrewExperienceHigh"
|
||||
};
|
||||
|
||||
private Camera cam;
|
||||
@@ -349,7 +349,7 @@ namespace Barotrauma
|
||||
|
||||
cam.UpdateTransform();
|
||||
|
||||
if (GameSettings.SendUserStatistics) GameAnalyticsSDK.Net.GameAnalytics.SetCustomDimension01("editor");
|
||||
GameAnalyticsManager.SetCustomDimension01("editor");
|
||||
}
|
||||
|
||||
public override void Deselect()
|
||||
@@ -587,23 +587,26 @@ namespace Barotrauma
|
||||
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);
|
||||
|
||||
|
||||
toggleExpLeft.OnClicked += (btn, userData) =>
|
||||
{
|
||||
int currentIndex = Array.IndexOf(crewExperienceLevels, experienceText.Text);
|
||||
int currentIndex = Array.IndexOf(crewExperienceLevels, (string)experienceText.UserData);
|
||||
currentIndex--;
|
||||
if (currentIndex < 0) currentIndex = crewExperienceLevels.Length - 1;
|
||||
experienceText.Text = crewExperienceLevels[currentIndex];
|
||||
Submarine.MainSub.RecommendedCrewExperience = experienceText.Text;
|
||||
experienceText.UserData = crewExperienceLevels[currentIndex];
|
||||
experienceText.Text = TextManager.Get(crewExperienceLevels[currentIndex]);
|
||||
Submarine.MainSub.RecommendedCrewExperience = (string)experienceText.UserData;
|
||||
return true;
|
||||
};
|
||||
|
||||
toggleExpRight.OnClicked += (btn, userData) =>
|
||||
{
|
||||
int currentIndex = Array.IndexOf(crewExperienceLevels, experienceText.Text);
|
||||
int currentIndex = Array.IndexOf(crewExperienceLevels, (string)experienceText.UserData);
|
||||
currentIndex++;
|
||||
if (currentIndex >= crewExperienceLevels.Length) currentIndex = 0;
|
||||
experienceText.Text = crewExperienceLevels[currentIndex];
|
||||
Submarine.MainSub.RecommendedCrewExperience = experienceText.Text;
|
||||
experienceText.UserData = crewExperienceLevels[currentIndex];
|
||||
experienceText.Text = TextManager.Get(crewExperienceLevels[currentIndex]);
|
||||
Submarine.MainSub.RecommendedCrewExperience = (string)experienceText.UserData;
|
||||
return true;
|
||||
};
|
||||
|
||||
@@ -613,8 +616,9 @@ namespace Barotrauma
|
||||
int max = Submarine.MainSub.RecommendedCrewSizeMax;
|
||||
crewSizeMin.IntValue = min;
|
||||
crewSizeMax.IntValue = max;
|
||||
experienceText.Text = string.IsNullOrEmpty(Submarine.MainSub.RecommendedCrewExperience) ?
|
||||
experienceText.UserData = string.IsNullOrEmpty(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);
|
||||
@@ -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];
|
||||
max = wallPoints[0];
|
||||
for (int i = 0; i < wallPoints.Count; i++)
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace Barotrauma.Sounds
|
||||
|
||||
using (VorbisReader reader = new VorbisReader(oggFile))
|
||||
{
|
||||
int bufferSize = (int)reader.TotalSamples;
|
||||
int bufferSize = (int)reader.TotalSamples * reader.Channels;
|
||||
|
||||
float[] buffer = new float[bufferSize];
|
||||
sound.castBuffer = new short[bufferSize];
|
||||
@@ -52,11 +52,13 @@ namespace Barotrauma.Sounds
|
||||
sound.format = reader.Channels == 1 ? ALFormat.Mono16 : ALFormat.Stereo16;
|
||||
sound.sampleRate = reader.SampleRate;
|
||||
|
||||
ALHelper.Check();
|
||||
|
||||
//alSourceId = AL.GenSource();
|
||||
AL.BufferData(sound.alBufferId, reader.Channels == 1 ? ALFormat.Mono16 : ALFormat.Stereo16, sound.castBuffer,
|
||||
readSamples * sizeof(short), reader.SampleRate);
|
||||
|
||||
ALHelper.Check();
|
||||
ALHelper.Check(oggFile);
|
||||
}
|
||||
|
||||
//AL.Source(alSourceId, ALSourcei.Buffer, alBufferId);
|
||||
@@ -100,12 +102,12 @@ namespace Barotrauma.Sounds
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
//var state = AL.GetSourceState(alSourceId);
|
||||
//if (state == ALSourceState.Playing || state == ALSourceState.Paused)
|
||||
// Stop();
|
||||
System.Diagnostics.Debug.WriteLine(alBufferId);
|
||||
//AL.DeleteSource(alSourceId);
|
||||
AL.DeleteBuffer(alBufferId);
|
||||
if (alBufferId > 0)
|
||||
{
|
||||
AL.DeleteBuffer(alBufferId);
|
||||
alBufferId = 0;
|
||||
}
|
||||
|
||||
//if (ALHelper.Efx.IsInitialized)
|
||||
// ALHelper.Efx.DeleteFilter(alFilterId);
|
||||
|
||||
@@ -45,16 +45,24 @@ namespace Barotrauma.Sounds
|
||||
//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;
|
||||
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
|
||||
DebugConsole.ThrowError("OpenAL error: " + AL.GetErrorString(error) + "\n" + Environment.StackTrace);
|
||||
DebugConsole.ThrowError(errorMsg);
|
||||
#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
|
||||
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;
|
||||
#endif
|
||||
|
||||
public OggStream(string filename, int bufferCount = DefaultBufferCount) : this(File.OpenRead(filename), bufferCount) { }
|
||||
public OggStream(Stream stream, int bufferCount = DefaultBufferCount)
|
||||
public string FileName
|
||||
{
|
||||
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;
|
||||
|
||||
alBufferIds = AL.GenBuffers(bufferCount);
|
||||
@@ -94,7 +110,7 @@ namespace Barotrauma.Sounds
|
||||
if (ALHelper.XRam.IsInitialized)
|
||||
{
|
||||
ALHelper.XRam.SetBufferMode(BufferCount, ref alBufferIds[0], XRamExtension.XRamStorage.Hardware);
|
||||
ALHelper.Check();
|
||||
ALHelper.Check(fileName);
|
||||
}
|
||||
|
||||
if (ALHelper.Efx.IsInitialized)
|
||||
@@ -163,7 +179,7 @@ namespace Barotrauma.Sounds
|
||||
|
||||
AL.SourcePlay(alSourceId);
|
||||
this.Volume = volume;
|
||||
ALHelper.Check();
|
||||
ALHelper.Check(FileName);
|
||||
|
||||
Preparing = false;
|
||||
|
||||
@@ -177,7 +193,7 @@ namespace Barotrauma.Sounds
|
||||
|
||||
OggStreamer.Instance.RemoveStream(this);
|
||||
AL.SourcePause(alSourceId);
|
||||
ALHelper.Check();
|
||||
ALHelper.Check(FileName);
|
||||
}
|
||||
|
||||
public void Resume()
|
||||
@@ -187,7 +203,7 @@ namespace Barotrauma.Sounds
|
||||
|
||||
OggStreamer.Instance.AddStream(this);
|
||||
AL.SourcePlay(alSourceId);
|
||||
ALHelper.Check();
|
||||
ALHelper.Check(FileName);
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
@@ -226,7 +242,7 @@ namespace Barotrauma.Sounds
|
||||
set
|
||||
{
|
||||
AL.Source(alSourceId, ALSourcef.Gain, volume = value);
|
||||
ALHelper.Check();
|
||||
ALHelper.Check(FileName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -256,20 +272,20 @@ namespace Barotrauma.Sounds
|
||||
/*if (ALHelper.Efx.IsInitialized)
|
||||
ALHelper.Efx.DeleteFilter(alFilterId);*/
|
||||
|
||||
ALHelper.Check();
|
||||
ALHelper.Check(FileName);
|
||||
}
|
||||
|
||||
void StopPlayback()
|
||||
{
|
||||
AL.SourceStop(alSourceId);
|
||||
ALHelper.Check();
|
||||
ALHelper.Check(FileName);
|
||||
}
|
||||
|
||||
void Empty()
|
||||
{
|
||||
int queued;
|
||||
AL.GetSource(alSourceId, ALGetSourcei.BuffersQueued, out queued);
|
||||
ALHelper.Check();
|
||||
ALHelper.Check(FileName);
|
||||
|
||||
if (queued > 0)
|
||||
{
|
||||
@@ -292,12 +308,12 @@ namespace Barotrauma.Sounds
|
||||
if (processed > 0)
|
||||
{
|
||||
AL.SourceUnqueueBuffers(alSourceId, processed, salvaged);
|
||||
ALHelper.Check();
|
||||
ALHelper.Check(FileName);
|
||||
}
|
||||
|
||||
// Try turning it off again?
|
||||
AL.SourceStop(alSourceId);
|
||||
ALHelper.Check();
|
||||
ALHelper.Check(FileName);
|
||||
|
||||
Empty();
|
||||
}
|
||||
@@ -314,7 +330,7 @@ namespace Barotrauma.Sounds
|
||||
// Fill first buffer synchronously
|
||||
OggStreamer.Instance.FillBuffer(this, alBufferIds[0]);
|
||||
AL.SourceQueueBuffer(alSourceId, alBufferIds[0]);
|
||||
ALHelper.Check();
|
||||
ALHelper.Check(FileName);
|
||||
|
||||
// Schedule the others asynchronously
|
||||
OggStreamer.Instance.AddStream(this);
|
||||
@@ -429,7 +445,7 @@ namespace Barotrauma.Sounds
|
||||
}
|
||||
AL.BufferData(bufferId, stream.Reader.Channels == 1 ? ALFormat.Mono16 : ALFormat.Stereo16, castBuffer,
|
||||
readSamples * sizeof(short), stream.Reader.SampleRate);
|
||||
ALHelper.Check();
|
||||
ALHelper.Check(stream.FileName);
|
||||
|
||||
return readSamples != BufferSize;
|
||||
}
|
||||
@@ -466,10 +482,10 @@ namespace Barotrauma.Sounds
|
||||
|
||||
int queued;
|
||||
AL.GetSource(stream.alSourceId, ALGetSourcei.BuffersQueued, out queued);
|
||||
ALHelper.Check();
|
||||
ALHelper.Check(stream.FileName);
|
||||
int processed;
|
||||
AL.GetSource(stream.alSourceId, ALGetSourcei.BuffersProcessed, out processed);
|
||||
ALHelper.Check();
|
||||
ALHelper.Check(stream.FileName);
|
||||
|
||||
if (processed == 0 && queued == stream.BufferCount) continue;
|
||||
|
||||
@@ -496,7 +512,7 @@ namespace Barotrauma.Sounds
|
||||
}
|
||||
|
||||
AL.SourceQueueBuffers(stream.alSourceId, tempBuffers.Length, tempBuffers);
|
||||
ALHelper.Check();
|
||||
ALHelper.Check(stream.FileName);
|
||||
|
||||
if (finished && !stream.IsLooped)
|
||||
continue;
|
||||
@@ -514,7 +530,7 @@ namespace Barotrauma.Sounds
|
||||
if (state == ALSourceState.Stopped)
|
||||
{
|
||||
AL.SourcePlay(stream.alSourceId);
|
||||
ALHelper.Check();
|
||||
ALHelper.Check(stream.FileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ namespace Barotrauma
|
||||
{
|
||||
DebugConsole.ThrowError("Failed to load sound "+file+"!", e);
|
||||
}
|
||||
ALHelper.Check();
|
||||
ALHelper.Check(file);
|
||||
}
|
||||
|
||||
baseVolume = 1.0f;
|
||||
@@ -219,7 +219,7 @@ namespace Barotrauma
|
||||
(SoundManager.IsPlaying(alSourceId) || SoundManager.IsPaused(alSourceId)))
|
||||
{
|
||||
SoundManager.Stop(alSourceId);
|
||||
ALHelper.Check();
|
||||
ALHelper.Check(filePath);
|
||||
}
|
||||
|
||||
foreach (Sound s in loadedSounds)
|
||||
@@ -228,7 +228,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
SoundManager.ClearAlSource(AlBufferId);
|
||||
ALHelper.Check();
|
||||
ALHelper.Check(filePath);
|
||||
|
||||
if (oggSound != null)
|
||||
{
|
||||
@@ -246,7 +246,7 @@ namespace Barotrauma
|
||||
|
||||
public static void StreamVolume(float volume = 1.0f)
|
||||
{
|
||||
if (SoundManager.Disabled) return;
|
||||
if (SoundManager.Disabled || stream == null) return;
|
||||
stream.Volume = volume;
|
||||
}
|
||||
|
||||
|
||||
@@ -143,7 +143,7 @@ namespace Barotrauma.Sounds
|
||||
volume = 0.0f;
|
||||
}
|
||||
|
||||
if (sourceIndex<1 || soundsPlaying[sourceIndex] != sound)
|
||||
if (sourceIndex < 1 || soundsPlaying[sourceIndex] != sound)
|
||||
{
|
||||
sourceIndex = Play(sound, position, volume, 0.0f, true);
|
||||
}
|
||||
@@ -153,7 +153,7 @@ namespace Barotrauma.Sounds
|
||||
AL.Source(alSources[sourceIndex], ALSourceb.Looping, true);
|
||||
}
|
||||
|
||||
ALHelper.Check();
|
||||
ALHelper.Check(sound?.FilePath);
|
||||
return sourceIndex;
|
||||
}
|
||||
|
||||
@@ -165,7 +165,7 @@ namespace Barotrauma.Sounds
|
||||
return;
|
||||
|
||||
AL.SourcePause(alSources[sourceIndex]);
|
||||
ALHelper.Check();
|
||||
ALHelper.Check(soundsPlaying[sourceIndex]?.FilePath);
|
||||
}
|
||||
|
||||
public static void Resume(int sourceIndex)
|
||||
@@ -176,7 +176,7 @@ namespace Barotrauma.Sounds
|
||||
return;
|
||||
|
||||
AL.SourcePlay(alSources[sourceIndex]);
|
||||
ALHelper.Check();
|
||||
ALHelper.Check(soundsPlaying[sourceIndex]?.FilePath);
|
||||
}
|
||||
|
||||
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.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.BindFilterToSource(alSources[sourceIndex], lowpassFilterId);
|
||||
ALHelper.Check();
|
||||
ALHelper.Check(soundsPlaying[sourceIndex]?.FilePath);
|
||||
}
|
||||
|
||||
public static OggStream StartStream(string file, float volume = 1.0f)
|
||||
@@ -331,7 +331,7 @@ namespace Barotrauma.Sounds
|
||||
|
||||
oggStream.Play(volume);
|
||||
|
||||
ALHelper.Check();
|
||||
ALHelper.Check(file);
|
||||
|
||||
return oggStream;
|
||||
}
|
||||
@@ -361,15 +361,15 @@ namespace Barotrauma.Sounds
|
||||
|
||||
for (int i = 0; i < DefaultSourceCount; i++)
|
||||
{
|
||||
string soundPath = soundsPlaying[i]?.FilePath;
|
||||
var state = OpenTK.Audio.OpenAL.AL.GetSourceState(alSources[i]);
|
||||
if (state == OpenTK.Audio.OpenAL.ALSourceState.Playing || state == OpenTK.Audio.OpenAL.ALSourceState.Paused)
|
||||
{
|
||||
Stop(i);
|
||||
}
|
||||
|
||||
OpenTK.Audio.OpenAL.AL.DeleteSource(alSources[i]);
|
||||
|
||||
ALHelper.Check();
|
||||
OpenTK.Audio.OpenAL.AL.DeleteSource(alSources[i]);
|
||||
ALHelper.Check(soundPath);
|
||||
}
|
||||
|
||||
if (oggStream != null)
|
||||
|
||||
@@ -254,11 +254,14 @@ namespace Barotrauma
|
||||
partial void DisposeTexture()
|
||||
{
|
||||
//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 (texture != null)
|
||||
{
|
||||
@@ -267,6 +270,5 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ namespace Barotrauma
|
||||
using (Stream fileStream = File.OpenRead(path))
|
||||
{
|
||||
var texture = Texture2D.FromStream(_graphicsDevice, fileStream);
|
||||
texture = PreMultiplyAlpha(texture);
|
||||
PreMultiplyAlpha(texture);
|
||||
return texture;
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ namespace Barotrauma
|
||||
try
|
||||
{
|
||||
var texture = Texture2D.FromStream(_graphicsDevice, fileStream);
|
||||
texture = PreMultiplyAlpha(texture);
|
||||
PreMultiplyAlpha(texture);
|
||||
return texture;
|
||||
}
|
||||
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
|
||||
using (RenderTarget2D renderTarget = new RenderTarget2D(_graphicsDevice, texture.Width, texture.Height))
|
||||
@@ -103,9 +103,7 @@ namespace Barotrauma
|
||||
// Unset texture from graphic device and set modified data back to it
|
||||
_graphicsDevice.Textures[0] = null;
|
||||
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
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("0.8.1.5")]
|
||||
[assembly: AssemblyFileVersion("0.8.1.5")]
|
||||
[assembly: AssemblyVersion("0.8.2.0")]
|
||||
[assembly: AssemblyFileVersion("0.8.2.0")]
|
||||
|
||||
@@ -124,7 +124,6 @@ namespace Barotrauma
|
||||
|
||||
public void CloseServer()
|
||||
{
|
||||
if (GameSettings.SendUserStatistics) GameAnalytics.OnStop();
|
||||
Server.Disconnect();
|
||||
Server = null;
|
||||
}
|
||||
@@ -171,7 +170,6 @@ namespace Barotrauma
|
||||
stopwatch.Stop();
|
||||
|
||||
CloseServer();
|
||||
|
||||
}
|
||||
|
||||
public void ProcessInput()
|
||||
|
||||
@@ -31,6 +31,7 @@ namespace Barotrauma
|
||||
inputThread.Start();
|
||||
game.Run();
|
||||
inputThread.Abort(); inputThread.Join();
|
||||
if (GameSettings.SendUserStatistics) GameAnalytics.OnStop();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
||||
@@ -119,7 +119,7 @@ namespace Barotrauma
|
||||
|
||||
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.");
|
||||
}
|
||||
@@ -187,7 +187,7 @@ namespace Barotrauma
|
||||
|
||||
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)];
|
||||
}
|
||||
if (GameMain.Server.ModeSelectionMode == SelectionMode.Random)
|
||||
|
||||
@@ -325,12 +325,6 @@
|
||||
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Electricity\lightsprite.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</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">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
|
||||
@@ -26,7 +26,8 @@
|
||||
<Item
|
||||
name="Medicine Cabinet"
|
||||
linkable="true"
|
||||
pickdistance ="150">
|
||||
pickdistance="150"
|
||||
waterproof="true">
|
||||
|
||||
<Sprite texture ="cabinets.png" depth="0.84" sourcerect="0,0,48,64" canflipx="false"/>
|
||||
|
||||
@@ -37,9 +38,10 @@
|
||||
</Item>
|
||||
|
||||
<Item
|
||||
name="Toxic Cabinet"
|
||||
linkable="true"
|
||||
pickdistance ="150">
|
||||
name="Toxic Cabinet"
|
||||
linkable="true"
|
||||
pickdistance="150"
|
||||
waterproof="true">
|
||||
|
||||
<Sprite texture ="cabinets.png" depth="0.84" sourcerect="0,64,48,64" canflipx="false"/>
|
||||
|
||||
@@ -52,7 +54,7 @@
|
||||
<Item
|
||||
name="Metal Crate"
|
||||
linkable="true"
|
||||
pickdistance ="150">
|
||||
pickdistance="150">
|
||||
|
||||
<Deconstruct time="20">
|
||||
<Item name="Steel Bar"/>
|
||||
@@ -74,7 +76,7 @@
|
||||
<Item
|
||||
name="Explosive Crate"
|
||||
linkable="true"
|
||||
pickdistance ="150">
|
||||
pickdistance="150">
|
||||
|
||||
<Deconstruct time="20">
|
||||
<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="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="Contained,Character" OxygenAvailable="1000.0" Condition="-0.5">
|
||||
<RequiredItem type="Contained" name="Oxygen Tank"/>
|
||||
|
||||
@@ -103,8 +103,7 @@
|
||||
|
||||
<Item
|
||||
name="Docking Port"
|
||||
linkable="true"
|
||||
>
|
||||
linkable="true">
|
||||
|
||||
<Sprite texture ="dockingport.png" sourcerect="0,0,112,208" depth="0.94" origin="0.5,0.5"/>
|
||||
|
||||
@@ -116,14 +115,8 @@
|
||||
<sound file="Content/Items/Door/doorBreak2.ogg" range="3000"/>
|
||||
</StatusEffect>
|
||||
</DockingPort>
|
||||
|
||||
<fixrequirement name="Electrical repairs">
|
||||
<skill name="Electrical Engineering" level="40"/>
|
||||
<item name="Wire"/>
|
||||
<item name="Screwdriver"/>
|
||||
</fixrequirement>
|
||||
|
||||
<PowerTransfer/>
|
||||
|
||||
<PowerTransfer CanBeOverloaded="false" FireProbability="0.0"/>
|
||||
<Wire/>
|
||||
|
||||
<fixrequirement name="Mechanical repairs">
|
||||
@@ -143,8 +136,7 @@
|
||||
|
||||
<Item
|
||||
name="Docking Hatch"
|
||||
linkable="true"
|
||||
>
|
||||
linkable="true">
|
||||
|
||||
<Sprite texture ="dockingport2.png" sourcerect="0,0,128,112" depth="0.94" origin="0.5,0.5"/>
|
||||
|
||||
@@ -157,13 +149,7 @@
|
||||
</StatusEffect>
|
||||
</DockingPort>
|
||||
|
||||
<fixrequirement name="Electrical repairs">
|
||||
<skill name="Electrical Engineering" level="40"/>
|
||||
<item name="Wire"/>
|
||||
<item name="Screwdriver"/>
|
||||
</fixrequirement>
|
||||
|
||||
<PowerTransfer/>
|
||||
<PowerTransfer CanBeOverloaded="false" FireProbability="0.0"/>
|
||||
<Wire/>
|
||||
|
||||
<fixrequirement name="Mechanical repairs">
|
||||
@@ -183,8 +169,7 @@
|
||||
|
||||
<Item
|
||||
name="Duct Block"
|
||||
linkable="true"
|
||||
>
|
||||
linkable="true">
|
||||
|
||||
<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"
|
||||
category="Electrical"
|
||||
Tags="smallitem,wire"
|
||||
spritecolor="1.0,0.0,0.0,1.0"
|
||||
spritecolor="0.7,0.06,0.06,1.0"
|
||||
linkable="true"
|
||||
canbepicked="true"
|
||||
cargocontainername="Metal Crate"
|
||||
@@ -50,7 +50,7 @@
|
||||
name="Blue Wire"
|
||||
category="Electrical"
|
||||
Tags="smallitem,wire"
|
||||
spritecolor="0.0,0.6,1.0,1.0"
|
||||
spritecolor="0.1,0.4,0.9,1.0"
|
||||
linkable="true"
|
||||
canbepicked="true"
|
||||
cargocontainername="Metal Crate"
|
||||
@@ -72,7 +72,7 @@
|
||||
name="Orange Wire"
|
||||
category="Electrical"
|
||||
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"
|
||||
@@ -90,6 +90,50 @@
|
||||
<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"
|
||||
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="FPGA Circuit"
|
||||
category="Electrical"
|
||||
@@ -261,7 +305,7 @@
|
||||
|
||||
<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"/>
|
||||
</RelayComponent>
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
</Deconstruct>
|
||||
|
||||
<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="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"/>
|
||||
|
||||
<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"/>
|
||||
<RequiredItem name="Medical Syringe" type="Container"/>
|
||||
</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">
|
||||
<!-- Injecting a still-conscious Husk will only piss it off and kill the "conscious" faster -->
|
||||
<Conditional HuskInfectionState="eq 1.0"/>
|
||||
|
||||
@@ -13,16 +13,13 @@
|
||||
</fixrequirement>
|
||||
|
||||
<OxygenGenerator powerconsumption="1000.0" minvoltage="0.5" canbeselected = "true">
|
||||
|
||||
<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="Oxygenite Tank" Condition="0.0"/>
|
||||
<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">
|
||||
<sound file="Content/Items/Reactor/explosion.ogg"/>
|
||||
<Explosion range="50" damage="0" stun="0" force="3.0" flames="false" shockwave="false" sparks="true"/>
|
||||
</StatusEffect>
|
||||
<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">
|
||||
<sound file="Content/Items/Reactor/explosion.ogg"/>
|
||||
<Explosion range="50" damage="0" stun="0" force="3.0" flames="false" shockwave="false" sparks="true"/>
|
||||
</StatusEffect>
|
||||
</OxygenGenerator>
|
||||
|
||||
<trigger/>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
<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"/>
|
||||
<RequiredSkill name="Construction" level="30"/>
|
||||
<StatusEffect type="InWater" target="This" Temperature="-500.0"/>
|
||||
|
||||
@@ -286,11 +286,11 @@
|
||||
|
||||
<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"/>
|
||||
<!-- 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>
|
||||
|
||||
<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">
|
||||
<Containable name="Battery Cell, Fulgurium Battery Cell">
|
||||
|
||||
@@ -9,11 +9,12 @@
|
||||
|
||||
<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"
|
||||
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"/>
|
||||
<input name="trigger_in"/>
|
||||
</ConnectionPanel>
|
||||
|
||||
@@ -2,13 +2,18 @@
|
||||
<Item
|
||||
name="Railgun"
|
||||
category="Machine"
|
||||
interactthroughwalls="true"
|
||||
interactdistance="10"
|
||||
focusonselected="true"
|
||||
offsetonselected="700"
|
||||
linkable="true">
|
||||
|
||||
<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"
|
||||
powerconsumption="20000.0"
|
||||
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"/>
|
||||
|
||||
<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">
|
||||
<Sound file="Content/Items/Weapons/harpoon1.ogg" type="OnUse"/>
|
||||
@@ -119,15 +119,15 @@
|
||||
<Item name="Aluminium"/>
|
||||
<Item name="Polycarbonate Bar"/>
|
||||
</Deconstruct>
|
||||
|
||||
<Sprite texture="weapons.png" sourcerect="26,97,25,19" depth="0.55"/>
|
||||
|
||||
<Sprite texture="weapons.png" sourcerect="24,102,37,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"
|
||||
aimpos="75,18" handle1="-10,-5"/>
|
||||
|
||||
<RangedWeapon barrelpos="37,3" spread="0" unskilledspread="2">
|
||||
aimpos="90,10" handle1="-11,-7"/>
|
||||
|
||||
<RangedWeapon barrelpos="14,6" spread="0" unskilledspread="2">
|
||||
<Sound file="Content/Items/Weapons/revolver.ogg" type="OnUse" range="3000"/>
|
||||
<StatusEffect type="OnUse">
|
||||
<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="Battery Cell"/>
|
||||
</Item>
|
||||
<Item name="Revolver" equip="false">
|
||||
<Item name="Revolver Round"/>
|
||||
<Item name="Revolver Round"/>
|
||||
<Item name="Revolver Round"/>
|
||||
</Item>
|
||||
<Item name="Revolver" equip="false">
|
||||
<Item name="Revolver Round"/>
|
||||
<Item name="Revolver Round"/>
|
||||
<Item name="Revolver Round"/>
|
||||
</Item>
|
||||
</Items>
|
||||
</Job>
|
||||
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
<Item file="Content/Items/Diving/divinggear.xml" />
|
||||
<Item file="Content/Items/Door/doors.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/signalitems.xml" />
|
||||
<Item file="Content/Items/Engine/engine.xml" />
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
|
||||
<Preset
|
||||
name="Moderator"
|
||||
description="Allowed to manage round settings and kick players."
|
||||
permissions="EndRound,Kick,SelectSub,SelectMode,ManageCampaign,ConsoleCommands">
|
||||
description="Allowed to manage round settings, kick players and access server logs."
|
||||
permissions="EndRound,Kick,SelectSub,SelectMode,ManageCampaign,ConsoleCommands,ServerLog">
|
||||
<Command name="clientlist"/>
|
||||
<Command name="autorestart"/>
|
||||
<Command name="autorestartinterval"/>
|
||||
@@ -21,8 +21,8 @@
|
||||
|
||||
<Preset
|
||||
name="Admin"
|
||||
description="Allowed to ban and kick players, manage round settings and use nearly all console commands."
|
||||
permissions="EndRound,Kick,Ban,SelectSub,SelectMode,ManageCampaign,ConsoleCommands">
|
||||
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,ServerLog">
|
||||
<Command name="clientlist"/>
|
||||
<Command name="autorestart"/>
|
||||
<Command name="autorestartinterval"/>
|
||||
|
||||
@@ -38,6 +38,9 @@ namespace Barotrauma
|
||||
#if DEBUG
|
||||
DebugConsole.ThrowError("Attempted to access a removed AITarget\n" + Environment.StackTrace);
|
||||
#endif
|
||||
GameAnalyticsManager.AddErrorEventOnce("AITarget.WorldPosition:EntityRemoved",
|
||||
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||
"Attempted to access a removed AITarget\n" + Environment.StackTrace);
|
||||
return Vector2.Zero;
|
||||
}
|
||||
|
||||
@@ -54,6 +57,9 @@ namespace Barotrauma
|
||||
#if DEBUG
|
||||
DebugConsole.ThrowError("Attempted to access a removed AITarget\n" + Environment.StackTrace);
|
||||
#endif
|
||||
GameAnalyticsManager.AddErrorEventOnce("AITarget.WorldPosition:EntityRemoved",
|
||||
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||
"Attempted to access a removed AITarget\n" + Environment.StackTrace);
|
||||
return Vector2.Zero;
|
||||
}
|
||||
|
||||
|
||||
@@ -274,7 +274,15 @@ namespace Barotrauma
|
||||
|
||||
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.SteeringAvoid(deltaTime, 2f);
|
||||
}
|
||||
@@ -484,8 +492,10 @@ namespace Barotrauma
|
||||
|
||||
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.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);
|
||||
|
||||
@@ -63,6 +63,7 @@ namespace Barotrauma
|
||||
character.SetInput(InputType.Aim, false, true);
|
||||
|
||||
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);
|
||||
Vector2 weaponDir = new Vector2((float)Math.Cos(weaponAngle), (float)Math.Sin(weaponAngle));
|
||||
|
||||
|
||||
@@ -30,14 +30,9 @@ namespace Barotrauma
|
||||
|
||||
protected override void Act(float deltaTime)
|
||||
{
|
||||
|
||||
var pathSteering = character.AIController.SteeringManager as IndoorsSteeringManager;
|
||||
if (pathSteering == null) return;
|
||||
|
||||
if (pathSteering==null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (character.AnimController.InWater)
|
||||
{
|
||||
//attempt to find a safer place if in water
|
||||
@@ -67,16 +62,16 @@ namespace Barotrauma
|
||||
|
||||
newTargetTimer -= deltaTime;
|
||||
|
||||
|
||||
|
||||
//wander randomly
|
||||
// - if reached the end of the path
|
||||
// - if the target is unreachable
|
||||
// - 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)))
|
||||
{
|
||||
//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 rightDist = character.AnimController.CurrentHull.Rect.Right - character.Position.X;
|
||||
@@ -113,8 +108,13 @@ namespace Barotrauma
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -92,7 +92,7 @@ namespace Barotrauma
|
||||
|
||||
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)
|
||||
{
|
||||
|
||||
@@ -80,9 +80,9 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -97,12 +97,12 @@ namespace Barotrauma
|
||||
targetVel = Vector2.Normalize(targetVel) * speed;
|
||||
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();
|
||||
if (steeringSpeed > Math.Abs(speed))
|
||||
{
|
||||
newSteering = Vector2.Normalize(newSteering)*Math.Abs(speed);
|
||||
newSteering = Vector2.Normalize(newSteering) * Math.Abs(speed);
|
||||
}
|
||||
|
||||
return newSteering;
|
||||
@@ -151,8 +151,7 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
Structure closestStructure = closestBody.UserData as Structure;
|
||||
if (closestStructure != null)
|
||||
if (closestBody.UserData is Structure closestStructure)
|
||||
{
|
||||
Vector2 obstaclePosition = Submarine.LastPickedPosition;
|
||||
if (closestStructure.IsHorizontal)
|
||||
@@ -166,15 +165,17 @@ namespace Barotrauma
|
||||
|
||||
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);
|
||||
}
|
||||
else
|
||||
{
|
||||
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 UpdateUseItem(bool allowMovement, Vector2 handPos) { }
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,8 +64,16 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
Collider.LinearVelocity = (MainLimb.SimPosition - Collider.SimPosition) * 60.0f;
|
||||
Collider.SmoothRotate(MainLimb.Rotation);
|
||||
Vector2 diff = (MainLimb.SimPosition - Collider.SimPosition);
|
||||
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)
|
||||
|
||||
@@ -24,6 +24,8 @@ namespace Barotrauma
|
||||
|
||||
private float inWaterTimer;
|
||||
private bool swimming;
|
||||
|
||||
private float useItemTimer;
|
||||
|
||||
protected override float TorsoPosition
|
||||
{
|
||||
@@ -92,14 +94,22 @@ namespace Barotrauma
|
||||
{
|
||||
levitatingCollider = 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.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;
|
||||
}
|
||||
|
||||
@@ -180,6 +190,12 @@ namespace Barotrauma
|
||||
case Animation.UsingConstruction:
|
||||
default:
|
||||
|
||||
if (Anim == Animation.UsingConstruction)
|
||||
{
|
||||
useItemTimer -= deltaTime;
|
||||
if (useItemTimer <= 0.0f) Anim = Animation.None;
|
||||
}
|
||||
|
||||
if (character.SelectedCharacter != null) DragCharacter(character.SelectedCharacter);
|
||||
|
||||
//0.5 second delay for switching between swimming and walking
|
||||
@@ -1067,8 +1083,31 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
targetLimb.pullJoint.Enabled = false;
|
||||
@@ -1204,25 +1243,29 @@ namespace Barotrauma
|
||||
|
||||
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 (rightHand.IsSevered) return;
|
||||
transformedHoldPos = rightHand.pullJoint.WorldAnchorA - transformedHandlePos[0];
|
||||
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
|
||||
{
|
||||
if (character.SelectedItems[0] == item)
|
||||
{
|
||||
if (rightHand.IsSevered) return;
|
||||
rightHand.Disabled = true;
|
||||
}
|
||||
if (character.SelectedItems[1] == item)
|
||||
{
|
||||
if (leftHand.IsSevered) return;
|
||||
leftHand.Disabled = true;
|
||||
}
|
||||
|
||||
@@ -1235,6 +1278,24 @@ namespace Barotrauma
|
||||
Vector2 currItemPos = (character.SelectedItems[0] == item) ?
|
||||
rightHand.pullJoint.WorldAnchorA - transformedHandlePos[0] :
|
||||
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(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);
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
base.Flip();
|
||||
|
||||
@@ -3,6 +3,7 @@ using FarseerPhysics;
|
||||
using FarseerPhysics.Dynamics;
|
||||
using FarseerPhysics.Dynamics.Contacts;
|
||||
using FarseerPhysics.Dynamics.Joints;
|
||||
using FarseerPhysics.Factories;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -25,6 +26,11 @@ namespace Barotrauma
|
||||
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));
|
||||
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 limbs;
|
||||
@@ -42,6 +48,7 @@ namespace Barotrauma
|
||||
frozen = value;
|
||||
|
||||
Collider.PhysEnabled = !frozen;
|
||||
if (frozen && MainLimb != null) MainLimb.pullJoint.WorldAnchorB = MainLimb.SimPosition;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,7 +94,11 @@ namespace Barotrauma
|
||||
|
||||
protected List<PhysicsBody> collider;
|
||||
protected int colliderIndex = 0;
|
||||
|
||||
|
||||
private Category prevCollisionCategory = Category.None;
|
||||
|
||||
private Body outsideCollisionBlocker;
|
||||
|
||||
public PhysicsBody Collider
|
||||
{
|
||||
get
|
||||
@@ -269,11 +280,7 @@ namespace Barotrauma
|
||||
get { return ignorePlatforms; }
|
||||
set
|
||||
{
|
||||
if (ignorePlatforms == value) return;
|
||||
ignorePlatforms = value;
|
||||
|
||||
UpdateCollisionCategories();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -352,21 +359,29 @@ namespace Barotrauma
|
||||
if (collider[0] == null)
|
||||
{
|
||||
DebugConsole.ThrowError("No collider configured for \"" + character.Name + "\"!");
|
||||
collider[0] = new PhysicsBody(0.0f, 0.0f, 0.5f, 5.0f);
|
||||
collider[0].UserData = character;
|
||||
collider[0].BodyType = BodyType.Dynamic;
|
||||
collider[0].CollisionCategories = Physics.CollisionCharacter;
|
||||
collider[0] = new PhysicsBody(0.0f, 0.0f, 0.5f, 5.0f)
|
||||
{
|
||||
UserData = character,
|
||||
BodyType = BodyType.Dynamic,
|
||||
CollisionCategories = Physics.CollisionCharacter
|
||||
};
|
||||
collider[0].FarseerBody.AngularDamping = 5.0f;
|
||||
collider[0].FarseerBody.FixedRotation = true;
|
||||
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();
|
||||
|
||||
foreach (var joint in LimbJoints)
|
||||
{
|
||||
joint.BodyB.SetTransform(
|
||||
joint.BodyA.Position + (joint.LocalAnchorA - joint.LocalAnchorB)*0.1f,
|
||||
joint.LimbB?.body?.SetTransform(
|
||||
joint.BodyA.Position + (joint.LocalAnchorA - joint.LocalAnchorB) * 0.1f,
|
||||
(joint.LowerLimit + joint.UpperLimit) / 2.0f);
|
||||
}
|
||||
|
||||
@@ -391,7 +406,7 @@ namespace Barotrauma
|
||||
Limb torso = GetLimb(LimbType.Torso);
|
||||
Limb head = GetLimb(LimbType.Head);
|
||||
|
||||
MainLimb = torso == null ? head : torso;
|
||||
MainLimb = torso ?? head;
|
||||
}
|
||||
|
||||
public void AddJoint(XElement subElement, float scale = 1.0f)
|
||||
@@ -488,7 +503,10 @@ namespace Barotrauma
|
||||
Structure structure = f2.Body.UserData as Structure;
|
||||
|
||||
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
|
||||
if (structure == null)
|
||||
{
|
||||
@@ -739,7 +757,15 @@ namespace Barotrauma
|
||||
|
||||
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);
|
||||
|
||||
@@ -754,10 +780,13 @@ namespace Barotrauma
|
||||
//this is preferable to the cost of using continuous collision detection for the character collider
|
||||
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
|
||||
Vector2? intersection = MathUtils.GetLineRectangleIntersection(
|
||||
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));
|
||||
|
||||
if (intersection != null)
|
||||
@@ -774,15 +803,7 @@ namespace Barotrauma
|
||||
//in -> out
|
||||
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;
|
||||
|
||||
Teleport(ConvertUnits.ToSimUnits(currentHull.Submarine.Position), currentHull.Submarine.Velocity);
|
||||
}
|
||||
//out -> in
|
||||
@@ -799,10 +820,49 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
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)
|
||||
@@ -842,7 +902,10 @@ namespace Barotrauma
|
||||
Category collisionCategory = (ignorePlatforms) ?
|
||||
wall | Physics.CollisionProjectile | Physics.CollisionStairs
|
||||
: wall | Physics.CollisionProjectile | Physics.CollisionPlatform | Physics.CollisionStairs;
|
||||
|
||||
|
||||
if (collisionCategory == prevCollisionCategory) return;
|
||||
prevCollisionCategory = collisionCategory;
|
||||
|
||||
Collider.CollidesWith = collisionCategory;
|
||||
|
||||
foreach (Limb limb in Limbs)
|
||||
@@ -868,10 +931,12 @@ namespace Barotrauma
|
||||
|
||||
UpdateNetPlayerPosition(deltaTime);
|
||||
CheckDistFromCollider();
|
||||
UpdateCollisionCategories();
|
||||
|
||||
Vector2 flowForce = Vector2.Zero;
|
||||
|
||||
FindHull();
|
||||
PreventOutsideCollision();
|
||||
|
||||
splashSoundTimer -= deltaTime;
|
||||
|
||||
@@ -1089,22 +1154,19 @@ namespace Barotrauma
|
||||
|
||||
float tfloorY = rayStart.Y + (rayEnd.Y - rayStart.Y) * closestFraction;
|
||||
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;
|
||||
newSpeed.Y = (targetY - Collider.SimPosition.Y)*5.0f;
|
||||
Collider.LinearVelocity = newSpeed;
|
||||
}
|
||||
else
|
||||
{
|
||||
Vector2 newSpeed = Collider.LinearVelocity;
|
||||
newSpeed.Y = 0.0f;
|
||||
Collider.LinearVelocity = newSpeed;
|
||||
Vector2 newPos = Collider.SimPosition;
|
||||
newPos.Y = targetY;
|
||||
Collider.SetTransform(newPos, Collider.Rotation);
|
||||
}
|
||||
if (forceImmediate)
|
||||
{
|
||||
Collider.LinearVelocity = new Vector2(Collider.LinearVelocity.X, 0);
|
||||
Collider.SetTransform(new Vector2(Collider.SimPosition.X, targetY), Collider.Rotation);
|
||||
}
|
||||
else
|
||||
{
|
||||
Collider.LinearVelocity = new Vector2(Collider.LinearVelocity.X, (targetY - Collider.SimPosition.Y) * 5.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1165,6 +1227,16 @@ namespace Barotrauma
|
||||
|
||||
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;
|
||||
|
||||
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
|
||||
SetPosition(Collider.SimPosition, true);
|
||||
|
||||
UpdateCollisionCategories();
|
||||
collisionsDisabled = false;
|
||||
//force collision categories to be updated
|
||||
prevCollisionCategory = Category.None;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1312,8 +1384,24 @@ namespace Barotrauma
|
||||
character.AnimController.Anim = AnimController.Animation.None;
|
||||
}
|
||||
|
||||
Collider.LinearVelocity = Vector2.Zero;
|
||||
Collider.CorrectPosition(character.MemState, deltaTime, out overrideTargetMovement);
|
||||
Vector2 newVelocity = Vector2.Zero;
|
||||
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
|
||||
// -> we need to correct it manually
|
||||
@@ -1431,10 +1519,18 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
Collider.SetTransform(Collider.SimPosition + positionError, Collider.Rotation + rotationError);
|
||||
foreach (Limb limb in Limbs)
|
||||
float errorMagnitude = positionError.Length();
|
||||
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()
|
||||
{
|
||||
Vector2 limbPos = ConvertUnits.ToDisplayUnits(Limbs[0].SimPosition);
|
||||
Vector2 limbPos = Limbs[0].Position;
|
||||
|
||||
Vector2 force = Vector2.Zero;
|
||||
foreach (MapEntity e in MapEntity.mapEntityList)
|
||||
foreach (Gap gap in Gap.GapList)
|
||||
{
|
||||
Gap gap = e as Gap;
|
||||
if (gap == null || gap.FlowTargetHull != currentHull || gap.LerpedFlowForce == Vector2.Zero) continue;
|
||||
if (gap.Open <= 0.0f || gap.FlowTargetHull != currentHull || gap.LerpedFlowForce.LengthSquared() < 0.01f) continue;
|
||||
|
||||
Vector2 gapPos = gap.SimPosition;
|
||||
|
||||
float dist = Vector2.Distance(limbPos, gapPos);
|
||||
|
||||
force += Vector2.Normalize(gap.LerpedFlowForce) * (Math.Max(gap.LerpedFlowForce.Length() - dist, 0.0f) / 500.0f);
|
||||
}
|
||||
|
||||
if (force.Length() > 20.0f) return force;
|
||||
return force;
|
||||
}
|
||||
|
||||
@@ -1526,6 +1617,12 @@ namespace Barotrauma
|
||||
b.Remove();
|
||||
}
|
||||
|
||||
if (outsideCollisionBlocker != null)
|
||||
{
|
||||
GameMain.World.RemoveBody(outsideCollisionBlocker);
|
||||
outsideCollisionBlocker = null;
|
||||
}
|
||||
|
||||
if (LimbJoints != null)
|
||||
{
|
||||
foreach (RevoluteJoint joint in LimbJoints)
|
||||
|
||||
@@ -144,6 +144,10 @@ namespace Barotrauma
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1611,12 +1615,20 @@ namespace Barotrauma
|
||||
//Health effects
|
||||
if (needsAir) UpdateOxygen(deltaTime);
|
||||
|
||||
Health -= bleeding * deltaTime;
|
||||
Bleeding -= BleedingDecreaseSpeed * deltaTime;
|
||||
if (DoesBleed)
|
||||
{
|
||||
Health -= bleeding * deltaTime;
|
||||
Bleeding -= BleedingDecreaseSpeed * deltaTime;
|
||||
}
|
||||
|
||||
if (health <= minHealth) Kill(CauseOfDeath.Bloodloss);
|
||||
|
||||
UpdateSightRange();
|
||||
if (aiTarget != null) aiTarget.SoundRange = 0.0f;
|
||||
|
||||
if (!IsDead) LockHands = false;
|
||||
lowPassMultiplier = MathHelper.Lerp(lowPassMultiplier, 1.0f, 0.1f);
|
||||
|
||||
if (health <= minHealth) Kill(CauseOfDeath.Bloodloss);
|
||||
|
||||
//ragdoll button
|
||||
if (IsRagdolled)
|
||||
@@ -1643,21 +1655,7 @@ namespace Barotrauma
|
||||
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;
|
||||
//CPR stuff is handled in the UpdateCPR function in HumanoidAnimController
|
||||
}
|
||||
|
||||
partial void UpdateControlled(float deltaTime, Camera cam);
|
||||
@@ -1960,7 +1958,7 @@ namespace Barotrauma
|
||||
characterType = "Enemy";
|
||||
else if (AIController is HumanAIController)
|
||||
characterType = "AICrew";
|
||||
GameAnalyticsSDK.Net.GameAnalytics.AddDesignEvent("Kill:" + characterType + ":" + SpeciesName + ":" + causeOfDeath);
|
||||
GameAnalyticsManager.AddDesignEvent("Kill:" + characterType + ":" + SpeciesName + ":" + causeOfDeath);
|
||||
}
|
||||
|
||||
if (OnDeath != null) OnDeath(this, causeOfDeath);
|
||||
@@ -1997,7 +1995,7 @@ namespace Barotrauma
|
||||
}
|
||||
partial void KillProjSpecific();
|
||||
|
||||
public void Revive(bool isNetworkMessage)
|
||||
public void Revive()
|
||||
{
|
||||
if (Removed)
|
||||
{
|
||||
@@ -2024,6 +2022,7 @@ namespace Barotrauma
|
||||
|
||||
foreach (Limb limb in AnimController.Limbs)
|
||||
{
|
||||
limb.body.Enabled = true;
|
||||
limb.IsSevered = false;
|
||||
}
|
||||
|
||||
@@ -2044,6 +2043,9 @@ namespace Barotrauma
|
||||
|
||||
base.Remove();
|
||||
|
||||
if (selectedItems[0] != null) selectedItems[0].Drop(this);
|
||||
if (selectedItems[1] != null) selectedItems[1].Drop(this);
|
||||
|
||||
if (info != null) info.Remove();
|
||||
|
||||
CharacterList.Remove(this);
|
||||
@@ -2054,9 +2056,6 @@ namespace Barotrauma
|
||||
|
||||
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)
|
||||
{
|
||||
if (c.focusedCharacter == this) c.focusedCharacter = null;
|
||||
|
||||
@@ -17,11 +17,16 @@ namespace Barotrauma
|
||||
get
|
||||
{
|
||||
string disguiseName = "?";
|
||||
if (Character == null || !Character.HideFace)
|
||||
if (Character == null || !Character.HideFace || (GameMain.Server != null && !GameMain.Server.AllowDisguises))
|
||||
{
|
||||
return Name;
|
||||
}
|
||||
|
||||
#if CLIENT
|
||||
if (GameMain.Client != null && !GameMain.Client.AllowDisguises)
|
||||
{
|
||||
return Name;
|
||||
}
|
||||
#endif
|
||||
if (Character.Inventory != null)
|
||||
{
|
||||
int cardSlotIndex = Character.Inventory.FindLimbSlot(InvSlotType.Card);
|
||||
|
||||
@@ -79,11 +79,16 @@ namespace Barotrauma
|
||||
|
||||
private List<CharacterStateInfo> memState = new List<CharacterStateInfo>();
|
||||
private List<CharacterStateInfo> memLocalState = new List<CharacterStateInfo>();
|
||||
|
||||
|
||||
private bool networkUpdateSent;
|
||||
|
||||
public bool isSynced = false;
|
||||
|
||||
|
||||
public string OwnerClientIP;
|
||||
public string OwnerClientName;
|
||||
public bool ClientDisconnected;
|
||||
public float KillDisconnectedTimer;
|
||||
|
||||
public List<CharacterStateInfo> 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.Xml.Linq;
|
||||
|
||||
@@ -135,6 +136,11 @@ namespace Barotrauma
|
||||
if (!string.IsNullOrWhiteSpace(spawnPoint.IdCardDesc))
|
||||
item.Description = spawnPoint.IdCardDesc;
|
||||
}
|
||||
|
||||
foreach (WifiComponent wifiComponent in item.GetComponents<WifiComponent>())
|
||||
{
|
||||
wifiComponent.TeamID = character.TeamID;
|
||||
}
|
||||
|
||||
if (parentItem != null) parentItem.Combine(item);
|
||||
|
||||
|
||||
@@ -85,9 +85,10 @@ namespace Barotrauma
|
||||
set
|
||||
{
|
||||
isSevered = value;
|
||||
if (!isSevered) severedFadeOutTimer = 0.0f;
|
||||
#if CLIENT
|
||||
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("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) =>
|
||||
@@ -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) =>
|
||||
{
|
||||
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);
|
||||
if (revivedCharacter == null) return;
|
||||
|
||||
revivedCharacter.Revive(false);
|
||||
revivedCharacter.Revive();
|
||||
if (GameMain.Server != null)
|
||||
{
|
||||
foreach (Client c in GameMain.Server.ConnectedClients)
|
||||
@@ -1342,7 +1353,7 @@ namespace Barotrauma
|
||||
Character revivedCharacter = (args.Length == 0) ? client.Character : FindMatchingCharacter(args);
|
||||
if (revivedCharacter == null) return;
|
||||
|
||||
revivedCharacter.Revive(false);
|
||||
revivedCharacter.Revive();
|
||||
if (GameMain.Server != null)
|
||||
{
|
||||
foreach (Client c in GameMain.Server.ConnectedClients)
|
||||
@@ -1502,6 +1513,13 @@ namespace Barotrauma
|
||||
{
|
||||
Character killedCharacter = (args.Length == 0) ? client.Character : FindMatchingCharacter(args);
|
||||
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) =>
|
||||
@@ -1712,7 +1730,7 @@ namespace Barotrauma
|
||||
var itemContainer = item.GetComponent<ItemContainer>();
|
||||
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 });
|
||||
@@ -1895,10 +1913,19 @@ namespace Barotrauma
|
||||
return;
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(command)) return;
|
||||
if (string.IsNullOrWhiteSpace(command) || command == "\\" || command == "\n") return;
|
||||
|
||||
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"))
|
||||
{
|
||||
NewMessage(command, Color.White, true);
|
||||
@@ -1976,6 +2003,13 @@ namespace Barotrauma
|
||||
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
|
||||
{
|
||||
matchingCommand.ServerExecuteOnClientRequest(client, cursorWorldPos, splitCommand.Skip(1).ToArray());
|
||||
@@ -2139,57 +2173,55 @@ namespace Barotrauma
|
||||
Vector2? spawnPos = null;
|
||||
Inventory spawnInventory = null;
|
||||
|
||||
if (args.Length > 1)
|
||||
int extraParams = 0;
|
||||
switch (args.Last().ToLowerInvariant())
|
||||
{
|
||||
switch (args[1])
|
||||
{
|
||||
case "cursor":
|
||||
spawnPos = cursorPos;
|
||||
break;
|
||||
case "inventory":
|
||||
spawnInventory = controlledCharacter?.Inventory;
|
||||
break;
|
||||
default:
|
||||
//Check if last arg matches the name of an in-game player
|
||||
if (GameMain.Server != null)
|
||||
{
|
||||
var client = GameMain.Server.ConnectedClients.Find(c => c.Name.ToLower() == args.Last().ToLower());
|
||||
if (client == null)
|
||||
{
|
||||
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);
|
||||
break;
|
||||
}
|
||||
else if (client.Character == null)
|
||||
{
|
||||
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;
|
||||
}
|
||||
case "cursor":
|
||||
extraParams = 1;
|
||||
spawnPos = cursorPos;
|
||||
break;
|
||||
case "inventory":
|
||||
extraParams = 1;
|
||||
spawnInventory = controlledCharacter == null ? null : controlledCharacter.Inventory;
|
||||
break;
|
||||
case "cargo":
|
||||
var wp = WayPoint.GetRandom(SpawnType.Cargo, null, Submarine.MainSub);
|
||||
spawnPos = wp == null ? Vector2.Zero : wp.WorldPosition;
|
||||
break;
|
||||
//Dont do a thing, random is basically Human points anyways - its in the help description.
|
||||
case "random":
|
||||
extraParams = 1;
|
||||
return;
|
||||
default:
|
||||
extraParams = 0;
|
||||
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)
|
||||
{
|
||||
errorMsg = "Item \"" + itemName + "\" not found!";
|
||||
return;
|
||||
}
|
||||
|
||||
if (spawnPos == null && spawnInventory == null)
|
||||
if ((spawnPos == null || spawnPos == Vector2.Zero) && spawnInventory == null)
|
||||
{
|
||||
var wp = WayPoint.GetRandom(SpawnType.Human, null, Submarine.MainSub);
|
||||
spawnPos = wp == null ? Vector2.Zero : wp.WorldPosition;
|
||||
@@ -2198,6 +2230,7 @@ namespace Barotrauma
|
||||
if (spawnPos != null)
|
||||
{
|
||||
Entity.Spawner.AddToSpawnQueue(itemPrefab, (Vector2)spawnPos);
|
||||
|
||||
}
|
||||
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);
|
||||
|
||||
item = new Item(itemPrefab, position, null);
|
||||
item.MoveWithLevel = true;
|
||||
item.body.FarseerBody.IsKinematic = true;
|
||||
|
||||
//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)
|
||||
{
|
||||
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;
|
||||
|
||||
state = 1;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Barotrauma.Networking;
|
||||
using Barotrauma.Items.Components;
|
||||
using Barotrauma.Networking;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@@ -72,7 +73,7 @@ namespace Barotrauma
|
||||
descriptions[i] = descriptions[i].Replace("[location" + (n + 1) + "]", locations[n].Name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
teamNames = new string[]
|
||||
{
|
||||
prefab.ConfigElement.GetAttributeString("teamname1", "Team A"),
|
||||
@@ -145,6 +146,23 @@ namespace Barotrauma
|
||||
subs[1].SetPosition(Level.Loaded.EndPosition - new Vector2(0.0f, 2000.0f));
|
||||
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>() };
|
||||
|
||||
foreach (Submarine submarine in Submarine.Loaded)
|
||||
@@ -208,7 +226,7 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
if (winner>=0 && subs[winner] != null &&
|
||||
if (winner >= 0 && subs[winner] != null &&
|
||||
(winner == 0 && subs[winner].AtStartPosition) || (winner == 1 && subs[winner].AtEndPosition) &&
|
||||
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);
|
||||
|
||||
item = new Item(itemPrefab, position, null);
|
||||
item.MoveWithLevel = true;
|
||||
item.body.FarseerBody.IsKinematic = true;
|
||||
|
||||
if (item.HasTag("alien"))
|
||||
|
||||
@@ -1,19 +1,51 @@
|
||||
using GameAnalyticsSDK.Net;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
public static class GameAnalyticsManager
|
||||
{
|
||||
private static HashSet<string> sentEventIdentifiers = new HashSet<string>();
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
#if DEBUB
|
||||
#if DEBUG
|
||||
GameAnalytics.SetEnabledInfoLog(true);
|
||||
#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.Initialize("a3a073c20982de7c15d21e840e149122", "9010ad9a671233b8d9610d76cec8c897d9ff3ba7");
|
||||
|
||||
|
||||
string contentPackageName = GameMain.Config?.SelectedContentPackage?.Name;
|
||||
if (!string.IsNullOrEmpty(contentPackageName))
|
||||
{
|
||||
@@ -21,5 +53,47 @@ namespace Barotrauma
|
||||
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
|
||||
{
|
||||
class PurchasedItem
|
||||
{
|
||||
public ItemPrefab itemPrefab;
|
||||
public int quantity;
|
||||
|
||||
public PurchasedItem(ItemPrefab itemPrefab, int quantity)
|
||||
{
|
||||
this.itemPrefab = itemPrefab;
|
||||
this.quantity = quantity;
|
||||
}
|
||||
}
|
||||
|
||||
class CargoManager
|
||||
{
|
||||
private readonly List<ItemPrefab> purchasedItems;
|
||||
private readonly List<PurchasedItem> purchasedItems;
|
||||
|
||||
private readonly CampaignMode campaign;
|
||||
|
||||
public Action OnItemsChanged;
|
||||
|
||||
public List<ItemPrefab> PurchasedItems
|
||||
public List<PurchasedItem> PurchasedItems
|
||||
{
|
||||
get { return purchasedItems; }
|
||||
}
|
||||
|
||||
public CargoManager(CampaignMode campaign)
|
||||
{
|
||||
purchasedItems = new List<ItemPrefab>();
|
||||
purchasedItems = new List<PurchasedItem>();
|
||||
this.campaign = campaign;
|
||||
}
|
||||
|
||||
public void SetPurchasedItems(List<ItemPrefab> items)
|
||||
public void SetPurchasedItems(List<PurchasedItem> items)
|
||||
{
|
||||
purchasedItems.Clear();
|
||||
purchasedItems.AddRange(items);
|
||||
@@ -33,33 +45,53 @@ namespace Barotrauma
|
||||
OnItemsChanged?.Invoke();
|
||||
}
|
||||
|
||||
public void PurchaseItem(ItemPrefab item)
|
||||
public void PurchaseItem(ItemPrefab item, int Quantity = 1)
|
||||
{
|
||||
campaign.Money -= item.Price;
|
||||
purchasedItems.Add(item);
|
||||
PurchasedItem purchasedItem = PurchasedItems.Find(pi => pi.itemPrefab == 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();
|
||||
}
|
||||
|
||||
public void SellItem(ItemPrefab item)
|
||||
public void SellItem(ItemPrefab item, int quantity = 1)
|
||||
{
|
||||
campaign.Money += item.Price;
|
||||
purchasedItems.Remove(item);
|
||||
campaign.Money += (item.Price * quantity);
|
||||
PurchasedItem purchasedItem = PurchasedItems.Find(pi => pi.itemPrefab == item);
|
||||
if (purchasedItem != null && purchasedItem.quantity - quantity > 0)
|
||||
{
|
||||
purchasedItem.quantity -= quantity;
|
||||
}
|
||||
else
|
||||
{
|
||||
PurchasedItems.Remove(purchasedItem);
|
||||
}
|
||||
|
||||
OnItemsChanged?.Invoke();
|
||||
}
|
||||
|
||||
public int GetTotalItemCost()
|
||||
{
|
||||
return purchasedItems.Sum(i => i.Price);
|
||||
return purchasedItems.Sum(i => (i.itemPrefab.Price * i.quantity));
|
||||
}
|
||||
|
||||
public void CreateItems()
|
||||
{
|
||||
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);
|
||||
|
||||
@@ -78,24 +110,25 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
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(
|
||||
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;
|
||||
if (!string.IsNullOrEmpty(prefab.CargoContainerName))
|
||||
if (!string.IsNullOrEmpty(pi.itemPrefab.CargoContainerName))
|
||||
{
|
||||
itemContainer = availableContainers.Keys.ToList().Find(ac =>
|
||||
ac.Item.Prefab.NameMatches(prefab.CargoContainerName) ||
|
||||
ac.Item.Prefab.Tags.Contains(prefab.CargoContainerName.ToLowerInvariant()));
|
||||
ac.Item.Prefab.NameMatches(pi.itemPrefab.CargoContainerName) ||
|
||||
ac.Item.Prefab.Tags.Contains(pi.itemPrefab.CargoContainerName.ToLowerInvariant()));
|
||||
|
||||
if (itemContainer == null)
|
||||
{
|
||||
var containerPrefab = MapEntityPrefab.List.Find(ep =>
|
||||
ep.NameMatches(prefab.CargoContainerName) ||
|
||||
(ep.Tags != null && ep.Tags.Contains(prefab.CargoContainerName.ToLowerInvariant()))) as ItemPrefab;
|
||||
containerPrefab = MapEntityPrefab.List.Find(ep =>
|
||||
ep.NameMatches(pi.itemPrefab.CargoContainerName) ||
|
||||
(ep.Tags != null && ep.Tags.Contains(pi.itemPrefab.CargoContainerName.ToLowerInvariant()))) as ItemPrefab;
|
||||
|
||||
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
|
||||
if (GameMain.Server != null)
|
||||
{
|
||||
Entity.Spawner.AddToSpawnQueue(prefab, itemContainer.Inventory);
|
||||
Entity.Spawner.AddToSpawnQueue(pi.itemPrefab, itemContainer.Inventory);
|
||||
}
|
||||
else
|
||||
{
|
||||
var item = new Item(prefab, position, wp.Submarine);
|
||||
var item = new Item(pi.itemPrefab, position, wp.Submarine);
|
||||
itemContainer.Inventory.TryPutItem(item, null);
|
||||
}
|
||||
|
||||
//reduce the number of available slots in the container
|
||||
availableContainers[itemContainer]--;
|
||||
if (availableContainers[itemContainer] <= 0)
|
||||
//if there is a container
|
||||
if (availableContainers.ContainsKey(itemContainer))
|
||||
{
|
||||
availableContainers[itemContainer]--;
|
||||
}
|
||||
if (availableContainers.ContainsKey(itemContainer) && availableContainers[itemContainer] <= 0)
|
||||
{
|
||||
availableContainers.Remove(itemContainer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
itemsToSpawn.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -194,9 +194,10 @@ namespace Barotrauma
|
||||
msg.Write(Money);
|
||||
|
||||
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 purchasedItemCount = msg.ReadUInt16();
|
||||
|
||||
List<ItemPrefab> purchasedItems = new List<ItemPrefab>();
|
||||
List<PurchasedItem> purchasedItems = new List<PurchasedItem>();
|
||||
for (int i = 0; i < purchasedItemCount; i++)
|
||||
{
|
||||
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))
|
||||
@@ -220,15 +222,15 @@ namespace Barotrauma
|
||||
|
||||
Map.SelectLocation(selectedLocIndex == UInt16.MaxValue ? -1 : selectedLocIndex);
|
||||
|
||||
List<ItemPrefab> currentItems = new List<ItemPrefab>(CargoManager.PurchasedItems);
|
||||
foreach (ItemPrefab ip in currentItems)
|
||||
List<PurchasedItem> currentItems = new List<PurchasedItem>(CargoManager.PurchasedItems);
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
GameMain.LightManager.LosEnabled = GameMain.NetworkMember == null || GameMain.NetworkMember.CharacterInfo != null;
|
||||
@@ -210,11 +210,10 @@ namespace Barotrauma
|
||||
Submarine.MainSubs[1].Load(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (level != null)
|
||||
{
|
||||
level.Generate();
|
||||
|
||||
level.Generate(mirrorLevel);
|
||||
submarine.SetPosition(submarine.FindSpawnPos(level.StartPosition - new Vector2(0.0f, 2000.0f)));
|
||||
}
|
||||
|
||||
@@ -229,18 +228,17 @@ namespace Barotrauma
|
||||
if (GameMode != null)
|
||||
{
|
||||
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)
|
||||
{
|
||||
GameAnalyticsSDK.Net.GameAnalytics.AddDesignEvent("Submarine:" + submarine.Name);
|
||||
GameAnalyticsSDK.Net.GameAnalytics.AddProgressionEvent(GameAnalyticsSDK.Net.EGAProgressionStatus.Start,
|
||||
|
||||
GameAnalyticsManager.AddDesignEvent("Submarine:" + submarine.Name);
|
||||
GameAnalyticsManager.AddDesignEvent("Level", ToolBox.StringToInt(level.Seed));
|
||||
GameAnalyticsManager.AddProgressionEvent(GameAnalyticsSDK.Net.EGAProgressionStatus.Start,
|
||||
GameMode.Name, (Mission == null ? "None" : Mission.GetType().ToString()));
|
||||
}
|
||||
|
||||
|
||||
#if CLIENT
|
||||
roundSummary = new RoundSummary(this);
|
||||
@@ -253,11 +251,10 @@ namespace Barotrauma
|
||||
public void EndRound(string endMessage)
|
||||
{
|
||||
if (Mission != null) Mission.End();
|
||||
if (GameSettings.SendUserStatistics)
|
||||
{
|
||||
GameAnalyticsSDK.Net.GameAnalytics.AddProgressionEvent((Mission == null || Mission.Completed) ? GameAnalyticsSDK.Net.EGAProgressionStatus.Complete : GameAnalyticsSDK.Net.EGAProgressionStatus.Fail,
|
||||
GameMode.Name, (Mission == null ? "None" : Mission.GetType().ToString()));
|
||||
}
|
||||
GameAnalyticsManager.AddProgressionEvent(
|
||||
(Mission == null || Mission.Completed) ? GameAnalyticsSDK.Net.EGAProgressionStatus.Complete : GameAnalyticsSDK.Net.EGAProgressionStatus.Fail,
|
||||
GameMode.Name,
|
||||
(Mission == null ? "None" : Mission.GetType().ToString()));
|
||||
|
||||
#if CLIENT
|
||||
if (roundSummary != null)
|
||||
|
||||
@@ -164,7 +164,7 @@ namespace Barotrauma
|
||||
GameMain.Config.Save("config.xml");
|
||||
}
|
||||
}
|
||||
public static bool ShowUserStatisticsPrompt { get; private set; }
|
||||
public static bool ShowUserStatisticsPrompt { get; set; }
|
||||
|
||||
public GameSettings(string filePath)
|
||||
{
|
||||
@@ -334,8 +334,12 @@ namespace Barotrauma
|
||||
new XAttribute("soundvolume", soundVolume),
|
||||
new XAttribute("verboselogging", VerboseLogging),
|
||||
new XAttribute("savedebugconsolelogs", SaveDebugConsoleLogs),
|
||||
new XAttribute("enablesplashscreen", EnableSplashScreen),
|
||||
new XAttribute("senduserstatistics", sendUserStatistics));
|
||||
new XAttribute("enablesplashscreen", EnableSplashScreen));
|
||||
|
||||
if (!ShowUserStatisticsPrompt)
|
||||
{
|
||||
doc.Root.Add(new XAttribute("senduserstatistics", sendUserStatistics));
|
||||
}
|
||||
|
||||
if (WasGameUpdated)
|
||||
{
|
||||
@@ -398,7 +402,16 @@ namespace Barotrauma
|
||||
new XAttribute("gender", characterGender));
|
||||
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()
|
||||
|
||||
@@ -50,6 +50,10 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
if (ic.DeleteOnUse)
|
||||
|
||||
@@ -27,18 +27,14 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
private Joint joint;
|
||||
|
||||
private Hull[] hulls;
|
||||
private ushort?[] hullIds;
|
||||
private readonly Hull[] hulls = new Hull[2];
|
||||
private Gap gap;
|
||||
|
||||
private Door door;
|
||||
|
||||
private Body[] bodies;
|
||||
|
||||
private Body doorBody;
|
||||
|
||||
private Gap gap;
|
||||
private ushort? gapId;
|
||||
|
||||
private bool docked;
|
||||
|
||||
public int DockingDir
|
||||
@@ -114,9 +110,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
|
||||
IsActive = true;
|
||||
|
||||
hullIds = new ushort?[2];
|
||||
|
||||
|
||||
list.Add(this);
|
||||
}
|
||||
|
||||
@@ -129,7 +123,7 @@ namespace Barotrauma.Items.Components
|
||||
if (joint != null)
|
||||
{
|
||||
CreateJoint(joint is WeldJoint);
|
||||
LinkHullsToGap();
|
||||
LinkHullsToGaps();
|
||||
}
|
||||
else if (dockingTarget.joint != null)
|
||||
{
|
||||
@@ -138,7 +132,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
dockingTarget.CreateJoint(dockingTarget.joint is WeldJoint);
|
||||
}
|
||||
dockingTarget.LinkHullsToGap();
|
||||
dockingTarget.LinkHullsToGaps();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -207,22 +201,16 @@ namespace Barotrauma.Items.Components
|
||||
Math.Sign(dockingTarget.item.WorldPosition.X - item.WorldPosition.X) :
|
||||
Math.Sign(dockingTarget.item.WorldPosition.Y - item.WorldPosition.Y);
|
||||
dockingTarget.dockingDir = -dockingDir;
|
||||
|
||||
|
||||
foreach (WayPoint wp in WayPoint.WayPointList)
|
||||
if (door != null && dockingTarget.door != null)
|
||||
{
|
||||
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;
|
||||
|
||||
foreach (WayPoint wp2 in WayPoint.WayPointList)
|
||||
if (myWayPoint != null && targetWayPoint != null)
|
||||
{
|
||||
if (wp2.Submarine != dockingTarget.item.Submarine || wp2.SpawnType != SpawnType.Path) continue;
|
||||
|
||||
if (!Submarine.RectContains(dockingTarget.item.Rect, wp2.Position)) continue;
|
||||
|
||||
wp.linkedTo.Add(wp2);
|
||||
wp2.linkedTo.Add(wp);
|
||||
myWayPoint.linkedTo.Add(targetWayPoint);
|
||||
targetWayPoint.linkedTo.Add(myWayPoint);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -238,35 +226,37 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
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");
|
||||
return;
|
||||
}
|
||||
else if (joint is WeldJoint)
|
||||
{
|
||||
//DebugConsole.ThrowError("Error - attempted to lock a docking port that's already locked");
|
||||
return;
|
||||
}
|
||||
|
||||
dockingDir = IsHorizontal ?
|
||||
Math.Sign(dockingTarget.item.WorldPosition.X - item.WorldPosition.X) :
|
||||
Math.Sign(dockingTarget.item.WorldPosition.Y - item.WorldPosition.Y);
|
||||
dockingTarget.dockingDir = -dockingDir;
|
||||
if (!(joint is WeldJoint))
|
||||
{
|
||||
|
||||
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
|
||||
PlaySound(ActionType.OnSecondaryUse, item.WorldPosition);
|
||||
PlaySound(ActionType.OnSecondaryUse, item.WorldPosition);
|
||||
#endif
|
||||
|
||||
ConnectWireBetweenPorts();
|
||||
ConnectWireBetweenPorts();
|
||||
CreateJoint(true);
|
||||
|
||||
CreateJoint(true);
|
||||
|
||||
if (GameMain.Server != null)
|
||||
{
|
||||
item.CreateServerEvent(this);
|
||||
if (GameMain.Server != null)
|
||||
{
|
||||
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))
|
||||
{
|
||||
CreateHull();
|
||||
@@ -345,17 +335,31 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
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,
|
||||
dockingTarget.door.Body.width,
|
||||
dockingTarget.door.Body.height,
|
||||
1.0f,
|
||||
position,
|
||||
dockingTarget.door);
|
||||
|
||||
doorBody.CollisionCategories = Physics.CollisionWall;
|
||||
doorBody.BodyType = BodyType.Static;
|
||||
doorBody.SetTransform(
|
||||
ConvertUnits.ToSimUnits(item.Position + (dockingTarget.door.Item.WorldPosition - item.WorldPosition)),
|
||||
0.0f);
|
||||
}
|
||||
|
||||
private void CreateHull()
|
||||
@@ -363,7 +367,6 @@ namespace Barotrauma.Items.Components
|
||||
var hullRects = new Rectangle[] { item.WorldRect, dockingTarget.item.WorldRect };
|
||||
var subs = new Submarine[] { item.Submarine, dockingTarget.item.Submarine };
|
||||
|
||||
hulls = new Hull[2];
|
||||
bodies = new Body[4];
|
||||
|
||||
if (dockingTarget.door != null)
|
||||
@@ -392,6 +395,7 @@ namespace Barotrauma.Items.Components
|
||||
hullRects[i].Location -= MathUtils.ToPoint((subs[i].WorldPosition - subs[i].HiddenSubPosition));
|
||||
hulls[i] = new Hull(MapEntityPrefab.Find("Hull"), hullRects[i], subs[i]);
|
||||
hulls[i].AddToGrid(subs[i]);
|
||||
hulls[i].FreeID();
|
||||
|
||||
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]);
|
||||
if (gapId != null) gap.ID = (ushort)gapId;
|
||||
|
||||
LinkHullsToGap();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -422,25 +423,22 @@ namespace Barotrauma.Items.Components
|
||||
hullRects[i].Location -= MathUtils.ToPoint((subs[i].WorldPosition - subs[i].HiddenSubPosition));
|
||||
hulls[i] = new Hull(MapEntityPrefab.Find("Hull"), hullRects[i], subs[i]);
|
||||
hulls[i].AddToGrid(subs[i]);
|
||||
|
||||
if (hullIds[i] != null) hulls[i].ID = (ushort)hullIds[i];
|
||||
hulls[i].FreeID();
|
||||
}
|
||||
|
||||
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[1]);
|
||||
|
||||
hullIds[0] = hulls[0].ID;
|
||||
hullIds[1] = hulls[1].ID;
|
||||
|
||||
gap.FreeID();
|
||||
gap.DisableHullRechecks = true;
|
||||
gapId = gap.ID;
|
||||
|
||||
gap.ShouldBeSaved = false;
|
||||
item.linkedTo.Add(gap);
|
||||
|
||||
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)
|
||||
{
|
||||
@@ -491,6 +489,37 @@ namespace Barotrauma.Items.Components
|
||||
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()
|
||||
@@ -503,25 +532,19 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
dockingTarget.item.Submarine.DockedTo.Remove(item.Submarine);
|
||||
item.Submarine.DockedTo.Remove(dockingTarget.item.Submarine);
|
||||
|
||||
//remove all waypoint links between this sub and the dockingtarget
|
||||
foreach (WayPoint wp in WayPoint.WayPointList)
|
||||
|
||||
if (door != null && dockingTarget.door != null)
|
||||
{
|
||||
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;
|
||||
if (wp2 == null) continue;
|
||||
|
||||
if (wp.Submarine == dockingTarget.item.Submarine)
|
||||
{
|
||||
wp.linkedTo.RemoveAt(i);
|
||||
wp2.linkedTo.Remove(wp);
|
||||
}
|
||||
myWayPoint.linkedTo.Remove(targetWayPoint);
|
||||
targetWayPoint.linkedTo.Remove(myWayPoint);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
item.linkedTo.Clear();
|
||||
|
||||
docked = false;
|
||||
@@ -546,26 +569,17 @@ namespace Barotrauma.Items.Components
|
||||
GameMain.World.RemoveJoint(joint);
|
||||
joint = null;
|
||||
}
|
||||
|
||||
if (hulls != null)
|
||||
{
|
||||
hulls[0].Remove();
|
||||
hulls[1].Remove();
|
||||
hulls = null;
|
||||
}
|
||||
|
||||
hulls[0]?.Remove(); hulls[0] = null;
|
||||
hulls[1]?.Remove(); hulls[1] = null;
|
||||
|
||||
if (gap != null)
|
||||
{
|
||||
gap.Remove();
|
||||
gap = null;
|
||||
}
|
||||
|
||||
hullIds[0] = null;
|
||||
hullIds[1] = null;
|
||||
|
||||
gapId = null;
|
||||
|
||||
if (bodies!=null)
|
||||
if (bodies != null)
|
||||
{
|
||||
foreach (Body body in bodies)
|
||||
{
|
||||
@@ -627,6 +641,9 @@ namespace Barotrauma.Items.Components
|
||||
protected override void RemoveComponentSpecific()
|
||||
{
|
||||
list.Remove(this);
|
||||
hulls[0]?.Remove(); hulls[0] = null;
|
||||
hulls[1]?.Remove(); hulls[1] = null;
|
||||
gap?.Remove(); gap = null;
|
||||
}
|
||||
|
||||
public override void OnMapLoaded()
|
||||
@@ -715,19 +732,8 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
if (docked)
|
||||
{
|
||||
msg.Write(dockingTarget.item.ID);
|
||||
|
||||
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);
|
||||
}
|
||||
msg.Write(dockingTarget.item.ID);
|
||||
msg.Write(hulls != null && hulls[0] != null && hulls[1] != null && gap != null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -735,19 +741,27 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
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)
|
||||
{
|
||||
ushort dockingTargetID = msg.ReadUInt16();
|
||||
|
||||
bool isLocked = msg.ReadBoolean();
|
||||
|
||||
if (isLocked)
|
||||
{
|
||||
hullIds[0] = msg.ReadUInt16();
|
||||
hullIds[1] = msg.ReadUInt16();
|
||||
gapId = msg.ReadUInt16();
|
||||
}
|
||||
|
||||
|
||||
Entity targetEntity = Entity.FindEntityByID(dockingTargetID);
|
||||
if (targetEntity == null || !(targetEntity is Item))
|
||||
{
|
||||
@@ -767,10 +781,6 @@ namespace Barotrauma.Items.Components
|
||||
if (isLocked)
|
||||
{
|
||||
Lock(true);
|
||||
|
||||
hulls[0].ID = (ushort)hullIds[0];
|
||||
hulls[1].ID = (ushort)hullIds[1];
|
||||
gap.ID = (ushort)gapId;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -334,9 +334,13 @@ namespace Barotrauma.Items.Components
|
||||
body.Remove();
|
||||
body = null;
|
||||
}
|
||||
|
||||
|
||||
if (linkedGap != null) linkedGap.Remove();
|
||||
|
||||
//no need to remove the gap if we're unloading the whole submarine
|
||||
//otherwise the gap will be removed twice and cause console warnings
|
||||
if (!Submarine.Unloading)
|
||||
{
|
||||
if (linkedGap != null) linkedGap.Remove();
|
||||
}
|
||||
|
||||
doorSprite.Remove();
|
||||
if (weldedSprite != null) weldedSprite.Remove();
|
||||
@@ -349,6 +353,14 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
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
|
||||
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)
|
||||
{
|
||||
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);
|
||||
|
||||
List<PhysicsBody> bodies = c.AnimController.Limbs.Select(l => l.body).ToList();
|
||||
@@ -368,17 +390,24 @@ namespace Barotrauma.Items.Components
|
||||
foreach (PhysicsBody body in bodies)
|
||||
{
|
||||
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 (body.SimPosition.X < simPos.X || body.SimPosition.X > simPos.X + simSize.X) continue;
|
||||
|
||||
diff = body.SimPosition.Y - item.SimPosition.Y;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (body.SimPosition.Y > simPos.Y || body.SimPosition.Y < simPos.Y - simSize.Y) continue;
|
||||
|
||||
diff = body.SimPosition.X - item.SimPosition.X;
|
||||
}
|
||||
|
||||
@@ -442,8 +471,10 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
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)
|
||||
{
|
||||
//clients can "predict" that the door opens/closes when a signal is received
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
Drop(true, dropper);
|
||||
@@ -160,7 +171,24 @@ namespace Barotrauma.Items.Components
|
||||
if (item.body != null)
|
||||
{
|
||||
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);
|
||||
@@ -214,6 +242,14 @@ namespace Barotrauma.Items.Components
|
||||
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)
|
||||
{
|
||||
if (!attachable)
|
||||
@@ -221,6 +257,8 @@ namespace Barotrauma.Items.Components
|
||||
return base.Pick(picker);
|
||||
}
|
||||
|
||||
if (!CanBeDeattached()) return false;
|
||||
|
||||
if (Attached)
|
||||
{
|
||||
return base.Pick(picker);
|
||||
@@ -330,7 +368,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
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
|
||||
{
|
||||
@@ -410,7 +448,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
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());
|
||||
|
||||
if (!attachable)
|
||||
@@ -419,7 +457,7 @@ namespace Barotrauma.Items.Components
|
||||
return;
|
||||
}
|
||||
|
||||
if (isAttached)
|
||||
if (shouldBeAttached)
|
||||
{
|
||||
Drop(false, null);
|
||||
item.SetTransform(simPosition, 0.0f);
|
||||
@@ -427,16 +465,19 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
else
|
||||
{
|
||||
DropConnectedWires(null);
|
||||
|
||||
if (body != null)
|
||||
if (attached)
|
||||
{
|
||||
item.body = body;
|
||||
item.body.Enabled = true;
|
||||
}
|
||||
IsActive = false;
|
||||
DropConnectedWires(null);
|
||||
|
||||
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 Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
@@ -24,6 +25,8 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
private float reloadTimer;
|
||||
|
||||
private HashSet<Entity> hitTargets = new HashSet<Entity>();
|
||||
|
||||
[Serialize(0.0f, false)]
|
||||
public float Range
|
||||
{
|
||||
@@ -94,6 +97,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
|
||||
hitting = true;
|
||||
hitTargets.Clear();
|
||||
|
||||
IsActive = true;
|
||||
return false;
|
||||
@@ -131,8 +135,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
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);
|
||||
}
|
||||
else
|
||||
@@ -142,28 +145,13 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
else
|
||||
{
|
||||
//Vector2 diff = Vector2.Normalize(picker.CursorPosition - ac.RefLimb.Position);
|
||||
//diff.X = diff.X * ac.Dir;
|
||||
|
||||
hitPos -= deltaTime*15.0f;
|
||||
|
||||
//angl = -hitPos * 2.0f;
|
||||
// System.Diagnostics.Debug.WriteLine("<1.0f "+hitPos);
|
||||
|
||||
|
||||
|
||||
hitPos -= deltaTime * 15.0f;
|
||||
ac.HoldItem(deltaTime, item, handlePos, new Vector2(0.6f, -0.1f), new Vector2(-0.3f, 0.2f), false, hitPos);
|
||||
//}
|
||||
//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)
|
||||
if (hitPos < -MathHelper.PiOver4 * 1.2f)
|
||||
{
|
||||
RestoreCollision();
|
||||
hitting = false;
|
||||
hitTargets.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -230,15 +218,22 @@ namespace Barotrauma.Items.Components
|
||||
targetLimb = (Limb)f2.Body.UserData;
|
||||
if (targetLimb.IsSevered || targetLimb.character == null) return false;
|
||||
targetCharacter = targetLimb.character;
|
||||
|
||||
if (hitTargets.Contains(targetCharacter)) return false;
|
||||
hitTargets.Add(targetCharacter);
|
||||
}
|
||||
else if (f2.Body.UserData is Character)
|
||||
{
|
||||
targetCharacter = (Character)f2.Body.UserData;
|
||||
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)
|
||||
{
|
||||
targetStructure = (Structure)f2.Body.UserData;
|
||||
if (hitTargets.Contains(targetStructure)) return false;
|
||||
hitTargets.Add(targetStructure);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -266,10 +261,7 @@ namespace Barotrauma.Items.Components
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
RestoreCollision();
|
||||
hitting = false;
|
||||
|
||||
|
||||
if (GameMain.Client != null) return true;
|
||||
|
||||
if (GameMain.Server != null && targetCharacter != null) //TODO: Log structure hits
|
||||
|
||||
@@ -127,18 +127,8 @@ namespace Barotrauma.Items.Components
|
||||
Color.Red, Color.Green);
|
||||
#endif
|
||||
|
||||
picker.AnimController.Anim = AnimController.Animation.UsingConstruction;
|
||||
|
||||
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);
|
||||
|
||||
picker.AnimController.UpdateUseItem(true, item.SimPosition + Vector2.UnitY * ((pickTimer / 10.0f) % 0.1f));
|
||||
|
||||
pickTimer += CoroutineManager.DeltaTime;
|
||||
|
||||
yield return CoroutineStatus.Running;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user