(6eeea9b7c) v0.9.10.0.0

This commit is contained in:
Joonas Rikkonen
2020-06-04 16:41:07 +03:00
parent ce4ccd99ac
commit eeac247a8e
366 changed files with 7772 additions and 3692 deletions

3
.gitignore vendored
View File

@@ -37,5 +37,8 @@ Libraries/webm_mem_playback/opus_x64_linux/
# Mac
*.DS_Store
# Win
desktop.ini
#Merge script
temp.txt

View File

@@ -200,7 +200,7 @@ namespace Barotrauma
worldView = new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight);
viewMatrix = Matrix.CreateTranslation(new Vector3(GameMain.GraphicsWidth / 2.0f, GameMain.GraphicsHeight / 2.0f, 0));
globalZoomScale = (float)Math.Pow(new Vector2(resolution.X, resolution.Y).Length() / new Vector2(1920, 1080).Length(), 2);
globalZoomScale = (float)Math.Pow(new Vector2(GUI.UIWidth, resolution.Y).Length() / GUI.ReferenceResolution.Length(), 2);
}
public void UpdateTransform(bool interpolate = true)

View File

@@ -19,11 +19,14 @@ namespace Barotrauma
var target = _selectedAiTarget ?? _lastAiTarget;
if (target != null && target.Entity != null)
{
var memory = GetTargetMemory(target);
Vector2 targetPos = memory.Location;
targetPos.Y = -targetPos.Y;
GUI.DrawLine(spriteBatch, pos, targetPos, Color.White * 0.5f, 0, 4);
GUI.DrawString(spriteBatch, pos - Vector2.UnitY * 60.0f, $"{target.Entity.ToString()} ({memory.Priority.FormatZeroDecimal()})", Color.White, Color.Black);
var memory = GetTargetMemory(target, false);
if (memory != null)
{
Vector2 targetPos = memory.Location;
targetPos.Y = -targetPos.Y;
GUI.DrawLine(spriteBatch, pos, targetPos, Color.White * 0.5f, 0, 4);
GUI.DrawString(spriteBatch, pos - Vector2.UnitY * 60.0f, $"{target.Entity} ({memory.Priority.FormatZeroDecimal()})", Color.White, Color.Black);
}
}
}
else if (SelectedAiTarget?.Entity != null)
@@ -35,7 +38,7 @@ namespace Barotrauma
}
targetPos.Y = -targetPos.Y;
GUI.DrawLine(spriteBatch, pos, targetPos, GUI.Style.Red * 0.5f, 0, 4);
if (wallTarget != null)
if (wallTarget != null && (State == AIState.Attack || State == AIState.Aggressive || State == AIState.PassiveAggressive))
{
Vector2 wallTargetPos = wallTarget.Position;
if (wallTarget.Structure.Submarine != null) { wallTargetPos += wallTarget.Structure.Submarine.Position; }
@@ -43,7 +46,7 @@ namespace Barotrauma
GUI.DrawRectangle(spriteBatch, wallTargetPos - new Vector2(10.0f, 10.0f), new Vector2(20.0f, 20.0f), Color.Orange, false);
GUI.DrawLine(spriteBatch, pos, wallTargetPos, Color.Orange * 0.5f, 0, 5);
}
GUI.DrawString(spriteBatch, pos - Vector2.UnitY * 60.0f, $"{SelectedAiTarget.Entity.ToString()} ({GetTargetMemory(SelectedAiTarget).Priority.FormatZeroDecimal()})", GUI.Style.Red, Color.Black);
GUI.DrawString(spriteBatch, pos - Vector2.UnitY * 60.0f, $"{SelectedAiTarget.Entity} ({GetTargetMemory(SelectedAiTarget, false)?.Priority.FormatZeroDecimal()})", GUI.Style.Red, Color.Black);
GUI.DrawString(spriteBatch, pos - Vector2.UnitY * 40.0f, $"({targetValue.FormatZeroDecimal()})", GUI.Style.Red, Color.Black);
}

View File

@@ -44,19 +44,20 @@ namespace Barotrauma
var currentObjective = ObjectiveManager.CurrentObjective;
if (currentObjective != null)
{
if (currentOrder == null)
int offset = currentOrder != null ? 20 : 0;
if (currentOrder == null || currentOrder.Priority <= 0)
{
GUI.DrawString(spriteBatch, pos + textOffset + new Vector2(0, 20), $"MAIN OBJECTIVE: {currentObjective.DebugTag} ({currentObjective.Priority.FormatZeroDecimal()})", Color.White, Color.Black);
GUI.DrawString(spriteBatch, pos + textOffset + new Vector2(0, 20 + offset), $"MAIN OBJECTIVE: {currentObjective.DebugTag} ({currentObjective.Priority.FormatZeroDecimal()})", Color.White, Color.Black);
}
var subObjective = currentObjective.CurrentSubObjective;
if (subObjective != null)
{
GUI.DrawString(spriteBatch, pos + textOffset + new Vector2(0, 40), $"SUBOBJECTIVE: {subObjective.DebugTag} ({subObjective.Priority.FormatZeroDecimal()})", Color.White, Color.Black);
GUI.DrawString(spriteBatch, pos + textOffset + new Vector2(0, 40 + offset), $"SUBOBJECTIVE: {subObjective.DebugTag} ({subObjective.Priority.FormatZeroDecimal()})", Color.White, Color.Black);
}
var activeObjective = ObjectiveManager.GetActiveObjective();
if (activeObjective != null)
{
GUI.DrawString(spriteBatch, pos + textOffset + new Vector2(0, 60), $"ACTIVE OBJECTIVE: {activeObjective.DebugTag} ({activeObjective.Priority.FormatZeroDecimal()})", Color.White, Color.Black);
GUI.DrawString(spriteBatch, pos + textOffset + new Vector2(0, 60 + offset), $"ACTIVE OBJECTIVE: {activeObjective.DebugTag} ({activeObjective.Priority.FormatZeroDecimal()})", Color.White, Color.Black);
}
}
}
@@ -86,7 +87,7 @@ namespace Barotrauma
new Vector2(path.CurrentNode.DrawPosition.X, -path.CurrentNode.DrawPosition.Y),
Color.BlueViolet, 0, 3);
GUI.DrawString(spriteBatch, pos + textOffset + new Vector2(0, 80), "Path cost: " + path.Cost.FormatZeroDecimal(), Color.White, Color.Black * 0.5f);
GUI.DrawString(spriteBatch, pos + textOffset + new Vector2(0, 100), "Path cost: " + path.Cost.FormatZeroDecimal(), Color.White, Color.Black * 0.5f);
}
}
}

View File

@@ -389,7 +389,7 @@ namespace Barotrauma
{
foreach (Limb limb in Limbs)
{
if (limb == null || limb.IsSevered || limb.ActiveSprite == null) continue;
if (limb == null || limb.IsSevered || limb.ActiveSprite == null) { continue; }
Vector2 spriteOrigin = limb.ActiveSprite.Origin;
spriteOrigin.X = limb.ActiveSprite.SourceRect.Width - spriteOrigin.X;
@@ -404,8 +404,8 @@ namespace Barotrauma
float gibParticleAmount = MathHelper.Clamp(limb.Mass / character.AnimController.Mass, 0.1f, 1.0f);
foreach (ParticleEmitter emitter in character.GibEmitters)
{
if (inWater && emitter.Prefab.ParticlePrefab.DrawTarget == ParticlePrefab.DrawTargetType.Air) continue;
if (!inWater && emitter.Prefab.ParticlePrefab.DrawTarget == ParticlePrefab.DrawTargetType.Water) continue;
if (inWater && emitter.Prefab.ParticlePrefab.DrawTarget == ParticlePrefab.DrawTargetType.Air) { continue; }
if (!inWater && emitter.Prefab.ParticlePrefab.DrawTarget == ParticlePrefab.DrawTargetType.Water) { continue; }
emitter.Emit(1.0f, limb.WorldPosition, character.CurrentHull, amountMultiplier: gibParticleAmount);
}
@@ -418,7 +418,8 @@ namespace Barotrauma
if (playSound)
{
SoundPlayer.PlayDamageSound("Gore", 1.0f, limbJoint.LimbA.body);
var damageSound = character.GetSound(s => s.Type == CharacterSound.SoundType.Damage);
SoundPlayer.PlayDamageSound(limbJoint.Params.BreakSound, 1.0f, limbJoint.LimbA.body.DrawPosition, range: damageSound != null ? damageSound.Range : 800);
}
}
@@ -446,9 +447,10 @@ namespace Barotrauma
float depthOffset = GetDepthOffset();
for (int i = 0; i < limbs.Length; i++)
{
if (depthOffset != 0.0f) { inversedLimbDrawOrder[i].ActiveSprite.Depth += depthOffset; }
inversedLimbDrawOrder[i].Draw(spriteBatch, cam, color);
if (depthOffset != 0.0f) { inversedLimbDrawOrder[i].ActiveSprite.Depth -= depthOffset; }
var limb = inversedLimbDrawOrder[i];
if (depthOffset != 0.0f) { limb.ActiveSprite.Depth += depthOffset; }
limb.Draw(spriteBatch, cam, color);
if (depthOffset != 0.0f) { limb.ActiveSprite.Depth -= depthOffset; }
}
LimbJoints.ForEach(j => j.Draw(spriteBatch));
}
@@ -489,8 +491,8 @@ namespace Barotrauma
public void DebugDraw(SpriteBatch spriteBatch)
{
if (!GameMain.DebugDraw || !character.Enabled) return;
if (simplePhysicsEnabled) return;
if (!GameMain.DebugDraw || !character.Enabled) { return; }
if (simplePhysicsEnabled) { return; }
foreach (Limb limb in Limbs)
{
@@ -508,7 +510,7 @@ namespace Barotrauma
Collider.DebugDraw(spriteBatch, frozen ? GUI.Style.Red : (inWater ? Color.SkyBlue : Color.Gray));
GUI.Font.DrawString(spriteBatch, Collider.LinearVelocity.X.FormatSingleDecimal(), new Vector2(Collider.DrawPosition.X, -Collider.DrawPosition.Y), Color.Orange);
foreach (RevoluteJoint joint in LimbJoints)
foreach (var joint in LimbJoints)
{
Vector2 pos = ConvertUnits.ToDisplayUnits(joint.WorldAnchorA);
GUI.DrawRectangle(spriteBatch, new Rectangle((int)pos.X, (int)-pos.Y, 5, 5), Color.White, true);
@@ -522,7 +524,10 @@ namespace Barotrauma
if (limb.body.TargetPosition != null)
{
Vector2 pos = ConvertUnits.ToDisplayUnits((Vector2)limb.body.TargetPosition);
if (currentHull?.Submarine != null) pos += currentHull.Submarine.DrawPosition;
if (currentHull?.Submarine != null)
{
pos += currentHull.Submarine.DrawPosition;
}
pos.Y = -pos.Y;
GUI.DrawRectangle(spriteBatch, new Rectangle((int)pos.X - 10, (int)pos.Y - 10, 20, 20), Color.Cyan, false, 0.01f);
@@ -541,13 +546,19 @@ namespace Barotrauma
if (character.MemState.Count > 1)
{
Vector2 prevPos = ConvertUnits.ToDisplayUnits(character.MemState[0].Position);
if (currentHull?.Submarine != null) prevPos += currentHull.Submarine.DrawPosition;
if (currentHull?.Submarine != null)
{
prevPos += currentHull.Submarine.DrawPosition;
}
prevPos.Y = -prevPos.Y;
for (int i = 1; i < character.MemState.Count; i++)
{
Vector2 currPos = ConvertUnits.ToDisplayUnits(character.MemState[i].Position);
if (currentHull?.Submarine != null) currPos += currentHull.Submarine.DrawPosition;
if (currentHull?.Submarine != null)
{
currPos += currentHull.Submarine.DrawPosition;
}
currPos.Y = -currPos.Y;
GUI.DrawRectangle(spriteBatch, new Rectangle((int)currPos.X - 3, (int)currPos.Y - 3, 6, 6), Color.Cyan * 0.6f, true, 0.01f);

View File

@@ -10,6 +10,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using Barotrauma.Extensions;
namespace Barotrauma
{
@@ -357,7 +358,16 @@ namespace Barotrauma
partial void OnAttackedProjSpecific(Character attacker, AttackResult attackResult, float stun)
{
if (attackResult.Damage <= 1.0f || IsDead) { return; }
if (IsDead) { return; }
if (attacker != null)
{
if (attackResult.Damage <= 0.01f) { return; }
}
else
{
if (attackResult.Damage <= 1.0f) { return; }
}
if (soundTimer < soundInterval * 0.5f)
{
PlaySound(CharacterSound.SoundType.Damage);
@@ -813,20 +823,22 @@ namespace Barotrauma
return progressBar;
}
private readonly List<CharacterSound> matchingSounds = new List<CharacterSound>();
private SoundChannel soundChannel;
public void PlaySound(CharacterSound.SoundType soundType)
{
if (sounds == null || sounds.Count == 0) { return; }
if (soundChannel != null && soundChannel.IsPlaying) { return; }
if (GameMain.SoundManager?.Disabled ?? true) { return; }
var matchingSounds = sounds.Where(s =>
s.Type == soundType &&
(s.Gender == Gender.None || (info != null && info.Gender == s.Gender)));
if (!matchingSounds.Any()) { return; }
var matchingSoundsList = matchingSounds.ToList();
var selectedSound = matchingSoundsList[Rand.Int(matchingSoundsList.Count)];
matchingSounds.Clear();
foreach (var s in sounds)
{
if (s.Type == soundType && (s.Gender == Gender.None || (info != null && info.Gender == s.Gender)))
{
matchingSounds.Add(s);
}
}
var selectedSound = matchingSounds.GetRandom();
if (selectedSound?.Sound == null) { return; }
soundChannel = SoundPlayer.PlaySound(selectedSound.Sound, AnimController.WorldPosition, selectedSound.Volume, selectedSound.Range, CurrentHull);
soundTimer = soundInterval;
@@ -846,6 +858,11 @@ namespace Barotrauma
activeObjectiveEntities.Remove(found);
}
/// <summary>
/// Note that when a predicate is provided, the random option uses Linq.Where() extension method, which creates a new collection.
/// </summary>
public CharacterSound GetSound(Func<CharacterSound, bool> predicate = null, bool random = false) => random ? sounds.GetRandom(predicate) : sounds.FirstOrDefault(predicate);
partial void ImplodeFX()
{
Vector2 centerOfMass = AnimController.GetCenterOfMass();

View File

@@ -29,7 +29,7 @@ namespace Barotrauma
{
if (hudFrame == null)
{
hudFrame = new GUIFrame(new RectTransform(Vector2.One, GUI.Canvas), style: null)
hudFrame = new GUIFrame(new RectTransform(GUI.Canvas.RelativeSize, GUI.Canvas), style: null)
{
CanBeFocused = false
};
@@ -163,7 +163,7 @@ namespace Barotrauma
foreach (Item item in Item.ItemList)
{
if (item.Submarine == null || item.Submarine.TeamID != character.TeamID || item.Submarine.Info.IsWreck) { continue; }
if (!item.Repairables.Any(r => item.ConditionPercentage <= r.AIRepairThreshold)) { continue; }
if (!item.Repairables.Any(r => item.ConditionPercentage <= r.RepairThreshold)) { continue; }
if (Submarine.VisibleEntities != null && !Submarine.VisibleEntities.Contains(item)) { continue; }
Vector2 diff = item.WorldPosition - character.WorldPosition;
@@ -202,6 +202,7 @@ namespace Barotrauma
foreach (Item brokenItem in brokenItems)
{
if (brokenItem.NonInteractable) { continue; }
float dist = Vector2.Distance(character.WorldPosition, brokenItem.WorldPosition);
Vector2 drawPos = brokenItem.DrawPosition;
float alpha = Math.Min((1000.0f - dist) / 1000.0f * 2.0f, 1.0f);
@@ -373,7 +374,7 @@ namespace Barotrauma
{
GUIComponent.DrawToolTip(
spriteBatch,
character.Info?.Job == null ? character.DisplayName : character.Name + " (" + character.Info.Job.Name + ")",
character.Info?.Job == null ? character.DisplayName : character.DisplayName + " (" + character.Info.Job.Name + ")",
HUDLayoutSettings.PortraitArea);
}
}
@@ -393,10 +394,6 @@ namespace Barotrauma
startPos = cam.WorldToScreen(startPos);
string focusName = character.FocusedCharacter.DisplayName;
if (character.FocusedCharacter.Info != null)
{
focusName = character.FocusedCharacter.Info.DisplayName;
}
Vector2 textPos = startPos;
Vector2 textSize = GUI.Font.MeasureString(focusName);
Vector2 largeTextSize = GUI.SubHeadingFont.MeasureString(focusName);

View File

@@ -146,7 +146,8 @@ namespace Barotrauma
"+" + ((int)((newLevel - prevLevel) * 100.0f)).ToString() + " XP",
GUI.Style.Green,
textPopupPos,
Vector2.UnitY * 10.0f);
Vector2.UnitY * 10.0f,
playSound: Character.Controlled?.Info == this);
}
else if (prevLevel % 0.1f > 0.05f && newLevel % 0.1f < 0.05f)
{
@@ -154,7 +155,8 @@ namespace Barotrauma
"+10 XP",
GUI.Style.Green,
textPopupPos,
Vector2.UnitY * 10.0f);
Vector2.UnitY * 10.0f,
playSound: Character.Controlled?.Info == this);
}
if ((int)newLevel > (int)prevLevel)

View File

@@ -502,11 +502,9 @@ namespace Barotrauma
causeOfDeathAffliction = AfflictionPrefab.Prefabs[afflictionName];
}
}
byte severedLimbCount = msg.ReadByte();
if (!IsDead)
{
if (causeOfDeathType == CauseOfDeathType.Pressure)
if (causeOfDeathType == CauseOfDeathType.Pressure || causeOfDeathAffliction == AfflictionPrefab.Pressure)
{
Implode(true);
}
@@ -515,26 +513,26 @@ namespace Barotrauma
Kill(causeOfDeathType, causeOfDeathAffliction?.Instantiate(1.0f), true);
}
}
for (int i = 0; i < severedLimbCount; i++)
{
int severedJointIndex = msg.ReadByte();
if (severedJointIndex < 0 || severedJointIndex >= AnimController.LimbJoints.Length)
{
string errorMsg = $"Error in CharacterNetworking.ReadStatus: severed joint index out of bounds (index: {severedJointIndex}, joint count: {AnimController.LimbJoints.Length})";
GameAnalyticsManager.AddErrorEventOnce("CharacterNetworking.ReadStatus:JointIndexOutOfBounts", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
}
else
{
AnimController.SeverLimbJoint(AnimController.LimbJoints[severedJointIndex]);
}
}
}
else
{
if (IsDead) { Revive(); }
CharacterHealth.ClientRead(msg);
}
byte severedLimbCount = msg.ReadByte();
for (int i = 0; i < severedLimbCount; i++)
{
int severedJointIndex = msg.ReadByte();
if (severedJointIndex < 0 || severedJointIndex >= AnimController.LimbJoints.Length)
{
string errorMsg = $"Error in CharacterNetworking.ReadStatus: severed joint index out of bounds (index: {severedJointIndex}, joint count: {AnimController.LimbJoints.Length})";
GameAnalyticsManager.AddErrorEventOnce("CharacterNetworking.ReadStatus:JointIndexOutOfBounts", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
}
else
{
AnimController.SeverLimbJoint(AnimController.LimbJoints[severedJointIndex]);
}
}
}
}
}

View File

@@ -1,6 +1,6 @@
using Microsoft.Xna.Framework;
using System.Collections.Generic;
using System.IO;
using Barotrauma.IO;
using System.Linq;
using System.Xml.Linq;

View File

@@ -1,4 +1,5 @@
using Barotrauma.Extensions;
using Barotrauma.Items.Components;
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
@@ -20,9 +21,9 @@ namespace Barotrauma
}
const int MaxFakeFireSources = 10;
private float minFakeFireSourceInterval = 10.0f, maxFakeFireSourceInterval = 200.0f;
const float MinFakeFireSourceInterval = 30.0f, MaxFakeFireSourceInterval = 240.0f;
private float createFireSourceTimer;
private List<FakeFireSource> fakeFireSources = new List<FakeFireSource>();
private readonly List<FakeFireSource> fakeFireSources = new List<FakeFireSource>();
enum FloodType
{
@@ -31,26 +32,30 @@ namespace Barotrauma
HideFlooding
}
private float minSoundInterval = 10.0f, maxSoundInterval = 60.0f;
const float MinSoundInterval = 10.0f, MaxSoundInterval = 180.0f;
private FloodType currentFloodType;
private float soundTimer;
private float minFloodInterval = 30.0f, maxFloodInterval = 180.0f;
const float MinFloodInterval = 60.0f, MaxFloodInterval = 240.0f;
private float createFloodTimer;
private float currentFloodState;
private float currentFloodDuration;
private float fakeBrokenInterval = 30.0f;
private float fakeBrokenTimer = 0.0f;
partial void UpdateProjSpecific(CharacterHealth characterHealth, Limb targetLimb, float deltaTime)
{
if (Character.Controlled != characterHealth.Character) return;
UpdateFloods(deltaTime);
UpdateSounds(characterHealth.Character, deltaTime);
UpdateFires(characterHealth.Character, deltaTime);
UpdateFires(characterHealth.Character, deltaTime);
UpdateFakeBroken(deltaTime);
}
private void UpdateSounds(Character character, float deltaTime)
{
if (soundTimer < MathHelper.Lerp(maxSoundInterval, minSoundInterval, Strength / 100.0f))
if (soundTimer < MathHelper.Lerp(MaxSoundInterval, MinSoundInterval, Strength / 100.0f))
{
soundTimer += deltaTime;
return;
@@ -97,7 +102,7 @@ namespace Barotrauma
return;
}
if (createFloodTimer < MathHelper.Lerp(maxFloodInterval, minFloodInterval, Strength / 100.0f))
if (createFloodTimer < MathHelper.Lerp(MaxFloodInterval, MinFloodInterval, Strength / 100.0f))
{
createFloodTimer += deltaTime;
return;
@@ -124,7 +129,7 @@ namespace Barotrauma
createFireSourceTimer += deltaTime;
if (fakeFireSources.Count < MaxFakeFireSources &&
character.Submarine != null &&
createFireSourceTimer > MathHelper.Lerp(maxFakeFireSourceInterval, minFakeFireSourceInterval, Strength / 100.0f))
createFireSourceTimer > MathHelper.Lerp(MaxFakeFireSourceInterval, MinFakeFireSourceInterval, Strength / 100.0f))
{
Hull fireHull = Hull.hullList.GetRandom(h => h.Submarine == character.Submarine);
@@ -140,9 +145,9 @@ namespace Barotrauma
foreach (FakeFireSource fakeFireSource in fakeFireSources)
{
if (fakeFireSource.Hull.Surface > fakeFireSource.Hull.Rect.Y - fakeFireSource.Hull.Rect.Height + fakeFireSource.Position.Y)
if (fakeFireSource.Hull.DrawSurface > fakeFireSource.Hull.Rect.Y - fakeFireSource.Hull.Rect.Height + fakeFireSource.Position.Y)
{
fakeFireSource.LifeTime -= deltaTime * 10.0f;
fakeFireSource.LifeTime -= deltaTime * 100.0f;
}
fakeFireSource.LifeTime -= deltaTime;
@@ -162,5 +167,28 @@ namespace Barotrauma
fakeFireSources.RemoveAll(fs => fs.LifeTime <= 0.0f);
}
private void UpdateFakeBroken(float deltaTime)
{
fakeBrokenTimer -= deltaTime;
if (fakeBrokenTimer > 0.0f) { return; }
foreach (Item item in Item.ItemList)
{
var repairable = item.GetComponent<Repairable>();
if (repairable == null) { continue; }
if (ShouldFakeBrokenItem(item))
{
repairable.FakeBrokenTimer = 60.0f;
}
}
fakeBrokenTimer = fakeBrokenInterval;
}
private bool ShouldFakeBrokenItem(Item item)
{
return Rand.Range(0.0f, 1000.0f) < Strength;
}
}
}

View File

@@ -251,8 +251,7 @@ namespace Barotrauma
{
get
{
// 0.38775510204f = percentage of offset before reaching the healthbar portion of the graphic going from bottom upwards
return new Point(2, (int)(HUDLayoutSettings.HealthBarArea.Size.Y * 0.38775510204f));
return new Point(Math.Max(2, GUI.IntScaleCeiling(1.5f)), Math.Min(GUI.IntScaleFloor(18f), 19));
}
}
@@ -260,7 +259,7 @@ namespace Barotrauma
{
get
{
return new Point((int)Math.Ceiling(HUDLayoutSettings.HealthBarArea.Size.X - 45 * GUI.Scale), (int)(healthBarHolder.Rect.Height - Math.Min(23 * GUI.Scale, 25)) / 2);
return new Point(healthBarHolder.Rect.Width - Math.Min(GUI.IntScale(45f), 47), GUI.IntScale(15f));
}
}
@@ -597,12 +596,14 @@ namespace Barotrauma
switch (alignment)
{
case Alignment.Left:
healthInterfaceFrame.RectTransform.SetPosition(Anchor.CenterLeft);
healthInterfaceFrame.RectTransform.SetPosition(Anchor.BottomLeft);
break;
case Alignment.Right:
healthInterfaceFrame.RectTransform.SetPosition(Anchor.CenterRight);
healthInterfaceFrame.RectTransform.SetPosition(Anchor.BottomRight);
break;
}
healthInterfaceFrame.RectTransform.AbsoluteOffset = new Point(HUDLayoutSettings.Padding, screenResolution.Y - HUDLayoutSettings.ChatBoxArea.Y + HUDLayoutSettings.Padding);
healthInterfaceFrame.RectTransform.RecalculateChildren(false);
}
@@ -1107,7 +1108,7 @@ namespace Barotrauma
float currHealth = healthBar.BarSize;
Color prevColor = healthBar.Color;
healthBarShadow.BarSize = healthShadowSize;
healthBarShadow.Color = GUI.Style.Red;
healthBarShadow.Color = Color.Lerp(GUI.Style.Red, Color.Black, 0.5f);
healthBarShadow.Visible = true;
healthBar.BarSize = currHealth;
healthBar.Color = prevColor;
@@ -1822,7 +1823,7 @@ namespace Barotrauma
Vector2 iconPos = highlightArea.Center.ToVector2();
//Affliction mostSevereAffliction = thisAfflictions.FirstOrDefault(a => !a.Prefab.IsBuff && !thisAfflictions.Any(a2 => !a2.Prefab.IsBuff && a2.Strength > a.Strength)) ?? thisAfflictions.FirstOrDefault();
Affliction mostSevereAffliction = SortAfflictionsBySeverity(thisAfflictions).FirstOrDefault();
Affliction mostSevereAffliction = SortAfflictionsBySeverity(thisAfflictions, excludeBuffs: false).FirstOrDefault();
if (mostSevereAffliction != null) { DrawLimbAfflictionIcon(spriteBatch, mostSevereAffliction, iconScale, ref iconPos); }
if (thisAfflictions.Count() > 1)

View File

@@ -8,12 +8,14 @@ namespace Barotrauma
{
partial class JobPrefab : IPrefab, IDisposable
{
public GUIButton CreateInfoFrame(int variant)
public GUIButton CreateInfoFrame(out GUIComponent buttonContainer)
{
int width = 500, height = 400;
GUIButton backFrame = new GUIButton(new RectTransform(Vector2.One, GUI.Canvas), style: "GUIBackgroundBlocker");
GUIFrame frame = new GUIFrame(new RectTransform(new Point(width, height), backFrame.RectTransform, Anchor.Center));
GUIButton frameHolder = new GUIButton(new RectTransform(Vector2.One, GUI.Canvas, Anchor.Center), style: null);
new GUIFrame(new RectTransform(GUI.Canvas.RelativeSize, frameHolder.RectTransform, Anchor.Center), style: "GUIBackgroundBlocker");
GUIFrame frame = new GUIFrame(new RectTransform(new Point(width, height), frameHolder.RectTransform, Anchor.Center));
GUIFrame paddedFrame = new GUIFrame(new RectTransform(new Vector2(0.9f, 0.9f), frame.RectTransform, Anchor.Center), style: null);
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.1f), paddedFrame.RectTransform), Name, font: GUI.LargeFont);
@@ -32,6 +34,8 @@ namespace Barotrauma
font: GUI.SmallFont);
}
buttonContainer = paddedFrame;
/*if (!ItemIdentifiers.TryGetValue(variant, out var itemIdentifiers)) { return backFrame; }
var itemContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.45f, 0.5f), paddedFrame.RectTransform, Anchor.TopRight)
{ RelativeOffset = new Vector2(0.0f, 0.2f + descriptionBlock.RectTransform.RelativeSize.Y) })
@@ -49,7 +53,7 @@ namespace Barotrauma
font: GUI.SmallFont);
}*/
return backFrame;
return frameHolder;
}

View File

