Merge branch 'master' into patch-2
This commit is contained in:
@@ -31,5 +31,5 @@ using System.Runtime.InteropServices;
|
|||||||
// You can specify all the values or you can default the Build and Revision Numbers
|
// You can specify all the values or you can default the Build and Revision Numbers
|
||||||
// by using the '*' as shown below:
|
// by using the '*' as shown below:
|
||||||
// [assembly: AssemblyVersion("1.0.*")]
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
[assembly: AssemblyVersion("0.8.1.4")]
|
[assembly: AssemblyVersion("0.8.1.5")]
|
||||||
[assembly: AssemblyFileVersion("0.8.1.4")]
|
[assembly: AssemblyFileVersion("0.8.1.5")]
|
||||||
|
|||||||
@@ -394,7 +394,7 @@ namespace Barotrauma
|
|||||||
NewMessage(GUI.DisableHUD ? "Disabled HUD" : "Enabled HUD", Color.White);
|
NewMessage(GUI.DisableHUD ? "Disabled HUD" : "Enabled HUD", Color.White);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
commands.Add(new Command("followsub", "followsub: Toggle whether the ", (string[] args) =>
|
commands.Add(new Command("followsub", "followsub: Toggle whether the camera should follow the nearest submarine.", (string[] args) =>
|
||||||
{
|
{
|
||||||
Camera.FollowSub = !Camera.FollowSub;
|
Camera.FollowSub = !Camera.FollowSub;
|
||||||
NewMessage(Camera.FollowSub ? "Set the camera to follow the closest submarine" : "Disabled submarine following.", Color.White);
|
NewMessage(Camera.FollowSub ? "Set the camera to follow the closest submarine" : "Disabled submarine following.", Color.White);
|
||||||
|
|||||||
@@ -822,7 +822,7 @@ namespace Barotrauma.Networking
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
submarines.Add(new Submarine(Path.Combine(Submarine.SavePath, subName), subHash, false));
|
submarines.Add(new Submarine(Path.Combine(Submarine.SavePath, subName) + ".sub", subHash, false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1441,6 +1441,8 @@ namespace Barotrauma.Networking
|
|||||||
msg.Write((byte)ClientPermissions.Ban);
|
msg.Write((byte)ClientPermissions.Ban);
|
||||||
msg.Write(kickedName);
|
msg.Write(kickedName);
|
||||||
msg.Write(reason);
|
msg.Write(reason);
|
||||||
|
msg.Write(range);
|
||||||
|
msg.Write(duration.HasValue ? duration.Value.TotalSeconds : 0.0); //0 = permaban
|
||||||
|
|
||||||
client.SendMessage(msg, NetDeliveryMethod.ReliableUnordered);
|
client.SendMessage(msg, NetDeliveryMethod.ReliableUnordered);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,10 +3,10 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using GameAnalyticsSDK.Net;
|
||||||
|
|
||||||
#if WINDOWS
|
#if WINDOWS
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using GameAnalyticsSDK.Net;
|
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -561,14 +561,18 @@ namespace Barotrauma
|
|||||||
var playYourself = new GUITickBox(new Rectangle(0, 0, 20, 20), TextManager.Get("PlayYourself"), Alignment.TopLeft, myPlayerFrame);
|
var playYourself = new GUITickBox(new Rectangle(0, 0, 20, 20), TextManager.Get("PlayYourself"), Alignment.TopLeft, myPlayerFrame);
|
||||||
playYourself.Selected = GameMain.NetworkMember.CharacterInfo != null;
|
playYourself.Selected = GameMain.NetworkMember.CharacterInfo != null;
|
||||||
playYourself.OnSelected = TogglePlayYourself;
|
playYourself.OnSelected = TogglePlayYourself;
|
||||||
playYourself.UserData = "playyourself";
|
playYourself.UserData = "playyourself";
|
||||||
|
|
||||||
GUIButton toggleHead = new GUIButton(new Rectangle(0, 50, 15, 15), "<", "", myPlayerFrame);
|
GUIButton toggleHead = new GUIButton(new Rectangle(0, 50, 15, 15), "<", "", myPlayerFrame)
|
||||||
toggleHead.UserData = -1;
|
{
|
||||||
toggleHead.OnClicked = ToggleHead;
|
UserData = -1,
|
||||||
toggleHead = new GUIButton(new Rectangle(60, 50, 15, 15), ">", "", myPlayerFrame);
|
OnClicked = ToggleHead
|
||||||
toggleHead.UserData = 1;
|
};
|
||||||
toggleHead.OnClicked = ToggleHead;
|
toggleHead = new GUIButton(new Rectangle(60, 50, 15, 15), ">", "", myPlayerFrame)
|
||||||
|
{
|
||||||
|
UserData = 1,
|
||||||
|
OnClicked = ToggleHead
|
||||||
|
};
|
||||||
|
|
||||||
new GUITextBlock(new Rectangle(100, 30, 200, 30), TextManager.Get("Gender"), "", myPlayerFrame);
|
new GUITextBlock(new Rectangle(100, 30, 200, 30), TextManager.Get("Gender"), "", myPlayerFrame);
|
||||||
|
|
||||||
@@ -631,7 +635,10 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (tickBox.Selected)
|
if (tickBox.Selected)
|
||||||
{
|
{
|
||||||
GameMain.NetworkMember.CharacterInfo = new CharacterInfo(Character.HumanConfigFile, GameMain.NetworkMember.Name, Gender.None, null);
|
GameMain.NetworkMember.CharacterInfo =
|
||||||
|
new CharacterInfo(Character.HumanConfigFile, GameMain.NetworkMember.Name, GameMain.Config.CharacterGender, null);
|
||||||
|
GameMain.NetworkMember.CharacterInfo.HeadSpriteId = GameMain.Config.CharacterHeadIndex;
|
||||||
|
|
||||||
UpdatePlayerFrame(GameMain.NetworkMember.CharacterInfo);
|
UpdatePlayerFrame(GameMain.NetworkMember.CharacterInfo);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1249,14 +1256,12 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private bool ToggleHead(GUIButton button, object userData)
|
private bool ToggleHead(GUIButton button, object userData)
|
||||||
{
|
{
|
||||||
int dir = (int)userData;
|
|
||||||
|
|
||||||
if (GameMain.NetworkMember.CharacterInfo == null) return true;
|
if (GameMain.NetworkMember.CharacterInfo == null) return true;
|
||||||
|
|
||||||
|
int dir = (int)userData;
|
||||||
GameMain.NetworkMember.CharacterInfo.HeadSpriteId += dir;
|
GameMain.NetworkMember.CharacterInfo.HeadSpriteId += dir;
|
||||||
|
GameMain.Config.CharacterHeadIndex = GameMain.NetworkMember.CharacterInfo.HeadSpriteId;
|
||||||
UpdatePlayerHead(GameMain.NetworkMember.CharacterInfo);
|
UpdatePlayerHead(GameMain.NetworkMember.CharacterInfo);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1264,7 +1269,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
Gender gender = (Gender)obj;
|
Gender gender = (Gender)obj;
|
||||||
GameMain.NetworkMember.CharacterInfo.Gender = gender;
|
GameMain.NetworkMember.CharacterInfo.Gender = gender;
|
||||||
|
GameMain.Config.CharacterGender = GameMain.NetworkMember.CharacterInfo.Gender;
|
||||||
UpdatePlayerHead(GameMain.NetworkMember.CharacterInfo);
|
UpdatePlayerHead(GameMain.NetworkMember.CharacterInfo);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,5 +31,5 @@ using System.Runtime.InteropServices;
|
|||||||
// You can specify all the values or you can default the Build and Revision Numbers
|
// You can specify all the values or you can default the Build and Revision Numbers
|
||||||
// by using the '*' as shown below:
|
// by using the '*' as shown below:
|
||||||
// [assembly: AssemblyVersion("1.0.*")]
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
[assembly: AssemblyVersion("0.8.1.4")]
|
[assembly: AssemblyVersion("0.8.1.5")]
|
||||||
[assembly: AssemblyFileVersion("0.8.1.4")]
|
[assembly: AssemblyFileVersion("0.8.1.5")]
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
lock (QueuedCommands)
|
lock (QueuedCommands)
|
||||||
{
|
{
|
||||||
while (QueuedCommands.Count>0)
|
while (QueuedCommands.Count > 0)
|
||||||
{
|
{
|
||||||
ExecuteCommand(QueuedCommands[0]);
|
ExecuteCommand(QueuedCommands[0]);
|
||||||
QueuedCommands.RemoveAt(0);
|
QueuedCommands.RemoveAt(0);
|
||||||
@@ -190,6 +190,16 @@ namespace Barotrauma
|
|||||||
NewMessage(ent.ToString(), Color.Lime);
|
NewMessage(ent.ToString(), Color.Lime);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
//"dummy commands" that only exist so that the server can give clients permissions to use them
|
||||||
|
commands.Add(new Command("control|controlcharacter", "control [character name]: Start controlling the specified character (client-only).", null));
|
||||||
|
commands.Add(new Command("los", "Toggle the line of sight effect on/off (client-only).", null));
|
||||||
|
commands.Add(new Command("lighting|lights", "Toggle lighting on/off (client-only).", null));
|
||||||
|
commands.Add(new Command("debugdraw", "Toggle the debug drawing mode on/off (client-only).", null));
|
||||||
|
commands.Add(new Command("togglehud|hud", "Toggle the character HUD (inventories, icons, buttons, etc) on/off (client-only).", null));
|
||||||
|
commands.Add(new Command("followsub", "Toggle whether the camera should follow the nearest submarine (client-only).", null));
|
||||||
|
commands.Add(new Command("toggleaitargets|aitargets", "Toggle the visibility of AI targets (= targets that enemies can detect and attack/escape from) (client-only).", null));
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
commands.Add(new Command("eventdata", "", (string[] args) =>
|
commands.Add(new Command("eventdata", "", (string[] args) =>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -17,9 +17,11 @@
|
|||||||
|
|
||||||
<Pickable holdpos="30,-15" handle1="0,1" slots="RightHand,LeftHand,Any">
|
<Pickable holdpos="30,-15" handle1="0,1" slots="RightHand,LeftHand,Any">
|
||||||
<StatusEffect type="OnFire" target="This" Condition="-100.0" disabledeltatime="true">
|
<StatusEffect type="OnFire" target="This" Condition="-100.0" disabledeltatime="true">
|
||||||
|
<Conditional Condition="gt 25"/>
|
||||||
<sound file="Content/Items/Reactor/explosion.ogg"/>
|
<sound file="Content/Items/Reactor/explosion.ogg"/>
|
||||||
<Explosion range="250.0" structuredamage="10" damage="20" stun="5" force="3.0"/>
|
<Explosion range="250.0" structuredamage="10" damage="20" stun="5" force="3.0"/>
|
||||||
</StatusEffect>
|
</StatusEffect>
|
||||||
|
<StatusEffect type="OnFire" target="This" Condition="-100.0" disabledeltatime="true"/>
|
||||||
</Pickable>
|
</Pickable>
|
||||||
</Item>
|
</Item>
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
</fixrequirement>
|
</fixrequirement>
|
||||||
|
|
||||||
<OxygenGenerator powerconsumption="1000.0" minvoltage="0.5" canbeselected = "true">
|
<OxygenGenerator powerconsumption="1000.0" minvoltage="0.5" canbeselected = "true">
|
||||||
|
|
||||||
<StatusEffect type="OnFire" target="This" Condition="-0.5"/>
|
<StatusEffect type="OnFire" target="This" Condition="-0.5"/>
|
||||||
<StatusEffect type="OnActive" target="Contained" targetnames="Oxygen Tank" Condition="2.0"/>
|
<StatusEffect type="OnActive" target="Contained" targetnames="Oxygen Tank" Condition="2.0"/>
|
||||||
<StatusEffect type="OnActive" target="Contained" targetnames="Oxygenite Tank" Condition="0.0"/>
|
<StatusEffect type="OnActive" target="Contained" targetnames="Oxygenite Tank" Condition="0.0"/>
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ namespace Barotrauma
|
|||||||
public float Range { get; private set; }
|
public float Range { get; private set; }
|
||||||
|
|
||||||
[Serialize(0.0f, false)]
|
[Serialize(0.0f, false)]
|
||||||
public float DamageRange { get; private set; }
|
public float DamageRange { get; set; }
|
||||||
|
|
||||||
[Serialize(0.0f, false)]
|
[Serialize(0.0f, false)]
|
||||||
public float Duration { get; private set; }
|
public float Duration { get; private set; }
|
||||||
|
|||||||
@@ -88,6 +88,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public void Execute(string[] args)
|
public void Execute(string[] args)
|
||||||
{
|
{
|
||||||
|
if (onExecute == null) return;
|
||||||
onExecute(args);
|
onExecute(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,6 +101,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (onClientRequestExecute == null)
|
if (onClientRequestExecute == null)
|
||||||
{
|
{
|
||||||
|
if (onExecute == null) return;
|
||||||
onExecute(args);
|
onExecute(args);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -247,11 +249,10 @@ namespace Barotrauma
|
|||||||
};
|
};
|
||||||
}));
|
}));
|
||||||
|
|
||||||
commands.Add(new Command("spawnitem", "spawnitem [itemname] [cursor/inventory]: Spawn an item at the position of the cursor, in the inventory of the controlled character or at a random spawnpoint if the last parameter is omitted.",
|
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\".",
|
||||||
(string[] args) =>
|
(string[] args) =>
|
||||||
{
|
{
|
||||||
string errorMsg;
|
SpawnItem(args, GameMain.GameScreen.Cam.ScreenToWorld(PlayerInput.MousePosition), Character.Controlled, out string errorMsg);
|
||||||
SpawnItem(args, GameMain.GameScreen.Cam.ScreenToWorld(PlayerInput.MousePosition), out errorMsg);
|
|
||||||
if (!string.IsNullOrWhiteSpace(errorMsg))
|
if (!string.IsNullOrWhiteSpace(errorMsg))
|
||||||
{
|
{
|
||||||
ThrowError(errorMsg);
|
ThrowError(errorMsg);
|
||||||
@@ -260,20 +261,18 @@ namespace Barotrauma
|
|||||||
null,
|
null,
|
||||||
(Client client, Vector2 cursorWorldPos, string[] args) =>
|
(Client client, Vector2 cursorWorldPos, string[] args) =>
|
||||||
{
|
{
|
||||||
string errorMsg;
|
SpawnItem(args, cursorWorldPos, client.Character, out string errorMsg);
|
||||||
SpawnItem(args, cursorWorldPos, out errorMsg);
|
|
||||||
if (!string.IsNullOrWhiteSpace(errorMsg))
|
if (!string.IsNullOrWhiteSpace(errorMsg))
|
||||||
{
|
{
|
||||||
ThrowError(errorMsg);
|
GameMain.Server.SendConsoleMessage(errorMsg, client);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
() =>
|
() =>
|
||||||
{
|
{
|
||||||
List<string> itemNames = new List<string>();
|
List<string> itemNames = new List<string>();
|
||||||
foreach (MapEntityPrefab prefab in MapEntityPrefab.List)
|
foreach (MapEntityPrefab prefab in MapEntityPrefab.List)
|
||||||
{
|
{
|
||||||
ItemPrefab itemPrefab = prefab as ItemPrefab;
|
if (prefab is ItemPrefab itemPrefab) itemNames.Add(itemPrefab.Name);
|
||||||
if (itemPrefab != null) itemNames.Add(itemPrefab.Name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return new string[][]
|
return new string[][]
|
||||||
@@ -283,6 +282,7 @@ namespace Barotrauma
|
|||||||
};
|
};
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
||||||
commands.Add(new Command("disablecrewai", "disablecrewai: Disable the AI of the NPCs in the crew.", (string[] args) =>
|
commands.Add(new Command("disablecrewai", "disablecrewai: Disable the AI of the NPCs in the crew.", (string[] args) =>
|
||||||
{
|
{
|
||||||
HumanAIController.DisableCrewAI = true;
|
HumanAIController.DisableCrewAI = true;
|
||||||
@@ -849,8 +849,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (args.Length < 2) return;
|
if (args.Length < 2) return;
|
||||||
|
|
||||||
int id;
|
int.TryParse(args[0], out int id);
|
||||||
int.TryParse(args[0], out id);
|
|
||||||
var client = GameMain.Server.ConnectedClients.Find(c => c.ID == id);
|
var client = GameMain.Server.ConnectedClients.Find(c => c.ID == id);
|
||||||
if (client == null)
|
if (client == null)
|
||||||
{
|
{
|
||||||
@@ -891,8 +890,7 @@ namespace Barotrauma
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int id;
|
int.TryParse(args[0], out int id);
|
||||||
int.TryParse(args[0], out id);
|
|
||||||
var client = GameMain.Server.ConnectedClients.Find(c => c.ID == id);
|
var client = GameMain.Server.ConnectedClients.Find(c => c.ID == id);
|
||||||
if (client == null)
|
if (client == null)
|
||||||
{
|
{
|
||||||
@@ -1019,11 +1017,10 @@ namespace Barotrauma
|
|||||||
|
|
||||||
commands.Add(new Command("kickid", "kickid [id]: Kick the player with the specified client ID out of the server.", (string[] args) =>
|
commands.Add(new Command("kickid", "kickid [id]: Kick the player with the specified client ID out of the server.", (string[] args) =>
|
||||||
{
|
{
|
||||||
if (GameMain.Server == null || args.Length == 0) return;
|
if (GameMain.NetworkMember == null || args.Length == 0) return;
|
||||||
|
|
||||||
int id = 0;
|
int.TryParse(args[0], out int id);
|
||||||
int.TryParse(args[0], out id);
|
var client = GameMain.NetworkMember.ConnectedClients.Find(c => c.ID == id);
|
||||||
var client = GameMain.Server.ConnectedClients.Find(c => c.ID == id);
|
|
||||||
if (client == null)
|
if (client == null)
|
||||||
{
|
{
|
||||||
ThrowError("Client id \"" + id + "\" not found.");
|
ThrowError("Client id \"" + id + "\" not found.");
|
||||||
@@ -1032,7 +1029,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
ShowQuestionPrompt("Reason for kicking \"" + client.Name + "\"?", (reason) =>
|
ShowQuestionPrompt("Reason for kicking \"" + client.Name + "\"?", (reason) =>
|
||||||
{
|
{
|
||||||
GameMain.Server.KickPlayer(client.Name, reason);
|
GameMain.NetworkMember.KickPlayer(client.Name, reason);
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@@ -1073,17 +1070,16 @@ namespace Barotrauma
|
|||||||
|
|
||||||
commands.Add(new Command("banid", "banid [id]: Kick and ban the player with the specified client ID from the server.", (string[] args) =>
|
commands.Add(new Command("banid", "banid [id]: Kick and ban the player with the specified client ID from the server.", (string[] args) =>
|
||||||
{
|
{
|
||||||
if (GameMain.Server == null || args.Length == 0) return;
|
if (GameMain.NetworkMember == null || args.Length == 0) return;
|
||||||
|
|
||||||
int id = 0;
|
int.TryParse(args[0], out int id);
|
||||||
int.TryParse(args[0], out id);
|
var client = GameMain.NetworkMember.ConnectedClients.Find(c => c.ID == id);
|
||||||
var client = GameMain.Server.ConnectedClients.Find(c => c.ID == id);
|
|
||||||
if (client == null)
|
if (client == null)
|
||||||
{
|
{
|
||||||
ThrowError("Client id \"" + id + "\" not found.");
|
ThrowError("Client id \"" + id + "\" not found.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ShowQuestionPrompt("Reason for banning \"" + client.Name + "\"?", (reason) =>
|
ShowQuestionPrompt("Reason for banning \"" + client.Name + "\"?", (reason) =>
|
||||||
{
|
{
|
||||||
ShowQuestionPrompt("Enter the duration of the ban (leave empty to ban permanently, or use the format \"[days] d [hours] h\")", (duration) =>
|
ShowQuestionPrompt("Enter the duration of the ban (leave empty to ban permanently, or use the format \"[days] d [hours] h\")", (duration) =>
|
||||||
@@ -1091,8 +1087,7 @@ namespace Barotrauma
|
|||||||
TimeSpan? banDuration = null;
|
TimeSpan? banDuration = null;
|
||||||
if (!string.IsNullOrWhiteSpace(duration))
|
if (!string.IsNullOrWhiteSpace(duration))
|
||||||
{
|
{
|
||||||
TimeSpan parsedBanDuration;
|
if (!TryParseTimeSpan(duration, out TimeSpan parsedBanDuration))
|
||||||
if (!TryParseTimeSpan(duration, out parsedBanDuration))
|
|
||||||
{
|
{
|
||||||
ThrowError("\"" + duration + "\" is not a valid ban duration. Use the format \"[days] d [hours] h\", \"[days] d\" or \"[hours] h\".");
|
ThrowError("\"" + duration + "\" is not a valid ban duration. Use the format \"[days] d [hours] h\", \"[days] d\" or \"[hours] h\".");
|
||||||
return;
|
return;
|
||||||
@@ -1100,7 +1095,7 @@ namespace Barotrauma
|
|||||||
banDuration = parsedBanDuration;
|
banDuration = parsedBanDuration;
|
||||||
}
|
}
|
||||||
|
|
||||||
GameMain.Server.BanPlayer(client.Name, reason, false, banDuration);
|
GameMain.NetworkMember.BanPlayer(client.Name, reason, false, banDuration);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
@@ -1117,8 +1112,7 @@ namespace Barotrauma
|
|||||||
TimeSpan? banDuration = null;
|
TimeSpan? banDuration = null;
|
||||||
if (!string.IsNullOrWhiteSpace(duration))
|
if (!string.IsNullOrWhiteSpace(duration))
|
||||||
{
|
{
|
||||||
TimeSpan parsedBanDuration;
|
if (!TryParseTimeSpan(duration, out TimeSpan parsedBanDuration))
|
||||||
if (!TryParseTimeSpan(duration, out parsedBanDuration))
|
|
||||||
{
|
{
|
||||||
ThrowError("\"" + duration + "\" is not a valid ban duration. Use the format \"[days] d [hours] h\", \"[days] d\" or \"[hours] h\".");
|
ThrowError("\"" + duration + "\" is not a valid ban duration. Use the format \"[days] d [hours] h\", \"[days] d\" or \"[hours] h\".");
|
||||||
return;
|
return;
|
||||||
@@ -1139,23 +1133,72 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
(string[] args) =>
|
||||||
|
{
|
||||||
|
#if CLIENT
|
||||||
|
if (GameMain.Client == null || args.Length == 0) return;
|
||||||
|
ShowQuestionPrompt("Reason for banning the ip \"" + args[0] + "\"?", (reason) =>
|
||||||
|
{
|
||||||
|
ShowQuestionPrompt("Enter the duration of the ban (leave empty to ban permanently, or use the format \"[days] d [hours] h\")", (duration) =>
|
||||||
|
{
|
||||||
|
TimeSpan? banDuration = null;
|
||||||
|
if (!string.IsNullOrWhiteSpace(duration))
|
||||||
|
{
|
||||||
|
if (!TryParseTimeSpan(duration, out TimeSpan parsedBanDuration))
|
||||||
|
{
|
||||||
|
ThrowError("\"" + duration + "\" is not a valid ban duration. Use the format \"[days] d [hours] h\", \"[days] d\" or \"[hours] h\".");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
banDuration = parsedBanDuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
GameMain.Client.SendConsoleCommand(
|
||||||
|
"banip " +
|
||||||
|
args[0] + " " +
|
||||||
|
(banDuration.HasValue ? banDuration.Value.TotalSeconds.ToString() : "0") + " " +
|
||||||
|
reason);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
#endif
|
||||||
|
},
|
||||||
|
(Client client, Vector2 cursorPos, string[] args) =>
|
||||||
|
{
|
||||||
|
if (args.Length < 1) return;
|
||||||
|
var clients = GameMain.Server.ConnectedClients.FindAll(c => c.Connection.RemoteEndPoint.Address.ToString() == args[0]);
|
||||||
|
TimeSpan? duration = null;
|
||||||
|
if (args.Length > 1)
|
||||||
|
{
|
||||||
|
if (double.TryParse(args[1], out double durationSeconds))
|
||||||
|
{
|
||||||
|
if (durationSeconds > 0) duration = TimeSpan.FromSeconds(durationSeconds);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GameMain.Server.SendConsoleMessage("\"" + args[1] + "\" is not a valid ban duration.", client);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
string reason = "";
|
||||||
|
if (args.Length > 2) reason = string.Join(" ", args.Skip(2));
|
||||||
|
|
||||||
|
if (clients.Count == 0)
|
||||||
|
{
|
||||||
|
GameMain.Server.BanList.BanPlayer("Unnamed", args[0], reason, duration);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach (Client cl in clients)
|
||||||
|
{
|
||||||
|
GameMain.Server.BanClient(cl, reason, false, duration);
|
||||||
|
}
|
||||||
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
commands.Add(new Command("teleportcharacter|teleport", "teleport [character name]: Teleport the specified character to the position of the cursor. If the name parameter is omitted, the controlled character will be teleported.", (string[] args) =>
|
commands.Add(new Command("teleportcharacter|teleport", "teleport [character name]: Teleport the specified character to the position of the cursor. If the name parameter is omitted, the controlled character will be teleported.", (string[] args) =>
|
||||||
{
|
{
|
||||||
Character tpCharacter = null;
|
Character tpCharacter = (args.Length == 0) ? Character.Controlled : FindMatchingCharacter(args, false);
|
||||||
|
|
||||||
if (args.Length == 0)
|
|
||||||
{
|
|
||||||
tpCharacter = Character.Controlled;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tpCharacter = FindMatchingCharacter(args, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tpCharacter == null) return;
|
if (tpCharacter == null) return;
|
||||||
|
|
||||||
var cam = GameMain.GameScreen.Cam;
|
var cam = GameMain.GameScreen.Cam;
|
||||||
@@ -1167,17 +1210,7 @@ namespace Barotrauma
|
|||||||
null,
|
null,
|
||||||
(Client client, Vector2 cursorWorldPos, string[] args) =>
|
(Client client, Vector2 cursorWorldPos, string[] args) =>
|
||||||
{
|
{
|
||||||
Character tpCharacter = null;
|
Character tpCharacter = (args.Length == 0) ? client.Character : FindMatchingCharacter(args, false);
|
||||||
|
|
||||||
if (args.Length == 0)
|
|
||||||
{
|
|
||||||
tpCharacter = client.Character;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tpCharacter = FindMatchingCharacter(args, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tpCharacter == null) return;
|
if (tpCharacter == null) return;
|
||||||
|
|
||||||
var cam = GameMain.GameScreen.Cam;
|
var cam = GameMain.GameScreen.Cam;
|
||||||
@@ -1234,18 +1267,29 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
commands.Add(new Command("findentityids", "findentityids [entityname]", (string[] args) =>
|
||||||
|
{
|
||||||
|
if (args.Length == 0) return;
|
||||||
|
args[0] = args[0].ToLowerInvariant();
|
||||||
|
foreach (MapEntity mapEntity in MapEntity.mapEntityList)
|
||||||
|
{
|
||||||
|
if (mapEntity.Name.ToLowerInvariant() == args[0])
|
||||||
|
{
|
||||||
|
ThrowError(mapEntity.ID + ": " + mapEntity.Name.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach (Character character in Character.CharacterList)
|
||||||
|
{
|
||||||
|
if (character.Name.ToLowerInvariant() == args[0] || character.SpeciesName.ToLowerInvariant() == args[0])
|
||||||
|
{
|
||||||
|
ThrowError(character.ID + ": " + character.Name.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
commands.Add(new Command("heal", "heal [character name]: Restore the specified character to full health. If the name parameter is omitted, the controlled character will be healed.", (string[] args) =>
|
commands.Add(new Command("heal", "heal [character name]: Restore the specified character to full health. If the name parameter is omitted, the controlled character will be healed.", (string[] args) =>
|
||||||
{
|
{
|
||||||
Character healedCharacter = null;
|
Character healedCharacter = (args.Length == 0) ? Character.Controlled : FindMatchingCharacter(args);
|
||||||
if (args.Length == 0)
|
|
||||||
{
|
|
||||||
healedCharacter = Character.Controlled;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
healedCharacter = FindMatchingCharacter(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (healedCharacter != null)
|
if (healedCharacter != null)
|
||||||
{
|
{
|
||||||
healedCharacter.AddDamage(CauseOfDeath.Damage, -healedCharacter.MaxHealth, null);
|
healedCharacter.AddDamage(CauseOfDeath.Damage, -healedCharacter.MaxHealth, null);
|
||||||
@@ -1257,16 +1301,7 @@ namespace Barotrauma
|
|||||||
null,
|
null,
|
||||||
(Client client, Vector2 cursorWorldPos, string[] args) =>
|
(Client client, Vector2 cursorWorldPos, string[] args) =>
|
||||||
{
|
{
|
||||||
Character healedCharacter = null;
|
Character healedCharacter = (args.Length == 0) ? client.Character : FindMatchingCharacter(args);
|
||||||
if (args.Length == 0)
|
|
||||||
{
|
|
||||||
healedCharacter = client.Character;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
healedCharacter = FindMatchingCharacter(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (healedCharacter != null)
|
if (healedCharacter != null)
|
||||||
{
|
{
|
||||||
healedCharacter.AddDamage(CauseOfDeath.Damage, -healedCharacter.MaxHealth, null);
|
healedCharacter.AddDamage(CauseOfDeath.Damage, -healedCharacter.MaxHealth, null);
|
||||||
@@ -1285,16 +1320,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
commands.Add(new Command("revive", "revive [character name]: Bring the specified character back from the dead. If the name parameter is omitted, the controlled character will be revived.", (string[] args) =>
|
commands.Add(new Command("revive", "revive [character name]: Bring the specified character back from the dead. If the name parameter is omitted, the controlled character will be revived.", (string[] args) =>
|
||||||
{
|
{
|
||||||
Character revivedCharacter = null;
|
Character revivedCharacter = (args.Length == 0) ? Character.Controlled : FindMatchingCharacter(args);
|
||||||
if (args.Length == 0)
|
|
||||||
{
|
|
||||||
revivedCharacter = Character.Controlled;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
revivedCharacter = FindMatchingCharacter(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (revivedCharacter == null) return;
|
if (revivedCharacter == null) return;
|
||||||
|
|
||||||
revivedCharacter.Revive(false);
|
revivedCharacter.Revive(false);
|
||||||
@@ -1313,16 +1339,7 @@ namespace Barotrauma
|
|||||||
null,
|
null,
|
||||||
(Client client, Vector2 cursorWorldPos, string[] args) =>
|
(Client client, Vector2 cursorWorldPos, string[] args) =>
|
||||||
{
|
{
|
||||||
Character revivedCharacter = null;
|
Character revivedCharacter = (args.Length == 0) ? client.Character : FindMatchingCharacter(args);
|
||||||
if (args.Length == 0)
|
|
||||||
{
|
|
||||||
revivedCharacter = client.Character;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
revivedCharacter = FindMatchingCharacter(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (revivedCharacter == null) return;
|
if (revivedCharacter == null) return;
|
||||||
|
|
||||||
revivedCharacter.Revive(false);
|
revivedCharacter.Revive(false);
|
||||||
@@ -1358,16 +1375,16 @@ namespace Barotrauma
|
|||||||
|
|
||||||
commands.Add(new Command("ragdoll", "ragdoll [character name]: Force-ragdoll the specified character. If the name parameter is omitted, the controlled character will be ragdolled.", (string[] args) =>
|
commands.Add(new Command("ragdoll", "ragdoll [character name]: Force-ragdoll the specified character. If the name parameter is omitted, the controlled character will be ragdolled.", (string[] args) =>
|
||||||
{
|
{
|
||||||
Character ragdolledCharacter = null;
|
Character ragdolledCharacter = (args.Length == 0) ? Character.Controlled : FindMatchingCharacter(args);
|
||||||
if (args.Length == 0)
|
if (ragdolledCharacter != null)
|
||||||
{
|
{
|
||||||
ragdolledCharacter = Character.Controlled;
|
ragdolledCharacter.IsForceRagdolled = !ragdolledCharacter.IsForceRagdolled;
|
||||||
}
|
}
|
||||||
else
|
},
|
||||||
{
|
null,
|
||||||
ragdolledCharacter = FindMatchingCharacter(args);
|
(Client client, Vector2 cursorWorldPos, string[] args) =>
|
||||||
}
|
{
|
||||||
|
Character ragdolledCharacter = (args.Length == 0) ? client.Character : FindMatchingCharacter(args);
|
||||||
if (ragdolledCharacter != null)
|
if (ragdolledCharacter != null)
|
||||||
{
|
{
|
||||||
ragdolledCharacter.IsForceRagdolled = !ragdolledCharacter.IsForceRagdolled;
|
ragdolledCharacter.IsForceRagdolled = !ragdolledCharacter.IsForceRagdolled;
|
||||||
@@ -1477,20 +1494,14 @@ namespace Barotrauma
|
|||||||
|
|
||||||
commands.Add(new Command("kill", "kill [character]: Immediately kills the specified character.", (string[] args) =>
|
commands.Add(new Command("kill", "kill [character]: Immediately kills the specified character.", (string[] args) =>
|
||||||
{
|
{
|
||||||
Character killedCharacter = null;
|
Character killedCharacter = (args.Length == 0) ? Character.Controlled : FindMatchingCharacter(args);
|
||||||
if (args.Length == 0)
|
killedCharacter?.AddDamage(CauseOfDeath.Damage, killedCharacter.MaxHealth * 2, null);
|
||||||
{
|
},
|
||||||
killedCharacter = Character.Controlled;
|
null,
|
||||||
}
|
(Client client, Vector2 cursorWorldPos, string[] args) =>
|
||||||
else
|
{
|
||||||
{
|
Character killedCharacter = (args.Length == 0) ? client.Character : FindMatchingCharacter(args);
|
||||||
killedCharacter = FindMatchingCharacter(args);
|
killedCharacter?.AddDamage(CauseOfDeath.Damage, killedCharacter.MaxHealth * 2, null);
|
||||||
}
|
|
||||||
|
|
||||||
if (killedCharacter != null)
|
|
||||||
{
|
|
||||||
killedCharacter.AddDamage(CauseOfDeath.Damage, killedCharacter.MaxHealth * 2, null);
|
|
||||||
}
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
commands.Add(new Command("killmonsters", "killmonsters: Immediately kills all AI-controlled enemies in the level.", (string[] args) =>
|
commands.Add(new Command("killmonsters", "killmonsters: Immediately kills all AI-controlled enemies in the level.", (string[] args) =>
|
||||||
@@ -2120,7 +2131,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void SpawnItem(string[] args, Vector2 cursorPos, out string errorMsg)
|
private static void SpawnItem(string[] args, Vector2 cursorPos, Character controlledCharacter, out string errorMsg)
|
||||||
{
|
{
|
||||||
errorMsg = "";
|
errorMsg = "";
|
||||||
if (args.Length < 1) return;
|
if (args.Length < 1) return;
|
||||||
@@ -2128,23 +2139,48 @@ namespace Barotrauma
|
|||||||
Vector2? spawnPos = null;
|
Vector2? spawnPos = null;
|
||||||
Inventory spawnInventory = null;
|
Inventory spawnInventory = null;
|
||||||
|
|
||||||
int extraParams = 0;
|
if (args.Length > 1)
|
||||||
switch (args.Last())
|
|
||||||
{
|
{
|
||||||
case "cursor":
|
switch (args[1])
|
||||||
extraParams = 1;
|
{
|
||||||
spawnPos = cursorPos;
|
case "cursor":
|
||||||
break;
|
spawnPos = cursorPos;
|
||||||
case "inventory":
|
break;
|
||||||
extraParams = 1;
|
case "inventory":
|
||||||
spawnInventory = Character.Controlled == null ? null : Character.Controlled.Inventory;
|
spawnInventory = controlledCharacter?.Inventory;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
extraParams = 0;
|
//Check if last arg matches the name of an in-game player
|
||||||
break;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
string itemName = string.Join(" ", args.Take(args.Length - extraParams)).ToLowerInvariant();
|
string itemName = args[0];
|
||||||
|
|
||||||
var itemPrefab = MapEntityPrefab.Find(itemName) as ItemPrefab;
|
var itemPrefab = MapEntityPrefab.Find(itemName) as ItemPrefab;
|
||||||
if (itemPrefab == null)
|
if (itemPrefab == null)
|
||||||
@@ -2162,7 +2198,6 @@ namespace Barotrauma
|
|||||||
if (spawnPos != null)
|
if (spawnPos != null)
|
||||||
{
|
{
|
||||||
Entity.Spawner.AddToSpawnQueue(itemPrefab, (Vector2)spawnPos);
|
Entity.Spawner.AddToSpawnQueue(itemPrefab, (Vector2)spawnPos);
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (spawnInventory != null)
|
else if (spawnInventory != null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -55,13 +55,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public override void Start()
|
public override void Start()
|
||||||
{
|
{
|
||||||
base.Start();
|
base.Start();
|
||||||
|
|
||||||
if (GameMain.Server != null)
|
|
||||||
{
|
|
||||||
CargoManager.CreateItems();
|
|
||||||
}
|
|
||||||
|
|
||||||
lastUpdateID++;
|
lastUpdateID++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -108,10 +108,9 @@ namespace Barotrauma
|
|||||||
codeWords = ToolBox.GetRandomLine(wordsTxt) + ", " + ToolBox.GetRandomLine(wordsTxt);
|
codeWords = ToolBox.GetRandomLine(wordsTxt) + ", " + ToolBox.GetRandomLine(wordsTxt);
|
||||||
codeResponse = ToolBox.GetRandomLine(wordsTxt) + ", " + ToolBox.GetRandomLine(wordsTxt);
|
codeResponse = ToolBox.GetRandomLine(wordsTxt) + ", " + ToolBox.GetRandomLine(wordsTxt);
|
||||||
|
|
||||||
while (traitorCount-- >= 0)
|
while (traitorCount-- > 0)
|
||||||
{
|
{
|
||||||
if (traitorCandidates.Count <= 0)
|
if (traitorCandidates.Count <= 0) break;
|
||||||
break;
|
|
||||||
|
|
||||||
int traitorIndex = Rand.Int(traitorCandidates.Count);
|
int traitorIndex = Rand.Int(traitorCandidates.Count);
|
||||||
Character traitorCharacter = traitorCandidates[traitorIndex];
|
Character traitorCharacter = traitorCandidates[traitorIndex];
|
||||||
|
|||||||
@@ -226,7 +226,14 @@ namespace Barotrauma
|
|||||||
|
|
||||||
EventManager.StartRound(level);
|
EventManager.StartRound(level);
|
||||||
|
|
||||||
if (GameMode != null) GameMode.MsgBox();
|
if (GameMode != null)
|
||||||
|
{
|
||||||
|
GameMode.MsgBox();
|
||||||
|
if (GameMode is MultiPlayerCampaign campaign && GameMain.Server != null)
|
||||||
|
{
|
||||||
|
campaign.CargoManager.CreateItems();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (GameSettings.SendUserStatistics)
|
if (GameSettings.SendUserStatistics)
|
||||||
{
|
{
|
||||||
@@ -234,7 +241,7 @@ namespace Barotrauma
|
|||||||
GameAnalyticsSDK.Net.GameAnalytics.AddProgressionEvent(GameAnalyticsSDK.Net.EGAProgressionStatus.Start,
|
GameAnalyticsSDK.Net.GameAnalytics.AddProgressionEvent(GameAnalyticsSDK.Net.EGAProgressionStatus.Start,
|
||||||
GameMode.Name, (Mission == null ? "None" : Mission.GetType().ToString()));
|
GameMode.Name, (Mission == null ? "None" : Mission.GetType().ToString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
#if CLIENT
|
#if CLIENT
|
||||||
roundSummary = new RoundSummary(this);
|
roundSummary = new RoundSummary(this);
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ namespace Barotrauma
|
|||||||
public bool EnableSplashScreen { get; set; }
|
public bool EnableSplashScreen { get; set; }
|
||||||
|
|
||||||
//public bool FullScreenEnabled { get; set; }
|
//public bool FullScreenEnabled { get; set; }
|
||||||
|
|
||||||
private KeyOrMouse[] keyMapping;
|
private KeyOrMouse[] keyMapping;
|
||||||
|
|
||||||
private WindowMode windowMode;
|
private WindowMode windowMode;
|
||||||
@@ -51,8 +51,37 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool unsavedSettings;
|
private int characterHeadIndex;
|
||||||
|
public int CharacterHeadIndex
|
||||||
|
{
|
||||||
|
get { return characterHeadIndex; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value == characterHeadIndex) return;
|
||||||
|
// Begin saving coroutine. Remove any existing save coroutines if one is running.
|
||||||
|
if (CoroutineManager.IsCoroutineRunning("saveCoroutine")) { CoroutineManager.StopCoroutines("saveCoroutine"); }
|
||||||
|
CoroutineManager.StartCoroutine(ApplyUnsavedChanges(), "saveCoroutine");
|
||||||
|
|
||||||
|
characterHeadIndex = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Gender characterGender;
|
||||||
|
public Gender CharacterGender
|
||||||
|
{
|
||||||
|
get { return characterGender; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value == characterGender) return;
|
||||||
|
// Begin saving coroutine. Remove any existing save coroutines if one is running.
|
||||||
|
if (CoroutineManager.IsCoroutineRunning("saveCoroutine")) { CoroutineManager.StopCoroutines("saveCoroutine"); }
|
||||||
|
CoroutineManager.StartCoroutine(ApplyUnsavedChanges(), "saveCoroutine");
|
||||||
|
|
||||||
|
characterGender = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool unsavedSettings;
|
||||||
public bool UnsavedSettings
|
public bool UnsavedSettings
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@@ -230,18 +259,15 @@ namespace Barotrauma
|
|||||||
case "keymapping":
|
case "keymapping":
|
||||||
foreach (XAttribute attribute in subElement.Attributes())
|
foreach (XAttribute attribute in subElement.Attributes())
|
||||||
{
|
{
|
||||||
InputType inputType;
|
if (Enum.TryParse(attribute.Name.ToString(), true, out InputType inputType))
|
||||||
if (Enum.TryParse(attribute.Name.ToString(), true, out inputType))
|
|
||||||
{
|
{
|
||||||
int mouseButton;
|
if (int.TryParse(attribute.Value.ToString(), out int mouseButton))
|
||||||
if (int.TryParse(attribute.Value.ToString(), out mouseButton))
|
|
||||||
{
|
{
|
||||||
keyMapping[(int)inputType] = new KeyOrMouse(mouseButton);
|
keyMapping[(int)inputType] = new KeyOrMouse(mouseButton);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Keys key;
|
if (Enum.TryParse(attribute.Value.ToString(), true, out Keys key))
|
||||||
if (Enum.TryParse(attribute.Value.ToString(), true, out key))
|
|
||||||
{
|
{
|
||||||
keyMapping[(int)inputType] = new KeyOrMouse(key);
|
keyMapping[(int)inputType] = new KeyOrMouse(key);
|
||||||
}
|
}
|
||||||
@@ -258,6 +284,9 @@ namespace Barotrauma
|
|||||||
break;
|
break;
|
||||||
case "player":
|
case "player":
|
||||||
defaultPlayerName = subElement.GetAttributeString("name", "");
|
defaultPlayerName = subElement.GetAttributeString("name", "");
|
||||||
|
characterHeadIndex = subElement.GetAttributeInt("headindex", Rand.Int(10));
|
||||||
|
characterGender = subElement.GetAttributeString("gender", Rand.Range(0.0f, 1.0f) < 0.5f ? "male" : "female")
|
||||||
|
.ToLowerInvariant() == "male" ? Gender.Male : Gender.Female;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -363,8 +392,10 @@ namespace Barotrauma
|
|||||||
gameplay.Add(jobPreferences);
|
gameplay.Add(jobPreferences);
|
||||||
doc.Root.Add(gameplay);
|
doc.Root.Add(gameplay);
|
||||||
|
|
||||||
var playerElement = new XElement("player");
|
var playerElement = new XElement("player",
|
||||||
playerElement.Add(new XAttribute("name", defaultPlayerName ?? ""));
|
new XAttribute("name", defaultPlayerName ?? ""),
|
||||||
|
new XAttribute("headindex", characterHeadIndex),
|
||||||
|
new XAttribute("gender", characterGender));
|
||||||
doc.Root.Add(playerElement);
|
doc.Root.Add(playerElement);
|
||||||
|
|
||||||
doc.Save(filePath);
|
doc.Save(filePath);
|
||||||
|
|||||||
@@ -93,6 +93,26 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void OnItemLoaded()
|
||||||
|
{
|
||||||
|
if (attack != null && attack.DamageRange <= 0.0f && item.body != null)
|
||||||
|
{
|
||||||
|
switch (item.body.BodyShape)
|
||||||
|
{
|
||||||
|
case PhysicsBody.Shape.Circle:
|
||||||
|
attack.DamageRange = item.body.radius;
|
||||||
|
break;
|
||||||
|
case PhysicsBody.Shape.Capsule:
|
||||||
|
attack.DamageRange = item.body.height / 2 + item.body.radius;
|
||||||
|
break;
|
||||||
|
case PhysicsBody.Shape.Rectangle:
|
||||||
|
attack.DamageRange = new Vector2(item.body.width / 2.0f, item.body.height / 2.0f).Length();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
attack.DamageRange = ConvertUnits.ToDisplayUnits(attack.DamageRange);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override bool Use(float deltaTime, Character character = null)
|
public override bool Use(float deltaTime, Character character = null)
|
||||||
{
|
{
|
||||||
if (character != null && !characterUsable) return false;
|
if (character != null && !characterUsable) return false;
|
||||||
@@ -196,7 +216,6 @@ namespace Barotrauma.Items.Components
|
|||||||
if (OnProjectileCollision(fixture, normal))
|
if (OnProjectileCollision(fixture, normal))
|
||||||
{
|
{
|
||||||
hitSomething = true;
|
hitSomething = true;
|
||||||
//Character.Controlled.AnimController.Teleport(point - Character.Controlled.SimPosition, Vector2.Zero);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -281,8 +300,7 @@ namespace Barotrauma.Items.Components
|
|||||||
Character character = null;
|
Character character = null;
|
||||||
if (attack != null)
|
if (attack != null)
|
||||||
{
|
{
|
||||||
var submarine = target.Body.UserData as Submarine;
|
if (target.Body.UserData is Submarine submarine)
|
||||||
if (submarine != null)
|
|
||||||
{
|
{
|
||||||
item.Move(-submarine.Position);
|
item.Move(-submarine.Position);
|
||||||
item.Submarine = submarine;
|
item.Submarine = submarine;
|
||||||
@@ -290,9 +308,8 @@ namespace Barotrauma.Items.Components
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Limb limb = target.Body.UserData as Limb;
|
|
||||||
Structure structure;
|
Structure structure;
|
||||||
if (limb != null)
|
if (target.Body.UserData is Limb limb)
|
||||||
{
|
{
|
||||||
attackResult = attack.DoDamageToLimb(User, limb, item.WorldPosition, 1.0f);
|
attackResult = attack.DoDamageToLimb(User, limb, item.WorldPosition, 1.0f);
|
||||||
if (limb.character != null)
|
if (limb.character != null)
|
||||||
@@ -350,13 +367,12 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
contained.SetTransform(item.SimPosition, contained.body.Rotation);
|
contained.SetTransform(item.SimPosition, contained.body.Rotation);
|
||||||
}
|
}
|
||||||
//contained.Condition = 0.0f; //Let the freaking .xml handle it jeez
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (RemoveOnHit)
|
if (RemoveOnHit)
|
||||||
{
|
{
|
||||||
Item.Spawner.AddToRemoveQueue(item);
|
Entity.Spawner.AddToRemoveQueue(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -315,9 +315,9 @@ namespace Barotrauma
|
|||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
#if CLIENT
|
#if CLIENT
|
||||||
return (GameMain.DebugDraw) ? Name + "(ID: " + ID + ")" : Name;
|
return (GameMain.DebugDraw) ? Name + " (ID: " + ID + ")" : Name;
|
||||||
#elif SERVER
|
#elif SERVER
|
||||||
return Name + "(ID: " + ID + ")";
|
return Name + " (ID: " + ID + ")";
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ namespace Barotrauma
|
|||||||
if (distSqr > displayRangeSqr) continue;
|
if (distSqr > displayRangeSqr) continue;
|
||||||
|
|
||||||
//ignore reactors (don't want to blow them up)
|
//ignore reactors (don't want to blow them up)
|
||||||
if (item.GetComponent<Reactor>() == null) continue;
|
if (item.GetComponent<Reactor>() != null) continue;
|
||||||
|
|
||||||
float distFactor = 1.0f - (float)Math.Sqrt(distSqr) / displayRange;
|
float distFactor = 1.0f - (float)Math.Sqrt(distSqr) / displayRange;
|
||||||
|
|
||||||
|
|||||||
@@ -664,19 +664,20 @@ namespace Barotrauma
|
|||||||
float damageAmount = 0.0f;
|
float damageAmount = 0.0f;
|
||||||
for (int i = 0; i < SectionCount; i++)
|
for (int i = 0; i < SectionCount; i++)
|
||||||
{
|
{
|
||||||
if (Vector2.DistanceSquared(SectionPosition(i, true), worldPosition) <= attack.DamageRange * attack.DamageRange)
|
Rectangle sectionRect = sections[i].rect;
|
||||||
|
sectionRect.Y -= sections[i].rect.Height;
|
||||||
|
if (MathUtils.CircleIntersectsRectangle(transformedPos, attack.DamageRange, sectionRect))
|
||||||
{
|
{
|
||||||
damageAmount = attack.GetStructureDamage(deltaTime);
|
damageAmount = attack.GetStructureDamage(deltaTime);
|
||||||
AddDamage(i, damageAmount, attacker);
|
AddDamage(i, damageAmount, attacker);
|
||||||
|
|
||||||
#if CLIENT
|
#if CLIENT
|
||||||
GameMain.ParticleManager.CreateParticle("dustcloud", SectionPosition(i), 0.0f, 0.0f);
|
GameMain.ParticleManager.CreateParticle("dustcloud", SectionPosition(i), 0.0f, 0.0f);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if CLIENT
|
#if CLIENT
|
||||||
if (playSound)// && !SectionBodyDisabled(i))
|
if (playSound)
|
||||||
{
|
{
|
||||||
string damageSoundType = (attack.DamageType == DamageType.Blunt) ? "StructureBlunt" : "StructureSlash";
|
string damageSoundType = (attack.DamageType == DamageType.Blunt) ? "StructureBlunt" : "StructureSlash";
|
||||||
SoundPlayer.PlayDamageSound(damageSoundType, damageAmount, worldPosition, tags: Tags);
|
SoundPlayer.PlayDamageSound(damageSoundType, damageAmount, worldPosition, tags: Tags);
|
||||||
|
|||||||
@@ -29,10 +29,20 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
public byte TeamID = 0;
|
public byte TeamID = 0;
|
||||||
|
|
||||||
public Character Character;
|
private Character character;
|
||||||
|
public Character Character
|
||||||
|
{
|
||||||
|
get { return character; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
character = value;
|
||||||
|
if (character != null) HasSpawned = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
public CharacterInfo CharacterInfo;
|
public CharacterInfo CharacterInfo;
|
||||||
public NetConnection Connection { get; set; }
|
public NetConnection Connection { get; set; }
|
||||||
public bool InGame;
|
public bool InGame;
|
||||||
|
public bool HasSpawned; //has the client spawned as a character during the current round
|
||||||
|
|
||||||
public UInt16 LastRecvGeneralUpdate = 0;
|
public UInt16 LastRecvGeneralUpdate = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -780,11 +780,21 @@ namespace Barotrauma.Networking
|
|||||||
case ClientPermissions.Ban:
|
case ClientPermissions.Ban:
|
||||||
string bannedName = inc.ReadString().ToLowerInvariant();
|
string bannedName = inc.ReadString().ToLowerInvariant();
|
||||||
string banReason = inc.ReadString();
|
string banReason = inc.ReadString();
|
||||||
|
bool range = inc.ReadBoolean();
|
||||||
|
double durationSeconds = inc.ReadDouble();
|
||||||
|
|
||||||
var bannedClient = connectedClients.Find(cl => cl != sender && cl.Name.ToLowerInvariant() == bannedName);
|
var bannedClient = connectedClients.Find(cl => cl != sender && cl.Name.ToLowerInvariant() == bannedName);
|
||||||
if (bannedClient != null)
|
if (bannedClient != null)
|
||||||
{
|
{
|
||||||
Log("Client \"" + sender.Name + "\" banned \"" + bannedClient.Name + "\".", ServerLog.MessageType.ServerMessage);
|
Log("Client \"" + sender.Name + "\" banned \"" + bannedClient.Name + "\".", ServerLog.MessageType.ServerMessage);
|
||||||
BanClient(bannedClient, string.IsNullOrEmpty(banReason) ? "Banned by " + sender.Name : banReason, false);
|
if (durationSeconds > 0)
|
||||||
|
{
|
||||||
|
BanClient(bannedClient, string.IsNullOrEmpty(banReason) ? "Banned by " + sender.Name : banReason, range, TimeSpan.FromSeconds(durationSeconds));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BanClient(bannedClient, string.IsNullOrEmpty(banReason) ? "Banned by " + sender.Name : banReason, range);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ClientPermissions.EndRound:
|
case ClientPermissions.EndRound:
|
||||||
@@ -1343,11 +1353,12 @@ namespace Barotrauma.Networking
|
|||||||
List<Character> characters = new List<Character>();
|
List<Character> characters = new List<Character>();
|
||||||
foreach (Client client in ConnectedClients)
|
foreach (Client client in ConnectedClients)
|
||||||
{
|
{
|
||||||
if (client.Character != null)
|
if (client.Character != null) characters.Add(client.Character);
|
||||||
characters.Add(client.Character);
|
|
||||||
}
|
}
|
||||||
var max = (int)Math.Round(characters.Count * 0.2f, 1);
|
if (Character != null) characters.Add(Character);
|
||||||
var traitorCount = Math.Max(1, TraitorsEnabled == YesNoMaybe.Maybe ? Rand.Int(max) + 1 : max);
|
|
||||||
|
int max = Math.Max(TraitorUseRatio ? (int)Math.Round(characters.Count * TraitorRatio, 1) : 1, 1);
|
||||||
|
int traitorCount = Rand.Int(max + 1);
|
||||||
TraitorManager = new TraitorManager(this, traitorCount);
|
TraitorManager = new TraitorManager(this, traitorCount);
|
||||||
|
|
||||||
if (TraitorManager.TraitorList.Count > 0)
|
if (TraitorManager.TraitorList.Count > 0)
|
||||||
@@ -1501,6 +1512,7 @@ namespace Barotrauma.Networking
|
|||||||
foreach (Client client in connectedClients)
|
foreach (Client client in connectedClients)
|
||||||
{
|
{
|
||||||
client.Character = null;
|
client.Character = null;
|
||||||
|
client.HasSpawned = false;
|
||||||
client.InGame = false;
|
client.InGame = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1620,6 +1632,7 @@ namespace Barotrauma.Networking
|
|||||||
}
|
}
|
||||||
|
|
||||||
client.Character = null;
|
client.Character = null;
|
||||||
|
client.HasSpawned = false;
|
||||||
client.InGame = false;
|
client.InGame = false;
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(msg)) msg = client.Name + " has left the server";
|
if (string.IsNullOrWhiteSpace(msg)) msg = client.Name + " has left the server";
|
||||||
|
|||||||
@@ -111,11 +111,11 @@ namespace Barotrauma
|
|||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case VoteType.EndRound:
|
case VoteType.EndRound:
|
||||||
if (sender.Character == null) return;
|
if (!sender.HasSpawned) return;
|
||||||
sender.SetVote(voteType, inc.ReadBoolean());
|
sender.SetVote(voteType, inc.ReadBoolean());
|
||||||
|
|
||||||
GameMain.NetworkMember.EndVoteCount = GameMain.Server.ConnectedClients.Count(c => c.Character != null && c.GetVote<bool>(VoteType.EndRound));
|
GameMain.NetworkMember.EndVoteCount = GameMain.Server.ConnectedClients.Count(c => c.HasSpawned && c.GetVote<bool>(VoteType.EndRound));
|
||||||
GameMain.NetworkMember.EndVoteMax = GameMain.Server.ConnectedClients.Count(c => c.Character != null);
|
GameMain.NetworkMember.EndVoteMax = GameMain.Server.ConnectedClients.Count(c => c.HasSpawned);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case VoteType.Kick:
|
case VoteType.Kick:
|
||||||
|
|||||||
@@ -1,3 +1,34 @@
|
|||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
v0.8.1.5
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
- Added the option to automatically send crash reports and anonymous usage statistics to the developers.
|
||||||
|
The usage statistics include information such as the selected game mode, selected submarine, causes of
|
||||||
|
death and mission outcomes. When the game is started for the first time, a message box prompts you to
|
||||||
|
select whether you want to send the information or not.
|
||||||
|
- Fixed a bug that caused clients to get desynced when purchasing items in the multiplayer campaign.
|
||||||
|
- Added a signal component that adds the received signals together.
|
||||||
|
- Devices outside the submarine can be rewired in-game (not just in the sub editor).
|
||||||
|
- Fixed a crash caused by vision obstruction logic.
|
||||||
|
- Fixed clients being unable to give non-permanent or range bans.
|
||||||
|
- Clients are allowed to vote to end the round if they have spawned at some point during the round,
|
||||||
|
even if the character they controlled doesn't exist anymore.
|
||||||
|
- Dedicated servers can give clients the permission to use console commands that aren't available in
|
||||||
|
for dedicated server (e.g. los, lights, control)
|
||||||
|
- Banip, banid & kickid commands can be used by clients now (if they have the permission to do so).
|
||||||
|
- Spawnitem [item] inventory, ragdoll and kill commands target the character of the client using
|
||||||
|
the command instead of the host's character.
|
||||||
|
- Spawnitem can be used to spawn items in the inventory of a specific character.
|
||||||
|
- Fixed explosions with an EMP value only damaging reactors (when they should only ignore reactors).
|
||||||
|
- Fire can only explode oxygen tanks that are >25% full (otherwise the condition of the tank just drops
|
||||||
|
to 0). Prevents infinite explosions when an oxygen generator is on fire with oxygen tanks inside.
|
||||||
|
- Fixed projectiles with a damage range of 0 not applying their structuredamage value to structures.
|
||||||
|
- Items with a physics body can be used as pumps, so now it's possible to make portable items that remove
|
||||||
|
water from inside the sub.
|
||||||
|
- Fixed traitor ratio setting being ignored and the minimum number of traitors being 2.
|
||||||
|
- Fixed crashes caused by custom characters with no AI configuration.
|
||||||
|
- Character head and gender settings are saved.
|
||||||
|
|
||||||
---------------------------------------------------------------------------------------------------------
|
---------------------------------------------------------------------------------------------------------
|
||||||
v0.8.1.4
|
v0.8.1.4
|
||||||
---------------------------------------------------------------------------------------------------------
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
|||||||
Reference in New Issue
Block a user