(bf212a41f) v0.9.2.0 pre-release test version
This commit is contained in:
9
.gitignore
vendored
9
.gitignore
vendored
@@ -12,11 +12,11 @@ bld/
|
||||
[Dd]ebug*/
|
||||
[Rr]elease*/
|
||||
|
||||
# Barotrauma content folder
|
||||
BarotraumaShared/Content/
|
||||
|
||||
# Misc vs crap
|
||||
*.v12.suo
|
||||
*.suo
|
||||
*.csproj.user
|
||||
*.shproj.user
|
||||
|
||||
#performance reports & sessions
|
||||
*.vsp
|
||||
@@ -25,3 +25,6 @@ BarotraumaShared/Content/
|
||||
|
||||
# Mac
|
||||
*.DS_Store
|
||||
|
||||
#Merge script
|
||||
temp.txt
|
||||
|
||||
@@ -160,6 +160,7 @@
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Networking\EntitySpawner.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Networking\FileTransfer\FileReceiver.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Networking\GameClient.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Networking\KarmaManager.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Networking\NetEntityEvent\ClientEntityEventManager.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Networking\NetEntityEvent\NetEntityEvent.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Networking\NetStats.cs" />
|
||||
|
||||
@@ -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.9.1.0")]
|
||||
[assembly: AssemblyVersion("0.9.200.0")]
|
||||
[assembly: AssemblyFileVersion("0.9.1.0")]
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using Barotrauma.Networking;
|
||||
using Lidgren.Network;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
using System;
|
||||
|
||||
@@ -171,6 +173,11 @@ namespace Barotrauma
|
||||
get { return targetPos; }
|
||||
set { targetPos = value; }
|
||||
}
|
||||
|
||||
public Vector2 GetPosition()
|
||||
{
|
||||
return position;
|
||||
}
|
||||
|
||||
// Auxiliary function to move the camera
|
||||
public void Translate(Vector2 amount)
|
||||
@@ -178,6 +185,15 @@ namespace Barotrauma
|
||||
position += amount;
|
||||
}
|
||||
|
||||
public void ClientWrite(NetOutgoingMessage msg)
|
||||
{
|
||||
if (Character.Controlled != null && !Character.Controlled.IsDead) return;
|
||||
|
||||
msg.Write((byte)ClientNetObject.SPECTATING_POS);
|
||||
msg.Write(position.X);
|
||||
msg.Write(position.Y);
|
||||
}
|
||||
|
||||
private void CreateMatrices()
|
||||
{
|
||||
resolution = new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight);
|
||||
|
||||
@@ -14,6 +14,13 @@ namespace Barotrauma
|
||||
{
|
||||
if (this != Controlled)
|
||||
{
|
||||
if (GameMain.Client.EndCinematic != null) // Freezes the characters during the ending cinematic
|
||||
{
|
||||
AnimController.Frozen = true;
|
||||
memState.Clear();
|
||||
return;
|
||||
}
|
||||
|
||||
//freeze AI characters if more than 1 seconds have passed since last update from the server
|
||||
if (lastRecvPositionUpdateTime < NetTime.Now - 1.0f)
|
||||
{
|
||||
|
||||
@@ -128,6 +128,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
public WearableSprite HuskSprite { get; private set; }
|
||||
public WearableSprite HerpesSprite { get; private set; }
|
||||
|
||||
public void LoadHuskSprite()
|
||||
{
|
||||
@@ -139,6 +140,16 @@ namespace Barotrauma
|
||||
HuskSprite = new WearableSprite(element.Element("sprite"), WearableType.Husk);
|
||||
}
|
||||
}
|
||||
public void LoadHerpesSprite()
|
||||
{
|
||||
var info = character.Info;
|
||||
if (info == null) { return; }
|
||||
var element = info.FilterByTypeAndHeadID(character.Info.FilterElementsByGenderAndRace(character.Info.Wearables), WearableType.Herpes).FirstOrDefault();
|
||||
if (element != null)
|
||||
{
|
||||
HerpesSprite = new WearableSprite(element.Element("sprite"), WearableType.Herpes);
|
||||
}
|
||||
}
|
||||
|
||||
public float TextureScale => limbParams.Ragdoll.TextureScale;
|
||||
|
||||
@@ -387,7 +398,7 @@ namespace Barotrauma
|
||||
color *= SeveredFadeOutTime - severedFadeOutTimer;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
body.Dir = Dir;
|
||||
|
||||
bool hideLimb = wearingItems.Any(w => w != null && w.HideLimb);
|
||||
@@ -425,10 +436,20 @@ namespace Barotrauma
|
||||
SpriteEffects spriteEffect = (dir == Direction.Right) ? SpriteEffects.None : SpriteEffects.FlipHorizontally;
|
||||
if (onlyDrawable == null)
|
||||
{
|
||||
if (HerpesSprite != null)
|
||||
{
|
||||
float herpesStrength = character.CharacterHealth.GetAfflictionStrength("spaceherpes");
|
||||
if (herpesStrength > 0.0f)
|
||||
{
|
||||
DrawWearable(HerpesSprite, depthStep, spriteBatch, color * (herpesStrength / 100.0f), spriteEffect);
|
||||
depthStep += 0.000001f;
|
||||
}
|
||||
}
|
||||
if (HuskSprite != null && (character.SpeciesName == "Humanhusk" || (character.SpeciesName == "Human" &&
|
||||
character.CharacterHealth.GetAffliction<AfflictionHusk>("huskinfection")?.State == AfflictionHusk.InfectionState.Active)))
|
||||
{
|
||||
DrawWearable(HuskSprite, depthStep, spriteBatch, color, spriteEffect);
|
||||
depthStep += 0.000001f;
|
||||
}
|
||||
foreach (WearableSprite wearable in OtherWearables)
|
||||
{
|
||||
@@ -585,6 +606,9 @@ namespace Barotrauma
|
||||
|
||||
HuskSprite?.Sprite.Remove();
|
||||
HuskSprite = null;
|
||||
|
||||
HerpesSprite?.Sprite.Remove();
|
||||
HerpesSprite = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,17 +133,7 @@ namespace Barotrauma
|
||||
|
||||
if (PlayerInput.KeyHit(Keys.F3))
|
||||
{
|
||||
isOpen = !isOpen;
|
||||
if (isOpen)
|
||||
{
|
||||
textBox.Select();
|
||||
AddToGUIUpdateList();
|
||||
}
|
||||
else
|
||||
{
|
||||
GUI.ForceMouseOn(null);
|
||||
textBox.Deselect();
|
||||
}
|
||||
Toggle();
|
||||
}
|
||||
else if (isOpen && PlayerInput.KeyHit(Keys.Escape))
|
||||
{
|
||||
@@ -179,6 +169,21 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public static void Toggle()
|
||||
{
|
||||
isOpen = !isOpen;
|
||||
if (isOpen)
|
||||
{
|
||||
textBox.Select();
|
||||
AddToGUIUpdateList();
|
||||
}
|
||||
else
|
||||
{
|
||||
GUI.ForceMouseOn(null);
|
||||
textBox.Deselect();
|
||||
}
|
||||
}
|
||||
|
||||
public static void Draw(SpriteBatch spriteBatch)
|
||||
{
|
||||
if (!isOpen) return;
|
||||
@@ -298,9 +303,16 @@ namespace Barotrauma
|
||||
|
||||
private static void AssignOnClientExecute(string names, Action<string[]> onClientExecute)
|
||||
{
|
||||
Command command = commands.First(c => c.names.Intersect(names.Split('|')).Count() > 0);
|
||||
command.OnClientExecute = onClientExecute;
|
||||
command.RelayToServer = false;
|
||||
Command command = commands.Find(c => c.names.Intersect(names.Split('|')).Count() > 0);
|
||||
if (command == null)
|
||||
{
|
||||
throw new Exception("AssignOnClientExecute failed. Command matching the name(s) \"" + names + "\" not found.");
|
||||
}
|
||||
else
|
||||
{
|
||||
command.OnClientExecute = onClientExecute;
|
||||
command.RelayToServer = false;
|
||||
}
|
||||
}
|
||||
|
||||
private static void AssignRelayToServer(string names, bool relay)
|
||||
@@ -1797,6 +1809,11 @@ namespace Barotrauma
|
||||
limb.HuskSprite.Sprite.ReloadXML();
|
||||
limb.HuskSprite.Sprite.ReloadTexture();
|
||||
}
|
||||
if (limb.HerpesSprite != null)
|
||||
{
|
||||
limb.HerpesSprite.Sprite.ReloadXML();
|
||||
limb.HerpesSprite.Sprite.ReloadTexture();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -278,7 +278,7 @@ namespace Barotrauma
|
||||
Color.White, Color.Black * 0.5f, 0, SmallFont);
|
||||
|
||||
DrawString(spriteBatch, new Vector2(10, 40),
|
||||
"Bodies: " + GameMain.World.BodyList.Count + " (" + GameMain.World.BodyList.FindAll(b => b.Awake && b.Enabled).Count + " awake)",
|
||||
$"Bodies: {GameMain.World.BodyList.Count} ({GameMain.World.BodyList.FindAll(b => b.Awake && b.Enabled).Count} awake, {GameMain.World.BodyList.FindAll(b => b.Awake && b.BodyType == FarseerPhysics.Dynamics.BodyType.Dynamic && b.Enabled).Count} dynamic)",
|
||||
Color.White, Color.Black * 0.5f, 0, SmallFont);
|
||||
|
||||
if (Screen.Selected.Cam != null)
|
||||
@@ -1040,6 +1040,8 @@ namespace Barotrauma
|
||||
|
||||
public static Texture2D CreateRectangle(int width, int height)
|
||||
{
|
||||
width = Math.Max(width, 1);
|
||||
height = Math.Max(height, 1);
|
||||
Color[] data = new Color[width * height];
|
||||
|
||||
for (int i = 0; i < data.Length; i++)
|
||||
@@ -1057,7 +1059,6 @@ namespace Barotrauma
|
||||
TrySetArray(data, (height - 1) * width + x, Color.White);
|
||||
}
|
||||
|
||||
|
||||
Texture2D texture = null;
|
||||
CrossThread.RequestExecutionOnMainThread(() =>
|
||||
{
|
||||
|
||||
@@ -178,25 +178,27 @@ namespace Barotrauma
|
||||
}
|
||||
else if (DrawLoadingText)
|
||||
{
|
||||
string loadText = "";
|
||||
if (LoadState == 100.0f)
|
||||
if (TextManager.Initialized)
|
||||
{
|
||||
loadText = TextManager.Get("PressAnyKey");
|
||||
}
|
||||
else
|
||||
{
|
||||
loadText = TextManager.Get("Loading");
|
||||
if (LoadState != null)
|
||||
string loadText;
|
||||
if (LoadState == 100.0f)
|
||||
{
|
||||
loadText += " " + (int)LoadState + " %";
|
||||
loadText = TextManager.Get("PressAnyKey");
|
||||
}
|
||||
else
|
||||
{
|
||||
loadText = TextManager.Get("Loading");
|
||||
if (LoadState != null)
|
||||
{
|
||||
loadText += " " + (int)LoadState + " %";
|
||||
}
|
||||
}
|
||||
if (GUI.LargeFont != null)
|
||||
{
|
||||
GUI.LargeFont.DrawString(spriteBatch, loadText.ToUpper(),
|
||||
new Vector2(GameMain.GraphicsWidth / 2.0f - GUI.LargeFont.MeasureString(loadText).X / 2.0f, GameMain.GraphicsHeight * 0.7f),
|
||||
Color.White);
|
||||
}
|
||||
}
|
||||
|
||||
if (GUI.LargeFont != null)
|
||||
{
|
||||
GUI.LargeFont.DrawString(spriteBatch, loadText.ToUpper(),
|
||||
new Vector2(GameMain.GraphicsWidth / 2.0f - GUI.LargeFont.MeasureString(loadText).X / 2.0f, GameMain.GraphicsHeight * 0.7f),
|
||||
Color.White);
|
||||
}
|
||||
|
||||
if (GUI.Font != null && selectedTip != null)
|
||||
|
||||
@@ -58,6 +58,8 @@ namespace Barotrauma
|
||||
public event Action<SpriteBatch, float> PreDraw;
|
||||
public event Action<SpriteBatch, float> PostDraw;
|
||||
|
||||
public bool RequireMouseOn = true;
|
||||
|
||||
public Action refresh;
|
||||
|
||||
public object data;
|
||||
@@ -109,7 +111,7 @@ namespace Barotrauma
|
||||
{
|
||||
PreUpdate?.Invoke(deltaTime);
|
||||
if (!enabled) { return; }
|
||||
if (IsMouseOver)
|
||||
if (IsMouseOver || (!RequireMouseOn && selectedWidgets.Contains(this) && PlayerInput.LeftButtonHeld()))
|
||||
{
|
||||
Hovered?.Invoke();
|
||||
if ((multiselect && !selectedWidgets.Contains(this)) || selectedWidgets.None())
|
||||
|
||||
@@ -404,54 +404,13 @@ namespace Barotrauma
|
||||
DebugConsole.Log("Selected content packages: " + string.Join(", ", SelectedPackages.Select(cp => cp.Name)));
|
||||
}
|
||||
|
||||
/*#if DEBUG
|
||||
#if DEBUG
|
||||
GameSettings.ShowUserStatisticsPrompt = false;
|
||||
GameSettings.SendUserStatistics = false;
|
||||
#endif*/
|
||||
#endif
|
||||
|
||||
InitUserStats();
|
||||
|
||||
yield return CoroutineStatus.Running;
|
||||
|
||||
LightManager = new Lights.LightManager(base.GraphicsDevice, Content);
|
||||
|
||||
TitleScreen.LoadState = 1.0f;
|
||||
yield return CoroutineStatus.Running;
|
||||
|
||||
GUI.LoadContent();
|
||||
TitleScreen.LoadState = 2.0f;
|
||||
|
||||
yield return CoroutineStatus.Running;
|
||||
|
||||
MissionPrefab.Init();
|
||||
MapEntityPrefab.Init();
|
||||
Tutorials.Tutorial.Init();
|
||||
MapGenerationParams.Init();
|
||||
LevelGenerationParams.LoadPresets();
|
||||
ScriptedEventSet.LoadPrefabs();
|
||||
AfflictionPrefab.LoadAll(GetFilesOfType(ContentType.Afflictions));
|
||||
TitleScreen.LoadState = 10.0f;
|
||||
yield return CoroutineStatus.Running;
|
||||
|
||||
StructurePrefab.LoadAll(GetFilesOfType(ContentType.Structure));
|
||||
TitleScreen.LoadState = 15.0f;
|
||||
yield return CoroutineStatus.Running;
|
||||
|
||||
ItemPrefab.LoadAll(GetFilesOfType(ContentType.Item));
|
||||
TitleScreen.LoadState = 25.0f;
|
||||
yield return CoroutineStatus.Running;
|
||||
|
||||
JobPrefab.LoadAll(GetFilesOfType(ContentType.Jobs));
|
||||
// Add any missing jobs from the prefab into Config.JobNamePreferences.
|
||||
foreach (JobPrefab job in JobPrefab.List)
|
||||
{
|
||||
if (!Config.JobPreferences.Contains(job.Identifier)) { Config.JobPreferences.Add(job.Identifier); }
|
||||
}
|
||||
|
||||
NPCConversation.LoadAll(GetFilesOfType(ContentType.NPCConversations));
|
||||
|
||||
ItemAssemblyPrefab.LoadAll();
|
||||
TitleScreen.LoadState = 30.0f;
|
||||
yield return CoroutineStatus.Running;
|
||||
|
||||
Debug.WriteLine("sounds");
|
||||
@@ -464,55 +423,105 @@ namespace Barotrauma
|
||||
|
||||
i++;
|
||||
TitleScreen.LoadState = SoundPlayer.SoundCount == 0 ?
|
||||
30.0f :
|
||||
Math.Min(30.0f + 40.0f * i / Math.Max(SoundPlayer.SoundCount, 1), 70.0f);
|
||||
1.0f :
|
||||
Math.Min(40.0f * i / Math.Max(SoundPlayer.SoundCount, 1), 40.0f);
|
||||
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
TitleScreen.LoadState = 70.0f;
|
||||
TitleScreen.LoadState = 40.0f;
|
||||
yield return CoroutineStatus.Running;
|
||||
|
||||
LightManager = new Lights.LightManager(base.GraphicsDevice, Content);
|
||||
|
||||
TitleScreen.LoadState = 41.0f;
|
||||
yield return CoroutineStatus.Running;
|
||||
|
||||
GUI.LoadContent();
|
||||
TitleScreen.LoadState = 42.0f;
|
||||
|
||||
yield return CoroutineStatus.Running;
|
||||
|
||||
MissionPrefab.Init();
|
||||
MapEntityPrefab.Init();
|
||||
Tutorials.Tutorial.Init();
|
||||
MapGenerationParams.Init();
|
||||
LevelGenerationParams.LoadPresets();
|
||||
ScriptedEventSet.LoadPrefabs();
|
||||
AfflictionPrefab.LoadAll(GetFilesOfType(ContentType.Afflictions));
|
||||
TitleScreen.LoadState = 50.0f;
|
||||
yield return CoroutineStatus.Running;
|
||||
|
||||
StructurePrefab.LoadAll(GetFilesOfType(ContentType.Structure));
|
||||
TitleScreen.LoadState = 53.0f;
|
||||
yield return CoroutineStatus.Running;
|
||||
|
||||
ItemPrefab.LoadAll(GetFilesOfType(ContentType.Item));
|
||||
TitleScreen.LoadState = 55.0f;
|
||||
yield return CoroutineStatus.Running;
|
||||
|
||||
JobPrefab.LoadAll(GetFilesOfType(ContentType.Jobs));
|
||||
// Add any missing jobs from the prefab into Config.JobNamePreferences.
|
||||
foreach (JobPrefab job in JobPrefab.List)
|
||||
{
|
||||
if (!Config.JobPreferences.Contains(job.Identifier)) { Config.JobPreferences.Add(job.Identifier); }
|
||||
}
|
||||
|
||||
NPCConversation.LoadAll(GetFilesOfType(ContentType.NPCConversations));
|
||||
|
||||
ItemAssemblyPrefab.LoadAll();
|
||||
TitleScreen.LoadState = 60.0f;
|
||||
yield return CoroutineStatus.Running;
|
||||
|
||||
GameModePreset.Init();
|
||||
|
||||
Submarine.RefreshSavedSubs();
|
||||
|
||||
TitleScreen.LoadState = 80.0f;
|
||||
|
||||
TitleScreen.LoadState = 65.0f;
|
||||
yield return CoroutineStatus.Running;
|
||||
|
||||
GameScreen = new GameScreen(GraphicsDeviceManager.GraphicsDevice, Content);
|
||||
|
||||
TitleScreen.LoadState = 90.0f;
|
||||
|
||||
TitleScreen.LoadState = 68.0f;
|
||||
yield return CoroutineStatus.Running;
|
||||
|
||||
MainMenuScreen = new MainMenuScreen(this);
|
||||
LobbyScreen = new LobbyScreen();
|
||||
ServerListScreen = new ServerListScreen();
|
||||
|
||||
TitleScreen.LoadState = 70.0f;
|
||||
yield return CoroutineStatus.Running;
|
||||
|
||||
if (SteamManager.USE_STEAM)
|
||||
{
|
||||
SteamWorkshopScreen = new SteamWorkshopScreen();
|
||||
}
|
||||
|
||||
SubEditorScreen = new SubEditorScreen();
|
||||
|
||||
TitleScreen.LoadState = 75.0f;
|
||||
yield return CoroutineStatus.Running;
|
||||
|
||||
ParticleEditorScreen = new ParticleEditorScreen();
|
||||
|
||||
TitleScreen.LoadState = 80.0f;
|
||||
yield return CoroutineStatus.Running;
|
||||
|
||||
LevelEditorScreen = new LevelEditorScreen();
|
||||
SpriteEditorScreen = new SpriteEditorScreen();
|
||||
CharacterEditorScreen = new CharacterEditorScreen();
|
||||
|
||||
yield return CoroutineStatus.Running;
|
||||
|
||||
TitleScreen.LoadState = 95.0f;
|
||||
TitleScreen.LoadState = 85.0f;
|
||||
ParticleManager = new ParticleManager(GameScreen.Cam);
|
||||
ParticleManager.LoadPrefabs();
|
||||
TitleScreen.LoadState = 97.0f;
|
||||
TitleScreen.LoadState = 88.0f;
|
||||
LevelObjectPrefab.LoadAll();
|
||||
DecalManager = new DecalManager();
|
||||
TitleScreen.LoadState = 99.0f;
|
||||
|
||||
TitleScreen.LoadState = 90.0f;
|
||||
yield return CoroutineStatus.Running;
|
||||
|
||||
DecalManager = new DecalManager();
|
||||
LocationType.Init();
|
||||
MainMenuScreen.Select();
|
||||
|
||||
@@ -634,6 +643,7 @@ namespace Barotrauma
|
||||
|
||||
PlayerInput.Update(Timing.Step);
|
||||
|
||||
|
||||
if (loadingScreenOpen)
|
||||
{
|
||||
//reset accumulator if loading
|
||||
@@ -641,6 +651,11 @@ namespace Barotrauma
|
||||
// -> no pause caused by leftover time in the accumulator when starting a new shift
|
||||
GameMain.ResetFrameTime();
|
||||
|
||||
if (!TitleScreen.PlayingSplashScreen)
|
||||
{
|
||||
SoundPlayer.Update((float)Timing.Step);
|
||||
}
|
||||
|
||||
if (TitleScreen.LoadState >= 100.0f && !TitleScreen.PlayingSplashScreen &&
|
||||
(!waitForKeyHit || ((PlayerInput.GetKeyboardState.GetPressedKeys().Length > 0 || PlayerInput.LeftButtonClicked()) && WindowActive)))
|
||||
{
|
||||
|
||||
@@ -455,10 +455,14 @@ namespace Barotrauma
|
||||
isHorizontal: true, childAnchor: Anchor.CenterLeft)
|
||||
{
|
||||
AbsoluteSpacing = (int)(10 * GUI.Scale),
|
||||
UserData = "orderbuttons",
|
||||
CanBeFocused = false
|
||||
UserData = "orderbuttons"
|
||||
};
|
||||
|
||||
var spacer = new GUIFrame(new RectTransform(new Point(spacing, orderButtonFrame.Rect.Height), frame.RectTransform)
|
||||
{
|
||||
AbsoluteOffset = new Point(characterInfoWidth, 0)
|
||||
});
|
||||
|
||||
//listbox for holding the orders inappropriate for this character
|
||||
//(so we can easily toggle their visibility)
|
||||
var wrongOrderList = new GUIListBox(new RectTransform(new Point(50, orderButtonFrame.Rect.Height), orderButtonFrame.RectTransform), isHorizontal: true, style: null)
|
||||
|
||||
@@ -32,7 +32,6 @@ namespace Barotrauma.Tutorials
|
||||
private LightComponent mechanic_thirdDoorLight;
|
||||
private Structure mechanic_brokenWall_1;
|
||||
private Hull mechanic_brokenhull_1;
|
||||
private MotionSensor mechanic_ladderSensor;
|
||||
|
||||
// Room 4
|
||||
private MotionSensor mechanic_craftingObjectiveSensor;
|
||||
|
||||
@@ -752,11 +752,11 @@ namespace Barotrauma
|
||||
character.SelectedBy.Inventory != null)
|
||||
{
|
||||
//item is in the inventory of another character -> attempt to get the item from there
|
||||
success = character.SelectedBy.Inventory.TryPutItem(item, Character.Controlled, item.AllowedSlots, true);
|
||||
success = character.SelectedBy.Inventory.TryPutItemWithAutoEquipCheck(item, Character.Controlled, item.AllowedSlots, true);
|
||||
}
|
||||
break;
|
||||
case QuickUseAction.TakeFromContainer:
|
||||
success = TryPutItem(item, Character.Controlled, item.AllowedSlots, true);
|
||||
success = TryPutItemWithAutoEquipCheck(item, Character.Controlled, item.AllowedSlots, true);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -182,7 +182,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
|
||||
|
||||
partial void SetState(bool open, bool isNetworkMessage, bool sendNetworkMessage)
|
||||
partial void SetState(bool open, bool isNetworkMessage, bool sendNetworkMessage, bool forcedOpen)
|
||||
{
|
||||
if (isStuck ||
|
||||
(PredictedState == null && isOpen == open) ||
|
||||
@@ -200,12 +200,16 @@ namespace Barotrauma.Items.Components
|
||||
//sent by the server, or reverting it back to its old state if no msg from server was received
|
||||
PredictedState = open;
|
||||
resetPredictionTimer = CorrectionDelay;
|
||||
if (stateChanged) PlaySound(ActionType.OnUse, item.WorldPosition);
|
||||
if (stateChanged) PlaySound(forcedOpen ? ActionType.OnPicked : ActionType.OnUse, item.WorldPosition);
|
||||
}
|
||||
else
|
||||
{
|
||||
isOpen = open;
|
||||
if (!isNetworkMessage || open != PredictedState) PlaySound(ActionType.OnUse, item.WorldPosition);
|
||||
if (!isNetworkMessage || open != PredictedState)
|
||||
{
|
||||
StopPicking(null);
|
||||
PlaySound(forcedOpen ? ActionType.OnPicked : ActionType.OnUse, item.WorldPosition);
|
||||
}
|
||||
}
|
||||
|
||||
//opening a partially stuck door makes it less stuck
|
||||
@@ -217,7 +221,9 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
base.ClientRead(type, msg, sendingTime);
|
||||
|
||||
SetState(msg.ReadBoolean(), isNetworkMessage: true, sendNetworkMessage: false);
|
||||
bool open = msg.ReadBoolean();
|
||||
bool forcedOpen = msg.ReadBoolean();
|
||||
SetState(open, isNetworkMessage: true, sendNetworkMessage: false, forcedOpen: forcedOpen);
|
||||
Stuck = msg.ReadRangedSingle(0.0f, 100.0f, 8);
|
||||
|
||||
PredictedState = null;
|
||||
|
||||
@@ -291,16 +291,16 @@ namespace Barotrauma.Items.Components
|
||||
else
|
||||
{
|
||||
float volume = GetSoundVolume(itemSound);
|
||||
if (volume <= 0.0f) return;
|
||||
if (volume <= 0.0f) { return; }
|
||||
SoundPlayer.PlaySound(itemSound.RoundSound.Sound, position, volume, itemSound.Range, item.CurrentHull);
|
||||
}
|
||||
}
|
||||
|
||||
public void StopSounds(ActionType type)
|
||||
{
|
||||
if (loopingSound == null) return;
|
||||
if (loopingSound == null) { return; }
|
||||
|
||||
if (loopingSound.Type != type) return;
|
||||
if (loopingSound.Type != type) { return; }
|
||||
|
||||
if (loopingSoundChannel != null)
|
||||
{
|
||||
|
||||
@@ -25,12 +25,12 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
noPowerTip = TextManager.Get("SteeringNoPowerTip");
|
||||
|
||||
GuiFrame.RectTransform.RelativeOffset = new Vector2(0.4f, 0.0f);
|
||||
new GUICustomComponent(new RectTransform(new Vector2(0.9f, 0.85f), GuiFrame.RectTransform, Anchor.Center),
|
||||
GuiFrame.RectTransform.RelativeOffset = new Vector2(0.05f, 0.0f);
|
||||
new GUICustomComponent(new RectTransform(new Vector2(0.95f, 0.9f), GuiFrame.RectTransform, Anchor.Center),
|
||||
DrawHUDBack, null);
|
||||
submarineContainer = new GUIFrame(new RectTransform(new Vector2(0.9f, 0.85f), GuiFrame.RectTransform, Anchor.Center), style: null);
|
||||
submarineContainer = new GUIFrame(new RectTransform(new Vector2(0.95f, 0.9f), GuiFrame.RectTransform, Anchor.Center), style: null);
|
||||
|
||||
new GUICustomComponent(new RectTransform(new Vector2(0.9f, 0.85f), GuiFrame.RectTransform, Anchor.Center),
|
||||
new GUICustomComponent(new RectTransform(new Vector2(0.95f, 0.9f), GuiFrame.RectTransform, Anchor.Center),
|
||||
DrawHUDFront, null)
|
||||
{
|
||||
CanBeFocused = false
|
||||
@@ -179,11 +179,21 @@ namespace Barotrauma.Items.Components
|
||||
GetLinkedHulls(hull, hullData.LinkedHulls);
|
||||
hullDatas.Add(hull, hullData);
|
||||
}
|
||||
|
||||
Color neutralColor = Color.DarkCyan;
|
||||
if (hull.RoomName != null)
|
||||
{
|
||||
if (hull.RoomName.Contains("ballast") || hull.RoomName.Contains("Ballast") ||
|
||||
hull.RoomName.Contains("airlock") || hull.RoomName.Contains("Airlock"))
|
||||
{
|
||||
neutralColor = new Color(9, 80, 159);
|
||||
}
|
||||
}
|
||||
|
||||
if (hullData.Distort)
|
||||
{
|
||||
hullFrame.Children.First().Color = Color.Lerp(Color.Black, Color.DarkGray * 0.5f, Rand.Range(0.0f, 1.0f));
|
||||
hullFrame.Color = Color.DarkGray * 0.5f;
|
||||
hullFrame.Color = neutralColor * 0.5f;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -192,20 +202,23 @@ namespace Barotrauma.Items.Components
|
||||
hullFrame.Parent.Rect.Width / (float)hull.Submarine.Borders.Width,
|
||||
hullFrame.Parent.Rect.Height / (float)hull.Submarine.Borders.Height);
|
||||
|
||||
Color borderColor = Color.DarkCyan;
|
||||
Color borderColor = neutralColor;
|
||||
|
||||
float? gapOpenSum = 0.0f;
|
||||
if (ShowHullIntegrity)
|
||||
{
|
||||
gapOpenSum = hull.ConnectedGaps.Where(g => !g.IsRoomToRoom).Sum(g => g.Open);
|
||||
borderColor = Color.Lerp(Color.DarkCyan, Color.Red, Math.Min((float)gapOpenSum, 1.0f));
|
||||
borderColor = Color.Lerp(neutralColor, Color.Red, Math.Min((float)gapOpenSum, 1.0f));
|
||||
}
|
||||
|
||||
float? oxygenAmount = null;
|
||||
if (!RequireOxygenDetectors || hullData?.Oxygen != null)
|
||||
{
|
||||
oxygenAmount = RequireOxygenDetectors ? hullData.Oxygen : hull.OxygenPercentage;
|
||||
GUI.DrawRectangle(spriteBatch, hullFrame.Rect, Color.Lerp(Color.Red * 0.5f, Color.Green * 0.3f, (float)oxygenAmount / 100.0f), true);
|
||||
GUI.DrawRectangle(
|
||||
spriteBatch, hullFrame.Rect,
|
||||
Color.Lerp(Color.Red * 0.5f, Color.Green * 0.3f, (float)oxygenAmount / 100.0f),
|
||||
true);
|
||||
}
|
||||
|
||||
float? waterAmount = null;
|
||||
@@ -234,7 +247,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
else
|
||||
{
|
||||
hullFrame.Children.First().Color = Color.DarkCyan * 0.8f;
|
||||
hullFrame.Children.First().Color = neutralColor * 0.8f;
|
||||
}
|
||||
|
||||
if (mouseOnHull == hull)
|
||||
@@ -291,8 +304,6 @@ namespace Barotrauma.Items.Components
|
||||
GUI.DrawLine(spriteBatch, center + start, center + end, Color.DarkCyan * Rand.Range(0.3f, 0.35f), width: (int)(10 * GUI.Scale));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void GetLinkedHulls(Hull hull, List<Hull> linkedHulls)
|
||||
|
||||
@@ -58,6 +58,10 @@ namespace Barotrauma.Items.Components
|
||||
private GUIFrame inventoryContainer;
|
||||
|
||||
private GUIComponent leftHUDColumn;
|
||||
private GUIComponent midHUDColumn;
|
||||
private GUIComponent rightHUDColumn;
|
||||
|
||||
private GUILayoutGroup sliderControlsContainer;
|
||||
|
||||
private Dictionary<string, GUIButton> warningButtons = new Dictionary<string, GUIButton>();
|
||||
|
||||
@@ -107,11 +111,13 @@ namespace Barotrauma.Items.Components
|
||||
RelativeSpacing = 0.012f,
|
||||
Stretch = true
|
||||
};
|
||||
|
||||
|
||||
GUIFrame columnLeft = new GUIFrame(new RectTransform(new Vector2(0.25f, 1.0f), paddedFrame.RectTransform), style: null);
|
||||
leftHUDColumn = columnLeft;
|
||||
GUIFrame columnMid = new GUIFrame(new RectTransform(new Vector2(0.45f, 1.0f), paddedFrame.RectTransform), style: null);
|
||||
GUIFrame columnRight = new GUIFrame(new RectTransform(new Vector2(0.3f, 1.0f), paddedFrame.RectTransform), style: null);
|
||||
leftHUDColumn = columnLeft;
|
||||
midHUDColumn = columnMid;
|
||||
rightHUDColumn = columnRight;
|
||||
|
||||
//----------------------------------------------------------
|
||||
//left column
|
||||
@@ -180,9 +186,16 @@ namespace Barotrauma.Items.Components
|
||||
ToolTip = TextManager.Get("ReactorTipTurbineOutput")
|
||||
};
|
||||
|
||||
new GUITextBlock(new RectTransform(new Point(0, (int)(20 * GUI.Scale)), columnMid.RectTransform, Anchor.BottomLeft) { AbsoluteOffset = new Point(0, (int)(90 * GUI.Scale)) },
|
||||
GUILayoutGroup sliderControls = new GUILayoutGroup(new RectTransform(new Point(columnMid.Rect.Width, (int)(114 * GUI.Scale)), columnMid.RectTransform, Anchor.BottomCenter))
|
||||
{
|
||||
Stretch = true,
|
||||
AbsoluteSpacing = (int)(5 * GUI.Scale)
|
||||
};
|
||||
sliderControlsContainer = sliderControls;
|
||||
|
||||
new GUITextBlock(new RectTransform(new Point(0, (int)(20 * GUI.Scale)), sliderControls.RectTransform, Anchor.TopLeft),
|
||||
TextManager.Get("ReactorFissionRate"));
|
||||
fissionRateScrollBar = new GUIScrollBar(new RectTransform(new Point(columnMid.Rect.Width, (int)(30 * GUI.Scale)), columnMid.RectTransform, Anchor.BottomCenter) { AbsoluteOffset = new Point(0, (int)(60 * GUI.Scale)) },
|
||||
fissionRateScrollBar = new GUIScrollBar(new RectTransform(new Point(sliderControls.Rect.Width, (int)(30 * GUI.Scale)), sliderControls.RectTransform, Anchor.TopCenter),
|
||||
style: "GUISlider", barSize: 0.1f)
|
||||
{
|
||||
OnMoved = (GUIScrollBar bar, float scrollAmount) =>
|
||||
@@ -194,10 +207,10 @@ namespace Barotrauma.Items.Components
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
new GUITextBlock(new RectTransform(new Point(0, (int)(20 * GUI.Scale)), columnMid.RectTransform, Anchor.BottomLeft) { AbsoluteOffset = new Point(0, (int)(30 * GUI.Scale)) },
|
||||
|
||||
new GUITextBlock(new RectTransform(new Point(0, (int)(20 * GUI.Scale)), sliderControls.RectTransform, Anchor.BottomLeft),
|
||||
TextManager.Get("ReactorTurbineOutput"));
|
||||
turbineOutputScrollBar = new GUIScrollBar(new RectTransform(new Point(columnMid.Rect.Width, (int)(30 * GUI.Scale)), columnMid.RectTransform, Anchor.BottomCenter),
|
||||
turbineOutputScrollBar = new GUIScrollBar(new RectTransform(new Point(sliderControls.Rect.Width, (int)(30 * GUI.Scale)), sliderControls.RectTransform, Anchor.BottomCenter),
|
||||
style: "GUISlider", barSize: 0.1f, isHorizontal: true)
|
||||
{
|
||||
OnMoved = (GUIScrollBar bar, float scrollAmount) =>
|
||||
@@ -263,11 +276,11 @@ namespace Barotrauma.Items.Components
|
||||
"Load", textColor: Color.LightBlue, textAlignment: Alignment.CenterLeft)
|
||||
{
|
||||
ToolTip = TextManager.Get("ReactorTipLoad")
|
||||
};
|
||||
};
|
||||
string loadStr = TextManager.Get("ReactorLoad");
|
||||
loadText.TextGetter += () => { return loadStr.Replace("[kw]", ((int)load).ToString()); };
|
||||
|
||||
var outputText = new GUITextBlock(new RectTransform(textSize, graphArea.RectTransform, Anchor.BottomLeft, Pivot.TopLeft),
|
||||
var outputText = new GUITextBlock(new RectTransform(textSize, graphArea.RectTransform, Anchor.BottomLeft, Pivot.TopLeft),
|
||||
"Output", textColor: Color.LightGreen, textAlignment: Alignment.CenterLeft)
|
||||
{
|
||||
ToolTip = TextManager.Get("ReactorTipPower")
|
||||
@@ -321,9 +334,9 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
if (temperature > optimalTemperature.Y)
|
||||
{
|
||||
GUI.DrawRectangle(spriteBatch,
|
||||
new Vector2(graphArea.X - 30, graphArea.Y),
|
||||
new Vector2(tempMeterFrame.SourceRect.Width, (graphArea.Bottom - graphArea.Height * optimalTemperature.Y / 100.0f) - graphArea.Y),
|
||||
GUI.DrawRectangle(spriteBatch,
|
||||
new Vector2(graphArea.X - 30, graphArea.Y),
|
||||
new Vector2(tempMeterFrame.SourceRect.Width, (graphArea.Bottom - graphArea.Height * optimalTemperature.Y / 100.0f) - graphArea.Y),
|
||||
Color.Red * (float)Math.Sin(Timing.TotalTime * 5.0f) * 0.7f, isFilled: true);
|
||||
}
|
||||
if (temperature < optimalTemperature.X)
|
||||
@@ -415,15 +428,52 @@ namespace Barotrauma.Items.Components
|
||||
warningButtons["ReactorWarningLowFuel"].Selected = prevAvailableFuel < fissionRate && lightOn;
|
||||
warningButtons["ReactorWarningMeltdown"].Selected = meltDownTimer > MeltdownDelay * 0.5f || item.Condition == 0.0f && lightOn;
|
||||
warningButtons["ReactorWarningSCRAM"].Selected = temperature > 0.1f && onOffSwitch.BarScroll > 0.5f;
|
||||
|
||||
|
||||
AutoTemp = autoTempSlider.BarScroll < 0.5f;
|
||||
shutDown = onOffSwitch.BarScroll > 0.5f;
|
||||
|
||||
if ((sliderControlsContainer.Rect.Contains(PlayerInput.MousePosition) || sliderControlsContainer.Children.Contains(GUIScrollBar.draggingBar)) &&
|
||||
!PlayerInput.KeyDown(InputType.Deselect) && !PlayerInput.KeyHit(InputType.Deselect))
|
||||
{
|
||||
Character.DisableControls = true;
|
||||
}
|
||||
|
||||
if (shutDown)
|
||||
{
|
||||
fissionRateScrollBar.BarScroll = FissionRate / 100.0f;
|
||||
turbineOutputScrollBar.BarScroll = TurbineOutput / 100.0f;
|
||||
}
|
||||
}
|
||||
else if (!autoTemp && Character.DisableControls && GUI.KeyboardDispatcher.Subscriber == null)
|
||||
{
|
||||
Vector2 input = Vector2.Zero;
|
||||
float rate = 50.0f; //percentage per second
|
||||
|
||||
if (PlayerInput.KeyDown(InputType.Left)) input.X += -1.0f;
|
||||
if (PlayerInput.KeyDown(InputType.Right)) input.X += 1.0f;
|
||||
if (PlayerInput.KeyDown(InputType.Up)) input.Y += 1.0f;
|
||||
if (PlayerInput.KeyDown(InputType.Down)) input.Y += -1.0f;
|
||||
if (PlayerInput.KeyDown(InputType.Run)) rate = 200.0f;
|
||||
|
||||
rate *= deltaTime;
|
||||
input.X *= rate;
|
||||
input.Y *= rate;
|
||||
|
||||
if (input.LengthSquared() > 0)
|
||||
{
|
||||
LastUser = Character.Controlled;
|
||||
unsentChanges = true;
|
||||
if (input.X != 0.0f && GUIScrollBar.draggingBar != fissionRateScrollBar)
|
||||
{
|
||||
targetFissionRate = MathHelper.Clamp(targetFissionRate + input.X, 0.0f, 100.0f);
|
||||
fissionRateScrollBar.BarScroll += input.X / 100.0f;
|
||||
}
|
||||
if (input.Y != 0.0f && GUIScrollBar.draggingBar != turbineOutputScrollBar)
|
||||
{
|
||||
targetTurbineOutput = MathHelper.Clamp(targetTurbineOutput + input.Y, 0.0f, 100.0f);
|
||||
turbineOutputScrollBar.BarScroll += input.Y / 100.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool ToggleAutoTemp(GUITickBox tickBox)
|
||||
|
||||
@@ -11,12 +11,6 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
partial class Sonar : Powered, IServerSerializable, IClientSerializable
|
||||
{
|
||||
enum Mode
|
||||
{
|
||||
Active,
|
||||
Passive
|
||||
};
|
||||
|
||||
private bool dynamicDockingIndicator = true;
|
||||
|
||||
private bool unsentChanges;
|
||||
@@ -43,8 +37,6 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
private List<SonarBlip> sonarBlips;
|
||||
|
||||
private float prevPingRadius;
|
||||
|
||||
private float prevPassivePingRadius;
|
||||
|
||||
private Vector2 center;
|
||||
@@ -102,7 +94,7 @@ namespace Barotrauma.Items.Components
|
||||
ToolTip = TextManager.Get("SonarTipActive"),
|
||||
OnSelected = (GUITickBox box) =>
|
||||
{
|
||||
IsActive = box.Selected;
|
||||
CurrentMode = box.Selected ? Mode.Active : Mode.Passive;
|
||||
if (GameMain.Client != null)
|
||||
{
|
||||
unsentChanges = true;
|
||||
@@ -262,7 +254,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
if (component is GUITextBlock textBlock)
|
||||
{
|
||||
textBlock.TextColor = IsActive ? textBlock.Style.textColor : textBlock.Style.textColor * 0.5f;
|
||||
textBlock.TextColor = currentMode == Mode.Active ? textBlock.Style.textColor : textBlock.Style.textColor * 0.5f;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -281,14 +273,21 @@ namespace Barotrauma.Items.Components
|
||||
if (Level.Loaded != null)
|
||||
{
|
||||
Dictionary<LevelTrigger, Vector2> levelTriggerFlows = new Dictionary<LevelTrigger, Vector2>();
|
||||
foreach (LevelObject levelObject in Level.Loaded.LevelObjectManager.GetAllObjects(transducerCenter, range * pingState / zoom))
|
||||
for (var pingIndex = 0; pingIndex < activePingsCount; ++pingIndex)
|
||||
{
|
||||
//gather all nearby triggers that are causing the water to flow into the dictionary
|
||||
foreach (LevelTrigger trigger in levelObject.Triggers)
|
||||
var activePing = activePings[pingIndex];
|
||||
foreach (LevelObject levelObject in Level.Loaded.LevelObjectManager.GetAllObjects(transducerCenter, range * activePing.State / zoom))
|
||||
{
|
||||
Vector2 flow = trigger.GetWaterFlowVelocity();
|
||||
//ignore ones that are barely doing anything (flow^2 < 1)
|
||||
if (flow.LengthSquared() > 1.0f) levelTriggerFlows.Add(trigger, flow);
|
||||
//gather all nearby triggers that are causing the water to flow into the dictionary
|
||||
foreach (LevelTrigger trigger in levelObject.Triggers)
|
||||
{
|
||||
Vector2 flow = trigger.GetWaterFlowVelocity();
|
||||
//ignore ones that are barely doing anything (flow^2 < 1)
|
||||
if (flow.LengthSquared() > 1.0f && !levelTriggerFlows.ContainsKey(trigger))
|
||||
{
|
||||
levelTriggerFlows.Add(trigger, flow);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -350,13 +349,18 @@ namespace Barotrauma.Items.Components
|
||||
prevDockingDist = float.MaxValue;
|
||||
}
|
||||
|
||||
if (IsActive)
|
||||
for (var pingIndex = 0; pingIndex < activePingsCount; ++pingIndex)
|
||||
{
|
||||
var activePing = activePings[pingIndex];
|
||||
float pingRadius = DisplayRadius * activePing.State / zoom;
|
||||
UpdateDisruptions(transducerCenter, pingRadius / displayScale, activePing.PrevPingRadius / displayScale);
|
||||
Ping(transducerCenter, transducerCenter,
|
||||
pingRadius, activePing.PrevPingRadius, displayScale, range / zoom, passive: false, pingStrength: 2.0f);
|
||||
activePing.PrevPingRadius = pingRadius;
|
||||
|
||||
}
|
||||
if (currentMode == Mode.Active && currentPingIndex != -1)
|
||||
{
|
||||
float pingRadius = DisplayRadius * pingState / zoom;
|
||||
UpdateDisruptions(transducerCenter, pingRadius / displayScale, prevPingRadius / displayScale);
|
||||
Ping(transducerCenter, transducerCenter,
|
||||
pingRadius, prevPingRadius, displayScale, range / zoom, passive: false, pingStrength: 2.0f);
|
||||
prevPingRadius = pingRadius;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -396,17 +400,18 @@ namespace Barotrauma.Items.Components
|
||||
screenBackground.Draw(spriteBatch, center, 0.0f, rect.Width / screenBackground.size.X);
|
||||
}
|
||||
|
||||
if (IsActive)
|
||||
if (currentMode == Mode.Active && currentPingIndex != -1)
|
||||
{
|
||||
if (isLastPingDirectional && directionalPingCircle != null)
|
||||
var activePing = activePings[currentPingIndex];
|
||||
if (activePing.IsDirectional && directionalPingCircle != null)
|
||||
{
|
||||
directionalPingCircle.Draw(spriteBatch, center, Color.White * (1.0f - pingState),
|
||||
rotate: MathUtils.VectorToAngle(lastPingDirection),
|
||||
scale: (DisplayRadius / directionalPingCircle.size.X) * pingState);
|
||||
directionalPingCircle.Draw(spriteBatch, center, Color.White * (1.0f - activePing.State),
|
||||
rotate: MathUtils.VectorToAngle(activePing.Direction),
|
||||
scale: (DisplayRadius / directionalPingCircle.size.X) * activePing.State);
|
||||
}
|
||||
else
|
||||
{
|
||||
pingCircle.Draw(spriteBatch, center, Color.White * (1.0f - pingState), 0.0f, (DisplayRadius * 2 / pingCircle.size.X) * pingState);
|
||||
pingCircle.Draw(spriteBatch, center, Color.White * (1.0f - activePing.State), 0.0f, (DisplayRadius * 2 / pingCircle.size.X) * activePing.State);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -448,7 +453,7 @@ namespace Barotrauma.Items.Components
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend);
|
||||
}
|
||||
|
||||
float directionalPingVisibility = useDirectionalPing && IsActive ? 1.0f : showDirectionalIndicatorTimer;
|
||||
float directionalPingVisibility = useDirectionalPing && currentMode == Mode.Active ? 1.0f : showDirectionalIndicatorTimer;
|
||||
if (directionalPingVisibility > 0.0f)
|
||||
{
|
||||
Vector2 sector1 = MathUtils.RotatePointAroundTarget(pingDirection * DisplayRadius, Vector2.Zero, DirectionalPingSector * 0.5f);
|
||||
@@ -753,24 +758,47 @@ namespace Barotrauma.Items.Components
|
||||
disruptedDirections.Clear();
|
||||
if (Level.Loaded == null) { return; }
|
||||
|
||||
foreach (LevelObject levelObject in Level.Loaded.LevelObjectManager.GetAllObjects(pingSource, range * pingState))
|
||||
for (var pingIndex = 0; pingIndex < activePingsCount; ++pingIndex)
|
||||
{
|
||||
if (levelObject.ActivePrefab?.SonarDisruption <= 0.0f) { continue; }
|
||||
|
||||
float disruptionStrength = levelObject.ActivePrefab.SonarDisruption;
|
||||
Vector2 disruptionPos = new Vector2(levelObject.Position.X, levelObject.Position.Y);
|
||||
|
||||
float disruptionDist = Vector2.Distance(pingSource, disruptionPos);
|
||||
disruptedDirections.Add(new Pair<Vector2, float>((disruptionPos - pingSource) / disruptionDist, disruptionStrength));
|
||||
|
||||
if (disruptionDist > worldPrevPingRadius && disruptionDist <= worldPingRadius)
|
||||
var activePing = activePings[pingIndex];
|
||||
foreach (LevelObject levelObject in Level.Loaded.LevelObjectManager.GetAllObjects(pingSource, range * activePing.State))
|
||||
{
|
||||
for (int i = 0; i < disruptionStrength * Level.GridCellSize * 0.02f; i++)
|
||||
if (levelObject.ActivePrefab?.SonarDisruption <= 0.0f) { continue; }
|
||||
|
||||
float disruptionStrength = levelObject.ActivePrefab.SonarDisruption;
|
||||
Vector2 disruptionPos = new Vector2(levelObject.Position.X, levelObject.Position.Y);
|
||||
|
||||
float disruptionDist = Vector2.Distance(pingSource, disruptionPos);
|
||||
disruptedDirections.Add(new Pair<Vector2, float>((disruptionPos - pingSource) / disruptionDist, disruptionStrength));
|
||||
|
||||
if (disruptionDist > worldPrevPingRadius && disruptionDist <= worldPingRadius)
|
||||
{
|
||||
var blip = new SonarBlip(disruptionPos + Rand.Vector(Rand.Range(0.0f, Level.GridCellSize * 4 * disruptionStrength)), MathHelper.Lerp(1.0f, 1.5f, disruptionStrength), Rand.Range(1.0f, 2.0f + disruptionStrength));
|
||||
sonarBlips.Add(blip);
|
||||
CreateBlipsForDisruption(disruptionPos, disruptionStrength);
|
||||
}
|
||||
}
|
||||
foreach (AITarget aiTarget in AITarget.List)
|
||||
{
|
||||
if (aiTarget.SonarDisruption <= 0.0f || !aiTarget.Enabled) { continue; }
|
||||
float distSqr = Vector2.DistanceSquared(aiTarget.WorldPosition, pingSource);
|
||||
if (distSqr > worldPingRadiusSqr) { continue; }
|
||||
|
||||
float disruptionDist = (float)Math.Sqrt(distSqr);
|
||||
disruptedDirections.Add(new Pair<Vector2, float>((aiTarget.WorldPosition - pingSource) / disruptionDist, aiTarget.SonarDisruption));
|
||||
|
||||
if (disruptionDist > worldPrevPingRadius && disruptionDist <= worldPingRadius)
|
||||
{
|
||||
CreateBlipsForDisruption(aiTarget.WorldPosition, aiTarget.SonarDisruption);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CreateBlipsForDisruption(Vector2 disruptionPos, float disruptionStrength)
|
||||
{
|
||||
for (int i = 0; i < disruptionStrength * Level.GridCellSize * 0.02f; i++)
|
||||
{
|
||||
var blip = new SonarBlip(disruptionPos + Rand.Vector(Rand.Range(0.0f, Level.GridCellSize * 4 * disruptionStrength)), MathHelper.Lerp(1.0f, 1.5f, disruptionStrength), Rand.Range(1.0f, 2.0f + disruptionStrength));
|
||||
sonarBlips.Add(blip);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1045,9 +1073,9 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
|
||||
Vector2 dir = pos / (float)Math.Sqrt(posDistSqr);
|
||||
if (isLastPingDirectional)
|
||||
if (currentPingIndex != -1 && activePings[currentPingIndex].IsDirectional)
|
||||
{
|
||||
if (Vector2.Dot(lastPingDirection, dir) < DirectionalPingDotProduct)
|
||||
if (Vector2.Dot(activePings[currentPingIndex].Direction, dir) < DirectionalPingDotProduct)
|
||||
{
|
||||
blip.FadeTimer = 0.0f;
|
||||
return false;
|
||||
@@ -1155,8 +1183,8 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public void ClientWrite(Lidgren.Network.NetBuffer msg, object[] extraData = null)
|
||||
{
|
||||
msg.Write(IsActive);
|
||||
if (IsActive)
|
||||
msg.Write(currentMode == Mode.Active);
|
||||
if (currentMode == Mode.Active)
|
||||
{
|
||||
msg.WriteRangedSingle(zoom, MinZoom, MaxZoom, 8);
|
||||
msg.Write(useDirectionalPing);
|
||||
@@ -1192,8 +1220,8 @@ namespace Barotrauma.Items.Components
|
||||
StartDelayedCorrection(type, msg.ExtractBits(msgLength), sendingTime);
|
||||
return;
|
||||
}
|
||||
|
||||
IsActive = isActive;
|
||||
|
||||
CurrentMode = isActive ? Mode.Active : Mode.Passive;
|
||||
if (isActive)
|
||||
{
|
||||
activeTickBox.Selected = true;
|
||||
|
||||
@@ -735,9 +735,7 @@ namespace Barotrauma.Items.Components
|
||||
if (sourcePort.Docked || sourcePort.Item.Submarine == null) { continue; }
|
||||
if (sourcePort.Item.Submarine != controlledSub) { continue; }
|
||||
|
||||
int sourceDir = sourcePort.IsHorizontal ?
|
||||
Math.Sign(sourcePort.Item.WorldPosition.X - sourcePort.Item.Submarine.WorldPosition.X) :
|
||||
Math.Sign(sourcePort.Item.WorldPosition.Y - sourcePort.Item.Submarine.WorldPosition.Y);
|
||||
int sourceDir = sourcePort.GetDir();
|
||||
|
||||
foreach (DockingPort targetPort in DockingPort.List)
|
||||
{
|
||||
@@ -745,9 +743,7 @@ namespace Barotrauma.Items.Components
|
||||
if (targetPort.Item.Submarine == controlledSub || targetPort.IsHorizontal != sourcePort.IsHorizontal) { continue; }
|
||||
if (Level.Loaded != null && targetPort.Item.Submarine.WorldPosition.Y > Level.Loaded.Size.Y) { continue; }
|
||||
|
||||
int targetDir = targetPort.IsHorizontal ?
|
||||
Math.Sign(targetPort.Item.WorldPosition.X - targetPort.Item.Submarine.WorldPosition.X) :
|
||||
Math.Sign(targetPort.Item.WorldPosition.Y - targetPort.Item.Submarine.WorldPosition.Y);
|
||||
int targetDir = targetPort.GetDir();
|
||||
|
||||
if (sourceDir == targetDir) { continue; }
|
||||
|
||||
|
||||
@@ -1,19 +1,16 @@
|
||||
using System.Collections.Generic;
|
||||
using Barotrauma.Sounds;
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Linq;
|
||||
using Barotrauma.Sounds;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
partial class Powered : ItemComponent
|
||||
{
|
||||
protected List<RoundSound> sparkSounds;
|
||||
|
||||
private RoundSound powerOnSound;
|
||||
private bool powerOnSoundPlayed;
|
||||
|
||||
partial void InitProjectSpecific(XElement element)
|
||||
{
|
||||
sparkSounds = new List<RoundSound>();
|
||||
foreach (XElement subElement in element.Elements())
|
||||
{
|
||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||
@@ -21,10 +18,6 @@ namespace Barotrauma.Items.Components
|
||||
case "poweronsound":
|
||||
powerOnSound = Submarine.LoadRoundSound(subElement, false);
|
||||
break;
|
||||
case "sparksound":
|
||||
var sparkSound = Submarine.LoadRoundSound(subElement, false);
|
||||
if (sparkSound != null) { sparkSounds.Add(sparkSound); }
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,8 @@ namespace Barotrauma.Items.Components
|
||||
private List<ParticleEmitter> ParticleEmitterHitCharacter = new List<ParticleEmitter>();
|
||||
private List<Pair<RelatedItem, ParticleEmitter>> ParticleEmitterHitItem = new List<Pair<RelatedItem, ParticleEmitter>>();
|
||||
|
||||
private float prevProgressBarState;
|
||||
|
||||
partial void InitProjSpecific(XElement element)
|
||||
{
|
||||
foreach (XElement subElement in element.Elements())
|
||||
@@ -70,7 +72,7 @@ namespace Barotrauma.Items.Components
|
||||
float particleAngle = item.body.Rotation + ((item.body.Dir > 0.0f) ? 0.0f : MathHelper.Pi);
|
||||
ParticleEmitter.Emit(
|
||||
deltaTime, item.WorldPosition + TransformedBarrelPos,
|
||||
item.CurrentHull, particleAngle, -particleAngle);
|
||||
item.CurrentHull, particleAngle, ParticleEmitter.Prefab.CopyEntityAngle ? -particleAngle : 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,19 +112,22 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
partial void FixItemProjSpecific(Character user, float deltaTime, Item targetItem, float prevCondition)
|
||||
partial void FixItemProjSpecific(Character user, float deltaTime, Item targetItem)
|
||||
{
|
||||
if (prevCondition != targetItem.Condition)
|
||||
float progressBarState = targetItem.ConditionPercentage / 100.0f;
|
||||
if (!MathUtils.NearlyEqual(progressBarState, prevProgressBarState))
|
||||
{
|
||||
Vector2 progressBarPos = targetItem.DrawPosition;
|
||||
var progressBar = user.UpdateHUDProgressBar(
|
||||
targetItem,
|
||||
progressBarPos,
|
||||
targetItem.Condition / item.MaxCondition,
|
||||
progressBarState,
|
||||
Color.Red, Color.Green);
|
||||
if (progressBar != null) { progressBar.Size = new Vector2(60.0f, 20.0f); }
|
||||
}
|
||||
|
||||
prevProgressBarState = progressBarState;
|
||||
|
||||
Vector2 particlePos = ConvertUnits.ToDisplayUnits(pickedPosition);
|
||||
if (targetItem.Submarine != null) particlePos += targetItem.Submarine.DrawPosition;
|
||||
foreach (var emitter in ParticleEmitterHitItem)
|
||||
|
||||
@@ -74,10 +74,16 @@ namespace Barotrauma.Items.Components
|
||||
//dropped or dragged from the panel to the players inventory
|
||||
if (draggingConnected != null)
|
||||
{
|
||||
int linkIndex = c.FindWireIndex(draggingConnected.Item);
|
||||
if (linkIndex > -1)
|
||||
//the wire can only be dragged out if it's not connected to anything at the other end
|
||||
if (Screen.Selected == GameMain.SubEditorScreen ||
|
||||
(draggingConnected.Connections[0] == null && draggingConnected.Connections[1] == null) ||
|
||||
(draggingConnected.Connections.Contains(c) && draggingConnected.Connections.Contains(null)))
|
||||
{
|
||||
Inventory.draggingItem = c.wires[linkIndex].Item;
|
||||
int linkIndex = c.FindWireIndex(draggingConnected.Item);
|
||||
if (linkIndex > -1 || panel.DisconnectedWires.Contains(draggingConnected))
|
||||
{
|
||||
Inventory.draggingItem = draggingConnected.Item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,59 +115,79 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
if (draggingConnected != null)
|
||||
{
|
||||
DrawWire(spriteBatch, draggingConnected, draggingConnected.Item, PlayerInput.MousePosition, new Vector2(x + width / 2, y + height - 10), mouseInRect, null, panel, "");
|
||||
if (mouseInRect)
|
||||
{
|
||||
DrawWire(spriteBatch, draggingConnected, PlayerInput.MousePosition, new Vector2(x + width / 2, y + height - 10), null, panel, "");
|
||||
}
|
||||
|
||||
if (!PlayerInput.LeftButtonHeld())
|
||||
{
|
||||
if (GameMain.Client != null)
|
||||
if (draggingConnected.Connections[0]?.ConnectionPanel == panel ||
|
||||
draggingConnected.Connections[1]?.ConnectionPanel == panel)
|
||||
{
|
||||
panel.Item.CreateClientEvent(panel);
|
||||
draggingConnected.RemoveConnection(panel.Item);
|
||||
panel.DisconnectedWires.Add(draggingConnected);
|
||||
}
|
||||
|
||||
if (GameMain.Client != null) { panel.Item.CreateClientEvent(panel); }
|
||||
draggingConnected = 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
|
||||
if (equippedWire != null)
|
||||
if (equippedWire != null && (draggingConnected != equippedWire || !mouseInRect))
|
||||
{
|
||||
if (panel.Connections.Find(c => c.Wires.Contains(equippedWire)) == null)
|
||||
{
|
||||
DrawWire(spriteBatch, equippedWire, equippedWire.Item,
|
||||
new Vector2(x + width / 2, y + height - 100),
|
||||
new Vector2(x + width / 2, y + height), mouseInRect, null, panel, "");
|
||||
DrawWire(spriteBatch, equippedWire, new Vector2(x + width / 2, y + height - 150 * GUI.Scale),
|
||||
new Vector2(x + width / 2, y + height),
|
||||
null, panel, "");
|
||||
|
||||
if (draggingConnected == equippedWire) Inventory.draggingItem = equippedWire.Item;
|
||||
if (draggingConnected == equippedWire) { Inventory.draggingItem = equippedWire.Item; }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
float step = (width * 0.75f) / panel.DisconnectedWires.Count();
|
||||
x = (int)(x + width / 2 - step * (panel.DisconnectedWires.Count() - 1) / 2);
|
||||
foreach (Wire wire in panel.DisconnectedWires)
|
||||
{
|
||||
if (wire == draggingConnected && mouseInRect) { continue; }
|
||||
|
||||
Connection recipient = wire.OtherConnection(null);
|
||||
string label = recipient == null ? "" : recipient.item.Name + $" ({recipient.DisplayName})";
|
||||
if (wire.Locked) { label += "\n" + TextManager.Get("ConnectionLocked"); }
|
||||
DrawWire(spriteBatch, wire, new Vector2(x, y + height - 100 * GUI.Scale),
|
||||
new Vector2(x, y + height),
|
||||
null, panel, label);
|
||||
x += (int)step;
|
||||
}
|
||||
|
||||
//stop dragging a wire item if the cursor is within any connection panel
|
||||
//(so we don't drop the item when dropping the wire on a connection)
|
||||
if (mouseInRect || GUI.MouseOn?.UserData is ConnectionPanel) Inventory.draggingItem = null;
|
||||
if (mouseInRect || GUI.MouseOn?.UserData is ConnectionPanel) { Inventory.draggingItem = null; }
|
||||
}
|
||||
|
||||
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, DisplayName, IsPower ? Color.Red : Color.White, Color.Black, 0, GUI.SmallFont);
|
||||
|
||||
|
||||
connectionSprite.Draw(spriteBatch, position);
|
||||
|
||||
for (int i = 0; i < MaxLinked; i++)
|
||||
{
|
||||
if (wires[i] == null || wires[i].Hidden || draggingConnected == wires[i]) continue;
|
||||
if (wires[i] == null || wires[i].Hidden || (draggingConnected == wires[i] && (mouseIn || Screen.Selected == GameMain.SubEditorScreen))) { continue; }
|
||||
|
||||
Connection recipient = wires[i].OtherConnection(this);
|
||||
|
||||
string label = recipient == null ? "" :
|
||||
wires[i].Locked ? recipient.item.Name + "\n" + TextManager.Get("ConnectionLocked") : recipient.item.Name;
|
||||
DrawWire(spriteBatch, wires[i], (recipient == null) ? wires[i].Item : recipient.item, position, wirePosition, mouseIn, equippedWire, panel, label);
|
||||
string label = recipient == null ? "" : recipient.item.Name + $" ({recipient.DisplayName})";
|
||||
if (wires[i].Locked) { label += "\n" + TextManager.Get("ConnectionLocked"); }
|
||||
DrawWire(spriteBatch, wires[i], position, wirePosition, equippedWire, panel, label);
|
||||
|
||||
wirePosition.Y += wireInterval;
|
||||
}
|
||||
|
||||
if (draggingConnected != null && Vector2.Distance(position, PlayerInput.MousePosition) < 13.0f)
|
||||
if (draggingConnected != null && Vector2.Distance(position, PlayerInput.MousePosition) < (20.0f * GUI.Scale))
|
||||
{
|
||||
connectionSpriteHighlight.Draw(spriteBatch, position);
|
||||
|
||||
@@ -172,15 +198,15 @@ namespace Barotrauma.Items.Components
|
||||
if (index > -1 && !Wires.Contains(draggingConnected))
|
||||
{
|
||||
bool alreadyConnected = draggingConnected.IsConnectedTo(panel.Item);
|
||||
|
||||
draggingConnected.RemoveConnection(panel.Item);
|
||||
|
||||
if (draggingConnected.Connect(this, !alreadyConnected, true))
|
||||
{
|
||||
var otherConnection = draggingConnected.OtherConnection(this);
|
||||
SetWire(index, draggingConnected);
|
||||
}
|
||||
}
|
||||
if (GameMain.Client != null) { panel.Item.CreateClientEvent(panel); }
|
||||
draggingConnected = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -215,15 +241,8 @@ namespace Barotrauma.Items.Components
|
||||
flashTimer -= deltaTime;
|
||||
}
|
||||
|
||||
private static void DrawWire(SpriteBatch spriteBatch, Wire wire, Item item, Vector2 end, Vector2 start, bool mouseIn, Wire equippedWire, ConnectionPanel panel, string label)
|
||||
private static void DrawWire(SpriteBatch spriteBatch, Wire wire, Vector2 end, Vector2 start, Wire equippedWire, ConnectionPanel panel, string label)
|
||||
{
|
||||
if (draggingConnected == wire)
|
||||
{
|
||||
if (!mouseIn) return;
|
||||
end = PlayerInput.MousePosition;
|
||||
start.X = (start.X + end.X) / 2.0f;
|
||||
}
|
||||
|
||||
int textX = (int)start.X;
|
||||
if (start.X < end.X)
|
||||
textX -= 10;
|
||||
@@ -244,11 +263,19 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
if (!string.IsNullOrEmpty(label))
|
||||
{
|
||||
GUI.DrawString(spriteBatch,
|
||||
new Vector2(start.X < end.X ? textX - GUI.SmallFont.MeasureString(label).X : textX, start.Y - 5.0f),
|
||||
label,
|
||||
(mouseOn ? Color.Gold : Color.White) * (wire.Locked ? 0.6f : 1.0f), Color.Black * 0.8f,
|
||||
3, GUI.SmallFont);
|
||||
if (start.Y > panel.GuiFrame.Rect.Bottom - 1.0f)
|
||||
{
|
||||
//wire at the bottom of the panel -> draw the text below the panel, tilted 45 degrees
|
||||
GUI.SmallFont.DrawString(spriteBatch, label, start + Vector2.UnitY * 20 * GUI.Scale, Color.White, 45.0f, Vector2.Zero, 1.0f, SpriteEffects.None, 0.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
GUI.DrawString(spriteBatch,
|
||||
new Vector2(start.X < end.X ? textX - GUI.SmallFont.MeasureString(label).X : textX, start.Y - 5.0f),
|
||||
label,
|
||||
(mouseOn ? Color.Gold : Color.White) * (wire.Locked ? 0.6f : 1.0f), Color.Black * 0.8f,
|
||||
3, GUI.SmallFont);
|
||||
}
|
||||
}
|
||||
|
||||
var wireEnd = end + Vector2.Normalize(start - end) * 30.0f;
|
||||
@@ -259,14 +286,14 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
spriteBatch.Draw(wireVertical.Texture, new Rectangle(wireEnd.ToPoint(), new Point(18, (int)dist)), wireVertical.SourceRect,
|
||||
Color.Gold,
|
||||
MathUtils.VectorToAngle(end - start) + MathHelper.PiOver2, //angle of line (calulated above)
|
||||
MathUtils.VectorToAngle(end - start) + MathHelper.PiOver2,
|
||||
new Vector2(6, 0), // point in line about which to rotate
|
||||
SpriteEffects.None,
|
||||
0.0f);
|
||||
}
|
||||
spriteBatch.Draw(wireVertical.Texture, new Rectangle(wireEnd.ToPoint(), new Point(12, (int)dist)), wireVertical.SourceRect,
|
||||
wire.Item.Color * alpha,
|
||||
MathUtils.VectorToAngle(end - start) + MathHelper.PiOver2, //angle of line (calulated above)
|
||||
MathUtils.VectorToAngle(end - start) + MathHelper.PiOver2,
|
||||
new Vector2(6, 0), // point in line about which to rotate
|
||||
SpriteEffects.None,
|
||||
0.0f);
|
||||
@@ -283,7 +310,7 @@ namespace Barotrauma.Items.Components
|
||||
if (allowRewiring && !wire.Locked && (!panel.Locked || Screen.Selected == GameMain.SubEditorScreen))
|
||||
{
|
||||
//start dragging the wire
|
||||
if (PlayerInput.LeftButtonHeld()) draggingConnected = wire;
|
||||
if (PlayerInput.LeftButtonHeld()) { draggingConnected = wire; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
private void DrawConnections(SpriteBatch spriteBatch, GUICustomComponent container)
|
||||
{
|
||||
if (user != Character.Controlled || user == null) return;
|
||||
if (user != Character.Controlled || user == null) { return; }
|
||||
|
||||
HighlightedWire = null;
|
||||
Connection.DrawConnections(spriteBatch, this, user);
|
||||
@@ -70,8 +70,22 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
//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);
|
||||
long msgStartPos = msg.Position;
|
||||
foreach (Connection connection in Connections)
|
||||
{
|
||||
for (int i = 0; i < Connection.MaxLinked; i++)
|
||||
{
|
||||
msg.ReadUInt16();
|
||||
}
|
||||
}
|
||||
ushort disconnectedWireCount = msg.ReadUInt16();
|
||||
for (int i = 0; i < disconnectedWireCount; i++)
|
||||
{
|
||||
msg.ReadUInt16();
|
||||
}
|
||||
int msgLength = (int)(msg.Position - msgStartPos);
|
||||
msg.Position = msgStartPos;
|
||||
StartDelayedCorrection(type, msg.ExtractBits(msgLength), sendingTime, waitForMidRoundSync: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -95,11 +109,9 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
ushort wireId = msg.ReadUInt16();
|
||||
|
||||
Item wireItem = Entity.FindEntityByID(wireId) as Item;
|
||||
if (wireItem == null) continue;
|
||||
|
||||
if (!(Entity.FindEntityByID(wireId) is Item wireItem)) { continue; }
|
||||
Wire wireComponent = wireItem.GetComponent<Wire>();
|
||||
if (wireComponent == null) continue;
|
||||
if (wireComponent == null) { continue; }
|
||||
|
||||
newWires.Add(wireComponent);
|
||||
|
||||
@@ -108,18 +120,46 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
List<Wire> previousDisconnectedWires = new List<Wire>(DisconnectedWires);
|
||||
DisconnectedWires.Clear();
|
||||
ushort disconnectedWireCount = msg.ReadUInt16();
|
||||
for (int i = 0; i < disconnectedWireCount; i++)
|
||||
{
|
||||
ushort wireId = msg.ReadUInt16();
|
||||
if (!(Entity.FindEntityByID(wireId) is Item wireItem)) { continue; }
|
||||
Wire wireComponent = wireItem.GetComponent<Wire>();
|
||||
if (wireComponent == null) { continue; }
|
||||
DisconnectedWires.Add(wireComponent);
|
||||
}
|
||||
|
||||
foreach (Wire wire in prevWires)
|
||||
{
|
||||
if (wire.Connections[0] == null && wire.Connections[1] == null)
|
||||
bool connected = wire.Connections[0] != null || wire.Connections[1] != null;
|
||||
if (!connected)
|
||||
{
|
||||
foreach (Item item in Item.ItemList)
|
||||
{
|
||||
var connectionPanel = item.GetComponent<ConnectionPanel>();
|
||||
if (connectionPanel != null && connectionPanel.DisconnectedWires.Contains(wire))
|
||||
{
|
||||
connected = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (wire.Item.ParentInventory == null && !connected)
|
||||
{
|
||||
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))
|
||||
}
|
||||
|
||||
foreach (Wire disconnectedWire in previousDisconnectedWires)
|
||||
{
|
||||
if (disconnectedWire.Connections[0] == null &&
|
||||
disconnectedWire.Connections[1] == null &&
|
||||
!DisconnectedWires.Contains(disconnectedWire))
|
||||
{
|
||||
wire.Item.Drop(null);
|
||||
disconnectedWire.Item.Drop(dropper: null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
@@ -90,18 +91,26 @@ namespace Barotrauma.Items.Components
|
||||
section.Draw(spriteBatch, item.Color, drawOffset, depth, 0.3f);
|
||||
}
|
||||
|
||||
if (IsActive && nodes.Count > 0 && Vector2.Distance(newNodePos, nodes[nodes.Count - 1]) > nodeDistance)
|
||||
if (nodes.Count > 0)
|
||||
{
|
||||
WireSection.Draw(
|
||||
spriteBatch,
|
||||
new Vector2(nodes[nodes.Count - 1].X, nodes[nodes.Count - 1].Y) + drawOffset,
|
||||
new Vector2(newNodePos.X, newNodePos.Y) + drawOffset,
|
||||
item.Color * 0.5f,
|
||||
depth,
|
||||
0.3f);
|
||||
if (!IsActive)
|
||||
{
|
||||
if (connections[0] == null) { DrawHangingWire(spriteBatch, nodes[0] + drawOffset, depth); }
|
||||
if (connections[1] == null) { DrawHangingWire(spriteBatch, nodes.Last() + drawOffset, depth); }
|
||||
}
|
||||
if (IsActive && Vector2.Distance(newNodePos, nodes[nodes.Count - 1]) > nodeDistance)
|
||||
{
|
||||
WireSection.Draw(
|
||||
spriteBatch,
|
||||
new Vector2(nodes[nodes.Count - 1].X, nodes[nodes.Count - 1].Y) + drawOffset,
|
||||
new Vector2(newNodePos.X, newNodePos.Y) + drawOffset,
|
||||
item.Color * 0.5f,
|
||||
depth,
|
||||
0.3f);
|
||||
}
|
||||
}
|
||||
|
||||
if (!editing || !GameMain.SubEditorScreen.WiringMode) return;
|
||||
if (!editing || !GameMain.SubEditorScreen.WiringMode) { return; }
|
||||
|
||||
for (int i = 0; i < nodes.Count; i++)
|
||||
{
|
||||
@@ -126,6 +135,23 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawHangingWire(SpriteBatch spriteBatch, Vector2 start, float depth)
|
||||
{
|
||||
float angle = (float)Math.Sin(GameMain.GameScreen.GameTime * 2.0f + item.ID) * 0.2f;
|
||||
Vector2 endPos = start + new Vector2((float)Math.Sin(angle), -(float)Math.Cos(angle)) * 50.0f;
|
||||
|
||||
WireSection.Draw(
|
||||
spriteBatch,
|
||||
start, endPos,
|
||||
Color.Orange, depth + 0.00001f, 0.2f);
|
||||
|
||||
WireSection.Draw(
|
||||
spriteBatch,
|
||||
start, start + (endPos - start) * 0.7f,
|
||||
item.Color, depth, 0.3f);
|
||||
}
|
||||
|
||||
|
||||
public static void UpdateEditing(List<Wire> wires)
|
||||
{
|
||||
//dragging a node of some wire
|
||||
|
||||
@@ -25,6 +25,9 @@ namespace Barotrauma.Items.Components
|
||||
private SoundChannel moveSoundChannel;
|
||||
|
||||
private Vector2 crosshairPos, crosshairPointerPos;
|
||||
|
||||
private Dictionary<string, Widget> widgets = new Dictionary<string, Widget>();
|
||||
private float prevAngle;
|
||||
|
||||
private bool flashLowPower;
|
||||
private bool flashNoAmmo;
|
||||
@@ -117,6 +120,25 @@ namespace Barotrauma.Items.Components
|
||||
barSize: 0.0f);
|
||||
}
|
||||
|
||||
private void InitializeRotationLimitWidget(Widget widget)
|
||||
{
|
||||
widget.Hovered += () =>
|
||||
{
|
||||
widget.secondaryColor = Color.Green;
|
||||
};
|
||||
widget.Selected += () =>
|
||||
{
|
||||
widget.color = Color.Green;
|
||||
};
|
||||
widget.MouseHeld += (deltaTime) =>
|
||||
{
|
||||
widget.DrawPos = PlayerInput.MousePosition;
|
||||
};
|
||||
widget.Deselected += () =>
|
||||
{
|
||||
widget.color = Color.Red;
|
||||
};
|
||||
}
|
||||
|
||||
partial void LaunchProjSpecific()
|
||||
{
|
||||
@@ -246,24 +268,153 @@ namespace Barotrauma.Items.Components
|
||||
item.SpriteColor,
|
||||
rotation + MathHelper.PiOver2, item.Scale,
|
||||
SpriteEffects.None, item.SpriteDepth + (barrelSprite.Depth - item.Sprite.Depth));
|
||||
|
||||
|
||||
if (!editing) return;
|
||||
|
||||
if (!editing) { return; }
|
||||
|
||||
float widgetRadius = 60.0f;
|
||||
|
||||
GUI.DrawLine(spriteBatch,
|
||||
drawPos,
|
||||
drawPos + new Vector2((float)Math.Cos(minRotation), (float)Math.Sin(minRotation)) * 60.0f,
|
||||
drawPos + new Vector2((float)Math.Cos(minRotation), (float)Math.Sin(minRotation)) * widgetRadius,
|
||||
Color.Green);
|
||||
|
||||
GUI.DrawLine(spriteBatch,
|
||||
drawPos,
|
||||
drawPos + new Vector2((float)Math.Cos(maxRotation), (float)Math.Sin(maxRotation)) * 60.0f,
|
||||
drawPos + new Vector2((float)Math.Cos(maxRotation), (float)Math.Sin(maxRotation)) * widgetRadius,
|
||||
Color.Green);
|
||||
|
||||
GUI.DrawLine(spriteBatch,
|
||||
drawPos,
|
||||
drawPos + new Vector2((float)Math.Cos((maxRotation + minRotation) / 2), (float)Math.Sin((maxRotation + minRotation) / 2)) * 60.0f,
|
||||
drawPos + new Vector2((float)Math.Cos((maxRotation + minRotation) / 2), (float)Math.Sin((maxRotation + minRotation) / 2)) * widgetRadius,
|
||||
Color.LightGreen);
|
||||
|
||||
if (!item.IsSelected) { return; }
|
||||
|
||||
Widget minRotationWidget = GetWidget("minrotation", spriteBatch, size: 10, initMethod: (widget) =>
|
||||
{
|
||||
widget.MouseDown += () =>
|
||||
{
|
||||
widget.color = Color.Green;
|
||||
prevAngle = minRotation;
|
||||
};
|
||||
widget.Deselected += () =>
|
||||
{
|
||||
widget.color = Color.Yellow;
|
||||
item.CreateEditingHUD();
|
||||
};
|
||||
widget.MouseHeld += (deltaTime) =>
|
||||
{
|
||||
minRotation = GetRotationAngle(drawPos);
|
||||
if (minRotation > maxRotation)
|
||||
{
|
||||
float temp = minRotation;
|
||||
minRotation = maxRotation;
|
||||
maxRotation = temp;
|
||||
}
|
||||
MapEntity.DisableSelect = true;
|
||||
};
|
||||
widget.PreUpdate += (deltaTime) =>
|
||||
{
|
||||
widget.DrawPos = new Vector2(widget.DrawPos.X, -widget.DrawPos.Y);
|
||||
widget.DrawPos = Screen.Selected.Cam.WorldToScreen(widget.DrawPos);
|
||||
};
|
||||
widget.PostUpdate += (deltaTime) =>
|
||||
{
|
||||
widget.DrawPos = Screen.Selected.Cam.ScreenToWorld(widget.DrawPos);
|
||||
widget.DrawPos = new Vector2(widget.DrawPos.X, -widget.DrawPos.Y);
|
||||
};
|
||||
widget.PreDraw += (sprtBtch, deltaTime) =>
|
||||
{
|
||||
widget.tooltip = "Min: " + (int)MathHelper.ToDegrees(minRotation);
|
||||
widget.DrawPos = drawPos + new Vector2((float)Math.Cos(minRotation), (float)Math.Sin(minRotation)) * widgetRadius;
|
||||
widget.Update(deltaTime);
|
||||
};
|
||||
});
|
||||
|
||||
Widget maxRotationWidget = GetWidget("maxrotation", spriteBatch, size: 10, initMethod: (widget) =>
|
||||
{
|
||||
widget.MouseDown += () =>
|
||||
{
|
||||
widget.color = Color.Green;
|
||||
prevAngle = minRotation;
|
||||
};
|
||||
widget.Deselected += () =>
|
||||
{
|
||||
widget.color = Color.Yellow;
|
||||
item.CreateEditingHUD();
|
||||
};
|
||||
widget.MouseHeld += (deltaTime) =>
|
||||
{
|
||||
maxRotation = GetRotationAngle(drawPos);
|
||||
if (minRotation > maxRotation)
|
||||
{
|
||||
float temp = minRotation;
|
||||
minRotation = maxRotation;
|
||||
maxRotation = temp;
|
||||
}
|
||||
MapEntity.DisableSelect = true;
|
||||
};
|
||||
widget.PreUpdate += (deltaTime) =>
|
||||
{
|
||||
widget.DrawPos = new Vector2(widget.DrawPos.X, -widget.DrawPos.Y);
|
||||
widget.DrawPos = Screen.Selected.Cam.WorldToScreen(widget.DrawPos);
|
||||
};
|
||||
widget.PostUpdate += (deltaTime) =>
|
||||
{
|
||||
widget.DrawPos = Screen.Selected.Cam.ScreenToWorld(widget.DrawPos);
|
||||
widget.DrawPos = new Vector2(widget.DrawPos.X, -widget.DrawPos.Y);
|
||||
};
|
||||
widget.PreDraw += (sprtBtch, deltaTime) =>
|
||||
{
|
||||
widget.tooltip = "Max: " + (int)MathHelper.ToDegrees(maxRotation);
|
||||
widget.DrawPos = drawPos + new Vector2((float)Math.Cos(maxRotation), (float)Math.Sin(maxRotation)) * widgetRadius;
|
||||
widget.Update(deltaTime);
|
||||
};
|
||||
});
|
||||
minRotationWidget.Draw(spriteBatch, (float)Timing.Step);
|
||||
maxRotationWidget.Draw(spriteBatch, (float)Timing.Step);
|
||||
}
|
||||
|
||||
private Widget GetWidget(string id, SpriteBatch spriteBatch, int size = 5, Action<Widget> initMethod = null)
|
||||
{
|
||||
if (!widgets.TryGetValue(id, out Widget widget))
|
||||
{
|
||||
widget = new Widget(id, size, Widget.Shape.Rectangle)
|
||||
{
|
||||
color = Color.Yellow,
|
||||
tooltipOffset = new Vector2(size / 2 + 5, -10),
|
||||
inputAreaMargin = 20,
|
||||
RequireMouseOn = false
|
||||
};
|
||||
widgets.Add(id, widget);
|
||||
initMethod?.Invoke(widget);
|
||||
}
|
||||
return widget;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns correct angle between -2PI and +2PI
|
||||
/// </summary>
|
||||
/// <param name="drawPosition"></param>
|
||||
/// <returns></returns>
|
||||
private float GetRotationAngle(Vector2 drawPosition)
|
||||
{
|
||||
Vector2 mouseVector = Screen.Selected.Cam.ScreenToWorld(PlayerInput.MousePosition);
|
||||
mouseVector.Y = -mouseVector.Y;
|
||||
Vector2 rotationVector = mouseVector - drawPosition;
|
||||
rotationVector.Normalize();
|
||||
double angle = Math.Atan2(MathHelper.ToRadians(rotationVector.Y), MathHelper.ToRadians(rotationVector.X));
|
||||
if (angle < 0)
|
||||
{// calculates which coterminal angle is closer to previous angle
|
||||
angle = Math.Abs(angle - prevAngle) < Math.Abs((angle + Math.PI * 2) - prevAngle) ? angle : angle + Math.PI * 2;
|
||||
}
|
||||
else if (angle > 0)
|
||||
{
|
||||
angle = Math.Abs(angle - prevAngle) < Math.Abs((angle - Math.PI * 2) - prevAngle) ? angle : angle - Math.PI * 2;
|
||||
}
|
||||
angle = MathHelper.Clamp((float)angle, -((float)Math.PI * 2), (float)Math.PI * 2);
|
||||
prevAngle = (float)angle;
|
||||
return (float)angle;
|
||||
}
|
||||
|
||||
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
|
||||
|
||||
@@ -329,6 +329,10 @@ namespace Barotrauma
|
||||
item.AiTarget?.Draw(spriteBatch);
|
||||
}
|
||||
}
|
||||
if (body != null)
|
||||
{
|
||||
body.DebugDraw(spriteBatch, Color.White);
|
||||
}
|
||||
}
|
||||
|
||||
if (!editing || (body != null && !body.Enabled))
|
||||
@@ -880,7 +884,6 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case NetEntityEvent.Type.InventoryState:
|
||||
{
|
||||
int containerIndex = msg.ReadRangedInteger(0, components.Count - 1);
|
||||
@@ -969,6 +972,10 @@ namespace Barotrauma
|
||||
case NetEntityEvent.Type.ChangeProperty:
|
||||
WritePropertyChange(msg, extraData, true);
|
||||
break;
|
||||
case NetEntityEvent.Type.Combine:
|
||||
UInt16 combineTargetID = (UInt16)extraData[1];
|
||||
msg.Write(combineTargetID);
|
||||
break;
|
||||
}
|
||||
msg.WritePadBits();
|
||||
}
|
||||
|
||||
@@ -90,6 +90,15 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
private Vector2 ClampParticlePos(Vector2 particlePos, Hull hull)
|
||||
{
|
||||
if (hull == null) return particlePos;
|
||||
|
||||
return new Vector2(
|
||||
MathHelper.Clamp(particlePos.X, hull.WorldRect.X, hull.WorldRect.Right),
|
||||
MathHelper.Clamp(particlePos.Y, hull.WorldRect.Y - hull.WorldRect.Height, hull.WorldRect.Y));
|
||||
}
|
||||
|
||||
private IEnumerable<object> DimLight(LightSource light)
|
||||
{
|
||||
float currBrightness = 1.0f;
|
||||
|
||||
@@ -260,20 +260,19 @@ namespace Barotrauma.Lights
|
||||
(int)(GameMain.GraphicsWidth * currLightMapScale), (int)(GameMain.GraphicsHeight * currLightMapScale)), Color.Black);
|
||||
spriteBatch.End();
|
||||
}
|
||||
else
|
||||
|
||||
visibleHulls = GetVisibleHulls(cam);
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Opaque, transformMatrix: spriteBatchTransform);
|
||||
foreach (Rectangle drawRect in visibleHulls.Values)
|
||||
{
|
||||
visibleHulls = GetVisibleHulls(cam);
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Opaque, transformMatrix: spriteBatchTransform);
|
||||
foreach (Rectangle drawRect in visibleHulls.Values)
|
||||
{
|
||||
//TODO: draw some sort of smoothed rectangle
|
||||
GUI.DrawRectangle(spriteBatch,
|
||||
new Vector2(drawRect.X, -drawRect.Y),
|
||||
new Vector2(drawRect.Width, drawRect.Height),
|
||||
Color.Black, true);
|
||||
}
|
||||
spriteBatch.End();
|
||||
}
|
||||
//TODO: draw some sort of smoothed rectangle
|
||||
GUI.DrawRectangle(spriteBatch,
|
||||
new Vector2(drawRect.X, -drawRect.Y),
|
||||
new Vector2(drawRect.Width, drawRect.Height),
|
||||
Color.Black, true);
|
||||
}
|
||||
spriteBatch.End();
|
||||
|
||||
|
||||
graphics.BlendState = BlendState.Additive;
|
||||
}
|
||||
|
||||
@@ -382,8 +382,28 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
selectedList.Clear();
|
||||
newSelection.ForEach(e => AddSelection(e));
|
||||
selectedList = newSelection;
|
||||
//selectedList.Clear();
|
||||
//newSelection.ForEach(e => AddSelection(e));
|
||||
foreach (var entity in newSelection)
|
||||
{
|
||||
HandleDoorGapLinks(entity,
|
||||
onGapFound: (door, gap) =>
|
||||
{
|
||||
door.RefreshLinkedGap();
|
||||
if (!selectedList.Contains(gap))
|
||||
{
|
||||
selectedList.Add(gap);
|
||||
}
|
||||
},
|
||||
onDoorFound: (door, gap) =>
|
||||
{
|
||||
if (!selectedList.Contains(door.Item))
|
||||
{
|
||||
selectedList.Add(door.Item);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
//select wire if both items it's connected to are selected
|
||||
|
||||
@@ -12,11 +12,6 @@ using System.Collections.Generic;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
partial class WallSection
|
||||
{
|
||||
public ConvexHull hull;
|
||||
}
|
||||
|
||||
partial class Structure : MapEntity, IDamageable, IServerSerializable
|
||||
{
|
||||
public static bool ShowWalls = true, ShowStructures = true;
|
||||
|
||||
@@ -204,8 +204,7 @@ namespace Barotrauma.Networking
|
||||
ulong fileSize = inc.ReadUInt64();
|
||||
string fileName = inc.ReadString();
|
||||
|
||||
string errorMsg;
|
||||
if (!ValidateInitialData(fileType, fileName, fileSize, out errorMsg))
|
||||
if (!ValidateInitialData(fileType, fileName, fileSize, out string errorMsg))
|
||||
{
|
||||
GameMain.Client.CancelFileTransfer(inc.SequenceChannel);
|
||||
DebugConsole.ThrowError("File transfer failed (" + errorMsg + ")");
|
||||
|
||||
@@ -32,6 +32,8 @@ namespace Barotrauma.Networking
|
||||
|
||||
protected GUITickBox cameraFollowsSub;
|
||||
|
||||
public RoundEndCinematic EndCinematic;
|
||||
|
||||
private ClientPermissions permissions = ClientPermissions.None;
|
||||
private List<string> permittedConsoleCommands = new List<string>();
|
||||
|
||||
@@ -209,7 +211,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
otherClients = new List<Client>();
|
||||
|
||||
serverSettings = new ServerSettings("Server", 0, 0, 0, false, false);
|
||||
serverSettings = new ServerSettings(this, "Server", 0, 0, 0, false, false);
|
||||
|
||||
ConnectToServer(ip, serverName);
|
||||
|
||||
@@ -800,7 +802,7 @@ namespace Barotrauma.Networking
|
||||
GameMain.GameSession.WinningTeam = winningTeam;
|
||||
GameMain.GameSession.Mission.Completed = true;
|
||||
}
|
||||
CoroutineManager.StartCoroutine(EndGame(endMessage));
|
||||
CoroutineManager.StartCoroutine(EndGame(endMessage), "EndGame");
|
||||
break;
|
||||
case ServerPacketHeader.CAMPAIGN_SETUP_INFO:
|
||||
UInt16 saveCount = inc.ReadUInt16();
|
||||
@@ -1059,6 +1061,12 @@ namespace Barotrauma.Networking
|
||||
if (Character != null) Character.Remove();
|
||||
HasSpawned = false;
|
||||
|
||||
while (CoroutineManager.IsCoroutineRunning("EndGame"))
|
||||
{
|
||||
if (EndCinematic != null) { EndCinematic.Stop(); }
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
GameMain.LightManager.LightingEnabled = true;
|
||||
|
||||
//enable spectate button in case we fail to start the round now
|
||||
@@ -1192,6 +1200,15 @@ namespace Barotrauma.Networking
|
||||
|
||||
if (GameMain.GameSession != null) { GameMain.GameSession.GameMode.End(endMessage); }
|
||||
|
||||
// Enable characters near the main sub for the endCinematic
|
||||
foreach (Character c in Character.CharacterList)
|
||||
{
|
||||
if (Vector2.DistanceSquared(Submarine.MainSub.WorldPosition, c.WorldPosition) < NetConfig.EnableCharacterDistSqr)
|
||||
{
|
||||
c.Enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
ServerSettings.ServerDetailsChanged = true;
|
||||
|
||||
gameStarted = false;
|
||||
@@ -1199,17 +1216,15 @@ namespace Barotrauma.Networking
|
||||
GameMain.GameScreen.Cam.TargetPos = Vector2.Zero;
|
||||
GameMain.LightManager.LosEnabled = false;
|
||||
respawnManager = null;
|
||||
|
||||
float endPreviewLength = 10.0f;
|
||||
|
||||
if (Screen.Selected == GameMain.GameScreen)
|
||||
{
|
||||
new RoundEndCinematic(Submarine.MainSub, GameMain.GameScreen.Cam, endPreviewLength);
|
||||
float secondsLeft = endPreviewLength;
|
||||
do
|
||||
EndCinematic = new RoundEndCinematic(Submarine.MainSub, GameMain.GameScreen.Cam);
|
||||
while (EndCinematic.Running && Screen.Selected == GameMain.GameScreen)
|
||||
{
|
||||
secondsLeft -= CoroutineManager.UnscaledDeltaTime;
|
||||
yield return CoroutineStatus.Running;
|
||||
} while (secondsLeft > 0.0f && Screen.Selected == GameMain.GameScreen);
|
||||
}
|
||||
EndCinematic = null;
|
||||
}
|
||||
|
||||
Submarine.Unload();
|
||||
@@ -1628,6 +1643,7 @@ namespace Barotrauma.Networking
|
||||
outmsg.Write(LastClientListUpdateID);
|
||||
|
||||
Character.Controlled?.ClientWrite(outmsg);
|
||||
GameMain.GameScreen.Cam?.ClientWrite(outmsg);
|
||||
|
||||
entityEventManager.Write(outmsg, client.ServerConnection);
|
||||
|
||||
@@ -1829,9 +1845,10 @@ namespace Barotrauma.Networking
|
||||
steamAuthTicket?.Cancel();
|
||||
steamAuthTicket = null;
|
||||
|
||||
foreach (var fileTransfer in FileReceiver.ActiveTransfers)
|
||||
List<FileReceiver.FileTransferIn> activeTransfers = new List<FileReceiver.FileTransferIn>(FileReceiver.ActiveTransfers);
|
||||
foreach (var fileTransfer in activeTransfers)
|
||||
{
|
||||
fileTransfer.Dispose();
|
||||
FileReceiver.StopTransfer(fileTransfer, deleteFile: true);
|
||||
}
|
||||
|
||||
if (HasPermission(ClientPermissions.ServerLog))
|
||||
@@ -1842,7 +1859,8 @@ namespace Barotrauma.Networking
|
||||
if (GameMain.ServerChildProcess != null)
|
||||
{
|
||||
int checks = 0;
|
||||
while (!GameMain.ServerChildProcess.HasExited) {
|
||||
while (!GameMain.ServerChildProcess.HasExited)
|
||||
{
|
||||
if (checks > 10)
|
||||
{
|
||||
GameMain.ServerChildProcess.Kill();
|
||||
@@ -2329,24 +2347,34 @@ namespace Barotrauma.Networking
|
||||
|
||||
if (respawnManager != null)
|
||||
{
|
||||
string respawnInfo = "";
|
||||
string respawnText = "";
|
||||
float textScale = 1.0f;
|
||||
Color textColor = Color.White;
|
||||
if (respawnManager.CurrentState == RespawnManager.State.Waiting &&
|
||||
respawnManager.CountdownStarted)
|
||||
respawnManager.RespawnCountdownStarted)
|
||||
{
|
||||
respawnInfo = TextManager.GetWithVariable(respawnManager.UsingShuttle ? "RespawnShuttleDispatching" : "RespawningIn", "[time]", ToolBox.SecondsToReadableTime(respawnManager.RespawnTimer));
|
||||
float timeLeft = (float)(respawnManager.RespawnTime - DateTime.Now).TotalSeconds;
|
||||
respawnText = TextManager.GetWithVariable(respawnManager.UsingShuttle ? "RespawnShuttleDispatching" : "RespawningIn", "[time]", ToolBox.SecondsToReadableTime(timeLeft));
|
||||
}
|
||||
else if (respawnManager.CurrentState == RespawnManager.State.Transporting)
|
||||
else if (respawnManager.CurrentState == RespawnManager.State.Transporting &&
|
||||
respawnManager.ReturnCountdownStarted)
|
||||
{
|
||||
respawnInfo = respawnManager.TransportTimer <= 0.0f ?
|
||||
float timeLeft = (float)(respawnManager.ReturnTime - DateTime.Now).TotalSeconds;
|
||||
respawnText = timeLeft <= 0.0f ?
|
||||
"" :
|
||||
TextManager.GetWithVariable("RespawnShuttleLeavingIn", "[time]", ToolBox.SecondsToReadableTime(respawnManager.TransportTimer));
|
||||
TextManager.GetWithVariable("RespawnShuttleLeavingIn", "[time]", ToolBox.SecondsToReadableTime(timeLeft));
|
||||
if (timeLeft < 20.0f)
|
||||
{
|
||||
//oscillate between 0-1
|
||||
float phase = (float)(Math.Sin(timeLeft * MathHelper.Pi) + 1.0f) * 0.5f;
|
||||
textScale = 1.0f + phase * 0.5f;
|
||||
textColor = Color.Lerp(Color.Red, Color.White, 1.0f - phase);
|
||||
}
|
||||
}
|
||||
|
||||
if (respawnManager != null)
|
||||
|
||||
if (!string.IsNullOrEmpty(respawnText))
|
||||
{
|
||||
GUI.DrawString(spriteBatch,
|
||||
new Vector2(120.0f, 10),
|
||||
respawnInfo, Color.White, null, 0, GUI.SmallFont);
|
||||
GUI.SmallFont.DrawString(spriteBatch, respawnText, new Vector2(120.0f, 10), textColor, 0.0f, Vector2.Zero, textScale, Microsoft.Xna.Framework.Graphics.SpriteEffects.None, 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
partial class KarmaManager : ISerializableEntity
|
||||
{
|
||||
public void CreateSettingsFrame(GUIComponent parent)
|
||||
{
|
||||
CreateLabeledSlider(parent, 0.0f, 40.0f, 1.0f, "KickBanThreshold");
|
||||
CreateLabeledSlider(parent, 0.0f, 50.0f, 1.0f, "HerpesThreshold");
|
||||
|
||||
CreateLabeledSlider(parent, 0.0f, 0.5f, 0.01f, "KarmaDecay");
|
||||
CreateLabeledSlider(parent, 50.0f, 100.0f, 1.0f, "KarmaDecayThreshold");
|
||||
CreateLabeledSlider(parent, 0.0f, 0.5f, 0.01f, "KarmaIncrease");
|
||||
CreateLabeledSlider(parent, 0.0f, 50.0f, 1.0f, "KarmaIncreaseThreshold");
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.12f), parent.RectTransform), TextManager.Get("Karma.PositiveActions"), textAlignment: Alignment.Center)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
|
||||
CreateLabeledSlider(parent, 0.0f, 1.0f, 0.01f, "StructureRepairKarmaIncrease");
|
||||
CreateLabeledSlider(parent, 0.0f, 1.0f, 0.01f, "HealFriendlyKarmaIncrease");
|
||||
CreateLabeledSlider(parent, 0.0f, 1.0f, 0.01f, "DamageEnemyKarmaIncrease");
|
||||
CreateLabeledSlider(parent, 0.0f, 1.0f, 0.01f, "ItemRepairKarmaIncrease");
|
||||
CreateLabeledSlider(parent, 0.0f, 10.0f, 0.05f, "ExtinguishFireKarmaIncrease");
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.12f), parent.RectTransform), TextManager.Get("Karma.NegativeActions"), textAlignment: Alignment.Center)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
|
||||
CreateLabeledSlider(parent, 0.0f, 1.0f, 0.01f, "StructureDamageKarmaDecrease");
|
||||
CreateLabeledSlider(parent, 0.0f, 1.0f, 0.01f, "DamageFriendlyKarmaDecrease");
|
||||
CreateLabeledSlider(parent, 0.0f, 100.0f, 1.0f, "ReactorMeltdownKarmaDecrease");
|
||||
CreateLabeledSlider(parent, 0.0f, 10.0f, 0.05f, "ReactorOverheatKarmaDecrease");
|
||||
CreateLabeledSlider(parent, 0.0f, 20.0f, 1f, "AllowedWireDisconnectionsPerMinute");
|
||||
CreateLabeledSlider(parent, 0.0f, 20.0f, 0.5f, "WireDisconnectionKarmaDecrease");
|
||||
CreateLabeledSlider(parent, 0.0f, 30.0f, 1.0f, "SpamFilterKarmaDecrease");
|
||||
}
|
||||
|
||||
private void CreateLabeledSlider(GUIComponent parent, float min, float max, float step, string propertyName)
|
||||
{
|
||||
var container = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.1f), parent.RectTransform), isHorizontal: true)
|
||||
{
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.05f,
|
||||
ToolTip = TextManager.Get("Karma." + propertyName + "ToolTip")
|
||||
};
|
||||
|
||||
string labelText = TextManager.Get("Karma." + propertyName);
|
||||
var label = new GUITextBlock(new RectTransform(new Vector2(0.7f, 0.8f), container.RectTransform),
|
||||
labelText, font: GUI.SmallFont)
|
||||
{
|
||||
ToolTip = TextManager.Get("Karma." + propertyName + "ToolTip")
|
||||
};
|
||||
|
||||
var slider = new GUIScrollBar(new RectTransform(new Vector2(0.3f, 0.8f), container.RectTransform), barSize: 0.1f)
|
||||
{
|
||||
Step = step <= 0.0f ? 0.0f : step / (max - min),
|
||||
Range = new Vector2(min, max),
|
||||
OnMoved = (GUIScrollBar scrollBar, float barScroll) =>
|
||||
{
|
||||
string formattedValueStr = step >= 1.0f ?
|
||||
((int)scrollBar.BarScrollValue).ToString() :
|
||||
scrollBar.BarScrollValue.Format(decimalCount: step <= 0.1f ? 2 : 1);
|
||||
label.Text = TextManager.AddPunctuation(':', labelText, formattedValueStr);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
GameMain.NetworkMember.ServerSettings.AssignGUIComponent(propertyName, slider);
|
||||
slider.OnMoved(slider, slider.BarScroll);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,25 +1,59 @@
|
||||
using System;
|
||||
using Lidgren.Network;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
|
||||
namespace Barotrauma.Networking
|
||||
{
|
||||
partial class RespawnManager
|
||||
{
|
||||
partial void UpdateWaiting(float deltaTime)
|
||||
{
|
||||
if (CountdownStarted)
|
||||
{
|
||||
respawnTimer = Math.Max(0.0f, respawnTimer - deltaTime);
|
||||
}
|
||||
}
|
||||
private DateTime lastShuttleLeavingWarningTime;
|
||||
|
||||
partial void UpdateTransportingProjSpecific(float deltaTime)
|
||||
{
|
||||
if (shuttleTransportTimer + deltaTime > 15.0f && shuttleTransportTimer <= 15.0f &&
|
||||
GameMain.Client?.Character != null &&
|
||||
GameMain.Client.Character.Submarine == respawnShuttle)
|
||||
if (GameMain.Client?.Character == null || GameMain.Client.Character.Submarine != RespawnShuttle) { return; }
|
||||
if (!ReturnCountdownStarted) { return; }
|
||||
|
||||
//show a warning when there's 20 seconds until the shuttle leaves
|
||||
if ((ReturnTime - DateTime.Now).TotalSeconds < 20.0f &&
|
||||
(DateTime.Now - lastShuttleLeavingWarningTime).TotalSeconds > 30.0f)
|
||||
{
|
||||
lastShuttleLeavingWarningTime = DateTime.Now;
|
||||
GameMain.Client.AddChatMessage("ServerMessage.ShuttleLeaving", ChatMessageType.Server);
|
||||
}
|
||||
}
|
||||
|
||||
public void ClientRead(ServerNetObject type, NetBuffer msg, float sendingTime)
|
||||
{
|
||||
var newState = (State)msg.ReadRangedInteger(0, Enum.GetNames(typeof(State)).Length);
|
||||
|
||||
switch (newState)
|
||||
{
|
||||
case State.Transporting:
|
||||
ReturnCountdownStarted = msg.ReadBoolean();
|
||||
maxTransportTime = msg.ReadSingle();
|
||||
float transportTimeLeft = msg.ReadSingle();
|
||||
|
||||
ReturnTime = DateTime.Now + new TimeSpan(0, 0, 0, 0, milliseconds: (int)(transportTimeLeft * 1000.0f));
|
||||
RespawnCountdownStarted = false;
|
||||
if (CurrentState != newState)
|
||||
{
|
||||
CoroutineManager.StopCoroutines("forcepos");
|
||||
//CoroutineManager.StartCoroutine(ForceShuttleToPos(Level.Loaded.StartPosition - Vector2.UnitY * Level.ShaftHeight, 100.0f), "forcepos");
|
||||
}
|
||||
break;
|
||||
case State.Waiting:
|
||||
RespawnCountdownStarted = msg.ReadBoolean();
|
||||
ResetShuttle();
|
||||
float newRespawnTime = msg.ReadSingle();
|
||||
RespawnTime = DateTime.Now + new TimeSpan(0, 0, 0, 0, milliseconds: (int)(newRespawnTime * 1000.0f));
|
||||
break;
|
||||
case State.Returning:
|
||||
RespawnCountdownStarted = false;
|
||||
break;
|
||||
}
|
||||
CurrentState = newState;
|
||||
|
||||
msg.ReadPadBits();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +51,22 @@ namespace Barotrauma.Networking
|
||||
|
||||
public bool ContentPackagesMatch(IEnumerable<ContentPackage> myContentPackages)
|
||||
{
|
||||
return ContentPackagesMatch(myContentPackages.Select(cp => cp.MD5hash.Hash));
|
||||
//make sure we have all the packages the server requires
|
||||
foreach (string hash in ContentPackageHashes)
|
||||
{
|
||||
if (!myContentPackages.Any(myPackage => myPackage.MD5hash.Hash == hash)) { return false; }
|
||||
}
|
||||
|
||||
//make sure the server isn't missing any of our packages that cause multiplayer incompatibility
|
||||
foreach (ContentPackage myPackage in myContentPackages)
|
||||
{
|
||||
if (myPackage.HasMultiplayerIncompatibleContent)
|
||||
{
|
||||
if (!ContentPackageHashes.Any(hash => hash == myPackage.MD5hash.Hash)) { return false; }
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool ContentPackagesMatch(IEnumerable<string> myContentPackageHashes)
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace Barotrauma.Networking
|
||||
public void AssignGUIComponent(GUIComponent component)
|
||||
{
|
||||
GUIComponent = component;
|
||||
GUIComponentValue = property.GetValue(serverSettings);
|
||||
GUIComponentValue = property.GetValue(parentObject);
|
||||
TempValue = GUIComponentValue;
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ namespace Barotrauma.Networking
|
||||
else if (GUIComponent is GUITextBox textBox) return textBox.Text;
|
||||
else if (GUIComponent is GUIScrollBar scrollBar) return scrollBar.BarScrollValue;
|
||||
else if (GUIComponent is GUIRadioButtonGroup radioButtonGroup) return radioButtonGroup.Selected;
|
||||
else if (GUIComponent is GUIDropDown dropdown) return dropdown.SelectedData;
|
||||
return null;
|
||||
}
|
||||
set
|
||||
@@ -39,6 +40,7 @@ namespace Barotrauma.Networking
|
||||
else if (GUIComponent is GUITextBox textBox) textBox.Text = (string)value;
|
||||
else if (GUIComponent is GUIScrollBar scrollBar) scrollBar.BarScrollValue = (float)value;
|
||||
else if (GUIComponent is GUIRadioButtonGroup radioButtonGroup) radioButtonGroup.Selected = (Enum)value;
|
||||
else if (GUIComponent is GUIDropDown dropdown) dropdown.SelectItem(value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,31 +52,6 @@ namespace Barotrauma.Networking
|
||||
return !PropEquals(TempValue, GUIComponentValue);
|
||||
}
|
||||
}
|
||||
|
||||
public bool PropEquals(object a,object b)
|
||||
{
|
||||
switch (typeString)
|
||||
{
|
||||
case "float":
|
||||
if (!(a is float?)) return false;
|
||||
if (!(b is float?)) return false;
|
||||
return (float)a == (float)b;
|
||||
case "int":
|
||||
if (!(a is int?)) return false;
|
||||
if (!(b is int?)) return false;
|
||||
return (int)a == (int)b;
|
||||
case "bool":
|
||||
if (!(a is bool?)) return false;
|
||||
if (!(b is bool?)) return false;
|
||||
return (bool)a == (bool)b;
|
||||
case "Enum":
|
||||
if (!(a is Enum)) return false;
|
||||
if (!(b is Enum)) return false;
|
||||
return ((Enum)a).Equals((Enum)b);
|
||||
default:
|
||||
return a.ToString().Equals(b.ToString(),StringComparison.InvariantCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
private Dictionary<string, bool> tempMonsterEnabled;
|
||||
|
||||
@@ -222,11 +199,15 @@ namespace Barotrauma.Networking
|
||||
private GUIFrame[] settingsTabs;
|
||||
private GUIButton[] tabButtons;
|
||||
private int settingsTabIndex;
|
||||
|
||||
private GUIDropDown karmaPresetDD;
|
||||
private GUIComponent karmaSettingsBlocker;
|
||||
|
||||
enum SettingsTab
|
||||
{
|
||||
General,
|
||||
Rounds,
|
||||
Server,
|
||||
Antigriefing,
|
||||
Banlist,
|
||||
Whitelist
|
||||
}
|
||||
@@ -236,6 +217,11 @@ namespace Barotrauma.Networking
|
||||
return netProperties.First(p => p.Value.Name == name).Value;
|
||||
}
|
||||
|
||||
public void AssignGUIComponent(string propertyName, GUIComponent component)
|
||||
{
|
||||
GetPropertyData(propertyName).AssignGUIComponent(component);
|
||||
}
|
||||
|
||||
public void AddToGUIUpdateList()
|
||||
{
|
||||
if (GUI.DisableHUD) return;
|
||||
@@ -264,7 +250,7 @@ namespace Barotrauma.Networking
|
||||
};
|
||||
|
||||
//center frames
|
||||
GUIFrame innerFrame = new GUIFrame(new RectTransform(new Vector2(0.3f, 0.7f), settingsFrame.RectTransform, Anchor.Center) { MinSize = new Point(400, 430) });
|
||||
GUIFrame innerFrame = new GUIFrame(new RectTransform(new Vector2(0.4f, 0.75f), settingsFrame.RectTransform, Anchor.Center) { MinSize = new Point(400, 430) });
|
||||
GUIFrame paddedFrame = new GUIFrame(new RectTransform(new Vector2(0.9f, 0.9f), innerFrame.RectTransform, Anchor.Center), style: null);
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), paddedFrame.RectTransform), TextManager.Get("Settings"), font: GUI.LargeFont);
|
||||
@@ -304,18 +290,21 @@ namespace Barotrauma.Networking
|
||||
OnClicked = ToggleSettingsFrame
|
||||
};
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
// game settings
|
||||
// server settings
|
||||
//--------------------------------------------------------------------------------
|
||||
|
||||
var roundsTab = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.95f), settingsTabs[(int)SettingsTab.Rounds].RectTransform, Anchor.Center))
|
||||
var serverTab = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.95f), settingsTabs[(int)SettingsTab.General].RectTransform, Anchor.Center))
|
||||
{
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.02f
|
||||
};
|
||||
|
||||
//***********************************************
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), roundsTab.RectTransform), TextManager.Get("ServerSettingsSubSelection"));
|
||||
var selectionFrame = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), roundsTab.RectTransform), isHorizontal: true)
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), serverTab.RectTransform), TextManager.Get("ServerSettingsSubSelection"));
|
||||
var selectionFrame = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), serverTab.RectTransform), isHorizontal: true)
|
||||
{
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.05f
|
||||
@@ -327,11 +316,11 @@ namespace Barotrauma.Networking
|
||||
var selectionTick = new GUITickBox(new RectTransform(new Vector2(0.3f, 1.0f), selectionFrame.RectTransform), TextManager.Get(((SelectionMode)i).ToString()), font: GUI.SmallFont);
|
||||
selectionMode.AddRadioButton((SelectionMode)i, selectionTick);
|
||||
}
|
||||
DebugConsole.NewMessage(SubSelectionMode.ToString(),Color.White);
|
||||
DebugConsole.NewMessage(SubSelectionMode.ToString(), Color.White);
|
||||
GetPropertyData("SubSelectionMode").AssignGUIComponent(selectionMode);
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), roundsTab.RectTransform), TextManager.Get("ServerSettingsModeSelection"));
|
||||
selectionFrame = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), roundsTab.RectTransform), isHorizontal: true)
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), serverTab.RectTransform), TextManager.Get("ServerSettingsModeSelection"));
|
||||
selectionFrame = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), serverTab.RectTransform), isHorizontal: true)
|
||||
{
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.05f
|
||||
@@ -345,6 +334,84 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
GetPropertyData("ModeSelectionMode").AssignGUIComponent(selectionMode);
|
||||
|
||||
|
||||
//***********************************************
|
||||
|
||||
var voiceChatEnabled = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), serverTab.RectTransform),
|
||||
TextManager.Get("ServerSettingsVoiceChatEnabled"));
|
||||
GetPropertyData("VoiceChatEnabled").AssignGUIComponent(voiceChatEnabled);
|
||||
|
||||
//***********************************************
|
||||
|
||||
string autoRestartDelayLabel = TextManager.Get("ServerSettingsAutoRestartDelay") + " ";
|
||||
var startIntervalText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), serverTab.RectTransform), autoRestartDelayLabel);
|
||||
var startIntervalSlider = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.05f), serverTab.RectTransform), barSize: 0.1f)
|
||||
{
|
||||
UserData = startIntervalText,
|
||||
Step = 0.05f,
|
||||
OnMoved = (GUIScrollBar scrollBar, float barScroll) =>
|
||||
{
|
||||
GUITextBlock text = scrollBar.UserData as GUITextBlock;
|
||||
text.Text = autoRestartDelayLabel + ToolBox.SecondsToReadableTime(scrollBar.BarScrollValue);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
startIntervalSlider.Range = new Vector2(10.0f, 300.0f);
|
||||
GetPropertyData("AutoRestartInterval").AssignGUIComponent(startIntervalSlider);
|
||||
startIntervalSlider.OnMoved(startIntervalSlider, startIntervalSlider.BarScroll);
|
||||
|
||||
//***********************************************
|
||||
|
||||
var startWhenClientsReady = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), serverTab.RectTransform),
|
||||
TextManager.Get("ServerSettingsStartWhenClientsReady"));
|
||||
GetPropertyData("StartWhenClientsReady").AssignGUIComponent(startWhenClientsReady);
|
||||
|
||||
CreateLabeledSlider(serverTab, "ServerSettingsStartWhenClientsReadyRatio", out GUIScrollBar slider, out GUITextBlock sliderLabel);
|
||||
string clientsReadyRequiredLabel = sliderLabel.Text;
|
||||
slider.Step = 0.2f;
|
||||
slider.Range = new Vector2(0.5f, 1.0f);
|
||||
slider.OnMoved = (GUIScrollBar scrollBar, float barScroll) =>
|
||||
{
|
||||
((GUITextBlock)scrollBar.UserData).Text = clientsReadyRequiredLabel.Replace("[percentage]", ((int)MathUtils.Round(scrollBar.BarScrollValue * 100.0f, 10.0f)).ToString());
|
||||
return true;
|
||||
};
|
||||
GetPropertyData("StartWhenClientsReadyRatio").AssignGUIComponent(slider);
|
||||
slider.OnMoved(slider, slider.BarScroll);
|
||||
|
||||
//***********************************************
|
||||
|
||||
var allowSpecBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), serverTab.RectTransform), TextManager.Get("ServerSettingsAllowSpectating"));
|
||||
GetPropertyData("AllowSpectating").AssignGUIComponent(allowSpecBox);
|
||||
|
||||
|
||||
var shareSubsBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), serverTab.RectTransform), TextManager.Get("ServerSettingsShareSubFiles"));
|
||||
GetPropertyData("AllowFileTransfers").AssignGUIComponent(shareSubsBox);
|
||||
|
||||
var randomizeLevelBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), serverTab.RectTransform), TextManager.Get("ServerSettingsRandomizeSeed"));
|
||||
GetPropertyData("RandomizeSeed").AssignGUIComponent(randomizeLevelBox);
|
||||
|
||||
var saveLogsBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), serverTab.RectTransform), TextManager.Get("ServerSettingsSaveLogs"))
|
||||
{
|
||||
OnSelected = (GUITickBox) =>
|
||||
{
|
||||
//TODO: fix?
|
||||
//showLogButton.Visible = SaveServerLogs;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
GetPropertyData("SaveServerLogs").AssignGUIComponent(saveLogsBox);
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
// game settings
|
||||
//--------------------------------------------------------------------------------
|
||||
|
||||
var roundsTab = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.95f), settingsTabs[(int)SettingsTab.Rounds].RectTransform, Anchor.Center))
|
||||
{
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.02f
|
||||
};
|
||||
|
||||
|
||||
var endBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), roundsTab.RectTransform),
|
||||
TextManager.Get("ServerSettingsEndRoundWhenDestReached"));
|
||||
GetPropertyData("EndRoundAtLevelEnd").AssignGUIComponent(endBox);
|
||||
@@ -353,7 +420,7 @@ namespace Barotrauma.Networking
|
||||
TextManager.Get("ServerSettingsEndRoundVoting"));
|
||||
GetPropertyData("AllowEndVoting").AssignGUIComponent(endVoteBox);
|
||||
|
||||
CreateLabeledSlider(roundsTab, "ServerSettingsEndRoundVotesRequired", out GUIScrollBar slider, out GUITextBlock sliderLabel);
|
||||
CreateLabeledSlider(roundsTab, "ServerSettingsEndRoundVotesRequired", out slider, out sliderLabel);
|
||||
|
||||
string endRoundLabel = sliderLabel.Text;
|
||||
slider.Step = 0.2f;
|
||||
@@ -361,7 +428,7 @@ namespace Barotrauma.Networking
|
||||
GetPropertyData("EndVoteRequiredRatio").AssignGUIComponent(slider);
|
||||
slider.OnMoved = (GUIScrollBar scrollBar, float barScroll) =>
|
||||
{
|
||||
((GUITextBlock)scrollBar.UserData).Text = endRoundLabel + (int)MathUtils.Round(scrollBar.BarScrollValue * 100.0f, 10.0f) + " %";
|
||||
((GUITextBlock)scrollBar.UserData).Text = endRoundLabel + " " + (int)MathUtils.Round(scrollBar.BarScrollValue * 100.0f, 10.0f) + " %";
|
||||
return true;
|
||||
};
|
||||
slider.OnMoved(slider, slider.BarScroll);
|
||||
@@ -378,7 +445,7 @@ namespace Barotrauma.Networking
|
||||
slider.OnMoved = (GUIScrollBar scrollBar, float barScroll) =>
|
||||
{
|
||||
GUITextBlock text = scrollBar.UserData as GUITextBlock;
|
||||
text.Text = intervalLabel + ToolBox.SecondsToReadableTime(scrollBar.BarScrollValue);
|
||||
text.Text = intervalLabel + " " + ToolBox.SecondsToReadableTime(scrollBar.BarScrollValue);
|
||||
return true;
|
||||
};
|
||||
slider.OnMoved(slider, slider.BarScroll);
|
||||
@@ -437,6 +504,57 @@ namespace Barotrauma.Networking
|
||||
};
|
||||
slider.OnMoved(slider, slider.BarScroll);
|
||||
|
||||
|
||||
var ragdollButtonBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), roundsTab.RectTransform), TextManager.Get("ServerSettingsAllowRagdollButton"));
|
||||
GetPropertyData("AllowRagdollButton").AssignGUIComponent(ragdollButtonBox);
|
||||
|
||||
var traitorRatioBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), roundsTab.RectTransform), TextManager.Get("ServerSettingsUseTraitorRatio"));
|
||||
|
||||
CreateLabeledSlider(roundsTab, "", out slider, out sliderLabel);
|
||||
var traitorRatioSlider = slider;
|
||||
traitorRatioBox.OnSelected = (GUITickBox) =>
|
||||
{
|
||||
traitorRatioSlider.OnMoved(traitorRatioSlider, traitorRatioSlider.BarScroll);
|
||||
return true;
|
||||
};
|
||||
|
||||
if (TraitorUseRatio)
|
||||
{
|
||||
traitorRatioSlider.Range = new Vector2(0.1f, 1.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
traitorRatioSlider.Range = new Vector2(1.0f, maxPlayers);
|
||||
}
|
||||
|
||||
string traitorRatioLabel = TextManager.Get("ServerSettingsTraitorRatio") + " ";
|
||||
string traitorCountLabel = TextManager.Get("ServerSettingsTraitorCount") + " ";
|
||||
|
||||
traitorRatioSlider.Range = new Vector2(0.1f, 1.0f);
|
||||
traitorRatioSlider.OnMoved = (GUIScrollBar scrollBar, float barScroll) =>
|
||||
{
|
||||
GUITextBlock traitorText = scrollBar.UserData as GUITextBlock;
|
||||
if (traitorRatioBox.Selected)
|
||||
{
|
||||
scrollBar.Step = 0.01f;
|
||||
scrollBar.Range = new Vector2(0.1f, 1.0f);
|
||||
traitorText.Text = traitorRatioLabel + (int)MathUtils.Round(scrollBar.BarScrollValue * 100.0f, 1.0f) + " %";
|
||||
}
|
||||
else
|
||||
{
|
||||
scrollBar.Step = 1f / (maxPlayers - 1);
|
||||
scrollBar.Range = new Vector2(1.0f, maxPlayers);
|
||||
traitorText.Text = traitorCountLabel + scrollBar.BarScrollValue;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
GetPropertyData("TraitorUseRatio").AssignGUIComponent(traitorRatioBox);
|
||||
GetPropertyData("TraitorRatio").AssignGUIComponent(traitorRatioSlider);
|
||||
|
||||
traitorRatioSlider.OnMoved(traitorRatioSlider, traitorRatioSlider.BarScroll);
|
||||
traitorRatioBox.OnSelected(traitorRatioBox);
|
||||
|
||||
var buttonHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.07f), roundsTab.RectTransform), isHorizontal: true)
|
||||
{
|
||||
Stretch = true,
|
||||
@@ -558,68 +676,21 @@ namespace Barotrauma.Networking
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
// server settings
|
||||
// antigriefing
|
||||
//--------------------------------------------------------------------------------
|
||||
|
||||
var serverTab = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.95f), settingsTabs[(int)SettingsTab.Server].RectTransform, Anchor.Center))
|
||||
var antigriefingTab = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.95f), settingsTabs[(int)SettingsTab.Antigriefing].RectTransform, Anchor.Center))
|
||||
{
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.02f
|
||||
};
|
||||
|
||||
//***********************************************
|
||||
|
||||
var voiceChatEnabled = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), serverTab.RectTransform),
|
||||
TextManager.Get("ServerSettingsVoiceChatEnabled"));
|
||||
GetPropertyData("VoiceChatEnabled").AssignGUIComponent(voiceChatEnabled);
|
||||
|
||||
//***********************************************
|
||||
|
||||
string autoRestartDelayLabel = TextManager.Get("ServerSettingsAutoRestartDelay") + " ";
|
||||
var startIntervalText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), serverTab.RectTransform), autoRestartDelayLabel);
|
||||
var startIntervalSlider = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.05f), serverTab.RectTransform), barSize: 0.1f)
|
||||
{
|
||||
UserData = startIntervalText,
|
||||
Step = 0.05f,
|
||||
OnMoved = (GUIScrollBar scrollBar, float barScroll) =>
|
||||
{
|
||||
GUITextBlock text = scrollBar.UserData as GUITextBlock;
|
||||
text.Text = autoRestartDelayLabel + ToolBox.SecondsToReadableTime(scrollBar.BarScrollValue);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
startIntervalSlider.Range = new Vector2(10.0f, 300.0f);
|
||||
GetPropertyData("AutoRestartInterval").AssignGUIComponent(startIntervalSlider);
|
||||
startIntervalSlider.OnMoved(startIntervalSlider, startIntervalSlider.BarScroll);
|
||||
|
||||
//***********************************************
|
||||
|
||||
var startWhenClientsReady = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), serverTab.RectTransform),
|
||||
TextManager.Get("ServerSettingsStartWhenClientsReady"));
|
||||
GetPropertyData("StartWhenClientsReady").AssignGUIComponent(startWhenClientsReady);
|
||||
|
||||
CreateLabeledSlider(serverTab, "ServerSettingsStartWhenClientsReadyRatio", out slider, out sliderLabel);
|
||||
string clientsReadyRequiredLabel = sliderLabel.Text;
|
||||
slider.Step = 0.2f;
|
||||
slider.Range = new Vector2(0.5f, 1.0f);
|
||||
slider.OnMoved = (GUIScrollBar scrollBar, float barScroll) =>
|
||||
{
|
||||
((GUITextBlock)scrollBar.UserData).Text = clientsReadyRequiredLabel.Replace("[percentage]", ((int)MathUtils.Round(scrollBar.BarScrollValue * 100.0f, 10.0f)).ToString());
|
||||
return true;
|
||||
};
|
||||
GetPropertyData("StartWhenClientsReadyRatio").AssignGUIComponent(slider);
|
||||
slider.OnMoved(slider, slider.BarScroll);
|
||||
|
||||
//***********************************************
|
||||
|
||||
var allowSpecBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), serverTab.RectTransform), TextManager.Get("ServerSettingsAllowSpectating"));
|
||||
GetPropertyData("AllowSpectating").AssignGUIComponent(allowSpecBox);
|
||||
|
||||
var voteKickBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), serverTab.RectTransform), TextManager.Get("ServerSettingsAllowVoteKick"));
|
||||
var voteKickBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), antigriefingTab.RectTransform), TextManager.Get("ServerSettingsAllowVoteKick"));
|
||||
GetPropertyData("AllowVoteKick").AssignGUIComponent(voteKickBox);
|
||||
|
||||
CreateLabeledSlider(serverTab, "ServerSettingsKickVotesRequired", out slider, out sliderLabel);
|
||||
CreateLabeledSlider(antigriefingTab, "ServerSettingsKickVotesRequired", out slider, out sliderLabel);
|
||||
string votesRequiredLabel = sliderLabel.Text + " ";
|
||||
slider.Step = 0.2f;
|
||||
slider.Range = new Vector2(0.5f, 1.0f);
|
||||
@@ -631,9 +702,9 @@ namespace Barotrauma.Networking
|
||||
GetPropertyData("KickVoteRequiredRatio").AssignGUIComponent(slider);
|
||||
slider.OnMoved(slider, slider.BarScroll);
|
||||
|
||||
CreateLabeledSlider(serverTab, "ServerSettingsAutobanTime", out slider, out sliderLabel);
|
||||
CreateLabeledSlider(antigriefingTab, "ServerSettingsAutobanTime", out slider, out sliderLabel);
|
||||
string autobanLabel = sliderLabel.Text + " ";
|
||||
slider.Step = 0.05f;
|
||||
slider.Step = 0.01f;
|
||||
slider.Range = new Vector2(0.0f, MaxAutoBanTime);
|
||||
slider.OnMoved = (GUIScrollBar scrollBar, float barScroll) =>
|
||||
{
|
||||
@@ -643,91 +714,66 @@ namespace Barotrauma.Networking
|
||||
GetPropertyData("AutoBanTime").AssignGUIComponent(slider);
|
||||
slider.OnMoved(slider, slider.BarScroll);
|
||||
|
||||
var shareSubsBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), serverTab.RectTransform), TextManager.Get("ServerSettingsShareSubFiles"));
|
||||
GetPropertyData("AllowFileTransfers").AssignGUIComponent(shareSubsBox);
|
||||
// karma --------------------------------------------------------------------------
|
||||
|
||||
var randomizeLevelBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), serverTab.RectTransform), TextManager.Get("ServerSettingsRandomizeSeed"));
|
||||
GetPropertyData("RandomizeSeed").AssignGUIComponent(randomizeLevelBox);
|
||||
|
||||
var saveLogsBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), serverTab.RectTransform), TextManager.Get("ServerSettingsSaveLogs"))
|
||||
{
|
||||
OnSelected = (GUITickBox) =>
|
||||
{
|
||||
//TODO: fix?
|
||||
//showLogButton.Visible = SaveServerLogs;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
GetPropertyData("SaveServerLogs").AssignGUIComponent(saveLogsBox);
|
||||
|
||||
var ragdollButtonBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), serverTab.RectTransform), TextManager.Get("ServerSettingsAllowRagdollButton"));
|
||||
GetPropertyData("AllowRagdollButton").AssignGUIComponent(ragdollButtonBox);
|
||||
|
||||
var traitorRatioBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), serverTab.RectTransform), TextManager.Get("ServerSettingsUseTraitorRatio"));
|
||||
|
||||
CreateLabeledSlider(serverTab, "", out slider, out sliderLabel);
|
||||
/*var traitorRatioText = new GUITextBlock(new Rectangle(20, y + 20, 20, 20), "Traitor ratio: 20 %", "", settingsTabs[1], GUI.SmallFont);
|
||||
var traitorRatioSlider = new GUIScrollBar(new Rectangle(150, y + 22, 100, 15), "", 0.1f, settingsTabs[1]);*/
|
||||
var traitorRatioSlider = slider;
|
||||
traitorRatioBox.OnSelected = (GUITickBox) =>
|
||||
{
|
||||
traitorRatioSlider.OnMoved(traitorRatioSlider, traitorRatioSlider.BarScroll);
|
||||
return true;
|
||||
};
|
||||
|
||||
if (TraitorUseRatio)
|
||||
{
|
||||
traitorRatioSlider.Range = new Vector2(0.1f, 1.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
traitorRatioSlider.Range = new Vector2(1.0f, maxPlayers);
|
||||
}
|
||||
|
||||
string traitorRatioLabel = TextManager.Get("ServerSettingsTraitorRatio") + " ";
|
||||
string traitorCountLabel = TextManager.Get("ServerSettingsTraitorCount") + " ";
|
||||
|
||||
traitorRatioSlider.Range = new Vector2(0.1f, 1.0f);
|
||||
traitorRatioSlider.OnMoved = (GUIScrollBar scrollBar, float barScroll) =>
|
||||
{
|
||||
GUITextBlock traitorText = scrollBar.UserData as GUITextBlock;
|
||||
if (traitorRatioBox.Selected)
|
||||
{
|
||||
scrollBar.Step = 0.01f;
|
||||
scrollBar.Range = new Vector2(0.1f, 1.0f);
|
||||
traitorText.Text = traitorRatioLabel + (int)MathUtils.Round(scrollBar.BarScrollValue * 100.0f, 1.0f) + " %";
|
||||
}
|
||||
else
|
||||
{
|
||||
scrollBar.Step = 1f / (maxPlayers - 1);
|
||||
scrollBar.Range = new Vector2(1.0f, maxPlayers);
|
||||
traitorText.Text = traitorCountLabel + scrollBar.BarScrollValue;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
GetPropertyData("TraitorUseRatio").AssignGUIComponent(traitorRatioBox);
|
||||
GetPropertyData("TraitorRatio").AssignGUIComponent(traitorRatioSlider);
|
||||
|
||||
traitorRatioSlider.OnMoved(traitorRatioSlider, traitorRatioSlider.BarScroll);
|
||||
traitorRatioBox.OnSelected(traitorRatioBox);
|
||||
|
||||
|
||||
var karmaBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), serverTab.RectTransform), TextManager.Get("ServerSettingsUseKarma"));
|
||||
var karmaBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), antigriefingTab.RectTransform), TextManager.Get("ServerSettingsUseKarma"));
|
||||
GetPropertyData("KarmaEnabled").AssignGUIComponent(karmaBox);
|
||||
|
||||
karmaPresetDD = new GUIDropDown(new RectTransform(new Vector2(1.0f, 0.05f), antigriefingTab.RectTransform));
|
||||
foreach (string karmaPreset in GameMain.NetworkMember.KarmaManager.Presets.Keys)
|
||||
{
|
||||
karmaPresetDD.AddItem(TextManager.Get("KarmaPreset." + karmaPreset), karmaPreset);
|
||||
}
|
||||
|
||||
var karmaSettingsContainer = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.5f), antigriefingTab.RectTransform), style: null);
|
||||
var karmaSettingsList = new GUIListBox(new RectTransform(Vector2.One, karmaSettingsContainer.RectTransform));
|
||||
|
||||
karmaSettingsBlocker = new GUIFrame(new RectTransform(Vector2.One, karmaSettingsContainer.RectTransform, Anchor.CenterLeft) { MaxSize = new Point(karmaSettingsList.Content.Rect.Width, int.MaxValue) },
|
||||
style: "InnerFrame");
|
||||
karmaPresetDD.OnSelected = (selected, obj) =>
|
||||
{
|
||||
List<NetPropertyData> properties = netProperties.Values.ToList();
|
||||
List<object> prevValues = new List<object>();
|
||||
foreach (NetPropertyData prop in netProperties.Values)
|
||||
{
|
||||
prevValues.Add(prop.TempValue);
|
||||
if (prop.GUIComponent != null) { prop.Value = prop.GUIComponentValue; }
|
||||
}
|
||||
if (KarmaPreset == "custom")
|
||||
{
|
||||
GameMain.NetworkMember?.KarmaManager?.SaveCustomPreset();
|
||||
GameMain.NetworkMember?.KarmaManager?.Save();
|
||||
}
|
||||
KarmaPreset = obj as string;
|
||||
GameMain.NetworkMember.KarmaManager.SelectPreset(KarmaPreset);
|
||||
karmaSettingsList.Content.ClearChildren();
|
||||
karmaSettingsBlocker.Visible = !karmaBox.Selected || KarmaPreset != "custom";
|
||||
GameMain.NetworkMember.KarmaManager.CreateSettingsFrame(karmaSettingsList.Content);
|
||||
for (int i = 0; i < netProperties.Count; i++)
|
||||
{
|
||||
properties[i].TempValue = prevValues[i];
|
||||
}
|
||||
return true;
|
||||
};
|
||||
karmaPresetDD.SelectItem(KarmaPreset);
|
||||
AssignGUIComponent("KarmaPreset", karmaPresetDD);
|
||||
karmaBox.OnSelected = (tb) =>
|
||||
{
|
||||
karmaSettingsBlocker.Visible = !tb.Selected || KarmaPreset != "custom";
|
||||
return true;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
// banlist
|
||||
//--------------------------------------------------------------------------------
|
||||
|
||||
BanList.CreateBanFrame(settingsTabs[2]);
|
||||
BanList.CreateBanFrame(settingsTabs[(int)SettingsTab.Banlist]);
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
// whitelist
|
||||
//--------------------------------------------------------------------------------
|
||||
|
||||
Whitelist.CreateWhiteListFrame(settingsTabs[3]);
|
||||
|
||||
Whitelist.CreateWhiteListFrame(settingsTabs[(int)SettingsTab.Whitelist]);
|
||||
}
|
||||
|
||||
private void CreateLabeledSlider(GUIComponent parent, string labelTag, out GUIScrollBar slider, out GUITextBlock label)
|
||||
@@ -763,6 +809,11 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
if (settingsFrame == null)
|
||||
{
|
||||
if (KarmaPreset == "custom")
|
||||
{
|
||||
GameMain.NetworkMember?.KarmaManager?.SaveCustomPreset();
|
||||
GameMain.NetworkMember?.KarmaManager?.Save();
|
||||
}
|
||||
CreateSettingsFrame();
|
||||
}
|
||||
else
|
||||
@@ -777,44 +828,5 @@ namespace Barotrauma.Networking
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void ManagePlayersFrame(GUIFrame infoFrame)
|
||||
{
|
||||
GUIListBox cList = new GUIListBox(new RectTransform(Vector2.One, infoFrame.RectTransform));
|
||||
/*foreach (Client c in ConnectedClients)
|
||||
{
|
||||
var frame = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), cList.Content.RectTransform),
|
||||
c.Name + " (" + c.Connection.RemoteEndPoint.Address.ToString() + ")", style: "ListBoxElement")
|
||||
{
|
||||
Color = (c.InGame && c.Character != null && !c.Character.IsDead) ? Color.Gold * 0.2f : Color.Transparent,
|
||||
HoverColor = Color.LightGray * 0.5f,
|
||||
SelectedColor = Color.Gold * 0.5f
|
||||
};
|
||||
|
||||
var buttonArea = new GUILayoutGroup(new RectTransform(new Vector2(0.45f, 0.85f), frame.RectTransform, Anchor.CenterRight) { RelativeOffset = new Vector2(0.05f, 0.0f) },
|
||||
isHorizontal: true);
|
||||
|
||||
var kickButton = new GUIButton(new RectTransform(new Vector2(0.25f, 1.0f), buttonArea.RectTransform),
|
||||
TextManager.Get("Kick"))
|
||||
{
|
||||
UserData = c.Name,
|
||||
OnClicked = GameMain.NetLobbyScreen.KickPlayer
|
||||
};
|
||||
|
||||
var banButton = new GUIButton(new RectTransform(new Vector2(0.25f, 1.0f), buttonArea.RectTransform),
|
||||
TextManager.Get("Ban"))
|
||||
{
|
||||
UserData = c.Name,
|
||||
OnClicked = GameMain.NetLobbyScreen.BanPlayer
|
||||
};
|
||||
|
||||
var rangebanButton = new GUIButton(new RectTransform(new Vector2(0.25f, 1.0f), buttonArea.RectTransform),
|
||||
TextManager.Get("BanRange"))
|
||||
{
|
||||
UserData = c.Name,
|
||||
OnClicked = GameMain.NetLobbyScreen.BanPlayerRange
|
||||
};
|
||||
}*/ //TODO: reimplement
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -597,6 +597,8 @@ namespace Barotrauma.Steam
|
||||
if (string.IsNullOrEmpty(item.Error))
|
||||
{
|
||||
DebugConsole.NewMessage("Published workshop item " + item.Title + " successfully.", Microsoft.Xna.Framework.Color.LightGreen);
|
||||
var newItem = instance.client.Workshop.GetItem(item.Id);
|
||||
newItem?.Subscribe();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -56,6 +56,8 @@ namespace Barotrauma.Particles
|
||||
private int animFrame;
|
||||
|
||||
private float collisionUpdateTimer;
|
||||
|
||||
public bool HighQualityCollisionDetection;
|
||||
|
||||
public ParticlePrefab.DrawTargetType DrawTarget
|
||||
{
|
||||
@@ -133,6 +135,8 @@ namespace Barotrauma.Particles
|
||||
velocityChange = prefab.VelocityChangeDisplay;
|
||||
velocityChangeWater = prefab.VelocityChangeWaterDisplay;
|
||||
|
||||
HighQualityCollisionDetection = false;
|
||||
|
||||
OnChangeHull = null;
|
||||
|
||||
subEmitters.Clear();
|
||||
@@ -224,7 +228,7 @@ namespace Barotrauma.Particles
|
||||
}
|
||||
|
||||
lifeTime -= deltaTime;
|
||||
if (lifeTime <= 0.0f || color.A <= 0 || size.X <= 0.0f || size.Y <= 0.0f) return false;
|
||||
if (lifeTime <= 0.0f || color.A <= 0 || size.X <= 0.0f || size.Y <= 0.0f) { return false; }
|
||||
|
||||
if (hasSubEmitters)
|
||||
{
|
||||
@@ -234,16 +238,23 @@ namespace Barotrauma.Particles
|
||||
}
|
||||
}
|
||||
|
||||
if (!prefab.UseCollision) return true;
|
||||
if (!prefab.UseCollision) { return true; }
|
||||
|
||||
collisionUpdateTimer -= deltaTime;
|
||||
if (collisionUpdateTimer <= 0.0f)
|
||||
if (HighQualityCollisionDetection)
|
||||
{
|
||||
//more frequent collision updates if the particle is moving fast
|
||||
collisionUpdateTimer = 0.5f - Math.Min((Math.Abs(velocity.X) + Math.Abs(velocity.Y)) * 0.001f, 0.4f);
|
||||
return CollisionUpdate();
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
collisionUpdateTimer -= deltaTime;
|
||||
if (collisionUpdateTimer <= 0.0f)
|
||||
{
|
||||
//more frequent collision updates if the particle is moving fast
|
||||
collisionUpdateTimer = 0.5f - Math.Min((Math.Abs(velocity.X) + Math.Abs(velocity.Y)) * 0.01f, 0.45f);
|
||||
return CollisionUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -288,7 +299,7 @@ namespace Barotrauma.Particles
|
||||
bool gapFound = false;
|
||||
foreach (Gap gap in hullGaps)
|
||||
{
|
||||
if (gap.Open <= 0.0f || gap.IsHorizontal != (collisionNormal.X != 0.0f)) continue;
|
||||
if (gap.Open <= 0.9f || gap.IsHorizontal != (collisionNormal.X != 0.0f)) continue;
|
||||
|
||||
if (gap.IsHorizontal)
|
||||
{
|
||||
|
||||
@@ -56,6 +56,7 @@ namespace Barotrauma.Particles
|
||||
if (particle != null)
|
||||
{
|
||||
particle.Size *= Rand.Range(Prefab.ScaleMin, Prefab.ScaleMax);
|
||||
particle.HighQualityCollisionDetection = Prefab.HighQualityCollisionDetection;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,6 +99,8 @@ namespace Barotrauma.Particles
|
||||
|
||||
public readonly float ParticlesPerSecond;
|
||||
|
||||
public readonly bool HighQualityCollisionDetection;
|
||||
|
||||
public readonly bool CopyEntityAngle;
|
||||
|
||||
public ParticleEmitterPrefab(XElement element)
|
||||
@@ -145,7 +148,7 @@ namespace Barotrauma.Particles
|
||||
EmitInterval = element.GetAttributeFloat("emitinterval", 0.0f);
|
||||
ParticlesPerSecond = element.GetAttributeInt("particlespersecond", 0);
|
||||
ParticleAmount = element.GetAttributeInt("particleamount", 0);
|
||||
|
||||
HighQualityCollisionDetection = element.GetAttributeBool("highqualitycollisiondetection", false);
|
||||
CopyEntityAngle = element.GetAttributeBool("copyentityangle", false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (!body.Enabled)
|
||||
{
|
||||
color = Color.Gray;
|
||||
color = Color.Black;
|
||||
}
|
||||
else if (!body.Awake)
|
||||
{
|
||||
|
||||
@@ -267,6 +267,17 @@ namespace Barotrauma
|
||||
sb.AppendLine(exception.StackTrace);
|
||||
sb.AppendLine("\n");
|
||||
|
||||
if (exception.InnerException != null)
|
||||
{
|
||||
sb.AppendLine("InnerException: " + exception.InnerException.Message);
|
||||
if (exception.InnerException.TargetSite != null)
|
||||
{
|
||||
sb.AppendLine("Target site: " + exception.InnerException.TargetSite.ToString());
|
||||
}
|
||||
sb.AppendLine("Stack trace: ");
|
||||
sb.AppendLine(exception.InnerException.StackTrace);
|
||||
}
|
||||
|
||||
sb.AppendLine("Last debug messages:");
|
||||
for (int i = DebugConsole.Messages.Count - 1; i >= 0; i--)
|
||||
{
|
||||
|
||||
@@ -2788,6 +2788,7 @@ namespace Barotrauma
|
||||
if (editRagdoll || !editLimbs && !editJoints)
|
||||
{
|
||||
RagdollParams.AddToEditor(ParamsEditor.Instance, alsoChildren: false);
|
||||
RagdollParams.ColliderParams.ForEach(c => c.AddToEditor(ParamsEditor.Instance));
|
||||
}
|
||||
if (editJoints)
|
||||
{
|
||||
@@ -3041,14 +3042,16 @@ namespace Barotrauma
|
||||
|
||||
private void CalculateSpritesheetZoom()
|
||||
{
|
||||
float width = textures.OrderByDescending(t => t.Width).First().Width;
|
||||
var texture = textures.OrderByDescending(t => t.Width).FirstOrDefault();
|
||||
if (texture == null)
|
||||
{
|
||||
spriteSheetZoom = 1;
|
||||
return;
|
||||
}
|
||||
float width = texture.Width;
|
||||
float height = textures.Sum(t => t.Height);
|
||||
float margin = 20;
|
||||
if (textures == null || textures.None())
|
||||
{
|
||||
spriteSheetMaxZoom = 1;
|
||||
}
|
||||
else if (height > width)
|
||||
if (height > width)
|
||||
{
|
||||
spriteSheetMaxZoom = (centerArea.Rect.Bottom - spriteSheetOffsetY - margin) / height;
|
||||
}
|
||||
|
||||
@@ -415,9 +415,22 @@ namespace Barotrauma
|
||||
ServerInfo s1 = c1.GUIComponent.UserData as ServerInfo;
|
||||
ServerInfo s2 = c2.GUIComponent.UserData as ServerInfo;
|
||||
|
||||
if (s1 == null && s2 == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (s1 == null)
|
||||
{
|
||||
return ascending ? 1 : -1;
|
||||
}
|
||||
else if (s2 == null)
|
||||
{
|
||||
return ascending ? -1 : 1;
|
||||
}
|
||||
|
||||
switch (sortBy)
|
||||
{
|
||||
case "ServerListCompatible":
|
||||
case "ServerListCompatible":
|
||||
bool? s1Compatible = NetworkMember.IsCompatible(GameMain.Version.ToString(), s1.GameVersion);
|
||||
if (!s1.ContentPackageHashes.Any()) { s1Compatible = null; }
|
||||
if (s1Compatible.HasValue) { s1Compatible = s1Compatible.Value && s1.ContentPackagesMatch(GameMain.SelectedPackages); };
|
||||
@@ -441,7 +454,7 @@ namespace Barotrauma
|
||||
if (s1.HasPassword == s2.HasPassword) { return 0; }
|
||||
return (s1.HasPassword ? 1 : -1) * (ascending ? 1 : -1);
|
||||
case "ServerListName":
|
||||
return s1.ServerName.CompareTo(s2.ServerName) * (ascending ? 1 : -1);
|
||||
return string.Compare(s1.ServerName, s2.ServerName) * (ascending ? 1 : -1);
|
||||
case "ServerListRoundStarted":
|
||||
if (s1.GameStarted == s2.GameStarted) { return 0; }
|
||||
return (s1.GameStarted ? 1 : -1) * (ascending ? 1 : -1);
|
||||
|
||||
@@ -20,6 +20,8 @@ namespace Barotrauma
|
||||
private GUIFrame bottomPanel;
|
||||
private GUIFrame backgroundColorPanel;
|
||||
|
||||
private bool drawGrid, snapToGrid;
|
||||
|
||||
private GUIFrame topPanelContents;
|
||||
private GUITextBlock texturePathText;
|
||||
private GUITextBlock xmlPathText;
|
||||
@@ -137,7 +139,7 @@ namespace Barotrauma
|
||||
return true;
|
||||
}
|
||||
};
|
||||
new GUIButton(new RectTransform(new Vector2(0.05f, 0.35f), topPanelContents.RectTransform, Anchor.TopCenter, Pivot.CenterLeft) { RelativeOffset = new Vector2(0.055f, 0.3f) }, "Reset Zoom")
|
||||
var resetBtn = new GUIButton(new RectTransform(new Vector2(0.05f, 0.35f), topPanelContents.RectTransform, Anchor.TopCenter, Pivot.CenterLeft) { RelativeOffset = new Vector2(0.055f, 0.3f) }, "Reset Zoom")
|
||||
{
|
||||
OnClicked = (box, data) =>
|
||||
{
|
||||
@@ -145,6 +147,26 @@ namespace Barotrauma
|
||||
return true;
|
||||
}
|
||||
};
|
||||
resetBtn.TextBlock.AutoScale = true;
|
||||
|
||||
new GUITickBox(new RectTransform(new Vector2(0.2f, 0.2f), topPanelContents.RectTransform, Anchor.BottomCenter, Pivot.CenterRight) { RelativeOffset = new Vector2(0, 0.3f) }, "Show grid")
|
||||
{
|
||||
Selected = drawGrid,
|
||||
OnSelected = (tickBox) =>
|
||||
{
|
||||
drawGrid = tickBox.Selected;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
new GUITickBox(new RectTransform(new Vector2(0.2f, 0.2f), topPanelContents.RectTransform, Anchor.BottomCenter, Pivot.CenterRight) { RelativeOffset = new Vector2(0.17f, 0.3f) }, "Snap to grid")
|
||||
{
|
||||
Selected = snapToGrid,
|
||||
OnSelected = (tickBox) =>
|
||||
{
|
||||
snapToGrid = tickBox.Selected;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
texturePathText = new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.4f), topPanelContents.RectTransform, Anchor.Center, Pivot.BottomCenter) { RelativeOffset = new Vector2(0.4f, 0) }, "", Color.LightGray);
|
||||
xmlPathText = new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.4f), topPanelContents.RectTransform, Anchor.Center, Pivot.TopCenter) { RelativeOffset = new Vector2(0.4f, 0) }, "", Color.LightGray);
|
||||
@@ -230,8 +252,7 @@ namespace Barotrauma
|
||||
}, style: null, color: Color.Black * 0.6f);
|
||||
var colorLabel = new GUITextBlock(new RectTransform(new Vector2(0.3f, 1), element.RectTransform, Anchor.CenterLeft), colorComponentLabels[i],
|
||||
font: GUI.SmallFont, textAlignment: Alignment.CenterLeft);
|
||||
GUINumberInput numberInput = new GUINumberInput(new RectTransform(new Vector2(0.7f, 1), element.RectTransform, Anchor.CenterRight),
|
||||
GUINumberInput.NumberType.Int)
|
||||
var numberInput = new GUINumberInput(new RectTransform(new Vector2(0.7f, 1), element.RectTransform, Anchor.CenterRight), GUINumberInput.NumberType.Int)
|
||||
{
|
||||
Font = GUI.SmallFont
|
||||
};
|
||||
@@ -259,26 +280,32 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
private HashSet<Sprite> loadedSprites = new HashSet<Sprite>();
|
||||
private readonly HashSet<Sprite> loadedSprites = new HashSet<Sprite>();
|
||||
private void LoadSprites()
|
||||
{
|
||||
loadedSprites.ForEach(s => s.Remove());
|
||||
loadedSprites.Clear();
|
||||
//foreach (string filePath in ContentPackage.GetAllContentFiles(GameMain.SelectedPackages))
|
||||
//{
|
||||
// XDocument doc = XMLExtensions.TryLoadXml(filePath);
|
||||
// if (doc != null && doc.Root != null)
|
||||
// {
|
||||
// LoadSprites(doc.Root);
|
||||
// }
|
||||
//}
|
||||
var contentPackages = GameMain.Config.SelectedContentPackages.ToList();
|
||||
|
||||
foreach (string filePath in Directory.GetFiles("Content/", "*.xml", SearchOption.AllDirectories))
|
||||
#if !DEBUG
|
||||
var vanilla = GameMain.VanillaContent;
|
||||
if (vanilla != null)
|
||||
{
|
||||
XDocument doc = XMLExtensions.TryLoadXml(filePath);
|
||||
if (doc != null && doc.Root != null)
|
||||
contentPackages.Remove(vanilla);
|
||||
}
|
||||
#endif
|
||||
foreach (var contentPackage in contentPackages)
|
||||
{
|
||||
foreach (var file in contentPackage.Files)
|
||||
{
|
||||
LoadSprites(doc.Root);
|
||||
if (file.Path.EndsWith(".xml"))
|
||||
{
|
||||
XDocument doc = XMLExtensions.TryLoadXml(file.Path);
|
||||
if (doc != null && doc.Root != null)
|
||||
{
|
||||
LoadSprites(doc.Root);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -304,11 +331,12 @@ namespace Barotrauma
|
||||
{
|
||||
string spriteFolder = "";
|
||||
string textureElement = element.GetAttributeString("texture", "");
|
||||
// TODO: parse and create
|
||||
// TODO: parse and create?
|
||||
if (textureElement.Contains("[GENDER]") || textureElement.Contains("[HEADID]") || textureElement.Contains("[RACE]")) { return; }
|
||||
if (!textureElement.Contains("/"))
|
||||
{
|
||||
spriteFolder = Path.GetDirectoryName(element.ParseContentPathFromUri());
|
||||
var parsedPath = element.ParseContentPathFromUri();
|
||||
spriteFolder = Path.GetDirectoryName(parsedPath);
|
||||
}
|
||||
// Uncomment if we do multiple passes -> there can be duplicates
|
||||
//string identifier = Sprite.GetID(element);
|
||||
@@ -344,7 +372,7 @@ namespace Barotrauma
|
||||
xmlPathText.TextColor = Color.LightGreen;
|
||||
return true;
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region Public methods
|
||||
public override void AddToGUIUpdateList()
|
||||
@@ -466,6 +494,11 @@ namespace Barotrauma
|
||||
//GUI.DrawRectangle(spriteBatch, viewArea, Color.Green, isFilled: false);
|
||||
GUI.DrawRectangle(spriteBatch, textureRect, Color.Gray, isFilled: false);
|
||||
|
||||
if (drawGrid)
|
||||
{
|
||||
DrawGrid(spriteBatch, textureRect, zoom, Submarine.GridSize);
|
||||
}
|
||||
|
||||
foreach (GUIComponent element in spriteList.Content.Children)
|
||||
{
|
||||
Sprite sprite = element.UserData as Sprite;
|
||||
@@ -507,8 +540,11 @@ namespace Barotrauma
|
||||
w.tooltip = $"Position: {sprite.SourceRect.Location}";
|
||||
w.MouseHeld += dTime =>
|
||||
{
|
||||
w.DrawPos = PlayerInput.MousePosition;
|
||||
sprite.SourceRect = new Rectangle(((w.DrawPos + new Vector2(w.size / 2) - textureRect.Location.ToVector2()) / zoom).ToPoint(), sprite.SourceRect.Size);
|
||||
w.DrawPos = (drawGrid && snapToGrid) ?
|
||||
SnapToGrid(PlayerInput.MousePosition, textureRect, zoom, Submarine.GridSize, Submarine.GridSize.X / 4.0f * zoom) :
|
||||
PlayerInput.MousePosition;
|
||||
w.DrawPos = new Vector2((float)Math.Ceiling(w.DrawPos.X), (float)Math.Ceiling(w.DrawPos.Y));
|
||||
sprite.SourceRect = new Rectangle(((w.DrawPos - textureRect.Location.ToVector2()) / zoom).ToPoint(), sprite.SourceRect.Size);
|
||||
if (spriteList.SelectedComponent is GUITextBlock textBox)
|
||||
{
|
||||
// TODO: cache the sprite name?
|
||||
@@ -516,15 +552,18 @@ namespace Barotrauma
|
||||
}
|
||||
w.tooltip = $"Position: {sprite.SourceRect.Location}";
|
||||
};
|
||||
w.refresh = () => w.DrawPos = textureRect.Location.ToVector2() + sprite.SourceRect.Location.ToVector2() * zoom - new Vector2(w.size / 2);
|
||||
w.refresh = () => w.DrawPos = textureRect.Location.ToVector2() + sprite.SourceRect.Location.ToVector2() * zoom;
|
||||
});
|
||||
var sizeWidget = GetWidget($"{id}_size", sprite, widgetSize, Widget.Shape.Rectangle, initMethod: w =>
|
||||
{
|
||||
w.tooltip = $"Size: {sprite.SourceRect.Size}";
|
||||
w.MouseHeld += dTime =>
|
||||
{
|
||||
w.DrawPos = PlayerInput.MousePosition;
|
||||
sprite.SourceRect = new Rectangle(sprite.SourceRect.Location, ((w.DrawPos - new Vector2(w.size) - positionWidget.DrawPos) / zoom).ToPoint());
|
||||
w.DrawPos = (drawGrid && snapToGrid) ?
|
||||
SnapToGrid(PlayerInput.MousePosition, textureRect, zoom, Submarine.GridSize, Submarine.GridSize.X / 4.0f * zoom) :
|
||||
PlayerInput.MousePosition;
|
||||
w.DrawPos = new Vector2((float)Math.Ceiling(w.DrawPos.X), (float)Math.Ceiling(w.DrawPos.Y));
|
||||
sprite.SourceRect = new Rectangle(sprite.SourceRect.Location, ((w.DrawPos - positionWidget.DrawPos) / zoom).ToPoint());
|
||||
// TODO: allow to lock the origin
|
||||
sprite.RelativeOrigin = sprite.RelativeOrigin;
|
||||
if (spriteList.SelectedComponent is GUITextBlock textBox)
|
||||
@@ -534,7 +573,7 @@ namespace Barotrauma
|
||||
}
|
||||
w.tooltip = $"Size: {sprite.SourceRect.Size}";
|
||||
};
|
||||
w.refresh = () => w.DrawPos = textureRect.Location.ToVector2() + new Vector2(sprite.SourceRect.Right, sprite.SourceRect.Bottom) * zoom + new Vector2(w.size / 2);
|
||||
w.refresh = () => w.DrawPos = textureRect.Location.ToVector2() + new Vector2(sprite.SourceRect.Right, sprite.SourceRect.Bottom) * zoom;
|
||||
});
|
||||
if (isSelected)
|
||||
{
|
||||
@@ -553,6 +592,58 @@ namespace Barotrauma
|
||||
spriteBatch.End();
|
||||
}
|
||||
|
||||
private void DrawGrid(SpriteBatch spriteBatch, Rectangle gridArea, float zoom, Vector2 gridSize)
|
||||
{
|
||||
gridSize *= zoom;
|
||||
if (gridSize.X < 1.0f) { return; }
|
||||
if (gridSize.Y < 1.0f) { return; }
|
||||
int xLines = (int)(gridArea.Width / gridSize.X);
|
||||
int yLines = (int)(gridArea.Height / gridSize.Y);
|
||||
|
||||
for (int x = 0; x <= xLines; x++)
|
||||
{
|
||||
GUI.DrawLine(spriteBatch,
|
||||
new Vector2(gridArea.X + x * gridSize.X, gridArea.Y),
|
||||
new Vector2(gridArea.X + x * gridSize.X, gridArea.Bottom),
|
||||
Color.White * 0.25f);
|
||||
}
|
||||
for (int y = 0; y <= yLines; y++)
|
||||
{
|
||||
GUI.DrawLine(spriteBatch,
|
||||
new Vector2(gridArea.X, gridArea.Y + y * gridSize.Y),
|
||||
new Vector2(gridArea.Right, gridArea.Y + y * gridSize.Y),
|
||||
Color.White * 0.25f);
|
||||
}
|
||||
}
|
||||
|
||||
private Vector2 SnapToGrid(Vector2 position, Rectangle gridArea, float zoom, Vector2 gridSize, float tolerance)
|
||||
{
|
||||
gridSize *= zoom;
|
||||
if (gridSize.X < 1.0f) { return position; }
|
||||
if (gridSize.Y < 1.0f) { return position; }
|
||||
|
||||
Vector2 snappedPos = position;
|
||||
snappedPos.X -= gridArea.X;
|
||||
snappedPos.Y -= gridArea.Y;
|
||||
|
||||
Vector2 gridPos = new Vector2(
|
||||
MathUtils.RoundTowardsClosest(snappedPos.X, gridSize.X),
|
||||
MathUtils.RoundTowardsClosest(snappedPos.Y, gridSize.Y));
|
||||
|
||||
if (Math.Abs(gridPos.X - snappedPos.X) < tolerance)
|
||||
{
|
||||
snappedPos.X = gridPos.X;
|
||||
}
|
||||
if (Math.Abs(gridPos.Y - snappedPos.Y) < tolerance)
|
||||
{
|
||||
snappedPos.Y = gridPos.Y;
|
||||
}
|
||||
|
||||
snappedPos.X += gridArea.X;
|
||||
snappedPos.Y += gridArea.Y;
|
||||
return snappedPos;
|
||||
}
|
||||
|
||||
public override void Select()
|
||||
{
|
||||
base.Select();
|
||||
@@ -706,7 +797,7 @@ namespace Barotrauma
|
||||
zoomBar.BarScroll = GetBarScrollValue();
|
||||
viewAreaOffset = Point.Zero;
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region Helpers
|
||||
private Point viewAreaOffset;
|
||||
@@ -750,7 +841,7 @@ namespace Barotrauma
|
||||
// Keeps the relative origin unchanged. The absolute origin will be recalculated.
|
||||
sprite.RelativeOrigin = sprite.RelativeOrigin;
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region Widgets
|
||||
private Dictionary<string, Widget> widgets = new Dictionary<string, Widget>();
|
||||
@@ -792,6 +883,6 @@ namespace Barotrauma
|
||||
widgets.Clear();
|
||||
Widget.selectedWidgets.Clear();
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ namespace Barotrauma
|
||||
|
||||
tabs = new GUIFrame[Enum.GetValues(typeof(Tab)).Length];
|
||||
|
||||
menu = new GUIFrame(new RectTransform(new Vector2(0.85f, 0.8f), GUI.Canvas, Anchor.Center) { MinSize = new Point(GameMain.GraphicsHeight, 0) });
|
||||
menu = new GUIFrame(new RectTransform(new Vector2(0.85f, 0.85f), GUI.Canvas, Anchor.Center) { MinSize = new Point(GameMain.GraphicsHeight, 0) });
|
||||
|
||||
var container = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.85f), menu.RectTransform, Anchor.Center) { RelativeOffset = new Vector2(0.0f, 0.05f) }) { Stretch = true };
|
||||
|
||||
@@ -111,6 +111,7 @@ namespace Barotrauma
|
||||
|
||||
var listContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.5f, 1.0f), tabs[(int)Tab.Browse].RectTransform))
|
||||
{
|
||||
RelativeSpacing = 0.01f,
|
||||
Stretch = true
|
||||
};
|
||||
|
||||
@@ -125,7 +126,7 @@ namespace Barotrauma
|
||||
};
|
||||
|
||||
var findModsButtonContainer = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.02f), listContainer.RectTransform), style: null);
|
||||
new GUIButton(new RectTransform(new Vector2(1.0f, 1.0f), findModsButtonContainer.RectTransform, Anchor.Center), TextManager.Get("FindModsButton"), style: null)
|
||||
new GUIButton(new RectTransform(new Vector2(1.0f, 0.9f), findModsButtonContainer.RectTransform, Anchor.Center), TextManager.Get("FindModsButton"), style: null)
|
||||
{
|
||||
Color = new Color(38, 86, 38, 75),
|
||||
HoverColor = new Color(85, 203, 99, 50),
|
||||
@@ -260,7 +261,12 @@ namespace Barotrauma
|
||||
|
||||
private void RefreshItemLists()
|
||||
{
|
||||
SteamManager.GetSubscribedWorkshopItems((items) => { OnItemsReceived(items, subscribedItemList); });
|
||||
SteamManager.GetSubscribedWorkshopItems((items) =>
|
||||
{
|
||||
//filter out the items published by the player (they're shown in the publish tab)
|
||||
var mySteamID = SteamManager.GetSteamID();
|
||||
OnItemsReceived(items.Where(it => it.OwnerId != mySteamID).ToList(), subscribedItemList);
|
||||
});
|
||||
SteamManager.GetPopularWorkshopItems((items) => { OnItemsReceived(items, topItemList); }, 20);
|
||||
SteamManager.GetPublishedWorkshopItems((items) => { OnItemsReceived(items, publishedItemList); });
|
||||
|
||||
@@ -704,19 +710,17 @@ namespace Barotrauma
|
||||
}
|
||||
};
|
||||
|
||||
var headerAreaBackground = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.5f), content.RectTransform, maxSize: new Point(int.MaxValue, 235))) { Color = Color.Black };
|
||||
|
||||
var headerArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f), headerAreaBackground.RectTransform), childAnchor: Anchor.Center);
|
||||
var headerArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.5f), content.RectTransform)) { Color = Color.Black };
|
||||
|
||||
if (itemPreviewSprites.ContainsKey(item.PreviewImageUrl))
|
||||
{
|
||||
new GUIImage(new RectTransform(new Point(headerArea.Rect.Width, headerArea.Rect.Height), headerArea.RectTransform), itemPreviewSprites[item.PreviewImageUrl], scaleToFit: true);
|
||||
new GUIImage(new RectTransform(Vector2.One, headerArea.RectTransform), itemPreviewSprites[item.PreviewImageUrl], scaleToFit: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
new GUIImage(new RectTransform(new Point(headerArea.Rect.Width, headerArea.Rect.Height), headerArea.RectTransform), SteamManager.Instance.DefaultPreviewImage, scaleToFit: true);
|
||||
new GUIImage(new RectTransform(Vector2.One, headerArea.RectTransform), SteamManager.Instance.DefaultPreviewImage, scaleToFit: true);
|
||||
}
|
||||
|
||||
|
||||
var descriptionContainer = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.2f), content.RectTransform)) { ScrollBarVisible = true };
|
||||
|
||||
//spacing
|
||||
@@ -944,21 +948,25 @@ namespace Barotrauma
|
||||
tagBtn.TextBlock.AutoScale = true;
|
||||
tagBtn.Color *= 0.5f;
|
||||
tagBtn.SelectedColor = Color.LightGreen;
|
||||
tagBtn.HoverColor = Color.Lerp(tagBtn.HoverColor, Color.LightGreen, 0.5f);
|
||||
tagBtn.Selected = itemEditor.Tags.Any(t => t.ToLowerInvariant() == tag);
|
||||
|
||||
Color defaultTextColor = tagBtn.TextColor;
|
||||
tagBtn.TextColor = tagBtn.Selected ? Color.LightGreen : defaultTextColor;
|
||||
|
||||
tagBtn.OnClicked = (btn, userdata) =>
|
||||
{
|
||||
if (!tagBtn.Selected)
|
||||
{
|
||||
if (!itemEditor.Tags.Any(t => t.ToLowerInvariant() == tag)) { itemEditor.Tags.Add(tagBtn.Text); }
|
||||
tagBtn.Selected = true;
|
||||
tagBtn.TextBlock.TextColor = Color.LightGreen;
|
||||
tagBtn.TextColor = Color.LightGreen;
|
||||
}
|
||||
else
|
||||
{
|
||||
itemEditor.Tags.RemoveAll(t => t.ToLowerInvariant() == tagBtn.Text.ToLowerInvariant());
|
||||
tagBtn.Selected = false;
|
||||
tagBtn.TextBlock.TextColor = tagBtn.TextColor;
|
||||
tagBtn.TextColor = defaultTextColor;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
@@ -71,6 +71,12 @@ namespace Barotrauma
|
||||
private Color primaryColor = new Color(12, 14, 15, 190);
|
||||
private Color secondaryColor = new Color(12, 14, 15, 215);
|
||||
|
||||
private const int submarineNameLimit = 30;
|
||||
private GUITextBlock submarineNameCharacterCount;
|
||||
|
||||
private const int submarineDescriptionLimit = 500;
|
||||
private GUITextBlock submarineDescriptionCharacterCount;
|
||||
|
||||
public override Camera Cam
|
||||
{
|
||||
get { return cam; }
|
||||
@@ -346,7 +352,6 @@ namespace Barotrauma
|
||||
UseGridLayout = true,
|
||||
CheckSelected = MapEntityPrefab.GetSelected
|
||||
};
|
||||
UpdateEntityList();
|
||||
|
||||
//empty guiframe as a separator
|
||||
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.02f), paddedLeftPanel.RectTransform), style: null);
|
||||
@@ -603,14 +608,16 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
|
||||
entityList.Content.RectTransform.SortChildren((i1, i2) =>
|
||||
entityList.Content.RectTransform.SortChildren((i1, i2) =>
|
||||
(i1.GUIComponent.UserData as MapEntityPrefab).Name.CompareTo((i2.GUIComponent.UserData as MapEntityPrefab).Name));
|
||||
}
|
||||
|
||||
|
||||
public override void Select()
|
||||
{
|
||||
base.Select();
|
||||
|
||||
UpdateEntityList();
|
||||
|
||||
foreach (MapEntityPrefab prefab in MapEntityPrefab.List)
|
||||
{
|
||||
prefab.sprite?.EnsureLazyLoaded();
|
||||
@@ -950,32 +957,60 @@ namespace Barotrauma
|
||||
OnClicked = (btn, userdata) => { if (GUI.MouseOn == btn || GUI.MouseOn == btn.TextBlock) saveFrame = null; return true; }
|
||||
};
|
||||
|
||||
var innerFrame = new GUIFrame(new RectTransform(new Vector2(0.4f, 0.45f), saveFrame.RectTransform, Anchor.Center) { MinSize = new Point(750, 400) });
|
||||
var innerFrame = new GUIFrame(new RectTransform(new Vector2(0.4f, 0.5f), saveFrame.RectTransform, Anchor.Center) { MinSize = new Point(750, 400) });
|
||||
var paddedSaveFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.9f), innerFrame.RectTransform, Anchor.Center)) { Stretch = true, RelativeSpacing = 0.02f };
|
||||
|
||||
//var header = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedSaveFrame.RectTransform), TextManager.Get("SaveSubDialogHeader"), font: GUI.LargeFont);
|
||||
|
||||
var columnArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.9f), paddedSaveFrame.RectTransform), isHorizontal: true) { Stretch = true };
|
||||
var leftColumn = new GUILayoutGroup(new RectTransform(new Vector2(0.55f, 1.0f), columnArea.RectTransform)) { RelativeSpacing = 0.02f, Stretch = true };
|
||||
var leftColumn = new GUILayoutGroup(new RectTransform(new Vector2(0.55f, 1.0f), columnArea.RectTransform)) { RelativeSpacing = 0.01f, Stretch = true };
|
||||
var rightColumn = new GUILayoutGroup(new RectTransform(new Vector2(0.42f, 1.0f), columnArea.RectTransform)) { RelativeSpacing = 0.02f, Stretch = true };
|
||||
|
||||
// left column -----------------------------------------------------------------------
|
||||
|
||||
var saveSubLabel = new GUITextBlock(new RectTransform(new Vector2(0.4f, 0.03f), leftColumn.RectTransform),
|
||||
var nameHeaderGroup = new GUILayoutGroup(new RectTransform(new Vector2(.975f, 0.03f), leftColumn.RectTransform), true);
|
||||
var saveSubLabel = new GUITextBlock(new RectTransform(new Vector2(.5f, 1f), nameHeaderGroup.RectTransform),
|
||||
TextManager.Get("SaveSubDialogName"));
|
||||
|
||||
nameBox = new GUITextBox(new RectTransform(new Vector2(0.65f, 0.05f), leftColumn.RectTransform))
|
||||
submarineNameCharacterCount = new GUITextBlock(new RectTransform(new Vector2(.5f, 1f), nameHeaderGroup.RectTransform), string.Empty, textAlignment: Alignment.TopRight);
|
||||
|
||||
nameBox = new GUITextBox(new RectTransform(new Vector2(.95f, 0.05f), leftColumn.RectTransform))
|
||||
{
|
||||
OnEnterPressed = ChangeSubName,
|
||||
Text = GetSubName()
|
||||
};
|
||||
nameBox.OnTextChanged += (textBox, text) =>
|
||||
{
|
||||
if (text.Length > submarineNameLimit)
|
||||
{
|
||||
nameBox.Text = text.Substring(0, submarineNameLimit);
|
||||
nameBox.Flash(Color.Red);
|
||||
return true;
|
||||
}
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.03f), leftColumn.RectTransform), TextManager.Get("SaveSubDialogDescription"));
|
||||
submarineNameCharacterCount.Text = text.Length + " / " + submarineNameLimit;
|
||||
return true;
|
||||
};
|
||||
|
||||
submarineNameCharacterCount.Text = nameBox.Text.Length + " / " + submarineNameLimit;
|
||||
|
||||
var descriptionHeaderGroup = new GUILayoutGroup(new RectTransform(new Vector2(.975f, 0.03f), leftColumn.RectTransform), true);
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(0.5f, 1f), descriptionHeaderGroup.RectTransform), TextManager.Get("SaveSubDialogDescription"));
|
||||
submarineDescriptionCharacterCount = new GUITextBlock(new RectTransform(new Vector2(.5f, 1f), descriptionHeaderGroup.RectTransform), string.Empty, textAlignment: Alignment.TopRight);
|
||||
|
||||
var descriptionContainer = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.25f), leftColumn.RectTransform));
|
||||
descriptionBox = new GUITextBox(new RectTransform(Vector2.One, descriptionContainer.Content.RectTransform), font: GUI.SmallFont, wrap: true);
|
||||
descriptionBox = new GUITextBox(new RectTransform(Vector2.One, descriptionContainer.Content.RectTransform, Anchor.Center), font: GUI.SmallFont, wrap: true);
|
||||
|
||||
descriptionBox.OnTextChanged += (textBox, text) =>
|
||||
{
|
||||
if (text.Length > submarineDescriptionLimit)
|
||||
{
|
||||
descriptionBox.Text = text.Substring(0, submarineDescriptionLimit);
|
||||
descriptionBox.Flash(Color.Red);
|
||||
return true;
|
||||
}
|
||||
|
||||
Vector2 textSize = textBox.Font.MeasureString(descriptionBox.WrappedText);
|
||||
textBox.RectTransform.NonScaledSize = new Point(textBox.RectTransform.NonScaledSize.X, Math.Max(descriptionContainer.Rect.Height, (int)textSize.Y + 10));
|
||||
descriptionContainer.UpdateScrollBarSize();
|
||||
@@ -984,6 +1019,7 @@ namespace Barotrauma
|
||||
return true;
|
||||
};
|
||||
descriptionBox.Text = Submarine.MainSub == null ? "" : Submarine.MainSub.Description;
|
||||
submarineDescriptionCharacterCount.Text = descriptionBox.Text.Length + " / " + submarineDescriptionLimit;
|
||||
|
||||
var crewSizeArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.03f), leftColumn.RectTransform), isHorizontal: true) { AbsoluteSpacing = 5 };
|
||||
|
||||
@@ -1493,8 +1529,21 @@ namespace Barotrauma
|
||||
|
||||
private void TryDeleteSub(Submarine sub)
|
||||
{
|
||||
if (sub == null) return;
|
||||
|
||||
if (sub == null) { return; }
|
||||
|
||||
//if the sub is included in a content package that only defines that one sub,
|
||||
//delete the content package as well
|
||||
ContentPackage subPackage = null;
|
||||
foreach (ContentPackage cp in ContentPackage.List)
|
||||
{
|
||||
if (cp.Files.Count == 1 && Path.GetFullPath(cp.Files[0].Path) == Path.GetFullPath(sub.FilePath))
|
||||
{
|
||||
subPackage = cp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
subPackage?.Delete();
|
||||
|
||||
var msgBox = new GUIMessageBox(
|
||||
TextManager.Get("DeleteDialogLabel"),
|
||||
TextManager.GetWithVariable("DeleteDialogQuestion", "[file]", sub.Name),
|
||||
@@ -1524,7 +1573,6 @@ namespace Barotrauma
|
||||
if (CharacterMode) SetCharacterMode(false);
|
||||
if (WiringMode) SetWiringMode(false);
|
||||
|
||||
|
||||
saveFrame = null;
|
||||
loadFrame = null;
|
||||
|
||||
@@ -1754,7 +1802,9 @@ namespace Barotrauma
|
||||
{
|
||||
textBox.UserData = text;
|
||||
}
|
||||
|
||||
|
||||
submarineDescriptionCharacterCount.Text = text.Length + " / " + submarineDescriptionLimit;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2131,6 +2181,10 @@ namespace Barotrauma
|
||||
{
|
||||
dummyCharacter.SelectedConstruction.AddToGUIUpdateList();
|
||||
}
|
||||
else if (WiringMode && MapEntity.SelectedList.Count == 1 && MapEntity.SelectedList[0] is Item item && item.GetComponent<Wire>() != null)
|
||||
{
|
||||
MapEntity.SelectedList[0].AddToGUIUpdateList();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2290,9 +2344,9 @@ namespace Barotrauma
|
||||
dummyCharacter.SelectedConstruction = null;
|
||||
}*/
|
||||
}
|
||||
else if (MapEntity.FilteredSelectedList.Count == 1)
|
||||
else if (MapEntity.SelectedList.Count == 1)
|
||||
{
|
||||
(MapEntity.FilteredSelectedList[0] as Item)?.UpdateHUD(cam, dummyCharacter, (float)deltaTime);
|
||||
(MapEntity.SelectedList[0] as Item)?.UpdateHUD(cam, dummyCharacter, (float)deltaTime);
|
||||
}
|
||||
|
||||
CharacterHUD.Update((float)deltaTime, dummyCharacter, cam);
|
||||
|
||||
@@ -203,6 +203,8 @@ namespace Barotrauma
|
||||
|
||||
public static void Update(float deltaTime)
|
||||
{
|
||||
if (!Initialized) { return; }
|
||||
|
||||
UpdateMusic(deltaTime);
|
||||
|
||||
if (startUpSound != null && !GameMain.SoundManager.IsPlaying(startUpSound))
|
||||
@@ -629,7 +631,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (OverrideMusicType != null) return OverrideMusicType;
|
||||
|
||||
if (Screen.Selected != GameMain.GameScreen)
|
||||
if (Screen.Selected == null || Screen.Selected != GameMain.GameScreen)
|
||||
{
|
||||
return "menu";
|
||||
}
|
||||
@@ -644,7 +646,7 @@ namespace Barotrauma
|
||||
Submarine targetSubmarine = Character.Controlled?.Submarine;
|
||||
|
||||
if ((targetSubmarine != null && targetSubmarine.AtDamageDepth) ||
|
||||
(Screen.Selected == GameMain.GameScreen && GameMain.GameScreen.Cam.Position.Y < SubmarineBody.DamageDepth))
|
||||
(GameMain.GameScreen != null && Screen.Selected == GameMain.GameScreen && GameMain.GameScreen.Cam.Position.Y < SubmarineBody.DamageDepth))
|
||||
{
|
||||
return "deep";
|
||||
}
|
||||
|
||||
@@ -54,7 +54,9 @@ namespace Barotrauma
|
||||
|
||||
partial void ApplyProjSpecific(float deltaTime, Entity entity, List<ISerializableEntity> targets, Hull hull)
|
||||
{
|
||||
if (entity != null && sounds.Count > 0)
|
||||
if (entity == null) { return; }
|
||||
|
||||
if (sounds.Count > 0)
|
||||
{
|
||||
if (soundChannel == null || !soundChannel.IsPlaying)
|
||||
{
|
||||
@@ -95,22 +97,20 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
if (entity != null)
|
||||
foreach (ParticleEmitter emitter in particleEmitters)
|
||||
{
|
||||
foreach (ParticleEmitter emitter in particleEmitters)
|
||||
float angle = 0.0f;
|
||||
if (emitter.Prefab.CopyEntityAngle)
|
||||
{
|
||||
float angle = 0.0f;
|
||||
if (emitter.Prefab.CopyEntityAngle)
|
||||
if (entity is Item item && item.body != null)
|
||||
{
|
||||
if (entity is Item it)
|
||||
{
|
||||
angle = it.body == null ? 0.0f : it.body.Rotation;
|
||||
}
|
||||
angle = item.body.Rotation + ((item.body.Dir > 0.0f) ? 0.0f : MathHelper.Pi);
|
||||
}
|
||||
|
||||
emitter.Emit(deltaTime, entity.WorldPosition, hull, angle);
|
||||
}
|
||||
|
||||
emitter.Emit(deltaTime, entity.WorldPosition, hull, angle);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static partial void UpdateAllProjSpecific(float deltaTime)
|
||||
|
||||
Binary file not shown.
@@ -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.9.1.0")]
|
||||
[assembly: AssemblyVersion("0.9.200.0")]
|
||||
[assembly: AssemblyFileVersion("0.9.1.0")]
|
||||
|
||||
@@ -212,6 +212,7 @@
|
||||
<Compile Include="Source\Networking\FileTransfer\FileSender.cs" />
|
||||
<Compile Include="Source\Networking\GameServer.cs" />
|
||||
<Compile Include="Source\Networking\GameServerLogin.cs" />
|
||||
<Compile Include="Source\Networking\KarmaManager.cs" />
|
||||
<Compile Include="Source\Networking\NetEntityEvent\ServerEntityEventManager.cs" />
|
||||
<Compile Include="Source\Networking\NetworkMember.cs" />
|
||||
<Compile Include="Source\Networking\OrderChatMessage.cs" />
|
||||
|
||||
@@ -120,12 +120,16 @@ namespace Barotrauma
|
||||
get { return targetPos; }
|
||||
set { targetPos = value; }
|
||||
}
|
||||
|
||||
public Vector2 GetPosition()
|
||||
{
|
||||
return position;
|
||||
}
|
||||
|
||||
// Auxiliary function to move the camera
|
||||
public void Translate(Vector2 amount)
|
||||
{
|
||||
position += amount;
|
||||
|
||||
}
|
||||
|
||||
public void UpdateTransform(bool interpolate = true, bool clampPos = false)
|
||||
|
||||
@@ -11,22 +11,9 @@ namespace Barotrauma
|
||||
{
|
||||
}
|
||||
|
||||
partial void AdjustKarma(Character attacker, AttackResult attackResult)
|
||||
partial void OnAttackedProjSpecific(Character attacker, AttackResult attackResult)
|
||||
{
|
||||
if (attacker == null) return;
|
||||
|
||||
Client attackerClient = GameMain.Server.ConnectedClients.Find(c => c.Character == attacker);
|
||||
if (attackerClient == null) return;
|
||||
|
||||
Client targetClient = GameMain.Server.ConnectedClients.Find(c => c.Character == this);
|
||||
if (targetClient != null)
|
||||
{
|
||||
if (attacker.TeamID == TeamID)
|
||||
{
|
||||
attackerClient.Karma -= attackResult.Damage * 0.01f;
|
||||
if (CharacterHealth.MaxVitality <= CharacterHealth.MinVitality) attackerClient.Karma = 0.0f;
|
||||
}
|
||||
}
|
||||
GameMain.Server.KarmaManager.OnCharacterHealthChanged(this, attacker, attackResult.Damage, attackResult.Afflictions);
|
||||
}
|
||||
|
||||
partial void KillProjSpecific(CauseOfDeathType causeOfDeath, Affliction causeOfDeathAffliction)
|
||||
|
||||
@@ -21,29 +21,25 @@ namespace Barotrauma
|
||||
{
|
||||
if (!Enabled) { return 1000.0f; }
|
||||
|
||||
if (recipient.Character == null || recipient.Character.IsDead)
|
||||
{
|
||||
return 0.2f;
|
||||
}
|
||||
else
|
||||
{
|
||||
float distance = Vector2.Distance(recipient.Character.WorldPosition, WorldPosition);
|
||||
float priority = 1.0f - MathUtils.InverseLerp(
|
||||
NetConfig.HighPrioCharacterPositionUpdateDistance,
|
||||
NetConfig.LowPrioCharacterPositionUpdateDistance,
|
||||
distance);
|
||||
Vector2 comparePosition = recipient.SpectatePos == null ? recipient.Character.WorldPosition : recipient.SpectatePos.Value;
|
||||
|
||||
float interval = MathHelper.Lerp(
|
||||
NetConfig.LowPrioCharacterPositionUpdateInterval,
|
||||
NetConfig.HighPrioCharacterPositionUpdateInterval,
|
||||
priority);
|
||||
float distance = Vector2.Distance(comparePosition, WorldPosition);
|
||||
float priority = 1.0f - MathUtils.InverseLerp(
|
||||
NetConfig.HighPrioCharacterPositionUpdateDistance,
|
||||
NetConfig.LowPrioCharacterPositionUpdateDistance,
|
||||
distance);
|
||||
|
||||
if (IsDead)
|
||||
{
|
||||
interval = Math.Max(interval * 2, 0.1f);
|
||||
}
|
||||
return interval;
|
||||
float interval = MathHelper.Lerp(
|
||||
NetConfig.LowPrioCharacterPositionUpdateInterval,
|
||||
NetConfig.HighPrioCharacterPositionUpdateInterval,
|
||||
priority);
|
||||
|
||||
if (IsDead)
|
||||
{
|
||||
interval = Math.Max(interval * 2, 0.1f);
|
||||
}
|
||||
|
||||
return interval;
|
||||
}
|
||||
|
||||
partial void UpdateNetInput()
|
||||
|
||||
@@ -86,7 +86,8 @@ namespace Barotrauma
|
||||
int inputLines = Math.Max((int)Math.Ceiling(input.Length / (float)Console.WindowWidth), 1);
|
||||
Console.CursorLeft = 0;
|
||||
Console.Write(new string(' ', consoleWidth));
|
||||
Console.CursorTop -= inputLines; Console.CursorLeft = 0;
|
||||
Console.CursorTop = Math.Max(Console.CursorTop - inputLines, 0);
|
||||
Console.CursorLeft = 0;
|
||||
while (queuedMessages.Count > 0)
|
||||
{
|
||||
ColoredText msg = queuedMessages.Dequeue();
|
||||
@@ -121,9 +122,9 @@ namespace Barotrauma
|
||||
switch (key.Key)
|
||||
{
|
||||
case ConsoleKey.Enter:
|
||||
lock (DebugConsole.QueuedCommands)
|
||||
lock (QueuedCommands)
|
||||
{
|
||||
DebugConsole.QueuedCommands.Add(input);
|
||||
QueuedCommands.Add(input);
|
||||
}
|
||||
input = "";
|
||||
memoryIndex = -1;
|
||||
@@ -219,7 +220,15 @@ namespace Barotrauma
|
||||
|
||||
private static void AssignOnClientRequestExecute(string names, Action<Client, Vector2, string[]> onClientRequestExecute)
|
||||
{
|
||||
commands.First(c => c.names.Intersect(names.Split('|')).Count() > 0).OnClientRequestExecute = onClientRequestExecute;
|
||||
var matchingCommand = commands.Find(c => c.names.Intersect(names.Split('|')).Count() > 0);
|
||||
if (matchingCommand == null)
|
||||
{
|
||||
throw new Exception("AssignOnClientRequestExecute failed. Command matching the name(s) \"" + names + "\" not found.");
|
||||
}
|
||||
else
|
||||
{
|
||||
matchingCommand.OnClientRequestExecute = onClientRequestExecute;
|
||||
}
|
||||
}
|
||||
|
||||
private static void InitProjectSpecific()
|
||||
@@ -568,10 +577,8 @@ namespace Barotrauma
|
||||
NewMessage(client.Name + " has the following permissions:", Color.White);
|
||||
foreach (ClientPermissions permission in Enum.GetValues(typeof(ClientPermissions)))
|
||||
{
|
||||
if (permission == ClientPermissions.None || !client.HasPermission(permission)) continue;
|
||||
System.Reflection.FieldInfo fi = typeof(ClientPermissions).GetField(permission.ToString());
|
||||
DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
|
||||
NewMessage(" - " + attributes[0].Description, Color.White);
|
||||
if (permission == ClientPermissions.None || !client.HasPermission(permission)) { continue; }
|
||||
NewMessage(" - " + TextManager.Get("ClientPermission." + permission), Color.White);
|
||||
}
|
||||
if (client.HasPermission(ClientPermissions.ConsoleCommands))
|
||||
{
|
||||
@@ -590,12 +597,100 @@ namespace Barotrauma
|
||||
}
|
||||
});
|
||||
|
||||
/*AssignOnExecute("togglekarma", (string[] args) =>
|
||||
AssignOnExecute("togglekarma", (string[] args) =>
|
||||
{
|
||||
return;
|
||||
if (GameMain.Server == null) return;
|
||||
GameMain.Server.ServerSettings.KarmaEnabled = !GameMain.Server.ServerSettings.KarmaEnabled;
|
||||
});*/
|
||||
NewMessage(GameMain.Server.ServerSettings.KarmaEnabled ? "Karma system enabled." : "Karma system disabled.", Color.LightGreen);
|
||||
});
|
||||
|
||||
AssignOnExecute("resetkarma", (string[] args) =>
|
||||
{
|
||||
if (GameMain.Server == null || args.Length == 0) return;
|
||||
var client = GameMain.Server.ConnectedClients.Find(c => c.Name == args[0]);
|
||||
if (client == null)
|
||||
{
|
||||
ThrowError("Client \"" + args[0] + "\" not found.");
|
||||
return;
|
||||
}
|
||||
client.Karma = 100.0f;
|
||||
NewMessage("Set the karma of the client \"" + args[0] + "\" to 100.", Color.LightGreen);
|
||||
});
|
||||
AssignOnClientRequestExecute("resetkarma", (Client client, Vector2 cursorWorldPos, string[] args) =>
|
||||
{
|
||||
if (GameMain.Server == null || args.Length == 0) return;
|
||||
var targetClient = GameMain.Server.ConnectedClients.Find(c => c.Name == args[0]);
|
||||
if (targetClient == null)
|
||||
{
|
||||
ThrowError("Client \"" + args[0] + "\" not found.");
|
||||
return;
|
||||
}
|
||||
targetClient.Karma = 100.0f;
|
||||
GameMain.Server.SendDirectChatMessage("Set the karma of the client \"" + args[0] + "\" to 100.", client);
|
||||
NewMessage("Client \"" + client.Name + "\" set the karma of \"" + args[0] + "\" to 100.", Color.LightGreen);
|
||||
});
|
||||
|
||||
AssignOnExecute("setkarma", (string[] args) =>
|
||||
{
|
||||
if (GameMain.Server == null || args.Length < 2) return;
|
||||
var client = GameMain.Server.ConnectedClients.Find(c => c.Name == args[0]);
|
||||
if (client == null)
|
||||
{
|
||||
ThrowError("Client \"" + args[0] + "\" not found.");
|
||||
return;
|
||||
}
|
||||
if (!float.TryParse(args[1], out float karmaValue) || karmaValue < 0.0f || karmaValue > 100.0f)
|
||||
{
|
||||
ThrowError("\"" + args[1] + "\" is not a valid karma value. You need to enter a number between 0-100.");
|
||||
return;
|
||||
}
|
||||
client.Karma = karmaValue;
|
||||
NewMessage("Set the karma of the client \"" + args[0] + "\" to " + karmaValue + ".", Color.LightGreen);
|
||||
});
|
||||
AssignOnClientRequestExecute("setkarma", (Client client, Vector2 cursorWorldPos, string[] args) =>
|
||||
{
|
||||
if (GameMain.Server == null || args.Length < 2) return;
|
||||
var targetClient = GameMain.Server.ConnectedClients.Find(c => c.Name == args[0]);
|
||||
if (targetClient == null)
|
||||
{
|
||||
GameMain.Server.SendDirectChatMessage("Client \"" + args[0] + "\" not found.", client);
|
||||
return;
|
||||
}
|
||||
if (!float.TryParse(args[1], out float karmaValue) || karmaValue < 0.0f || karmaValue > 100.0f)
|
||||
{
|
||||
GameMain.Server.SendDirectChatMessage("\"" + args[1] + "\" is not a valid karma value. You need to enter a number between 0-100.", client);
|
||||
return;
|
||||
}
|
||||
targetClient.Karma = karmaValue;
|
||||
GameMain.Server.SendDirectChatMessage("Set the karma of the client \"" + args[0] + "\" to " + karmaValue + ".", client);
|
||||
NewMessage("Client \"" + client.Name + "\" set the karma of \"" + args[0] + "\" to " + karmaValue + ".", Color.LightGreen);
|
||||
});
|
||||
|
||||
AssignOnExecute("showkarma", (string[] args) =>
|
||||
{
|
||||
if (GameMain.Server == null) return;
|
||||
NewMessage("***************", Color.Cyan);
|
||||
foreach (Client c in GameMain.Server.ConnectedClients)
|
||||
{
|
||||
NewMessage("- " + c.ID.ToString() + ": " + c.Name + (c.Character != null ? " playing " + c.Character.LogName : "") + ", " + c.Karma, Color.Cyan);
|
||||
}
|
||||
NewMessage("***************", Color.Cyan);
|
||||
});
|
||||
AssignOnClientRequestExecute("showkarma", (Client client, Vector2 cursorWorldPos, string[] args) =>
|
||||
{
|
||||
GameMain.Server.SendConsoleMessage("***************", client);
|
||||
foreach (Client c in GameMain.Server.ConnectedClients)
|
||||
{
|
||||
GameMain.Server.SendConsoleMessage("- " + c.ID.ToString() + ": " + c.Name + (c.Character != null ? " playing " + c.Character.LogName : "") + ", " + c.Karma, client);
|
||||
}
|
||||
GameMain.Server.SendConsoleMessage("***************", client);
|
||||
});
|
||||
AssignOnExecute("togglekarmatestmode|karmatestmode", (string[] args) =>
|
||||
{
|
||||
if (GameMain.Server?.KarmaManager == null) return;
|
||||
GameMain.Server.KarmaManager.TestMode = !GameMain.Server.KarmaManager.TestMode;
|
||||
NewMessage(GameMain.Server.KarmaManager.TestMode ? "Karma test mode enabled." : "Karma test mode disabled.", Color.LightGreen);
|
||||
});
|
||||
|
||||
AssignOnExecute("banip", (string[] args) =>
|
||||
{
|
||||
@@ -989,6 +1084,16 @@ namespace Barotrauma
|
||||
};
|
||||
}));
|
||||
|
||||
|
||||
AssignOnExecute("respawnnow", (string[] args) =>
|
||||
{
|
||||
if (GameMain.Server?.RespawnManager == null) { return; }
|
||||
if (GameMain.Server.RespawnManager.CurrentState != RespawnManager.State.Transporting)
|
||||
{
|
||||
GameMain.Server.RespawnManager.ForceRespawn();
|
||||
}
|
||||
});
|
||||
|
||||
commands.Add(new Command("startgame|startround|start", "start/startgame/startround: Start a new round.", (string[] args) =>
|
||||
{
|
||||
if (Screen.Selected == GameMain.GameScreen) return;
|
||||
@@ -1523,7 +1628,11 @@ namespace Barotrauma
|
||||
"showperm",
|
||||
(Client senderClient, Vector2 cursorWorldPos, string[] args) =>
|
||||
{
|
||||
if (args.Length < 2) return;
|
||||
if (args.Length < 1)
|
||||
{
|
||||
GameMain.Server.SendConsoleMessage("showperm [id]: Shows the current administrative permissions of the client with the specified client ID.", senderClient);
|
||||
return;
|
||||
}
|
||||
|
||||
int.TryParse(args[0], out int id);
|
||||
var client = GameMain.Server.ConnectedClients.Find(c => c.ID == id);
|
||||
@@ -1542,10 +1651,8 @@ namespace Barotrauma
|
||||
GameMain.Server.SendConsoleMessage(client.Name + " has the following permissions:", senderClient);
|
||||
foreach (ClientPermissions permission in Enum.GetValues(typeof(ClientPermissions)))
|
||||
{
|
||||
if (permission == ClientPermissions.None || !client.HasPermission(permission)) continue;
|
||||
System.Reflection.FieldInfo fi = typeof(ClientPermissions).GetField(permission.ToString());
|
||||
DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
|
||||
GameMain.Server.SendConsoleMessage(" - " + attributes[0].Description, senderClient);
|
||||
if (permission == ClientPermissions.None || !client.HasPermission(permission)) { continue; }
|
||||
GameMain.Server.SendConsoleMessage(" - " + TextManager.Get("ClientPermission." + permission), senderClient);
|
||||
}
|
||||
if (client.HasPermission(ClientPermissions.ConsoleCommands))
|
||||
{
|
||||
|
||||
@@ -8,6 +8,9 @@ namespace Barotrauma
|
||||
{
|
||||
private bool[] teamDead = new bool[2];
|
||||
|
||||
private bool initialized = false;
|
||||
private int state = 0;
|
||||
|
||||
public override string Description
|
||||
{
|
||||
get
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
partial class Door
|
||||
{
|
||||
partial void SetState(bool open, bool isNetworkMessage, bool sendNetworkMessage)
|
||||
partial void SetState(bool open, bool isNetworkMessage, bool sendNetworkMessage, bool forcedOpen)
|
||||
{
|
||||
if (isStuck || isOpen == open)
|
||||
{
|
||||
@@ -18,7 +18,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
if (sendNetworkMessage)
|
||||
{
|
||||
item.CreateServerEvent(this);
|
||||
GameMain.Server.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.ComponentState, item.GetComponentIndex(this), forcedOpen });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ namespace Barotrauma.Items.Components
|
||||
base.ServerWrite(msg, c, extraData);
|
||||
|
||||
msg.Write(isOpen);
|
||||
msg.Write(extraData.Length == 3 ? (bool)extraData[2] : false); //forced open
|
||||
msg.WriteRangedSingle(stuck, 0.0f, 100.0f, 8);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,5 +7,11 @@ namespace Barotrauma.Items.Components
|
||||
public bool MaintainPos;
|
||||
public bool LevelStartSelected;
|
||||
public bool LevelEndSelected;
|
||||
|
||||
public bool UnsentChanges
|
||||
{
|
||||
get { return unsentChanges; }
|
||||
set { unsentChanges = value; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,12 +5,6 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
partial class Repairable : ItemComponent, IServerSerializable, IClientSerializable
|
||||
{
|
||||
void InitProjSpecific()
|
||||
{
|
||||
//let the clients know the initial deterioration delay
|
||||
item.CreateServerEvent(this);
|
||||
}
|
||||
|
||||
public void ServerRead(ClientNetObject type, NetBuffer msg, Client c)
|
||||
{
|
||||
if (c.Character == null) return;
|
||||
|
||||
@@ -33,6 +33,18 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
List<Wire> clientSideDisconnectedWires = new List<Wire>();
|
||||
ushort disconnectedWireCount = msg.ReadUInt16();
|
||||
for (int i = 0; i < disconnectedWireCount; i++)
|
||||
{
|
||||
ushort wireId = msg.ReadUInt16();
|
||||
if (!(Entity.FindEntityByID(wireId) is Item wireItem)) { continue; }
|
||||
Wire wireComponent = wireItem.GetComponent<Wire>();
|
||||
if (wireComponent == null) { continue; }
|
||||
clientSideDisconnectedWires.Add(wireComponent);
|
||||
}
|
||||
|
||||
//don't allow rewiring locked panels
|
||||
if (Locked || !GameMain.NetworkMember.ServerSettings.AllowRewiring) { return; }
|
||||
|
||||
@@ -47,7 +59,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
//wire not found in any of the connections yet (client is trying to connect a new wire)
|
||||
// -> we need to check if the client has access to it
|
||||
if (!Connections.Any(connection => connection.Wires.Contains(wire)))
|
||||
if (!Connections.Any(connection => connection.Wires.Contains(wire)) && !DisconnectedWires.Contains(wire))
|
||||
{
|
||||
if (!wire.Item.CanClientAccess(c)) { return; }
|
||||
}
|
||||
@@ -75,11 +87,19 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
|
||||
existingWire.RemoveConnection(item);
|
||||
item.GetComponent<ConnectionPanel>()?.DisconnectedWires.Add(existingWire);
|
||||
|
||||
GameMain.Server.KarmaManager.OnWireDisconnected(c.Character, existingWire);
|
||||
|
||||
if (existingWire.Connections[0] == null && existingWire.Connections[1] == null)
|
||||
{
|
||||
GameServer.Log(c.Character.LogName + " disconnected a wire from " +
|
||||
Connections[i].Item.Name + " (" + Connections[i].Name + ")", ServerLog.MessageType.ItemInteraction);
|
||||
|
||||
if (!clientSideDisconnectedWires.Contains(existingWire))
|
||||
{
|
||||
existingWire.Item.Drop(c.Character);
|
||||
}
|
||||
}
|
||||
else if (existingWire.Connections[0] != null)
|
||||
{
|
||||
@@ -89,24 +109,24 @@ namespace Barotrauma.Items.Components
|
||||
//wires that are not in anyone's inventory (i.e. not currently being rewired)
|
||||
//can never be connected to only one connection
|
||||
// -> the client must have dropped the wire from the connection panel
|
||||
if (existingWire.Item.ParentInventory == null && !wires.Any(w => w.Contains(existingWire)))
|
||||
/*if (existingWire.Item.ParentInventory == null && !wires.Any(w => w.Contains(existingWire)))
|
||||
{
|
||||
//let other clients know the item was also disconnected from the other connection
|
||||
existingWire.Connections[0].Item.CreateServerEvent(existingWire.Connections[0].Item.GetComponent<ConnectionPanel>());
|
||||
existingWire.Item.Drop(c.Character);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
else if (existingWire.Connections[1] != null)
|
||||
{
|
||||
GameServer.Log(c.Character.LogName + " disconnected a wire from " +
|
||||
Connections[i].Item.Name + " (" + Connections[i].Name + ") to " + existingWire.Connections[1].Item.Name + " (" + existingWire.Connections[1].Name + ")", ServerLog.MessageType.ItemInteraction);
|
||||
|
||||
if (existingWire.Item.ParentInventory == null && !wires.Any(w => w.Contains(existingWire)))
|
||||
/*if (existingWire.Item.ParentInventory == null && !wires.Any(w => w.Contains(existingWire)))
|
||||
{
|
||||
//let other clients know the item was also disconnected from the other connection
|
||||
existingWire.Connections[1].Item.CreateServerEvent(existingWire.Connections[1].Item.GetComponent<ConnectionPanel>());
|
||||
existingWire.Item.Drop(c.Character);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
Connections[i].SetWire(j, null);
|
||||
@@ -114,6 +134,17 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
foreach (Wire disconnectedWire in DisconnectedWires.ToList())
|
||||
{
|
||||
if (disconnectedWire.Connections[0] == null &&
|
||||
disconnectedWire.Connections[1] == null &&
|
||||
!clientSideDisconnectedWires.Contains(disconnectedWire))
|
||||
{
|
||||
disconnectedWire.Item.Drop(c.Character);
|
||||
GameServer.Log(c.Character.LogName + " dropped " + disconnectedWire.Name, ServerLog.MessageType.Inventory);
|
||||
}
|
||||
}
|
||||
|
||||
//go through new wires
|
||||
for (int i = 0; i < Connections.Count; i++)
|
||||
{
|
||||
|
||||
@@ -186,6 +186,15 @@ namespace Barotrauma
|
||||
case NetEntityEvent.Type.ChangeProperty:
|
||||
ReadPropertyChange(msg, true, c);
|
||||
break;
|
||||
case NetEntityEvent.Type.Combine:
|
||||
UInt16 combineTargetID = msg.ReadUInt16();
|
||||
Item combineTarget = FindEntityByID(combineTargetID) as Item;
|
||||
if (combineTarget == null || !c.Character.CanInteractWith(this) || !c.Character.CanInteractWith(combineTarget))
|
||||
{
|
||||
return;
|
||||
}
|
||||
Combine(combineTarget);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,24 +5,9 @@ namespace Barotrauma
|
||||
{
|
||||
partial class Structure : MapEntity, IDamageable, IServerSerializable, ISerializableEntity
|
||||
{
|
||||
partial void AdjustKarma(IDamageable attacker, float amount)
|
||||
partial void OnHealthChangedProjSpecific(Character attacker, float damageAmount)
|
||||
{
|
||||
if (GameMain.Server != null)
|
||||
{
|
||||
if (Submarine == null) return;
|
||||
if (attacker == null) return;
|
||||
if (attacker is Character attackerCharacter)
|
||||
{
|
||||
Client attackerClient = GameMain.Server.ConnectedClients.Find(c => c.Character == attackerCharacter);
|
||||
if (attackerClient != null)
|
||||
{
|
||||
if (attackerCharacter.TeamID == Submarine.TeamID)
|
||||
{
|
||||
attackerClient.Karma -= amount * 0.001f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
GameMain.Server.KarmaManager.OnStructureHealthChanged(this, attacker, damageAmount);
|
||||
}
|
||||
|
||||
public void ServerWrite(NetBuffer msg, Client c, object[] extraData = null)
|
||||
|
||||
@@ -83,8 +83,9 @@ namespace Barotrauma.Networking
|
||||
|
||||
if (similarity + c.ChatSpamSpeed > 5.0f && !isOwner)
|
||||
{
|
||||
c.ChatSpamCount++;
|
||||
GameMain.Server.KarmaManager.OnSpamFilterTriggered(c);
|
||||
|
||||
c.ChatSpamCount++;
|
||||
if (c.ChatSpamCount > 3)
|
||||
{
|
||||
//kick for spamming too much
|
||||
|
||||
@@ -65,20 +65,19 @@ namespace Barotrauma.Networking
|
||||
|
||||
public bool SpectateOnly;
|
||||
|
||||
private float karma = 1.0f;
|
||||
private float karma = 100.0f;
|
||||
public float Karma
|
||||
{
|
||||
get
|
||||
{
|
||||
if (GameMain.Server == null) return 1.0f;
|
||||
if (!GameMain.Server.ServerSettings.KarmaEnabled) return 1.0f;
|
||||
if (GameMain.Server == null || !GameMain.Server.ServerSettings.KarmaEnabled) { return 100.0f; }
|
||||
if (HasPermission(ClientPermissions.KarmaImmunity)) { return 100.0f; }
|
||||
return karma;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (GameMain.Server == null) return;
|
||||
if (!GameMain.Server.ServerSettings.KarmaEnabled) return;
|
||||
karma = Math.Min(Math.Max(value, 0.0f), 1.0f);
|
||||
if (GameMain.Server == null || !GameMain.Server.ServerSettings.KarmaEnabled) { return; }
|
||||
karma = Math.Min(Math.Max(value, 0.0f), 100.0f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
get { return entityEventManager; }
|
||||
}
|
||||
|
||||
|
||||
public TimeSpan UpdateInterval
|
||||
{
|
||||
get { return updateInterval; }
|
||||
@@ -109,7 +109,6 @@ namespace Barotrauma.Networking
|
||||
LastClientListUpdateID = 0;
|
||||
|
||||
NetPeerConfiguration = new NetPeerConfiguration("barotrauma");
|
||||
|
||||
NetPeerConfiguration.Port = port;
|
||||
Port = port;
|
||||
QueryPort = queryPort;
|
||||
@@ -119,12 +118,12 @@ namespace Barotrauma.Networking
|
||||
NetPeerConfiguration.EnableUPnP = true;
|
||||
}
|
||||
|
||||
serverSettings = new ServerSettings(name, port, queryPort, maxPlayers, isPublic, attemptUPnP);
|
||||
serverSettings = new ServerSettings(this, name, port, queryPort, maxPlayers, isPublic, attemptUPnP);
|
||||
if (!string.IsNullOrEmpty(password))
|
||||
{
|
||||
serverSettings.SetPassword(password);
|
||||
}
|
||||
|
||||
|
||||
NetPeerConfiguration.MaximumConnections = maxPlayers * 2; //double the lidgren connections for unauthenticated players
|
||||
|
||||
NetPeerConfiguration.DisableMessageType(NetIncomingMessageType.DebugMessage |
|
||||
@@ -353,6 +352,7 @@ namespace Barotrauma.Networking
|
||||
unauthenticatedClients.RemoveAll(uc => uc.AuthTimer <= 0.0f);
|
||||
|
||||
fileSender.Update(deltaTime);
|
||||
KarmaManager.UpdateClients(ConnectedClients, deltaTime);
|
||||
|
||||
if (serverSettings.VoiceChatEnabled)
|
||||
{
|
||||
@@ -361,7 +361,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
if (gameStarted)
|
||||
{
|
||||
if (respawnManager != null) respawnManager.Update(deltaTime);
|
||||
if (respawnManager != null) { respawnManager.Update(deltaTime); }
|
||||
|
||||
entityEventManager.Update(connectedClients);
|
||||
|
||||
@@ -415,25 +415,32 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
}
|
||||
|
||||
if (isCrewDead && respawnManager == null)
|
||||
float endRoundDelay = 1.0f;
|
||||
if (serverSettings.AutoRestart && isCrewDead)
|
||||
{
|
||||
endRoundDelay = 5.0f;
|
||||
endRoundTimer += deltaTime;
|
||||
}
|
||||
else if (serverSettings.EndRoundAtLevelEnd && subAtLevelEnd)
|
||||
{
|
||||
endRoundDelay = 5.0f;
|
||||
endRoundTimer += deltaTime;
|
||||
}
|
||||
else if (isCrewDead && respawnManager == null)
|
||||
{
|
||||
if (endRoundTimer <= 0.0f)
|
||||
{
|
||||
SendChatMessage(TextManager.GetWithVariable("CrewDeadNoRespawns", "[time]", "60"), ChatMessageType.Server);
|
||||
}
|
||||
endRoundDelay = 60.0f;
|
||||
endRoundTimer += deltaTime;
|
||||
}
|
||||
else
|
||||
{
|
||||
endRoundTimer = 0.0f;
|
||||
}
|
||||
|
||||
//restart if all characters are dead or submarine is at the end of the level
|
||||
if ((serverSettings.AutoRestart && isCrewDead)
|
||||
||
|
||||
(serverSettings.EndRoundAtLevelEnd && subAtLevelEnd)
|
||||
||
|
||||
(isCrewDead && respawnManager == null && endRoundTimer >= 60.0f))
|
||||
|
||||
if (endRoundTimer >= endRoundDelay)
|
||||
{
|
||||
if (serverSettings.AutoRestart && isCrewDead)
|
||||
{
|
||||
@@ -1029,6 +1036,9 @@ namespace Barotrauma.Networking
|
||||
case ClientNetObject.VOTE:
|
||||
serverSettings.Voting.ServerRead(inc, c);
|
||||
break;
|
||||
case ClientNetObject.SPECTATING_POS:
|
||||
c.SpectatePos = new Vector2(inc.ReadFloat(), inc.ReadFloat());
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
@@ -1346,11 +1356,20 @@ namespace Barotrauma.Networking
|
||||
foreach (Character character in Character.CharacterList)
|
||||
{
|
||||
if (!character.Enabled) continue;
|
||||
if (c.Character != null &&
|
||||
Vector2.DistanceSquared(character.WorldPosition, c.Character.WorldPosition) >=
|
||||
NetConfig.DisableCharacterDistSqr)
|
||||
|
||||
if (c.SpectatePos == null)
|
||||
{
|
||||
continue;
|
||||
if (c.Character != null && Vector2.DistanceSquared(character.WorldPosition, c.Character.WorldPosition) >= NetConfig.DisableCharacterDistSqr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Vector2.DistanceSquared(character.WorldPosition, c.SpectatePos.Value) >= NetConfig.DisableCharacterDistSqr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
float updateInterval = character.GetPositionUpdateInterval(c);
|
||||
@@ -2005,8 +2024,16 @@ namespace Barotrauma.Networking
|
||||
|
||||
public void EndGame()
|
||||
{
|
||||
if (!gameStarted) return;
|
||||
Log("Ending the round...", ServerLog.MessageType.ServerMessage);
|
||||
if (!gameStarted) { return; }
|
||||
if (GameSettings.VerboseLogging)
|
||||
{
|
||||
Log("Ending the round...\n" + Environment.StackTrace, ServerLog.MessageType.ServerMessage);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
Log("Ending the round...", ServerLog.MessageType.ServerMessage);
|
||||
}
|
||||
|
||||
string endMessage = "The round has ended." + '\n';
|
||||
|
||||
@@ -2068,31 +2095,14 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
}
|
||||
|
||||
CoroutineManager.StartCoroutine(EndCinematic(), "EndCinematic");
|
||||
|
||||
GameMain.NetLobbyScreen.RandomizeSettings();
|
||||
}
|
||||
|
||||
public IEnumerable<object> EndCinematic()
|
||||
{
|
||||
float endPreviewLength = 10.0f;
|
||||
|
||||
var cinematic = new RoundEndCinematic(Submarine.MainSub, GameMain.GameScreen.Cam, endPreviewLength);
|
||||
|
||||
do
|
||||
{
|
||||
yield return CoroutineStatus.Running;
|
||||
} while (cinematic.Running);
|
||||
|
||||
Submarine.Unload();
|
||||
entityEventManager.Clear();
|
||||
|
||||
GameMain.NetLobbyScreen.Select();
|
||||
Log("Round ended.", ServerLog.MessageType.ServerMessage);
|
||||
|
||||
yield return CoroutineStatus.Success;
|
||||
GameMain.NetLobbyScreen.RandomizeSettings();
|
||||
}
|
||||
|
||||
|
||||
public override void AddChatMessage(ChatMessage message)
|
||||
{
|
||||
if (string.IsNullOrEmpty(message.Text)) { return; }
|
||||
@@ -2257,6 +2267,7 @@ namespace Barotrauma.Networking
|
||||
previousPlayers.Add(previousPlayer);
|
||||
}
|
||||
previousPlayer.Name = client.Name;
|
||||
previousPlayer.Karma = client.Karma;
|
||||
previousPlayer.KickVoters.Clear();
|
||||
foreach (Client c in connectedClients)
|
||||
{
|
||||
@@ -2267,6 +2278,8 @@ namespace Barotrauma.Networking
|
||||
client.Dispose();
|
||||
connectedClients.Remove(client);
|
||||
|
||||
KarmaManager.OnClientDisconnected(client);
|
||||
|
||||
UpdateVoteStatus();
|
||||
|
||||
SendChatMessage(msg, ChatMessageType.Server);
|
||||
@@ -3077,6 +3090,7 @@ namespace Barotrauma.Networking
|
||||
public string Name;
|
||||
public string IP;
|
||||
public UInt64 SteamID;
|
||||
public float Karma;
|
||||
public readonly List<Client> KickVoters = new List<Client>();
|
||||
|
||||
public PreviousPlayer(Client c)
|
||||
|
||||
@@ -472,9 +472,10 @@ namespace Barotrauma.Networking
|
||||
unauthClient = null;
|
||||
ConnectedClients.Add(newClient);
|
||||
|
||||
var previousPlayer = previousPlayers.Find(p => p.MatchesClient(newClient));
|
||||
var previousPlayer = previousPlayers.Find(p => p.MatchesClient(newClient));
|
||||
if (previousPlayer != null)
|
||||
{
|
||||
newClient.Karma = previousPlayer.Karma;
|
||||
foreach (Client c in previousPlayer.KickVoters)
|
||||
{
|
||||
if (!connectedClients.Contains(c)) { continue; }
|
||||
|
||||
337
Barotrauma/BarotraumaServer/Source/Networking/KarmaManager.cs
Normal file
337
Barotrauma/BarotraumaServer/Source/Networking/KarmaManager.cs
Normal file
@@ -0,0 +1,337 @@
|
||||
using Barotrauma.Items.Components;
|
||||
using Barotrauma.Networking;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
partial class KarmaManager : ISerializableEntity
|
||||
{
|
||||
private class ClientMemory
|
||||
{
|
||||
public List<Pair<Wire, float>> WireDisconnectTime = new List<Pair<Wire, float>>();
|
||||
|
||||
//the client's karma value when they were last sent a notification about it (e.g. "your karma is very low")
|
||||
public float PreviousNotifiedKarma;
|
||||
|
||||
public float StructureDamageAccumulator;
|
||||
|
||||
private float structureDamagePerSecond;
|
||||
public float StructureDamagePerSecond
|
||||
{
|
||||
get { return Math.Max(StructureDamageAccumulator, structureDamagePerSecond); }
|
||||
set { structureDamagePerSecond = value; }
|
||||
}
|
||||
}
|
||||
|
||||
public bool TestMode = false;
|
||||
|
||||
private readonly Dictionary<Client, ClientMemory> clientMemories = new Dictionary<Client, ClientMemory>();
|
||||
private readonly List<Client> bannedClients = new List<Client>();
|
||||
|
||||
private DateTime perSecondUpdate;
|
||||
|
||||
private double KarmaNotificationTime;
|
||||
|
||||
public void UpdateClients(IEnumerable<Client> clients, float deltaTime)
|
||||
{
|
||||
if (!GameMain.Server.GameStarted) { return; }
|
||||
|
||||
bannedClients.Clear();
|
||||
foreach (Client client in clients)
|
||||
{
|
||||
var clientMemory = GetClientMemory(client);
|
||||
UpdateClient(client, deltaTime);
|
||||
|
||||
if (perSecondUpdate < DateTime.Now)
|
||||
{
|
||||
clientMemory.StructureDamagePerSecond = clientMemory.StructureDamageAccumulator;
|
||||
clientMemory.StructureDamageAccumulator = 0.0f;
|
||||
}
|
||||
}
|
||||
if (perSecondUpdate < DateTime.Now)
|
||||
{
|
||||
perSecondUpdate = DateTime.Now + new TimeSpan(0, 0, 1);
|
||||
}
|
||||
|
||||
if (TestMode || Timing.TotalTime > KarmaNotificationTime)
|
||||
{
|
||||
foreach (Client client in clients)
|
||||
{
|
||||
SendKarmaNotifications(client);
|
||||
}
|
||||
KarmaNotificationTime = Timing.TotalTime + KarmaNotificationInterval;
|
||||
}
|
||||
|
||||
foreach (Client bannedClient in bannedClients)
|
||||
{
|
||||
GameMain.Server.BanClient(bannedClient, $"KarmaBanned~[banthreshold]={(int)KickBanThreshold}", duration: TimeSpan.FromSeconds(GameMain.Server.ServerSettings.AutoBanTime));
|
||||
}
|
||||
}
|
||||
|
||||
private void SendKarmaNotifications(Client client, string debugKarmaChangeReason = "")
|
||||
{
|
||||
var clientMemory = GetClientMemory(client);
|
||||
float karmaChange = client.Karma - clientMemory.PreviousNotifiedKarma;
|
||||
if (Math.Abs(karmaChange) > KarmaNotificationInterval || (TestMode && Math.Abs(karmaChange) > 2.0f))
|
||||
{
|
||||
if (TestMode)
|
||||
{
|
||||
string msg =
|
||||
karmaChange < 0 ? $"You karma has decreased to {client.Karma}" : $"You karma has increased to {client.Karma}";
|
||||
if (!string.IsNullOrEmpty(debugKarmaChangeReason))
|
||||
{
|
||||
msg += $". Reason: {debugKarmaChangeReason}";
|
||||
}
|
||||
GameMain.Server.SendDirectChatMessage(msg, client);
|
||||
}
|
||||
else if (Math.Abs(KickBanThreshold - client.Karma) < KarmaNotificationInterval)
|
||||
{
|
||||
GameMain.Server.SendDirectChatMessage(TextManager.Get("KarmaBanWarning"), client);
|
||||
}
|
||||
else
|
||||
{
|
||||
GameMain.Server.SendDirectChatMessage(TextManager.Get(karmaChange < 0 ? "KarmaDecreasedUnknownAmount" : "KarmaIncreasedUnknownAmount"), client);
|
||||
}
|
||||
clientMemory.PreviousNotifiedKarma = client.Karma;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateClient(Client client, float deltaTime)
|
||||
{
|
||||
if (client.Karma > KarmaDecayThreshold)
|
||||
{
|
||||
client.Karma -= KarmaDecay * deltaTime;
|
||||
}
|
||||
else if (client.Karma < KarmaIncreaseThreshold)
|
||||
{
|
||||
client.Karma += KarmaIncrease * deltaTime;
|
||||
}
|
||||
|
||||
if (client.Character != null && !client.Character.Removed)
|
||||
{
|
||||
//increase the strength of the herpes affliction in steps instead of linearly
|
||||
//otherwise clients could determine their exact karma value from the strength
|
||||
float herpesStrength = 0.0f;
|
||||
if (client.Karma < 20)
|
||||
herpesStrength = 100.0f;
|
||||
else if (client.Karma < 30)
|
||||
herpesStrength = 60.0f;
|
||||
else if (client.Karma < 40.0f)
|
||||
herpesStrength = 30.0f;
|
||||
|
||||
var existingAffliction = client.Character.CharacterHealth.GetAffliction<AfflictionSpaceHerpes>("spaceherpes");
|
||||
if (existingAffliction == null && herpesStrength > 0.0f)
|
||||
{
|
||||
client.Character.CharacterHealth.ApplyAffliction(null, new Affliction(herpesAffliction, herpesStrength));
|
||||
}
|
||||
else if (existingAffliction != null)
|
||||
{
|
||||
existingAffliction.Strength = herpesStrength;
|
||||
}
|
||||
|
||||
//check if the client has disconnected an excessive number of wires
|
||||
var clientMemory = GetClientMemory(client);
|
||||
if (clientMemory.WireDisconnectTime.Count > (int)AllowedWireDisconnectionsPerMinute)
|
||||
{
|
||||
clientMemory.WireDisconnectTime.RemoveRange(0, clientMemory.WireDisconnectTime.Count - (int)AllowedWireDisconnectionsPerMinute);
|
||||
if (clientMemory.WireDisconnectTime.All(w => Timing.TotalTime - w.Second < 60.0f))
|
||||
{
|
||||
float karmaDecrease = -WireDisconnectionKarmaDecrease;
|
||||
//engineers don't lose as much karma for removing lots of wires
|
||||
if (client.Character.Info?.Job.Prefab.Identifier == "engineer") { karmaDecrease *= 0.5f; }
|
||||
AdjustKarma(client.Character, karmaDecrease, "Disconnected excessive number of wires");
|
||||
}
|
||||
}
|
||||
|
||||
if (client.Character?.Info?.Job.Prefab.Identifier == "captain" && client.Character.SelectedConstruction != null)
|
||||
{
|
||||
if (client.Character.SelectedConstruction.GetComponent<Steering>() != null)
|
||||
{
|
||||
AdjustKarma(client.Character, SteerSubKarmaIncrease * deltaTime, "Steering the sub");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (client.Karma < KickBanThreshold && client.Connection != GameMain.Server.OwnerConnection)
|
||||
{
|
||||
if (TestMode)
|
||||
{
|
||||
client.Karma = 50.0f;
|
||||
GameMain.Server.SendDirectChatMessage("BANNED! (not really because karma test mode is enabled)", client);
|
||||
}
|
||||
else
|
||||
{
|
||||
bannedClients.Add(client);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void OnClientDisconnected(Client client)
|
||||
{
|
||||
clientMemories.Remove(client);
|
||||
}
|
||||
|
||||
public void OnCharacterHealthChanged(Character target, Character attacker, float damage, IEnumerable<Affliction> appliedAfflictions = null)
|
||||
{
|
||||
if (target == null || attacker == null) { return; }
|
||||
if (target == attacker) { return; }
|
||||
|
||||
//damaging dead characters doesn't affect karma
|
||||
if (target.IsDead || target.Removed) { return; }
|
||||
|
||||
bool isEnemy = target.AIController is EnemyAIController || target.TeamID != attacker.TeamID;
|
||||
if (GameMain.Server.TraitorManager != null)
|
||||
{
|
||||
if (GameMain.Server.TraitorManager.TraitorList.Any(t => t.Character == target))
|
||||
{
|
||||
//traitors always count as enemies
|
||||
isEnemy = true;
|
||||
}
|
||||
if (GameMain.Server.TraitorManager.TraitorList.Any(t => t.Character == attacker && t.TargetCharacter == target))
|
||||
{
|
||||
//target counts as an enemy to the traitor
|
||||
isEnemy = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (appliedAfflictions != null)
|
||||
{
|
||||
foreach (Affliction affliction in appliedAfflictions)
|
||||
{
|
||||
if (MathUtils.NearlyEqual(affliction.Prefab.KarmaChangeOnApplied, 0.0f)) { continue; }
|
||||
damage -= affliction.Prefab.KarmaChangeOnApplied * affliction.Strength;
|
||||
}
|
||||
}
|
||||
|
||||
if (target.AIController is EnemyAIController || target.TeamID != attacker.TeamID)
|
||||
{
|
||||
if (damage > 0)
|
||||
{
|
||||
float karmaIncrease = damage * DamageEnemyKarmaIncrease;
|
||||
if (attacker?.Info?.Job.Prefab.Identifier == "securityofficer") { karmaIncrease *= 2.0f; }
|
||||
AdjustKarma(attacker, karmaIncrease, "Damaged enemy");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (damage > 0)
|
||||
{
|
||||
AdjustKarma(attacker, -damage * DamageFriendlyKarmaDecrease, "Damaged friendly");
|
||||
}
|
||||
else
|
||||
{
|
||||
float karmaIncrease = -damage * HealFriendlyKarmaIncrease;
|
||||
if (attacker?.Info?.Job.Prefab.Identifier == "medicaldoctor") { karmaIncrease *= 2.0f; }
|
||||
AdjustKarma(attacker, karmaIncrease, "Healed friendly");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void OnStructureHealthChanged(Structure structure, Character attacker, float damageAmount)
|
||||
{
|
||||
if (attacker == null) { return; }
|
||||
//damaging/repairing ruin structures or enemy subs doesn't affect karma
|
||||
if (structure.Submarine == null || structure.Submarine.TeamID != attacker.TeamID)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (damageAmount > 0)
|
||||
{
|
||||
if (StructureDamageKarmaDecrease <= 0.0f) { return; }
|
||||
Client client = GameMain.Server.ConnectedClients.Find(c => c.Character == attacker);
|
||||
if (client != null)
|
||||
{
|
||||
//cap the damage so the karma can't decrease by more than MaxStructureDamageKarmaDecreasePerSecond per second
|
||||
var clientMemory = GetClientMemory(client);
|
||||
clientMemory.StructureDamageAccumulator += damageAmount;
|
||||
if (clientMemory.StructureDamagePerSecond + damageAmount >= MaxStructureDamageKarmaDecreasePerSecond / StructureDamageKarmaDecrease)
|
||||
{
|
||||
damageAmount -= (MaxStructureDamageKarmaDecreasePerSecond / StructureDamageKarmaDecrease) - clientMemory.StructureDamagePerSecond;
|
||||
if (damageAmount <= 0.0f) { return; }
|
||||
}
|
||||
}
|
||||
AdjustKarma(attacker, -damageAmount * StructureDamageKarmaDecrease, "Damaged structures");
|
||||
}
|
||||
else
|
||||
{
|
||||
float karmaIncrease = -damageAmount * StructureRepairKarmaIncrease;
|
||||
//mechanics get twice as much karma for repairing walls
|
||||
if (attacker.Info?.Job.Prefab.Identifier == "mechanic") { karmaIncrease *= 2.0f; }
|
||||
AdjustKarma(attacker, karmaIncrease, "Repaired structures");
|
||||
}
|
||||
}
|
||||
|
||||
public void OnItemRepaired(Character character, Repairable repairable, float repairAmount)
|
||||
{
|
||||
float karmaIncrease = repairAmount * ItemRepairKarmaIncrease;
|
||||
if (repairable.HasRequiredSkills(character)) { karmaIncrease *= 2.0f; }
|
||||
AdjustKarma(character, karmaIncrease, "Repaired item");
|
||||
}
|
||||
|
||||
public void OnReactorOverHeating(Character character, float deltaTime)
|
||||
{
|
||||
AdjustKarma(character, -ReactorOverheatKarmaDecrease * deltaTime, "Caused reactor to overheat");
|
||||
}
|
||||
|
||||
public void OnReactorMeltdown(Character character)
|
||||
{
|
||||
AdjustKarma(character, -ReactorMeltdownKarmaDecrease, "Caused a reactor meltdown");
|
||||
}
|
||||
|
||||
public void OnExtinguishingFire(Character character, float deltaTime)
|
||||
{
|
||||
AdjustKarma(character, ExtinguishFireKarmaIncrease * deltaTime, "Extinguished a fire");
|
||||
}
|
||||
|
||||
public void OnWireDisconnected(Character character, Wire wire)
|
||||
{
|
||||
if (character == null || wire == null) { return; }
|
||||
Client client = GameMain.Server.ConnectedClients.Find(c => c.Character == character);
|
||||
if (client == null) { return; }
|
||||
|
||||
if (!clientMemories.ContainsKey(client)) { clientMemories[client] = new ClientMemory(); }
|
||||
|
||||
clientMemories[client].WireDisconnectTime.RemoveAll(w => w.First == wire);
|
||||
clientMemories[client].WireDisconnectTime.Add(new Pair<Wire, float>(wire, (float)Timing.TotalTime));
|
||||
}
|
||||
|
||||
private ClientMemory GetClientMemory(Client client)
|
||||
{
|
||||
if (!clientMemories.ContainsKey(client))
|
||||
{
|
||||
clientMemories[client] = new ClientMemory()
|
||||
{
|
||||
PreviousNotifiedKarma = client.Karma
|
||||
};
|
||||
}
|
||||
return clientMemories[client];
|
||||
}
|
||||
|
||||
public void OnSpamFilterTriggered(Client client)
|
||||
{
|
||||
if (client != null)
|
||||
{
|
||||
client.Karma -= SpamFilterKarmaDecrease;
|
||||
SendKarmaNotifications(client, "Triggered the spam filter");
|
||||
}
|
||||
}
|
||||
|
||||
private void AdjustKarma(Character target, float amount, string debugKarmaChangeReason = "")
|
||||
{
|
||||
if (target == null) { return; }
|
||||
|
||||
Client client = GameMain.Server.ConnectedClients.Find(c => c.Character == target);
|
||||
if (client == null) { return; }
|
||||
|
||||
client.Karma += amount;
|
||||
if (TestMode)
|
||||
{
|
||||
SendKarmaNotifications(client, debugKarmaChangeReason);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using Barotrauma.Items.Components;
|
||||
using Lidgren.Network;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -53,36 +54,34 @@ namespace Barotrauma.Networking
|
||||
return botsToRespawn;
|
||||
}
|
||||
|
||||
partial void UpdateWaiting(float deltaTime)
|
||||
private bool RespawnPending()
|
||||
{
|
||||
int characterToRespawnCount = GetClientsToRespawn().Count;
|
||||
int totalCharacterCount = GameMain.Server.ConnectedClients.Count;
|
||||
/*if (server.Character != null)
|
||||
{
|
||||
totalCharacterCount++;
|
||||
if (server.Character.IsDead) characterToRespawnCount++;
|
||||
}*/
|
||||
bool startCountdown = (float)characterToRespawnCount >= Math.Max((float)totalCharacterCount * GameMain.Server.ServerSettings.MinRespawnRatio, 1.0f);
|
||||
return (float)characterToRespawnCount >= Math.Max((float)totalCharacterCount * GameMain.Server.ServerSettings.MinRespawnRatio, 1.0f);
|
||||
}
|
||||
|
||||
if (startCountdown != CountdownStarted)
|
||||
partial void UpdateWaiting(float deltaTime)
|
||||
{
|
||||
bool respawnPending = RespawnPending();
|
||||
if (respawnPending != RespawnCountdownStarted)
|
||||
{
|
||||
CountdownStarted = startCountdown;
|
||||
RespawnCountdownStarted = respawnPending;
|
||||
RespawnTime = DateTime.Now + new TimeSpan(0,0,0,0, (int)(GameMain.Server.ServerSettings.RespawnInterval * 1000.0f));
|
||||
GameMain.Server.CreateEntityEvent(this);
|
||||
}
|
||||
|
||||
if (!CountdownStarted) return;
|
||||
if (!RespawnCountdownStarted) { return; }
|
||||
|
||||
respawnTimer -= deltaTime;
|
||||
if (respawnTimer <= 0.0f)
|
||||
if (DateTime.Now > RespawnTime)
|
||||
{
|
||||
respawnTimer = GameMain.Server.ServerSettings.RespawnInterval;
|
||||
|
||||
DispatchShuttle();
|
||||
RespawnCountdownStarted = false;
|
||||
}
|
||||
|
||||
if (respawnShuttle == null) return;
|
||||
if (RespawnShuttle == null) { return; }
|
||||
|
||||
respawnShuttle.Velocity = Vector2.Zero;
|
||||
RespawnShuttle.Velocity = Vector2.Zero;
|
||||
|
||||
if (shuttleSteering != null)
|
||||
{
|
||||
@@ -93,9 +92,9 @@ namespace Barotrauma.Networking
|
||||
|
||||
partial void DispatchShuttle()
|
||||
{
|
||||
if (respawnShuttle != null)
|
||||
if (RespawnShuttle != null)
|
||||
{
|
||||
state = State.Transporting;
|
||||
CurrentState = State.Transporting;
|
||||
GameMain.Server.CreateEntityEvent(this);
|
||||
|
||||
ResetShuttle();
|
||||
@@ -110,11 +109,27 @@ namespace Barotrauma.Networking
|
||||
RespawnCharacters();
|
||||
|
||||
CoroutineManager.StopCoroutines("forcepos");
|
||||
CoroutineManager.StartCoroutine(ForceShuttleToPos(Level.Loaded.StartPosition - Vector2.UnitY * Level.ShaftHeight, 100.0f), "forcepos");
|
||||
Vector2 spawnPos = FindSpawnPos();
|
||||
if (spawnPos.Y > Level.Loaded.Size.Y)
|
||||
{
|
||||
CoroutineManager.StartCoroutine(ForceShuttleToPos(Level.Loaded.StartPosition - Vector2.UnitY * Level.ShaftHeight, 100.0f), "forcepos");
|
||||
}
|
||||
else
|
||||
{
|
||||
RespawnShuttle.SetPosition(spawnPos);
|
||||
RespawnShuttle.Velocity = Vector2.Zero;
|
||||
if (shuttleSteering != null)
|
||||
{
|
||||
shuttleSteering.AutoPilot = true;
|
||||
shuttleSteering.MaintainPos = true;
|
||||
shuttleSteering.PosToMaintain = RespawnShuttle.WorldPosition;
|
||||
shuttleSteering.UnsentChanges = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
state = State.Waiting;
|
||||
CurrentState = State.Waiting;
|
||||
GameServer.Log("Respawning everyone in main sub.", ServerLog.MessageType.Spawning);
|
||||
GameMain.Server.CreateEntityEvent(this);
|
||||
|
||||
@@ -129,18 +144,18 @@ namespace Barotrauma.Networking
|
||||
if (door.IsOpen) door.TrySetState(false, false, true);
|
||||
}
|
||||
|
||||
var shuttleGaps = Gap.GapList.FindAll(g => g.Submarine == respawnShuttle && g.ConnectedWall != null);
|
||||
var shuttleGaps = Gap.GapList.FindAll(g => g.Submarine == RespawnShuttle && g.ConnectedWall != null);
|
||||
shuttleGaps.ForEach(g => Spawner.AddToRemoveQueue(g));
|
||||
|
||||
var dockingPorts = Item.ItemList.FindAll(i => i.Submarine == respawnShuttle && i.GetComponent<DockingPort>() != null);
|
||||
var dockingPorts = Item.ItemList.FindAll(i => i.Submarine == RespawnShuttle && i.GetComponent<DockingPort>() != null);
|
||||
dockingPorts.ForEach(d => d.GetComponent<DockingPort>().Undock());
|
||||
|
||||
//shuttle has returned if the path has been traversed or the shuttle is close enough to the exit
|
||||
if (!CoroutineManager.IsCoroutineRunning("forcepos"))
|
||||
{
|
||||
if ((shuttleSteering?.SteeringPath != null && shuttleSteering.SteeringPath.Finished)
|
||||
|| (respawnShuttle.WorldPosition.Y + respawnShuttle.Borders.Y > Level.Loaded.StartPosition.Y - Level.ShaftHeight &&
|
||||
Math.Abs(Level.Loaded.StartPosition.X - respawnShuttle.WorldPosition.X) < 1000.0f))
|
||||
|| (RespawnShuttle.WorldPosition.Y + RespawnShuttle.Borders.Y > Level.Loaded.StartPosition.Y - Level.ShaftHeight &&
|
||||
Math.Abs(Level.Loaded.StartPosition.X - RespawnShuttle.WorldPosition.X) < 1000.0f))
|
||||
{
|
||||
CoroutineManager.StopCoroutines("forcepos");
|
||||
CoroutineManager.StartCoroutine(
|
||||
@@ -149,46 +164,60 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
}
|
||||
|
||||
if (respawnShuttle.WorldPosition.Y > Level.Loaded.Size.Y || shuttleReturnTimer <= 0.0f)
|
||||
if (RespawnShuttle.WorldPosition.Y > Level.Loaded.Size.Y || DateTime.Now > despawnTime)
|
||||
{
|
||||
CoroutineManager.StopCoroutines("forcepos");
|
||||
|
||||
ResetShuttle();
|
||||
|
||||
state = State.Waiting;
|
||||
CurrentState = State.Waiting;
|
||||
GameServer.Log("The respawn shuttle has left.", ServerLog.MessageType.Spawning);
|
||||
GameMain.Server.CreateEntityEvent(this);
|
||||
|
||||
respawnTimer = GameMain.Server.ServerSettings.RespawnInterval;
|
||||
CountdownStarted = false;
|
||||
RespawnCountdownStarted = false;
|
||||
}
|
||||
}
|
||||
|
||||
partial void UpdateTransportingProjSpecific(float deltaTime)
|
||||
{
|
||||
//if there are no living chracters inside, transporting can be stopped immediately
|
||||
if (!Character.CharacterList.Any(c => c.Submarine == respawnShuttle && !c.IsDead))
|
||||
|
||||
if (!ReturnCountdownStarted)
|
||||
{
|
||||
shuttleTransportTimer = 0.0f;
|
||||
//if there are no living chracters inside, transporting can be stopped immediately
|
||||
if (!Character.CharacterList.Any(c => c.Submarine == RespawnShuttle && !c.IsDead))
|
||||
{
|
||||
ReturnTime = DateTime.Now;
|
||||
ReturnCountdownStarted = true;
|
||||
}
|
||||
else if (!RespawnPending())
|
||||
{
|
||||
//don't start counting down until someone else needs to respawn
|
||||
ReturnTime = DateTime.Now + new TimeSpan(0, 0, 0, 0, milliseconds: (int)(maxTransportTime * 1000));
|
||||
despawnTime = ReturnTime + new TimeSpan(0, 0, seconds: 30);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
ReturnCountdownStarted = true;
|
||||
GameMain.Server.CreateEntityEvent(this);
|
||||
}
|
||||
}
|
||||
|
||||
if (shuttleTransportTimer <= 0.0f)
|
||||
if (DateTime.Now > ReturnTime)
|
||||
{
|
||||
GameServer.Log("The respawn shuttle is leaving.", ServerLog.MessageType.ServerMessage);
|
||||
state = State.Returning;
|
||||
CurrentState = State.Returning;
|
||||
|
||||
GameMain.Server.CreateEntityEvent(this);
|
||||
|
||||
CountdownStarted = false;
|
||||
RespawnCountdownStarted = false;
|
||||
maxTransportTime = GameMain.Server.ServerSettings.MaxTransportTime;
|
||||
shuttleReturnTimer = maxTransportTime;
|
||||
shuttleTransportTimer = maxTransportTime;
|
||||
}
|
||||
}
|
||||
|
||||
partial void RespawnCharactersProjSpecific()
|
||||
{
|
||||
var respawnSub = respawnShuttle ?? Submarine.MainSub;
|
||||
var respawnSub = RespawnShuttle ?? Submarine.MainSub;
|
||||
|
||||
var clients = GetClientsToRespawn();
|
||||
foreach (Client c in clients)
|
||||
@@ -250,7 +279,7 @@ namespace Barotrauma.Networking
|
||||
GameServer.Log(string.Format("Respawning {0} ({1}) as {2}", clients[i].Name, clients[i].Connection?.RemoteEndPoint?.Address, characterInfos[i].Job.Name), ServerLog.MessageType.Spawning);
|
||||
}
|
||||
|
||||
if (divingSuitPrefab != null && oxyPrefab != null && respawnShuttle != null)
|
||||
if (divingSuitPrefab != null && oxyPrefab != null && RespawnShuttle != null)
|
||||
{
|
||||
Vector2 pos = cargoSp == null ? character.Position : cargoSp.Position;
|
||||
if (divingSuitPrefab != null && oxyPrefab != null)
|
||||
@@ -295,5 +324,27 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ServerWrite(NetBuffer msg, Client c, object[] extraData = null)
|
||||
{
|
||||
msg.WriteRangedInteger(0, Enum.GetNames(typeof(State)).Length, (int)CurrentState);
|
||||
|
||||
switch (CurrentState)
|
||||
{
|
||||
case State.Transporting:
|
||||
msg.Write(ReturnCountdownStarted);
|
||||
msg.Write(GameMain.Server.ServerSettings.MaxTransportTime);
|
||||
msg.Write((float)(ReturnTime - DateTime.Now).TotalSeconds);
|
||||
break;
|
||||
case State.Waiting:
|
||||
msg.Write(RespawnCountdownStarted);
|
||||
msg.Write((float)(RespawnTime - DateTime.Now).TotalSeconds);
|
||||
break;
|
||||
case State.Returning:
|
||||
break;
|
||||
}
|
||||
|
||||
msg.WritePadBits();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,8 +101,12 @@ namespace Barotrauma.Networking
|
||||
|
||||
if (netProperties.ContainsKey(key))
|
||||
{
|
||||
object prevValue = netProperties[key].Value;
|
||||
netProperties[key].Read(incMsg);
|
||||
GameServer.Log(c.Name + " changed " + netProperties[key].Name + " to " + netProperties[key].Value.ToString(), ServerLog.MessageType.ServerMessage);
|
||||
if (!netProperties[key].PropEquals(prevValue, netProperties[key]))
|
||||
{
|
||||
GameServer.Log(c.Name + " changed " + netProperties[key].Name + " to " + netProperties[key].Value.ToString(), ServerLog.MessageType.ServerMessage);
|
||||
}
|
||||
changed = true;
|
||||
}
|
||||
else
|
||||
@@ -205,6 +209,12 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
doc.Save(writer);
|
||||
}
|
||||
|
||||
if (KarmaPreset == "custom")
|
||||
{
|
||||
GameMain.Server?.KarmaManager?.SaveCustomPreset();
|
||||
}
|
||||
GameMain.Server?.KarmaManager?.Save();
|
||||
}
|
||||
|
||||
private void LoadSettings()
|
||||
@@ -300,9 +310,6 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
if (!MonsterEnabled.ContainsKey(s)) MonsterEnabled.Add(s, true);
|
||||
}
|
||||
|
||||
AutoBanTime = doc.Root.GetAttributeFloat("autobantime", 60);
|
||||
MaxAutoBanTime = doc.Root.GetAttributeFloat("maxautobantime", 360);
|
||||
}
|
||||
|
||||
public void LoadClientPermissions()
|
||||
|
||||
@@ -89,6 +89,17 @@ namespace Barotrauma
|
||||
sb.AppendLine(exception.StackTrace);
|
||||
sb.AppendLine("\n");
|
||||
|
||||
if (exception.InnerException != null)
|
||||
{
|
||||
sb.AppendLine("InnerException: " + exception.InnerException.Message);
|
||||
if (exception.InnerException.TargetSite != null)
|
||||
{
|
||||
sb.AppendLine("Target site: " + exception.InnerException.TargetSite.ToString());
|
||||
}
|
||||
sb.AppendLine("Stack trace: ");
|
||||
sb.AppendLine(exception.InnerException.StackTrace);
|
||||
}
|
||||
|
||||
sb.AppendLine("Last debug messages:");
|
||||
for (int i = DebugConsole.Messages.Count - 1; i > 0 && i > DebugConsole.Messages.Count - 15; i-- )
|
||||
{
|
||||
|
||||
66
Barotrauma/BarotraumaShared/Data/karmasettings.xml
Normal file
66
Barotrauma/BarotraumaShared/Data/karmasettings.xml
Normal file
@@ -0,0 +1,66 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<KarmaManager>
|
||||
<Preset
|
||||
name="Default"
|
||||
karmadecay="0.08"
|
||||
karmadecaythreshold="50"
|
||||
karmaincrease="0.1"
|
||||
karmaincreasethreshold="50"
|
||||
structurerepairkarmaincrease="0.05"
|
||||
structuredamagekarmadecrease="0.1"
|
||||
itemrepairkarmaincrease="0.03"
|
||||
reactoroverheatkarmadecrease="0.5"
|
||||
reactormeltdownkarmadecrease="30"
|
||||
damageenemykarmaincrease="0.1"
|
||||
damagefriendlykarmadecrease="0.2"
|
||||
extinguishfirekarmaincrease="1"
|
||||
allowedwiredisconnectionsperminute="5"
|
||||
wiredisconnectionkarmadecrease="6.0"
|
||||
steersubkarmaincrease="0.15"
|
||||
spamfilterkarmadecrease="15"
|
||||
herpesthreshold="40"
|
||||
kickbanthreshold="1"
|
||||
karmanotificationinterval="10" />
|
||||
<Preset
|
||||
name="Strict"
|
||||
karmadecay="0.08"
|
||||
karmadecaythreshold="50"
|
||||
karmaincrease="0.08"
|
||||
karmaincreasethreshold="45"
|
||||
structurerepairkarmaincrease="0.05"
|
||||
structuredamagekarmadecrease="0.15"
|
||||
itemrepairkarmaincrease="0.03"
|
||||
reactoroverheatkarmadecrease="1.0"
|
||||
reactormeltdownkarmadecrease="35"
|
||||
damageenemykarmaincrease="0.1"
|
||||
damagefriendlykarmadecrease="0.3"
|
||||
extinguishfirekarmaincrease="1"
|
||||
allowedwiredisconnectionsperminute="4"
|
||||
wiredisconnectionkarmadecrease="10.0"
|
||||
steersubkarmaincrease="0.15"
|
||||
spamfilterkarmadecrease="25"
|
||||
herpesthreshold="40"
|
||||
kickbanthreshold="1"
|
||||
karmanotificationinterval="10" />
|
||||
<Preset
|
||||
name="Custom"
|
||||
karmadecay="0.08"
|
||||
karmadecaythreshold="50"
|
||||
karmaincrease="0.1"
|
||||
karmaincreasethreshold="50"
|
||||
structurerepairkarmaincrease="0.05"
|
||||
structuredamagekarmadecrease="0.1"
|
||||
itemrepairkarmaincrease="0.03"
|
||||
reactoroverheatkarmadecrease="0.5"
|
||||
reactormeltdownkarmadecrease="30"
|
||||
damageenemykarmaincrease="0.1"
|
||||
damagefriendlykarmadecrease="0.2"
|
||||
extinguishfirekarmaincrease="1"
|
||||
allowedwiredisconnectionsperminute="5"
|
||||
wiredisconnectionkarmadecrease="6.0"
|
||||
steersubkarmaincrease="0.15"
|
||||
spamfilterkarmadecrease="15"
|
||||
herpesthreshold="40"
|
||||
kickbanthreshold="1"
|
||||
karmanotificationinterval="10" />
|
||||
</KarmaManager>
|
||||
@@ -25,6 +25,7 @@
|
||||
<Command name="kickid"/>
|
||||
<Command name="campaigninfo"/>
|
||||
<Command name="campaigndestination"/>
|
||||
<Command name="respawnnow"/>
|
||||
</Preset>
|
||||
|
||||
<Preset
|
||||
@@ -76,5 +77,6 @@
|
||||
<Command name="power"/>
|
||||
<Command name="oxygen"/>
|
||||
<Command name="setclientcharacter"/>
|
||||
<Command name="respawnnow"/>
|
||||
</Preset>
|
||||
</PermissionPresets>
|
||||
@@ -66,6 +66,7 @@
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Characters\Health\Afflictions\AfflictionHusk.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Characters\Health\Afflictions\AfflictionPrefab.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Characters\Health\Afflictions\AfflictionPsychosis.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Characters\Health\Afflictions\AfflictionSpaceHerpes.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Characters\Health\Buffs\BuffDurationIncrease.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Characters\Health\CharacterHealth.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Characters\Health\DamageModifier.cs" />
|
||||
@@ -226,6 +227,7 @@
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Networking\EntitySpawner.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Networking\FileTransfer\FileTransfer.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Networking\INetSerializable.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Networking\KarmaManager.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Networking\NetBufferExtensions.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Networking\NetConfig.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Networking\NetEntityEvent\NetEntityEvent.cs" />
|
||||
|
||||
@@ -481,6 +481,9 @@
|
||||
<Content Include="$(MSBuildThisFileDirectory)Content\Map\LabelLetters.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="$(MSBuildThisFileDirectory)Content\Map\MapPieces\MapPieces.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="$(MSBuildThisFileDirectory)Content\Map\OpbgMaintenanceBay.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
@@ -683,6 +686,9 @@
|
||||
<Content Include="$(MSBuildThisFileDirectory)Content\UI\tutorialAtlas.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="$(MSBuildThisFileDirectory)Data\karmasettings.xml">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<None Include="$(MSBuildThisFileDirectory)Concentus_LICENSE">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
@@ -1640,54 +1646,6 @@
|
||||
<Content Include="$(MSBuildThisFileDirectory)Content\Map\MapLine.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="$(MSBuildThisFileDirectory)Content\Map\MapPieces\btMAP_Test_01.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="$(MSBuildThisFileDirectory)Content\Map\MapPieces\btMAP_Test_02.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="$(MSBuildThisFileDirectory)Content\Map\MapPieces\btMAP_Test_03.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="$(MSBuildThisFileDirectory)Content\Map\MapPieces\btMAP_Test_04.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="$(MSBuildThisFileDirectory)Content\Map\MapPieces\btMAP_Test_05.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="$(MSBuildThisFileDirectory)Content\Map\MapPieces\btMAP_Test_06.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="$(MSBuildThisFileDirectory)Content\Map\MapPieces\btMAP_Test_07.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="$(MSBuildThisFileDirectory)Content\Map\MapPieces\btMAP_Test_08.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="$(MSBuildThisFileDirectory)Content\Map\MapPieces\btMAP_Test_09.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="$(MSBuildThisFileDirectory)Content\Map\MapPieces\btMAP_Test_10.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="$(MSBuildThisFileDirectory)Content\Map\MapPieces\btMAP_Test_11.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="$(MSBuildThisFileDirectory)Content\Map\MapPieces\btMAP_Test_12.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="$(MSBuildThisFileDirectory)Content\Map\MapPieces\btMAP_Test_13.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="$(MSBuildThisFileDirectory)Content\Map\MapPieces\btMAP_Test_14.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="$(MSBuildThisFileDirectory)Content\Map\MapPieces\btMAP_Test_15.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="$(MSBuildThisFileDirectory)Content\Map\MapPieces\btMAP_Test_16.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="$(MSBuildThisFileDirectory)Content\Map\Reticles.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
@@ -2183,9 +2141,105 @@
|
||||
<None Include="$(MSBuildThisFileDirectory)Content\Items\PowerOnLight3.ogg">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="$(MSBuildThisFileDirectory)Content\Items\Reactor\ReactorOverheatAlarm.ogg">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="$(MSBuildThisFileDirectory)Content\Items\Weapons\ElectricalDischarger.ogg">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="$(MSBuildThisFileDirectory)Content\Items\Weapons\FlameThrowerLoop.ogg">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="$(MSBuildThisFileDirectory)Content\Items\Weapons\FragGrenade40mmShot1.ogg">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="$(MSBuildThisFileDirectory)Content\Items\Weapons\FragGrenade40mmShot2.ogg">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="$(MSBuildThisFileDirectory)Content\Items\Weapons\GrenadeLauncherShot1.ogg">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="$(MSBuildThisFileDirectory)Content\Items\Weapons\GrenadeLauncherShot2.ogg">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="$(MSBuildThisFileDirectory)Content\Items\Weapons\GrenadeLauncherShot3.ogg">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="$(MSBuildThisFileDirectory)Content\Items\Weapons\ShotgunLoad1.ogg">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="$(MSBuildThisFileDirectory)Content\Items\Weapons\ShotgunLoad2.ogg">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="$(MSBuildThisFileDirectory)Content\Items\Weapons\ShotgunLoad3.ogg">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="$(MSBuildThisFileDirectory)Content\Items\Weapons\ShotgunShot1.ogg">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="$(MSBuildThisFileDirectory)Content\Items\Weapons\ShotgunShot2.ogg">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="$(MSBuildThisFileDirectory)Content\Items\Weapons\ShotgunShot3.ogg">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="$(MSBuildThisFileDirectory)Content\Items\Weapons\ShotgunShot4.ogg">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="$(MSBuildThisFileDirectory)Content\Items\Weapons\SMGsingleShot1.ogg">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="$(MSBuildThisFileDirectory)Content\Items\Weapons\SMGsingleShot2.ogg">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="$(MSBuildThisFileDirectory)Content\Items\Weapons\SMGsingleShot3.ogg">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="$(MSBuildThisFileDirectory)Content\Items\Weapons\SMGsingleShot4.ogg">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="$(MSBuildThisFileDirectory)Content\Items\Weapons\SMGsingleShot5.ogg">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="$(MSBuildThisFileDirectory)Content\Items\Weapons\SMGsingleShot6.ogg">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="$(MSBuildThisFileDirectory)Content\Items\Weapons\StunGrenade40mmShot1.ogg">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="$(MSBuildThisFileDirectory)Content\Items\Weapons\StunGrenade40mmShot2.ogg">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="$(MSBuildThisFileDirectory)Content\Items\Weapons\TaserHit1.ogg">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="$(MSBuildThisFileDirectory)Content\Items\Weapons\TaserHit2.ogg">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="$(MSBuildThisFileDirectory)Content\Items\Weapons\TaserShot1.ogg">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="$(MSBuildThisFileDirectory)Content\Items\Weapons\TaserShot2.ogg">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="$(MSBuildThisFileDirectory)Content\Items\Weapons\ToyHammerHit1.ogg">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="$(MSBuildThisFileDirectory)Content\Items\Weapons\ToyHammerHit2.ogg">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="$(MSBuildThisFileDirectory)Content\Items\Weapons\ToyHammerHit3.ogg">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="$(MSBuildThisFileDirectory)Content\Items\Weapons\ToyHammerHit4.ogg">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="$(MSBuildThisFileDirectory)Content\Items\Weapons\ToyHammerHit5.ogg">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="$(MSBuildThisFileDirectory)Content\Items\Weapons\ToyHammerHit6.ogg">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="$(MSBuildThisFileDirectory)Content\Map\Outposts\Outpost2.sub">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
|
||||
@@ -64,6 +64,12 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public float SonarDisruption
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public string SonarLabel;
|
||||
|
||||
public bool Enabled = true;
|
||||
@@ -127,6 +133,7 @@ namespace Barotrauma
|
||||
MaxSightRange = element.GetAttributeFloat("maxsightrange", SightRange);
|
||||
MaxSoundRange = element.GetAttributeFloat("maxsoundrange", SoundRange);
|
||||
FadeOutTime = element.GetAttributeFloat("fadeouttime", FadeOutTime);
|
||||
SonarDisruption = element.GetAttributeFloat("sonardisruption", 0.0f);
|
||||
SonarLabel = element.GetAttributeString("sonarlabel", "");
|
||||
string typeString = element.GetAttributeString("type", "Any");
|
||||
if (Enum.TryParse(typeString, out TargetType t))
|
||||
|
||||
@@ -841,7 +841,7 @@ namespace Barotrauma
|
||||
private Limb GetAttackLimb(Vector2 attackWorldPos, Limb ignoredLimb = null)
|
||||
{
|
||||
AttackContext currentContext = Character.GetAttackContext();
|
||||
var target = wallTarget != null ? wallTarget.Structure : SelectedAiTarget.Entity;
|
||||
var target = wallTarget != null ? wallTarget.Structure : SelectedAiTarget?.Entity;
|
||||
Limb selectedLimb = null;
|
||||
float currentPriority = 0;
|
||||
foreach (Limb limb in Character.AnimController.Limbs)
|
||||
|
||||
@@ -163,7 +163,7 @@ namespace Barotrauma
|
||||
{
|
||||
Weapon = null;
|
||||
}
|
||||
else if (!WeaponComponent.HasRequiredContainedItems(false))
|
||||
else if (!WeaponComponent.HasRequiredContainedItems(character, addMessage: false))
|
||||
{
|
||||
// Seek ammunition only if cannot find a new weapon
|
||||
if (!Reload(!HoldPosition, () => GetWeapon(out _) == null))
|
||||
@@ -234,14 +234,14 @@ namespace Barotrauma
|
||||
{
|
||||
if (component is RangedWeapon rw)
|
||||
{
|
||||
if (ignoreRequiredItems || rw.HasRequiredContainedItems(false))
|
||||
if (ignoreRequiredItems || rw.HasRequiredContainedItems(character, addMessage: false))
|
||||
{
|
||||
weapons.Add(rw);
|
||||
}
|
||||
}
|
||||
else if (component is MeleeWeapon mw)
|
||||
{
|
||||
if (ignoreRequiredItems || mw.HasRequiredContainedItems(false))
|
||||
if (ignoreRequiredItems || mw.HasRequiredContainedItems(character, addMessage: false))
|
||||
{
|
||||
weapons.Add(mw);
|
||||
}
|
||||
@@ -257,7 +257,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (statusEffect.Afflictions.Any())
|
||||
{
|
||||
if (ignoreRequiredItems || component.HasRequiredContainedItems(false))
|
||||
if (ignoreRequiredItems || component.HasRequiredContainedItems(character, addMessage: false))
|
||||
{
|
||||
weapons.Add(component);
|
||||
}
|
||||
@@ -284,7 +284,7 @@ namespace Barotrauma
|
||||
private bool Equip()
|
||||
{
|
||||
if (character.LockHands) { return false; }
|
||||
if (!WeaponComponent.HasRequiredContainedItems(false))
|
||||
if (!WeaponComponent.HasRequiredContainedItems(character, addMessage: false))
|
||||
{
|
||||
Mode = CombatMode.Retreat;
|
||||
return false;
|
||||
@@ -428,7 +428,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
}
|
||||
if (WeaponComponent.HasRequiredContainedItems(false))
|
||||
if (WeaponComponent.HasRequiredContainedItems(character, addMessage: false))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -108,6 +108,7 @@ namespace Barotrauma
|
||||
else
|
||||
{
|
||||
move = false;
|
||||
character.SetInput(extinguisher.Item.IsShootable ? InputType.Shoot : InputType.Use, false, true);
|
||||
extinguisher.Use(deltaTime, character);
|
||||
if (!targetHull.FireSources.Contains(fs))
|
||||
{
|
||||
|
||||
@@ -4,7 +4,6 @@ using System;
|
||||
using System.Linq;
|
||||
using Barotrauma.Extensions;
|
||||
using FarseerPhysics;
|
||||
using Barotrauma.Items.Components;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
|
||||
@@ -207,7 +207,7 @@ namespace Barotrauma
|
||||
bool remove = false;
|
||||
foreach (ItemComponent ic in item.Components)
|
||||
{
|
||||
if (!ic.HasRequiredContainedItems(addMessage: false)) { continue; }
|
||||
if (!ic.HasRequiredContainedItems(user: character, addMessage: false)) { continue; }
|
||||
#if CLIENT
|
||||
ic.PlaySound(ActionType.OnUse, character.WorldPosition, character);
|
||||
#endif
|
||||
|
||||
@@ -50,23 +50,13 @@ namespace Barotrauma
|
||||
|
||||
if (!IsRemotePlayer)
|
||||
{
|
||||
float characterDist = Vector2.DistanceSquared(cam.WorldViewCenter, WorldPosition);
|
||||
#if SERVER
|
||||
float characterDist = float.MaxValue;
|
||||
#if CLIENT
|
||||
characterDist = Vector2.DistanceSquared(cam.GetPosition(), WorldPosition);
|
||||
#elif SERVER
|
||||
if (GameMain.Server != null)
|
||||
{
|
||||
//get the distance from the closest player to this character
|
||||
foreach (Character c in CharacterList)
|
||||
{
|
||||
if (c != this && c.IsRemotePlayer)
|
||||
{
|
||||
float dist = Vector2.DistanceSquared(c.WorldPosition, WorldPosition);
|
||||
if (dist < characterDist)
|
||||
{
|
||||
characterDist = dist;
|
||||
if (characterDist < DisableSimplePhysicsDistSqr) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
characterDist = GetClosestDistance();
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -90,5 +80,50 @@ namespace Barotrauma
|
||||
aiController.Update(deltaTime);
|
||||
}
|
||||
}
|
||||
|
||||
#if SERVER
|
||||
// Gets the closest distance, either an active player character or spectator
|
||||
private float GetClosestDistance()
|
||||
{
|
||||
float minDist = float.MaxValue;
|
||||
|
||||
for (int i = 0; i < GameMain.Server.ConnectedClients.Count; i++)
|
||||
{
|
||||
var spectatePos = GameMain.Server.ConnectedClients[i].SpectatePos;
|
||||
if (spectatePos != null)
|
||||
{
|
||||
float dist = Vector2.DistanceSquared(spectatePos.Value, WorldPosition);
|
||||
|
||||
if (dist < minDist)
|
||||
{
|
||||
minDist = dist;
|
||||
}
|
||||
if (dist < DisableSimplePhysicsDistSqr)
|
||||
{
|
||||
return dist;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (Character c in CharacterList)
|
||||
{
|
||||
if (c != this && c.IsRemotePlayer)
|
||||
{
|
||||
float dist = Vector2.DistanceSquared(c.WorldPosition, WorldPosition);
|
||||
|
||||
if (dist < minDist)
|
||||
{
|
||||
minDist = dist;
|
||||
}
|
||||
if (dist < DisableSimplePhysicsDistSqr)
|
||||
{
|
||||
return dist;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return minDist;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,8 +139,9 @@ namespace Barotrauma
|
||||
Collider.FarseerBody.FixedRotation = false;
|
||||
if (GameMain.NetworkMember == null || !GameMain.NetworkMember.IsClient)
|
||||
{
|
||||
Collider.LinearVelocity = MainLimb.LinearVelocity;
|
||||
Collider.Enabled = false;
|
||||
Collider.FarseerBody.FixedRotation = false;
|
||||
Collider.LinearVelocity = MainLimb.LinearVelocity;
|
||||
Collider.SetTransformIgnoreContacts(MainLimb.SimPosition, MainLimb.Rotation);
|
||||
}
|
||||
if (character.IsDead && deathAnimTimer < deathAnimDuration)
|
||||
|
||||
@@ -286,7 +286,7 @@ namespace Barotrauma
|
||||
var waistJoint = GetJointBetweenLimbs(LimbType.Waist, upperLegType);
|
||||
Vector2 localAnchorWaist = Vector2.Zero;
|
||||
Vector2 localAnchorKnee = Vector2.Zero;
|
||||
if (shoulder != null)
|
||||
if (waistJoint != null)
|
||||
{
|
||||
localAnchorWaist = waistJoint.LimbA.type == upperLegType ? waistJoint.LocalAnchorA : waistJoint.LocalAnchorB;
|
||||
}
|
||||
@@ -298,6 +298,7 @@ namespace Barotrauma
|
||||
upperLegLength = Vector2.Distance(localAnchorWaist, localAnchorKnee);
|
||||
|
||||
LimbJoint ankleJoint = GetJointBetweenLimbs(lowerLegType, footType);
|
||||
if (ankleJoint == null || kneeJoint == null) { return; }
|
||||
lowerLegLength = Vector2.Distance(
|
||||
kneeJoint.LimbA.type == lowerLegType ? kneeJoint.LocalAnchorA : kneeJoint.LocalAnchorB,
|
||||
ankleJoint.LimbA.type == lowerLegType ? ankleJoint.LocalAnchorA : ankleJoint.LocalAnchorB);
|
||||
@@ -537,14 +538,13 @@ namespace Barotrauma
|
||||
|
||||
float limpAmount =
|
||||
character.CharacterHealth.GetAfflictionStrength("damage", leftFoot, true) +
|
||||
character.CharacterHealth.GetAfflictionStrength("damage", rightFoot, true);
|
||||
character.CharacterHealth.GetAfflictionStrength("damage", rightFoot, true) +
|
||||
character.CharacterHealth.GetAfflictionStrength("spaceherpes");
|
||||
limpAmount = MathHelper.Clamp(limpAmount / 100.0f, 0.0f, 1.0f);
|
||||
|
||||
float walkCycleMultiplier = 1.0f;
|
||||
if (Stairs != null)
|
||||
{
|
||||
//TODO: allow editing these values in character editor?
|
||||
bool running = Math.Abs(targetMovement.X) > 2.0f;
|
||||
TargetMovement = new Vector2(MathHelper.Clamp(TargetMovement.X, -1.7f, 1.7f), TargetMovement.Y);
|
||||
walkCycleMultiplier *= 1.5f;
|
||||
}
|
||||
@@ -579,7 +579,7 @@ namespace Barotrauma
|
||||
if (limpAmount > 0.0f)
|
||||
{
|
||||
//make the footpos oscillate when limping
|
||||
footMid += (Math.Max(Math.Abs(walkPosX) * limpAmount, 0.0f) * Math.Min(Math.Abs(TargetMovement.X), 0.3f));
|
||||
footMid += (Math.Max(Math.Abs(walkPosX) * limpAmount, 0.0f) * Math.Min(Math.Abs(TargetMovement.X), 0.3f)) * Dir;
|
||||
}
|
||||
|
||||
movement = overrideTargetMovement == Vector2.Zero ?
|
||||
@@ -663,7 +663,13 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
if (TorsoAngle.HasValue) torso.body.SmoothRotate(TorsoAngle.Value * Dir, 50.0f);
|
||||
if (TorsoAngle.HasValue)
|
||||
{
|
||||
float torsoAngle = TorsoAngle.Value;
|
||||
float herpesStrength = character.CharacterHealth.GetAfflictionStrength("spaceherpes");
|
||||
torsoAngle -= herpesStrength / 150.0f;
|
||||
torso.body.SmoothRotate(torsoAngle * Dir, 50.0f);
|
||||
}
|
||||
if (HeadAngle.HasValue) head.body.SmoothRotate(HeadAngle.Value * Dir, 50.0f);
|
||||
|
||||
if (!onGround)
|
||||
@@ -689,7 +695,6 @@ namespace Barotrauma
|
||||
for (int i = -1; i < 2; i += 2)
|
||||
{
|
||||
Limb foot = i == -1 ? leftFoot : rightFoot;
|
||||
Limb leg = i == -1 ? leftLeg : rightLeg;
|
||||
|
||||
Vector2 footPos = stepSize * -i;
|
||||
footPos += new Vector2(Math.Sign(movement.X) * FootMoveOffset.X, FootMoveOffset.Y);
|
||||
@@ -706,6 +711,15 @@ namespace Barotrauma
|
||||
}
|
||||
footPos.Y = Math.Min(waistPos.Y - colliderPos.Y - 0.4f, footPos.Y);
|
||||
|
||||
#if CLIENT
|
||||
if ((i == 1 && Math.Sign(Math.Sin(WalkPos)) > 0 && Math.Sign(walkPosY) < 0) ||
|
||||
(i == -1 && Math.Sign(Math.Sin(WalkPos)) < 0 && Math.Sign(walkPosY) > 0))
|
||||
{
|
||||
PlayImpactSound(foot);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if (!foot.Disabled)
|
||||
{
|
||||
foot.DebugRefPos = colliderPos;
|
||||
@@ -766,7 +780,6 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
var foot = i == -1 ? rightFoot : leftFoot;
|
||||
Limb leg = i == -1 ? rightLeg : leftLeg;
|
||||
|
||||
if (!foot.Disabled)
|
||||
{
|
||||
|
||||
@@ -96,16 +96,16 @@ namespace Barotrauma
|
||||
public virtual AnimationType AnimationType { get; protected set; }
|
||||
|
||||
public static string GetDefaultFileName(string speciesName, AnimationType animType) => $"{speciesName.CapitaliseFirstInvariant()}{animType.ToString()}";
|
||||
public static string GetDefaultFolder(string speciesName) => $"Content/Characters/{speciesName.CapitaliseFirstInvariant()}/Animations/";
|
||||
public static string GetDefaultFile(string speciesName, AnimationType animType, ContentPackage contentPackage = null) =>
|
||||
$"{GetFolder(speciesName, contentPackage)}{GetDefaultFileName(speciesName, animType)}.xml";
|
||||
|
||||
public static string GetFolder(string speciesName, ContentPackage contentPackage = null)
|
||||
{
|
||||
var folder = XMLExtensions.TryLoadXml(Character.GetConfigFile(speciesName, contentPackage))?.Root?.Element("animations")?.GetAttributeString("folder", string.Empty);
|
||||
string configFilePath = Character.GetConfigFile(speciesName, contentPackage);
|
||||
var folder = XMLExtensions.TryLoadXml(configFilePath)?.Root?.Element("animations")?.GetAttributeString("folder", string.Empty);
|
||||
if (string.IsNullOrEmpty(folder) || folder.ToLowerInvariant() == "default")
|
||||
{
|
||||
folder = GetDefaultFolder(speciesName);
|
||||
folder = Path.Combine(Path.GetDirectoryName(configFilePath), "Animations");
|
||||
}
|
||||
return folder;
|
||||
}
|
||||
|
||||
@@ -66,7 +66,6 @@ namespace Barotrauma
|
||||
.Concat(Joints.Select(j => j as RagdollSubParams)));
|
||||
|
||||
public static string GetDefaultFileName(string speciesName) => $"{speciesName.CapitaliseFirstInvariant()}DefaultRagdoll";
|
||||
public static string GetDefaultFolder(string speciesName) => $"Content/Characters/{speciesName.CapitaliseFirstInvariant()}/Ragdolls/";
|
||||
public static string GetDefaultFile(string speciesName, ContentPackage contentPackage = null) => $"{GetFolder(speciesName, contentPackage)}{GetDefaultFileName(speciesName)}.xml";
|
||||
|
||||
private static readonly object[] dummyParams = new object[]
|
||||
@@ -84,11 +83,11 @@ namespace Barotrauma
|
||||
|
||||
public static string GetFolder(string speciesName, ContentPackage contentPackage = null)
|
||||
{
|
||||
var folder = XMLExtensions.TryLoadXml(Character.GetConfigFile(speciesName, contentPackage))?.Root?.Element("ragdolls")?.GetAttributeString("folder", string.Empty);
|
||||
string configFilePath = Character.GetConfigFile(speciesName, contentPackage);
|
||||
var folder = XMLExtensions.TryLoadXml(configFilePath)?.Root?.Element("ragdolls")?.GetAttributeString("folder", string.Empty);
|
||||
if (string.IsNullOrEmpty(folder) || folder.ToLowerInvariant() == "default")
|
||||
{
|
||||
//DebugConsole.NewMessage("[RagollParams] Using the default folder.");
|
||||
folder = GetDefaultFolder(speciesName);
|
||||
folder = Path.Combine(Path.GetDirectoryName(configFilePath), "Ragdolls") + Path.DirectorySeparatorChar;
|
||||
}
|
||||
return folder;
|
||||
}
|
||||
|
||||
@@ -1047,11 +1047,16 @@ namespace Barotrauma
|
||||
|
||||
protected bool levitatingCollider = true;
|
||||
|
||||
/// <summary>
|
||||
/// How long has the ragdoll stayed motionless
|
||||
/// </summary>
|
||||
private float bodyInRestTimer;
|
||||
|
||||
public bool forceStanding;
|
||||
|
||||
public void Update(float deltaTime, Camera cam)
|
||||
{
|
||||
if (!character.Enabled || Frozen || Invalid) return;
|
||||
if (!character.Enabled || Frozen || Invalid) { return; }
|
||||
|
||||
CheckValidity();
|
||||
|
||||
@@ -1063,6 +1068,8 @@ namespace Barotrauma
|
||||
|
||||
FindHull();
|
||||
PreventOutsideCollision();
|
||||
|
||||
CheckBodyInRest(deltaTime);
|
||||
|
||||
splashSoundTimer -= deltaTime;
|
||||
|
||||
@@ -1315,6 +1322,29 @@ namespace Barotrauma
|
||||
UpdateProjSpecific(deltaTime);
|
||||
}
|
||||
|
||||
private void CheckBodyInRest(float deltaTime)
|
||||
{
|
||||
if (Collider.LinearVelocity.LengthSquared() > 0.01f || character.SelectedBy != null || !character.IsDead)
|
||||
{
|
||||
bodyInRestTimer = 0.0f;
|
||||
foreach (Limb limb in Limbs)
|
||||
{
|
||||
limb.body.PhysEnabled = true;
|
||||
}
|
||||
}
|
||||
else if (Limbs.All(l => l != null && !l.body.Enabled || l.LinearVelocity.LengthSquared() < 0.001f))
|
||||
{
|
||||
bodyInRestTimer += deltaTime;
|
||||
if (bodyInRestTimer > 1.0f)
|
||||
{
|
||||
foreach (Limb limb in Limbs)
|
||||
{
|
||||
limb.body.PhysEnabled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool Invalid { get; private set; }
|
||||
private int validityResets;
|
||||
private bool CheckValidity()
|
||||
|
||||
@@ -298,7 +298,10 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
float afflictionStrength = subElement.GetAttributeFloat(1.0f, "amount", "strength");
|
||||
Afflictions.Add(afflictionPrefab.Instantiate(afflictionStrength));
|
||||
var affliction = afflictionPrefab.Instantiate(afflictionStrength);
|
||||
affliction.ApplyProbability = subElement.GetAttributeFloat("probability", 1.0f);
|
||||
Afflictions.Add(affliction);
|
||||
|
||||
break;
|
||||
case "conditional":
|
||||
foreach (XAttribute attribute in subElement.Attributes())
|
||||
|
||||
@@ -743,31 +743,33 @@ namespace Barotrauma
|
||||
PressureProtection = 100.0f;
|
||||
}
|
||||
|
||||
List<XElement> inventoryElements = new List<XElement>();
|
||||
List<float> inventoryCommonness = new List<float>();
|
||||
List<XElement> healthElements = new List<XElement>();
|
||||
List<float> healthCommonness = new List<float>();
|
||||
foreach (XElement subElement in doc.Root.Elements())
|
||||
{
|
||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||
{
|
||||
case "inventory":
|
||||
Inventory = new CharacterInventory(subElement, this);
|
||||
inventoryElements.Add(subElement);
|
||||
inventoryCommonness.Add(subElement.GetAttributeFloat("commonness", 1.0f));
|
||||
break;
|
||||
case "health":
|
||||
CharacterHealth = new CharacterHealth(subElement, this);
|
||||
healthElements.Add(subElement);
|
||||
healthCommonness.Add(subElement.GetAttributeFloat("commonness", 1.0f));
|
||||
break;
|
||||
case "statuseffect":
|
||||
statusEffects.Add(StatusEffect.Load(subElement, Name));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
List<XElement> healthElements = new List<XElement>();
|
||||
List<float> healthCommonness = new List<float>();
|
||||
foreach (XElement element in doc.Root.Elements())
|
||||
if (inventoryElements.Count > 0)
|
||||
{
|
||||
if (element.Name.ToString().ToLowerInvariant() != "health") continue;
|
||||
healthElements.Add(element);
|
||||
healthCommonness.Add(element.GetAttributeFloat("commonness", 1.0f));
|
||||
Inventory = new CharacterInventory(
|
||||
inventoryElements.Count == 1 ? inventoryElements[0] : ToolBox.SelectWeightedRandom(inventoryElements, inventoryCommonness, random),
|
||||
this);
|
||||
}
|
||||
|
||||
if (healthElements.Count == 0)
|
||||
{
|
||||
CharacterHealth = new CharacterHealth(this);
|
||||
@@ -834,6 +836,7 @@ namespace Barotrauma
|
||||
|
||||
#if CLIENT
|
||||
head.LoadHuskSprite();
|
||||
head.LoadHerpesSprite();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -977,7 +980,30 @@ namespace Barotrauma
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (inputType == InputType.Up || inputType == InputType.Down ||
|
||||
inputType == InputType.Left || inputType == InputType.Right)
|
||||
{
|
||||
var invertControls = CharacterHealth.GetAffliction("invertcontrols");
|
||||
if (invertControls != null)
|
||||
{
|
||||
switch (inputType)
|
||||
{
|
||||
case InputType.Left:
|
||||
inputType = InputType.Right;
|
||||
break;
|
||||
case InputType.Right:
|
||||
inputType = InputType.Left;
|
||||
break;
|
||||
case InputType.Up:
|
||||
inputType = InputType.Down;
|
||||
break;
|
||||
case InputType.Down:
|
||||
inputType = InputType.Up;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return keys[(int)inputType].Held;
|
||||
}
|
||||
|
||||
@@ -1579,9 +1605,16 @@ namespace Barotrauma
|
||||
//locked wires are never interactable
|
||||
if (wire.Locked) return false;
|
||||
|
||||
//wires are interactable if the character has selected either of the items the wire is connected to
|
||||
if (wire.Connections[0]?.Item != null && SelectedConstruction == wire.Connections[0].Item) return true;
|
||||
if (wire.Connections[1]?.Item != null && SelectedConstruction == wire.Connections[1].Item) return true;
|
||||
//wires are interactable if the character has selected an item the wire is connected to,
|
||||
//and it's disconnected from the other end
|
||||
if (wire.Connections[0]?.Item != null && SelectedConstruction == wire.Connections[0].Item)
|
||||
{
|
||||
return wire.Connections[1] == null;
|
||||
}
|
||||
if (wire.Connections[1]?.Item != null && SelectedConstruction == wire.Connections[1].Item)
|
||||
{
|
||||
return wire.Connections[0] == null;
|
||||
}
|
||||
}
|
||||
|
||||
if (checkLinked && item.DisplaySideBySideWhenLinked)
|
||||
@@ -1891,15 +1924,30 @@ namespace Barotrauma
|
||||
distSqr = Math.Min(distSqr, Vector2.DistanceSquared(otherCharacter.WorldPosition, c.WorldPosition));
|
||||
}
|
||||
|
||||
#if SERVER
|
||||
for (int i = 0; i < GameMain.Server.ConnectedClients.Count; i++)
|
||||
{
|
||||
var spectatePos = GameMain.Server.ConnectedClients[i].SpectatePos;
|
||||
if (spectatePos != null)
|
||||
{
|
||||
distSqr = Math.Min(distSqr, Vector2.DistanceSquared(spectatePos.Value, c.WorldPosition));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (distSqr > NetConfig.DisableCharacterDistSqr)
|
||||
{
|
||||
c.Enabled = false;
|
||||
if (c.IsDead && c.AIController is EnemyAIController)
|
||||
{
|
||||
Entity.Spawner?.AddToRemoveQueue(c);
|
||||
}
|
||||
}
|
||||
else if (distSqr < NetConfig.EnableCharacterDistSqr)
|
||||
{
|
||||
c.Enabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (Submarine.MainSub != null)
|
||||
{
|
||||
@@ -1907,19 +1955,22 @@ namespace Barotrauma
|
||||
float distSqr = Vector2.DistanceSquared(Submarine.MainSub.WorldPosition, c.WorldPosition);
|
||||
if (Controlled != null)
|
||||
{
|
||||
distSqr = Math.Min(distSqr, Vector2.DistanceSquared(Controlled.WorldPosition, c.WorldPosition));
|
||||
distSqr = Math.Min(distSqr, Vector2.DistanceSquared(GameMain.GameScreen.Cam.GetPosition(), c.WorldPosition));
|
||||
}
|
||||
|
||||
|
||||
if (distSqr > NetConfig.DisableCharacterDistSqr)
|
||||
{
|
||||
c.Enabled = false;
|
||||
if (c.IsDead && c.AIController is EnemyAIController)
|
||||
{
|
||||
Entity.Spawner?.AddToRemoveQueue(c);
|
||||
}
|
||||
}
|
||||
else if ( distSqr < NetConfig.EnableCharacterDistSqr)
|
||||
else if (distSqr < NetConfig.EnableCharacterDistSqr)
|
||||
{
|
||||
c.Enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2261,8 +2312,6 @@ namespace Barotrauma
|
||||
speechBubbleColor = color;
|
||||
}
|
||||
|
||||
partial void AdjustKarma(Character attacker, AttackResult attackResult);
|
||||
|
||||
partial void DamageHUD(float amount);
|
||||
|
||||
public void SetAllDamage(float damageAmount, float bleedingDamageAmount, float burnDamageAmount)
|
||||
@@ -2358,7 +2407,12 @@ namespace Barotrauma
|
||||
{
|
||||
hitLimb = null;
|
||||
|
||||
if (Removed) return new AttackResult();
|
||||
if (Removed) { return new AttackResult(); }
|
||||
|
||||
if (attacker != null && GameMain.NetworkMember != null && !GameMain.NetworkMember.ServerSettings.AllowFriendlyFire)
|
||||
{
|
||||
if (attacker.TeamID == TeamID) { return new AttackResult(); }
|
||||
}
|
||||
|
||||
float closestDistance = 0.0f;
|
||||
foreach (Limb limb in AnimController.Limbs)
|
||||
@@ -2376,7 +2430,12 @@ namespace Barotrauma
|
||||
|
||||
public AttackResult DamageLimb(Vector2 worldPosition, Limb hitLimb, List<Affliction> afflictions, float stun, bool playSound, float attackImpulse, Character attacker = null)
|
||||
{
|
||||
if (Removed) return new AttackResult();
|
||||
if (Removed) { return new AttackResult(); }
|
||||
|
||||
if (attacker != null && attacker != this && GameMain.NetworkMember != null && !GameMain.NetworkMember.ServerSettings.AllowFriendlyFire)
|
||||
{
|
||||
if (attacker.TeamID == TeamID) { return new AttackResult(); }
|
||||
}
|
||||
|
||||
SetStun(stun);
|
||||
Vector2 dir = hitLimb.WorldPosition - worldPosition;
|
||||
@@ -2395,7 +2454,6 @@ namespace Barotrauma
|
||||
OnAttacked?.Invoke(attacker, attackResult);
|
||||
OnAttackedProjSpecific(attacker, attackResult);
|
||||
};
|
||||
AdjustKarma(attacker, attackResult);
|
||||
|
||||
if (attacker != null && attackResult.Damage > 0.0f)
|
||||
{
|
||||
|
||||
@@ -18,6 +18,11 @@ namespace Barotrauma
|
||||
public float StrengthDiminishMultiplier = 1.0f;
|
||||
public Affliction MultiplierSource;
|
||||
|
||||
/// <summary>
|
||||
/// Probability for the affliction to be applied. Used by attacks.
|
||||
/// </summary>
|
||||
public float ApplyProbability;
|
||||
|
||||
/// <summary>
|
||||
/// Which character gave this affliction
|
||||
/// </summary>
|
||||
@@ -162,6 +167,7 @@ namespace Barotrauma
|
||||
|
||||
foreach (StatusEffect statusEffect in currentEffect.StatusEffects)
|
||||
{
|
||||
statusEffect.SetUser(Source);
|
||||
if (statusEffect.HasTargetType(StatusEffect.TargetType.Character))
|
||||
{
|
||||
statusEffect.Apply(ActionType.OnActive, deltaTime, characterHealth.Character, characterHealth.Character);
|
||||
|
||||
@@ -157,6 +157,9 @@ namespace Barotrauma
|
||||
//how high the strength has to be for the affliction icon to be shown with a health scanner
|
||||
public readonly float ShowInHealthScannerThreshold = 0.05f;
|
||||
|
||||
//how much karma changes when a player applies this affliction to someone (per strength of the affliction)
|
||||
public float KarmaChangeOnApplied;
|
||||
|
||||
public float BurnOverlayAlpha;
|
||||
public float DamageOverlayAlpha;
|
||||
|
||||
@@ -265,9 +268,12 @@ namespace Barotrauma
|
||||
DamageOverlayAlpha = element.GetAttributeFloat("damageoverlayalpha", 0.0f);
|
||||
BurnOverlayAlpha = element.GetAttributeFloat("burnoverlayalpha", 0.0f);
|
||||
|
||||
KarmaChangeOnApplied = element.GetAttributeFloat("karmachangeonapplied", 0.0f);
|
||||
|
||||
CauseOfDeathDescription = TextManager.Get("AfflictionCauseOfDeath." + Identifier, true) ?? element.GetAttributeString("causeofdeathdescription", "");
|
||||
SelfCauseOfDeathDescription = TextManager.Get("AfflictionCauseOfDeathSelf." + Identifier, true) ?? element.GetAttributeString("selfcauseofdeathdescription", "");
|
||||
|
||||
|
||||
AchievementOnRemoved = element.GetAttributeString("achievementonremoved", "");
|
||||
|
||||
foreach (XElement subElement in element.Elements())
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
class AfflictionSpaceHerpes : Affliction
|
||||
{
|
||||
private float invertControlsCooldown = 60.0f;
|
||||
private float stunCoolDown = 60.0f;
|
||||
public AfflictionSpaceHerpes(AfflictionPrefab prefab, float strength) : base(prefab, strength)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Update(CharacterHealth characterHealth, Limb targetLimb, float deltaTime)
|
||||
{
|
||||
base.Update(characterHealth, targetLimb, deltaTime);
|
||||
|
||||
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) { return; }
|
||||
|
||||
invertControlsCooldown -= deltaTime;
|
||||
if (invertControlsCooldown <= 0.0f)
|
||||
{
|
||||
//invert controls every 126-234 seconds when strength is close to 0
|
||||
//every 56-104 seconds when strength is close to 100
|
||||
invertControlsCooldown = (180.0f - Strength) * Rand.Range(0.7f, 1.3f);
|
||||
var invertControlsAffliction = AfflictionPrefab.List.Find(ap => ap.Identifier == "invertcontrols");
|
||||
float invertControlsDuration = MathHelper.Lerp(10.0f, 60.0f, Strength / 100.0f) * Rand.Range(0.7f, 1.3f);
|
||||
characterHealth.ApplyAffliction(null, new Affliction(invertControlsAffliction, invertControlsDuration));
|
||||
}
|
||||
|
||||
if (Strength > 50.0f)
|
||||
{
|
||||
stunCoolDown -= deltaTime;
|
||||
if (stunCoolDown <= 0.0f)
|
||||
{
|
||||
//stun every 126-234 seconds when strength is close to 0
|
||||
//stun 56-104 seconds when strength is close to 100
|
||||
stunCoolDown = (180.0f - Strength) * Rand.Range(0.7f, 1.3f);
|
||||
float stunDuration = MathHelper.Lerp(3.0f, 10.0f, Strength / 100.0f) * Rand.Range(0.7f, 1.3f);
|
||||
characterHealth.Character.SetStun(stunDuration);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -411,7 +411,7 @@ namespace Barotrauma
|
||||
amount -= reduceAmount;
|
||||
}
|
||||
}
|
||||
|
||||
CalculateVitality();
|
||||
}
|
||||
|
||||
public void ApplyDamage(Limb hitLimb, AttackResult attackResult)
|
||||
|
||||
@@ -407,7 +407,7 @@ namespace Barotrauma
|
||||
{
|
||||
List<DamageModifier> appliedDamageModifiers = new List<DamageModifier>();
|
||||
//create a copy of the original affliction list to prevent modifying the afflictions of an Attack/StatusEffect etc
|
||||
afflictions = new List<Affliction>(afflictions);
|
||||
afflictions = new List<Affliction>(afflictions.Where(a => Rand.Range(0.0f, 1.0f) <= a.ApplyProbability));
|
||||
for (int i = 0; i < afflictions.Count; i++)
|
||||
{
|
||||
foreach (DamageModifier damageModifier in damageModifiers)
|
||||
|
||||
@@ -485,6 +485,22 @@ namespace Barotrauma
|
||||
List.Add(package);
|
||||
}
|
||||
}
|
||||
|
||||
public void Delete()
|
||||
{
|
||||
try
|
||||
{
|
||||
File.Delete(Path);
|
||||
GameMain.Config.SelectedContentPackages.Remove(this);
|
||||
GameMain.Config.SaveNewPlayerConfig();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
DebugConsole.ThrowError("Failed to delete content package \"" + Name + "\".", e);
|
||||
return;
|
||||
}
|
||||
List.Remove(this);
|
||||
}
|
||||
}
|
||||
|
||||
public class ContentFile
|
||||
|
||||
@@ -136,7 +136,7 @@ namespace Barotrauma
|
||||
if (!handle.Coroutine.MoveNext()) return;
|
||||
}
|
||||
}
|
||||
catch (ThreadAbortException tae)
|
||||
catch (ThreadAbortException)
|
||||
{
|
||||
//not an error, don't worry about it
|
||||
}
|
||||
|
||||
@@ -110,7 +110,15 @@ namespace Barotrauma
|
||||
|
||||
private static void AssignOnExecute(string names, Action<string[]> onExecute)
|
||||
{
|
||||
commands.First(c => c.names.Intersect(names.Split('|')).Count() > 0).OnExecute = onExecute;
|
||||
var matchingCommand = commands.Find(c => c.names.Intersect(names.Split('|')).Count() > 0);
|
||||
if (matchingCommand == null)
|
||||
{
|
||||
throw new Exception("AssignOnExecute failed. Command matching the name(s) \""+names+"\" not found.");
|
||||
}
|
||||
else
|
||||
{
|
||||
matchingCommand.OnExecute = onExecute;
|
||||
}
|
||||
}
|
||||
|
||||
static DebugConsole()
|
||||
@@ -251,16 +259,11 @@ namespace Barotrauma
|
||||
spawnPosParams.ToArray()
|
||||
};
|
||||
}, isCheat: true));
|
||||
|
||||
|
||||
|
||||
commands.Add(new Command("disablecrewai", "disablecrewai: Disable the AI of the NPCs in the crew.", (string[] args) =>
|
||||
{
|
||||
HumanAIController.DisableCrewAI = true;
|
||||
NewMessage("Crew AI disabled", Color.Red);
|
||||
// This is probably not where it should be?
|
||||
//ThrowError("Karma has not been fully implemented yet, and is disabled in this version of Barotrauma.");
|
||||
/*if (GameMain.Server == null) return;
|
||||
GameMain.Server.KarmaEnabled = !GameMain.Server.KarmaEnabled;*/
|
||||
}));
|
||||
|
||||
commands.Add(new Command("enablecrewai", "enablecrewai: Enable the AI of the NPCs in the crew.", (string[] args) =>
|
||||
@@ -304,8 +307,31 @@ namespace Barotrauma
|
||||
commands.Add(new Command("revokecommandperm", "revokecommandperm [id]: Revokes permission to use the specified console commands from the player with the specified client ID.", null));
|
||||
|
||||
commands.Add(new Command("showperm", "showperm [id]: Shows the current administrative permissions of the client with the specified client ID.", null));
|
||||
|
||||
commands.Add(new Command("respawnnow", "respawnnow: Trigger a respawn immediately if there are any clients waiting to respawn.", null));
|
||||
|
||||
//commands.Add(new Command("togglekarma", "togglekarma: Toggles the karma system.", null));
|
||||
commands.Add(new Command("showkarma", "showkarma: Show the current karma values of the players.", null));
|
||||
commands.Add(new Command("togglekarma", "togglekarma: Toggle the karma system on/off.", null));
|
||||
commands.Add(new Command("resetkarma", "resetkarma [client]: Resets the karma value of the specified client to 100.", null,
|
||||
() =>
|
||||
{
|
||||
if (GameMain.NetworkMember?.ConnectedClients == null) { return null; }
|
||||
return new string[][]
|
||||
{
|
||||
GameMain.NetworkMember.ConnectedClients.Select(c => c.Name).ToArray()
|
||||
};
|
||||
}));
|
||||
commands.Add(new Command("setkarma", "setkarma [client] [0-100]: Sets the karma of the specified client to the specified value.", null,
|
||||
() =>
|
||||
{
|
||||
if (GameMain.NetworkMember?.ConnectedClients == null) { return null; }
|
||||
return new string[][]
|
||||
{
|
||||
GameMain.NetworkMember.ConnectedClients.Select(c => c.Name).ToArray(),
|
||||
new string[] { "50" }
|
||||
};
|
||||
}));
|
||||
commands.Add(new Command("togglekarmatestmode", "togglekarmatestmode: Toggle the karma test mode on/off. When test mode is enabled, clients get notified when their karma value changes (including the reason for the increase/decrease) and the server doesn't ban clients whose karma decreases below the ban threshold.", null));
|
||||
|
||||
commands.Add(new Command("kick", "kick [name]: Kick a player out of the server.", (string[] args) =>
|
||||
{
|
||||
@@ -654,11 +680,11 @@ namespace Barotrauma
|
||||
|
||||
if (args.Length > 0 && args[0].ToLowerInvariant() == "start")
|
||||
{
|
||||
Submarine.MainSub.SetPosition(Level.Loaded.StartPosition);
|
||||
Submarine.MainSub.SetPosition(Level.Loaded.StartPosition - Vector2.UnitY * Submarine.MainSub.Borders.Height);
|
||||
}
|
||||
else
|
||||
{
|
||||
Submarine.MainSub.SetPosition(Level.Loaded.EndPosition);
|
||||
Submarine.MainSub.SetPosition(Level.Loaded.EndPosition - Vector2.UnitY * Submarine.MainSub.Borders.Height);
|
||||
}
|
||||
}, isCheat: true));
|
||||
|
||||
|
||||
@@ -280,16 +280,23 @@ namespace Barotrauma
|
||||
|
||||
float holeCount = 0.0f;
|
||||
floodingAmount = 0.0f;
|
||||
int hullCount = 0;
|
||||
foreach (Hull hull in Hull.hullList)
|
||||
{
|
||||
if (hull.Submarine == null || hull.Submarine.IsOutpost) { continue; }
|
||||
hullCount++;
|
||||
foreach (Gap gap in hull.ConnectedGaps)
|
||||
{
|
||||
if (!gap.IsRoomToRoom) holeCount += gap.Open;
|
||||
}
|
||||
floodingAmount += hull.WaterVolume / hull.Volume / Hull.hullList.Count;
|
||||
floodingAmount += hull.WaterVolume / hull.Volume;
|
||||
fireAmount += hull.FireSources.Sum(fs => fs.Size.X);
|
||||
}
|
||||
if (hullCount > 0)
|
||||
{
|
||||
floodingAmount = floodingAmount / hullCount;
|
||||
}
|
||||
|
||||
//hull integrity at 0.0 if there are 10 or more wide-open holes
|
||||
avgHullIntegrity = MathHelper.Clamp(1.0f - holeCount / 10.0f, 0.0f, 1.0f);
|
||||
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
using Barotrauma.Items.Components;
|
||||
using Barotrauma.Networking;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -12,9 +8,6 @@ namespace Barotrauma
|
||||
private Submarine[] subs;
|
||||
private List<Character>[] crews;
|
||||
|
||||
private bool initialized = false;
|
||||
private int state = 0;
|
||||
|
||||
private string[] descriptions;
|
||||
private static string[] teamNames = { "Team A", "Team B" };
|
||||
|
||||
|
||||
@@ -81,10 +81,8 @@ namespace Barotrauma
|
||||
|
||||
bool success =
|
||||
GameMain.Server.ConnectedClients.Any(c => c.InGame && c.Character != null && !c.Character.IsDead);
|
||||
|
||||
#if CLIENT
|
||||
|
||||
success = success || (GameMain.Server.Character != null && !GameMain.Server.Character.IsDead);
|
||||
#endif
|
||||
|
||||
/*if (success)
|
||||
{
|
||||
@@ -119,11 +117,7 @@ namespace Barotrauma
|
||||
{
|
||||
c.Inventory?.DeleteAllItems();
|
||||
}
|
||||
|
||||
#if CLIENT
|
||||
GameMain.GameSession.CrewManager.EndRound();
|
||||
#endif
|
||||
|
||||
|
||||
if (success)
|
||||
{
|
||||
bool atEndPosition = Submarine.MainSub.AtEndPosition;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user