@@ -3,25 +3,24 @@ using Barotrauma.Particles;
using Barotrauma.SpriteDeformations;
using Barotrauma.Extensions;
using FarseerPhysics;
using FarseerPhysics.Dynamics.Joints;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
using System.IO;
using Barotrauma.IO;
using System.Linq;
using System.Xml.Linq;
using SpriteParams = Barotrauma.RagdollParams.SpriteParams;
namespace Barotrauma
{
partial class LimbJoint : RevoluteJoint
partial class LimbJoint
{
public void UpdateDeformations(float deltaTime)
{
float diff = Math.Abs(UpperLimit - LowerLimit);
float strength = MathHelper.Lerp(0, 1, MathUtils.InverseLerp(0, MathHelper.Pi, diff));
float jointAngle = this.JointAngle * strength;
float jointAngle = JointAngle * strength;
JointBendDeformation limbADeformation = LimbA.Deformations.Find(d => d is JointBendDeformation) as JointBendDeformation;
JointBendDeformation limbBDeformation = LimbB.Deformations.Find(d => d is JointBendDeformation) as JointBendDeformation;
@@ -70,7 +69,6 @@ namespace Barotrauma
}
}
}
}
public void Draw(SpriteBatch spriteBatch)
@@ -126,7 +124,7 @@ namespace Barotrauma
{
get
{
var conditionalSprite = ConditionalSprites.FirstOrDefault(c => c.IsActive && c.DeformableSprite != null);
var conditionalSprite = ConditionalSprites.FirstOrDefault(c => c.Exclusive && c.IsActive && c.DeformableSprite != null);
if (conditionalSprite != null)
{
return conditionalSprite.DeformableSprite;
@@ -144,7 +142,7 @@ namespace Barotrauma
{
get
{
var conditionalSprite = ConditionalSprites.FirstOrDefault(c => c.IsActive && c.ActiveSprite != null);
var conditionalSprite = ConditionalSprites.FirstOrDefault(c => c.Exclusive && c.IsActive && c.ActiveSprite != null);
if (conditionalSprite != null)
{
return conditionalSprite.ActiveSprite;
@@ -166,6 +164,12 @@ namespace Barotrauma
public Sprite DamagedSprite { get; private set; }
public bool Hide
{
get => Params.Hide;
set => Params.Hide = value;
}
public List<ConditionalSprite> ConditionalSprites { get; private set; } = new List<ConditionalSprite>();
private Dictionary<DecorativeSprite, SpriteState> spriteAnimState = new Dictionary<DecorativeSprite, SpriteState>();
private Dictionary<int, List<DecorativeSprite>> DecorativeSpriteGroups = new Dictionary<int, List<DecorativeSprite>>();
@@ -274,7 +278,17 @@ namespace Barotrauma
DamagedSprite = new Sprite(subElement, file: GetSpritePath(subElement, Params.damagedSpriteParams));
break;
case "conditionalsprite":
var conditionalSprite = new ConditionalSprite(subElement, character, file: GetSpritePath(subElement, null));
ISerializableEntity targetEntity;
string target = subElement.GetAttributeString("target", null);
if (string.Equals(target, "character", StringComparison.OrdinalIgnoreCase))
{
targetEntity = character;
}
else
{
targetEntity = this;
}
var conditionalSprite = new ConditionalSprite(subElement, targetEntity, file: GetSpritePath(subElement, null));
ConditionalSprites.Add(conditionalSprite);
if (conditionalSprite.DeformableSprite != null)
{
@@ -373,12 +387,16 @@ namespace Barotrauma
private string GetSpritePath(XElement element, SpriteParams spriteParams)
{
string texturePath = element.GetAttributeString("texture", null);
if (string.IsNullOrWhiteSpace(texturePath) && spriteParams != null)
if (spriteParams != null)
{
texturePath = spriteParams.Ragdoll.Texture;
return GetSpritePath(spriteParams.GetTexturePath());
}
else
{
string texturePath = element.GetAttributeString("texture", null);
texturePath = string.IsNullOrWhiteSpace(texturePath) ? ragdoll.RagdollParams.Texture : texturePath;
return GetSpritePath(texturePath);
}
return GetSpritePath(texturePath);
}
/// <summary>
@@ -419,12 +437,29 @@ namespace Barotrauma
}
}
partial void AddDamageProjSpecific(IEnumerable<Affliction> afflictions, bool playSound, IEnumerable<DamageModifier> appliedDamageModifiers)
partial void AddDamageProjSpecific(bool playSound, AttackResult result)
{
float bleedingDamage = character.CharacterHealth.DoesBleed ? afflictions.Where(a => a is AfflictionBleeding).Sum(a => a.GetVitalityDecrease(character.CharacterHealth)) : 0;
float damage = afflictions.Where(a => a.Prefab.AfflictionType == "damage").Sum(a => a.GetVitalityDecrease(character.CharacterHealth));
float bleedingDamage = 0;
if (character.CharacterHealth.DoesBleed)
{
foreach (var affliction in result.Afflictions)
{
if (affliction is AfflictionBleeding)
{
bleedingDamage += affliction.GetVitalityDecrease(character.CharacterHealth);
}
}
}
float damage = 0;
foreach (var affliction in result.Afflictions)
{
if (affliction.Prefab.AfflictionType == "damage")
{
damage += affliction.GetVitalityDecrease(character.CharacterHealth);
}
}
float damageMultiplier = 1;
foreach (DamageModifier damageModifier in appliedDamageModifiers)
foreach (DamageModifier damageModifier in result.AppliedDamageModifiers)
{
foreach (var afflictionPrefab in AfflictionPrefab.List)
{
@@ -433,6 +468,7 @@ namespace Barotrauma
if (afflictionPrefab.Effects.Any(e => e.MaxVitalityDecrease > 0))
{
damageMultiplier *= damageModifier.DamageMultiplier;
break;
}
}
}
@@ -440,7 +476,7 @@ namespace Barotrauma
if (playSound)
{
string damageSoundType = (bleedingDamage > damage) ? "LimbSlash" : "LimbBlunt";
foreach (DamageModifier damageModifier in appliedDamageModifiers)
foreach (DamageModifier damageModifier in result.AppliedDamageModifiers)
{
if (!string.IsNullOrWhiteSpace(damageModifier.DamageSound))
{
@@ -457,9 +493,8 @@ namespace Barotrauma
{
foreach (ParticleEmitter emitter in character.DamageEmitters)
{
if (inWater && emitter.Prefab.ParticlePrefab.DrawTarget == ParticlePrefab.DrawTargetType.Air) continue;
if (!inWater && emitter.Prefab.ParticlePrefab.DrawTarget == ParticlePrefab.DrawTargetType.Water) continue;
if (inWater && emitter.Prefab.ParticlePrefab.DrawTarget == ParticlePrefab.DrawTargetType.Air) { continue; }
if (!inWater && emitter.Prefab.ParticlePrefab.DrawTarget == ParticlePrefab.DrawTargetType.Water) { continue; }
emitter.Emit(1.0f, WorldPosition, character.CurrentHull, amountMultiplier: damageParticleAmount);
}
}
@@ -471,9 +506,8 @@ namespace Barotrauma
foreach (ParticleEmitter emitter in character.BloodEmitters)
{
if (inWater && emitter.Prefab.ParticlePrefab.DrawTarget == ParticlePrefab.DrawTargetType.Air) continue;
if (!inWater && emitter.Prefab.ParticlePrefab.DrawTarget == ParticlePrefab.DrawTargetType.Water) continue;
if (inWater && emitter.Prefab.ParticlePrefab.DrawTarget == ParticlePrefab.DrawTargetType.Air) { continue; }
if (!inWater && emitter.Prefab.ParticlePrefab.DrawTarget == ParticlePrefab.DrawTargetType.Water) { continue; }
emitter.Emit(1.0f, WorldPosition, character.CurrentHull, sizeMultiplier: bloodParticleSize, amountMultiplier: bloodParticleAmount);
}
@@ -481,15 +515,14 @@ namespace Barotrauma
{
character.CurrentHull.AddDecal(character.BloodDecalName, WorldPosition, MathHelper.Clamp(bloodParticleSize, 0.5f, 1.0f));
}
}
}
}
partial void UpdateProjSpecific(float deltaTime)
{
if (!body.Enabled) { return; }
if (!character.IsDead)
if (!IsDead)
{
DamageOverlayStrength -= deltaTime;
BurnOverlayStrength -= deltaTime;
@@ -534,6 +567,10 @@ namespace Barotrauma
{
LightSource.LightSprite.Depth = ActiveSprite.Depth;
}
if (LightSource.DeformableLightSprite != null)
{
LightSource.DeformableLightSprite.Sprite.Depth = ActiveSprite.Depth;
}
}
UpdateSpriteStates(deltaTime);
@@ -543,6 +580,8 @@ namespace Barotrauma
{
float brightness = 1.0f - (burnOverLayStrength / 100.0f) * 0.5f;
var spriteParams = Params.GetSprite();
if (spriteParams == null) { return; }
Color color = new Color(spriteParams.Color.R / 255f * brightness, spriteParams.Color.G / 255f * brightness, spriteParams.Color.B / 255f * brightness, spriteParams.Color.A / 255f);
if (deadTimer > 0)
{
@@ -568,7 +607,7 @@ namespace Barotrauma
float herpesStrength = character.CharacterHealth.GetAfflictionStrength("spaceherpes");
bool hideLimb = Params.Hide ||
bool hideLimb = Hide ||
OtherWearables.Any(w => w.HideLimb) ||
wearingItems.Any(w => w != null && w.HideLimb);
@@ -589,6 +628,11 @@ namespace Barotrauma
{
var deformation = SpriteDeformation.GetDeformation(Deformations, deformSprite.Size);
deformSprite.Deform(deformation);
if (LightSource != null && LightSource.DeformableLightSprite != null)
{
deformation = SpriteDeformation.GetDeformation(Deformations, deformSprite.Size, dir == Direction.Left);
LightSource.DeformableLightSprite.Deform(deformation);
}
}
else
{
@@ -600,6 +644,31 @@ namespace Barotrauma
{
body.Draw(spriteBatch, activeSprite, color, null, Scale * TextureScale, Params.MirrorHorizontally, Params.MirrorVertically);
}
// Handle non-exlusive, i.e. additional conditional sprites
foreach (var conditionalSprite in ConditionalSprites)
{
// Exclusive conditional sprites are handled in the Properties
if (conditionalSprite.Exclusive) { continue; }
if (!conditionalSprite.IsActive) { continue; }
if (conditionalSprite.DeformableSprite != null)
{
var defSprite = conditionalSprite.DeformableSprite;
if (Deformations != null && Deformations.Any())
{
var deformation = SpriteDeformation.GetDeformation(Deformations, defSprite.Size);
defSprite.Deform(deformation);
}
else
{
defSprite.Reset();
}
body.Draw(defSprite, cam, Vector2.One * Scale * TextureScale, color, Params.MirrorHorizontally);
}
else
{
body.Draw(spriteBatch, conditionalSprite.Sprite, color, null, Scale * TextureScale, Params.MirrorHorizontally, Params.MirrorVertically);
}
}
}
SpriteEffects spriteEffect = (dir == Direction.Right) ? SpriteEffects.None : SpriteEffects.FlipHorizontally;
if (LightSource != null)

View File

@@ -5,7 +5,7 @@ using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System;
using System.Collections.Generic;
using System.IO;
using Barotrauma.IO;
using System.Linq;
using System.Text;
using System.Xml.Linq;
@@ -456,18 +456,6 @@ namespace Barotrauma
GameMain.CharacterEditorScreen.Select();
}));
commands.Add(new Command("money", "", args =>
{
if (args.Length == 0) { return; }
if (GameMain.GameSession.GameMode is CampaignMode campaign)
{
if (int.TryParse(args[0], out int money))
{
campaign.Money += money;
}
}
}, isCheat: true));
commands.Add(new Command("steamnetdebug", "steamnetdebug: Toggles Steamworks debug logging.", (string[] args) =>
{
SteamManager.NetworkingDebugLog = !SteamManager.NetworkingDebugLog;
@@ -504,6 +492,7 @@ namespace Barotrauma
AssignRelayToServer("setpassword", true);
commands.Add(new Command("traitorlist", "", (string[] args) => { }));
AssignRelayToServer("traitorlist", true);
AssignRelayToServer("money", true);
AssignOnExecute("control", (string[] args) =>
{
@@ -669,6 +658,44 @@ namespace Barotrauma
}
}, isCheat: true));
commands.Add(new Command("listcloudfiles", "Lists all of your files on the Steam Cloud.", args =>
{
int i = 0;
foreach (var file in Steamworks.SteamRemoteStorage.Files)
{
NewMessage($"* {i}: {file.Filename}, {file.Size} bytes", Color.Orange);
i++;
}
NewMessage($"Bytes remaining: {Steamworks.SteamRemoteStorage.QuotaRemainingBytes}/{Steamworks.SteamRemoteStorage.QuotaBytes}", Color.Yellow);
}));
commands.Add(new Command("removefromcloud", "Removes a file from Steam Cloud.", args =>
{
if (args.Length < 1) { return; }
var files = Steamworks.SteamRemoteStorage.Files;
Steamworks.SteamRemoteStorage.RemoteFile file;
if (int.TryParse(args[0], out int index) && index>=0 && index<files.Count)
{
file = files[index];
}
else
{
file = files.Find(f => f.Filename.Equals(args[0], StringComparison.InvariantCultureIgnoreCase));
}
if (!string.IsNullOrEmpty(file.Filename))
{
if (file.Delete())
{
NewMessage($"Deleting {file.Filename}", Color.Orange);
}
else
{
ThrowError($"Failed to delete {file.Filename}");
}
}
}));
commands.Add(new Command("resetall", "Reset all items and structures to prefabs. Only applicable in the subeditor.", args =>
{
if (Screen.Selected == GameMain.SubEditorScreen)
@@ -846,7 +873,7 @@ namespace Barotrauma
return;
}
if (Submarine.MainSub.SaveAs(System.IO.Path.Combine(SubmarineInfo.SavePath, fileName + ".sub")))
if (Submarine.MainSub.SaveAs(Barotrauma.IO.Path.Combine(SubmarineInfo.SavePath, fileName + ".sub")))
{
NewMessage("Sub saved", Color.Green);
}
@@ -1038,8 +1065,7 @@ namespace Barotrauma
foreach (var deconstructItem in itemPrefab.DeconstructItems)
{
var targetItem = MapEntityPrefab.Find(null, deconstructItem.ItemIdentifier, showErrorMessages: false) as ItemPrefab;
if (targetItem == null)
if (!(MapEntityPrefab.Find(null, deconstructItem.ItemIdentifier, showErrorMessages: false) is ItemPrefab targetItem))
{
ThrowError("Error in item \"" + itemPrefab.Name + "\" - could not find deconstruct item \"" + deconstructItem.ItemIdentifier + "\"!");
continue;
@@ -1054,9 +1080,14 @@ namespace Barotrauma
if (fabricationRecipe != null)
{
if (!fabricationRecipe.RequiredItems.Any(r => r.ItemPrefab == targetItem))
var ingredient = fabricationRecipe.RequiredItems.Find(r => r.ItemPrefab == targetItem);
if (ingredient == null)
{
NewMessage("Deconstructing \"" + itemPrefab.Name + "\" produces \"" + deconstructItem.ItemIdentifier + "\", which isn't required in the fabrication recipe of the item.", Color.Orange);
NewMessage("Deconstructing \"" + itemPrefab.Name + "\" produces \"" + deconstructItem.ItemIdentifier + "\", which isn't required in the fabrication recipe of the item.", Color.Red);
}
else if (ingredient.UseCondition && ingredient.MinCondition < deconstructItem.OutCondition)
{
NewMessage($"Deconstructing \"{itemPrefab.Name}\" produces more \"{deconstructItem.ItemIdentifier}\", than what's required to fabricate the item (required: {ingredient.ItemPrefab.Name} {(int)(ingredient.MinCondition * 100)}%, output: {deconstructItem.ItemIdentifier} {(int)(deconstructItem.OutCondition * 100)}%)", Color.Red);
}
}
}
@@ -1267,6 +1298,13 @@ namespace Barotrauma
TextManager.Language = "English";
}));
commands.Add(new Command("eventstats", "", (string[] args) =>
{
var debugLines = ScriptedEventSet.GetDebugStatistics();
string filePath = "eventstats.txt";
File.WriteAllLines(filePath, debugLines);
ToolBox.OpenFileWithShell(Path.GetFullPath(filePath));
}));
#if DEBUG
commands.Add(new Command("printreceivertransfers", "", (string[] args) =>
{
@@ -1440,7 +1478,7 @@ namespace Barotrauma
element.Value = lines[i];
i++;
}
doc.Save(destinationPath);
doc.SaveSafe(destinationPath);
},
() =>
{
@@ -1475,7 +1513,7 @@ namespace Barotrauma
while ((!(nextNode is XElement) || nextNode == element) && nextNode != null) nextNode = nextNode.NextNode;
destinationElement = nextNode as XElement;
}
destinationDoc.Save(destinationPath);
destinationDoc.SaveSafe(destinationPath);
},
() =>
{
@@ -1730,69 +1768,69 @@ namespace Barotrauma
GameMain.Config.SaveNewPlayerConfig();
var saveFiles = System.IO.Directory.GetFiles(SaveUtil.SaveFolder);
var saveFiles = Barotrauma.IO.Directory.GetFiles(SaveUtil.SaveFolder);
foreach (string saveFile in saveFiles)
{
System.IO.File.Delete(saveFile);
Barotrauma.IO.File.Delete(saveFile);
NewMessage("Deleted " + saveFile, Color.Green);
}
if (System.IO.Directory.Exists(System.IO.Path.Combine(SaveUtil.SaveFolder, "temp")))
if (Barotrauma.IO.Directory.Exists(Barotrauma.IO.Path.Combine(SaveUtil.SaveFolder, "temp")))
{
System.IO.Directory.Delete(System.IO.Path.Combine(SaveUtil.SaveFolder, "temp"), true);
Barotrauma.IO.Directory.Delete(Barotrauma.IO.Path.Combine(SaveUtil.SaveFolder, "temp"), true);
NewMessage("Deleted temp save folder", Color.Green);
}
if (System.IO.Directory.Exists(ServerLog.SavePath))
if (Barotrauma.IO.Directory.Exists(ServerLog.SavePath))
{
var logFiles = System.IO.Directory.GetFiles(ServerLog.SavePath);
var logFiles = Barotrauma.IO.Directory.GetFiles(ServerLog.SavePath);
foreach (string logFile in logFiles)
{
System.IO.File.Delete(logFile);
Barotrauma.IO.File.Delete(logFile);
NewMessage("Deleted " + logFile, Color.Green);
}
}
if (System.IO.File.Exists("filelist.xml"))
if (Barotrauma.IO.File.Exists("filelist.xml"))
{
System.IO.File.Delete("filelist.xml");
Barotrauma.IO.File.Delete("filelist.xml");
NewMessage("Deleted filelist", Color.Green);
}
if (System.IO.File.Exists("Data/bannedplayers.txt"))
if (Barotrauma.IO.File.Exists("Data/bannedplayers.txt"))
{
System.IO.File.Delete("Data/bannedplayers.txt");
Barotrauma.IO.File.Delete("Data/bannedplayers.txt");
NewMessage("Deleted bannedplayers.txt", Color.Green);
}
if (System.IO.File.Exists("Submarines/TutorialSub.sub"))
if (Barotrauma.IO.File.Exists("Submarines/TutorialSub.sub"))
{
System.IO.File.Delete("Submarines/TutorialSub.sub");
Barotrauma.IO.File.Delete("Submarines/TutorialSub.sub");
NewMessage("Deleted TutorialSub from the submarine folder", Color.Green);
}
/*if (System.IO.File.Exists(GameServer.SettingsFile))
/*if (Barotrauma.IO.File.Exists(GameServer.SettingsFile))
{
System.IO.File.Delete(GameServer.SettingsFile);
Barotrauma.IO.File.Delete(GameServer.SettingsFile);
NewMessage("Deleted server settings", Color.Green);
}
if (System.IO.File.Exists(GameServer.ClientPermissionsFile))
if (Barotrauma.IO.File.Exists(GameServer.ClientPermissionsFile))
{
System.IO.File.Delete(GameServer.ClientPermissionsFile);
Barotrauma.IO.File.Delete(GameServer.ClientPermissionsFile);
NewMessage("Deleted client permission file", Color.Green);
}*/
if (System.IO.File.Exists("crashreport.log"))
if (Barotrauma.IO.File.Exists("crashreport.log"))
{
System.IO.File.Delete("crashreport.log");
Barotrauma.IO.File.Delete("crashreport.log");
NewMessage("Deleted crashreport.log", Color.Green);
}
if (!System.IO.File.Exists("Content/Map/TutorialSub.sub"))
if (!Barotrauma.IO.File.Exists("Content/Map/TutorialSub.sub"))
{
ThrowError("TutorialSub.sub not found!");
}
@@ -1841,7 +1879,7 @@ namespace Barotrauma
"giveperm",
(string[] args) =>
{
if (args.Length < 1) return;
if (args.Length < 1) { return; }
NewMessage("Valid permissions are:", Color.White);
foreach (ClientPermissions permission in Enum.GetValues(typeof(ClientPermissions)))
@@ -1898,7 +1936,7 @@ namespace Barotrauma
{
if (args.Length < 1) return;
ShowQuestionPrompt("Console command permissions to grant to client " + args[0] + "? You may enter multiple commands separated with a space.", (commandNames) =>
ShowQuestionPrompt("Console command permissions to grant to client " + args[0] + "? You may enter multiple commands separated with a space or use \"all\" to give the permission to use all console commands.", (commandNames) =>
{
GameMain.Client?.SendConsoleCommand("givecommandperm " + args[0] + " " + commandNames);
}, args, 1);
@@ -1911,7 +1949,7 @@ namespace Barotrauma
{
if (args.Length < 1) return;
ShowQuestionPrompt("Console command permissions to revoke from client " + args[0] + "? You may enter multiple commands separated with a space.", (commandNames) =>
ShowQuestionPrompt("Console command permissions to revoke from client " + args[0] + "? You may enter multiple commands separated with a space or use \"all\" to revoke the permission to use any console commands.", (commandNames) =>
{
GameMain.Client?.SendConsoleCommand("revokecommandperm " + args[0] + " " + commandNames);
}, args, 1);
@@ -2206,7 +2244,7 @@ namespace Barotrauma
ThrowError("Cannot use the flipx command while playing online.");
return;
}
Submarine.MainSub?.FlipX();
if (Submarine.MainSub.SubBody != null) { Submarine.MainSub?.FlipX(); }
}, isCheat: true));
commands.Add(new Command("gender", "Set the gender of the controlled character. Allowed parameters: Male, Female, None.", args =>
@@ -2328,9 +2366,16 @@ namespace Barotrauma
}
try
{
SubmarineInfo subInfo = new SubmarineInfo(args[0]);
Submarine spawnedSub = Submarine.Load(subInfo, false);
spawnedSub.SetPosition(GameMain.GameScreen.Cam.ScreenToWorld(PlayerInput.MousePosition));
var subInfo = SubmarineInfo.SavedSubmarines.FirstOrDefault(s => s.DisplayName.Equals(args[0], StringComparison.OrdinalIgnoreCase));
if (subInfo == null)
{
ThrowError($"Could not find a submarine with the name \"{args[0]}\".");
}
else
{
Submarine spawnedSub = Submarine.Load(subInfo, false);
spawnedSub.SetPosition(GameMain.GameScreen.Cam.ScreenToWorld(PlayerInput.MousePosition));
}
}
catch (Exception e)
{
@@ -2338,7 +2383,15 @@ namespace Barotrauma
ThrowError(errorMsg, e);
GameAnalyticsManager.AddErrorEventOnce("DebugConsole.SpawnSubmarine:Error", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg + '\n' + e.Message + '\n' + e.StackTrace);
}
}, isCheat: true));
},
() =>
{
return new string[][]
{
SubmarineInfo.SavedSubmarines.Select(s => s.DisplayName).ToArray()
};
},
isCheat: true));
commands.Add(new Command("pause", "Toggles the pause state when playing offline", (string[] args) =>
{

View File

@@ -83,10 +83,6 @@ namespace Barotrauma
}
foreach (ScriptedEventSet eventSet in pendingEventSets)
{
float distanceTraveled = MathHelper.Clamp(
(Submarine.MainSub.WorldPosition.X - level.StartPosition.X) / (level.EndPosition.X - level.StartPosition.X),
0.0f, 1.0f);
GUI.DrawString(spriteBatch, new Vector2(graphRect.X, y), "New event (ID " + eventSet.DebugIdentifier + ") after: ", Color.Orange * 0.8f, null, 0, GUI.SmallFont);
y += 12;

View File

@@ -6,6 +6,7 @@ namespace Barotrauma
{
public override void ClientReadInitial(IReadMessage msg)
{
items.Clear();
ushort itemCount = msg.ReadUInt16();
for (int i = 0; i < itemCount; i++)
{
@@ -17,7 +18,7 @@ namespace Barotrauma
}
if (items.Count != itemCount)
{
throw new System.Exception("Error in CargoMission.ClientReadInitial: item count does not match the server count (" + itemCount + " != " + items.Count + "mission: " + Prefab.Identifier + ")");
throw new System.Exception("Error in CargoMission.ClientReadInitial: item count does not match the server count (" + itemCount + " != " + items.Count + ", mission: " + Prefab.Identifier + ")");
}
if (requiredDeliveryAmount == 0) { requiredDeliveryAmount = items.Count; }
}

View File

@@ -122,7 +122,7 @@ namespace Barotrauma
};
chatSendButton.RectTransform.AbsoluteOffset = new Point((int)(InputBox.Rect.Height * 0.15f), 0);
InputBox.TextBlock.RectTransform.MaxSize
= new Point((int)(InputBox.Rect.Width - chatSendButton.Rect.Width * 1.25f - InputBox.TextBlock.Padding.Z), int.MaxValue);
= new Point((int)(InputBox.Rect.Width - chatSendButton.Rect.Width * 1.25f - InputBox.TextBlock.Padding.X - chatSendButton.RectTransform.AbsoluteOffset.X), int.MaxValue);
showNewMessagesButton = new GUIButton(new RectTransform(new Vector2(1f, 0.075f), GUIFrame.RectTransform, Anchor.BottomCenter) { RelativeOffset = new Vector2(0.0f, 0.125f) }, TextManager.Get("chat.shownewmessages"));
showNewMessagesButton.OnClicked += (GUIButton btn, object userdata) =>
@@ -384,17 +384,6 @@ namespace Barotrauma
prevUIScale = GUI.Scale;
}
//hide chatbox when accessing the inventory of another character to prevent overlaps
if (Character.Controlled?.SelectedCharacter?.Inventory != null &&
Character.Controlled.SelectedCharacter.CanInventoryBeAccessed)
{
SetVisibility(false);
}
else
{
SetVisibility(true);
}
if (showNewMessagesButton.Visible && chatBox.ScrollBar.BarScroll == 1f)
{
showNewMessagesButton.Visible = false;

View File

@@ -1,7 +1,7 @@
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.IO;
using Barotrauma.IO;
using System.Linq;
using System.Text;
@@ -38,7 +38,7 @@ namespace Barotrauma
private static GUIDropDown fileTypeDropdown;
private static GUIButton openButton;
private static FileSystemWatcher fileSystemWatcher;
private static System.IO.FileSystemWatcher fileSystemWatcher;
private static string currentFileTypePattern;
@@ -78,10 +78,10 @@ namespace Barotrauma
currentDirectory += "/";
}
fileSystemWatcher?.Dispose();
fileSystemWatcher = new FileSystemWatcher(currentDirectory)
fileSystemWatcher = new System.IO.FileSystemWatcher(currentDirectory)
{
Filter = "*",
NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName
NotifyFilter = System.IO.NotifyFilters.LastWrite | System.IO.NotifyFilters.FileName | System.IO.NotifyFilters.DirectoryName
};
fileSystemWatcher.Created += OnFileSystemChanges;
fileSystemWatcher.Deleted += OnFileSystemChanges;
@@ -97,11 +97,11 @@ namespace Barotrauma
set;
}
private static void OnFileSystemChanges(object sender, FileSystemEventArgs e)
private static void OnFileSystemChanges(object sender, System.IO.FileSystemEventArgs e)
{
switch (e.ChangeType)
{
case WatcherChangeTypes.Created:
case System.IO.WatcherChangeTypes.Created:
{
var itemFrame = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), fileList.Content.RectTransform), e.Name)
{
@@ -114,15 +114,15 @@ namespace Barotrauma
fileList.Content.RectTransform.SortChildren(SortFiles);
}
break;
case WatcherChangeTypes.Deleted:
case System.IO.WatcherChangeTypes.Deleted:
{
var itemFrame = fileList.Content.FindChild(c => (c is GUITextBlock tb) && (tb.Text == e.Name || tb.Text == e.Name + "/"));
if (itemFrame != null) { fileList.RemoveChild(itemFrame); }
}
break;
case WatcherChangeTypes.Renamed:
case System.IO.WatcherChangeTypes.Renamed:
{
RenamedEventArgs renameArgs = e as RenamedEventArgs;
System.IO.RenamedEventArgs renameArgs = e as System.IO.RenamedEventArgs;
var itemFrame = fileList.Content.FindChild(c => (c is GUITextBlock tb) && (tb.Text == renameArgs.OldName || tb.Text == renameArgs.OldName + "/")) as GUITextBlock;
itemFrame.UserData = (bool?)Directory.Exists(e.FullPath);
itemFrame.Text = renameArgs.Name;
@@ -156,7 +156,7 @@ namespace Barotrauma
public static void Init()
{
backgroundFrame = new GUIFrame(new RectTransform(Vector2.One, GUI.Canvas), style: null)
backgroundFrame = new GUIFrame(new RectTransform(GUI.Canvas.RelativeSize, GUI.Canvas), style: null)
{
Color = Color.Black * 0.5f,
HoverColor = Color.Black * 0.5f,
@@ -169,10 +169,10 @@ namespace Barotrauma
var horizontalLayout = new GUILayoutGroup(new RectTransform(Vector2.One * 0.9f, window.RectTransform, Anchor.Center), true);
sidebar = new GUIListBox(new RectTransform(new Vector2(0.29f, 1.0f), horizontalLayout.RectTransform));
var drives = DriveInfo.GetDrives();
var drives = System.IO.DriveInfo.GetDrives();
foreach (var drive in drives)
{
if (drive.DriveType == DriveType.Ram) { continue; }
if (drive.DriveType == System.IO.DriveType.Ram) { continue; }
if (ignoredDrivePrefixes.Any(p => drive.Name.StartsWith(p))) { continue; }
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), sidebar.Content.RectTransform), drive.Name.Replace('\\','/'));
}

View File

@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using Barotrauma.IO;
using System.Linq;
using System.Xml.Linq;
using Barotrauma.CharacterEditor;
@@ -80,8 +80,8 @@ namespace Barotrauma
public static readonly string[] colorComponentLabels = { "R", "G", "B", "A" };
public static Vector2 ReferenceResolution => new Vector2(1920f, 1080f);
public static float Scale => (GameMain.GraphicsWidth / ReferenceResolution.X + GameMain.GraphicsHeight / ReferenceResolution.Y) / 2.0f * GameSettings.HUDScale;
public static float xScale => GameMain.GraphicsWidth / ReferenceResolution.X * GameSettings.HUDScale;
public static float Scale => (UIWidth / ReferenceResolution.X + GameMain.GraphicsHeight / ReferenceResolution.Y) / 2.0f * GameSettings.HUDScale;
public static float xScale => UIWidth / ReferenceResolution.X * GameSettings.HUDScale;
public static float yScale => GameMain.GraphicsHeight / ReferenceResolution.Y * GameSettings.HUDScale;
public static int IntScale(float f) => (int)(f * Scale);
public static int IntScaleFloor(float f) => (int)Math.Floor(f * Scale);
@@ -90,6 +90,23 @@ namespace Barotrauma
public static float VerticalAspectRatio => GameMain.GraphicsHeight / (float)GameMain.GraphicsWidth;
public static float RelativeHorizontalAspectRatio => HorizontalAspectRatio / (ReferenceResolution.X / ReferenceResolution.Y);
public static float RelativeVerticalAspectRatio => VerticalAspectRatio / (ReferenceResolution.Y / ReferenceResolution.X);
public static bool IsUltrawide => HorizontalAspectRatio > 2.0f;
public static int UIWidth
{
get
{
// Ultrawide
if (IsUltrawide)
{
return (int)(GameMain.GraphicsHeight * ReferenceResolution.X / ReferenceResolution.Y);
}
else
{
return GameMain.GraphicsWidth;
}
}
}
public static float SlicedSpriteScale
{
@@ -521,6 +538,37 @@ namespace Barotrauma
DrawString(spriteBatch, new Vector2(GameMain.GraphicsWidth - (int)anchorPivotStringSize.X - padding, yPos), anchorPivotString, Color.LightGreen, Color.Black, 0, SmallFont);
yPos += (int)anchorPivotStringSize.Y + padding / 2;
}
else
{
string guiScaleString = $"GUI.Scale: {Scale}";
string guixScaleString = $"GUI.xScale: {xScale}";
string guiyScaleString = $"GUI.yScale: {yScale}";
string relativeHorizontalAspectRatioString = $"RelativeHorizontalAspectRatio: {RelativeHorizontalAspectRatio}";
string relativeVerticalAspectRatioString = $"RelativeVerticalAspectRatio: {RelativeVerticalAspectRatio}";
Vector2 guiScaleStringSize = SmallFont.MeasureString(guiScaleString);
Vector2 guixScaleStringSize = SmallFont.MeasureString(guixScaleString);
Vector2 guiyScaleStringSize = SmallFont.MeasureString(guiyScaleString);
Vector2 relativeHorizontalAspectRatioStringSize = SmallFont.MeasureString(relativeHorizontalAspectRatioString);
Vector2 relativeVerticalAspectRatioStringSize = SmallFont.MeasureString(relativeVerticalAspectRatioString);
int padding = IntScale(10);
int yPos = padding;
DrawString(spriteBatch, new Vector2(GameMain.GraphicsWidth - (int)guiScaleStringSize.X - padding, yPos), guiScaleString, Color.LightGreen, Color.Black, 0, SmallFont);
yPos += (int)guiScaleStringSize.Y + padding / 2;
DrawString(spriteBatch, new Vector2(GameMain.GraphicsWidth - (int)guixScaleStringSize.X - padding, yPos), guixScaleString, Color.LightGreen, Color.Black, 0, SmallFont);
yPos += (int)guixScaleStringSize.Y + padding / 2;
DrawString(spriteBatch, new Vector2(GameMain.GraphicsWidth - (int)guiyScaleStringSize.X - padding, yPos), guiyScaleString, Color.LightGreen, Color.Black, 0, SmallFont);
yPos += (int)guiyScaleStringSize.Y + padding / 2;
DrawString(spriteBatch, new Vector2(GameMain.GraphicsWidth - (int)relativeHorizontalAspectRatioStringSize.X - padding, yPos), relativeHorizontalAspectRatioString, Color.LightGreen, Color.Black, 0, SmallFont);
yPos += (int)relativeHorizontalAspectRatioStringSize.Y + padding / 2;
DrawString(spriteBatch, new Vector2(GameMain.GraphicsWidth - (int)relativeVerticalAspectRatioStringSize.X - padding, yPos), relativeVerticalAspectRatioString, Color.LightGreen, Color.Black, 0, SmallFont);
yPos += (int)relativeVerticalAspectRatioStringSize.Y + padding / 2;
}
}
if (HUDLayoutSettings.DebugDraw) HUDLayoutSettings.Draw(spriteBatch);
@@ -1917,8 +1965,9 @@ namespace Barotrauma
Inventory.draggingItem = null;
Inventory.DraggingInventory = null;
PauseMenu = new GUIFrame(new RectTransform(Vector2.One, Canvas), style: null, color: Color.Black * 0.5f);
PauseMenu = new GUIFrame(new RectTransform(Vector2.One, Canvas, Anchor.Center), style: null);
new GUIFrame(new RectTransform(GUI.Canvas.RelativeSize, PauseMenu.RectTransform, Anchor.Center), style: "GUIBackgroundBlocker");
var pauseMenuInner = new GUIFrame(new RectTransform(new Vector2(0.13f, 0.3f), PauseMenu.RectTransform, Anchor.Center) { MinSize = new Point(250, 300) });
var buttonContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.7f, 0.6f), pauseMenuInner.RectTransform, Anchor.Center))

View File

@@ -8,7 +8,7 @@ namespace Barotrauma
{
public class GUICanvas : RectTransform
{
protected GUICanvas() : base(Vector2.One, parent: null) { }
protected GUICanvas() : base(size, parent: null) { }
private static GUICanvas _instance;
public static GUICanvas Instance
@@ -22,15 +22,63 @@ namespace Barotrauma
{
GameMain.Instance.OnResolutionChanged += RecalculateSize;
}
_instance.ItemComponentHolder = new GUIFrame(new RectTransform(Vector2.One, _instance, Anchor.Center)).RectTransform;
}
return _instance;
}
}
public RectTransform ItemComponentHolder;
private static Vector2 size => new Vector2(GameMain.GraphicsWidth / (float)GUI.UIWidth, 1f);
protected override Rectangle NonScaledUIRect => UIRect;
private enum ResizeAxis { Both = 0, X = 1, Y = 2 }
// Turn public, if there is a need to call this manually.
private static void RecalculateSize()
{
Instance.Resize(Vector2.One, resizeChildren: true);
Vector2 recalculatedSize = size;
// Scale children that are supposed to encompass the whole screen so that they are properly scaled on ultrawide as well
for (int i = 0; i < Instance.Children.Count(); i++)
{
RectTransform target = Instance.GetChild(i);
if (target == null || target.RelativeSize.X < 1 && target.RelativeSize.Y < 1) continue;
ResizeAxis axis;
if (target.RelativeSize.X >= 1 && target.RelativeSize.Y >= 1)
{
axis = ResizeAxis.Both;
}
else if (target.RelativeSize.X >= 1)
{
axis = ResizeAxis.X;
}
else
{
axis = ResizeAxis.Y;
}
switch (axis)
{
case ResizeAxis.Both:
target.RelativeSize = recalculatedSize;
break;
case ResizeAxis.X:
target.RelativeSize = new Vector2(recalculatedSize.X, target.RelativeSize.Y);
break;
case ResizeAxis.Y:
target.RelativeSize = new Vector2(target.RelativeSize.X, recalculatedSize.Y);
break;
}
}
Instance.Resize(size, resizeChildren: true);
Instance.GetAllChildren().Select(c => c.GUIComponent as GUITextBlock).ForEach(t => t?.SetTextPos());
}
}

View File

@@ -5,7 +5,7 @@ using System.Linq;
using Barotrauma.Extensions;
using System;
using System.Xml.Linq;
using System.IO;
using Barotrauma.IO;
using RestSharp;
using System.Net;

View File

@@ -394,7 +394,7 @@ namespace Barotrauma
if (Dropped)
{
listBox.AddToGUIUpdateList(false, UpdateOrder);
listBox.AddToGUIUpdateList(false, 1);
}
}

View File

@@ -10,7 +10,17 @@ namespace Barotrauma
public class GUIImage : GUIComponent
{
//paths of the textures that are being loaded asynchronously
private static readonly HashSet<string> activeTextureLoads = new HashSet<string>();
private static readonly List<string> activeTextureLoads = new List<string>();
private static bool loadingTextures;
public static bool LoadingTextures
{
get
{
return loadingTextures;
}
}
public float Rotation;
@@ -25,7 +35,7 @@ namespace Barotrauma
private bool lazyLoaded, loading;
public bool LoadAsynchronously;
public bool Crop
{
get
@@ -122,6 +132,7 @@ namespace Barotrauma
{
if (LoadAsynchronously)
{
loadingTextures = true;
loading = true;
TaskPool.Add(LoadTextureAsync(), (Task) =>
{
@@ -223,6 +234,7 @@ namespace Barotrauma
lock (activeTextureLoads)
{
activeTextureLoads.Remove(Sprite.FullPath);
loadingTextures = activeTextureLoads.Count > 0;
}
}
return true;

View File

@@ -76,19 +76,7 @@ namespace Barotrauma
public GUILayoutGroup(RectTransform rectT, bool isHorizontal = false, Anchor childAnchor = Anchor.TopLeft) : base(null, rectT)
{
#if DEBUG
if (GameMain.DebugDraw)
{
CanBeFocused = true;
}
else
{
#endif
CanBeFocused = false;
#if DEBUG
}
#endif
CanBeFocused = false;
this.isHorizontal = isHorizontal;
this.childAnchor = childAnchor;
rectT.ChildrenChanged += (child) => needsToRecalculate = true;

View File

@@ -11,7 +11,7 @@ namespace Barotrauma
public static List<GUIComponent> MessageBoxes = new List<GUIComponent>();
private static int DefaultWidth
{
get { return Math.Max(400, 400 * (GameMain.GraphicsWidth / 1920)); }
get { return Math.Max(400, (int)(400 * (GameMain.GraphicsWidth / GUI.ReferenceResolution.X))); }
}
private float inGameCloseTimer = 0.0f;
@@ -63,7 +63,7 @@ namespace Barotrauma
}
public GUIMessageBox(string headerText, string text, string[] buttons, Vector2? relativeSize = null, Point? minSize = null, Alignment textAlignment = Alignment.TopLeft, Type type = Type.Default, string tag = "", Sprite icon = null)
: base(new RectTransform(Vector2.One, GUI.Canvas, Anchor.Center), style: GUI.Style.GetComponentStyle("GUIMessageBox." + type) != null ? "GUIMessageBox." + type : "GUIMessageBox")
: base(new RectTransform(GUI.Canvas.RelativeSize, GUI.Canvas, Anchor.Center), style: GUI.Style.GetComponentStyle("GUIMessageBox." + type) != null ? "GUIMessageBox." + type : "GUIMessageBox")
{
int width = (int)(DefaultWidth * (type == Type.Default ? 1.0f : 1.5f)), height = 0;
if (relativeSize.HasValue)

View File

@@ -510,6 +510,8 @@ namespace Barotrauma
var currPosition = positions[0];
float topY = positions.Min(p => p.Item1.Y);
for (int i = 1; i < positions.Count; i++)
{
var p1 = positions[i];
@@ -527,7 +529,7 @@ namespace Barotrauma
else
{
diffY = Math.Abs(p1.Item1.Y - pos.Y);
if (diffY < halfHeight)
if (diffY < halfHeight || (p1.Item1.Y == topY && pos.Y < topY))
{
//we are on this line, select the nearest character
float diffX = Math.Abs(p1.Item1.X - pos.X) - Math.Abs(p2.Item1.X - pos.X);

View File

@@ -67,6 +67,8 @@ namespace Barotrauma
private Vector2 selectionEndPos;
private Vector2 selectionRectSize;
private bool mouseHeldInside;
private readonly Memento<string> memento = new Memento<string>();
// Skip one update cycle, fixes Enter key instantly deselecting the chatbox
@@ -414,6 +416,7 @@ namespace Barotrauma
State = ComponentState.Hover;
if (PlayerInput.PrimaryMouseButtonDown())
{
mouseHeldInside = true;
Select();
}
else
@@ -436,7 +439,11 @@ namespace Barotrauma
}
else
{
if ((PlayerInput.LeftButtonClicked() || PlayerInput.RightButtonClicked()) && selected) Deselect();
if ((PlayerInput.LeftButtonClicked() || PlayerInput.RightButtonClicked()) && selected)
{
if (!mouseHeldInside) { Deselect(); }
mouseHeldInside = false;
}
isSelecting = false;
State = ComponentState.None;
}

View File

@@ -50,10 +50,6 @@ namespace Barotrauma
get; private set;
}
/*public static Rectangle HealthBarAreaRight
{
get; private set;
}*/
public static Rectangle HealthBarArea
{
get; private set;
@@ -120,17 +116,11 @@ namespace Barotrauma
//horizontal slices at the corners of the screen for health bar and affliction icons
int afflictionAreaHeight = (int)(50 * GUI.Scale);
int healthBarWidth = BottomRightInfoArea.Width + CharacterInventory.SlotSize.X + CharacterInventory.Spacing * 2 + CharacterInventory.HideButtonWidth;
int healthBarWidth = (int)(BottomRightInfoArea.Width * 1.58f);
int healthBarHeight = (int)(50f * GUI.Scale);
HealthBarArea = new Rectangle(BottomRightInfoArea.X - (healthBarWidth - BottomRightInfoArea.Width) + (int)(2 * GUI.Scale), BottomRightInfoArea.Y - healthBarHeight + (int)(10 * GUI.Scale), healthBarWidth, healthBarHeight);
AfflictionAreaLeft = new Rectangle(HealthBarArea.X, HealthBarArea.Y - Padding - afflictionAreaHeight, HealthBarArea.Width, afflictionAreaHeight);
//HealthBarAreaRight = new Rectangle(Padding, GameMain.GraphicsHeight - healthBarHeight - Padding, healthBarWidth, healthBarHeight);
/*if (HealthBarAreaRight.Y + healthBarHeight * 0.75f < PortraitArea.Y)
{
HealthBarAreaRight = new Rectangle(GameMain.GraphicsWidth - Padding - healthBarWidth, HealthBarAreaRight.Y, HealthBarAreaRight.Width, HealthBarAreaRight.Height);
}*/
//AfflictionAreaRight = new Rectangle(HealthBarAreaRight.X, HealthBarAreaRight.Y + healthBarHeight + Padding, healthBarWidth, afflictionAreaHeight);
HealthBarArea = new Rectangle(BottomRightInfoArea.Right - healthBarWidth + (int)Math.Floor(1 / GUI.Scale), BottomRightInfoArea.Y - healthBarHeight + GUI.IntScale(10), healthBarWidth, healthBarHeight);
AfflictionAreaLeft = new Rectangle(HealthBarArea.X, HealthBarArea.Y - Padding - afflictionAreaHeight, HealthBarArea.Width, afflictionAreaHeight);
int messageAreaWidth = GameMain.GraphicsWidth / 3;
MessageAreaTop = new Rectangle((GameMain.GraphicsWidth - messageAreaWidth) / 2, ButtonAreaTop.Bottom, messageAreaWidth, ButtonAreaTop.Height);
@@ -146,7 +136,7 @@ namespace Barotrauma
CrewArea = new Rectangle(Padding, Padding, (int)Math.Max(400 * GUI.Scale, 220), ObjectiveAnchor.Top - Padding * 2);
InventoryAreaLower = new Rectangle(Padding, inventoryTopY, GameMain.GraphicsWidth - Padding * 2, GameMain.GraphicsHeight - inventoryTopY);
InventoryAreaLower = new Rectangle(ChatBoxArea.Right + Padding * 7, inventoryTopY, GameMain.GraphicsWidth - Padding * 9 - ChatBoxArea.Width, GameMain.GraphicsHeight - inventoryTopY);
int healthWindowWidth = (int)(GameMain.GraphicsWidth * 0.5f);
int healthWindowHeight = (int)(GameMain.GraphicsWidth * 0.5f * 0.65f);

View File

@@ -253,11 +253,12 @@ namespace Barotrauma
return _rect;
}
}
public Rectangle ParentRect => Parent != null ? Parent.Rect : ScreenRect;
public Rectangle ParentRect => Parent != null ? Parent.Rect : UIRect;
protected Rectangle NonScaledRect => new Rectangle(NonScaledTopLeft, NonScaledSize);
protected Rectangle NonScaledParentRect => parent != null ? Parent.NonScaledRect : ScreenRect;
protected Rectangle ScreenRect => new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight);
protected virtual Rectangle NonScaledUIRect => NonScaledRect;
protected Rectangle NonScaledParentRect => parent != null ? Parent.NonScaledRect : UIRect;
protected Rectangle NonScaledParentUIRect => parent != null ? Parent.NonScaledUIRect : UIRect;
protected Rectangle UIRect => new Rectangle(0, 0, GUI.UIWidth, GameMain.GraphicsHeight);
private Pivot pivot;
/// <summary>
@@ -444,14 +445,14 @@ namespace Barotrauma
protected void RecalculateRelativeSize()
{
relativeSize = new Vector2(NonScaledSize.X, NonScaledSize.Y) / new Vector2(NonScaledParentRect.Width, NonScaledParentRect.Height);
relativeSize = new Vector2(NonScaledSize.X, NonScaledSize.Y) / new Vector2(NonScaledParentUIRect.Width, NonScaledParentUIRect.Height);
recalculateRect = true;
SizeChanged?.Invoke();
}
protected void RecalculateAbsoluteSize()
{
Point size = NonScaledParentRect.Size;
Point size = NonScaledParentUIRect.Size;
switch (ScaleBasis)
{
case ScaleBasis.BothWidth:

View File

@@ -177,7 +177,8 @@ namespace Barotrauma
{
tabButtons.Clear();
infoFrame = new GUIFrame(new RectTransform(Vector2.One, GUI.Canvas), style: "GUIBackgroundBlocker");
infoFrame = new GUIFrame(new RectTransform(Vector2.One, GUI.Canvas, Anchor.Center), style: null);
new GUIFrame(new RectTransform(GUI.Canvas.RelativeSize, infoFrame.RectTransform, Anchor.Center), style: "GUIBackgroundBlocker");
switch (selectedTab)
{
@@ -488,6 +489,12 @@ namespace Barotrauma
Color = (GameMain.NetworkMember != null && GameMain.Client.Character == character) ? ownCharacterBGColor : Color.Transparent
};
frame.OnSecondaryClicked += (component, data) =>
{
GameMain.GameSession?.CrewManager?.CreateModerationContextMenu(PlayerInput.MousePosition.ToPoint(), client);
return true;
};
var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.9f), frame.RectTransform, Anchor.Center), isHorizontal: true)
{
AbsoluteSpacing = 2
@@ -593,6 +600,8 @@ namespace Barotrauma
{
GUITextBlock characterNameBlock;
Sprite permissionIcon = GetPermissionIcon(client);
JobPrefab prefab = client.Character?.Info?.Job?.Prefab;
Color nameColor = prefab != null ? prefab.UIColor : Color.White;
if (permissionIcon != null)
{
@@ -600,7 +609,7 @@ namespace Barotrauma
float characterNameWidthAdjustment = (iconSize.X + paddedFrame.AbsoluteSpacing) / characterColumnWidth;
characterNameBlock = new GUITextBlock(new RectTransform(new Point(characterColumnWidth, paddedFrame.Rect.Height), paddedFrame.RectTransform),
ToolBox.LimitString(client.Name, GUI.Font, (int)(characterColumnWidth - paddedFrame.Rect.Width * characterNameWidthAdjustment)), textAlignment: Alignment.Center, textColor: client.Character != null ? client.Character.Info.Job.Prefab.UIColor : Color.White);
ToolBox.LimitString(client.Name, GUI.Font, (int)(characterColumnWidth - paddedFrame.Rect.Width * characterNameWidthAdjustment)), textAlignment: Alignment.Center, textColor: nameColor);
float iconWidth = iconSize.X / (float)characterColumnWidth;
int xOffset = (int)(jobColumnWidth + characterNameBlock.TextPos.X - GUI.Font.MeasureString(characterNameBlock.Text).X / 2f - paddedFrame.AbsoluteSpacing - iconWidth * paddedFrame.Rect.Width);
@@ -609,7 +618,7 @@ namespace Barotrauma
else
{
characterNameBlock = new GUITextBlock(new RectTransform(new Point(characterColumnWidth, paddedFrame.Rect.Height), paddedFrame.RectTransform),
ToolBox.LimitString(client.Name, GUI.Font, characterColumnWidth), textAlignment: Alignment.Center, textColor: client.Character != null ? client.Character.Info.Job.Prefab.UIColor : Color.White);
ToolBox.LimitString(client.Name, GUI.Font, characterColumnWidth), textAlignment: Alignment.Center, textColor: nameColor);
}
if (client.Character != null && client.Character.IsDead)

View File

@@ -3,7 +3,7 @@ using Microsoft.Xna.Framework.Graphics;
using System;
using System.Xml.Linq;
using Barotrauma.Media;
using System.IO;
using Barotrauma.IO;
using Microsoft.Xna.Framework.Input;
namespace Barotrauma
@@ -56,7 +56,7 @@ namespace Barotrauma
public VideoPlayer() // GUI elements with size set to Point.Zero are resized based on content
{
int screenWidth = (int)(GameMain.GraphicsWidth * 0.55f);
int screenWidth = (int)(GameMain.GraphicsWidth * 0.65f);
scaledVideoResolution = new Point(screenWidth, (int)(screenWidth / 16f * 9f));
int width = scaledVideoResolution.X;
@@ -178,6 +178,7 @@ namespace Barotrauma
videoFrame.RectTransform.NonScaledSize = scaledVideoResolution + new Point(scaledBorderSize, scaledBorderSize);
videoView.RectTransform.NonScaledSize = scaledVideoResolution;
videoFrame.RectTransform.AbsoluteOffset = new Point(0, videoFrame.RectTransform.NonScaledSize.Y);
title.RectTransform.NonScaledSize = new Point(scaledTextWidth, scaledTitleHeight);
title.RectTransform.AbsoluteOffset = new Point((int)(5 * GUI.Scale), (int)(10 * GUI.Scale));
@@ -247,7 +248,7 @@ namespace Barotrauma
}
else
{
videoFrame.RectTransform.AbsoluteOffset = new Point(0, (int)(100 * GUI.Scale));
videoFrame.RectTransform.AbsoluteOffset = new Point(0, 0);
okButton = new GUIButton(new RectTransform(scaledButtonSize, videoFrame.RectTransform, Anchor.TopLeft, Pivot.TopLeft) { AbsoluteOffset = new Point(scaledBorderSize, scaledBorderSize) }, TextManager.Get("Back"))
{

View File

@@ -12,7 +12,7 @@ using System.Diagnostics;
using System.Linq;
using System.Reflection;
using GameAnalyticsSDK.Net;
using System.IO;
using Barotrauma.IO;
using System.Threading;
using Barotrauma.Tutorials;
using Barotrauma.Media;
@@ -532,6 +532,8 @@ namespace Barotrauma
ScriptedEventSet.LoadPrefabs();
AfflictionPrefab.LoadAll(GetFilesOfType(ContentType.Afflictions));
SkillSettings.Load(GetFilesOfType(ContentType.SkillSettings));
Order.Init();
EventManagerSettings.Init();
TitleScreen.LoadState = 50.0f;
yield return CoroutineStatus.Running;
@@ -860,7 +862,7 @@ namespace Barotrauma
//TODO: do we need to check Inventory.SelectedSlot?
&& Inventory.SelectedSlot == null && CharacterHealth.OpenHealthWindow == null
&& !CrewManager.IsCommandInterfaceOpen
&& !(Screen.Selected is SubEditorScreen editor && !editor.WiringMode && Character.Controlled.SelectedConstruction != null))
&& !(Screen.Selected is SubEditorScreen editor && !editor.WiringMode && Character.Controlled?.SelectedConstruction != null))
{
// Otherwise toggle pausing, unless another window/interface is open.
GUI.TogglePauseMenu();

View File

@@ -1264,7 +1264,7 @@ namespace Barotrauma
}
else
{
CreateCommandUI(HUDLayoutSettings.PortraitArea.Contains(PlayerInput.MousePosition) ? Character.Controlled : GUI.MouseOn?.UserData as Character);
CreateCommandUI(HUDLayoutSettings.BottomRightInfoArea.Contains(PlayerInput.MousePosition) ? Character.Controlled : GUI.MouseOn?.UserData as Character);
}
GUI.PlayUISound(GUISoundType.PopupMenu);
clicklessSelectionActive = isOpeningClick = true;
@@ -1288,18 +1288,9 @@ namespace Barotrauma
else if (PlayerInput.SecondaryMouseButtonClicked() && characterContext == null &&
(optionNodes.Any(n => GUI.IsMouseOn(n.Item1)) || shortcutNodes.Any(n => GUI.IsMouseOn(n))))
{
var node = optionNodes.Find(n => GUI.IsMouseOn(n.Item1))?.Item1;
if (node == null)
{
node = shortcutNodes.Find(n => GUI.IsMouseOn(n));
}
// Make sure the node is for an option-less order...
if (node.UserData is Order order && !order.HasOptions)
{
CreateAssignmentNodes(node);
}
// ...or an order option
else if (node.UserData is Tuple<Order, string>)
var node = optionNodes.Find(n => GUI.IsMouseOn(n.Item1))?.Item1 ?? shortcutNodes.Find(n => GUI.IsMouseOn(n));
// Make sure the node is for an option-less order or an order option
if ((node.UserData is Order order && !order.HasOptions && (!order.MustSetTarget || itemContext != null)) || node.UserData is Tuple<Order, string>)
{
CreateAssignmentNodes(node);
}
@@ -1543,31 +1534,31 @@ namespace Barotrauma
}
private GUIFrame commandFrame, targetFrame;
private GUIButton centerNode, returnNode, expandNode, shortcutCenterNode;
private List<Tuple<GUIComponent, Keys>> optionNodes = new List<Tuple<GUIComponent, Keys>>();
private readonly List<Tuple<GUIComponent, Keys>> optionNodes = new List<Tuple<GUIComponent, Keys>>();
private Keys returnNodeHotkey = Keys.None, expandNodeHotkey = Keys.None;
private List<GUIComponent> shortcutNodes = new List<GUIComponent>();
private List<GUIComponent> extraOptionNodes = new List<GUIComponent>();
private readonly List<GUIComponent> shortcutNodes = new List<GUIComponent>();
private readonly List<GUIComponent> extraOptionNodes = new List<GUIComponent>();
private GUICustomComponent nodeConnectors;
private GUIImage background;
private GUIButton selectedNode;
private float selectionTime = 0.75f, timeSelected = 0.0f;
private readonly float selectionTime = 0.75f;
private float timeSelected = 0.0f;
private bool clicklessSelectionActive, isOpeningClick, isSelectionHighlighted;
private Point centerNodeSize, nodeSize, shortcutCenterNodeSize, shortcutNodeSize, returnNodeSize;
private Point centerNodeSize, nodeSize, shortcutCenterNodeSize, shortcutNodeSize, returnNodeSize, assignmentNodeSize;
private float centerNodeMargin, optionNodeMargin, shortcutCenterNodeMargin, shortcutNodeMargin, returnNodeMargin;
private List<OrderCategory> availableCategories;
private Stack<GUIButton> historyNodes = new Stack<GUIButton>();
private List<Character> extraOptionCharacters = new List<Character>();
private readonly List<Character> extraOptionCharacters = new List<Character>();
/// <summary>
/// node.Color = node.HighlightColor * nodeColorMultiplier
/// </summary>
private const float nodeColorMultiplier = 0.75f;
private const int assignmentNodeMaxCount = 8;
private int nodeDistance = (int)(GUI.Scale * 250);
private float returnNodeDistanceModifier = 0.65f;
private const float returnNodeDistanceModifier = 0.65f;
private Order dismissedOrderPrefab;
private Character characterContext;
private Item itemContext;
@@ -1576,6 +1567,7 @@ namespace Barotrauma
private readonly List<Order> contextualOrders = new List<Order>();
private Point shorcutCenterNodeOffset;
private const int maxShorcutNodeCount = 4;
private bool WasCommandInterfaceDisabledThisUpdate { get; set; }
private bool CanIssueOrders
{
@@ -1584,7 +1576,7 @@ namespace Barotrauma
#if DEBUG
return Character.Controlled == null || Character.Controlled.Info != null && Character.Controlled.SpeechImpediment < 100.0f;
#else
return Character.Controlled != null && Character.Controlled.SpeechImpediment < 100.0f;
return Character.Controlled?.Info != null && Character.Controlled.SpeechImpediment < 100.0f;
#endif
}
}
@@ -1743,16 +1735,21 @@ namespace Barotrauma
private void ScaleCommandUI()
{
centerNodeSize = new Point((int)(100 * GUI.Scale));
// Node sizes
nodeSize = new Point((int)(100 * GUI.Scale));
shortcutCenterNodeSize = new Point((int)(48 * GUI.Scale));
shortcutNodeSize = new Point((int)(64 * GUI.Scale));
centerNodeSize = nodeSize;
returnNodeSize = new Point((int)(48 * GUI.Scale));
assignmentNodeSize = new Point((int)(64 * GUI.Scale));
shortcutCenterNodeSize = returnNodeSize;
shortcutNodeSize = assignmentNodeSize;
// Node margins (used in drawing the connecting lines)
centerNodeMargin = centerNodeSize.X * 0.5f;
optionNodeMargin = nodeSize.X * 0.5f;
shortcutCenterNodeMargin = shortcutCenterNodeSize.X * 0.45f;
shortcutNodeMargin = shortcutNodeSize.X * 0.5f;
returnNodeMargin = returnNodeSize.X * 0.5f;
nodeDistance = (int)(150 * GUI.Scale);
shorcutCenterNodeOffset = new Point(0, (int)(1.25f * nodeDistance));
}
@@ -1783,12 +1780,12 @@ namespace Barotrauma
{
if (centerNode == null || optionNodes == null) { return; }
var startNodePos = centerNode.Rect.Center.ToVector2();
if (targetFrame == null || !targetFrame.Visible)
// Don't draw connectors for mini map options or assignment nodes
if ((targetFrame == null || !targetFrame.Visible) && !(optionNodes.FirstOrDefault()?.Item1.UserData is Character))
{
optionNodes.ForEach(n => DrawNodeConnector(startNodePos, centerNodeMargin, n.Item1, optionNodeMargin, spriteBatch));
}
DrawNodeConnector(startNodePos, centerNodeMargin, returnNode, returnNodeMargin, spriteBatch);
DrawNodeConnector(startNodePos, centerNodeMargin, expandNode, optionNodeMargin, spriteBatch);
if (shortcutCenterNode == null || !shortcutCenterNode.Visible) { return; }
DrawNodeConnector(startNodePos, centerNodeMargin, shortcutCenterNode, shortcutCenterNodeMargin, spriteBatch);
startNodePos = shortcutCenterNode.Rect.Center.ToVector2();
@@ -1850,6 +1847,7 @@ namespace Barotrauma
shortcutNodes.Remove(node);
};
RemoveOptionNodes();
if (returnNode != null)
{
returnNode.RemoveChild(returnNode.GetChildByUserData("hotkey"));
@@ -1857,15 +1855,20 @@ namespace Barotrauma
returnNode.Visible = false;
historyNodes.Push(returnNode);
}
SetReturnNode(centerNode, new Point(
(int)(node.RectTransform.AbsoluteOffset.X * -returnNodeDistanceModifier),
(int)(node.RectTransform.AbsoluteOffset.Y * -returnNodeDistanceModifier)));
// When the mini map is shown, always position the return node on the bottom
var offset = node?.UserData is Order order && order.GetMatchingItems(true).Count > 1 ?
new Point(0, (int)(returnNodeDistanceModifier * nodeDistance)) :
node.RectTransform.AbsoluteOffset.Multiply(-returnNodeDistanceModifier);
SetReturnNode(centerNode, offset);
SetCenterNode(node);
if (shortcutCenterNode != null)
{
commandFrame.RemoveChild(shortcutCenterNode);
shortcutCenterNode = null;
}
CreateNodes(userData);
CreateReturnNodeHotkey();
return true;
@@ -1914,9 +1917,14 @@ namespace Barotrauma
}
}
private void SetCenterNode(GUIButton node)
private void SetCenterNode(GUIButton node, bool resetAnchor = false)
{
node.RectTransform.Parent = commandFrame.RectTransform;
if (resetAnchor)
{
node.RectTransform.SetPosition(Anchor.Center);
}
node.RectTransform.SetPosition(Anchor.Center);
node.RectTransform.MoveOverTime(Point.Zero, CommandNodeAnimDuration);
node.RectTransform.ScaleOverTime(centerNodeSize, CommandNodeAnimDuration);
node.RemoveChild(node.GetChildByUserData("hotkey"));
@@ -2021,14 +2029,13 @@ namespace Barotrauma
private void CreateShortcutNodes()
{
var sub = Character.Controlled != null && Character.Controlled.TeamID == Character.TeamType.Team2 && Submarine.MainSubs.Length > 1 ?
Submarine.MainSubs[1] : Submarine.MainSub;
Submarine sub = GetTargetSubmarine();
if (sub == null) { return; }
shortcutNodes.Clear();
if (shortcutNodes.Count < maxShorcutNodeCount && sub.GetItems(false).Find(i => i.HasTag("reactor"))?.GetComponent<Reactor>() is Reactor reactor)
if (shortcutNodes.Count < maxShorcutNodeCount && sub.GetItems(false).Find(i => i.HasTag("reactor") && !i.NonInteractable)?.GetComponent<Reactor>() is Reactor reactor)
{
var reactorOutput = -reactor.CurrPowerConsumption;
// If player is not an engineer AND the reactor is not powered up AND nobody is using the reactor
@@ -2037,8 +2044,9 @@ namespace Barotrauma
reactorOutput < float.Epsilon && characters.None(c => c.SelectedConstruction == reactor.Item))
{
var order = new Order(Order.GetPrefab("operatereactor"), reactor.Item, reactor, Character.Controlled);
var option = order.Prefab.Options[0];
shortcutNodes.Add(
CreateOrderOptionNode(shortcutNodeSize, null, Point.Zero, order, order.Prefab.Options[0], order.Prefab.OptionNames[0], -1));
CreateOrderOptionNode(shortcutNodeSize, null, Point.Zero, order, option, order.Prefab.GetOptionName(option), -1));
}
}
@@ -2046,7 +2054,7 @@ namespace Barotrauma
// If player is not a captain AND nobody is using the nav terminal AND the nav terminal is powered up
// --> Create shortcut node for Steer order
if (shortcutNodes.Count < maxShorcutNodeCount && (Character.Controlled == null || Character.Controlled.Info.Job.Prefab != JobPrefab.Get("captain")) &&
sub.GetItems(false).Find(i => i.HasTag("navterminal")) is Item nav && characters.None(c => c.SelectedConstruction == nav) &&
sub.GetItems(false).Find(i => i.HasTag("navterminal") && !i.NonInteractable) is Item nav && characters.None(c => c.SelectedConstruction == nav) &&
nav.GetComponent<Steering>() is Steering steering && steering.Voltage > steering.MinVoltage)
{
shortcutNodes.Add(
@@ -2097,7 +2105,10 @@ namespace Barotrauma
(n.UserData is Tuple<Order, string> orderWithOption && orderWithOption.Item1.Identifier == orderIdentifier)) &&
!orderPrefab.TargetAllCharacters && orderPrefab.Category != null)
{
shortcutNodes.Add(CreateOrderNode(shortcutNodeSize, null, Point.Zero, orderPrefab, -1));
if (!orderPrefab.MustSetTarget || orderPrefab.GetMatchingItems(sub, true).Any())
{
shortcutNodes.Add(CreateOrderNode(shortcutNodeSize, null, Point.Zero, orderPrefab, -1));
}
if (shortcutNodes.Count >= maxShorcutNodeCount) { break; }
}
}
@@ -2129,16 +2140,19 @@ namespace Barotrauma
private void CreateOrderNodes(OrderCategory orderCategory)
{
// TODO: Save the available orders for each category so we don't have to check them again during the same game?
var orders = Order.PrefabList.FindAll(o => o.Category == orderCategory && !o.TargetAllCharacters);
orders.RemoveAll(o => (o.ItemComponentType != null || o.ItemIdentifiers.Length > 0) && o.MustSetTarget && o.GetMatchingItems(true).None());
Order order;
bool disableNode;
var offsets = MathUtils.GetPointsOnCircumference(Vector2.Zero, nodeDistance,
GetCircumferencePointCount(orders.Count), GetFirstNodeAngle(orders.Count));
for (int i = 0; i < orders.Count; i++)
{
order = orders[i];
disableNode = !CanSomeoneHearCharacter() ||
(order.MustSetTarget && (order.ItemComponentType != null || order.ItemIdentifiers.Length > 0) && order.GetMatchingItems(true).None());
optionNodes.Add(new Tuple<GUIComponent, Keys>(
CreateOrderNode(nodeSize, commandFrame.RectTransform, offsets[i].ToPoint(), orders[i], (i + 1) % 10),
CanSomeoneHearCharacter() ? Keys.D0 + (i + 1) % 10 : Keys.None));
CreateOrderNode(nodeSize, commandFrame.RectTransform, offsets[i].ToPoint(), order, (i + 1) % 10, disableNode: disableNode, checkIfOrderCanBeHeard: false),
!disableNode ? Keys.D0 + (i + 1) % 10 : Keys.None));
}
}
@@ -2150,7 +2164,7 @@ namespace Barotrauma
if (contextualOrders.None())
{
// Check if targeting an item or a hull
if (itemContext != null)
if (itemContext != null && !itemContext.NonInteractable)
{
foreach (Order p in Order.PrefabList)
{
@@ -2165,11 +2179,11 @@ namespace Barotrauma
// If targeting a periscope connected to a turret, show the 'operateweapons' order
var orderIdentifier = "operateweapons";
var operateWeaponsPrefab = Order.GetPrefab(orderIdentifier);
if (contextualOrders.None(o => o.Identifier.Equals(orderIdentifier)) && itemContext.Components.Any(c => c is Controller) &&
(itemContext.GetConnectedComponents<Turret>().Any(c => operateWeaponsPrefab.ItemIdentifiers.Contains(c.Item.Prefab.Identifier)) ||
itemContext.GetConnectedComponents<Turret>(recursive: true).Any(c => operateWeaponsPrefab.ItemIdentifiers.Contains(c.Item.Prefab.Identifier))))
if (contextualOrders.None(o => o.Identifier.Equals(orderIdentifier)) && itemContext.Components.Any(c => c is Controller))
{
contextualOrders.Add(operateWeaponsPrefab);
var turret = itemContext.GetConnectedComponents<Turret>().FirstOrDefault(c => operateWeaponsPrefab.ItemIdentifiers.Contains(c.Item.Prefab.Identifier)) ??
itemContext.GetConnectedComponents<Turret>(recursive: true).FirstOrDefault(c => operateWeaponsPrefab.ItemIdentifiers.Contains(c.Item.Prefab.Identifier));
if (turret != null) { contextualOrders.Add(new Order(operateWeaponsPrefab, turret.Item, turret, Character.Controlled)); }
}
// If targeting a repairable item, show the 'repairsystems' order
@@ -2193,6 +2207,14 @@ namespace Barotrauma
{
contextualOrders.Add(new Order(Order.GetPrefab(orderIdentifier), itemContext, null, Character.Controlled));
}
// Remove the 'pumpwater' order if the target pump is auto-controlled (as it will immediately overwrite the work done by the bot)
orderIdentifier = "pumpwater";
if (contextualOrders.FirstOrDefault(o => o.Identifier.Equals(orderIdentifier)) is Order o &&
itemContext.Components.FirstOrDefault(c => c.GetType() == o.ItemComponentType) is Pump pump)
{
if (pump.IsAutoControlled) { contextualOrders.Remove(o); }
}
}
else if(hullContext != null)
{
@@ -2218,11 +2240,12 @@ namespace Barotrauma
}
var offsets = MathUtils.GetPointsOnCircumference(Vector2.Zero, nodeDistance, contextualOrders.Count, MathHelper.ToRadians(90f + 180f / contextualOrders.Count));
bool disableNode = !CanSomeoneHearCharacter();
for (int i = 0; i < contextualOrders.Count; i++)
{
optionNodes.Add(new Tuple<GUIComponent, Keys>(
CreateOrderNode(nodeSize, commandFrame.RectTransform, offsets[i].ToPoint(), contextualOrders[i], (i + 1) % 10),
CanSomeoneHearCharacter() ? Keys.D0 + (i + 1) % 10 : Keys.None));
CreateOrderNode(nodeSize, commandFrame.RectTransform, offsets[i].ToPoint(), contextualOrders[i], (i + 1) % 10, disableNode: disableNode, checkIfOrderCanBeHeard: false),
!disableNode ? Keys.D0 + (i + 1) % 10 : Keys.None));
}
}
@@ -2239,7 +2262,7 @@ namespace Barotrauma
item.GetConnectedComponents<Turret>(recursive: true).Any(c => operateWeaponsPrefab.ItemIdentifiers.Contains(c.Item.Prefab.Identifier)));
}
private GUIButton CreateOrderNode(Point size, RectTransform parent, Point offset, Order order, int hotkey)
private GUIButton CreateOrderNode(Point size, RectTransform parent, Point offset, Order order, int hotkey, bool disableNode = false, bool checkIfOrderCanBeHeard = true)
{
var node = new GUIButton(
new RectTransform(size, parent: parent, anchor: Anchor.Center), style: null)
@@ -2249,16 +2272,17 @@ namespace Barotrauma
node.RectTransform.MoveOverTime(offset, CommandNodeAnimDuration);
var canSomeoneHearCharacter = CanSomeoneHearCharacter();
if (checkIfOrderCanBeHeard && !disableNode) { disableNode = !CanSomeoneHearCharacter(); }
var mustSetOptionOrTarget = order.HasOptions || (order.MustSetTarget && itemContext == null);
node.OnClicked = (button, userData) =>
{
if (!canSomeoneHearCharacter || !CanIssueOrders) { return false; }
if (disableNode || !CanIssueOrders) { return false; }
var o = userData as Order;
if (o.MustManuallyAssign && characterContext == null)
{
CreateAssignmentNodes(node);
}
else if (o.HasOptions)
else if (mustSetOptionOrTarget)
{
NavigateForward(button, userData);
}
@@ -2270,11 +2294,11 @@ namespace Barotrauma
return true;
};
var icon = CreateNodeIcon(node.RectTransform, order.SymbolSprite, order.Color,
tooltip: order.HasOptions || characterContext != null ? order.Name : order.Name +
tooltip: mustSetOptionOrTarget || characterContext != null ? order.Name : order.Name +
"\n" + (!PlayerInput.MouseButtonsSwapped() ? TextManager.Get("input.leftmouse") : TextManager.Get("input.rightmouse")) + ": " + TextManager.Get("commandui.quickassigntooltip") +
"\n" + (!PlayerInput.MouseButtonsSwapped() ? TextManager.Get("input.rightmouse") : TextManager.Get("input.leftmouse")) + ": " + TextManager.Get("commandui.manualassigntooltip"));
if (!canSomeoneHearCharacter)
if (disableNode)
{
node.CanBeFocused = icon.CanBeFocused = false;
CreateBlockIcon(node.RectTransform);
@@ -2288,11 +2312,7 @@ namespace Barotrauma
private void CreateOrderOptions(Order order)
{
// This is largely based on the CreateOrderTargetFrame() method
Submarine submarine = Character.Controlled != null && Character.Controlled.TeamID == Character.TeamType.Team2 && Submarine.MainSubs.Length > 1 ?
Submarine.MainSubs[1] :
Submarine.MainSub;
Submarine submarine = GetTargetSubmarine();
var matchingItems = (itemContext == null && order.MustSetTarget) ? order.GetMatchingItems(submarine, true) : new List<Item>();
//more than one target item -> create a minimap-like selection with a pic of the sub
@@ -2332,7 +2352,7 @@ namespace Barotrauma
UserData = submarine
};
List<GUIComponent> optionFrames = new List<GUIComponent>();
List<GUIComponent> optionElements = new List<GUIComponent>();
foreach (Item item in matchingItems)
{
var itemTargetFrame = targetFrame.Children.First().FindChild(item);
@@ -2353,52 +2373,87 @@ namespace Barotrauma
anchor = Anchor.TopRight;
}
var optionFrame = new GUIFrame(
new RectTransform(
new Point((int)(250 * GUI.Scale), (int)((40 + order.Options.Length * 40) * GUI.Scale)),
parent: itemTargetFrame.RectTransform,
anchor: anchor),
style: "InnerFrame");
new GUIFrame(
new RectTransform(Vector2.One, optionFrame.RectTransform, anchor: Anchor.Center),
style: "OuterGlow",
color: Color.Black * 0.7f);
var optionContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.9f), optionFrame.RectTransform, anchor: Anchor.Center))
GUIComponent optionElement;
if (order.Options.Length > 1)
{
RelativeSpacing = 0.05f,
Stretch = true
};
optionElement = new GUIFrame(
new RectTransform(
new Point((int)(250 * GUI.Scale), (int)((40 + order.Options.Length * 40) * GUI.Scale)),
parent: itemTargetFrame.RectTransform,
anchor: anchor),
style: "InnerFrame");
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.3f), optionContainer.RectTransform), item != null ? item.Name : order.Name);
new GUIFrame(
new RectTransform(Vector2.One, optionElement.RectTransform, anchor: Anchor.Center),
style: "OuterGlow",
color: Color.Black * 0.7f);
for (int i = 0; i < order.Options.Length; i++)
{
optionNodes.Add(new Tuple<GUIComponent, Keys>(
new GUIButton(
new RectTransform(new Vector2(1.0f, 0.2f), optionContainer.RectTransform),
text: order.OptionNames[i],
style: "GUITextBox")
{
UserData = new Tuple<Order, string>(
item == null ? order : new Order(order, item, item.Components.FirstOrDefault(ic => ic.GetType() == order.ItemComponentType)),
order.Options[i]),
Font = GUI.SmallFont,
OnClicked = (_, userData) =>
var optionContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.9f), optionElement.RectTransform, anchor: Anchor.Center))
{
RelativeSpacing = 0.05f,
Stretch = true
};
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.3f), optionContainer.RectTransform), item != null ? item.Name : order.Name);
for (int i = 0; i < order.Options.Length; i++)
{
optionNodes.Add(new Tuple<GUIComponent, Keys>(
new GUIButton(
new RectTransform(new Vector2(1.0f, 0.2f), optionContainer.RectTransform),
text: order.GetOptionName(i),
style: "GUITextBox")
{
if (!CanIssueOrders) { return false; }
var o = userData as Tuple<Order, string>;
SetCharacterOrder(characterContext ?? GetCharacterForQuickAssignment(o.Item1), o.Item1, o.Item2, Character.Controlled);
DisableCommandUI();
return true;
}
},
Keys.None));
UserData = new Tuple<Order, string>(
item == null ? order : new Order(order, item, item.Components.FirstOrDefault(ic => ic.GetType() == order.ItemComponentType)),
order.Options[i]),
Font = GUI.SmallFont,
OnClicked = (_, userData) =>
{
if (!CanIssueOrders) { return false; }
var o = userData as Tuple<Order, string>;
SetCharacterOrder(characterContext ?? GetCharacterForQuickAssignment(o.Item1), o.Item1, o.Item2, Character.Controlled);
DisableCommandUI();
return true;
}
},
Keys.None));
}
}
optionFrames.Add(optionFrame);
else
{
var userData = new Tuple<Order, string>(item == null ? order : new Order(order, item, item.Components.FirstOrDefault(ic => ic.GetType() == order.ItemComponentType)), "");
optionElement = new GUIButton(
new RectTransform(
new Point((int)(50 * GUI.Scale)),
parent: itemTargetFrame.RectTransform,
anchor: anchor),
style: null)
{
UserData = userData,
Font = GUI.SmallFont,
ToolTip = item?.Name ?? order.Name,
OnClicked = (_, userData) =>
{
if (!CanIssueOrders) { return false; }
var o = userData as Tuple<Order, string>;
SetCharacterOrder(characterContext ?? GetCharacterForQuickAssignment(o.Item1), o.Item1, o.Item2, Character.Controlled);
DisableCommandUI();
return true;
}
};
Sprite icon = null;
order.MinimapIcons?.TryGetValue(item.Prefab.Identifier, out icon);
var colorMultiplier = characters.Any(c => c.CurrentOrder != null &&
c.CurrentOrder.Identifier == userData.Item1.Identifier &&
c.CurrentOrder.TargetEntity == userData.Item1.TargetEntity) ? 0.5f : 1f;
CreateNodeIcon(optionElement.RectTransform, icon ?? order.SymbolSprite, order.Color * colorMultiplier);
optionNodes.Add(new Tuple<GUIComponent, Keys>(optionElement, Keys.None));
}
optionElements.Add(optionElement);
}
GUI.PreventElementOverlap(optionFrames, clampArea: new Rectangle(10, 10, GameMain.GraphicsWidth - 20, GameMain.GraphicsHeight - 20));
GUI.PreventElementOverlap(optionElements, clampArea: new Rectangle(10, 10, GameMain.GraphicsWidth - 20, GameMain.GraphicsHeight - 20));
var shadow = new GUIFrame(
new RectTransform(targetFrame.Rect.Size + new Point((int)(200 * GUI.Scale)), targetFrame.RectTransform, anchor: Anchor.Center),
@@ -2420,7 +2475,7 @@ namespace Barotrauma
for (int i = 0; i < order.Options.Length; i++)
{
optionNodes.Add(new Tuple<GUIComponent, Keys>(
CreateOrderOptionNode(nodeSize, commandFrame.RectTransform, offsets[offsetIndex++].ToPoint(), o, order.Options[i], order.OptionNames[i], (i + 1) % 10),
CreateOrderOptionNode(nodeSize, commandFrame.RectTransform, offsets[offsetIndex++].ToPoint(), o, order.Options[i], order.GetOptionName(i), (i + 1) % 10),
Keys.D0 + (i + 1) % 10));
}
}
@@ -2428,12 +2483,7 @@ namespace Barotrauma
private GUIButton CreateOrderOptionNode(Point size, RectTransform parent, Point offset, Order order, string option, string optionName, int hotkey)
{
var node = new GUIButton(
new RectTransform(size, parent: parent, anchor: Anchor.Center)
{
AbsoluteOffset = offset
},
style: null)
var node = new GUIButton(new RectTransform(size, parent: parent, anchor: Anchor.Center), style: null)
{
UserData = new Tuple<Order, string>(order, option),
OnClicked = (_, userData) =>
@@ -2445,6 +2495,8 @@ namespace Barotrauma
return true;
}
};
node.RectTransform.MoveOverTime(offset, CommandNodeAnimDuration);
GUIImage icon = null;
if (order.Prefab.OptionSprites.TryGetValue(option, out Sprite sprite))
{
@@ -2472,40 +2524,47 @@ namespace Barotrauma
new Tuple<Order, string>(node.UserData as Order, null) :
node.UserData as Tuple<Order, string>;
var characters = GetCharactersForManualAssignment(order.Item1);
if (characters.Count < 1) { return; }
if (characters.None()) { return; }
if (!(optionNodes.Find(n => n.Item1 == node) is Tuple<GUIComponent, Keys> optionNode) || !optionNodes.Remove(optionNode))
{
shortcutNodes.Remove(node);
};
RemoveOptionNodes();
if (returnNode != null)
{
returnNode.Children.ForEach(child => child.Visible = false);
returnNode.Visible = false;
historyNodes.Push(returnNode);
}
SetReturnNode(centerNode, new Point(
(int)(node.RectTransform.AbsoluteOffset.X * -returnNodeDistanceModifier),
(int)(node.RectTransform.AbsoluteOffset.Y * -returnNodeDistanceModifier)));
SetReturnNode(centerNode, new Point(0, (int)(returnNodeDistanceModifier * nodeDistance)));
if (targetFrame == null || !targetFrame.Visible)
{
SetCenterNode(node as GUIButton);
}
else
{
var clickedOptionNode = new GUIButton(
if (string.IsNullOrEmpty(order.Item2))
{
SetCenterNode(node as GUIButton, resetAnchor: true);
}
else
{
var clickedOptionNode = new GUIButton(
new RectTransform(centerNodeSize, parent: commandFrame.RectTransform, anchor: Anchor.Center),
style: null)
{
UserData = node.UserData
};
if (order.Item1.Prefab.OptionSprites.TryGetValue(order.Item2, out Sprite sprite))
{
CreateNodeIcon(clickedOptionNode.RectTransform, sprite, order.Item1.Color, tooltip: order.Item2);
{
UserData = node.UserData
};
if (order.Item1.Prefab.OptionSprites.TryGetValue(order.Item2, out Sprite sprite))
{
CreateNodeIcon(clickedOptionNode.RectTransform, sprite, order.Item1.Color, tooltip: order.Item2);
}
SetCenterNode(clickedOptionNode);
node = null;
}
SetCenterNode(clickedOptionNode);
node = null;
targetFrame.Visible = false;
}
if (shortcutCenterNode != null)
@@ -2514,21 +2573,36 @@ namespace Barotrauma
shortcutCenterNode = null;
}
var needToExpand = characters.Count > assignmentNodeMaxCount + 1;
var nodeCount = needToExpand ? assignmentNodeMaxCount + 1 : characters.Count;
var extraNodeDistance = Math.Max(nodeCount - 6, 0) * (GUI.Scale * 30);
var offsets = MathUtils.GetPointsOnCircumference(Vector2.Zero, nodeDistance + extraNodeDistance,
GetCircumferencePointCount(nodeCount),
GetFirstNodeAngle(nodeCount));
var i = 0;
var assignmentNodeCount = (needToExpand ? nodeCount - 1 : nodeCount);
for (; i < assignmentNodeCount; i++)
var characterCount = characters.Count;
int hotkey = 1;
Vector2[] offsets;
var needToExpand = characterCount > 10;
if (characterCount > 5)
{
CreateAssignmentNode(order, characters[i], offsets[i].ToPoint(), (i + 1) % 10);
// First ring
var charactersOnFirstRing = needToExpand ? 5 : (int)Math.Floor(characterCount / 2f);
offsets = GetAssignmentNodeOffsets(charactersOnFirstRing);
for (int i = 0; i < charactersOnFirstRing; i++)
{
CreateAssignmentNode(order, characters[i], offsets[i].ToPoint(), hotkey++ % 10);
}
// Second ring
var charactersOnSecondRing = needToExpand ? 4 : characterCount - charactersOnFirstRing;
offsets = GetAssignmentNodeOffsets(needToExpand ? 5 : charactersOnSecondRing, false);
for (int i = 0; i < charactersOnSecondRing; i++)
{
CreateAssignmentNode(order, characters[charactersOnFirstRing + i], offsets[i].ToPoint(), hotkey++ % 10);
}
}
else
{
offsets = GetAssignmentNodeOffsets(characterCount);
for (int i = 0; i < characterCount; i++)
{
CreateAssignmentNode(order, characters[i], offsets[i].ToPoint(), hotkey++ % 10);
}
}
int hotkey;
if (!needToExpand)
{
hotkey = optionNodes.Count + 1;
@@ -2539,12 +2613,14 @@ namespace Barotrauma
}
extraOptionCharacters.Clear();
extraOptionCharacters.AddRange(characters.GetRange(i, characters.Count - i));
// Sort expanded assignment nodes by characters' jobs and then by their names
extraOptionCharacters.AddRange(characters.GetRange(hotkey - 1, characterCount - (hotkey - 1))
.OrderBy(c => c?.Info?.Job?.Name).ThenBy(c => c?.Info?.DisplayName));
expandNode = new GUIButton(
new RectTransform(nodeSize, parent: commandFrame.RectTransform, anchor: Anchor.Center)
new RectTransform(assignmentNodeSize, parent: commandFrame.RectTransform, anchor: Anchor.Center)
{
AbsoluteOffset = offsets[i].ToPoint()
AbsoluteOffset = offsets.Last().ToPoint()
},
style: null)
{
@@ -2560,6 +2636,22 @@ namespace Barotrauma
returnNodeHotkey = Keys.D0 + hotkey % 10;
}
private Vector2[] GetAssignmentNodeOffsets(int characters, bool firstRing = true)
{
var nodeDistance = 1.8f * this.nodeDistance;
var nodePositionsOnEachSide = characters % 2 > 0 ? 7 : 6;
var nodeCountForCalculation = 2 * nodePositionsOnEachSide + 2;
var offsets = MathUtils.GetPointsOnCircumference(firstRing ? new Vector2(0f, 0.5f * nodeDistance) : Vector2.Zero,
nodeDistance, nodeCountForCalculation, MathHelper.ToRadians(180f + 360f / nodeCountForCalculation));
var emptySpacesPerSide = (nodePositionsOnEachSide - characters) / 2;
var offsetsInUse = new Vector2[nodePositionsOnEachSide - 2 * emptySpacesPerSide];
for (int i = 0; i < offsetsInUse.Length; i++)
{
offsetsInUse[i] = offsets[i + emptySpacesPerSide];
}
return offsetsInUse;
}
private bool ExpandAssignmentNodes(GUIButton node, object userData)
{
node.OnClicked = (button, _) =>
@@ -2569,60 +2661,86 @@ namespace Barotrauma
return true;
};
var order = userData as Tuple<Order, string>;
// TODO: The value 100 should be determined by how large the inner circle is
var offsets = MathUtils.GetPointsOnCircumference(Vector2.Zero, (nodeDistance + GUI.Scale * 100) * 1.55f,
GetCircumferencePointCount(extraOptionCharacters.Count),
GetFirstNodeAngle(extraOptionCharacters.Count));
var availableNodePositions = 20;
var offsets = MathUtils.GetPointsOnCircumference(Vector2.Zero, 2.7f * this.nodeDistance, availableNodePositions,
firstAngle: MathHelper.ToRadians(-90f - ((extraOptionCharacters.Count - 1) * 0.5f * (360f / availableNodePositions))));
for (int i = 0; i < extraOptionCharacters.Count; i++)
{
CreateAssignmentNode(order, extraOptionCharacters[i], offsets[i].ToPoint(), -1);
CreateAssignmentNode(userData as Tuple<Order, string>, extraOptionCharacters[i], offsets[i].ToPoint(), -1, nameLabelScale: 1.15f);
}
return true;
}
private void CreateAssignmentNode(Tuple<Order, string> order, Character character, Point offset, int hotkey)
private void CreateAssignmentNode(Tuple<Order, string> order, Character character, Point offset, int hotkey, float nameLabelScale = 1f)
{
// Button
var node = new GUIButton(
new RectTransform(nodeSize, parent: commandFrame.RectTransform, anchor: Anchor.Center),
new RectTransform(assignmentNodeSize, parent: commandFrame.RectTransform, anchor: Anchor.Center),
style: null)
{
OnClicked = (button, userData) =>
UserData = character,
OnClicked = (_, userData) =>
{
if (!CanIssueOrders) { return false; }
SetCharacterOrder(character, order.Item1, order.Item2, Character.Controlled);
SetCharacterOrder(userData as Character, order.Item1, order.Item2, Character.Controlled);
DisableCommandUI();
return true;
}
};
node.RectTransform.MoveOverTime(offset, CommandNodeAnimDuration);
// Container
var icon = new GUIImage(
new RectTransform(new Vector2(1.2f), node.RectTransform, anchor: Anchor.Center),
"CommandNodeContainer",
scaleToFit: true)
{
Color = character.Info.Job.Prefab.UIColor * nodeColorMultiplier,
HoverColor = character.Info.Job.Prefab.UIColor,
PressedColor = character.Info.Job.Prefab.UIColor,
SelectedColor = character.Info.Job.Prefab.UIColor,
UserData = "colorsource"
};
// Character icon
new GUICustomComponent(
new RectTransform(Vector2.One, node.RectTransform),
(spriteBatch, _) =>
{
character.Info.DrawJobIcon(spriteBatch,
new Rectangle((int)(node.Rect.X + node.Rect.Width * 0.5f), (int)(node.Rect.Y + node.Rect.Height * 0.1f), (int)(node.Rect.Width * 0.6f), (int)(node.Rect.Height * 0.8f)));
character.Info.DrawIcon(spriteBatch, new Vector2(node.Rect.X + node.Rect.Width * 0.35f, node.Center.Y), node.Rect.Size.ToVector2() * 0.7f);
})
var jobColor = character.Info?.Job?.Prefab?.UIColor ?? Color.White;
// Order icon
GUIImage orderIcon;
if (character.CurrentOrder != null && !character.CurrentOrder.Identifier.Equals("dismissed"))
{
ToolTip = character.Info.DisplayName + " (" + character.Info.Job.Name + ")"
orderIcon = new GUIImage(new RectTransform(new Vector2(1.2f), node.RectTransform, anchor: Anchor.Center), character.CurrentOrder.SymbolSprite, scaleToFit: true);
var tooltip = character.CurrentOrder.Name;
if (!string.IsNullOrWhiteSpace(character.CurrentOrderOption)) { tooltip += " (" + character.CurrentOrder.GetOptionName(character.CurrentOrderOption) + ")"; };
orderIcon.ToolTip = tooltip;
}
else
{
orderIcon = new GUIImage(new RectTransform(new Vector2(1.2f), node.RectTransform, anchor: Anchor.Center), "CommandIdleNode", scaleToFit: true);
}
orderIcon.Color = jobColor * nodeColorMultiplier;
orderIcon.HoverColor = jobColor;
orderIcon.PressedColor = jobColor;
orderIcon.SelectedColor = jobColor;
orderIcon.UserData = "colorsource";
// Name label
var width = (int)(nameLabelScale * nodeSize.X);
var font = GUI.SmallFont;
var nameLabel = new GUITextBlock(
new RectTransform(new Point(width, 0), parent: node.RectTransform, anchor: Anchor.TopCenter, pivot: Pivot.BottomCenter)
{
RelativeOffset = new Vector2(0f, -0.25f)
},
ToolBox.LimitString(character.Info?.DisplayName, font, width), textColor: jobColor * nodeColorMultiplier, font: font, textAlignment: Alignment.Center, style: null)
{
CanBeFocused = false,
ForceUpperCase = true,
HoverTextColor = jobColor
};
if (character.Info?.Job?.Prefab?.IconSmall is Sprite smallJobIcon)
{
// Job icon
new GUIImage(
new RectTransform(new Vector2(0.4f), node.RectTransform, anchor: Anchor.TopCenter, pivot: Pivot.Center)
{
RelativeOffset = new Vector2(0.0f, -((orderIcon.RectTransform.RelativeSize.Y - 1) / 2))
},
smallJobIcon, scaleToFit: true)
{
CanBeFocused = false,
Color = jobColor,
HoverColor = jobColor
};
}
#if DEBUG
bool canHear = true;
#else
@@ -2630,7 +2748,7 @@ namespace Barotrauma
#endif
if (!canHear)
{
node.CanBeFocused = icon.CanBeFocused = false;
node.CanBeFocused = orderIcon.CanBeFocused = false;
CreateBlockIcon(node.RectTransform);
}
if (hotkey >= 0)
@@ -2705,8 +2823,9 @@ namespace Barotrauma
private void CreateBlockIcon(RectTransform parent)
{
new GUIImage(new RectTransform(Vector2.One, parent, anchor: Anchor.Center), cancelIcon, scaleToFit: true)
new GUIImage(new RectTransform(new Vector2(0.9f), parent, anchor: Anchor.Center), cancelIcon, scaleToFit: true)
{
CanBeFocused = false,
Color = GUI.Style.Red * nodeColorMultiplier,
HoverColor = GUI.Style.Red
};
@@ -2749,6 +2868,7 @@ namespace Barotrauma
private bool TryGetBreachedHullAtHoveredWall(out Hull breachedHull)
{
breachedHull = null;
// Based on the IsValidTarget() method of AIObjectiveFixLeaks class
List<Gap> leaks = Gap.GapList.FindAll(g =>
g != null && g.ConnectedWall != null && g.ConnectedDoor == null && g.Open > 0 && g.linkedTo.Any(l => l != null) &&
g.Submarine != null && (Character.Controlled != null && g.Submarine.TeamID == Character.Controlled.TeamID && g.Submarine.Info.IsPlayer));
@@ -2765,6 +2885,25 @@ namespace Barotrauma
return false;
}
private Submarine GetTargetSubmarine()
{
var sub = Submarine.MainSub;
if (Character.Controlled != null)
{
// Pick the second main sub when we have two teams (in combat mission)
if (Character.Controlled.TeamID == Character.TeamType.Team2 && Submarine.MainSubs.Length > 1)
{
sub = Submarine.MainSubs[1];
}
// Target current submarine (likely a shuttle) when undocked from the main sub
if (Character.Controlled.Submarine is Submarine currentSub && currentSub != sub && currentSub.TeamID == Character.Controlled.TeamID && !currentSub.IsConnectedTo(sub))
{
sub = currentSub;
}
}
return sub;
}
#region Crew Member Assignment Logic
private Character GetCharacterForQuickAssignment(Order order)
@@ -2776,7 +2915,7 @@ namespace Barotrauma
{
return operatingCharacter;
}
return GetCharactersSortedForOrder(order, false).FirstOrDefault();
return GetCharactersSortedForOrder(order, false).FirstOrDefault() ?? Character.Controlled;
}
private List<Character> GetCharactersForManualAssignment(Order order)
@@ -2784,6 +2923,11 @@ namespace Barotrauma
#if !DEBUG
if (Character.Controlled == null) { return new List<Character>(); }
#endif
if (order.Identifier == dismissedOrderPrefab.Identifier)
{
return characters.FindAll(c => c.CurrentOrder != null && c.CurrentOrder.Identifier != dismissedOrderPrefab.Identifier)
.OrderBy(c => c.Info.DisplayName).ToList();
}
return GetCharactersSortedForOrder(order, order.Identifier != "follow").ToList();
}
@@ -2822,10 +2966,7 @@ namespace Barotrauma
if (canIssueOrders)
{
//report buttons are hidden when accessing another character's inventory
ReportButtonFrame.Visible = !Character.Controlled.ShouldLockHud() &&
(Character.Controlled?.SelectedCharacter?.Inventory == null ||
!Character.Controlled.SelectedCharacter.CanInventoryBeAccessed);
ReportButtonFrame.Visible = !Character.Controlled.ShouldLockHud();
if (!ReportButtonFrame.Visible) { return; }
var reportButtonParent = ChatBox ?? GameMain.Client?.ChatBox;

View File

@@ -25,7 +25,7 @@ namespace Barotrauma
: base(preset, param)
{
int buttonHeight = (int)(HUDLayoutSettings.ButtonAreaTop.Height * 0.7f);
endRoundButton = new GUIButton(HUDLayoutSettings.ToRectTransform(new Rectangle(HUDLayoutSettings.ButtonAreaTop.Right - 200, HUDLayoutSettings.ButtonAreaTop.Center.Y - buttonHeight / 2, 200, buttonHeight), GUICanvas.Instance),
endRoundButton = new GUIButton(HUDLayoutSettings.ToRectTransform(new Rectangle(HUDLayoutSettings.ButtonAreaTop.Right - GUI.IntScale(200), HUDLayoutSettings.ButtonAreaTop.Center.Y - buttonHeight / 2, GUI.IntScale(200), buttonHeight), GUICanvas.Instance),
TextManager.Get("EndRound"), textAlignment: Alignment.Center)
{
Font = GUI.SmallFont,

View File

@@ -195,7 +195,7 @@ namespace Barotrauma.Tutorials
// GameMain.GameSession.CrewManager.HighlightOrderButton(captain_security, "operateweapons", highlightColor, new Vector2(5, 5));
HighlightOrderOption("fireatwill");
}
while (!HasOrder(captain_security, "operateweapons", "fireatwill"));
while (!HasOrder(captain_security, "operateweapons"));
RemoveCompletedObjective(segments[2]);
yield return new WaitForSeconds(4f, false);
TriggerTutorialSegment(3, GameMain.Config.KeyBindText(InputType.Command));

View File

@@ -1,6 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using Barotrauma.IO;
using System.Xml.Linq;
using System.Linq;
using Barotrauma.Items.Components;
@@ -315,6 +315,7 @@ namespace Barotrauma.Tutorials
yield return new WaitForSeconds(2f, false);
TriggerTutorialSegment(4, GameMain.Config.KeyBindText(InputType.Select), GameMain.Config.KeyBindText(InputType.Shoot), GameMain.Config.KeyBindText(InputType.Deselect)); // Kill hammerhead
officer_hammerhead = SpawnMonster("hammerhead", officer_hammerheadSpawnPos);
((EnemyAIController)officer_hammerhead.AIController).StayInsideLevel = false;
officer_hammerhead.AIController.SelectTarget(officer.AiTarget);
SetHighlight(officer_coilgunPeriscope, true);
float originalDistance = Vector2.Distance(officer_coilgunPeriscope.WorldPosition, officer_hammerheadSpawnPos);
@@ -329,7 +330,13 @@ namespace Barotrauma.Tutorials
if (distance > originalDistance)
{
// Ensure that the Hammerhead targets the player
officer.AiTarget.SoundRange = float.MaxValue;
officer.AiTarget.SightRange = float.MaxValue;
officer_hammerhead.AIController.SelectTarget(officer.AiTarget);
if ((officer_hammerhead.AIController as EnemyAIController)?.SelectedTargetingParams != null)
{
((EnemyAIController)officer_hammerhead.AIController).SelectedTargetingParams.ReactDistance = 5000.0f;
}
/*var ai = officer_hammerhead.AIController as EnemyAIController;
ai.sight = 2.0f;*/
}

View File

@@ -2,7 +2,7 @@
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.IO;
using Barotrauma.IO;
using System.Linq;
using System.Xml.Linq;

View File

@@ -515,7 +515,7 @@ namespace Barotrauma.Tutorials
height += (int)GUI.Font.MeasureString(title).Y + (int)(150 * GUI.Scale);
}
var background = new GUIFrame(new RectTransform(new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight), GUI.Canvas, Anchor.Center), style: null, Color.Black * 0.5f);
var background = new GUIFrame(new RectTransform(new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight), GUI.Canvas, Anchor.Center), style: "GUIBackgroundBlocker");
var infoBlock = new GUIFrame(new RectTransform(new Point(width, height), background.RectTransform, anchor));
infoBlock.Flash(GUI.Style.Green);

View File

@@ -32,7 +32,9 @@ namespace Barotrauma
SoundPlayer.OverrideMusicDuration = 18.0f;
}
GUIFrame frame = new GUIFrame(new RectTransform(Vector2.One, GUI.Canvas), style: "GUIBackgroundBlocker")
GUIFrame background = new GUIFrame(new RectTransform(GUI.Canvas.RelativeSize, GUI.Canvas, Anchor.Center), style: "GUIBackgroundBlocker");
GUIFrame frame = new GUIFrame(new RectTransform(Vector2.One, background.RectTransform, Anchor.Center), style: null)
{
UserData = "roundsummary"
};

View File

@@ -44,6 +44,8 @@ namespace Barotrauma
}
}
private const int inventoryHotkeyCount = 10;
public void SetDefaultBindings(XDocument doc = null, bool legacy = false)
{
keyMapping = new KeyOrMouse[Enum.GetNames(typeof(InputType)).Length];
@@ -100,6 +102,13 @@ namespace Barotrauma
keyMapping[(int)InputType.Select] = new KeyOrMouse(MouseButton.PrimaryMouse);
// shoot and deselect are handled in CheckBindings() so that we don't override the legacy settings.
}
inventoryKeyMapping = new KeyOrMouse[inventoryHotkeyCount];
for (int i = 0; i < inventoryKeyMapping.Length; i++)
{
inventoryKeyMapping[i] = new KeyOrMouse(Keys.D0 + (i + 1) % 10);
}
if (doc != null)
{
LoadControls(doc);
@@ -179,6 +188,26 @@ namespace Barotrauma
}
}
private void LoadInventoryKeybinds(XElement element)
{
for (int i = 0; i < inventoryKeyMapping.Length; i++)
{
XAttribute attribute = element.Attributes().ElementAt(i);
if (int.TryParse(attribute.Value.ToString(), out int mouseButtonInt))
{
inventoryKeyMapping[i] = new KeyOrMouse((MouseButton)mouseButtonInt);
}
else if (Enum.TryParse(attribute.Value.ToString(), true, out MouseButton mouseButton))
{
inventoryKeyMapping[i] = new KeyOrMouse(mouseButton);
}
else if (Enum.TryParse(attribute.Value.ToString(), true, out Keys key))
{
inventoryKeyMapping[i] = new KeyOrMouse(key);
}
}
}
private void LoadControls(XDocument doc)
{
XElement keyMapping = doc.Root.Element("keymapping");
@@ -186,6 +215,12 @@ namespace Barotrauma
{
LoadKeyBinds(keyMapping);
}
XElement inventoryKeyMapping = doc.Root.Element("inventorykeymapping");
if (inventoryKeyMapping != null)
{
LoadInventoryKeybinds(inventoryKeyMapping);
}
}
public KeyOrMouse KeyBind(InputType inputType)
@@ -195,25 +230,14 @@ namespace Barotrauma
public string KeyBindText(InputType inputType)
{
KeyOrMouse bind = keyMapping[(int)inputType];
if (bind.MouseButton != MouseButton.None)
{
switch (bind.MouseButton)
{
case MouseButton.PrimaryMouse:
return PlayerInput.MouseButtonsSwapped() ? TextManager.Get("input.rightmouse") : TextManager.Get("input.leftmouse");
case MouseButton.SecondaryMouse:
return PlayerInput.MouseButtonsSwapped() ? TextManager.Get("input.leftmouse") : TextManager.Get("input.rightmouse");
default:
return TextManager.Get("input." + bind.MouseButton.ToString().ToLowerInvariant());
}
}
return bind.ToString();
return keyMapping[(int)inputType].Name;
}
public KeyOrMouse InventoryKeyBind(int index)
{
return inventoryKeyMapping[index];
}
private GUIListBox contentPackageList;
private bool ChangeSliderText(GUIScrollBar scrollBar, float barScroll)
@@ -259,7 +283,8 @@ namespace Barotrauma
}
else
{
settingsFrame = new GUIFrame(new RectTransform(Vector2.One, GUI.Canvas), style: null, color: Color.Black * 0.5f);
settingsFrame = new GUIFrame(new RectTransform(Vector2.One, GUI.Canvas, Anchor.Center), style: null);
new GUIFrame(new RectTransform(GUI.Canvas.RelativeSize, settingsFrame.RectTransform, Anchor.Center), style: "GUIBackgroundBlocker");
var settingsFrameContent = new GUIFrame(new RectTransform(new Vector2(0.8f, 0.8f), settingsFrame.RectTransform, Anchor.Center));
settingsHolder = settingsFrameContent.RectTransform;
}
@@ -292,6 +317,25 @@ namespace Barotrauma
ButtonEnabled = ContentPackage.List.Count(cp => cp.CorePackage) > 1
};
var filterContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), leftPanel.RectTransform), isHorizontal: true)
{
Stretch = true
};
var searchTitle = new GUITextBlock(new RectTransform(new Vector2(0.001f, 1.0f), filterContainer.RectTransform), TextManager.Get("serverlog.filter"), textAlignment: Alignment.CenterLeft, font: GUI.Font);
var searchBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 1.0f), filterContainer.RectTransform, Anchor.CenterRight), font: GUI.Font, createClearButton: true);
filterContainer.RectTransform.MinSize = searchBox.RectTransform.MinSize;
searchBox.OnSelected += (sender, userdata) => { searchTitle.Visible = false; };
searchBox.OnDeselected += (sender, userdata) => { searchTitle.Visible = true; };
searchBox.OnTextChanged += (textBox, text) =>
{
foreach (GUIComponent child in contentPackageList.Content.Children)
{
if (!(child.UserData is ContentPackage cp)) { continue; }
child.Visible = string.IsNullOrEmpty(text) ? true : cp.Name.ToLower().Contains(text.ToLower());
}
return true;
};
contentPackageList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.70f), leftPanel.RectTransform))
{
OnSelected = (gc, obj) => false,
@@ -551,6 +595,37 @@ namespace Barotrauma
};
GUITickBox textureCompressionTickBox = new GUITickBox(new RectTransform(tickBoxScale, leftColumn.RectTransform), TextManager.Get("EnableTextureCompression"))
{
ToolTip = TextManager.Get("EnableTextureCompressionToolTip"),
OnSelected = (GUITickBox box) =>
{
if (box.Selected == TextureCompressionEnabled) { return true; }
bool prevTextureCompressionEnabled = TextureCompressionEnabled;
TextureCompressionEnabled = box.Selected;
var msgBox = new GUIMessageBox(
TextManager.Get("RestartRequiredLabel"),
TextManager.Get("RestartRequiredGeneric"),
buttons: new string[] { TextManager.Get("OK"), TextManager.Get("Cancel") });
msgBox.Buttons[0].OnClicked += (btn, userdata) =>
{
ApplySettings();
GameMain.Instance.Exit();
return true;
}; msgBox.Buttons[1].OnClicked += (btn, userdata) =>
{
TextureCompressionEnabled = prevTextureCompressionEnabled;
box.Selected = prevTextureCompressionEnabled;
msgBox.Close();
return true;
};
return true;
},
Selected = TextureCompressionEnabled
};
GUITickBox pauseOnFocusLostBox = new GUITickBox(new RectTransform(tickBoxScale, leftColumn.RectTransform),
TextManager.Get("PauseOnFocusLost"))
{
@@ -612,7 +687,8 @@ namespace Barotrauma
{
ChangeSliderText(scrollBar, barScroll);
LightMapScale = MathHelper.Lerp(0.2f, 1.0f, barScroll);
UnsavedSettings = true; return true;
UnsavedSettings = true;
return true;
},
Step = 0.25f
};
@@ -1113,6 +1189,24 @@ namespace Barotrauma
keyBox.SelectedColor = Color.Gold * 0.3f;
}
for (int i = 0; i < inventoryHotkeyCount; i++)
{
var inputContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.06f), ((i + 1) <= inventoryHotkeyCount / 2 ? inputColumnLeft : inputColumnRight).RectTransform))
{ Stretch = true, IsHorizontal = true, RelativeSpacing = 0.01f, Color = new Color(12, 14, 15, 215) };
var inputName = new GUITextBlock(new RectTransform(new Vector2(0.6f, 1.0f), inputContainer.RectTransform, Anchor.TopLeft) { MinSize = new Point(100, 0) },
TextManager.GetWithVariable("inventoryslotkeybind", "[slotnumber]", (i + 1).ToString()), font: GUI.SmallFont)
{ ForceUpperCase = true };
inputNameBlocks.Add(inputName);
var keyBox = new GUITextBox(new RectTransform(new Vector2(0.4f, 1.0f), inputContainer.RectTransform),
text: inventoryKeyMapping[i].Name, font: GUI.SmallFont, style: "GUITextBoxNoIcon")
{
UserData = i
};
keyBox.Text = ToolBox.LimitString(keyBox.Text, keyBox.Font, (int)(keyBox.Rect.Width - keyBox.Padding.X - keyBox.Padding.Z));
keyBox.OnSelected += InventoryKeyBoxSelected;
keyBox.SelectedColor = Color.Gold * 0.3f;
}
GUITextBlock.AutoScaleAndNormalize(inputNameBlocks);
var resetControlsArea = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.07f), controlsLayoutGroup.RectTransform), style: null);
@@ -1380,7 +1474,13 @@ namespace Barotrauma
private void KeyBoxSelected(GUITextBox textBox, Keys key)
{
textBox.Text = "";
CoroutineManager.StartCoroutine(WaitForKeyPress(textBox));
CoroutineManager.StartCoroutine(WaitForKeyPress(textBox, keyMapping));
}
private void InventoryKeyBoxSelected(GUITextBox textBox, Keys key)
{
textBox.Text = "";
CoroutineManager.StartCoroutine(WaitForKeyPress(textBox, inventoryKeyMapping));
}
private void ResetControls(bool legacy)
@@ -1476,7 +1576,7 @@ namespace Barotrauma
return true;
}
private IEnumerable<object> WaitForKeyPress(GUITextBox keyBox)
private IEnumerable<object> WaitForKeyPress(GUITextBox keyBox, KeyOrMouse[] keyArray)
{
yield return CoroutineStatus.Running;
@@ -1500,42 +1600,43 @@ namespace Barotrauma
if (PlayerInput.LeftButtonClicked())
{
keyMapping[keyIndex] = new KeyOrMouse(MouseButton.LeftMouse);
keyArray[keyIndex] = new KeyOrMouse(MouseButton.LeftMouse);
}
else if (PlayerInput.RightButtonClicked())
{
keyMapping[keyIndex] = new KeyOrMouse(MouseButton.RightMouse);
keyArray[keyIndex] = new KeyOrMouse(MouseButton.RightMouse);
}
else if (PlayerInput.MidButtonClicked())
{
keyMapping[keyIndex] = new KeyOrMouse(MouseButton.MiddleMouse);
keyArray[keyIndex] = new KeyOrMouse(MouseButton.MiddleMouse);
}
else if (PlayerInput.Mouse4ButtonClicked())
{
keyMapping[keyIndex] = new KeyOrMouse(MouseButton.MouseButton4);
keyArray[keyIndex] = new KeyOrMouse(MouseButton.MouseButton4);
}
else if (PlayerInput.Mouse5ButtonClicked())
{
keyMapping[keyIndex] = new KeyOrMouse(MouseButton.MouseButton5);
keyArray[keyIndex] = new KeyOrMouse(MouseButton.MouseButton5);
}
else if (PlayerInput.MouseWheelUpClicked())
{
keyMapping[keyIndex] = new KeyOrMouse(MouseButton.MouseWheelUp);
keyArray[keyIndex] = new KeyOrMouse(MouseButton.MouseWheelUp);
}
else if (PlayerInput.MouseWheelDownClicked())
{
keyMapping[keyIndex] = new KeyOrMouse(MouseButton.MouseWheelDown);
keyArray[keyIndex] = new KeyOrMouse(MouseButton.MouseWheelDown);
}
else if (PlayerInput.GetKeyboardState.GetPressedKeys().Length > 0)
{
Keys key = PlayerInput.GetKeyboardState.GetPressedKeys()[0];
keyMapping[keyIndex] = new KeyOrMouse(key);
keyArray[keyIndex] = new KeyOrMouse(key);
}
else
{
yield return CoroutineStatus.Success;
}
keyBox.Text = KeyBindText((InputType)keyIndex);
keyBox.Text = keyArray[keyIndex].Name;
keyBox.Text = ToolBox.LimitString(keyBox.Text, keyBox.Font, keyBox.Rect.Width);
keyBox.Deselect();

View File

@@ -354,7 +354,6 @@ namespace Barotrauma
break;
case Layout.Right:
{
int extraOffset = 0;
int x = HUDLayoutSettings.InventoryAreaLower.Right;
int personalSlotX = HUDLayoutSettings.InventoryAreaLower.Right - SlotSize.X - Spacing;
for (int i = 0; i < slots.Length; i++)
@@ -371,17 +370,18 @@ namespace Barotrauma
}
int lowerX = x;
int personalSlotY = GameMain.GraphicsHeight - bottomOffset * 2 - Spacing * 2 - (int)(!GUI.IsFourByThree() ? UnequippedIndicator.size.Y * UIScale * IndicatorScaleAdjustment : UnequippedIndicator.size.Y * UIScale * IndicatorScaleAdjustment * 2f);
for (int i = 0; i < SlotPositions.Length; i++)
{
if (HideSlot(i)) continue;
if (PersonalSlots.HasFlag(SlotTypes[i]))
{
SlotPositions[i] = new Vector2(personalSlotX, GameMain.GraphicsHeight - bottomOffset * 2 - extraOffset - Spacing * 2);
SlotPositions[i] = new Vector2(personalSlotX, personalSlotY);
personalSlotX -= slots[i].Rect.Width + Spacing;
}
else
{
SlotPositions[i] = new Vector2(x, GameMain.GraphicsHeight - bottomOffset - extraOffset);
SlotPositions[i] = new Vector2(x, GameMain.GraphicsHeight - bottomOffset);
x += slots[i].Rect.Width + Spacing;
}
}
@@ -391,7 +391,7 @@ namespace Barotrauma
{
if (!HideSlot(i)) continue;
x -= slots[i].Rect.Width + Spacing;
SlotPositions[i] = new Vector2(x, GameMain.GraphicsHeight - bottomOffset - extraOffset);
SlotPositions[i] = new Vector2(x, GameMain.GraphicsHeight - bottomOffset);
}
}
break;
@@ -399,12 +399,14 @@ namespace Barotrauma
{
int x = HUDLayoutSettings.InventoryAreaLower.X;
int personalSlotX = x;
int personalSlotY = GameMain.GraphicsHeight - bottomOffset * 2 - Spacing * 2 - (int)(!GUI.IsFourByThree() ? UnequippedIndicator.size.Y * UIScale * IndicatorScaleAdjustment : UnequippedIndicator.size.Y * UIScale * IndicatorScaleAdjustment * 2f);
for (int i = 0; i < SlotPositions.Length; i++)
{
if (HideSlot(i)) continue;
if (PersonalSlots.HasFlag(SlotTypes[i]))
{
SlotPositions[i] = new Vector2(personalSlotX, GameMain.GraphicsHeight - bottomOffset * 2 - Spacing * 2);
SlotPositions[i] = new Vector2(personalSlotX, personalSlotY);
personalSlotX += slots[i].Rect.Width + Spacing;
}
else
@@ -523,8 +525,7 @@ namespace Barotrauma
for (int i = 0; i < capacity; i++)
{
if (Items[i] != null && Items[i] != draggingItem && Character.Controlled?.Inventory == this &&
GUI.KeyboardDispatcher.Subscriber == null && !CrewManager.IsCommandInterfaceOpen &&
slots[i].QuickUseKey != Keys.None && PlayerInput.KeyHit(slots[i].QuickUseKey))
GUI.KeyboardDispatcher.Subscriber == null && !CrewManager.IsCommandInterfaceOpen && PlayerInput.InventoryKeyHit(slots[i].InventoryKeyIndex))
{
QuickUseItem(Items[i], true, false, true);
}
@@ -782,21 +783,16 @@ namespace Barotrauma
}
}
private void AssignQuickUseNumKeys()
public void AssignQuickUseNumKeys()
{
int num = 1;
int keyBindIndex = 0;
for (int i = 0; i < slots.Length; i++)
{
if (HideSlot(i))
{
slots[i].QuickUseKey = Keys.None;
continue;
}
if (HideSlot(i)) continue;
if (SlotTypes[i] == InvSlotType.Any)
{
slots[i].QuickUseKey = Keys.D0 + num % 10;
num++;
slots[i].InventoryKeyIndex = keyBindIndex;
keyBindIndex++;
}
}
}
@@ -819,16 +815,21 @@ namespace Barotrauma
{
if (item.Container == null || character.Inventory.FindIndex(item.Container) == -1) // Not a subinventory in the character's inventory
{
return item.ParentInventory is CharacterInventory ?
QuickUseAction.TakeFromCharacter : QuickUseAction.TakeFromContainer;
if (character.SelectedItems.Any(i => i?.OwnInventory != null && i.OwnInventory.CanBePut(item)))
{
return QuickUseAction.PutToEquippedItem;
}
else
{
return item.ParentInventory is CharacterInventory ? QuickUseAction.TakeFromCharacter : QuickUseAction.TakeFromContainer;
}
}
else
{
var selectedContainer = character.SelectedConstruction?.GetComponent<ItemContainer>();
if (selectedContainer != null &&
selectedContainer.Inventory != null &&
!selectedContainer.Inventory.Locked &&
allowInventorySwap)
!selectedContainer.Inventory.Locked)
{
// Move the item from the subinventory to the selected container
return QuickUseAction.PutToContainer;
@@ -928,24 +929,24 @@ namespace Barotrauma
//attempt to put in a free slot first
for (int i = capacity - 1; i >= 0; i--)
{
if (Items[i] != null) continue;
if (SlotTypes[i] == InvSlotType.Any || !item.AllowedSlots.Any(a => a.HasFlag(SlotTypes[i]))) continue;
if (Items[i] != null) { continue; }
if (SlotTypes[i] == InvSlotType.Any || !item.AllowedSlots.Any(a => a.HasFlag(SlotTypes[i]))) { continue; }
success = TryPutItem(item, i, true, false, Character.Controlled, true);
if (success) break;
if (success) { break; }
}
if (!success)
{
for (int i = capacity - 1; i >= 0; i--)
{
if (SlotTypes[i] == InvSlotType.Any || !item.AllowedSlots.Any(a => a.HasFlag(SlotTypes[i]))) continue;
//something else already equipped in the slot, attempt to unequip it
if (Items[i] != null && Items[i].AllowedSlots.Contains(InvSlotType.Any))
if (SlotTypes[i] == InvSlotType.Any || !item.AllowedSlots.Any(a => a.HasFlag(SlotTypes[i]))) { continue; }
// something else already equipped in a hand slot, attempt to unequip it so items aren't unnecessarily swapped to it
if (Items[i] != null && Items[i].AllowedSlots.Contains(InvSlotType.Any) && (SlotTypes[i] == InvSlotType.LeftHand || SlotTypes[i] == InvSlotType.RightHand))
{
TryPutItem(Items[i], Character.Controlled, new List<InvSlotType>() { InvSlotType.Any }, true);
}
success = TryPutItem(item, i, true, false, Character.Controlled, true);
if (success) break;
if (success) { break; }
}
}
break;
@@ -1041,6 +1042,7 @@ namespace Barotrauma
prevUIScale != UIScale ||
prevHUDScale != GUI.Scale)
{
CreateSlots();
SetSlotPositions(layout);
prevUIScale = UIScale;
prevHUDScale = GUI.Scale;

View File

@@ -237,6 +237,7 @@ namespace Barotrauma.Items.Components
{
StopPicking(null);
PlaySound(forcedOpen ? ActionType.OnPicked : ActionType.OnUse);
if (isOpen) { stuck = MathHelper.Clamp(stuck - StuckReductionOnOpen, 0.0f, 100.0f); }
}
}
}
@@ -245,7 +246,8 @@ namespace Barotrauma.Items.Components
{
base.ClientRead(type, msg, sendingTime);
bool open = msg.ReadBoolean();
bool open = msg.ReadBoolean();
bool broken = msg.ReadBoolean();
bool forcedOpen = msg.ReadBoolean();
SetState(open, isNetworkMessage: true, sendNetworkMessage: false, forcedOpen: forcedOpen);
Stuck = msg.ReadRangedSingle(0.0f, 100.0f, 8);
@@ -258,6 +260,7 @@ namespace Barotrauma.Items.Components
}
if (isStuck) { OpenState = 0.0f; }
IsBroken = broken;
PredictedState = null;
}
}

View File

@@ -1,4 +1,5 @@
using Microsoft.Xna.Framework;
using Barotrauma.Networking;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
@@ -52,5 +53,13 @@ namespace Barotrauma.Items.Components
}
}
}
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
{
CurrPowerConsumption = powerConsumption;
charging = true;
timer = Duration;
IsActive = true;
}
}
}

View File

@@ -17,7 +17,7 @@ namespace Barotrauma.Items.Components
public void Draw(SpriteBatch spriteBatch, bool editing, float itemDepth = -1)
{
if (!IsActive || picker == null || !CanBeAttached() || !picker.IsKeyDown(InputType.Aim) || picker != Character.Controlled) { return; }
if (!IsActive || picker == null || !CanBeAttached(picker) || !picker.IsKeyDown(InputType.Aim) || picker != Character.Controlled) { return; }
Vector2 gridPos = picker.Position;
Vector2 roundedGridPos = new Vector2(
@@ -71,6 +71,8 @@ namespace Barotrauma.Items.Components
base.ClientRead(type, msg, sendingTime);
bool shouldBeAttached = msg.ReadBoolean();
Vector2 simPosition = new Vector2(msg.ReadSingle(), msg.ReadSingle());
UInt16 submarineID = msg.ReadUInt16();
Submarine sub = Entity.FindEntityByID(submarineID) as Submarine;
if (!attachable)
{
@@ -84,6 +86,7 @@ namespace Barotrauma.Items.Components
{
Drop(false, null);
item.SetTransform(simPosition, 0.0f);
item.Submarine = sub;
AttachToWall();
}
}

View File

@@ -4,7 +4,7 @@ using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
using System.IO;
using Barotrauma.IO;
using System.Text;
using System.Xml.Linq;

View File

@@ -4,7 +4,7 @@ using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
using System.IO;
using Barotrauma.IO;
using System.Linq;
using System.Xml.Linq;
@@ -436,8 +436,7 @@ namespace Barotrauma.Items.Components
if (subElement.Attribute("color") != null) color = subElement.GetAttributeColor("color", Color.White);
string style = subElement.Attribute("style") == null ?
null : subElement.GetAttributeString("style", "");
GuiFrame = new GUIFrame(RectTransform.Load(subElement, GUI.Canvas, Anchor.Center), style, color);
GuiFrame = new GUIFrame(RectTransform.Load(subElement, GUI.Canvas.ItemComponentHolder, Anchor.Center), style, color);
DefaultLayout = GUILayoutSettings.Load(subElement);
break;
case "alternativelayout":

View File

@@ -28,7 +28,7 @@ namespace Barotrauma.Items.Components
}
private string text;
[Serialize("", true, translationTextTag: "Label.", description: "The text displayed in the label."), Editable(100)]
[Serialize("", true, translationTextTag: "Label.", description: "The text displayed in the label.", alwaysUseInstanceValues: true), Editable(100)]
public string Text
{
get { return text; }
@@ -58,7 +58,7 @@ namespace Barotrauma.Items.Components
private set;
}
[Editable, Serialize("0,0,0,255", true, description: "The color of the text displayed on the label (R,G,B,A).")]
[Editable, Serialize("0,0,0,255", true, description: "The color of the text displayed on the label (R,G,B,A).", alwaysUseInstanceValues: true)]
public Color TextColor
{
get { return textColor; }
@@ -69,7 +69,7 @@ namespace Barotrauma.Items.Components
}
}
[Editable(0.0f, 10.0f), Serialize(1.0f, true, description: "The scale of the text displayed on the label.")]
[Editable(0.0f, 10.0f), Serialize(1.0f, true, description: "The scale of the text displayed on the label.", alwaysUseInstanceValues: true)]
public float TextScale
{
get { return textBlock == null ? 1.0f : textBlock.TextScale; }

View File

@@ -48,7 +48,10 @@ namespace Barotrauma.Items.Components
{
if (light.LightSprite != null && (item.body == null || item.body.Enabled) && lightBrightness > 0.0f && IsOn)
{
light.LightSprite.Draw(spriteBatch, new Vector2(item.DrawPosition.X, -item.DrawPosition.Y), lightColor * lightBrightness, 0.0f, item.Scale, SpriteEffects.None, item.SpriteDepth - 0.0001f);
Vector2 origin = light.LightSprite.Origin;
if (light.LightSpriteEffect == SpriteEffects.FlipHorizontally) { origin.X = light.LightSprite.SourceRect.Width - origin.X; }
if (light.LightSpriteEffect == SpriteEffects.FlipVertically) { origin.Y = light.LightSprite.SourceRect.Height - origin.Y; }
light.LightSprite.Draw(spriteBatch, new Vector2(item.DrawPosition.X, -item.DrawPosition.Y), lightColor * lightBrightness, origin, -light.Rotation, item.Scale, light.LightSpriteEffect, item.SpriteDepth - 0.0001f);
}
}

View File

@@ -76,7 +76,7 @@ namespace Barotrauma.Items.Components
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
{
state = msg.ReadBoolean();
State = msg.ReadBoolean();
ushort userID = msg.ReadUInt16();
if (userID == 0)
{

View File

@@ -16,6 +16,10 @@ namespace Barotrauma.Items.Components
private GUIScrollBar forceSlider;
private GUITickBox autoControlIndicator;
private int particlesPerSec = 60;
private float particleTimer;
public float AnimSpeed
{
get;

View File

@@ -318,10 +318,10 @@ namespace Barotrauma.Items.Components
{
if (item.ParentInventory.slots[availableSlotIndex].HighlightTimer <= 0.0f)
{
item.ParentInventory.slots[availableSlotIndex].ShowBorderHighlight(GUI.Style.Green, 0.5f, 0.5f);
item.ParentInventory.slots[availableSlotIndex].ShowBorderHighlight(GUI.Style.Green, 0.5f, 0.5f, 0.2f);
if (slotIndex < inputContainer.Capacity)
{
inputContainer.Inventory.slots[slotIndex].ShowBorderHighlight(GUI.Style.Green, 0.5f, 0.5f);
inputContainer.Inventory.slots[slotIndex].ShowBorderHighlight(GUI.Style.Green, 0.5f, 0.5f, 0.2f);
}
}
}
@@ -337,10 +337,22 @@ namespace Barotrauma.Items.Components
slotRect.Center.ToVector2(),
color: requiredItem.ItemPrefab.InventoryIconColor * 0.3f,
scale: Math.Min(slotRect.Width / itemIcon.size.X, slotRect.Height / itemIcon.size.Y));
if (requiredItem.UseCondition && requiredItem.MinCondition < 1.0f)
{
GUI.DrawRectangle(spriteBatch, new Rectangle(slotRect.X, slotRect.Bottom - 8, slotRect.Width, 8), Color.Black * 0.8f, true);
GUI.DrawRectangle(spriteBatch,
new Rectangle(slotRect.X, slotRect.Bottom - 8, (int)(slotRect.Width * requiredItem.MinCondition), 8),
GUI.Style.Green * 0.8f, true);
}
if (slotRect.Contains(PlayerInput.MousePosition))
{
string toolTipText = requiredItem.ItemPrefab.Name;
if (requiredItem.UseCondition && requiredItem.MinCondition < 1.0f)
{
toolTipText += " " + (int)Math.Round(requiredItem.MinCondition * 100) + "%";
}
if (!string.IsNullOrEmpty(requiredItem.ItemPrefab.Description))
{
toolTipText += '\n' + requiredItem.ItemPrefab.Description;

View File

@@ -163,7 +163,7 @@ namespace Barotrauma.Items.Components
{
pumpSpeedLockTimer -= deltaTime;
isActiveLockTimer -= deltaTime;
autoControlIndicator.Selected = pumpSpeedLockTimer > 0.0f || isActiveLockTimer > 0.0f;
autoControlIndicator.Selected = IsAutoControlled;
PowerButton.Enabled = isActiveLockTimer <= 0.0f;
if (HasPower)
{

View File

@@ -18,6 +18,8 @@ namespace Barotrauma.Items.Components
Disruption
}
private PathFinder pathFinder;
private bool dynamicDockingIndicator = true;
private bool unsentChanges;
@@ -45,7 +47,7 @@ namespace Barotrauma.Items.Components
private Sprite sonarBlip;
private Sprite lineSprite;
private Dictionary<string, Sprite> targetIcons = new Dictionary<string, Sprite>();
private readonly Dictionary<string, Sprite> targetIcons = new Dictionary<string, Sprite>();
private float displayBorderSize;
@@ -65,7 +67,24 @@ namespace Barotrauma.Items.Components
//Vector2 = vector from the ping source to the position of the disruption
//float = strength of the disruption, between 0-1
List<Pair<Vector2, float>> disruptedDirections = new List<Pair<Vector2, float>>();
private readonly List<Pair<Vector2, float>> disruptedDirections = new List<Pair<Vector2, float>>();
class CachedDistance
{
public readonly Vector2 TransducerWorldPos;
public readonly Vector2 WorldPos;
public readonly float Distance;
public double RecalculationTime;
public CachedDistance(Vector2 transducerWorldPos, Vector2 worldPos, float dist)
{
TransducerWorldPos = transducerWorldPos;
WorldPos = worldPos;
Distance = dist;
}
}
private readonly Dictionary<object, CachedDistance> markerDistances = new Dictionary<object, CachedDistance>();
private readonly Color positiveColor = Color.Green;
private readonly Color warningColor = Color.Orange;
@@ -74,7 +93,7 @@ namespace Barotrauma.Items.Components
public static readonly Vector2 controlBoxSize = new Vector2(0.33f, 0.32f);
public static readonly Vector2 controlBoxOffset = new Vector2(0.025f, 0);
public static readonly float sonarAreaSize = 1.09f;
private static readonly float sonarAreaSize = 1.09f;
private static readonly Dictionary<BlipType, Color[]> blipColorGradient = new Dictionary<BlipType, Color[]>()
{
@@ -94,6 +113,8 @@ namespace Barotrauma.Items.Components
public float DisplayRadius { get; private set; }
public static Vector2 GUISizeCalculation => Vector2.One * Math.Min(GUI.RelativeHorizontalAspectRatio, 1f) * sonarAreaSize;
partial void InitProjSpecific(XElement element)
{
System.Diagnostics.Debug.Assert(Enum.GetValues(typeof(BlipType)).Cast<BlipType>().All(t => blipColorGradient.ContainsKey(t)));
@@ -254,7 +275,7 @@ namespace Barotrauma.Items.Components
controlContainer.RectTransform.SetPosition(Anchor.TopLeft);
sonarView.RectTransform.ScaleBasis = ScaleBasis.Smallest;
sonarView.RectTransform.SetPosition(Anchor.CenterRight);
sonarView.RectTransform.Resize(Vector2.One * GUI.RelativeHorizontalAspectRatio * sonarAreaSize);
sonarView.RectTransform.Resize(GUISizeCalculation);
GUITextBlock.AutoScaleAndNormalize(passiveTickBox.TextBlock, activeTickBox.TextBlock, zoomText, directionalModeSwitchText);
}
}
@@ -653,12 +674,16 @@ namespace Barotrauma.Items.Components
DrawMarker(spriteBatch,
GameMain.GameSession.StartLocation.Name,
"outpost",
(Level.Loaded.StartPosition - transducerCenter), displayScale, center, DisplayRadius);
GameMain.GameSession.StartLocation.Name,
Level.Loaded.StartPosition, transducerCenter,
displayScale, center, DisplayRadius);
DrawMarker(spriteBatch,
GameMain.GameSession.EndLocation.Name,
"outpost",
(Level.Loaded.EndPosition - transducerCenter), displayScale, center, DisplayRadius);
GameMain.GameSession.EndLocation.Name,
Level.Loaded.EndPosition, transducerCenter,
displayScale, center, DisplayRadius);
foreach (AITarget aiTarget in AITarget.List)
{
@@ -670,7 +695,9 @@ namespace Barotrauma.Items.Components
DrawMarker(spriteBatch,
aiTarget.SonarLabel,
aiTarget.SonarIconIdentifier,
aiTarget.WorldPosition - transducerCenter, displayScale, center, DisplayRadius * 0.975f);
aiTarget,
aiTarget.WorldPosition, transducerCenter,
displayScale, center, DisplayRadius * 0.975f);
}
}
@@ -685,7 +712,9 @@ namespace Barotrauma.Items.Components
DrawMarker(spriteBatch,
mission.SonarLabel,
mission.SonarIconIdentifier,
sonarPosition - transducerCenter, displayScale, center, DisplayRadius * 0.95f);
mission,
sonarPosition, transducerCenter,
displayScale, center, DisplayRadius * 0.95f);
}
}
}
@@ -704,7 +733,8 @@ namespace Barotrauma.Items.Components
DrawMarker(spriteBatch,
sub.Info.DisplayName,
sub.Info.HasTag(SubmarineTag.Shuttle) ? "shuttle" : "submarine",
sub.WorldPosition - transducerCenter,
sub,
sub.WorldPosition, transducerCenter,
displayScale, center, DisplayRadius * 0.95f);
}
@@ -951,14 +981,13 @@ namespace Barotrauma.Items.Components
}
foreach (AITarget aiTarget in AITarget.List)
{
if (aiTarget.SonarDisruption <= 0.0f || !aiTarget.Enabled) { continue; }
float disruption = aiTarget.Entity is Character c ? c.Params.SonarDisruption : aiTarget.SonarDisruption;
if (disruption <= 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));
CreateBlipsForDisruption(aiTarget.WorldPosition, aiTarget.SonarDisruption);
CreateBlipsForDisruption(aiTarget.WorldPosition, disruption);
}
}
@@ -1303,9 +1332,48 @@ namespace Barotrauma.Items.Components
sonarBlip.Draw(spriteBatch, center + pos, color * 0.5f, sonarBlip.Origin, 0, scale * 0.08f, SpriteEffects.None, 0);
}
private void DrawMarker(SpriteBatch spriteBatch, string label, string iconIdentifier, Vector2 position, float scale, Vector2 center, float radius)
private void DrawMarker(SpriteBatch spriteBatch, string label, string iconIdentifier, object targetIdentifier, Vector2 worldPosition, Vector2 transducerPosition, float scale, Vector2 center, float radius)
{
float dist = position.Length();
float linearDist = Vector2.Distance(worldPosition, transducerPosition);
float dist = linearDist;
if (linearDist > Range)
{
if (markerDistances.TryGetValue(targetIdentifier, out CachedDistance cachedDistance))
{
if (Timing.TotalTime > cachedDistance.RecalculationTime &&
(Vector2.DistanceSquared(cachedDistance.TransducerWorldPos, transducerPosition) > 500 * 500 ||
Vector2.DistanceSquared(cachedDistance.WorldPos, worldPosition) > 500 * 500))
{
markerDistances.Remove(targetIdentifier);
CalculateDistance();
}
else
{
dist = Math.Max(cachedDistance.Distance, linearDist);
}
}
else
{
CalculateDistance();
}
}
void CalculateDistance()
{
pathFinder ??= new PathFinder(WayPoint.WayPointList, indoorsSteering: false);
var path = pathFinder.FindPath(ConvertUnits.ToSimUnits(transducerPosition), ConvertUnits.ToSimUnits(worldPosition));
if (!path.Unreachable)
{
var cachedDistance = new CachedDistance(transducerPosition, worldPosition, path.TotalLength)
{
RecalculationTime = Timing.TotalTime + Rand.Range(1.0f, 5.0f)
};
markerDistances.Add(targetIdentifier, cachedDistance);
dist = path.TotalLength;
}
}
Vector2 position = worldPosition - transducerPosition;
position *= zoom;
position *= scale;
@@ -1314,16 +1382,16 @@ namespace Barotrauma.Items.Components
float textAlpha = MathHelper.Clamp(1.5f - dist / 50000.0f, 0.5f, 1.0f);
Vector2 dir = Vector2.Normalize(position);
Vector2 markerPos = (dist * zoom * scale > radius) ? dir * radius : position;
Vector2 markerPos = (linearDist * zoom * scale > radius) ? dir * radius : position;
markerPos += center;
markerPos.X = (int)markerPos.X;
markerPos.Y = (int)markerPos.Y;
float alpha = 1.0f;
if (dist * scale < radius)
if (linearDist * scale < radius)
{
float normalizedDist = dist * scale / radius;
float normalizedDist = linearDist * scale / radius;
alpha = Math.Max(normalizedDist - 0.4f, 0.0f);
float mouseDist = Vector2.Distance(PlayerInput.MousePosition, markerPos);
@@ -1334,14 +1402,6 @@ namespace Barotrauma.Items.Components
}
}
if (!GuiFrame.Children.First().Rect.Contains(markerPos))
{
if (MathUtils.GetLineRectangleIntersection(center, markerPos, GuiFrame.Children.First().Rect, out Vector2 intersection))
{
markerPos = intersection;
}
}
if (string.IsNullOrEmpty(iconIdentifier) || !targetIcons.ContainsKey(iconIdentifier))
{
GUI.DrawRectangle(spriteBatch, new Rectangle((int)markerPos.X - 3, (int)markerPos.Y - 3, 6, 6), markerColor, thickness: 2);

View File

@@ -390,7 +390,7 @@ namespace Barotrauma.Items.Components
};
// Sonar area
steerArea = new GUICustomComponent(new RectTransform(Vector2.One * GUI.RelativeHorizontalAspectRatio * Sonar.sonarAreaSize, GuiFrame.RectTransform, Anchor.CenterRight, scaleBasis: ScaleBasis.Smallest),
steerArea = new GUICustomComponent(new RectTransform(Sonar.GUISizeCalculation, GuiFrame.RectTransform, Anchor.CenterRight, scaleBasis: ScaleBasis.Smallest),
(spriteBatch, guiCustomComponent) => { DrawHUD(spriteBatch, guiCustomComponent.Rect); }, null);
steerRadius = steerArea.Rect.Width / 2;
@@ -438,11 +438,8 @@ namespace Barotrauma.Items.Components
if (Voltage < MinVoltage) { return; }
Rectangle velRect = new Rectangle(x + 20, y + 20, width - 40, height - 40);
Vector2 displaySubPos = (-sonar.DisplayOffset * sonar.Zoom) / sonar.Range * sonar.DisplayRadius * sonar.Zoom;
displaySubPos.Y = -displaySubPos.Y;
displaySubPos = displaySubPos.ClampLength(velRect.Width / 2);
displaySubPos = steerArea.Rect.Center.ToVector2() + displaySubPos;
Vector2 steeringOrigin = steerArea.Rect.Center.ToVector2();
if (!AutoPilot)
{
Vector2 unitSteeringInput = steeringInput / 100.0f;
@@ -450,18 +447,18 @@ namespace Barotrauma.Items.Components
Vector2 steeringInputPos = new Vector2(
steeringInput.X * (float)Math.Sqrt(1.0f - 0.5f * unitSteeringInput.Y * unitSteeringInput.Y),
-steeringInput.Y * (float)Math.Sqrt(1.0f - 0.5f * unitSteeringInput.X * unitSteeringInput.X));
steeringInputPos += displaySubPos;
steeringInputPos += steeringOrigin;
if (steeringIndicator != null)
{
Vector2 dir = steeringInputPos - displaySubPos;
Vector2 dir = steeringInputPos - steeringOrigin;
float angle = (float)Math.Atan2(dir.Y, dir.X);
steeringIndicator.Draw(spriteBatch, displaySubPos, Color.White, origin: steeringIndicator.Origin, rotate: angle,
steeringIndicator.Draw(spriteBatch, steeringOrigin, Color.White, origin: steeringIndicator.Origin, rotate: angle,
scale: new Vector2(dir.Length() / steeringIndicator.size.X, 1.0f));
}
else
{
GUI.DrawLine(spriteBatch, displaySubPos, steeringInputPos, Color.LightGray);
GUI.DrawLine(spriteBatch, steeringOrigin, steeringInputPos, Color.LightGray);
GUI.DrawRectangle(spriteBatch, new Rectangle((int)steeringInputPos.X - 5, (int)steeringInputPos.Y - 5, 10, 10), Color.White);
}
@@ -475,7 +472,7 @@ namespace Barotrauma.Items.Components
Sonar sonar = item.GetComponent<Sonar>();
if (sonar != null && controlledSub != null)
{
Vector2 displayPosToMaintain = ((posToMaintain.Value - sonar.DisplayOffset * sonar.Zoom - controlledSub.WorldPosition)) / sonar.Range * sonar.DisplayRadius * sonar.Zoom;
Vector2 displayPosToMaintain = ((posToMaintain.Value - controlledSub.WorldPosition)) / sonar.Range * sonar.DisplayRadius * sonar.Zoom;
displayPosToMaintain.Y = -displayPosToMaintain.Y;
displayPosToMaintain = displayPosToMaintain.ClampLength(velRect.Width / 2);
displayPosToMaintain = steerArea.Rect.Center.ToVector2() + displayPosToMaintain;
@@ -494,11 +491,11 @@ namespace Barotrauma.Items.Components
if (maintainPosOriginIndicator != null)
{
maintainPosOriginIndicator.Draw(spriteBatch, displaySubPos, GUI.Style.Orange, scale: 0.5f * sonar.Zoom);
maintainPosOriginIndicator.Draw(spriteBatch, steeringOrigin, GUI.Style.Orange, scale: 0.5f * sonar.Zoom);
}
else
{
GUI.DrawRectangle(spriteBatch, new Rectangle((int)displaySubPos.X - 5, (int)displaySubPos.Y - 5, 10, 10), GUI.Style.Orange);
GUI.DrawRectangle(spriteBatch, new Rectangle((int)steeringOrigin.X - 5, (int)steeringOrigin.Y - 5, 10, 10), GUI.Style.Orange);
}
}
}
@@ -508,20 +505,19 @@ namespace Barotrauma.Items.Components
Vector2 steeringPos = new Vector2(
targetVelocity.X * 0.9f * (float)Math.Sqrt(1.0f - 0.5f * unitTargetVel.Y * unitTargetVel.Y),
-targetVelocity.Y * 0.9f * (float)Math.Sqrt(1.0f - 0.5f * unitTargetVel.X * unitTargetVel.X));
steeringPos += displaySubPos;
steeringPos += steeringOrigin;
if (steeringIndicator != null)
{
Vector2 dir = steeringPos - displaySubPos;
Vector2 dir = steeringPos - steeringOrigin;
float angle = (float)Math.Atan2(dir.Y, dir.X);
steeringIndicator.Draw(spriteBatch, displaySubPos, Color.Gray, origin: steeringIndicator.Origin, rotate: angle,
steeringIndicator.Draw(spriteBatch, steeringOrigin, Color.Gray, origin: steeringIndicator.Origin, rotate: angle,
scale: new Vector2(dir.Length() / steeringIndicator.size.X, 0.7f));
}
else
{
GUI.DrawLine(spriteBatch,
displaySubPos,
steeringOrigin,
steeringPos,
Color.CadetBlue, 0, 2);
}
@@ -669,11 +665,7 @@ namespace Barotrauma.Items.Components
{
if (PlayerInput.PrimaryMouseButtonHeld() && !CrewManager.IsCommandInterfaceOpen && !GameSession.IsTabMenuOpen)
{
Vector2 displaySubPos = (-sonar.DisplayOffset * sonar.Zoom) / sonar.Range * sonar.DisplayRadius * sonar.Zoom;
displaySubPos.Y = -displaySubPos.Y;
displaySubPos = steerArea.Rect.Center.ToVector2() + displaySubPos;
Vector2 inputPos = PlayerInput.MousePosition - displaySubPos;
Vector2 inputPos = PlayerInput.MousePosition - steerArea.Rect.Center.ToVector2();
inputPos.Y = -inputPos.Y;
if (AutoPilot && !LevelStartSelected && !LevelEndSelected)
{
@@ -848,7 +840,6 @@ namespace Barotrauma.Items.Components
Vector2 newSteeringInput = steeringInput;
Vector2 newTargetVelocity = targetVelocity;
float newSteeringAdjustSpeed = steeringAdjustSpeed;
bool maintainPos = false;
Vector2? newPosToMaintain = null;
bool headingToStart = false;
@@ -859,8 +850,7 @@ namespace Barotrauma.Items.Components
if (autoPilot)
{
maintainPos = msg.ReadBoolean();
if (maintainPos)
if (msg.ReadBoolean())
{
newPosToMaintain = new Vector2(
msg.ReadSingle(),

View File

@@ -27,6 +27,8 @@ namespace Barotrauma.Items.Components
private FixActions requestStartFixAction;
public float FakeBrokenTimer;
[Serialize("", false, description: "An optional description of the needed repairs displayed in the repair interface.")]
public string Description
{
@@ -43,7 +45,7 @@ namespace Barotrauma.Items.Components
public override bool ShouldDrawHUD(Character character)
{
if (!HasRequiredItems(character, false) || character.SelectedConstruction != item) return false;
return !item.IsFullCondition || character.IsTraitor && item.ConditionPercentage > MinSabotageCondition || (CurrentFixer == character && (!item.IsFullCondition || (character.IsTraitor && item.ConditionPercentage > MinSabotageCondition)));
return item.ConditionPercentage < RepairThreshold || character.IsTraitor && item.ConditionPercentage > MinSabotageCondition || (CurrentFixer == character && (!item.IsFullCondition || (character.IsTraitor && item.ConditionPercentage > MinSabotageCondition)));
}
partial void InitProjSpecific(XElement element)
@@ -136,6 +138,17 @@ namespace Barotrauma.Items.Components
partial void UpdateProjSpecific(float deltaTime)
{
if (Character.Controlled == null || (Character.Controlled.CharacterHealth.GetAffliction("psychosis")?.Strength ?? 0.0f) <= 0.0f)
{
FakeBrokenTimer = 0.0f;
}
else
{
FakeBrokenTimer -= deltaTime;
}
item.FakeBroken = FakeBrokenTimer > 0.0f;
if (!GameMain.IsMultiplayer)
{
switch (requestStartFixAction)
@@ -150,10 +163,10 @@ namespace Barotrauma.Items.Components
break;
}
}
for (int i = 0; i < particleEmitters.Count; i++)
{
if (item.ConditionPercentage >= particleEmitterConditionRanges[i].X && item.ConditionPercentage <= particleEmitterConditionRanges[i].Y)
if ((item.ConditionPercentage >= particleEmitterConditionRanges[i].X && item.ConditionPercentage <= particleEmitterConditionRanges[i].Y) || FakeBrokenTimer > 0.0f)
{
particleEmitters[i].Emit(deltaTime, item.WorldPosition, item.CurrentHull);
}

View File

@@ -379,7 +379,7 @@ namespace Barotrauma.Items.Components
ConnectionPanel.HighlightedWire = wire;
bool allowRewiring = GameMain.NetworkMember?.ServerSettings == null || GameMain.NetworkMember.ServerSettings.AllowRewiring;
if (allowRewiring && !wire.Locked && (!panel.Locked || Screen.Selected == GameMain.SubEditorScreen))
if (allowRewiring && (!wire.Locked && !panel.Locked || Screen.Selected == GameMain.SubEditorScreen))
{
//start dragging the wire
if (PlayerInput.PrimaryMouseButtonHeld()) { DraggingConnected = wire; }

View File

@@ -285,6 +285,8 @@ namespace Barotrauma.Items.Components
public static void UpdateEditing(List<Wire> wires)
{
var doubleClicked = PlayerInput.DoubleClicked();
Wire equippedWire =
Character.Controlled?.SelectedItems[0]?.GetComponent<Wire>() ??
Character.Controlled?.SelectedItems[1]?.GetComponent<Wire>();
@@ -298,7 +300,7 @@ namespace Barotrauma.Items.Components
}
//dragging a node of some wire
if (draggingWire != null)
if (draggingWire != null && !doubleClicked)
{
if (Character.Controlled != null)
{
@@ -329,15 +331,18 @@ namespace Barotrauma.Items.Components
if (selectedNodeIndex.HasValue)
{
nodeWorldPos.X = MathUtils.Round(nodeWorldPos.X, Submarine.GridSize.X / 2.0f);
nodeWorldPos.Y = MathUtils.Round(nodeWorldPos.Y, Submarine.GridSize.Y / 2.0f);
if (!PlayerInput.IsShiftDown())
{
nodeWorldPos.X = MathUtils.Round(nodeWorldPos.X, Submarine.GridSize.X / 2.0f);
nodeWorldPos.Y = MathUtils.Round(nodeWorldPos.Y, Submarine.GridSize.Y / 2.0f);
}
draggingWire.nodes[(int)selectedNodeIndex] = nodeWorldPos;
draggingWire.UpdateSections();
}
else
{
if (Vector2.DistanceSquared(nodeWorldPos, draggingWire.nodes[(int)highlightedNodeIndex]) > Submarine.GridSize.X * Submarine.GridSize.X)
if (Vector2.DistanceSquared(nodeWorldPos, draggingWire.nodes[(int)highlightedNodeIndex]) > Submarine.GridSize.X * Submarine.GridSize.X || PlayerInput.IsShiftDown())
{
selectedNodeIndex = highlightedNodeIndex;
}
@@ -350,6 +355,8 @@ namespace Barotrauma.Items.Components
return;
}
bool updateHighlight = true;
//a wire has been selected -> check if we should start dragging one of the nodes
float nodeSelectDist = 10, sectionSelectDist = 5;
highlightedNodeIndex = null;
@@ -405,6 +412,37 @@ namespace Barotrauma.Items.Components
{
selectedWire.nodes.RemoveAt(closestIndex);
selectedWire.UpdateSections();
}
// if only one end of the wire is disconnect pick it back up with double click
else if (doubleClicked && equippedWire == null && Character.Controlled != null && selectedWire.connections.Any(conn => conn != null))
{
if (selectedWire.connections[0] == null && closestIndex == 0 || selectedWire.connections[1] == null && closestIndex == selectedWire.nodes.Count - 1)
{
selectedWire.IsActive = true;
selectedWire.nodes.RemoveAt(closestIndex);
selectedWire.UpdateSections();
// flip the wire
if (closestIndex == 0)
{
selectedWire.nodes.Reverse();
selectedWire.connections[0] = selectedWire.connections[1];
selectedWire.connections[1] = null;
}
selectedWire.shouldClearConnections = false;
Character.Controlled.Inventory.TryPutItem(selectedWire.item, Character.Controlled, new List<InvSlotType> { InvSlotType.LeftHand, InvSlotType.RightHand });
foreach (var entity in MapEntity.mapEntityList)
{
if (entity is Item item)
{
item.GetComponent<ConnectionPanel>()?.DisconnectedWires.Remove(selectedWire);
}
}
MapEntity.SelectedList.Clear();
selectedWire.shouldClearConnections = true;
updateHighlight = false;
}
}
}
}
@@ -446,7 +484,7 @@ namespace Barotrauma.Items.Components
}
}
if (highlighted != null)
if (highlighted != null && updateHighlight)
{
highlighted.item.IsHighlighted = true;
if (PlayerInput.PrimaryMouseButtonClicked())

View File

@@ -5,7 +5,7 @@ using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
using System.IO;
using Barotrauma.IO;
using System.Linq;
using System.Xml.Linq;

View File

@@ -31,7 +31,7 @@ namespace Barotrauma
public Sprite SlotSprite;
public Keys QuickUseKey;
public int InventoryKeyIndex = -1;
public int SubInventoryDir = -1;
@@ -709,12 +709,15 @@ namespace Barotrauma
/// Is the mouse on any inventory element (slot, equip button, subinventory...)
/// </summary>
/// <returns></returns>
public static bool IsMouseOnInventory()
public static bool IsMouseOnInventory(bool ignoreDraggedItem = false)
{
var isSubEditor = Screen.Selected is SubEditorScreen editor && !editor.WiringMode;
if (Character.Controlled == null) return false;
if (Character.Controlled == null) { return false; }
if (draggingItem != null || DraggingInventory != null) return true;
if (!ignoreDraggedItem)
{
if (draggingItem != null || DraggingInventory != null) { return true; }
}
if (Character.Controlled.Inventory != null && !isSubEditor)
{
@@ -966,7 +969,8 @@ namespace Barotrauma
{
Character.Controlled.ClearInputs();
if (CharacterHealth.OpenHealthWindow != null &&
if (!IsMouseOnInventory(ignoreDraggedItem: true) &&
CharacterHealth.OpenHealthWindow != null &&
CharacterHealth.OpenHealthWindow.OnItemDropped(draggingItem, false))
{
draggingItem = null;
@@ -1078,7 +1082,7 @@ namespace Barotrauma
protected static Rectangle GetSubInventoryHoverArea(SlotReference subSlot)
{
Rectangle hoverArea;
if (!subSlot.Inventory.Movable())
if (!subSlot.Inventory.Movable() || Character.Controlled?.Inventory == subSlot.ParentInventory && !Character.Controlled.HasEquippedItem(subSlot.Item))
{
hoverArea = subSlot.Slot.Rect;
hoverArea.Location += subSlot.Slot.DrawOffset.ToPoint();
@@ -1251,7 +1255,7 @@ namespace Barotrauma
if (item != null && drawItem)
{
if (!item.IsFullCondition && (itemContainer == null || !itemContainer.ShowConditionInContainedStateIndicator))
if (!item.IsFullCondition && !item.Prefab.HideConditionBar && (itemContainer == null || !itemContainer.ShowConditionInContainedStateIndicator))
{
GUI.DrawRectangle(spriteBatch, new Rectangle(rect.X, rect.Bottom - 8, rect.Width, 8), Color.Black * 0.8f, true);
GUI.DrawRectangle(spriteBatch,
@@ -1378,10 +1382,10 @@ namespace Barotrauma
if (inventory != null &&
!inventory.Locked &&
Character.Controlled?.Inventory == inventory &&
slot.QuickUseKey != Keys.None)
slot.InventoryKeyIndex != -1)
{
spriteBatch.Draw(slotHotkeySprite.Texture, rect.ScaleSize(1.15f), slotHotkeySprite.SourceRect, slotColor);
GUI.DrawString(spriteBatch, rect.Location.ToVector2() + new Vector2((int)(4.25f * UIScale), (int)Math.Ceiling(-1.5f * UIScale)), slot.QuickUseKey.ToString().Substring(1, 1), Color.Black, font: GUI.HotkeyFont);
GUI.DrawString(spriteBatch, rect.Location.ToVector2() + new Vector2((int)(4.25f * UIScale), (int)Math.Ceiling(-1.5f * UIScale)), GameMain.Config.InventoryKeyBind(slot.InventoryKeyIndex).Name, Color.Black, font: GUI.HotkeyFont);
}
}

View File

@@ -32,6 +32,20 @@ namespace Barotrauma
private readonly Dictionary<DecorativeSprite, DecorativeSprite.State> spriteAnimState = new Dictionary<DecorativeSprite, DecorativeSprite.State>();
private bool fakeBroken;
public bool FakeBroken
{
get { return fakeBroken; }
set
{
if (value != fakeBroken)
{
fakeBroken = value;
SetActiveSprite();
}
}
}
private Sprite activeSprite;
public override Sprite Sprite
{
@@ -71,6 +85,10 @@ namespace Barotrauma
{
get
{
if (!GameMain.SubEditorScreen.ShowThalamus && prefab.Category.HasFlag(MapEntityCategory.Thalamus))
{
return false;
}
return parentInventory == null && (body == null || body.Enabled) && ShowItems;
}
}
@@ -139,11 +157,12 @@ namespace Barotrauma
}
}
float displayCondition = FakeBroken ? 0.0f : condition;
for (int i = 0; i < Prefab.BrokenSprites.Count;i++)
{
if (Prefab.BrokenSprites[i].FadeIn) { continue; }
float minCondition = i > 0 ? Prefab.BrokenSprites[i - i].MaxCondition : 0.0f;
if (condition <= minCondition ||
condition <= Prefab.BrokenSprites[i].MaxCondition && !Prefab.BrokenSprites[i].FadeIn)
if (displayCondition <= minCondition || displayCondition <= Prefab.BrokenSprites[i].MaxCondition)
{
activeSprite = Prefab.BrokenSprites[i].Sprite;
break;
@@ -225,7 +244,9 @@ namespace Barotrauma
BrokenItemSprite fadeInBrokenSprite = null;
float fadeInBrokenSpriteAlpha = 0.0f;
if (condition < Prefab.Health)
float displayCondition = FakeBroken ? 0.0f : condition;
Vector2 drawOffset = Vector2.Zero;
if (displayCondition < Prefab.Health)
{
for (int i = 0; i < Prefab.BrokenSprites.Count; i++)
{
@@ -233,16 +254,17 @@ namespace Barotrauma
{
float min = i > 0 ? Prefab.BrokenSprites[i - i].MaxCondition : 0.0f;
float max = Prefab.BrokenSprites[i].MaxCondition;
fadeInBrokenSpriteAlpha = 1.0f - ((condition - min) / (max - min));
if (fadeInBrokenSpriteAlpha > 0.0f && fadeInBrokenSpriteAlpha < 1.0f)
fadeInBrokenSpriteAlpha = 1.0f - ((displayCondition - min) / (max - min));
if (fadeInBrokenSpriteAlpha > 0.0f && fadeInBrokenSpriteAlpha <= 1.0f)
{
fadeInBrokenSprite = Prefab.BrokenSprites[i];
}
continue;
}
if (condition <= Prefab.BrokenSprites[i].MaxCondition)
if (displayCondition <= Prefab.BrokenSprites[i].MaxCondition)
{
activeSprite = Prefab.BrokenSprites[i].Sprite;
drawOffset = Prefab.BrokenSprites[i].Offset.ToVector2() * Scale;
break;
}
}
@@ -264,9 +286,13 @@ namespace Barotrauma
{
if (prefab.ResizeHorizontal || prefab.ResizeVertical)
{
activeSprite.DrawTiled(spriteBatch, new Vector2(DrawPosition.X - rect.Width / 2, -(DrawPosition.Y + rect.Height / 2)), new Vector2(rect.Width, rect.Height), color: color,
Vector2 size = new Vector2(rect.Width, rect.Height);
activeSprite.DrawTiled(spriteBatch, new Vector2(DrawPosition.X - rect.Width / 2, -(DrawPosition.Y + rect.Height / 2)) + drawOffset,
size, color: color,
textureScale: Vector2.One * Scale,
depth: depth);
fadeInBrokenSprite?.Sprite.DrawTiled(spriteBatch, new Vector2(DrawPosition.X - rect.Width / 2, -(DrawPosition.Y + rect.Height / 2)), new Vector2(rect.Width, rect.Height), color: color * fadeInBrokenSpriteAlpha,
fadeInBrokenSprite?.Sprite.DrawTiled(spriteBatch, new Vector2(DrawPosition.X - rect.Width / 2, -(DrawPosition.Y + rect.Height / 2)) + fadeInBrokenSprite.Offset.ToVector2() * Scale, size, color: color * fadeInBrokenSpriteAlpha,
textureScale: Vector2.One * Scale,
depth: depth - 0.000001f);
foreach (var decorativeSprite in Prefab.DecorativeSprites)
{
@@ -280,8 +306,8 @@ namespace Barotrauma
}
else
{
activeSprite.Draw(spriteBatch, new Vector2(DrawPosition.X, -DrawPosition.Y), color, SpriteRotation, Scale, activeSprite.effects, depth);
fadeInBrokenSprite?.Sprite.Draw(spriteBatch, new Vector2(DrawPosition.X, -DrawPosition.Y), color * fadeInBrokenSpriteAlpha, SpriteRotation, Scale, activeSprite.effects, depth - 0.000001f);
activeSprite.Draw(spriteBatch, new Vector2(DrawPosition.X, -DrawPosition.Y) + drawOffset, color, SpriteRotation, Scale, activeSprite.effects, depth);
fadeInBrokenSprite?.Sprite.Draw(spriteBatch, new Vector2(DrawPosition.X, -DrawPosition.Y) + fadeInBrokenSprite.Offset.ToVector2() * Scale, color * fadeInBrokenSpriteAlpha, SpriteRotation, Scale, activeSprite.effects, depth - 0.000001f);
foreach (var decorativeSprite in Prefab.DecorativeSprites)
{
if (!spriteAnimState[decorativeSprite].IsActive) { continue; }
@@ -302,19 +328,25 @@ namespace Barotrauma
if (holdable.Picker.SelectedItems[0] == this)
{
Limb holdLimb = holdable.Picker.AnimController.GetLimb(LimbType.RightHand);
depth = holdLimb.ActiveSprite.Depth + holdable.Picker.AnimController.GetDepthOffset() + depthStep * 2;
foreach (WearableSprite wearableSprite in holdLimb.WearingItems)
if (holdLimb != null)
{
if (!wearableSprite.InheritLimbDepth && wearableSprite.Sprite != null) { depth = Math.Max(wearableSprite.Sprite.Depth + depthStep, depth); }
depth = holdLimb.ActiveSprite.Depth + holdable.Picker.AnimController.GetDepthOffset() + depthStep * 2;
foreach (WearableSprite wearableSprite in holdLimb.WearingItems)
{
if (!wearableSprite.InheritLimbDepth && wearableSprite.Sprite != null) { depth = Math.Max(wearableSprite.Sprite.Depth + depthStep, depth); }
}
}
}
else if (holdable.Picker.SelectedItems[1] == this)
{
Limb holdLimb = holdable.Picker.AnimController.GetLimb(LimbType.LeftHand);
depth = holdLimb.ActiveSprite.Depth + holdable.Picker.AnimController.GetDepthOffset() - depthStep * 2;
foreach (WearableSprite wearableSprite in holdLimb.WearingItems)
if (holdLimb != null)
{
if (!wearableSprite.InheritLimbDepth && wearableSprite.Sprite != null) { depth = Math.Min(wearableSprite.Sprite.Depth - depthStep, depth); }
depth = holdLimb.ActiveSprite.Depth + holdable.Picker.AnimController.GetDepthOffset() - depthStep * 2;
foreach (WearableSprite wearableSprite in holdLimb.WearingItems)
{
if (!wearableSprite.InheritLimbDepth && wearableSprite.Sprite != null) { depth = Math.Min(wearableSprite.Sprite.Depth - depthStep, depth); }
}
}
}
}
@@ -1263,6 +1295,14 @@ namespace Barotrauma
inventory = container.Inventory;
}
}
else if (inventoryOwner == null)
{
DebugConsole.ThrowError($"Failed to spawn item \"{(itemIdentifier ?? "null")}\" in the inventory of an entity with the ID {inventoryId} (entity not found)");
}
else
{
DebugConsole.ThrowError($"Failed to spawn item \"{(itemIdentifier ?? "null")}\" in the inventory of \"{inventoryOwner} ({inventoryOwner.ID})\" (invalid entity, should be an item or a character)");
}
}
var item = new Item(itemPrefab, pos, sub)

View File

@@ -14,12 +14,14 @@ namespace Barotrauma
public readonly float MaxCondition;
public readonly Sprite Sprite;
public readonly bool FadeIn;
public readonly Point Offset;
public BrokenItemSprite(Sprite sprite, float maxCondition, bool fadeIn)
public BrokenItemSprite(Sprite sprite, float maxCondition, bool fadeIn, Point offset)
{
Sprite = sprite;
MaxCondition = MathHelper.Clamp(maxCondition, 0.0f, 100.0f);
FadeIn = fadeIn;
Offset = offset;
}
}

View File

@@ -60,10 +60,10 @@ namespace Barotrauma
var particle = GameMain.ParticleManager.CreateParticle("flame",
particlePos, particleVel, 0.0f, hull);
if (particle == null) continue;
if (particle == null) { continue; }
//make some of the particles create another firesource when they enter another hull
if (Rand.Int(20) == 1) particle.OnChangeHull = onChangeHull;
if (Rand.Int(20) == 1) { particle.OnChangeHull = onChangeHull; }
particle.Size *= MathHelper.Clamp(size.X / 60.0f * Math.Max(hull.Oxygen / hull.Volume, 0.4f), 0.5f, 1.0f);

View File

@@ -2,6 +2,7 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Linq;
namespace Barotrauma
{
@@ -24,7 +25,7 @@ namespace Barotrauma
public override void Draw(SpriteBatch sb, bool editing, bool back = true)
{
if (!GameMain.DebugDraw && Screen.Selected.Cam.Zoom > 0.1f)
if (GameMain.DebugDraw && Screen.Selected.Cam.Zoom > 0.1f)
{
Vector2 center = new Vector2(WorldRect.X + rect.Width / 2.0f, -(WorldRect.Y - rect.Height / 2.0f));
GUI.DrawLine(sb, center, center + new Vector2(flowForce.X, -flowForce.Y) / 10.0f, GUI.Style.Red);
@@ -121,24 +122,36 @@ namespace Barotrauma
partial void EmitParticles(float deltaTime)
{
if (flowTargetHull == null) return;
if (flowTargetHull == null) { return; }
if (linkedTo.Count == 2 && linkedTo[0] is Hull hull1 && linkedTo[1] is Hull hull2)
{
//no flow particles between linked hulls (= rooms consisting of multiple hulls)
if (hull1.linkedTo.Contains(hull2)) { return; }
if (hull1.linkedTo.Any(h => h.linkedTo.Contains(hull1) && h.linkedTo.Contains(hull2))) { return; }
if (hull2.linkedTo.Any(h => h.linkedTo.Contains(hull1) && h.linkedTo.Contains(hull2))) { return; }
}
Vector2 pos = Position;
if (IsHorizontal)
{
pos.X += Math.Sign(flowForce.X);
pos.Y = MathHelper.Clamp((higherSurface + lowerSurface) / 2.0f, rect.Y - rect.Height, rect.Y) + 10;
pos.Y = MathHelper.Clamp(Rand.Range(higherSurface, lowerSurface), rect.Y - rect.Height, rect.Y);
}
else
{
pos.Y += Math.Sign(flowForce.Y) * rect.Height / 2.0f;
}
//spawn less particles when there's already a large number of them
float particleAmountMultiplier = 1.0f - GameMain.ParticleManager.ParticleCount / (float)GameMain.ParticleManager.MaxParticles;
particleAmountMultiplier *= particleAmountMultiplier;
//light dripping
if (open < 0.2f && LerpedFlowForce.LengthSquared() > 100.0f)
{
particleTimer += deltaTime;
float particlesPerSec = open * 100.0f;
float particlesPerSec = open * 100.0f * particleAmountMultiplier;
float emitInterval = 1.0f / particlesPerSec;
while (particleTimer > emitInterval)
{
@@ -174,12 +187,13 @@ namespace Barotrauma
particleTimer += deltaTime;
if (IsHorizontal)
{
float particlesPerSec = open * rect.Height * 0.1f;
float particlesPerSec = open * rect.Height * 0.1f * particleAmountMultiplier;
if (openedTimer > 0.0f) { particlesPerSec *= 1.0f + openedTimer * 10.0f; }
float emitInterval = 1.0f / particlesPerSec;
while (particleTimer > emitInterval)
{
Vector2 velocity = new Vector2(
MathHelper.Clamp(flowForce.X, -5000.0f, 5000.0f) * Rand.Range(0.5f, 0.7f),
MathHelper.Clamp(flowForce.X, -5000.0f, 5000.0f) * Rand.Range(0.5f, 0.7f),
flowForce.Y * Rand.Range(0.5f, 0.7f));
if (flowTargetHull.WaterVolume < flowTargetHull.Volume * 0.95f)
@@ -191,11 +205,11 @@ namespace Barotrauma
if (particle != null)
{
particle.Size = particle.Size * Math.Min(Math.Abs(flowForce.X / 1000.0f), 5.0f);
particle.Size *= Math.Min(Math.Abs(flowForce.X / 500.0f), 5.0f);
}
}
if (Math.Abs(flowForce.X) > 300.0f)
if (Math.Abs(flowForce.X) > 300.0f && flowTargetHull.WaterVolume > flowTargetHull.Volume * 0.1f)
{
pos.X += Math.Sign(flowForce.X) * 10.0f;
if (rect.Height < 32)
@@ -211,7 +225,7 @@ namespace Barotrauma
GameMain.ParticleManager.CreateParticle(
"bubbles",
Submarine == null ? pos : pos + Submarine.Position,
flowForce / 10.0f, 0, flowTargetHull);
velocity, 0, flowTargetHull);
}
particleTimer -= emitInterval;
}
@@ -220,7 +234,7 @@ namespace Barotrauma
{
if (Math.Sign(flowTargetHull.Rect.Y - rect.Y) != Math.Sign(lerpedFlowForce.Y)) return;
float particlesPerSec = open * rect.Width * 0.3f;
float particlesPerSec = open * rect.Width * 0.3f * particleAmountMultiplier;
float emitInterval = 1.0f / particlesPerSec;
while (particleTimer > emitInterval)
{
@@ -237,7 +251,7 @@ namespace Barotrauma
velocity, 0, FlowTargetHull);
if (splash != null) splash.Size = splash.Size * MathHelper.Clamp(rect.Width / 50.0f, 0.8f, 4.0f);
}
if (Math.Abs(flowForce.Y) > 190.0f && Rand.Range(0.0f, 1.0f) < 0.3f)
if (Math.Abs(flowForce.Y) > 190.0f && Rand.Range(0.0f, 1.0f) < 0.3f && flowTargetHull.WaterVolume > flowTargetHull.Volume * 0.1f)
{
GameMain.ParticleManager.CreateParticle(
"bubbles",

View File

@@ -14,7 +14,7 @@ namespace Barotrauma
{
public const int MaxDecalsPerHull = 10;
private List<Decal> decals = new List<Decal>();
private readonly List<Decal> decals = new List<Decal>();
private float serverUpdateDelay;
private float remoteWaterVolume, remoteOxygenPercentage;
@@ -23,6 +23,8 @@ namespace Barotrauma
private bool networkUpdatePending;
private float networkUpdateTimer;
private double lastAmbientLightEditTime;
public override bool SelectableInEditor
{
get
@@ -232,33 +234,36 @@ namespace Barotrauma
return;
}
/*if (!Visible)
if (!ShowHulls && !GameMain.DebugDraw) { return; }
if (!editing && (!GameMain.DebugDraw || Screen.Selected.Cam.Zoom < 0.1f)) { return; }
float alpha = 1.0f;
float hideTimeAfterEdit = 3.0f;
if (lastAmbientLightEditTime > Timing.TotalTime - hideTimeAfterEdit * 2.0f)
{
drawRect =
Submarine == null ? rect : new Rectangle((int)(Submarine.DrawPosition.X + rect.X), (int)(Submarine.DrawPosition.Y + rect.Y), rect.Width, rect.Height);
GUI.DrawRectangle(spriteBatch,
new Vector2(drawRect.X, -drawRect.Y),
new Vector2(rect.Width, rect.Height),
Color.Black, true,
0, (int)Math.Max((1.5f / GameScreen.Selected.Cam.Zoom), 1.0f));
}*/
if (!ShowHulls && !GameMain.DebugDraw) return;
if (!editing && (!GameMain.DebugDraw || Screen.Selected.Cam.Zoom < 0.1f)) return;
alpha = Math.Min((float)(Timing.TotalTime - lastAmbientLightEditTime) / hideTimeAfterEdit - 1.0f, 1.0f);
}
Rectangle drawRect =
Submarine == null ? rect : new Rectangle((int)(Submarine.DrawPosition.X + rect.X), (int)(Submarine.DrawPosition.Y + rect.Y), rect.Width, rect.Height);
if ((IsSelected || IsHighlighted) && editing)
{
GUI.DrawRectangle(spriteBatch,
new Vector2(drawRect.X, -drawRect.Y),
new Vector2(rect.Width, rect.Height),
(IsHighlighted ? Color.LightBlue * 0.8f : GUI.Style.Red * 0.5f) * alpha, false, 0, (int)Math.Max(5.0f / Screen.Selected.Cam.Zoom, 1.0f));
}
GUI.DrawRectangle(spriteBatch,
new Vector2(drawRect.X, -drawRect.Y),
new Vector2(rect.Width, rect.Height),
Color.Blue, false, (ID % 255) * 0.000001f, (int)Math.Max((1.5f / Screen.Selected.Cam.Zoom), 1.0f));
Color.Blue * alpha, false, (ID % 255) * 0.000001f, (int)Math.Max(1.5f / Screen.Selected.Cam.Zoom, 1.0f));
GUI.DrawRectangle(spriteBatch,
new Rectangle(drawRect.X, -drawRect.Y, rect.Width, rect.Height),
GUI.Style.Red * ((100.0f - OxygenPercentage) / 400.0f), true, 0, (int)Math.Max((1.5f / GameScreen.Selected.Cam.Zoom), 1.0f));
GUI.Style.Red * ((100.0f - OxygenPercentage) / 400.0f) * alpha, true, 0, (int)Math.Max(1.5f / Screen.Selected.Cam.Zoom, 1.0f));
if (GameMain.DebugDraw)
{
@@ -277,10 +282,12 @@ namespace Barotrauma
foreach (FireSource fs in FireSources)
{
Rectangle fireSourceRect = new Rectangle((int)fs.WorldPosition.X, -(int)fs.WorldPosition.Y, (int)fs.Size.X, (int)fs.Size.Y);
GUI.DrawRectangle(spriteBatch, fireSourceRect, GUI.Style.Orange, false, 0, 5);
GUI.DrawRectangle(spriteBatch, fireSourceRect, GUI.Style.Red, false, 0, 5);
GUI.DrawRectangle(spriteBatch, new Rectangle(fireSourceRect.X - (int)fs.DamageRange, fireSourceRect.Y, fireSourceRect.Width + (int)fs.DamageRange * 2, fireSourceRect.Height), GUI.Style.Orange, false, 0, 5);
//GUI.DrawRectangle(spriteBatch, new Rectangle((int)fs.LastExtinguishPos.X, (int)-fs.LastExtinguishPos.Y, 5,5), Color.Yellow, true);
}
/*GUI.DrawLine(spriteBatch, new Vector2(drawRect.X, -WorldSurface), new Vector2(drawRect.Right, -WorldSurface), Color.Cyan * 0.5f);
for (int i = 0; i < waveY.Length - 1; i++)
{
@@ -290,24 +297,15 @@ namespace Barotrauma
}*/
}
if ((IsSelected || IsHighlighted) && editing)
{
GUI.DrawRectangle(spriteBatch,
new Vector2(drawRect.X + 5, -drawRect.Y + 5),
new Vector2(rect.Width - 10, rect.Height - 10),
IsHighlighted ? Color.LightBlue * 0.5f : GUI.Style.Red * 0.5f, true, 0, (int)Math.Max((1.5f / GameScreen.Selected.Cam.Zoom), 1.0f));
}
foreach (MapEntity e in linkedTo)
{
if (e is Hull)
if (e is Hull linkedHull)
{
Hull linkedHull = (Hull)e;
Rectangle connectedHullRect = e.Submarine == null ?
linkedHull.rect :
Rectangle connectedHullRect = e.Submarine == null ?
linkedHull.rect :
new Rectangle(
(int)(Submarine.DrawPosition.X + linkedHull.WorldPosition.X),
(int)(Submarine.DrawPosition.Y + linkedHull.WorldPosition.Y),
(int)(Submarine.DrawPosition.Y + linkedHull.WorldPosition.Y),
linkedHull.WorldRect.Width, linkedHull.WorldRect.Height);
//center of the hull
@@ -315,7 +313,7 @@ namespace Barotrauma
WorldRect :
new Rectangle(
(int)(Submarine.DrawPosition.X + WorldPosition.X),
(int)(Submarine.DrawPosition.Y + WorldPosition.Y),
(int)(Submarine.DrawPosition.Y + WorldPosition.Y),
WorldRect.Width, WorldRect.Height);
GUI.DrawLine(spriteBatch,
@@ -326,22 +324,22 @@ namespace Barotrauma
}
}
public static void UpdateVertices(GraphicsDevice graphicsDevice, Camera cam, WaterRenderer renderer)
public static void UpdateVertices(Camera cam, WaterRenderer renderer)
{
foreach (EntityGrid entityGrid in EntityGrids)
{
if (entityGrid.WorldRect.X > cam.WorldView.Right || entityGrid.WorldRect.Right < cam.WorldView.X) continue;
if (entityGrid.WorldRect.Y - entityGrid.WorldRect.Height > cam.WorldView.Y || entityGrid.WorldRect.Y < cam.WorldView.Y - cam.WorldView.Height) continue;
if (entityGrid.WorldRect.X > cam.WorldView.Right || entityGrid.WorldRect.Right < cam.WorldView.X) { continue; }
if (entityGrid.WorldRect.Y - entityGrid.WorldRect.Height > cam.WorldView.Y || entityGrid.WorldRect.Y < cam.WorldView.Y - cam.WorldView.Height) { continue; }
var allEntities = entityGrid.GetAllEntities();
foreach (Hull hull in allEntities)
{
hull.UpdateVertices(graphicsDevice, cam, entityGrid, renderer);
hull.UpdateVertices(cam, entityGrid, renderer);
}
}
}
private void UpdateVertices(GraphicsDevice graphicsDevice, Camera cam, EntityGrid entityGrid, WaterRenderer renderer)
private void UpdateVertices(Camera cam, EntityGrid entityGrid, WaterRenderer renderer)
{
Vector2 submarinePos = Submarine == null ? Vector2.Zero : Submarine.DrawPosition;
@@ -554,11 +552,10 @@ namespace Barotrauma
remoteOxygenPercentage = message.ReadRangedSingle(0.0f, 100.0f, 8);
bool hasFireSources = message.ReadBoolean();
int fireSourceCount = 0;
remoteFireSources = new List<Vector3>();
if (hasFireSources)
{
fireSourceCount = message.ReadRangedInteger(0, 16);
int fireSourceCount = message.ReadRangedInteger(0, 16);
for (int i = 0; i < fireSourceCount; i++)
{
remoteFireSources.Add(new Vector3(

View File

@@ -18,6 +18,7 @@ namespace Barotrauma
foreach (Pair<MapEntityPrefab, Rectangle> entity in DisplayEntities)
{
if (entity.First is CoreEntityPrefab) { continue; }
Rectangle drawRect = entity.Second;
drawRect = new Rectangle(
(int)(drawRect.X * scale) + drawArea.Center.X, (int)((drawRect.Y) * scale) - drawArea.Center.Y,

View File

@@ -93,9 +93,9 @@ namespace Barotrauma.Lights
public static BasicEffect shadowEffect;
public static BasicEffect penumbraEffect;
private Segment[] segments = new Segment[4];
private SegmentPoint[] vertices = new SegmentPoint[4];
private SegmentPoint[] losVertices = new SegmentPoint[4];
private readonly Segment[] segments = new Segment[4];
private readonly SegmentPoint[] vertices = new SegmentPoint[4];
private readonly SegmentPoint[] losVertices = new SegmentPoint[4];
private readonly bool[] backFacing;
private readonly bool[] ignoreEdge;
@@ -106,6 +106,8 @@ namespace Barotrauma.Lights
public VertexPositionTexture[] PenumbraVertices { get; private set; }
public int ShadowVertexCount { get; private set; }
private readonly HashSet<ConvexHull> overlappingHulls = new HashSet<ConvexHull>();
public MapEntity ParentEntity { get; private set; }
private bool enabled;
@@ -176,7 +178,7 @@ namespace Barotrauma.Lights
if (door != null) { isHorizontal = door.IsHorizontal; }
}
var chList = HullLists.Find(x => x.Submarine == parent.Submarine);
var chList = HullLists.Find(h => h.Submarine == parent.Submarine);
if (chList == null)
{
chList = new ConvexHullList(parent.Submarine);
@@ -194,10 +196,12 @@ namespace Barotrauma.Lights
private void MergeOverlappingSegments(ConvexHull ch)
{
if (ch == this) return;
if (ch == this) { return; }
if (isHorizontal == ch.isHorizontal)
{
if (BoundingBox == ch.BoundingBox) { return; }
//hide segments that are roughly at the some position as some other segment (e.g. the ends of two adjacent wall pieces)
float mergeDist = 32;
float mergeDistSqr = mergeDist * mergeDist;
@@ -206,6 +210,7 @@ namespace Barotrauma.Lights
for (int j = 0; j < ch.segments.Length; j++)
{
if (segments[i].IsHorizontal != ch.segments[j].IsHorizontal) { continue; }
if (ignoreEdge[i] || ch.ignoreEdge[j]) { continue; }
//the segments must be at different sides of the convex hulls to be merged
//(e.g. the right edge of a wall piece and the left edge of another one)
@@ -247,6 +252,7 @@ namespace Barotrauma.Lights
p.Y >= ch.BoundingBox.Y && p.Y <= ch.BoundingBox.Bottom)
{
ignoreEdge[i] = true;
overlappingHulls.Add(ch);
}
}
}
@@ -283,11 +289,25 @@ namespace Barotrauma.Lights
}
else
{
losVertices[startPointIndex].Pos = segment2.ConvexHull.losVertices[startPoint2Index].Pos =
(segment1.Start.Pos + segment2.End.Pos) / 2.0f;
losVertices[endPointIndex].Pos = segment2.ConvexHull.losVertices[endPoint2Index].Pos =
(segment1.End.Pos + segment2.Start.Pos) / 2.0f;
if (Vector2.DistanceSquared(losVertices[startPointIndex].Pos, segment1.Start.Pos) <
Vector2.DistanceSquared(losVertices[startPointIndex].Pos, segment1.End.Pos))
{
losVertices[startPointIndex].Pos = segment2.ConvexHull.losVertices[startPoint2Index].Pos =
(segment1.Start.Pos + segment2.End.Pos) / 2.0f;
losVertices[endPointIndex].Pos = segment2.ConvexHull.losVertices[endPoint2Index].Pos =
(segment1.End.Pos + segment2.Start.Pos) / 2.0f;
}
else
{
losVertices[startPointIndex].Pos = segment2.ConvexHull.losVertices[startPoint2Index].Pos =
(segment1.End.Pos + segment2.Start.Pos) / 2.0f;
losVertices[endPointIndex].Pos = segment2.ConvexHull.losVertices[endPoint2Index].Pos =
(segment1.Start.Pos + segment2.End.Pos) / 2.0f;
}
}
overlappingHulls.Add(segment2.ConvexHull);
segment2.ConvexHull.overlappingHulls.Add(this);
}
public void Rotate(Vector2 origin, float amount)
@@ -328,7 +348,50 @@ namespace Barotrauma.Lights
LastVertexChangeTime = (float)Timing.TotalTime;
overlappingHulls.Clear();
for (int i = 0; i < 4; i++)
{
ignoreEdge[i] = false;
}
CalculateDimensions();
if (ParentEntity == null) { return; }
var chList = HullLists.Find(h => h.Submarine == ParentEntity.Submarine);
if (chList != null)
{
overlappingHulls.Clear();
foreach (ConvexHull ch in chList.List)
{
MergeOverlappingSegments(ch);
ch.MergeOverlappingSegments(this);
}
}
}
public static void RecalculateAll(Submarine sub)
{
var chList = HullLists.Find(h => h.Submarine == sub);
if (chList != null)
{
foreach (ConvexHull ch in chList.List)
{
ch.overlappingHulls.Clear();
for (int i = 0; i < 4; i++)
{
ch.ignoreEdge[i] = false;
}
}
for (int i = 0; i < chList.List.Count; i++)
{
for (int j = i + 1; j < chList.List.Count; j++)
{
chList.List[i].MergeOverlappingSegments(chList.List[j]);
chList.List[j].MergeOverlappingSegments(chList.List[i]);
}
}
}
}
public void SetVertices(Vector2[] points, Matrix? rotationMatrix = null)
@@ -348,6 +411,8 @@ namespace Barotrauma.Lights
ignoreEdge[i] = false;
}
overlappingHulls.Clear();
int margin = 0;
if (Math.Abs(points[0].X - points[2].X) < Math.Abs(points[0].Y - points[2].Y))
{
@@ -381,9 +446,10 @@ namespace Barotrauma.Lights
if (ParentEntity == null) return;
var chList = HullLists.Find(x => x.Submarine == ParentEntity.Submarine);
var chList = HullLists.Find(h => h.Submarine == ParentEntity.Submarine);
if (chList != null)
{
overlappingHulls.Clear();
foreach (ConvexHull ch in chList.List)
{
MergeOverlappingSegments(ch);
@@ -484,8 +550,8 @@ namespace Barotrauma.Lights
//find beginning and ending vertices which
//belong to the shadow
int startingIndex = 0;
int endingIndex = 0;
int startingIndex = -1;
int endingIndex = -1;
for (int i = 0; i < 4; i++)
{
int currentEdge = i;
@@ -498,6 +564,8 @@ namespace Barotrauma.Lights
startingIndex = nextEdge;
}
if (startingIndex == -1 || endingIndex == -1) { return; }
//nr of vertices that are in the shadow
if (endingIndex > startingIndex)
ShadowVertexCount = endingIndex - startingIndex + 1;
@@ -663,7 +731,7 @@ namespace Barotrauma.Lights
public void Remove()
{
var chList = HullLists.Find(x => x.Submarine == ParentEntity.Submarine);
var chList = HullLists.Find(h => h.Submarine == ParentEntity.Submarine);
if (chList != null)
{
@@ -672,8 +740,19 @@ namespace Barotrauma.Lights
{
HullLists.Remove(chList);
}
foreach (ConvexHull ch2 in overlappingHulls)
{
for (int i = 0; i < 4; i++)
{
ch2.ignoreEdge[i] = false;
}
ch2.overlappingHulls.Remove(this);
foreach (ConvexHull ch in chList.List)
{
ch.MergeOverlappingSegments(ch2);
}
}
}
}
}
}

View File

@@ -11,18 +11,6 @@ namespace Barotrauma.Lights
{
class LightManager
{
private const float AmbientLightUpdateInterval = 0.2f;
private const float AmbientLightFalloff = 0.8f;
/// <summary>
/// Enables a feature that makes lights inside the hull increase the brightness of the entire hull
/// and adjacent ones to some extent, if there are gaps for the lights to pass through.
/// Prevents unnaturally dark looking shadows in otherwise well-lit submarines, but disabled at least for
/// the time being because it makes the lighting behave unpredictably and may cause rooms to appear
/// excessively bright if different lighting conditions aren't tested and accounted for.
/// </summary>
private static readonly bool UseHullSpecificAmbientLight = false;
public static Entity ViewTarget { get; set; }
private float currLightMapScale;
@@ -57,7 +45,7 @@ namespace Barotrauma.Lights
public Effect LosEffect { get; private set; }
public Effect SolidColorEffect { get; private set; }
private List<LightSource> lights;
private readonly List<LightSource> lights;
public bool LosEnabled = true;
public LosMode LosMode = LosMode.Transparent;
@@ -66,13 +54,8 @@ namespace Barotrauma.Lights
public bool ObstructVision;
private Texture2D visionCircle;
private readonly Texture2D visionCircle;
private Dictionary<Hull, Color> hullAmbientLights;
private Dictionary<Hull, Color> smoothedHullAmbientLights;
private float ambientLightUpdateTimer;
public IEnumerable<LightSource> Lights
{
get { return lights; }
@@ -80,7 +63,7 @@ namespace Barotrauma.Lights
public LightManager(GraphicsDevice graphics, ContentManager content)
{
lights = new List<LightSource>();
lights = new List<LightSource>(100);
AmbientLight = new Color(20, 20, 20, 255);
@@ -114,9 +97,6 @@ namespace Barotrauma.Lights
};
}
});
hullAmbientLights = new Dictionary<Hull, Color>();
smoothedHullAmbientLights = new Dictionary<Hull, Color>();
}
private void CreateRenderTargets(GraphicsDevice graphics)
@@ -167,43 +147,12 @@ namespace Barotrauma.Lights
}
}
public void Update(float deltaTime)
{
if (UseHullSpecificAmbientLight)
{
if (ambientLightUpdateTimer > 0.0f)
{
ambientLightUpdateTimer -= deltaTime;
}
else
{
CalculateAmbientLights();
ambientLightUpdateTimer = AmbientLightUpdateInterval;
}
foreach (Hull hull in hullAmbientLights.Keys)
{
if (!smoothedHullAmbientLights.ContainsKey(hull))
{
smoothedHullAmbientLights.Add(hull, Color.TransparentBlack);
}
}
foreach (Hull hull in smoothedHullAmbientLights.Keys.ToList())
{
Color targetColor = Color.TransparentBlack;
hullAmbientLights.TryGetValue(hull, out targetColor);
smoothedHullAmbientLights[hull] = Color.Lerp(smoothedHullAmbientLights[hull], targetColor, deltaTime);
}
}
}
private List<LightSource> activeLights = new List<LightSource>(capacity: 100);
private readonly List<LightSource> activeLights = new List<LightSource>(capacity: 100);
public void UpdateLightMap(GraphicsDevice graphics, SpriteBatch spriteBatch, Camera cam, RenderTarget2D backgroundObstructor = null)
{
if (!LightingEnabled) return;
if (!LightingEnabled) { return; }
if (Math.Abs(currLightMapScale - GameMain.Config.LightMapScale) > 0.01f)
{
//lightmap scale has changed -> recreate render targets
@@ -261,16 +210,14 @@ namespace Barotrauma.Lights
//draw background lights
//---------------------------------------------------------------------------------------------------
graphics.SetRenderTarget(LightMap);
graphics.Clear(Color.Black);
graphics.Clear(AmbientLight);
graphics.BlendState = BlendState.Additive;
bool backgroundSpritesDrawn = false;
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Additive, transformMatrix: spriteBatchTransform);
foreach (LightSource light in activeLights)
{
if (!light.IsBackground) { continue; }
light.DrawSprite(spriteBatch, cam);
if (light.Color.A > 0 && light.Range > 0.0f) { light.DrawLightVolume(spriteBatch, lightEffect, transform); }
backgroundSpritesDrawn = true;
}
GameMain.ParticleManager.Draw(spriteBatch, true, null, Particles.ParticleBlendState.Additive);
spriteBatch.End();
@@ -278,33 +225,34 @@ namespace Barotrauma.Lights
//draw a black rectangle on hulls to hide background lights behind subs
//---------------------------------------------------------------------------------------------------
Dictionary<Hull, Rectangle> visibleHulls = null;
if (backgroundSpritesDrawn)
if (backgroundObstructor != null)
{
if (backgroundObstructor != null)
{
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied);
spriteBatch.Draw(backgroundObstructor, new Rectangle(0, 0,
(int)(GameMain.GraphicsWidth * currLightMapScale), (int)(GameMain.GraphicsHeight * currLightMapScale)), Color.Black);
spriteBatch.End();
}
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.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied);
spriteBatch.Draw(backgroundObstructor, new Rectangle(0, 0,
(int)(GameMain.GraphicsWidth * currLightMapScale), (int)(GameMain.GraphicsHeight * currLightMapScale)), Color.Black);
spriteBatch.End();
graphics.BlendState = BlendState.Additive;
}
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Opaque, transformMatrix: spriteBatchTransform);
Dictionary<Hull, Rectangle> visibleHulls = GetVisibleHulls(cam);
foreach (KeyValuePair<Hull, Rectangle> hull in visibleHulls)
{
GUI.DrawRectangle(spriteBatch,
new Vector2(hull.Value.X, -hull.Value.Y),
new Vector2(hull.Value.Width, hull.Value.Height),
hull.Key.AmbientLight == Color.TransparentBlack ? Color.Black : hull.Key.AmbientLight.Multiply(hull.Key.AmbientLight.A / 255.0f), true);
}
spriteBatch.End();
SolidColorEffect.CurrentTechnique = SolidColorEffect.Techniques["SolidColor"];
SolidColorEffect.Parameters["color"].SetValue(AmbientLight.ToVector4());
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, transformMatrix: spriteBatchTransform, effect: SolidColorEffect);
Submarine.DrawDamageable(spriteBatch, null);
spriteBatch.End();
graphics.BlendState = BlendState.Additive;
//draw the focused item and character to highlight them,
//and light sprites (done before drawing the actual light volumes so we can make characters obstruct the highlights and sprites)
//---------------------------------------------------------------------------------------------------
@@ -327,33 +275,37 @@ namespace Barotrauma.Lights
//draw characters to obstruct the highlighted items/characters and light sprites
//---------------------------------------------------------------------------------------------------
SolidColorEffect.CurrentTechnique = SolidColorEffect.Techniques["SolidColor"];
SolidColorEffect.Parameters["color"].SetValue(Color.Black.ToVector4());
SolidColorEffect.CurrentTechnique = SolidColorEffect.Techniques["SolidVertexColor"];
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, effect: SolidColorEffect, transformMatrix: spriteBatchTransform);
foreach (Character character in Character.CharacterList)
{
if (character.CurrentHull == null || !character.Enabled) continue;
if (Character.Controlled?.FocusedCharacter == character) continue;
if (character.CurrentHull == null || !character.Enabled) { continue; }
if (Character.Controlled?.FocusedCharacter == character) { continue; }
Color lightColor = character.CurrentHull.AmbientLight == Color.TransparentBlack ?
Color.Black :
character.CurrentHull.AmbientLight.Multiply(character.CurrentHull.AmbientLight.A / 255.0f).Opaque();
foreach (Limb limb in character.AnimController.Limbs)
{
if (limb.DeformSprite != null) continue;
limb.Draw(spriteBatch, cam, Color.Black);
if (limb.DeformSprite != null) { continue; }
limb.Draw(spriteBatch, cam, lightColor);
}
}
spriteBatch.End();
DeformableSprite.Effect.CurrentTechnique = DeformableSprite.Effect.Techniques["DeformShaderSolidColor"];
DeformableSprite.Effect.Parameters["solidColor"].SetValue(Color.Black.ToVector4());
DeformableSprite.Effect.CurrentTechnique = DeformableSprite.Effect.Techniques["DeformShaderSolidVertexColor"];
DeformableSprite.Effect.CurrentTechnique.Passes[0].Apply();
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, transformMatrix: spriteBatchTransform);
foreach (Character character in Character.CharacterList)
{
if (character.CurrentHull == null || !character.Enabled) continue;
if (Character.Controlled?.FocusedCharacter == character) continue;
if (character.CurrentHull == null || !character.Enabled) { continue; }
if (Character.Controlled?.FocusedCharacter == character) { continue; }
Color lightColor = character.CurrentHull.AmbientLight == Color.TransparentBlack ?
Color.Black :
character.CurrentHull.AmbientLight.Multiply(character.CurrentHull.AmbientLight.A / 255.0f).Opaque();
foreach (Limb limb in character.AnimController.Limbs)
{
if (limb.DeformSprite == null) continue;
limb.Draw(spriteBatch, cam, Color.Black);
if (limb.DeformSprite == null) { continue; }
limb.Draw(spriteBatch, cam, lightColor);
}
}
spriteBatch.End();
@@ -364,8 +316,6 @@ namespace Barotrauma.Lights
//---------------------------------------------------------------------------------------------------
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Additive, transformMatrix: spriteBatchTransform);
GUI.DrawRectangle(spriteBatch, new Rectangle(cam.WorldView.X, -cam.WorldView.Y, cam.WorldView.Width, cam.WorldView.Height), AmbientLight, isFilled: true);
spriteBatch.Draw(LimbLightMap, new Rectangle(cam.WorldView.X, -cam.WorldView.Y, cam.WorldView.Width, cam.WorldView.Height), Color.White);
foreach (ElectricalDischarger discharger in ElectricalDischarger.List)
@@ -382,24 +332,7 @@ namespace Barotrauma.Lights
lightEffect.World = transform;
GameMain.ParticleManager.Draw(spriteBatch, false, null, Particles.ParticleBlendState.Additive);
if (UseHullSpecificAmbientLight)
{
if (visibleHulls == null)
{
visibleHulls = GetVisibleHulls(cam);
}
foreach (Hull hull in smoothedHullAmbientLights.Keys)
{
if (smoothedHullAmbientLights[hull].A < 0.01f) continue;
if (!visibleHulls.TryGetValue(hull, out Rectangle drawRect)) continue;
GUI.DrawRectangle(spriteBatch,
new Vector2(drawRect.X, -drawRect.Y),
new Vector2(hull.Rect.Width, hull.Rect.Height),
smoothedHullAmbientLights[hull], true);
}
}
if (Character.Controlled != null)
{
Vector2 haloDrawPos = Character.Controlled.DrawPosition;
@@ -601,7 +534,10 @@ namespace Barotrauma.Lights
}
}
penumbraVerts.AddRange(convexHull.PenumbraVertices);
if (convexHull.ShadowVertexCount > 0)
{
penumbraVerts.AddRange(convexHull.PenumbraVertices);
}
}
if (shadowVerts.Count > 0)
@@ -622,86 +558,6 @@ namespace Barotrauma.Lights
graphics.SetRenderTarget(null);
}
private void CalculateAmbientLights()
{
hullAmbientLights.Clear();
foreach (LightSource light in lights)
{
if (light.Color.A < 1f || light.Range < 1.0f || light.IsBackground) continue;
var newAmbientLights = AmbientLightHulls(light);
foreach (Hull hull in newAmbientLights.Keys)
{
if (hullAmbientLights.ContainsKey(hull))
{
//hull already lit by some other light source -> add the ambient lights up
hullAmbientLights[hull] = new Color(
hullAmbientLights[hull].R + newAmbientLights[hull].R,
hullAmbientLights[hull].G + newAmbientLights[hull].G,
hullAmbientLights[hull].B + newAmbientLights[hull].B,
hullAmbientLights[hull].A + newAmbientLights[hull].A);
}
else
{
hullAmbientLights.Add(hull, newAmbientLights[hull]);
}
}
}
}
/// <summary>
/// Add ambient light to the hull the lightsource is inside + all adjacent hulls connected by a gap
/// </summary>
private Dictionary<Hull, Color> AmbientLightHulls(LightSource light)
{
Dictionary<Hull, Color> hullAmbientLight = new Dictionary<Hull, Color>();
var hull = Hull.FindHull(light.WorldPosition);
if (hull == null) return hullAmbientLight;
return AmbientLightHulls(hull, hullAmbientLight, light.Color * Math.Min(light.Range / 1000.0f, 1.0f));
}
/// <summary>
/// A flood fill algorithm that adds ambient light to all hulls the starting hull is connected to
/// </summary>
private Dictionary<Hull, Color> AmbientLightHulls(Hull hull, Dictionary<Hull, Color> hullAmbientLight, Color currColor)
{
if (hullAmbientLight.ContainsKey(hull))
{
if (hullAmbientLight[hull].A > currColor.A)
return hullAmbientLight;
else
hullAmbientLight[hull] = currColor;
}
else
{
hullAmbientLight.Add(hull, currColor);
}
Color nextHullLight = currColor * AmbientLightFalloff;
//light getting too dark to notice -> no need to spread further
if (nextHullLight.A < 20) return hullAmbientLight;
//use hashset to make sure that each hull is only included once
HashSet<Hull> hulls = new HashSet<Hull>();
foreach (Gap g in hull.ConnectedGaps)
{
if (!g.IsRoomToRoom || !g.PassAmbientLight || g.Open < 0.5f) continue;
hulls.Add((g.linkedTo[0] == hull ? g.linkedTo[1] : g.linkedTo[0]) as Hull);
}
foreach (Hull h in hulls)
{
hullAmbientLight = AmbientLightHulls(h, hullAmbientLight, nextHullLight);
}
return hullAmbientLight;
}
public void ClearLights()
{
lights.Clear();

View File

@@ -16,7 +16,7 @@ namespace Barotrauma.Lights
public Dictionary<string, SerializableProperty> SerializableProperties { get; private set; } = new Dictionary<string, SerializableProperty>();
[Serialize("1.0,1.0,1.0,1.0", true), Editable]
[Serialize("1.0,1.0,1.0,1.0", true, alwaysUseInstanceValues: true), Editable]
public Color Color
{
get;
@@ -25,7 +25,7 @@ namespace Barotrauma.Lights
private float range;
[Serialize(100.0f, true), Editable(MinValueFloat = 0.0f, MaxValueFloat = 2048.0f)]
[Serialize(100.0f, true, alwaysUseInstanceValues: true), Editable(MinValueFloat = 0.0f, MaxValueFloat = 2048.0f)]
public float Range
{
get { return range; }
@@ -331,7 +331,7 @@ namespace Barotrauma.Lights
if (lightSourceParams.DeformableLightSpriteElement != null)
{
DeformableLightSprite = new DeformableSprite(lightSourceParams.DeformableLightSpriteElement);
DeformableLightSprite = new DeformableSprite(lightSourceParams.DeformableLightSpriteElement, invert: true);
}
}
@@ -342,7 +342,7 @@ namespace Barotrauma.Lights
lightSourceParams.Persistent = true;
if (lightSourceParams.DeformableLightSpriteElement != null)
{
DeformableLightSprite = new DeformableSprite(lightSourceParams.DeformableLightSpriteElement);
DeformableLightSprite = new DeformableSprite(lightSourceParams.DeformableLightSpriteElement, invert: true);
}
}
@@ -952,23 +952,44 @@ namespace Barotrauma.Lights
{
Vector2 origin = DeformableLightSprite.Origin;
Vector2 drawPos = position;
if (ParentSub != null) drawPos += ParentSub.DrawPosition;
if (ParentSub != null)
{
drawPos += ParentSub.DrawPosition;
}
if (LightSpriteEffect == SpriteEffects.FlipHorizontally)
{
origin.X = DeformableLightSprite.Sprite.SourceRect.Width - origin.X;
}
if (LightSpriteEffect == SpriteEffects.FlipVertically)
{
origin.Y = DeformableLightSprite.Sprite.SourceRect.Height - origin.Y;
}
DeformableLightSprite.Draw(
cam, new Vector3(drawPos, 0.0f),
origin, -Rotation, SpriteScale,
new Color(Color, lightSourceParams.OverrideLightSpriteAlpha ?? Color.A / 255.0f),
LightSpriteEffect == SpriteEffects.FlipHorizontally);
LightSpriteEffect == SpriteEffects.FlipVertically);
}
if (LightSprite != null)
{
Vector2 origin = LightSprite.Origin;
if (LightSpriteEffect == SpriteEffects.FlipHorizontally) origin.X = LightSprite.SourceRect.Width - origin.X;
if (LightSpriteEffect == SpriteEffects.FlipVertically) origin.Y = LightSprite.SourceRect.Height - origin.Y;
if (LightSpriteEffect == SpriteEffects.FlipHorizontally)
{
origin.X = LightSprite.SourceRect.Width - origin.X;
}
if (LightSpriteEffect == SpriteEffects.FlipVertically)
{
origin.Y = LightSprite.SourceRect.Height - origin.Y;
}
Vector2 drawPos = position;
if (ParentSub != null) drawPos += ParentSub.DrawPosition;
if (ParentSub != null)
{
drawPos += ParentSub.DrawPosition;
}
drawPos.Y = -drawPos.Y;
LightSprite.Draw(

View File

@@ -2,7 +2,7 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System.IO;
using Barotrauma.IO;
using System.Linq;
using System.Xml.Linq;

View File

@@ -151,7 +151,8 @@ namespace Barotrauma
{
selectedList.ForEach(e =>
{
e.Remove();
//orphaned wires may already have been removed
if (!e.Removed) { e.Remove(); }
});
selectedList.Clear();
}

View File

@@ -24,6 +24,10 @@ namespace Barotrauma
{
get
{
if (!GameMain.SubEditorScreen.ShowThalamus && prefab.Category.HasFlag(MapEntityCategory.Thalamus))
{
return false;
}
return HasBody ? ShowWalls : ShowStructures;
}
}

View File

@@ -6,7 +6,7 @@ using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
using System.IO;
using Barotrauma.IO;
using System.Linq;
using System.Xml.Linq;
using Barotrauma.Items.Components;
@@ -31,6 +31,7 @@ namespace Barotrauma
Stream = sound.Stream;
Range = element.GetAttributeFloat("range", 1000.0f);
Volume = element.GetAttributeFloat("volume", 1.0f);
sound.IgnoreMuffling = element.GetAttributeBool("dontmuffle", false);
}
}
@@ -87,7 +88,7 @@ namespace Barotrauma
existingSound = GameMain.SoundManager.LoadSound(filename, stream);
if (existingSound == null) { return null; }
}
catch (FileNotFoundException e)
catch (System.IO.FileNotFoundException e)
{
string errorMsg = "Failed to load sound file \"" + filename + "\".";
DebugConsole.ThrowError(errorMsg, e);

View File

@@ -1,7 +1,7 @@
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.IO;
using Barotrauma.IO;
using System.Linq;
using System.Text;
using System.Xml.Linq;
@@ -19,9 +19,9 @@ namespace Barotrauma
{
try
{
using (MemoryStream mem = new MemoryStream(Convert.FromBase64String(previewImageData)))
using (System.IO.MemoryStream mem = new System.IO.MemoryStream(Convert.FromBase64String(previewImageData)))
{
var texture = TextureLoader.FromStream(mem, path: FilePath);
var texture = TextureLoader.FromStream(mem, path: FilePath, compress: false);
if (texture == null) { throw new Exception("PreviewImage texture returned null"); }
PreviewImage = new Sprite(texture, null, null);
}

View File

@@ -9,7 +9,7 @@ namespace Barotrauma
{
partial class WayPoint : MapEntity
{
private static Dictionary<SpawnType, Sprite> iconSprites;
private static Dictionary<string, Sprite> iconSprites;
private const int WaypointSize = 12, SpawnPointSize = 32;
public override bool IsVisible(Rectangle worldView)
@@ -56,10 +56,18 @@ namespace Barotrauma
Color.White);
}
Sprite sprite = iconSprites[SpawnType];
Sprite sprite = iconSprites[SpawnType.ToString()];
if (spawnType == SpawnType.Human && AssignedJob?.Icon != null)
{
sprite = iconSprites[SpawnType.Path];
sprite = iconSprites["Path"];
}
else if (ConnectedDoor != null)
{
sprite = iconSprites["Door"];
}
else if (Ladders != null)
{
sprite = iconSprites["Ladder"];
}
sprite.Draw(spriteBatch, drawPos, clr, scale: iconSize / (float)sprite.SourceRect.Width, depth: 0.001f);
sprite.RelativeOrigin = Vector2.One * 0.5f;

View File

@@ -1,5 +1,5 @@
using System;
using System.IO;
using Barotrauma.IO;
using System.Collections.Generic;
using System.Text;
using System.Threading;

View File

@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using Barotrauma.IO;
using System.IO.Pipes;
using System.Text;
using System.Threading;
@@ -18,8 +18,8 @@ namespace Barotrauma.Networking
public static void Start(ProcessStartInfo processInfo)
{
writePipe = new AnonymousPipeServerStream(PipeDirection.Out, HandleInheritability.Inheritable);
readPipe = new AnonymousPipeServerStream(PipeDirection.In, HandleInheritability.Inheritable);
writePipe = new AnonymousPipeServerStream(PipeDirection.Out, System.IO.HandleInheritability.Inheritable);
readPipe = new AnonymousPipeServerStream(PipeDirection.In, System.IO.HandleInheritability.Inheritable);
writeStream = writePipe; readStream = readPipe;
@@ -38,6 +38,13 @@ namespace Barotrauma.Networking
localHandlesDisposed = true;
}
public static void ClosePipes()
{
writePipe?.Close();
readPipe?.Close();
shutDown = true;
}
public static void ShutDown()
{
Process?.Kill(); Process = null;

View File

@@ -1,7 +1,7 @@
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.IO;
using Barotrauma.IO;
using System.Linq;
using System.Threading;
using System.Xml;
@@ -100,7 +100,7 @@ namespace Barotrauma.Networking
WriteStream = null;
}
WriteStream = new FileStream(FilePath, FileMode.Create, FileAccess.Write, FileShare.None);
WriteStream = File.Open(FilePath, System.IO.FileMode.Create, System.IO.FileAccess.Write);
TimeStarted = Environment.TickCount;
}
@@ -259,7 +259,7 @@ namespace Barotrauma.Networking
{
newTransfer.OpenStream();
}
catch (IOException e)
catch (System.IO.IOException e)
{
if (i < maxRetries)
{
@@ -422,7 +422,7 @@ namespace Barotrauma.Networking
}
if (string.IsNullOrEmpty(fileName) ||
fileName.IndexOfAny(Path.GetInvalidFileNameChars()) > -1)
fileName.IndexOfAny(Path.GetInvalidFileNameChars().ToArray()) > -1)
{
errorMessage = "Illegal characters in file name ''" + fileName + "''";
return false;
@@ -455,7 +455,7 @@ namespace Barotrauma.Networking
switch (fileTransfer.FileType)
{
case FileTransferType.Submarine:
Stream stream;
System.IO.Stream stream;
try
{
stream = SaveUtil.DecompressFiletoStream(fileTransfer.FilePath);

View File

@@ -3,7 +3,7 @@ using Barotrauma.Steam;
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.IO;
using Barotrauma.IO;
using System.IO.Compression;
using System.Linq;
using System.Text;
@@ -52,7 +52,7 @@ namespace Barotrauma.Networking
public GUITickBox EndVoteTickBox;
private GUIComponent buttonContainer;
private NetStats netStats;
public readonly NetStats NetStats;
protected GUITickBox cameraFollowsSub;
@@ -169,9 +169,9 @@ namespace Barotrauma.Networking
allowReconnect = true;
netStats = new NetStats();
NetStats = new NetStats();
inGameHUD = new GUIFrame(new RectTransform(Vector2.One, GUI.Canvas), style: null)
inGameHUD = new GUIFrame(new RectTransform(GUI.Canvas.RelativeSize, GUI.Canvas), style: null)
{
CanBeFocused = false
};
@@ -569,14 +569,7 @@ namespace Barotrauma.Networking
}
}
/*TODO: reimplement
if (ShowNetStats && client?.ServerConnection != null)
{
netStats.AddValue(NetStats.NetStatType.ReceivedBytes, client.ServerConnection.Statistics.ReceivedBytes);
netStats.AddValue(NetStats.NetStatType.SentBytes, client.ServerConnection.Statistics.SentBytes);
netStats.AddValue(NetStats.NetStatType.ResentMessages, client.ServerConnection.Statistics.ResentMessages);
netStats.Update(deltaTime);
}*/
NetStats.Update(deltaTime);
UpdateHUD(deltaTime);
@@ -781,7 +774,7 @@ namespace Barotrauma.Networking
if (readyToStart && !CoroutineManager.IsCoroutineRunning("WaitForStartRound"))
{
CoroutineManager.StartCoroutine(GameMain.NetLobbyScreen.WaitForStartRound(startButton: null, allowCancel: false), "WaitForStartRound");
CoroutineManager.StartCoroutine(GameMain.NetLobbyScreen.WaitForStartRound(startButton: null), "WaitForStartRound");
}
break;
case ServerPacketHeader.STARTGAME:
@@ -1455,6 +1448,15 @@ namespace Barotrauma.Networking
var teamID = i == 0 ? Character.TeamType.Team1 : Character.TeamType.Team2;
Submarine.MainSubs[i].TeamID = teamID;
foreach (Item item in Item.ItemList)
{
if (item.Submarine == null) { continue; }
if (item.Submarine != Submarine.MainSubs[i] && !Submarine.MainSubs[i].DockedTo.Contains(item.Submarine)) { continue; }
foreach (WifiComponent wifiComponent in item.GetComponents<WifiComponent>())
{
wifiComponent.TeamID = Submarine.MainSubs[i].TeamID;
}
}
foreach (Submarine sub in Submarine.MainSubs[i].DockedTo)
{
sub.TeamID = teamID;
@@ -1891,8 +1893,8 @@ namespace Barotrauma.Networking
DebugConsole.ThrowError("Writing object data to \"crashreport_object.bin\", please send this file to us at http://github.com/Regalis11/Barotrauma/issues");
using (FileStream fl = File.Open("crashreport_object.bin", FileMode.Create))
using (BinaryWriter sw = new BinaryWriter(fl))
using (FileStream fl = File.Open("crashreport_object.bin", System.IO.FileMode.Create))
using (System.IO.BinaryWriter sw = new System.IO.BinaryWriter(fl))
{
sw.Write(inc.Buffer, (int)(prevBytePos - prevByteLength), (int)(prevByteLength));
}
@@ -2759,15 +2761,15 @@ namespace Barotrauma.Networking
if (!ShowNetStats) return;
netStats.Draw(spriteBatch, new Rectangle(300, 10, 300, 150));
NetStats.Draw(spriteBatch, new Rectangle(300, 10, 300, 150));
/* TODO: reimplement
int width = 200, height = 300;
int x = GameMain.GraphicsWidth - width, y = (int)(GameMain.GraphicsHeight * 0.3f);
GUI.DrawRectangle(spriteBatch, new Rectangle(x, y, width, height), Color.Black * 0.7f, true);
GUI.Font.DrawString(spriteBatch, "Network statistics:", new Vector2(x + 10, y + 10), Color.White);
/* TODO: reimplement
if (client.ServerConnection != null)
{
GUI.Font.DrawString(spriteBatch, "Ping: " + (int)(client.ServerConnection.AverageRoundtripTime * 1000.0f) + " ms", new Vector2(x + 10, y + 25), Color.White);

View File

@@ -14,10 +14,10 @@ namespace Barotrauma.Networking
ResentMessages = 2
}
private Graph[] graphs;
private readonly Graph[] graphs;
private float[] totalValue;
private float[] lastValue;
private readonly float[] totalValue;
private readonly float[] lastValue;
const float UpdateInterval = 0.1f;
float updateTimer;
@@ -37,9 +37,7 @@ namespace Barotrauma.Networking
public void AddValue(NetStatType statType, float value)
{
float valueChange = value - lastValue[(int)statType];
totalValue[(int)statType] += valueChange;
lastValue[(int)statType] = value;
}
@@ -51,7 +49,6 @@ namespace Barotrauma.Networking
for (int i = 0; i < 3; i++)
{
graphs[i].Update(totalValue[i] / UpdateInterval);
totalValue[i] = 0.0f;
}
@@ -64,23 +61,22 @@ namespace Barotrauma.Networking
GUI.DrawRectangle(spriteBatch, rect, Color.Black * 0.4f, true);
graphs[(int)NetStatType.ReceivedBytes].Draw(spriteBatch, rect, null, 0.0f, Color.Cyan);
graphs[(int)NetStatType.SentBytes].Draw(spriteBatch, rect, null, 0.0f, GUI.Style.Orange);
graphs[(int)NetStatType.ResentMessages].Draw(spriteBatch, rect, null, 0.0f, GUI.Style.Red);
if (graphs[(int)NetStatType.ResentMessages].Average() > 0)
{
graphs[(int)NetStatType.ResentMessages].Draw(spriteBatch, rect, null, 0.0f, GUI.Style.Red);
GUI.SmallFont.DrawString(spriteBatch, "Peak resent: " + graphs[(int)NetStatType.ResentMessages].LargestValue() + " messages/s",
new Vector2(rect.Right + 10, rect.Y + 50), GUI.Style.Red);
}
GUI.SmallFont.DrawString(spriteBatch,
"Peak received: " + MathUtils.GetBytesReadable((int)graphs[(int)NetStatType.ReceivedBytes].LargestValue()) + "/s " +
"Avg received: " + MathUtils.GetBytesReadable((int)graphs[(int)NetStatType.ReceivedBytes].Average()) + "/s",
new Vector2(rect.Right + 10, rect.Y + 10), Color.Cyan);
GUI.SmallFont.DrawString(spriteBatch, "Peak sent: " + MathUtils.GetBytesReadable((int)graphs[(int)NetStatType.SentBytes].LargestValue()) + "/s " +
"Avg sent: " + MathUtils.GetBytesReadable((int)graphs[(int)NetStatType.SentBytes].Average()) + "/s",
new Vector2(rect.Right + 10, rect.Y + 30), GUI.Style.Orange);
GUI.SmallFont.DrawString(spriteBatch, "Peak resent: " + graphs[(int)NetStatType.ResentMessages].LargestValue() + " messages/s",
new Vector2(rect.Right + 10, rect.Y + 50), GUI.Style.Red);
#if DEBUG
/*int y = 10;

View File

@@ -97,6 +97,9 @@ namespace Barotrauma.Networking
incomingLidgrenMessages.Clear();
netClient.ReadMessages(incomingLidgrenMessages);
GameMain.Client?.NetStats?.AddValue(NetStats.NetStatType.ReceivedBytes, netClient.Statistics.ReceivedBytes);
GameMain.Client?.NetStats?.AddValue(NetStats.NetStatType.SentBytes, netClient.Statistics.SentBytes);
foreach (NetIncomingMessage inc in incomingLidgrenMessages)
{
if (inc.SenderConnection != (ServerConnection as LidgrenConnection).NetConnection) { continue; }

View File

@@ -18,6 +18,8 @@ namespace Barotrauma.Networking
private double timeout;
private double heartbeatTimer;
private long sentBytes, receivedBytes;
private List<IReadMessage> incomingInitializationMessages;
private List<IReadMessage> incomingDataMessages;
@@ -63,6 +65,7 @@ namespace Barotrauma.Networking
outMsg.Write((byte)ConnectionInitialization.ConnectionStarted);
Steamworks.SteamNetworking.SendP2PPacket(hostSteamId, outMsg.Buffer, outMsg.LengthBytes, 0, Steamworks.P2PSend.Reliable);
sentBytes += outMsg.LengthBytes;
initializationStep = ConnectionInitialization.SteamTicketAndVersion;
@@ -99,11 +102,11 @@ namespace Barotrauma.Networking
if (isConnectionInitializationStep)
{
ulong low = Lidgren.Network.NetBitWriter.ReadUInt32(data, 32, 8);
ulong high = Lidgren.Network.NetBitWriter.ReadUInt32(data, 32, 8+32);
ulong high = Lidgren.Network.NetBitWriter.ReadUInt32(data, 32, 8 + 32);
ulong lobbyId = low + (high << 32);
Steam.SteamManager.JoinLobby(lobbyId, false);
IReadMessage inc = new ReadOnlyMessage(data, false, 1+8, dataLength - 9, ServerConnection);
IReadMessage inc = new ReadOnlyMessage(data, false, 1 + 8, dataLength - 9, ServerConnection);
if (initializationStep != ConnectionInitialization.Success)
{
incomingInitializationMessages.Add(inc);
@@ -137,16 +140,20 @@ namespace Barotrauma.Networking
timeout -= deltaTime;
heartbeatTimer -= deltaTime;
for (int i=0;i<100;i++)
for (int i = 0; i < 100; i++)
{
if (!Steamworks.SteamNetworking.IsP2PPacketAvailable()) { break; }
var packet = Steamworks.SteamNetworking.ReadP2PPacket();
if (packet.HasValue)
{
OnP2PData(packet?.SteamId ?? 0, packet?.Data, packet?.Data.Length ?? 0, 0);
receivedBytes += packet?.Data.Length ?? 0;
}
}
GameMain.Client?.NetStats?.AddValue(NetStats.NetStatType.ReceivedBytes, receivedBytes);
GameMain.Client?.NetStats?.AddValue(NetStats.NetStatType.SentBytes, sentBytes);
if (heartbeatTimer < 0.0)
{
IWriteMessage outMsg = new WriteOnlyMessage();
@@ -154,6 +161,7 @@ namespace Barotrauma.Networking
outMsg.Write((byte)PacketHeader.IsHeartbeatMessage);
Steamworks.SteamNetworking.SendP2PPacket(hostSteamId, outMsg.Buffer, outMsg.LengthBytes, 0, Steamworks.P2PSend.Unreliable);
sentBytes += outMsg.LengthBytes;
heartbeatTimer = 5.0;
}
@@ -227,6 +235,7 @@ namespace Barotrauma.Networking
heartbeatTimer = 5.0;
Steamworks.SteamNetworking.SendP2PPacket(hostSteamId, outMsg.Buffer, outMsg.LengthBytes, 0, Steamworks.P2PSend.Reliable);
sentBytes += outMsg.LengthBytes;
break;
case ConnectionInitialization.ContentPackageOrder:
if (initializationStep == ConnectionInitialization.SteamTicketAndVersion ||
@@ -254,7 +263,7 @@ namespace Barotrauma.Networking
}
Steamworks.SteamNetworking.SendP2PPacket(hostSteamId, outMsg.Buffer, outMsg.LengthBytes, 0, Steamworks.P2PSend.Reliable);
sentBytes += outMsg.LengthBytes;
break;
case ConnectionInitialization.Password:
if (initializationStep == ConnectionInitialization.SteamTicketAndVersion) { initializationStep = ConnectionInitialization.Password; }
@@ -334,6 +343,7 @@ namespace Barotrauma.Networking
private void Send(byte[] buf, int length, Steamworks.P2PSend sendType)
{
bool successSend = Steamworks.SteamNetworking.SendP2PPacket(hostSteamId, buf, length + 4, 0, sendType);
sentBytes += length + 4;
if (!successSend)
{
if (sendType != Steamworks.P2PSend.Reliable)
@@ -341,6 +351,7 @@ namespace Barotrauma.Networking
DebugConsole.Log("WARNING: message couldn't be sent unreliably, forcing reliable send (" + length.ToString() + " bytes)");
sendType = Steamworks.P2PSend.Reliable;
successSend = Steamworks.SteamNetworking.SendP2PPacket(hostSteamId, buf, length + 4, 0, sendType);
sentBytes += length + 4;
}
if (!successSend)
{
@@ -364,6 +375,7 @@ namespace Barotrauma.Networking
heartbeatTimer = 5.0;
Steamworks.SteamNetworking.SendP2PPacket(hostSteamId, outMsg.Buffer, outMsg.LengthBytes, 0, Steamworks.P2PSend.Reliable);
sentBytes += outMsg.LengthBytes;
}
public override void Close(string msg = null)
@@ -380,6 +392,7 @@ namespace Barotrauma.Networking
outMsg.Write(msg ?? "Disconnected");
Steamworks.SteamNetworking.SendP2PPacket(hostSteamId, outMsg.Buffer, outMsg.LengthBytes, 0, Steamworks.P2PSend.Reliable);
sentBytes += outMsg.LengthBytes;
Thread.Sleep(100);

View File

@@ -13,7 +13,9 @@ namespace Barotrauma.Networking
private bool isActive;
private ConnectionInitialization initializationStep;
private UInt64 selfSteamID;
private readonly UInt64 selfSteamID;
private long sentBytes, receivedBytes;
class RemotePeer
{
@@ -204,22 +206,24 @@ namespace Barotrauma.Networking
}
}
for (int i=0;i<100;i++)
for (int i = 0; i < 100; i++)
{
if (!Steamworks.SteamNetworking.IsP2PPacketAvailable()) { break; }
var packet = Steamworks.SteamNetworking.ReadP2PPacket();
if (packet.HasValue)
{
OnP2PData(packet?.SteamId ?? 0, packet?.Data, packet?.Data.Length ?? 0, 0);
receivedBytes += packet?.Data.Length ?? 0;
}
}
GameMain.Client?.NetStats?.AddValue(NetStats.NetStatType.ReceivedBytes, receivedBytes);
GameMain.Client?.NetStats?.AddValue(NetStats.NetStatType.SentBytes, sentBytes);
while (ChildServerRelay.Read(out byte[] incBuf))
{
ChildServerRelay.DisposeLocalHandles();
IReadMessage inc = new ReadOnlyMessage(incBuf, false, 0, incBuf.Length, ServerConnection);
HandleDataMessage(inc);
}
}
@@ -295,6 +299,7 @@ namespace Barotrauma.Networking
}
bool successSend = Steamworks.SteamNetworking.SendP2PPacket(recipientSteamId, p2pData, p2pData.Length, 0, sendType);
sentBytes += p2pData.Length;
if (!successSend)
{
@@ -303,6 +308,7 @@ namespace Barotrauma.Networking
DebugConsole.Log("WARNING: message couldn't be sent unreliably, forcing reliable send (" + p2pData.Length.ToString() + " bytes)");
sendType = Steamworks.P2PSend.Reliable;
successSend = Steamworks.SteamNetworking.SendP2PPacket(recipientSteamId, p2pData, p2pData.Length, 0, sendType);
sentBytes += p2pData.Length;
}
if (!successSend)
{
@@ -336,7 +342,6 @@ namespace Barotrauma.Networking
byte[] msgToSend = (byte[])outMsg.Buffer.Clone();
Array.Resize(ref msgToSend, outMsg.LengthBytes);
ChildServerRelay.Write(msgToSend);
return;
}
else
@@ -369,6 +374,7 @@ namespace Barotrauma.Networking
outMsg.Write(msg);
Steamworks.SteamNetworking.SendP2PPacket(peer.SteamID, outMsg.Buffer, outMsg.LengthBytes, 0, Steamworks.P2PSend.Reliable);
sentBytes += outMsg.LengthBytes;
}
else
{
@@ -405,7 +411,7 @@ namespace Barotrauma.Networking
ClosePeerSession(remotePeers[i]);
}
ChildServerRelay.ShutDown();
ChildServerRelay.ClosePipes();
OnDisconnect?.Invoke();

View File

@@ -26,10 +26,13 @@ namespace Barotrauma.Networking
public void CreateLogFrame()
{
LogFrame = new GUIButton(new RectTransform(Vector2.One, GUI.Canvas), style: "GUIBackgroundBlocker")
LogFrame = new GUIButton(new RectTransform(Vector2.One, GUI.Canvas, Anchor.Center), style: null)
{
OnClicked = (btn, userdata) => { if (GUI.MouseOn == btn || GUI.MouseOn == btn.TextBlock) LogFrame = null; return true; }
};
new GUIFrame(new RectTransform(GUI.Canvas.RelativeSize, LogFrame.RectTransform, Anchor.Center), style: "GUIBackgroundBlocker");
new GUIButton(new RectTransform(Vector2.One, LogFrame.RectTransform), "", style: null).OnClicked += (btn, userData) =>
{
LogFrame = null;

View File

@@ -266,7 +266,9 @@ namespace Barotrauma.Networking
}
//background frame
settingsFrame = new GUIFrame(new RectTransform(Vector2.One, GUI.Canvas), style: null, color: Color.Black * 0.5f);
settingsFrame = new GUIFrame(new RectTransform(Vector2.One, GUI.Canvas, Anchor.Center), style: null);
new GUIFrame(new RectTransform(GUI.Canvas.RelativeSize, settingsFrame.RectTransform, Anchor.Center), style: "GUIBackgroundBlocker");
new GUIButton(new RectTransform(Vector2.One, settingsFrame.RectTransform), "", style: null).OnClicked += (btn, userData) =>
{
if (GUI.MouseOn == btn || GUI.MouseOn == btn.TextBlock) { ToggleSettingsFrame(btn, userData); }

View File

@@ -2,13 +2,12 @@
using RestSharp;
using System;
using System.Collections.Generic;
using System.IO;
using Barotrauma.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using RestSharp.Contrib;
using System.Xml.Linq;
using System.Xml;
using Color = Microsoft.Xna.Framework.Color;
using System.Runtime.InteropServices;
@@ -250,7 +249,8 @@ namespace Barotrauma.Steam
}
};
Steamworks.Data.LobbyQuery lobbyQuery = Steamworks.SteamMatchmaking.CreateLobbyQuery().FilterDistanceWorldwide();
//TODO: find a better strategy to fetch all lobbies, this is gonna take forever if we actually have 10000 lobbies
Steamworks.Data.LobbyQuery lobbyQuery = Steamworks.SteamMatchmaking.CreateLobbyQuery().FilterDistanceWorldwide().WithMaxResults(10000);
TaskPool.Add(Task.Run(async () =>
{
@@ -578,7 +578,7 @@ namespace Barotrauma.Steam
if (!isInitialized) return;
var query = new Steamworks.Ugc.Query(Steamworks.UgcType.All)
.RankedByTotalUniqueSubscriptions()
.RankedByTrend()
.WithLongDescription();
if (requireTags != null) query.WithTags(requireTags);
@@ -754,7 +754,7 @@ namespace Barotrauma.Steam
if (!CheckWorkshopItemEnabled(existingItem))
{
if (!EnableWorkShopItem(existingItem, false, out string errorMsg))
if (!EnableWorkShopItem(existingItem, out string errorMsg))
{
DebugConsole.NewMessage(errorMsg, Color.Red);
new GUIMessageBox(
@@ -881,6 +881,10 @@ namespace Barotrauma.Steam
DebugConsole.NewMessage("Published workshop item " + item?.Title + " successfully.", Microsoft.Xna.Framework.Color.LightGreen);
contentPackage.SteamWorkshopUrl = $"http://steamcommunity.com/sharedfiles/filedetails/?source=Facepunch.Steamworks&id={task.Result.FileId.Value}";
//NOTE: This sets InstallTime one hour into the future to guarantee
//that the published content package won't be autoupdated incorrectly.
//Change if it causes issues.
contentPackage.InstallTime = DateTime.UtcNow + TimeSpan.FromHours(1);
contentPackage.Save(contentPackage.Path);
SubscribeToWorkshopItem(task.Result.FileId);
@@ -892,7 +896,7 @@ namespace Barotrauma.Steam
/// <summary>
/// Enables a workshop item by moving it to the game folder.
/// </summary>
public static bool EnableWorkShopItem(Steamworks.Ugc.Item? item, bool allowFileOverwrite, out string errorMsg, bool selectContentPackage = false, bool suppressInstallNotif = false)
public static bool EnableWorkShopItem(Steamworks.Ugc.Item? item, out string errorMsg, bool selectContentPackage = false, bool suppressInstallNotif = false)
{
if (!(item?.IsInstalled ?? false))
{
@@ -916,7 +920,8 @@ namespace Barotrauma.Steam
};
string newContentPackagePath = GetWorkshopItemContentPackagePath(contentPackage);
if (ContentPackage.List.Any(cp => cp.Path.CleanUpPath() == newContentPackagePath.CleanUpPath()))
List<ContentPackage> existingPackages = ContentPackage.List.Where(cp => cp.Path.CleanUpPath() == newContentPackagePath.CleanUpPath()).ToList();
if (existingPackages.Any())
{
if (item?.Owner.Id != Steamworks.SteamClient.SteamId)
{
@@ -952,15 +957,9 @@ namespace Barotrauma.Steam
{
if (modCopiesInProgress.ContainsKey(item.Value.Id))
{
if (!modCopiesInProgress[item.Value.Id].IsCompleted &&
!modCopiesInProgress[item.Value.Id].IsFaulted &&
!modCopiesInProgress[item.Value.Id].IsCanceled)
{
errorMsg = ""; return true;
}
modCopiesInProgress.Remove(item.Value.Id);
errorMsg = ""; return true;
}
newTask = CopyWorkShopItemAsync(item, contentPackage, newContentPackagePath, metaDataFilePath, allowFileOverwrite);
newTask = CopyWorkShopItemAsync(item, contentPackage, newContentPackagePath, metaDataFilePath);
modCopiesInProgress.Add(item.Value.Id, newTask);
}
@@ -968,67 +967,85 @@ namespace Barotrauma.Steam
contentPackage,
(task, cp) =>
{
if (task.IsFaulted || task.IsCanceled)
try
{
DebugConsole.ThrowError($"Failed to copy \"{item?.Title}\"", task.Exception);
GameMain.SteamWorkshopScreen?.SetReinstallButtonStatus(item, true, GUI.Style.Red);
return;
}
if (!string.IsNullOrWhiteSpace(task.Result))
{
DebugConsole.ThrowError($"Failed to copy \"{item?.Title}\": {task.Result}");
GameMain.SteamWorkshopScreen?.SetReinstallButtonStatus(item, true, GUI.Style.Red);
return;
}
GameMain.Config.SuppressModFolderWatcher = true;
var newPackage = new ContentPackage(cp.Path, newContentPackagePath)
{
SteamWorkshopUrl = item?.Url,
InstallTime = item?.Updated > item?.Created ? item?.Updated : item?.Created
};
foreach (ContentFile contentFile in newPackage.Files)
{
contentFile.Path = CorrectContentFilePath(contentFile.Path, cp, true);
}
if (!Directory.Exists(Path.GetDirectoryName(newContentPackagePath)))
{
Directory.CreateDirectory(Path.GetDirectoryName(newContentPackagePath));
}
newPackage.Save(newContentPackagePath);
ContentPackage.List.Add(newPackage);
if (selectContentPackage)
{
if (newPackage.CorePackage)
if (task.IsFaulted || task.IsCanceled)
{
GameMain.Config.SelectCorePackage(newPackage);
DebugConsole.ThrowError($"Failed to copy \"{item?.Title}\"", task.Exception);
GameMain.SteamWorkshopScreen?.SetReinstallButtonStatus(item, true, GUI.Style.Red);
return;
}
else
if (!string.IsNullOrWhiteSpace(task.Result))
{
GameMain.Config.SelectContentPackage(newPackage);
DebugConsole.ThrowError($"Failed to copy \"{item?.Title}\": {task.Result}");
GameMain.SteamWorkshopScreen?.SetReinstallButtonStatus(item, true, GUI.Style.Red);
return;
}
GameMain.Config.SaveNewPlayerConfig();
GameMain.Config.WarnIfContentPackageSelectionDirty();
GameMain.Config.SuppressModFolderWatcher = true;
if (newPackage.Files.Any(f => f.Type == ContentType.Submarine))
var newPackage = new ContentPackage(cp.Path, newContentPackagePath)
{
SubmarineInfo.RefreshSavedSubs();
SteamWorkshopUrl = item?.Url,
InstallTime = item?.Updated > item?.Created ? item?.Updated : item?.Created
};
foreach (ContentFile contentFile in newPackage.Files)
{
contentFile.Path = CorrectContentFilePath(contentFile.Path, contentFile.Type, cp, true);
}
foreach (ContentFile file in existingPackages.SelectMany(p => p.Files))
{
string path = CorrectContentFilePath(file.Path, file.Type, cp, true).CleanUpPath();
if (newPackage.Files.Any(f => f.Path.CleanUpPath() == path)) { continue; }
newPackage.AddFile(path, file.Type);
}
if (!Directory.Exists(Path.GetDirectoryName(newContentPackagePath)))
{
Directory.CreateDirectory(Path.GetDirectoryName(newContentPackagePath));
}
newPackage.Save(newContentPackagePath);
ContentPackage.List.Add(newPackage);
if (selectContentPackage)
{
if (newPackage.CorePackage)
{
GameMain.Config.SelectCorePackage(newPackage);
}
else
{
GameMain.Config.SelectContentPackage(newPackage);
}
GameMain.Config.SaveNewPlayerConfig();
GameMain.Config.WarnIfContentPackageSelectionDirty();
if (newPackage.Files.Any(f => f.Type == ContentType.Submarine))
{
SubmarineInfo.RefreshSavedSubs();
}
}
else if (!suppressInstallNotif)
{
GameMain.MainMenuScreen?.SetEnableModsNotification(true);
}
GameMain.Config.SuppressModFolderWatcher = false;
GameMain.SteamWorkshopScreen?.SetReinstallButtonStatus(item, true, GUI.Style.Green);
}
else if (!suppressInstallNotif)
catch
{
GameMain.MainMenuScreen?.SetEnableModsNotification(true);
throw;
}
finally
{
modCopiesInProgress.Remove(item.Value.Id);
}
GameMain.Config.SuppressModFolderWatcher = false;
GameMain.SteamWorkshopScreen?.SetReinstallButtonStatus(item, true, GUI.Style.Green);
});
errorMsg = "";
@@ -1039,7 +1056,7 @@ namespace Barotrauma.Steam
/// Asynchronously copies a Workshop item into the Mods folder.
/// </summary>
/// <returns>Returns an empty string on success, otherwise returns an error message.</returns>
private async static Task<string> CopyWorkShopItemAsync(Steamworks.Ugc.Item? item, ContentPackage contentPackage, string newContentPackagePath, string metaDataFilePath, bool allowFileOverwrite)
private async static Task<string> CopyWorkShopItemAsync(Steamworks.Ugc.Item? item, ContentPackage contentPackage, string newContentPackagePath, string metaDataFilePath)
{
await Task.Yield();
@@ -1052,13 +1069,13 @@ namespace Barotrauma.Steam
Directory.CreateDirectory(targetPath);
File.WriteAllText(copyingPath, "TEMPORARY FILE");
SaveUtil.CopyFolder(item?.Directory, targetPath, copySubDirs: true, overwriteExisting: item?.Owner.Id != Steamworks.SteamClient.SteamId);
SaveUtil.CopyFolder(item?.Directory, targetPath, copySubDirs: true, overwriteExisting: false);
File.Delete(copyingPath);
return "";
}
var allPackageFiles = Directory.GetFiles(item?.Directory, "*", SearchOption.AllDirectories);
var allPackageFiles = Directory.GetFiles(item?.Directory, "*", System.IO.SearchOption.AllDirectories);
List<string> nonContentFiles = new List<string>();
foreach (string file in allPackageFiles)
{
@@ -1069,27 +1086,24 @@ namespace Barotrauma.Steam
nonContentFiles.Add(relativePath);
}
if (!allowFileOverwrite)
/*if (File.Exists(newContentPackagePath) && !CheckFileEquality(newContentPackagePath, metaDataFilePath))
{
if (File.Exists(newContentPackagePath) && !CheckFileEquality(newContentPackagePath, metaDataFilePath))
errorMsg = TextManager.GetWithVariables("WorkshopErrorOverwriteOnEnable", new string[2] { "[itemname]", "[filename]" }, new string[2] { item?.Title, newContentPackagePath });
DebugConsole.NewMessage(errorMsg, Color.Red);
return errorMsg;
}
foreach (ContentFile contentFile in contentPackage.Files)
{
string sourceFile = Path.Combine(item?.Directory, contentFile.Path);
if (File.Exists(sourceFile) && File.Exists(contentFile.Path) && !CheckFileEquality(sourceFile, contentFile.Path))
{
errorMsg = TextManager.GetWithVariables("WorkshopErrorOverwriteOnEnable", new string[2] { "[itemname]", "[filename]" }, new string[2] { item?.Title, newContentPackagePath });
errorMsg = TextManager.GetWithVariables("WorkshopErrorOverwriteOnEnable", new string[2] { "[itemname]", "[filename]" }, new string[2] { item?.Title, contentFile.Path });
DebugConsole.NewMessage(errorMsg, Color.Red);
return errorMsg;
}
foreach (ContentFile contentFile in contentPackage.Files)
{
string sourceFile = Path.Combine(item?.Directory, contentFile.Path);
if (File.Exists(sourceFile) && File.Exists(contentFile.Path) && !CheckFileEquality(sourceFile, contentFile.Path))
{
errorMsg = TextManager.GetWithVariables("WorkshopErrorOverwriteOnEnable", new string[2] { "[itemname]", "[filename]" }, new string[2] { item?.Title, contentFile.Path });
DebugConsole.NewMessage(errorMsg, Color.Red);
return errorMsg;
}
}
}
}*/
Directory.CreateDirectory(targetPath);
File.WriteAllText(copyingPath, "TEMPORARY FILE");
@@ -1107,7 +1121,7 @@ namespace Barotrauma.Steam
}
}
contentFile.Path = CorrectContentFilePath(contentFile.Path, contentPackage,
contentFile.Path = CorrectContentFilePath(contentFile.Path, contentFile.Type, contentPackage,
contentFile.Type != ContentType.Submarine);
//path not allowed -> the content file must be a reference to an external file (such as some vanilla file outside the Mods folder)
@@ -1145,16 +1159,16 @@ namespace Barotrauma.Steam
//make sure the destination directory exists
Directory.CreateDirectory(Path.GetDirectoryName(contentFile.Path));
CorrectContentFileCopy(contentPackage, sourceFile, contentFile.Path, overwrite: item?.Owner.Id != Steamworks.SteamClient.SteamId);
CorrectContentFileCopy(contentPackage, sourceFile, contentFile.Path, overwrite: false);
}
foreach (string nonContentFile in nonContentFiles)
{
string sourceFile = Path.Combine(item?.Directory, nonContentFile);
if (!File.Exists(sourceFile)) { continue; }
string destinationPath = CorrectContentFilePath(nonContentFile, contentPackage, false);
string destinationPath = CorrectContentFilePath(nonContentFile, ContentType.None, contentPackage, false);
Directory.CreateDirectory(Path.GetDirectoryName(destinationPath));
CorrectContentFileCopy(contentPackage, sourceFile, destinationPath, overwrite: item?.Owner.Id != Steamworks.SteamClient.SteamId);
CorrectContentFileCopy(contentPackage, sourceFile, destinationPath, overwrite: false);
}
File.Delete(copyingPath);
@@ -1271,7 +1285,7 @@ namespace Barotrauma.Steam
string metaDataPath = Path.Combine(item?.Directory, MetadataFileName);
if (!File.Exists(metaDataPath))
{
throw new FileNotFoundException("Metadata file for the Workshop item \"" + item?.Title + "\" not found. The file may be corrupted.");
throw new System.IO.FileNotFoundException("Metadata file for the Workshop item \"" + item?.Title + "\" not found. The file may be corrupted.");
}
ContentPackage contentPackage = new ContentPackage(metaDataPath);
@@ -1294,7 +1308,7 @@ namespace Barotrauma.Steam
{
metaDataPath = Path.Combine(item?.Directory, MetadataFileName);
}
catch (ArgumentException e)
catch (ArgumentException)
{
string errorMessage = "Metadata file for the Workshop item \"" + item?.Title +
"\" not found. Could not combine path (" + (item?.Directory ?? "directory name empty") + ").";
@@ -1354,6 +1368,8 @@ namespace Barotrauma.Steam
public static async Task<bool> AutoUpdateWorkshopItemsAsync()
{
await Task.Yield();
if (!isInitialized) { return false; }
var query = new Steamworks.Ugc.Query(Steamworks.UgcType.All)
@@ -1381,7 +1397,7 @@ namespace Barotrauma.Steam
string errorMsg;
if (!CheckWorkshopItemEnabled(item))
{
installedSuccessfully = EnableWorkShopItem(item, true, out errorMsg);
installedSuccessfully = EnableWorkShopItem(item, out errorMsg);
}
else if (!CheckWorkshopItemUpToDate(item))
{
@@ -1442,10 +1458,12 @@ namespace Barotrauma.Steam
{
while (updateNotifications.Count > 0)
{
float width = updateNotifications.Max(notif => GUI.Font.MeasureString(notif).X) * 1.25f;
int notificationsPerMsgBox = 20;
new GUIMessageBox("", string.Join('\n', updateNotifications.Take(notificationsPerMsgBox)),
relativeSize: new Microsoft.Xna.Framework.Vector2(0.5f, 0.0f),
minSize: new Microsoft.Xna.Framework.Point(600, 0));
relativeSize: new Microsoft.Xna.Framework.Vector2(0.25f, 0.0f),
minSize: new Microsoft.Xna.Framework.Point((int)width, 0));
updateNotifications.RemoveRange(0, Math.Min(notificationsPerMsgBox, updateNotifications.Count));
}
});
@@ -1465,12 +1483,12 @@ namespace Barotrauma.Steam
{
errorMsg = "";
if (!(item?.IsInstalled ?? false)) { return false; }
bool reenable = GameMain.Config.SelectedContentPackages.Any(p => !string.IsNullOrEmpty(p.SteamWorkshopUrl) && GetWorkshopItemIDFromUrl(p.SteamWorkshopUrl) == item?.Id);
if (item?.Owner.Id != Steamworks.SteamClient.SteamId)
{
if (!DisableWorkShopItem(item, false, out errorMsg)) { return false; }
}
if (!EnableWorkShopItem(item, allowFileOverwrite: false, errorMsg: out errorMsg)) { return false; }
if (!EnableWorkShopItem(item, errorMsg: out errorMsg, selectContentPackage: reenable)) { return false; }
return true;
}
@@ -1495,7 +1513,9 @@ namespace Barotrauma.Steam
attr.Name.ToString() == "characterfile") &&
attr.Value.CleanUpPath().Contains("/"))
{
attr.Value = CorrectContentFilePath(attr.Value, package, true);
ContentType type = ContentType.None;
Enum.TryParse(attr.Name.LocalName, true, out type);
attr.Value = CorrectContentFilePath(attr.Value, type, package, true);
}
}
@@ -1515,12 +1535,12 @@ namespace Barotrauma.Steam
if (doc != null)
{
CorrectXMLFilePaths(package, doc.Root);
using (MemoryStream stream = new MemoryStream())
using (System.IO.MemoryStream stream = new System.IO.MemoryStream())
{
XmlWriterSettings settings = new XmlWriterSettings();
System.Xml.XmlWriterSettings settings = new System.Xml.XmlWriterSettings();
settings.Indent = true;
settings.Encoding = new System.Text.UTF8Encoding(false);
using (var xmlWriter = XmlWriter.Create(stream, settings))
using (var xmlWriter = System.Xml.XmlWriter.Create(stream, settings))
{
doc.WriteTo(xmlWriter);
xmlWriter.Flush();
@@ -1540,15 +1560,24 @@ namespace Barotrauma.Steam
}
}
private static string CorrectContentFilePath(string contentFilePath, ContentPackage package, bool checkIfFileExists = false)
private static string CorrectContentFilePath(string contentFilePath, ContentType type, ContentPackage package, bool checkIfFileExists = false)
{
string packageName = Path.GetDirectoryName(GetWorkshopItemContentPackagePath(package));
contentFilePath = contentFilePath.CleanUpPathCrossPlatform();
if (checkIfFileExists && File.Exists(contentFilePath))
if (checkIfFileExists)
{
return contentFilePath;
bool exists = File.Exists(contentFilePath);
if (type == ContentType.Executable ||
type == ContentType.ServerExecutable)
{
exists |= File.Exists(contentFilePath + ".dll");
}
if (exists)
{
return contentFilePath;
}
}
string[] splitPath = contentFilePath.Split('/');

View File

@@ -275,14 +275,6 @@ namespace Barotrauma.Networking
}
}
public override void Write(IWriteMessage msg)
{
lock (buffers)
{
base.Write(msg);
}
}
public override void Dispose()
{
Instance = null;

View File

@@ -10,6 +10,8 @@ namespace Barotrauma.Particles
{
private ParticlePrefab prefab;
private string debugName = "Particle (uninitialized)";
public delegate void OnChangeHullHandler(Vector2 position, Hull currentHull);
public OnChangeHullHandler OnChangeHull;
@@ -92,10 +94,16 @@ namespace Barotrauma.Particles
{
get { return prefab; }
}
public override string ToString()
{
return debugName;
}
public void Init(ParticlePrefab prefab, Vector2 position, Vector2 speed, float rotation, Hull hullGuess = null, bool drawOnTop = false)
{
this.prefab = prefab;
debugName = $"Particle ({prefab.Name})";
spriteIndex = Rand.Int(prefab.Sprites.Count);

View File

@@ -89,7 +89,21 @@ namespace Barotrauma.Particles
{
public readonly string Name;
public readonly ParticlePrefab ParticlePrefab;
private string particlePrefabName;
private ParticlePrefab particlePrefab;
public ParticlePrefab ParticlePrefab
{
get
{
if (particlePrefab == null && particlePrefabName != null)
{
particlePrefab = GameMain.ParticleManager?.FindPrefab(particlePrefabName);
if (particlePrefab == null) { particlePrefabName = null; }
}
return particlePrefab;
}
}
public readonly float AngleMin, AngleMax;
@@ -114,8 +128,7 @@ namespace Barotrauma.Particles
public ParticleEmitterPrefab(XElement element)
{
Name = element.Name.ToString();
ParticlePrefab = GameMain.ParticleManager.FindPrefab(element.GetAttributeString("particle", ""));
particlePrefabName = element.GetAttributeString("particle", "");
if (element.Attribute("startrotation") == null)
{

View File

@@ -120,13 +120,13 @@ namespace Barotrauma.Particles
return CreateParticle(prefabName, position, new Vector2((float)Math.Cos(angle), (float)-Math.Sin(angle)) * speed, angle, hullGuess);
}
public Particle CreateParticle(string prefabName, Vector2 position, Vector2 velocity, float rotation=0.0f, Hull hullGuess = null)
public Particle CreateParticle(string prefabName, Vector2 position, Vector2 velocity, float rotation = 0.0f, Hull hullGuess = null)
{
ParticlePrefab prefab = FindPrefab(prefabName);
if (prefab == null)
{
DebugConsole.ThrowError("Particle prefab \"" + prefabName+"\" not found!");
DebugConsole.ThrowError("Particle prefab \"" + prefabName + "\" not found!");
return null;
}
@@ -135,7 +135,7 @@ namespace Barotrauma.Particles
public Particle CreateParticle(ParticlePrefab prefab, Vector2 position, Vector2 velocity, float rotation = 0.0f, Hull hullGuess = null, bool drawOnTop = false)
{
if (particleCount >= MaxParticles || prefab == null) return null;
if (particleCount >= MaxParticles || prefab == null || prefab.Sprites.Count == 0) { return null; }
Vector2 particleEndPos = prefab.CalculateEndPosition(position, velocity);
@@ -144,8 +144,8 @@ namespace Barotrauma.Particles
Rectangle expandedViewRect = MathUtils.ExpandRect(cam.WorldView, MaxOutOfViewDist);
if (minPos.X > expandedViewRect.Right || maxPos.X < expandedViewRect.X) return null;
if (minPos.Y > expandedViewRect.Y || maxPos.Y < expandedViewRect.Y - expandedViewRect.Height) return null;
if (minPos.X > expandedViewRect.Right || maxPos.X < expandedViewRect.X) { return null; }
if (minPos.Y > expandedViewRect.Y || maxPos.Y < expandedViewRect.Y - expandedViewRect.Height) { return null; }
if (particles[particleCount] == null) particles[particleCount] = new Particle();

View File

@@ -255,6 +255,11 @@ namespace Barotrauma.Particles
}
}
if (Sprites.Count == 0)
{
DebugConsole.ThrowError($"Particle prefab \"{Name}\" in the file \"{file}\" has no sprites defined!");
}
//if velocity change in water is not given, it defaults to the normal velocity change
if (element.Attribute("velocitychangewater") == null)
{

View File

@@ -17,7 +17,7 @@ namespace Barotrauma
get { return bodyShapeTexture; }
}
public void Draw(DeformableSprite deformSprite, Camera cam, Vector2 scale, Color color, bool mirror = false)
public void Draw(DeformableSprite deformSprite, Camera cam, Vector2 scale, Color color, bool invert = false)
{
if (!Enabled) return;
UpdateDrawPosition();
@@ -25,7 +25,7 @@ namespace Barotrauma
new Vector3(DrawPosition, MathHelper.Clamp(deformSprite.Sprite.Depth, 0, 1)),
deformSprite.Origin,
-DrawRotation,
scale, color, Dir < 0, mirror);
scale, color, Dir < 0, invert);
}
public void Draw(SpriteBatch spriteBatch, Sprite sprite, Color color, float? depth = null, float scale = 1.0f, bool mirrorX = false, bool mirrorY = false)

View File

@@ -25,6 +25,18 @@ namespace Barotrauma
public class KeyOrMouse
{
public Keys Key { get; private set; }
private string name;
public string Name
{
get
{
if (name == null) { name = GetName(); }
return name;
}
}
public MouseButton MouseButton { get; private set; }
public KeyOrMouse(Keys keyBinding)
@@ -133,6 +145,30 @@ namespace Barotrauma
hashCode = hashCode * -1521134295 + EqualityComparer<int?>.Default.GetHashCode((int)MouseButton);
return hashCode;
}
public string GetName()
{
if (PlayerInput.NumberKeys.Contains(Key))
{
return Key.ToString().Substring(1, 1);
}
if (MouseButton != MouseButton.None)
{
switch (MouseButton)
{
case MouseButton.PrimaryMouse:
return PlayerInput.MouseButtonsSwapped() ? TextManager.Get("input.rightmouse") : TextManager.Get("input.leftmouse");
case MouseButton.SecondaryMouse:
return PlayerInput.MouseButtonsSwapped() ? TextManager.Get("input.leftmouse") : TextManager.Get("input.rightmouse");
default:
return TextManager.Get("input." + MouseButton.ToString().ToLowerInvariant());
}
}
else
{
return Key.ToString();
}
}
}
public static class PlayerInput
@@ -155,6 +191,8 @@ namespace Barotrauma
static bool allowInput;
static bool wasWindowActive;
public static readonly List<Keys> NumberKeys = new List<Keys> { Keys.D0, Keys.D1, Keys.D2, Keys.D3, Keys.D4, Keys.D5, Keys.D6, Keys.D7, Keys.D8, Keys.D9 };
#if WINDOWS
[DllImport("user32.dll")]
static extern int GetSystemMetrics(int smIndex);
@@ -408,6 +446,12 @@ namespace Barotrauma
return (AllowInput && oldKeyboardState.IsKeyDown(button) && keyboardState.IsKeyUp(button));
}
public static bool InventoryKeyHit(int index)
{
if (index == -1) return false;
return AllowInput && GameMain.Config.InventoryKeyBind(index).IsHit();
}
public static bool KeyDown(Keys button)
{
return (AllowInput && keyboardState.IsKeyDown(button));
@@ -425,7 +469,11 @@ namespace Barotrauma
public static bool IsCtrlDown()
{
#if !OSX
return KeyDown(Keys.LeftControl) || KeyDown(Keys.RightControl);
#else
return KeyDown(Keys.LeftWindows) || KeyDown(Keys.RightWindows);
#endif
}
public static void Update(double deltaTime)
@@ -462,8 +510,9 @@ namespace Barotrauma
doubleClicked = false;
if (PrimaryMouseButtonClicked())
{
if (timeSinceClick < DoubleClickDelay &&
(mouseState.Position - lastClickPosition).ToVector2().Length() < MaxDoubleClickDistance)
float dist = (mouseState.Position - lastClickPosition).ToVector2().Length();
if (timeSinceClick < DoubleClickDelay && dist < MaxDoubleClickDistance)
{
doubleClicked = true;
timeSinceClick = DoubleClickDelay;
@@ -472,16 +521,15 @@ namespace Barotrauma
{
lastClickPosition = mouseState.Position;
}
timeSinceClick = 0.0;
if (!doubleClicked && dist < MaxDoubleClickDistance)
{
timeSinceClick = 0.0;
}
}
if (PrimaryMouseButtonDown())
{
if (timeSinceClick > DoubleClickDelay)
{
lastClickPosition = mouseState.Position;
}
lastClickPosition = mouseState.Position;
}
}

View File

@@ -1,7 +1,7 @@
#region Using Statements
using System;
using System.IO;
using Barotrauma.IO;
using System.Linq;
using System.Text;
using GameAnalyticsSDK.Net;
@@ -104,8 +104,6 @@ namespace Barotrauma
exeHash = new Md5Hash(stream);
}
StreamWriter sw = new StreamWriter(filePath);
StringBuilder sb = new StringBuilder();
sb.AppendLine("Barotrauma Client crash report (generated on " + DateTime.Now + ")");
sb.AppendLine("\n");
@@ -235,8 +233,7 @@ namespace Barotrauma
string crashReport = sb.ToString();
sw.WriteLine(crashReport);
sw.Close();
File.WriteAllText(filePath, crashReport);
if (GameSettings.SaveDebugConsoleLogs) DebugConsole.SaveLogs();

View File

@@ -2,7 +2,7 @@
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.IO;
using Barotrauma.IO;
using System.Linq;
using System.Xml.Linq;

View File

@@ -2,13 +2,17 @@
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using Barotrauma.Extensions;
using FarseerPhysics;
using FarseerPhysics.Dynamics;
#if DEBUG
using System.IO;
#else
using Barotrauma.IO;
#endif
namespace Barotrauma.CharacterEditor
{
@@ -278,7 +282,7 @@ namespace Barotrauma.CharacterEditor
return TextManager.Get(screenTextTag + tag);
}
#region Main methods
#region Main methods
public override void AddToGUIUpdateList()
{
rightArea.AddToGUIUpdateList();
@@ -662,9 +666,6 @@ namespace Barotrauma.CharacterEditor
}
if (!isFrozen)
{
Submarine.MainSub.SetPrevTransform(Submarine.MainSub.Position);
Submarine.MainSub.Update((float)deltaTime);
foreach (PhysicsBody body in PhysicsBody.List)
{
body.SetPrevTransform(body.SimPosition, body.Rotation);
@@ -991,9 +992,9 @@ namespace Barotrauma.CharacterEditor
}
spriteBatch.End();
}
#endregion
#endregion
#region Ragdoll Manipulation
#region Ragdoll Manipulation
private void UpdateJointCreation()
{
if (jointCreationMode == JointCreationMode.None)
@@ -1320,9 +1321,9 @@ namespace Barotrauma.CharacterEditor
}
RecreateRagdoll();
}
#endregion
#endregion
#region Endless runner
#region Endless runner
private int min;
private int max;
private void CalculateMovementLimits()
@@ -1425,9 +1426,9 @@ namespace Barotrauma.CharacterEditor
AllWalls.ForEach(w => w.SetCollisionCategory(collisionCategory));
GameMain.World.ProcessChanges();
}
#endregion
#endregion
#region Character spawning
#region Character spawning
private int characterIndex = -1;
private string currentCharacterConfig;
private string selectedJob = null;
@@ -1749,7 +1750,11 @@ namespace Barotrauma.CharacterEditor
{
Directory.CreateDirectory(mainFolder);
}
#if DEBUG
doc.Save(configFilePath);
#else
doc.SaveSafe(configFilePath);
#endif
// Add to the selected content package
contentPackage.AddFile(configFilePath, ContentType.Character);
contentPackage.Save(contentPackage.Path);
@@ -1830,9 +1835,9 @@ namespace Barotrauma.CharacterEditor
{
character.Inventory?.Items.ForEachMod(i => i?.Unequip(character));
}
#endregion
#endregion
#region GUI
#region GUI
private static Vector2 innerScale = new Vector2(0.95f, 0.95f);
private GUILayoutGroup rightArea, leftArea;
@@ -3147,9 +3152,9 @@ namespace Barotrauma.CharacterEditor
fileEditPanel.RectTransform.MinSize = new Point(0, (int)(layoutGroup.RectTransform.Children.Sum(c => c.MinSize.Y + layoutGroup.AbsoluteSpacing) * 1.2f));
}
#endregion
#endregion
#region ToggleButtons
#region ToggleButtons
private enum Direction
{
Left,
@@ -3211,9 +3216,9 @@ namespace Barotrauma.CharacterEditor
}
}
#endregion
#endregion
#region Params
#region Params
private CharacterParams CharacterParams => character.Params;
private List<AnimationParams> AnimParams => character.AnimController.AllAnimParams;
private AnimationParams CurrentAnimation => character.AnimController.CurrentAnimationParams;
@@ -3464,9 +3469,9 @@ namespace Barotrauma.CharacterEditor
}
}
}
#endregion
#endregion
#region Helpers
#region Helpers
private Vector2 ScreenToSim(float x, float y) => ScreenToSim(new Vector2(x, y));
private Vector2 ScreenToSim(Vector2 p) => ConvertUnits.ToSimUnits(Cam.ScreenToWorld(p)) + Submarine.MainSub.SimPosition;
private Vector2 SimToScreen(float x, float y) => SimToScreen(new Vector2(x, y));
@@ -3707,9 +3712,9 @@ namespace Barotrauma.CharacterEditor
SetToggle(spritesheetToggle, true);
}
}
#endregion
#endregion
#region Animation Controls
#region Animation Controls
private void DrawAnimationControls(SpriteBatch spriteBatch, float deltaTime)
{
var collider = character.AnimController.Collider;
@@ -4302,9 +4307,9 @@ namespace Barotrauma.CharacterEditor
}
}
}
#endregion
#endregion
#region Ragdoll
#region Ragdoll
private Vector2[] corners = new Vector2[4];
private Vector2[] GetLimbPhysicRect(Limb limb)
{
@@ -4626,9 +4631,9 @@ namespace Barotrauma.CharacterEditor
}
return otherLimbs;
}
#endregion
#endregion
#region Spritesheet
#region Spritesheet
private List<Texture2D> textures;
private List<Texture2D> Textures
{
@@ -5223,9 +5228,9 @@ namespace Barotrauma.CharacterEditor
CalculateSpritesheetZoom();
spriteSheetZoomBar.BarScroll = MathHelper.Lerp(0, 1, MathUtils.InverseLerp(spriteSheetMinZoom, spriteSheetMaxZoom, spriteSheetZoom));
}
#endregion
#endregion
#region Widgets as methods
#region Widgets as methods
private void DrawRadialWidget(SpriteBatch spriteBatch, Vector2 drawPos, float value, string toolTip, Color color, Action<float> onClick,
float circleRadius = 30, int widgetSize = 10, float rotationOffset = 0, bool clockWise = true, bool displayAngle = true, bool? autoFreeze = null, bool wrapAnglePi = false, bool holdPosition = false, int rounding = 1)
{
@@ -5334,9 +5339,9 @@ namespace Barotrauma.CharacterEditor
}
}
}
#endregion
#endregion
#region Widgets as classes
#region Widgets as classes
private Dictionary<string, Widget> animationWidgets = new Dictionary<string, Widget>();
private Dictionary<string, Widget> jointSelectionWidgets = new Dictionary<string, Widget>();
private Dictionary<string, Widget> limbEditWidgets = new Dictionary<string, Widget>();
@@ -5490,6 +5495,6 @@ namespace Barotrauma.CharacterEditor
return w;
}
}
#endregion
#endregion
}
}

View File

@@ -1,6 +1,6 @@
using Microsoft.Xna.Framework;
using System;
using System.IO;
using Barotrauma.IO;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;

View File

@@ -151,7 +151,10 @@ namespace Barotrauma
GameMain.ParticleManager.UpdateTransforms();
GameMain.LightManager.ObstructVision = Character.Controlled != null && Character.Controlled.ObstructVision;
GameMain.LightManager.ObstructVision =
Character.Controlled != null &&
Character.Controlled.ObstructVision &&
(Character.Controlled.ViewTarget == Character.Controlled || Character.Controlled.ViewTarget == null);
if (Character.Controlled != null)
{
@@ -261,7 +264,7 @@ namespace Barotrauma
graphics.SetRenderTarget(renderTargetFinal);
WaterRenderer.Instance.ResetBuffers();
Hull.UpdateVertices(graphics, cam, WaterRenderer.Instance);
Hull.UpdateVertices(cam, WaterRenderer.Instance);
WaterRenderer.Instance.RenderWater(spriteBatch, renderTargetWater, cam);
WaterRenderer.Instance.RenderAir(graphics, cam, renderTarget, Cam.ShaderTransform);
graphics.DepthStencilState = DepthStencilState.None;

View File

@@ -3,10 +3,14 @@ using Barotrauma.RuinGeneration;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.IO;
using System.Linq;
using System.Xml;
using System.Xml.Linq;
#if DEBUG
using System.IO;
using System.Xml;
#else
using Barotrauma.IO;
#endif
namespace Barotrauma
{
@@ -459,7 +463,7 @@ namespace Barotrauma
Submarine.Draw(spriteBatch, false);
Submarine.DrawFront(spriteBatch);
Submarine.DrawDamageable(spriteBatch, null);
GUI.DrawRectangle(spriteBatch, new Rectangle(new Point(0, -Level.Loaded.Size.Y), Level.Loaded.Size), Color.White, thickness: (int)(1.0f / cam.Zoom));
GUI.DrawRectangle(spriteBatch, new Rectangle(new Point(0, -Level.Loaded.Size.Y), Level.Loaded.Size), Color.Gray, thickness: (int)(1.0f / cam.Zoom));
spriteBatch.End();
if (lightingEnabled.Selected)
@@ -497,7 +501,7 @@ namespace Barotrauma
private void SerializeAll()
{
XmlWriterSettings settings = new XmlWriterSettings
System.Xml.XmlWriterSettings settings = new System.Xml.XmlWriterSettings
{
Indent = true,
NewLineOnAttributes = true
@@ -578,7 +582,7 @@ namespace Barotrauma
if (elementFound)
{
XmlWriterSettings settings = new XmlWriterSettings
System.Xml.XmlWriterSettings settings = new System.Xml.XmlWriterSettings
{
Indent = true,
NewLineOnAttributes = true
@@ -595,7 +599,7 @@ namespace Barotrauma
}
#region LevelObject Wizard
#region LevelObject Wizard
private class Wizard
{
private LevelObjectPrefab newPrefab;
@@ -676,8 +680,8 @@ namespace Barotrauma
}
newPrefab.Name = nameBox.Text;
XmlWriterSettings settings = new XmlWriterSettings { Indent = true };
System.Xml.XmlWriterSettings settings = new System.Xml.XmlWriterSettings { Indent = true };
foreach (ContentFile configFile in GameMain.Instance.GetFilesOfType(ContentType.LevelObjectPrefabs))
{
XDocument doc = XMLExtensions.TryLoadXml(configFile.Path);
@@ -710,6 +714,6 @@ namespace Barotrauma
}
}
#endregion
#endregion
}
}

View File

@@ -10,7 +10,7 @@ using RestSharp;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using Barotrauma.IO;
using System.Linq;
using System.Net;
using System.Threading;
@@ -409,10 +409,9 @@ namespace Barotrauma
this.game = game;
menuTabs[(int)Tab.Credits] = new GUIFrame(new RectTransform(Vector2.One, GUI.Canvas), style: null, color: Color.Black * 0.5f)
{
CanBeFocused = false
};
menuTabs[(int)Tab.Credits] = new GUIFrame(new RectTransform(Vector2.One, GUI.Canvas, Anchor.Center), style: null);
new GUIFrame(new RectTransform(GUI.Canvas.RelativeSize, menuTabs[(int)Tab.Credits].RectTransform, Anchor.Center), style: "GUIBackgroundBlocker");
var creditsContainer = new GUIFrame(new RectTransform(new Vector2(0.75f, 1.5f), menuTabs[(int)Tab.Credits].RectTransform, Anchor.CenterRight), style: "OuterGlow", color: Color.Black * 0.8f);
creditsPlayer = new CreditsPlayer(new RectTransform(Vector2.One, creditsContainer.RectTransform), "Content/Texts/Credits.xml");
@@ -1010,11 +1009,12 @@ namespace Barotrauma
GUI.Draw(Cam, spriteBatch);
#if !UNSTABLE
GUI.Font.DrawString(spriteBatch, "Barotrauma v" + GameMain.Version + " (" + AssemblyInfo.GetBuildString() + ", branch " + AssemblyInfo.GetGitBranch() + ", revision " + AssemblyInfo.GetGitRevision() + ")", new Vector2(10, GameMain.GraphicsHeight - 20), Color.White * 0.7f);
string versionString = "Barotrauma v" + GameMain.Version + " (" + AssemblyInfo.GetBuildString() + ", branch " + AssemblyInfo.GetGitBranch() + ", revision " + AssemblyInfo.GetGitRevision() + ")";
GUI.SmallFont.DrawString(spriteBatch, versionString, new Vector2(HUDLayoutSettings.Padding, GameMain.GraphicsHeight - GUI.SmallFont.MeasureString(versionString).Y - HUDLayoutSettings.Padding * 0.75f), Color.White * 0.7f);
#endif
if (selectedTab != Tab.Credits)
{
Vector2 textPos = new Vector2(GameMain.GraphicsWidth - 10, GameMain.GraphicsHeight - 10);
Vector2 textPos = new Vector2(GameMain.GraphicsWidth - HUDLayoutSettings.Padding, GameMain.GraphicsHeight - HUDLayoutSettings.Padding * 0.75f);
for (int i = legalCrap.Length - 1; i >= 0; i--)
{
Vector2 textSize = GUI.SmallFont.MeasureString(legalCrap[i]);
@@ -1069,7 +1069,7 @@ namespace Barotrauma
{
File.Copy(selectedSub.FilePath, Path.Combine(SaveUtil.TempPath, selectedSub.Name + ".sub"), true);
}
catch (IOException e)
catch (System.IO.IOException e)
{
DebugConsole.ThrowError("Copying the file \"" + selectedSub.FilePath + "\" failed. The file may have been deleted or in use by another process. Try again or select another submarine.", e);
GameAnalyticsManager.AddErrorEventOnce(

Some files were not shown because too many files have changed in this diff Show More