Unstable v0.10.600.0
This commit is contained in:
6
.gitignore
vendored
6
.gitignore
vendored
@@ -40,5 +40,9 @@ Libraries/webm_mem_playback/opus_x64_linux/
|
||||
# Win
|
||||
desktop.ini
|
||||
|
||||
#Merge script
|
||||
# Merge script
|
||||
temp.txt
|
||||
|
||||
# Private assets
|
||||
Barotrauma/BarotraumaShared/Content/*
|
||||
.github/ISSUE_TEMPLATE/release-checklist.md
|
||||
|
||||
@@ -414,7 +414,8 @@ namespace Barotrauma
|
||||
if (playSound)
|
||||
{
|
||||
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);
|
||||
float range = damageSound != null ? damageSound.Range * 2 : ConvertUnits.ToDisplayUnits(character.AnimController.Collider.GetSize().Length() * 10);
|
||||
SoundPlayer.PlayDamageSound(limbJoint.Params.BreakSound, 1.0f, limbJoint.LimbA.body.DrawPosition, range: range);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -426,10 +427,10 @@ namespace Barotrauma
|
||||
|
||||
if (Limbs == null)
|
||||
{
|
||||
DebugConsole.ThrowError("Failed to draw a ragdoll, limbs have been removed. Character: \"" + character.Name + "\", removed: " + character.Removed + "\n" + Environment.StackTrace);
|
||||
DebugConsole.ThrowError("Failed to draw a ragdoll, limbs have been removed. Character: \"" + character.Name + "\", removed: " + character.Removed + "\n" + Environment.StackTrace.CleanupStackTrace());
|
||||
GameAnalyticsManager.AddErrorEventOnce("Ragdoll.Draw:LimbsRemoved",
|
||||
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||
"Failed to draw a ragdoll, limbs have been removed. Character: \"" + character.Name + "\", removed: " + character.Removed + "\n" + Environment.StackTrace);
|
||||
"Failed to draw a ragdoll, limbs have been removed. Character: \"" + character.Name + "\", removed: " + character.Removed + "\n" + Environment.StackTrace.CleanupStackTrace());
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -559,6 +559,18 @@ namespace Barotrauma
|
||||
|
||||
partial void UpdateProjSpecific(float deltaTime, Camera cam)
|
||||
{
|
||||
if (InvisibleTimer > 0.0f)
|
||||
{
|
||||
if (Controlled == null || (Controlled.CharacterHealth.GetAffliction("psychosis")?.Strength ?? 0.0f) <= 0.0f)
|
||||
{
|
||||
InvisibleTimer = 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
InvisibleTimer -= deltaTime;
|
||||
}
|
||||
}
|
||||
|
||||
if (!enabled) { return; }
|
||||
|
||||
if (!IsDead && !IsIncapacitated)
|
||||
@@ -653,7 +665,7 @@ namespace Barotrauma
|
||||
|
||||
public void Draw(SpriteBatch spriteBatch, Camera cam)
|
||||
{
|
||||
if (!Enabled) { return; }
|
||||
if (!Enabled || InvisibleTimer > 0.0f) { return; }
|
||||
AnimController.Draw(spriteBatch, cam);
|
||||
}
|
||||
|
||||
@@ -665,7 +677,7 @@ namespace Barotrauma
|
||||
|
||||
public virtual void DrawFront(SpriteBatch spriteBatch, Camera cam)
|
||||
{
|
||||
if (!Enabled) { return; }
|
||||
if (!Enabled || InvisibleTimer > 0.0f) { return; }
|
||||
|
||||
if (GameMain.DebugDraw)
|
||||
{
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace Barotrauma
|
||||
{
|
||||
class CharacterHUD
|
||||
{
|
||||
private static Dictionary<Entity, int> orderIndicatorCount = new Dictionary<Entity, int>();
|
||||
private static Dictionary<ISpatialEntity, int> orderIndicatorCount = new Dictionary<ISpatialEntity, int>();
|
||||
const float ItemOverlayDelay = 1.0f;
|
||||
private static Item focusedItem;
|
||||
private static float focusedItemOverlayTimer;
|
||||
@@ -458,6 +458,8 @@ namespace Barotrauma
|
||||
|
||||
private static void DrawOrderIndicator(SpriteBatch spriteBatch, Camera cam, Character character, Order order, float iconAlpha = 1.0f)
|
||||
{
|
||||
if (order?.SymbolSprite == null) { return; }
|
||||
|
||||
if (order.TargetAllCharacters)
|
||||
{
|
||||
if (order.OrderGiver != character && !order.HasAppropriateJob(character))
|
||||
@@ -466,7 +468,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
Entity target = order.ConnectedController != null ? order.ConnectedController.Item : order.TargetEntity;
|
||||
ISpatialEntity target = order.ConnectedController != null ? order.ConnectedController.Item : order.TargetSpatialEntity;
|
||||
if (target == null) { return; }
|
||||
|
||||
//don't show the indicator if far away and not inside the same sub
|
||||
@@ -479,7 +481,9 @@ namespace Barotrauma
|
||||
|
||||
if (!orderIndicatorCount.ContainsKey(target)) { orderIndicatorCount.Add(target, 0); }
|
||||
|
||||
Vector2 drawPos = target.DrawPosition + Vector2.UnitX * order.SymbolSprite.size.X * 1.5f * orderIndicatorCount[target];
|
||||
Vector2 drawPos = target is Entity ? (target as Entity).DrawPosition :
|
||||
target.Submarine == null ? target.Position : target.Position + target.Submarine.DrawPosition;
|
||||
drawPos += Vector2.UnitX * order.SymbolSprite.size.X * 1.5f * orderIndicatorCount[target];
|
||||
GUI.DrawIndicator(spriteBatch, drawPos, cam, 100.0f, order.SymbolSprite, order.Color * iconAlpha);
|
||||
|
||||
orderIndicatorCount[target] = orderIndicatorCount[target] + 1;
|
||||
|
||||
@@ -154,7 +154,7 @@ namespace Barotrauma
|
||||
GUI.Style.Green,
|
||||
textPopupPos,
|
||||
Vector2.UnitY * 10.0f,
|
||||
playSound: Character.Controlled?.Info == this);
|
||||
playSound: false);
|
||||
}
|
||||
else if (prevLevel % 0.1f > 0.05f && newLevel % 0.1f < 0.05f)
|
||||
{
|
||||
@@ -163,7 +163,7 @@ namespace Barotrauma
|
||||
GUI.Style.Green,
|
||||
textPopupPos,
|
||||
Vector2.UnitY * 10.0f,
|
||||
playSound: Character.Controlled?.Info == this);
|
||||
playSound: false);
|
||||
}
|
||||
|
||||
if ((int)newLevel > (int)prevLevel)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Barotrauma.Extensions;
|
||||
using Barotrauma.Items.Components;
|
||||
using Barotrauma.Networking;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
@@ -444,14 +445,25 @@ namespace Barotrauma
|
||||
Entity targetEntity = FindEntityByID(inc.ReadUInt16());
|
||||
Character orderGiver = inc.ReadBoolean() ? FindEntityByID(inc.ReadUInt16()) as Character : null;
|
||||
int orderOptionIndex = inc.ReadByte();
|
||||
OrderTarget targetPosition = null;
|
||||
if (inc.ReadBoolean())
|
||||
{
|
||||
var x = inc.ReadSingle();
|
||||
var y = inc.ReadSingle();
|
||||
var hull = FindEntityByID(inc.ReadUInt16()) as Hull;
|
||||
targetPosition = new OrderTarget(new Vector2(x, y), hull, true);
|
||||
}
|
||||
|
||||
if (orderPrefabIndex >= 0 && orderPrefabIndex < Order.PrefabList.Count)
|
||||
{
|
||||
var orderPrefab = Order.PrefabList[orderPrefabIndex];
|
||||
if (!orderPrefab.MustSetTarget || (targetEntity != null && (targetEntity as Item).Components.Any(c => c?.GetType() == orderPrefab.ItemComponentType)))
|
||||
var component = orderPrefab.GetTargetItemComponent(targetEntity as Item);
|
||||
if (!orderPrefab.MustSetTarget || (targetEntity != null && component != null) || targetPosition != null)
|
||||
{
|
||||
character.SetOrder(
|
||||
new Order(orderPrefab, targetEntity, (targetEntity as Item)?.Components.FirstOrDefault(c => c?.GetType() == orderPrefab.ItemComponentType), orderGiver: orderGiver),
|
||||
var order = targetPosition == null ?
|
||||
new Order(orderPrefab, targetEntity, component, orderGiver: orderGiver) :
|
||||
new Order(orderPrefab, targetPosition, orderGiver: orderGiver);
|
||||
character.SetOrder(order,
|
||||
orderOptionIndex >= 0 && orderOptionIndex < orderPrefab.Options.Length ? orderPrefab.Options[orderOptionIndex] : null,
|
||||
orderGiver, speak: false);
|
||||
}
|
||||
|
||||
@@ -1,38 +1,26 @@
|
||||
using Barotrauma.Extensions;
|
||||
using Barotrauma.Items.Components;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
partial class AfflictionPsychosis : Affliction
|
||||
{
|
||||
class FakeFireSource
|
||||
{
|
||||
public Vector2 Size;
|
||||
public Vector2 Position;
|
||||
public Hull Hull;
|
||||
|
||||
public float LifeTime;
|
||||
}
|
||||
|
||||
const int MaxFakeFireSources = 10;
|
||||
const float MinFakeFireSourceInterval = 30.0f, MaxFakeFireSourceInterval = 240.0f;
|
||||
private float createFireSourceTimer;
|
||||
private readonly List<FakeFireSource> fakeFireSources = new List<FakeFireSource>();
|
||||
private readonly List<DummyFireSource> fakeFireSources = new List<DummyFireSource>();
|
||||
|
||||
enum FloodType
|
||||
public enum FloodType
|
||||
{
|
||||
None,
|
||||
Minor,
|
||||
Major,
|
||||
HideFlooding
|
||||
}
|
||||
|
||||
const float MinSoundInterval = 10.0f, MaxSoundInterval = 180.0f;
|
||||
const float MinSoundInterval = 60.0f, MaxSoundInterval = 240.0f;
|
||||
private FloodType currentFloodType;
|
||||
private float soundTimer;
|
||||
|
||||
@@ -44,12 +32,21 @@ namespace Barotrauma
|
||||
private float fakeBrokenInterval = 30.0f;
|
||||
private float fakeBrokenTimer = 0.0f;
|
||||
|
||||
private float invisibleCharacterInterval = 30.0f;
|
||||
private float invisibleCharacterTimer = 0.0f;
|
||||
|
||||
public FloodType CurrentFloodType
|
||||
{
|
||||
get { return currentFloodType; }
|
||||
}
|
||||
|
||||
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);
|
||||
UpdateInvisibleCharacters(deltaTime);
|
||||
UpdateFakeBroken(deltaTime);
|
||||
}
|
||||
|
||||
@@ -77,10 +74,14 @@ namespace Barotrauma
|
||||
{
|
||||
case FloodType.Minor:
|
||||
currentFloodState += deltaTime;
|
||||
//lerp the water surface in all hulls 50 units above the floor within 10 seconds
|
||||
//lerp the water surface in all hulls 15 units above the floor within 10 seconds
|
||||
foreach (Hull hull in Hull.hullList)
|
||||
{
|
||||
hull.DrawSurface = hull.Rect.Y - hull.Rect.Height + MathHelper.Lerp(0.0f, 50.0f, currentFloodState / 10.0f);
|
||||
for (int i = hull.FakeFireSources.Count - 1; i >= 0; i--)
|
||||
{
|
||||
hull.FakeFireSources[i].Extinguish(deltaTime, 50.0f);
|
||||
}
|
||||
hull.DrawSurface = hull.Rect.Y - hull.Rect.Height + MathHelper.Lerp(0.0f, 15.0f, currentFloodState / 10.0f);
|
||||
}
|
||||
break;
|
||||
case FloodType.Major:
|
||||
@@ -88,6 +89,10 @@ namespace Barotrauma
|
||||
//create a full flood in 10 seconds
|
||||
foreach (Hull hull in Hull.hullList)
|
||||
{
|
||||
for (int i = hull.FakeFireSources.Count - 1; i >= 0; i--)
|
||||
{
|
||||
hull.FakeFireSources[i].Extinguish(deltaTime, 200.0f);
|
||||
}
|
||||
hull.DrawSurface = hull.Rect.Y - MathHelper.Lerp(hull.Rect.Height, 0.0f, currentFloodState / 10.0f);
|
||||
}
|
||||
break;
|
||||
@@ -104,6 +109,7 @@ namespace Barotrauma
|
||||
|
||||
if (createFloodTimer < MathHelper.Lerp(MaxFloodInterval, MinFloodInterval, Strength / 100.0f))
|
||||
{
|
||||
currentFloodType = FloodType.None;
|
||||
createFloodTimer += deltaTime;
|
||||
return;
|
||||
}
|
||||
@@ -114,10 +120,12 @@ namespace Barotrauma
|
||||
if (Rand.Range(0.0f, 1.0f) < 0.5f)
|
||||
{
|
||||
currentFloodType = FloodType.HideFlooding;
|
||||
currentFloodType = FloodType.Minor;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentFloodType = Strength < 50.0f ? FloodType.Minor : FloodType.Major;
|
||||
//disabled Major flooding because it's too easy to tell it's fake
|
||||
currentFloodType = FloodType.Minor;// Strength < 50.0f ? FloodType.Minor : FloodType.Major;
|
||||
}
|
||||
currentFloodDuration = Rand.Range(20.0f, 100.0f);
|
||||
}
|
||||
@@ -127,47 +135,46 @@ namespace Barotrauma
|
||||
private void UpdateFires(Character character, float deltaTime)
|
||||
{
|
||||
createFireSourceTimer += deltaTime;
|
||||
fakeFireSources.RemoveAll(fs => fs.Removed);
|
||||
if (fakeFireSources.Count < MaxFakeFireSources &&
|
||||
character.Submarine != null &&
|
||||
createFireSourceTimer > MathHelper.Lerp(MaxFakeFireSourceInterval, MinFakeFireSourceInterval, Strength / 100.0f))
|
||||
{
|
||||
Hull fireHull = Hull.hullList.GetRandom(h => h.Submarine == character.Submarine);
|
||||
|
||||
fakeFireSources.Add(new FakeFireSource()
|
||||
if (fireHull != null)
|
||||
{
|
||||
Size = Vector2.One * 20.0f,
|
||||
Hull = fireHull,
|
||||
Position = new Vector2(Rand.Range(0.0f, fireHull.Rect.Width), 30.0f),
|
||||
LifeTime = MathHelper.Lerp(10.0f, 100.0f, Strength / 100.0f)
|
||||
});
|
||||
createFireSourceTimer = 0.0f;
|
||||
}
|
||||
|
||||
foreach (FakeFireSource fakeFireSource in fakeFireSources)
|
||||
{
|
||||
if (fakeFireSource.Hull.DrawSurface > fakeFireSource.Hull.Rect.Y - fakeFireSource.Hull.Rect.Height + fakeFireSource.Position.Y)
|
||||
{
|
||||
fakeFireSource.LifeTime -= deltaTime * 100.0f;
|
||||
var fakeFire = new DummyFireSource(Vector2.One * 500.0f, new Vector2(Rand.Range(fireHull.WorldRect.X, fireHull.WorldRect.Right), fireHull.WorldPosition.Y), fireHull, isNetworkMessage: true)
|
||||
{
|
||||
CausedByPsychosis = true,
|
||||
DamagesItems = false,
|
||||
DamagesCharacters = false
|
||||
};
|
||||
fakeFireSources.Add(fakeFire);
|
||||
createFireSourceTimer = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fakeFireSource.LifeTime -= deltaTime;
|
||||
float growAmount = deltaTime * 5.0f;
|
||||
fakeFireSource.Size.X += growAmount;
|
||||
fakeFireSource.Position.X = MathHelper.Clamp(fakeFireSource.Position.X - growAmount / 2.0f, 0.0f, fakeFireSource.Hull.Rect.Width);
|
||||
fakeFireSource.Position.Y = MathHelper.Clamp(fakeFireSource.Position.Y, 0.0f, fakeFireSource.Hull.Rect.Height);
|
||||
fakeFireSource.Size.X = Math.Min(fakeFireSource.Hull.Rect.Width - fakeFireSource.Position.X, fakeFireSource.Size.X);
|
||||
fakeFireSource.Size.Y = Math.Min(fakeFireSource.Hull.Rect.Height - fakeFireSource.Position.Y, fakeFireSource.Size.Y);
|
||||
private void UpdateInvisibleCharacters(float deltaTime)
|
||||
{
|
||||
invisibleCharacterTimer -= deltaTime;
|
||||
if (invisibleCharacterTimer > 0.0f) { return; }
|
||||
|
||||
FireSource.EmitParticles(
|
||||
fakeFireSource.Size,
|
||||
fakeFireSource.Hull.WorldRect.Location.ToVector2() + fakeFireSource.Position - Vector2.UnitY * fakeFireSource.Hull.Rect.Height,
|
||||
fakeFireSource.Hull,
|
||||
0.5f);
|
||||
foreach (Character c in Character.CharacterList)
|
||||
{
|
||||
if (c.IsDead || c == Character.Controlled) { continue; }
|
||||
if (c.WorldPosition.X < GameMain.GameScreen.Cam.WorldView.X || c.WorldPosition.X > GameMain.GameScreen.Cam.WorldView.Right) { continue; }
|
||||
if (c.WorldPosition.Y < GameMain.GameScreen.Cam.WorldView.Y - GameMain.GameScreen.Cam.WorldView.Height || c.WorldPosition.Y > GameMain.GameScreen.Cam.WorldView.Y) { continue; }
|
||||
if (Rand.Range(0.0f, 500.0f) < Strength)
|
||||
{
|
||||
c.InvisibleTimer = 60.0f;
|
||||
}
|
||||
}
|
||||
|
||||
fakeFireSources.RemoveAll(fs => fs.LifeTime <= 0.0f);
|
||||
invisibleCharacterTimer = invisibleCharacterInterval;
|
||||
}
|
||||
|
||||
|
||||
private void UpdateFakeBroken(float deltaTime)
|
||||
{
|
||||
fakeBrokenTimer -= deltaTime;
|
||||
|
||||
@@ -545,7 +545,7 @@ namespace Barotrauma
|
||||
|
||||
private void OnAttacked(Character attacker, AttackResult attackResult)
|
||||
{
|
||||
if (Math.Abs(attackResult.Damage) < 0.01f && attackResult.Afflictions.Count == 0) { return; }
|
||||
if (Math.Abs(attackResult.Damage) < 0.01f) { return; }
|
||||
DamageOverlayTimer = MathHelper.Clamp(attackResult.Damage / MaxVitality, DamageOverlayTimer, 1.0f);
|
||||
if (healthShadowDelay <= 0.0f) { healthShadowDelay = 1.0f; }
|
||||
|
||||
@@ -611,17 +611,41 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
partial void UpdateOxygenProjSpecific(float prevOxygen)
|
||||
private float timeUntilNextHeartbeatSound = 0.0f;
|
||||
private bool nextHeartbeatSoundIsSystole = true;
|
||||
private const string diastoleSoundTag = "heartbeatdiastole", systoleSoundTag = "heartbeatsystole";
|
||||
|
||||
partial void UpdateOxygenProjSpecific(float prevOxygen, float deltaTime)
|
||||
{
|
||||
if (prevOxygen > 0.0f && OxygenAmount <= 0.0f &&
|
||||
Character.Controlled == Character)
|
||||
if (prevOxygen > 0.0f && OxygenAmount <= 0.0f && Character.Controlled == Character)
|
||||
{
|
||||
SoundPlayer.PlaySound(Character.Info != null && Character.Info.Gender == Gender.Female ? "drownfemale" : "drownmale");
|
||||
}
|
||||
|
||||
if (Character == Character.Controlled && !IsUnconscious && !Character.IsDead && OxygenAmount < LowOxygenThreshold)
|
||||
{
|
||||
timeUntilNextHeartbeatSound -= deltaTime;
|
||||
if (timeUntilNextHeartbeatSound < 0.0f)
|
||||
{
|
||||
if (nextHeartbeatSoundIsSystole)
|
||||
{
|
||||
SoundPlayer.PlaySound(systoleSoundTag, 1.0f - (OxygenAmount / LowOxygenThreshold));
|
||||
timeUntilNextHeartbeatSound = MathHelper.Lerp(0.18f, 0.3f, Math.Clamp(OxygenAmount / InsufficientOxygenThreshold, 0.0f, 1.0f));
|
||||
}
|
||||
else
|
||||
{
|
||||
SoundPlayer.PlaySound(diastoleSoundTag, 1.0f - (OxygenAmount / LowOxygenThreshold));
|
||||
timeUntilNextHeartbeatSound = MathHelper.Lerp(0.3f, 0.5f, Math.Clamp(OxygenAmount / InsufficientOxygenThreshold, 0.0f, 1.0f));
|
||||
}
|
||||
nextHeartbeatSoundIsSystole = !nextHeartbeatSoundIsSystole;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
partial void UpdateBleedingProjSpecific(AfflictionBleeding affliction, Limb targetLimb, float deltaTime)
|
||||
{
|
||||
if (Character.InvisibleTimer > 0.0f) { return; }
|
||||
|
||||
bloodParticleTimer -= deltaTime * (affliction.Strength / 10.0f);
|
||||
if (bloodParticleTimer <= 0.0f)
|
||||
{
|
||||
@@ -664,7 +688,7 @@ namespace Barotrauma
|
||||
{
|
||||
forceAfflictionContainerUpdate = true;
|
||||
currentDisplayedAfflictions = GetAllAfflictions(mergeSameAfflictions: true)
|
||||
.FindAll(a => a.Strength >= a.Prefab.ShowIconThreshold && a.Prefab.Icon != null);
|
||||
.FindAll(a => a.ShouldShowIcon(Character) && a.Prefab.Icon != null);
|
||||
currentDisplayedAfflictions.Sort((a1, a2) =>
|
||||
{
|
||||
int dmgPerSecond = Math.Sign(a2.DamagePerSecond - a1.DamagePerSecond);
|
||||
@@ -1147,7 +1171,7 @@ namespace Barotrauma
|
||||
afflictionIconContainer.Content.ClearChildren();
|
||||
return;
|
||||
}
|
||||
var currentAfflictions = GetMatchingAfflictions(selectedLimb, a => a.Strength >= a.Prefab.ShowIconThreshold);
|
||||
var currentAfflictions = GetMatchingAfflictions(selectedLimb, a => a.ShouldShowIcon(Character));
|
||||
var displayedAfflictions = afflictionIconContainer.Content.Children.Select(c => c.UserData as Affliction);
|
||||
if (currentAfflictions.Any(a => !displayedAfflictions.Contains(a)) ||
|
||||
displayedAfflictions.Any(a => !currentAfflictions.Contains(a)))
|
||||
@@ -1675,9 +1699,9 @@ namespace Barotrauma
|
||||
|
||||
var tempAfflictions = GetMatchingAfflictions(limbHealth, a => true);
|
||||
|
||||
float negativeEffect = tempAfflictions.Where(a => !a.Prefab.IsBuff && a.Strength >= a.Prefab.ShowIconThreshold).Sum(a => a.Strength);
|
||||
float negativeEffect = tempAfflictions.Where(a => !a.Prefab.IsBuff && a.ShouldShowIcon(Character)).Sum(a => a.Strength);
|
||||
//float negativeMaxEffect = tempAfflictions.Where(a => !a.Prefab.IsBuff).Sum(a => a.Prefab.MaxStrength);
|
||||
float positiveEffect = tempAfflictions.Where(a => a.Prefab.IsBuff && a.Strength >= a.Prefab.ShowIconThreshold).Sum(a => a.Strength * 0.2f);
|
||||
float positiveEffect = tempAfflictions.Where(a => a.Prefab.IsBuff && a.ShouldShowIcon(Character)).Sum(a => a.Strength * 0.2f);
|
||||
//float positiveMaxEffect = tempAfflictions.Where(a => a.Prefab.IsBuff).Sum(a => a.Prefab.MaxStrength);
|
||||
|
||||
float midPoint = (float)limbEffectiveArea.Center.Y / (float)limbHealth.IndicatorSprite.Texture.Height;
|
||||
@@ -1786,11 +1810,11 @@ namespace Barotrauma
|
||||
i = 0;
|
||||
foreach (LimbHealth limbHealth in limbHealths)
|
||||
{
|
||||
IEnumerable<Affliction> thisAfflictions = limbHealth.Afflictions.Where(a => a.Strength >= a.Prefab.ShowIconThreshold);
|
||||
IEnumerable<Affliction> thisAfflictions = limbHealth.Afflictions.Where(a => a.ShouldShowIcon(Character));
|
||||
thisAfflictions = thisAfflictions.Concat(afflictions.Where(a =>
|
||||
{
|
||||
Limb indicatorLimb = Character.AnimController.GetLimb(a.Prefab.IndicatorLimb);
|
||||
return (indicatorLimb != null && indicatorLimb.HealthIndex == i && a.Strength >= a.Prefab.ShowIconThreshold);
|
||||
return indicatorLimb != null && indicatorLimb.HealthIndex == i && a.ShouldShowIcon(Character);
|
||||
}));
|
||||
|
||||
if (thisAfflictions.Count() <= 0) { i++; continue; }
|
||||
@@ -1837,12 +1861,14 @@ namespace Barotrauma
|
||||
|
||||
private void DrawLimbAfflictionIcon(SpriteBatch spriteBatch, Affliction affliction, float iconScale, ref Vector2 iconPos)
|
||||
{
|
||||
if (affliction.Strength < affliction.Prefab.ShowIconThreshold) return;
|
||||
Vector2 iconSize = (affliction.Prefab.Icon.size * iconScale);
|
||||
if (!affliction.ShouldShowIcon(Character)) { return; }
|
||||
Vector2 iconSize = affliction.Prefab.Icon.size * iconScale;
|
||||
|
||||
float showIconThreshold = Character.Controlled?.CharacterHealth == this ? affliction.Prefab.ShowIconThreshold : affliction.Prefab.ShowIconToOthersThreshold;
|
||||
|
||||
//afflictions that have a strength of less than 10 are faded out slightly
|
||||
float alpha = MathHelper.Lerp(0.3f, 1.0f,
|
||||
(affliction.Strength - affliction.Prefab.ShowIconThreshold) / Math.Min(affliction.Prefab.MaxStrength - affliction.Prefab.ShowIconThreshold, 10.0f));
|
||||
(affliction.Strength - showIconThreshold) / Math.Min(affliction.Prefab.MaxStrength - showIconThreshold, 10.0f));
|
||||
|
||||
affliction.Prefab.Icon.Draw(spriteBatch, iconPos - iconSize / 2.0f, GetAfflictionIconColor(affliction.Prefab, affliction) * alpha, 0, iconScale);
|
||||
iconPos += new Vector2(10.0f, 20.0f) * iconScale;
|
||||
|
||||
@@ -8,5 +8,12 @@
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
[Serialize("", false), Editable]
|
||||
public string DamageParticle
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -459,18 +459,16 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
float damageMultiplier = 1;
|
||||
float bleedingDamageMultiplier = 1;
|
||||
foreach (DamageModifier damageModifier in result.AppliedDamageModifiers)
|
||||
{
|
||||
foreach (var afflictionPrefab in AfflictionPrefab.List)
|
||||
if (damageModifier.MatchesAfflictionType("damage"))
|
||||
{
|
||||
if (damageModifier.MatchesAffliction(afflictionPrefab.Identifier, afflictionPrefab.AfflictionType))
|
||||
{
|
||||
if (afflictionPrefab.Effects.Any(e => e.MaxVitalityDecrease > 0))
|
||||
{
|
||||
damageMultiplier *= damageModifier.DamageMultiplier;
|
||||
break;
|
||||
}
|
||||
}
|
||||
damageMultiplier *= damageModifier.DamageMultiplier;
|
||||
}
|
||||
else if (damageModifier.MatchesAfflictionType("bleeding"))
|
||||
{
|
||||
bleedingDamageMultiplier *= damageModifier.DamageMultiplier;
|
||||
}
|
||||
}
|
||||
if (playSound)
|
||||
@@ -488,20 +486,29 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
// spawn damage particles
|
||||
float damageParticleAmount = Math.Min(damage / 5, 1.0f) * damageMultiplier;
|
||||
float damageParticleAmount = damage < 1 ? 0 : Math.Min(damage / 5, 1.0f) * damageMultiplier;
|
||||
if (damageParticleAmount > 0.001f)
|
||||
{
|
||||
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; }
|
||||
emitter.Emit(1.0f, WorldPosition, character.CurrentHull, amountMultiplier: damageParticleAmount);
|
||||
ParticlePrefab overrideParticle = null;
|
||||
foreach (DamageModifier damageModifier in result.AppliedDamageModifiers)
|
||||
{
|
||||
if (damageModifier.DamageMultiplier > 0 && !string.IsNullOrWhiteSpace(damageModifier.DamageParticle))
|
||||
{
|
||||
overrideParticle = GameMain.ParticleManager?.FindPrefab(damageModifier.DamageParticle);
|
||||
break;
|
||||
}
|
||||
}
|
||||
emitter.Emit(1.0f, WorldPosition, character.CurrentHull, amountMultiplier: damageParticleAmount, overrideParticle: overrideParticle);
|
||||
}
|
||||
}
|
||||
|
||||
if (bleedingDamage > 0)
|
||||
{
|
||||
float bloodParticleAmount = Math.Min(bleedingDamage / 5, 1.0f) * damageMultiplier;
|
||||
float bloodParticleAmount = Math.Min(bleedingDamage / 5, 1.0f) * bleedingDamageMultiplier;
|
||||
float bloodParticleSize = MathHelper.Clamp(bleedingDamage / 5, 0.1f, 1.0f);
|
||||
|
||||
foreach (ParticleEmitter emitter in character.BloodEmitters)
|
||||
@@ -930,6 +937,10 @@ namespace Barotrauma
|
||||
{
|
||||
depth -= depthStep;
|
||||
}
|
||||
if (wearableItemComponent.AllowedSlots.Contains(InvSlotType.Bag))
|
||||
{
|
||||
depth -= depthStep * 2;
|
||||
}
|
||||
wearableColor = wearableItemComponent.Item.GetSpriteColor();
|
||||
}
|
||||
float textureScale = wearable.InheritTextureScale ? TextureScale : 1;
|
||||
|
||||
@@ -2575,7 +2575,7 @@ namespace Barotrauma
|
||||
{
|
||||
string errorMsg = "Failed to spawn a submarine. Arguments: \"" + string.Join(" ", args) + "\".";
|
||||
ThrowError(errorMsg, e);
|
||||
GameAnalyticsManager.AddErrorEventOnce("DebugConsole.SpawnSubmarine:Error", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg + '\n' + e.Message + '\n' + e.StackTrace);
|
||||
GameAnalyticsManager.AddErrorEventOnce("DebugConsole.SpawnSubmarine:Error", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg + '\n' + e.Message + '\n' + e.StackTrace.CleanupStackTrace());
|
||||
}
|
||||
},
|
||||
() =>
|
||||
|
||||
@@ -109,7 +109,7 @@ namespace Barotrauma
|
||||
if (Character.Controlled != null && ChatMessage.CanUseRadio(Character.Controlled, out WifiComponent radio))
|
||||
{
|
||||
SetChannel(radio.Channel - 1, setText: true);
|
||||
GUI.PlayUISound(GUISoundType.PopupMenu);
|
||||
SoundPlayer.PlayUISound(GUISoundType.PopupMenu);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -142,7 +142,7 @@ namespace Barotrauma
|
||||
{
|
||||
int.TryParse(channelText.Text, out int newChannel);
|
||||
SetChannel(newChannel, setText: true);
|
||||
GUI.PlayUISound(GUISoundType.PopupMenu);
|
||||
SoundPlayer.PlayUISound(GUISoundType.PopupMenu);
|
||||
};
|
||||
|
||||
var buttonRight = new GUIButton(new RectTransform(new Vector2(0.1f, 0.8f), channelSettingsContent.RectTransform), style: "DeviceButton")
|
||||
@@ -152,7 +152,7 @@ namespace Barotrauma
|
||||
if (Character.Controlled != null && ChatMessage.CanUseRadio(Character.Controlled, out WifiComponent radio))
|
||||
{
|
||||
SetChannel(radio.Channel + 1, setText: true);
|
||||
GUI.PlayUISound(GUISoundType.PopupMenu);
|
||||
SoundPlayer.PlayUISound(GUISoundType.PopupMenu);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -194,7 +194,7 @@ namespace Barotrauma
|
||||
channelText.Flash(GUI.Style.Green);
|
||||
}
|
||||
SetChannel(radio.GetChannelMemory(index), setText: true);
|
||||
GUI.PlayUISound(GUISoundType.PopupMenu);
|
||||
SoundPlayer.PlayUISound(GUISoundType.PopupMenu);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -469,7 +469,7 @@ namespace Barotrauma
|
||||
soundType = GUISoundType.DeadMessage;
|
||||
}
|
||||
|
||||
GUI.PlayUISound(soundType);
|
||||
SoundPlayer.PlayUISound(soundType);
|
||||
}
|
||||
|
||||
public void SetVisibility(bool visible)
|
||||
|
||||
@@ -205,6 +205,7 @@ namespace Barotrauma
|
||||
};
|
||||
validateHiresButton = new GUIButton(new RectTransform(new Vector2(1.0f / 3.0f, 1.0f), group.RectTransform), text: TextManager.Get("campaigncrew.validate"))
|
||||
{
|
||||
ClickSound = GUISoundType.HireRepairClick,
|
||||
ForceUpperCase = true,
|
||||
OnClicked = (b, o) => ValidatePendingHires(true)
|
||||
};
|
||||
@@ -390,12 +391,29 @@ namespace Barotrauma
|
||||
|
||||
if (listBox == hireableList)
|
||||
{
|
||||
new GUIButton(new RectTransform(new Vector2(width, 0.9f), mainGroup.RectTransform), style: "CrewManagementAddButton")
|
||||
var hireButton = new GUIButton(new RectTransform(new Vector2(width, 0.9f), mainGroup.RectTransform), style: "CrewManagementAddButton")
|
||||
{
|
||||
UserData = characterInfo,
|
||||
Enabled = HasPermission,
|
||||
OnClicked = (b, o) => AddPendingHire(o as CharacterInfo)
|
||||
};
|
||||
hireButton.OnAddedToGUIUpdateList += (GUIComponent btn) =>
|
||||
{
|
||||
if (PendingHires.Count + campaign.CrewManager.GetCharacterInfos().Count() >= CrewManager.MaxCrewSize)
|
||||
{
|
||||
if (btn.Enabled)
|
||||
{
|
||||
btn.ToolTip = TextManager.Get("canthiremorecharacters");
|
||||
btn.Enabled = false;
|
||||
}
|
||||
}
|
||||
else if (!btn.Enabled)
|
||||
{
|
||||
btn.ToolTip = string.Empty;
|
||||
btn.Enabled = true;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
else if (listBox == pendingList)
|
||||
{
|
||||
@@ -514,6 +532,11 @@ namespace Barotrauma
|
||||
|
||||
private bool AddPendingHire(CharacterInfo characterInfo, bool createNetworkMessage = true)
|
||||
{
|
||||
if (PendingHires.Count + campaign.CrewManager.GetCharacters().Count() >= CrewManager.MaxCrewSize)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
hireableList.Content.RemoveChild(hireableList.Content.FindChild(c => (c.UserData as Tuple<CharacterInfo, float>).Item1 == characterInfo));
|
||||
hireableList.UpdateScrollBarSize();
|
||||
if (!PendingHires.Contains(characterInfo)) { PendingHires.Add(characterInfo); }
|
||||
|
||||
@@ -27,7 +27,11 @@ namespace Barotrauma
|
||||
PickItem,
|
||||
PickItemFail,
|
||||
DropItem,
|
||||
PopupMenu
|
||||
PopupMenu,
|
||||
DecreaseQuantity,
|
||||
IncreaseQuantity,
|
||||
HireRepairClick,
|
||||
UISwitch
|
||||
}
|
||||
|
||||
public enum CursorState
|
||||
@@ -135,7 +139,7 @@ namespace Barotrauma
|
||||
public static GraphicsDevice GraphicsDevice { get; private set; }
|
||||
|
||||
private static List<GUIMessage> messages = new List<GUIMessage>();
|
||||
private static Sound[] sounds;
|
||||
private static readonly Dictionary<GUISoundType, string> soundIdentifiers = new Dictionary<GUISoundType, string>();
|
||||
private static bool pauseMenuOpen, settingsMenuOpen;
|
||||
public static GUIFrame PauseMenu { get; private set; }
|
||||
private static Sprite arrow;
|
||||
@@ -256,23 +260,13 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public static void LoadContent(bool loadSounds = true)
|
||||
public static void LoadContent()
|
||||
{
|
||||
if (loadSounds)
|
||||
foreach (GUISoundType soundType in Enum.GetValues(typeof(GUISoundType)))
|
||||
{
|
||||
sounds = new Sound[Enum.GetValues(typeof(GUISoundType)).Length];
|
||||
|
||||
sounds[(int)GUISoundType.UIMessage] = GameMain.SoundManager.LoadSound("Content/Sounds/UI/UImsg.ogg", false);
|
||||
sounds[(int)GUISoundType.ChatMessage] = GameMain.SoundManager.LoadSound("Content/Sounds/UI/ChatMsg.ogg", false);
|
||||
sounds[(int)GUISoundType.RadioMessage] = GameMain.SoundManager.LoadSound("Content/Sounds/UI/RadioMsg.ogg", false);
|
||||
sounds[(int)GUISoundType.DeadMessage] = GameMain.SoundManager.LoadSound("Content/Sounds/UI/DeadMsg.ogg", false);
|
||||
sounds[(int)GUISoundType.Click] = GameMain.SoundManager.LoadSound("Content/Sounds/UI/Click.ogg", false);
|
||||
sounds[(int)GUISoundType.PopupMenu] = GameMain.SoundManager.LoadSound("Content/Sounds/UI/PopupMenu.ogg", false);
|
||||
|
||||
sounds[(int)GUISoundType.PickItem] = GameMain.SoundManager.LoadSound("Content/Sounds/PickItem.ogg", false);
|
||||
sounds[(int)GUISoundType.PickItemFail] = GameMain.SoundManager.LoadSound("Content/Sounds/PickItemFail.ogg", false);
|
||||
sounds[(int)GUISoundType.DropItem] = GameMain.SoundManager.LoadSound("Content/Sounds/DropItem.ogg", false);
|
||||
soundIdentifiers.Add(soundType, soundType.ToString().ToLowerInvariant());
|
||||
}
|
||||
|
||||
// create 1x1 texture for line drawing
|
||||
CrossThread.RequestExecutionOnMainThread(() =>
|
||||
{
|
||||
@@ -314,7 +308,7 @@ namespace Barotrauma
|
||||
|
||||
#if UNSTABLE
|
||||
string line1 = "Barotrauma Unstable v" + GameMain.Version;
|
||||
string line2 = "(" + AssemblyInfo.GetBuildString() + ", branch " + AssemblyInfo.GetGitBranch() + ", revision " + AssemblyInfo.GetGitRevision() + ")";
|
||||
string line2 = "(" + AssemblyInfo.BuildString + ", branch " + AssemblyInfo.GitBranch + ", revision " + AssemblyInfo.GitRevision + ")";
|
||||
|
||||
Rectangle watermarkRect = new Rectangle(-50, GameMain.GraphicsHeight - 80, 50 + (int)(Math.Max(LargeFont.MeasureString(line1).X, Font.MeasureString(line2).X) * 1.2f), 100);
|
||||
float alpha = 1.0f;
|
||||
@@ -2282,13 +2276,13 @@ namespace Barotrauma
|
||||
{
|
||||
if (messages.Any(msg => msg.Text == message)) { return; }
|
||||
messages.Add(new GUIMessage(message, color, lifeTime ?? MathHelper.Clamp(message.Length / 5.0f, 3.0f, 10.0f), font ?? LargeFont));
|
||||
if (playSound) PlayUISound(GUISoundType.UIMessage);
|
||||
if (playSound) SoundPlayer.PlayUISound(GUISoundType.UIMessage);
|
||||
}
|
||||
|
||||
public static void AddMessage(string message, Color color, Vector2 worldPos, Vector2 velocity, float lifeTime = 3.0f, bool playSound = true)
|
||||
public static void AddMessage(string message, Color color, Vector2 worldPos, Vector2 velocity, float lifeTime = 3.0f, bool playSound = true, GUISoundType soundType = GUISoundType.UIMessage)
|
||||
{
|
||||
messages.Add(new GUIMessage(message, color, worldPos, velocity, lifeTime, Alignment.Center, LargeFont));
|
||||
if (playSound) PlayUISound(GUISoundType.UIMessage);
|
||||
if (playSound) SoundPlayer.PlayUISound(soundType);
|
||||
}
|
||||
|
||||
public static void ClearMessages()
|
||||
@@ -2296,16 +2290,6 @@ namespace Barotrauma
|
||||
messages.Clear();
|
||||
}
|
||||
|
||||
public static void PlayUISound(GUISoundType soundType)
|
||||
{
|
||||
if (sounds == null) { return; }
|
||||
|
||||
int soundIndex = (int)soundType;
|
||||
if (soundIndex < 0 || soundIndex >= sounds.Length) { return; }
|
||||
|
||||
sounds[soundIndex]?.Play(null, "ui");
|
||||
}
|
||||
|
||||
public static bool IsFourByThree()
|
||||
{
|
||||
float aspectRatio = HorizontalAspectRatio;
|
||||
|
||||
@@ -157,6 +157,8 @@ namespace Barotrauma
|
||||
private float pulseTimer;
|
||||
private float pulseExpand;
|
||||
private bool flashed;
|
||||
|
||||
public GUISoundType ClickSound { get; set; } = GUISoundType.Click;
|
||||
|
||||
public GUIButton(RectTransform rectT, string text = "", Alignment textAlignment = Alignment.Center, string style = "", Color? color = null) : base(style, rectT)
|
||||
{
|
||||
@@ -247,7 +249,7 @@ namespace Barotrauma
|
||||
}
|
||||
else if (PlayerInput.PrimaryMouseButtonClicked())
|
||||
{
|
||||
GUI.PlayUISound(GUISoundType.Click);
|
||||
SoundPlayer.PlayUISound(ClickSound);
|
||||
if (OnClicked != null)
|
||||
{
|
||||
if (OnClicked(this, UserData))
|
||||
|
||||
@@ -404,7 +404,7 @@ namespace Barotrauma
|
||||
/// <param name="component"></param>
|
||||
public void ScrollToElement(GUIComponent component)
|
||||
{
|
||||
GUI.PlayUISound(GUISoundType.Click);
|
||||
SoundPlayer.PlayUISound(GUISoundType.Click);
|
||||
List<GUIComponent> children = Content.Children.ToList();
|
||||
int index = children.IndexOf(component);
|
||||
if (index < 0) { return; }
|
||||
|
||||
@@ -17,7 +17,8 @@ namespace Barotrauma
|
||||
|
||||
public GUITextBox TextBox { get; private set; }
|
||||
|
||||
private GUIButton plusButton, minusButton;
|
||||
public GUIButton PlusButton { get; private set; }
|
||||
public GUIButton MinusButton { get; private set; }
|
||||
|
||||
private NumberType inputType;
|
||||
public NumberType InputType
|
||||
@@ -142,14 +143,14 @@ namespace Barotrauma
|
||||
get => base.Enabled;
|
||||
set
|
||||
{
|
||||
plusButton.Enabled = true;
|
||||
minusButton.Enabled = true;
|
||||
PlusButton.Enabled = true;
|
||||
MinusButton.Enabled = true;
|
||||
if (InputType == NumberType.Int) { ClampIntValue(); } else { ClampFloatValue(); }
|
||||
TextBox.Enabled = value;
|
||||
if (!value)
|
||||
{
|
||||
plusButton.Enabled = false;
|
||||
minusButton.Enabled = false;
|
||||
PlusButton.Enabled = false;
|
||||
MinusButton.Enabled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -193,19 +194,19 @@ namespace Barotrauma
|
||||
TextBox.OnTextChanged += TextChanged;
|
||||
|
||||
var buttonArea = new GUIFrame(new RectTransform(new Vector2(_relativeButtonAreaWidth, 1.0f), LayoutGroup.RectTransform, Anchor.CenterRight), style: null);
|
||||
plusButton = new GUIButton(new RectTransform(new Vector2(1.0f, 0.5f), buttonArea.RectTransform), style: null);
|
||||
GUI.Style.Apply(plusButton, "PlusButton", this);
|
||||
plusButton.OnButtonDown += () =>
|
||||
PlusButton = new GUIButton(new RectTransform(new Vector2(1.0f, 0.5f), buttonArea.RectTransform), style: null);
|
||||
GUI.Style.Apply(PlusButton, "PlusButton", this);
|
||||
PlusButton.OnButtonDown += () =>
|
||||
{
|
||||
pressedTimer = pressedDelay;
|
||||
return true;
|
||||
};
|
||||
plusButton.OnClicked += (button, data) =>
|
||||
PlusButton.OnClicked += (button, data) =>
|
||||
{
|
||||
IncreaseValue();
|
||||
return true;
|
||||
};
|
||||
plusButton.OnPressed += () =>
|
||||
PlusButton.OnPressed += () =>
|
||||
{
|
||||
if (!IsPressedTimerRunning)
|
||||
{
|
||||
@@ -214,19 +215,19 @@ namespace Barotrauma
|
||||
return true;
|
||||
};
|
||||
|
||||
minusButton = new GUIButton(new RectTransform(new Vector2(1.0f, 0.5f), buttonArea.RectTransform, Anchor.BottomRight), style: null);
|
||||
GUI.Style.Apply(minusButton, "MinusButton", this);
|
||||
minusButton.OnButtonDown += () =>
|
||||
MinusButton = new GUIButton(new RectTransform(new Vector2(1.0f, 0.5f), buttonArea.RectTransform, Anchor.BottomRight), style: null);
|
||||
GUI.Style.Apply(MinusButton, "MinusButton", this);
|
||||
MinusButton.OnButtonDown += () =>
|
||||
{
|
||||
pressedTimer = pressedDelay;
|
||||
return true;
|
||||
};
|
||||
minusButton.OnClicked += (button, data) =>
|
||||
MinusButton.OnClicked += (button, data) =>
|
||||
{
|
||||
ReduceValue();
|
||||
return true;
|
||||
};
|
||||
minusButton.OnPressed += () =>
|
||||
MinusButton.OnPressed += () =>
|
||||
{
|
||||
if (!IsPressedTimerRunning)
|
||||
{
|
||||
@@ -279,17 +280,17 @@ namespace Barotrauma
|
||||
|
||||
private void HidePlusMinusButtons()
|
||||
{
|
||||
plusButton.Parent.Visible = false;
|
||||
plusButton.Parent.IgnoreLayoutGroups = true;
|
||||
PlusButton.Parent.Visible = false;
|
||||
PlusButton.Parent.IgnoreLayoutGroups = true;
|
||||
TextBox.RectTransform.RelativeSize = Vector2.One;
|
||||
LayoutGroup.Recalculate();
|
||||
}
|
||||
|
||||
private void ShowPlusMinusButtons()
|
||||
{
|
||||
plusButton.Parent.Visible = true;
|
||||
plusButton.Parent.IgnoreLayoutGroups = false;
|
||||
TextBox.RectTransform.RelativeSize = new Vector2(1.0f - plusButton.Parent.RectTransform.RelativeSize.X, 1.0f);
|
||||
PlusButton.Parent.Visible = true;
|
||||
PlusButton.Parent.IgnoreLayoutGroups = false;
|
||||
TextBox.RectTransform.RelativeSize = new Vector2(1.0f - PlusButton.Parent.RectTransform.RelativeSize.X, 1.0f);
|
||||
LayoutGroup.Recalculate();
|
||||
}
|
||||
|
||||
@@ -369,12 +370,12 @@ namespace Barotrauma
|
||||
if (MinValueFloat != null)
|
||||
{
|
||||
floatValue = Math.Max(floatValue, MinValueFloat.Value);
|
||||
minusButton.Enabled = floatValue > MinValueFloat;
|
||||
MinusButton.Enabled = floatValue > MinValueFloat;
|
||||
}
|
||||
if (MaxValueFloat != null)
|
||||
{
|
||||
floatValue = Math.Min(floatValue, MaxValueFloat.Value);
|
||||
plusButton.Enabled = floatValue < MaxValueFloat;
|
||||
PlusButton.Enabled = floatValue < MaxValueFloat;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -390,8 +391,8 @@ namespace Barotrauma
|
||||
intValue = Math.Min(intValue, MaxValueInt.Value);
|
||||
UpdateText();
|
||||
}
|
||||
plusButton.Enabled = intValue < MaxValueInt;
|
||||
minusButton.Enabled = intValue > MinValueInt;
|
||||
PlusButton.Enabled = intValue < MaxValueInt;
|
||||
MinusButton.Enabled = intValue > MinValueInt;
|
||||
}
|
||||
|
||||
private void UpdateText()
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace Barotrauma
|
||||
GameAnalyticsManager.AddErrorEventOnce(
|
||||
"GUIProgressBar.BarSize_setter",
|
||||
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||
"Attempted to set the BarSize of a GUIProgressBar to an invalid value (" + value + ")\n" + Environment.StackTrace);
|
||||
"Attempted to set the BarSize of a GUIProgressBar to an invalid value (" + value + ")\n" + Environment.StackTrace.CleanupStackTrace());
|
||||
return;
|
||||
}
|
||||
barSize = MathHelper.Clamp(value, 0.0f, 1.0f);
|
||||
@@ -106,7 +106,7 @@ namespace Barotrauma
|
||||
GameAnalyticsManager.AddErrorEventOnce(
|
||||
"GUIProgressBar.Draw:GetProgress",
|
||||
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||
"ProgressGetter of a GUIProgressBar (" + ProgressGetter.Target.ToString() + " - " + ProgressGetter.Method.ToString() + ") returned an invalid value (" + newSize + ")\n" + Environment.StackTrace);
|
||||
"ProgressGetter of a GUIProgressBar (" + ProgressGetter.Target.ToString() + " - " + ProgressGetter.Method.ToString() + ") returned an invalid value (" + newSize + ")\n" + Environment.StackTrace.CleanupStackTrace());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -664,7 +664,7 @@ namespace Barotrauma
|
||||
case (char)0x1: // ctrl-a
|
||||
SelectAll();
|
||||
break;
|
||||
case (char)0x1A when !Readonly: // ctrl-z
|
||||
case (char)0x1A when !Readonly && !SubEditorScreen.IsSubEditor(): // ctrl-z
|
||||
text = memento.Undo();
|
||||
if (text != Text)
|
||||
{
|
||||
@@ -674,7 +674,7 @@ namespace Barotrauma
|
||||
OnTextChanged?.Invoke(this, Text);
|
||||
}
|
||||
break;
|
||||
case (char)0x12 when !Readonly: // ctrl-r
|
||||
case (char)0x12 when !Readonly && !SubEditorScreen.IsSubEditor(): // ctrl-r
|
||||
text = memento.Redo();
|
||||
if (text != Text)
|
||||
{
|
||||
|
||||
@@ -519,7 +519,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (displayErrors)
|
||||
{
|
||||
DebugConsole.ThrowError("Parent null" + Environment.StackTrace);
|
||||
DebugConsole.ThrowError("Parent null" + Environment.StackTrace.CleanupStackTrace());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -527,7 +527,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (displayErrors)
|
||||
{
|
||||
DebugConsole.ThrowError("The children of the parent does not contain this child. This should not be possible! " + Environment.StackTrace);
|
||||
DebugConsole.ThrowError("The children of the parent does not contain this child. This should not be possible! " + Environment.StackTrace.CleanupStackTrace());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -535,7 +535,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (displayErrors)
|
||||
{
|
||||
DebugConsole.ThrowError("Unable to remove the child from the parent. " + Environment.StackTrace);
|
||||
DebugConsole.ThrowError("Unable to remove the child from the parent. " + Environment.StackTrace.CleanupStackTrace());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Barotrauma.Extensions;
|
||||
using Barotrauma.Items.Components;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -31,9 +32,13 @@ namespace Barotrauma
|
||||
private GUITextBlock shoppingCrateTotal;
|
||||
private GUIButton clearAllButton, confirmButton;
|
||||
|
||||
private bool needsRefresh, needsBuyingRefresh, needsSellingRefresh, needsItemsToSellRefresh;
|
||||
|
||||
private Point resolutionWhenCreated;
|
||||
private bool hadPermissions;
|
||||
|
||||
private Dictionary<ItemPrefab, int> OwnedItems { get; } = new Dictionary<ItemPrefab, int>();
|
||||
|
||||
private CargoManager CargoManager => campaignUI.Campaign.CargoManager;
|
||||
private Location CurrentLocation => campaignUI.Campaign.Map?.CurrentLocation;
|
||||
private int PlayerMoney => campaignUI.Campaign.Money;
|
||||
@@ -70,27 +75,30 @@ namespace Barotrauma
|
||||
campaignUI.Campaign.Map.OnLocationChanged += UpdateLocation;
|
||||
if (CurrentLocation?.Reputation != null)
|
||||
{
|
||||
CurrentLocation.Reputation.OnReputationValueChanged += Refresh;
|
||||
CurrentLocation.Reputation.OnReputationValueChanged += () => { needsRefresh = true; };
|
||||
}
|
||||
campaignUI.Campaign.CargoManager.OnItemsInBuyCrateChanged += RefreshBuying;
|
||||
campaignUI.Campaign.CargoManager.OnPurchasedItemsChanged += RefreshBuying;
|
||||
campaignUI.Campaign.CargoManager.OnItemsInSellCrateChanged += RefreshSelling;
|
||||
campaignUI.Campaign.CargoManager.OnItemsInBuyCrateChanged += () => { needsBuyingRefresh = true; };
|
||||
campaignUI.Campaign.CargoManager.OnPurchasedItemsChanged += () => { needsBuyingRefresh = true; };
|
||||
campaignUI.Campaign.CargoManager.OnItemsInSellCrateChanged += () => { needsSellingRefresh = true; };
|
||||
campaignUI.Campaign.CargoManager.OnSoldItemsChanged += () =>
|
||||
{
|
||||
RefreshItemsToSell();
|
||||
RefreshSelling();
|
||||
needsItemsToSellRefresh = true;
|
||||
needsSellingRefresh = true;
|
||||
};
|
||||
}
|
||||
|
||||
public void Refresh()
|
||||
{
|
||||
hadPermissions = HasPermissions;
|
||||
RefreshBuying();
|
||||
RefreshSelling();
|
||||
UpdateOwnedItems();
|
||||
RefreshBuying(updateOwned: false);
|
||||
RefreshSelling(updateOwned: false);
|
||||
needsRefresh = false;
|
||||
}
|
||||
|
||||
private void RefreshBuying()
|
||||
private void RefreshBuying(bool updateOwned = true)
|
||||
{
|
||||
if (updateOwned) { UpdateOwnedItems(); }
|
||||
RefreshShoppingCrateBuyList();
|
||||
//RefreshStoreDealsList();
|
||||
RefreshStoreBuyList();
|
||||
@@ -98,15 +106,18 @@ namespace Barotrauma
|
||||
//storeDealsList.Enabled = hasPermissions;
|
||||
storeBuyList.Enabled = hasPermissions;
|
||||
shoppingCrateBuyList.Enabled = hasPermissions;
|
||||
needsBuyingRefresh = false;
|
||||
}
|
||||
|
||||
private void RefreshSelling()
|
||||
private void RefreshSelling(bool updateOwned = true)
|
||||
{
|
||||
if (updateOwned) { UpdateOwnedItems(); }
|
||||
RefreshShoppingCrateSellList();
|
||||
RefreshStoreSellList();
|
||||
var hasPermissions = HasPermissions;
|
||||
storeSellList.Enabled = hasPermissions;
|
||||
shoppingCrateSellList.Enabled = hasPermissions;
|
||||
needsSellingRefresh = false;
|
||||
}
|
||||
|
||||
private void CreateUI()
|
||||
@@ -400,6 +411,7 @@ namespace Barotrauma
|
||||
SetConfirmButtonBehavior();
|
||||
clearAllButton = new GUIButton(new RectTransform(new Vector2(0.35f, 1.0f), buttonContainer.RectTransform), TextManager.Get("campaignstore.clearall"))
|
||||
{
|
||||
ClickSound = GUISoundType.DecreaseQuantity,
|
||||
Enabled = HasPermissions,
|
||||
ForceUpperCase = true,
|
||||
OnClicked = (button, userData) =>
|
||||
@@ -422,7 +434,7 @@ namespace Barotrauma
|
||||
|
||||
if (prevLocation?.Reputation != null)
|
||||
{
|
||||
prevLocation.Reputation.OnReputationValueChanged -= Refresh;
|
||||
prevLocation.Reputation.OnReputationValueChanged = null;
|
||||
}
|
||||
|
||||
foreach (ItemPrefab itemPrefab in ItemPrefab.Prefabs)
|
||||
@@ -432,7 +444,7 @@ namespace Barotrauma
|
||||
ChangeStoreTab(StoreTab.Buy);
|
||||
if (newLocation?.Reputation != null)
|
||||
{
|
||||
newLocation.Reputation.OnReputationValueChanged += Refresh;
|
||||
newLocation.Reputation.OnReputationValueChanged += () => { needsRefresh = true; };
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -535,6 +547,7 @@ namespace Barotrauma
|
||||
{
|
||||
(itemFrame.UserData as PurchasedItem).Quantity = quantity;
|
||||
SetQuantityLabelText(StoreTab.Buy, itemFrame);
|
||||
SetOwnedLabelText(itemFrame);
|
||||
SetItemFrameStatus(itemFrame, hasPermissions && quantity > 0);
|
||||
}
|
||||
existingItemFrames.Add(itemFrame);
|
||||
@@ -575,6 +588,7 @@ namespace Barotrauma
|
||||
{
|
||||
(itemFrame.UserData as PurchasedItem).Quantity = quantity;
|
||||
SetQuantityLabelText(StoreTab.Sell, itemFrame);
|
||||
SetOwnedLabelText(itemFrame);
|
||||
SetItemFrameStatus(itemFrame, hasPermissions);
|
||||
}
|
||||
if (quantity < 1) { itemFrame.Visible = false; }
|
||||
@@ -617,6 +631,7 @@ namespace Barotrauma
|
||||
CargoManager.ModifyItemQuantityInSellCrate(crateItem.ItemPrefab, playerItemQuantity - crateItem.Quantity);
|
||||
}
|
||||
}
|
||||
needsItemsToSellRefresh = false;
|
||||
}
|
||||
|
||||
private void RefreshShoppingCrateList(List<PurchasedItem> items, GUIListBox listBox)
|
||||
@@ -645,6 +660,7 @@ namespace Barotrauma
|
||||
numInput.UserData = item;
|
||||
numInput.Enabled = hasPermissions;
|
||||
}
|
||||
SetOwnedLabelText(itemFrame);
|
||||
SetItemFrameStatus(itemFrame, hasPermissions);
|
||||
}
|
||||
existingItemFrames.Add(itemFrame);
|
||||
@@ -740,7 +756,7 @@ namespace Barotrauma
|
||||
tooltip += "\n" + pi.ItemPrefab.Description;
|
||||
}
|
||||
|
||||
GUIFrame frame = new GUIFrame(new RectTransform(new Point(listBox.Content.Rect.Width, (int)(GUI.yScale * 60)), parent: listBox.Content.RectTransform), style: "ListBoxElement")
|
||||
GUIFrame frame = new GUIFrame(new RectTransform(new Point(listBox.Content.Rect.Width, (int)(GUI.yScale * 80)), parent: listBox.Content.RectTransform), style: "ListBoxElement")
|
||||
{
|
||||
ToolTip = tooltip,
|
||||
UserData = pi
|
||||
@@ -775,7 +791,7 @@ namespace Barotrauma
|
||||
CanBeFocused = false,
|
||||
Stretch = true
|
||||
};
|
||||
GUITextBlock nameBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), nameAndQuantityGroup.RectTransform),
|
||||
GUITextBlock nameBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.4f), nameAndQuantityGroup.RectTransform),
|
||||
pi.ItemPrefab.Name, font: GUI.SubHeadingFont, textAlignment: Alignment.BottomLeft)
|
||||
{
|
||||
CanBeFocused = false,
|
||||
@@ -783,11 +799,12 @@ namespace Barotrauma
|
||||
TextScale = 0.85f,
|
||||
UserData = "name"
|
||||
};
|
||||
GUILayoutGroup shoppingCrateAmountGroup = null;
|
||||
GUINumberInput amountInput = null;
|
||||
if (listBox == storeBuyList || listBox == storeSellList)
|
||||
{
|
||||
var block = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), nameAndQuantityGroup.RectTransform),
|
||||
CreateQuantityLabelText(listBox == storeSellList ? StoreTab.Sell : StoreTab.Buy, pi.Quantity), font: GUI.Font, textAlignment: Alignment.TopLeft)
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.3f), nameAndQuantityGroup.RectTransform),
|
||||
CreateQuantityLabelText(listBox == storeSellList ? StoreTab.Sell : StoreTab.Buy, pi.Quantity), font: GUI.Font, textAlignment: Alignment.BottomLeft)
|
||||
{
|
||||
CanBeFocused = false,
|
||||
TextColor = Color.White * (forceDisable ? 0.5f : 1.0f),
|
||||
@@ -797,7 +814,13 @@ namespace Barotrauma
|
||||
}
|
||||
else if (listBox == shoppingCrateBuyList || listBox == shoppingCrateSellList)
|
||||
{
|
||||
amountInput = new GUINumberInput(new RectTransform(new Vector2(0.5f), nameAndQuantityGroup.RectTransform), GUINumberInput.NumberType.Int)
|
||||
var relativePadding = nameBlock.Padding.X / nameBlock.Rect.Width;
|
||||
shoppingCrateAmountGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f - relativePadding, 0.6f), nameAndQuantityGroup.RectTransform) { RelativeOffset = new Vector2(relativePadding, 0) },
|
||||
isHorizontal: true)
|
||||
{
|
||||
RelativeSpacing = 0.02f
|
||||
};
|
||||
amountInput = new GUINumberInput(new RectTransform(new Vector2(0.4f, 1.0f), shoppingCrateAmountGroup.RectTransform), GUINumberInput.NumberType.Int)
|
||||
{
|
||||
MinValueInt = 0,
|
||||
MaxValueInt = GetMaxAvailable(pi.ItemPrefab, listBox == shoppingCrateBuyList ? StoreTab.Buy : StoreTab.Sell),
|
||||
@@ -818,9 +841,25 @@ namespace Barotrauma
|
||||
}
|
||||
AddToShoppingCrate(purchasedItem, quantity: numberInput.IntValue - purchasedItem.Quantity);
|
||||
};
|
||||
amountInput.PlusButton.ClickSound = GUISoundType.IncreaseQuantity;
|
||||
amountInput.MinusButton.ClickSound = GUISoundType.DecreaseQuantity;
|
||||
frame.HoverColor = frame.SelectedColor = Color.Transparent;
|
||||
}
|
||||
|
||||
// Amount in players' inventories and on the sub
|
||||
var rectTransform = shoppingCrateAmountGroup == null ?
|
||||
new RectTransform(new Vector2(1.0f, 0.3f), nameAndQuantityGroup.RectTransform) :
|
||||
new RectTransform(new Vector2(0.6f, 1.0f), shoppingCrateAmountGroup.RectTransform);
|
||||
new GUITextBlock(rectTransform, CreateOwnedLabelText(OwnedItems.GetValueOrDefault(pi.ItemPrefab, 0)), font: GUI.Font,
|
||||
textAlignment: shoppingCrateAmountGroup == null ? Alignment.TopLeft : Alignment.CenterLeft)
|
||||
{
|
||||
CanBeFocused = false,
|
||||
TextColor = Color.White * (forceDisable ? 0.5f : 1.0f),
|
||||
TextScale = 0.85f,
|
||||
UserData = "owned"
|
||||
};
|
||||
shoppingCrateAmountGroup?.Recalculate();
|
||||
|
||||
var buttonRelativeWidth = (0.9f * mainGroup.Rect.Height) / mainGroup.Rect.Width;
|
||||
|
||||
var priceBlock = new GUITextBlock(new RectTransform(new Vector2(priceAndButtonRelativeWidth - buttonRelativeWidth, 1.0f), mainGroup.RectTransform), "", font: GUI.SubHeadingFont, textAlignment: Alignment.Right)
|
||||
@@ -842,6 +881,7 @@ namespace Barotrauma
|
||||
{
|
||||
new GUIButton(new RectTransform(new Vector2(buttonRelativeWidth, 0.9f), mainGroup.RectTransform), style: "StoreAddToCrateButton")
|
||||
{
|
||||
ClickSound = GUISoundType.IncreaseQuantity,
|
||||
Enabled = !forceDisable && pi.Quantity > 0,
|
||||
ForceUpperCase = true,
|
||||
UserData = "addbutton",
|
||||
@@ -852,6 +892,7 @@ namespace Barotrauma
|
||||
{
|
||||
new GUIButton(new RectTransform(new Vector2(buttonRelativeWidth, 0.9f), mainGroup.RectTransform), style: "StoreRemoveFromCrateButton")
|
||||
{
|
||||
ClickSound = GUISoundType.DecreaseQuantity,
|
||||
Enabled = !forceDisable,
|
||||
ForceUpperCase = true,
|
||||
UserData = "removebutton",
|
||||
@@ -869,6 +910,39 @@ namespace Barotrauma
|
||||
return frame;
|
||||
}
|
||||
|
||||
private void UpdateOwnedItems()
|
||||
{
|
||||
OwnedItems.Clear();
|
||||
|
||||
// Add items on the sub(s)
|
||||
Submarine.MainSub?.GetItems(true)
|
||||
.Where(i => i.Components.All(c => !(c is Holdable h) || !h.Attachable || !h.Attached) &&
|
||||
i.Components.All(c => !(c is Wire w) || w.Connections.All(c => c == null)))
|
||||
.ForEach(i => AddToOwnedItems(i.Prefab));
|
||||
|
||||
// Add items in character inventories
|
||||
foreach (Character c in GameMain.GameSession.CrewManager.GetCharacters())
|
||||
{
|
||||
Item.ItemList.Where(i => i != null && i.GetRootInventoryOwner() == c)
|
||||
.ForEach(i => AddToOwnedItems(i.Prefab));
|
||||
}
|
||||
|
||||
// Add items already purchased
|
||||
CargoManager?.PurchasedItems?.ForEach(pi => AddToOwnedItems(pi.ItemPrefab, amount: pi.Quantity));
|
||||
|
||||
void AddToOwnedItems(ItemPrefab itemPrefab, int amount = 1)
|
||||
{
|
||||
if (OwnedItems.ContainsKey(itemPrefab))
|
||||
{
|
||||
OwnedItems[itemPrefab] += amount;
|
||||
}
|
||||
else
|
||||
{
|
||||
OwnedItems.Add(itemPrefab, amount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SetItemFrameStatus(GUIComponent itemFrame, bool enabled)
|
||||
{
|
||||
if (itemFrame == null || !(itemFrame.UserData is PurchasedItem pi)) { return; }
|
||||
@@ -901,6 +975,11 @@ namespace Barotrauma
|
||||
numberInput.Enabled = enabled;
|
||||
}
|
||||
|
||||
if (itemFrame.FindChild("owned", recursive: true) is GUITextBlock owned)
|
||||
{
|
||||
owned.TextColor = color;
|
||||
}
|
||||
|
||||
if (itemFrame.FindChild("price", recursive: true) is GUITextBlock price)
|
||||
{
|
||||
price.TextColor = color;
|
||||
@@ -918,7 +997,8 @@ namespace Barotrauma
|
||||
|
||||
private void SetQuantityLabelText(StoreTab mode, GUIComponent itemFrame)
|
||||
{
|
||||
if (itemFrame?.FindChild("quantitylabel", recursive: true) is GUITextBlock label)
|
||||
if (itemFrame == null) { return; }
|
||||
if (itemFrame.FindChild("quantitylabel", recursive: true) is GUITextBlock label)
|
||||
{
|
||||
label.Text = CreateQuantityLabelText(mode, (itemFrame.UserData as PurchasedItem).Quantity);
|
||||
}
|
||||
@@ -928,6 +1008,23 @@ namespace Barotrauma
|
||||
TextManager.GetWithVariable("campaignstore.quantity", "[amount]", quantity.ToString()) :
|
||||
TextManager.GetWithVariable("campaignstore.instock", "[amount]", quantity.ToString());
|
||||
|
||||
private void SetOwnedLabelText(GUIComponent itemComponent)
|
||||
{
|
||||
if (itemComponent == null) { return; }
|
||||
var itemCount = 0;
|
||||
if (itemComponent.UserData is PurchasedItem pi)
|
||||
{
|
||||
itemCount = OwnedItems.GetValueOrDefault(pi.ItemPrefab, itemCount);
|
||||
}
|
||||
if (itemComponent.FindChild("owned", recursive: true) is GUITextBlock label)
|
||||
{
|
||||
label.Text = CreateOwnedLabelText(itemCount);
|
||||
}
|
||||
}
|
||||
|
||||
private string CreateOwnedLabelText(int itemCount) => itemCount > 0 ?
|
||||
TextManager.GetWithVariable("campaignstore.owned", "[amount]", itemCount.ToString()) : "";
|
||||
|
||||
private int GetMaxAvailable(ItemPrefab itemPrefab, StoreTab mode)
|
||||
{
|
||||
var list = mode == StoreTab.Sell ? itemsToSell : CurrentLocation.StoreStock;
|
||||
@@ -1103,11 +1200,12 @@ namespace Barotrauma
|
||||
if (GameMain.GraphicsWidth != resolutionWhenCreated.X || GameMain.GraphicsHeight != resolutionWhenCreated.Y)
|
||||
{
|
||||
CreateUI();
|
||||
needsRefresh = false;
|
||||
}
|
||||
else if (hadPermissions != HasPermissions)
|
||||
{
|
||||
Refresh();
|
||||
}
|
||||
if (needsRefresh || hadPermissions != HasPermissions) { Refresh(); }
|
||||
if (needsBuyingRefresh) { RefreshBuying(); }
|
||||
if (needsItemsToSellRefresh) { RefreshItemsToSell(); }
|
||||
if (needsSellingRefresh) { RefreshSelling(); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -491,7 +491,7 @@ namespace Barotrauma
|
||||
new GUITextBlock(rectT(1, 0, textLayout), title, font: GUI.SubHeadingFont) { CanBeFocused = false, AutoScaleHorizontal = true };
|
||||
new GUITextBlock(rectT(1, 0, textLayout), FormatCurrency(price));
|
||||
GUILayoutGroup buyButtonLayout = new GUILayoutGroup(rectT(0.2f, 1, contentLayout), childAnchor: Anchor.Center) { UserData = "buybutton" };
|
||||
new GUIButton(rectT(0.7f, 0.5f, buyButtonLayout), string.Empty, style: "RepairBuyButton") { Enabled = Campaign.Money >= price && !isDisabled, OnClicked = onPressed };
|
||||
new GUIButton(rectT(0.7f, 0.5f, buyButtonLayout), string.Empty, style: "RepairBuyButton") { ClickSound = GUISoundType.HireRepairClick, Enabled = Campaign.Money >= price && !isDisabled, OnClicked = onPressed };
|
||||
contentLayout.Recalculate();
|
||||
buyButtonLayout.Recalculate();
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@ namespace Barotrauma
|
||||
if (gameSession == value) { return; }
|
||||
if (value == null && Screen.Selected == GameScreen && gameSession.GameMode is CampaignMode)
|
||||
{
|
||||
DebugConsole.AddWarning("GameSession set to null while in the game screen\n" + Environment.StackTrace);
|
||||
DebugConsole.AddWarning("GameSession set to null while in the game screen\n" + Environment.StackTrace.CleanupStackTrace());
|
||||
}
|
||||
if (gameSession?.GameMode != null && gameSession.GameMode != value?.GameMode)
|
||||
{
|
||||
@@ -669,7 +669,7 @@ namespace Barotrauma
|
||||
#if DEBUG
|
||||
DebugConsole.ThrowError($"Failed to parse a Steam friend's connect invitation command ({connectCommand})", e);
|
||||
#else
|
||||
DebugConsole.Log($"Failed to parse a Steam friend's connect invitation command ({connectCommand})\n" + e.StackTrace);
|
||||
DebugConsole.Log($"Failed to parse a Steam friend's connect invitation command ({connectCommand})\n" + e.StackTrace.CleanupStackTrace());
|
||||
#endif
|
||||
ConnectName = null;
|
||||
ConnectEndpoint = null;
|
||||
|
||||
@@ -52,11 +52,11 @@ namespace Barotrauma
|
||||
i.GetRootInventoryOwner() == character &&
|
||||
!i.SpawnedInOutpost &&
|
||||
(i.ContainedItems == null || i.ContainedItems.None() || i.ContainedItems.All(ci => soldEntities.Any(se => se.Item == ci))) &&
|
||||
i.Condition >= 0.9f * i.MaxCondition && soldEntities.None(se => se.Item == i));
|
||||
(i.Condition >= 0.9f * i.MaxCondition || i.Prefab.AllowSellingWhenBroken) && soldEntities.None(se => se.Item == i));
|
||||
|
||||
// Prevent selling items in equipment slots
|
||||
var slots = new List<InvSlotType>() { InvSlotType.Head, InvSlotType.InnerClothes, InvSlotType.OuterClothes, InvSlotType.Headset, InvSlotType.Card };
|
||||
foreach (InvSlotType slot in slots)
|
||||
var equipmentSlots = new List<InvSlotType>() { InvSlotType.Head, InvSlotType.InnerClothes, InvSlotType.OuterClothes, InvSlotType.Headset, InvSlotType.Card };
|
||||
foreach (InvSlotType slot in equipmentSlots)
|
||||
{
|
||||
var index = character.Inventory.FindLimbSlot(slot);
|
||||
if (character.Inventory.Items[index] is Item item)
|
||||
@@ -69,18 +69,27 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
// Prevent selling items contained in certain equipped items (like battery cell in equipped headset or oxygen tank in equipped diving mask)
|
||||
slots = new List<InvSlotType>() { InvSlotType.Head, InvSlotType.OuterClothes, InvSlotType.Headset };
|
||||
foreach (InvSlotType slot in slots)
|
||||
// Prevent selling items contained inside equipped items
|
||||
foreach (InvSlotType slot in equipmentSlots)
|
||||
{
|
||||
var index = character.Inventory.FindLimbSlot(slot);
|
||||
if (character.Inventory.Items[index] is Item item &&
|
||||
item.ContainedItems != null && item.AllowedSlots.Contains(InvSlotType.Any))
|
||||
{
|
||||
foreach (Item containedItem in item.ContainedItems)
|
||||
RemoveContainedFromSellables(item);
|
||||
}
|
||||
}
|
||||
|
||||
void RemoveContainedFromSellables(Item item)
|
||||
{
|
||||
foreach (Item containedItem in item.ContainedItems)
|
||||
{
|
||||
if (containedItem == null) { continue; }
|
||||
if (containedItem.ContainedItems != null)
|
||||
{
|
||||
sellables.Remove(containedItem);
|
||||
RemoveContainedFromSellables(containedItem);
|
||||
}
|
||||
sellables.Remove(containedItem);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace Barotrauma
|
||||
private GUIListBox crewList;
|
||||
private GUIButton commandButton, toggleCrewButton;
|
||||
private float crewListOpenState;
|
||||
private bool toggleCrewListOpen = true;
|
||||
private bool _isCrewMenuOpen = true;
|
||||
private Point crewListEntrySize;
|
||||
|
||||
private GUIFrame contextMenu;
|
||||
@@ -42,16 +42,26 @@ namespace Barotrauma
|
||||
|
||||
public bool AllowCharacterSwitch = true;
|
||||
|
||||
public bool ToggleCrewListOpen
|
||||
/// <summary>
|
||||
/// This property stores the preference in settings. Don't use for automatic logic.
|
||||
/// Use AutoShowCrewList(), AutoHideCrewList(), and ResetCrewList().
|
||||
/// </summary>
|
||||
public bool IsCrewMenuOpen
|
||||
{
|
||||
get { return toggleCrewListOpen; }
|
||||
get { return _isCrewMenuOpen; }
|
||||
set
|
||||
{
|
||||
if (toggleCrewListOpen == value) { return; }
|
||||
toggleCrewListOpen = GameMain.Config.CrewMenuOpen = value;
|
||||
if (_isCrewMenuOpen == value) { return; }
|
||||
_isCrewMenuOpen = GameMain.Config.CrewMenuOpen = value;
|
||||
}
|
||||
}
|
||||
|
||||
public bool AutoShowCrewList() => _isCrewMenuOpen = true;
|
||||
|
||||
public void AutoHideCrewList() => _isCrewMenuOpen = false;
|
||||
|
||||
public void ResetCrewList() => _isCrewMenuOpen = GameMain.Config.CrewMenuOpen;
|
||||
|
||||
const float CommandNodeAnimDuration = 0.2f;
|
||||
|
||||
public List<GUIButton> OrderOptionButtons = new List<GUIButton>();
|
||||
@@ -139,7 +149,7 @@ namespace Barotrauma
|
||||
{
|
||||
OnClicked = (GUIButton btn, object userdata) =>
|
||||
{
|
||||
ToggleCrewListOpen = !ToggleCrewListOpen;
|
||||
IsCrewMenuOpen = !IsCrewMenuOpen;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@@ -286,7 +296,7 @@ namespace Barotrauma
|
||||
|
||||
screenResolution = new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight);
|
||||
prevUIScale = GUI.Scale;
|
||||
ToggleCrewListOpen = GameMain.Config.CrewMenuOpen;
|
||||
_isCrewMenuOpen = GameMain.Config.CrewMenuOpen;
|
||||
dismissedOrderPrefab ??= Order.GetPrefab("dismissed");
|
||||
}
|
||||
|
||||
@@ -318,7 +328,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (character == null)
|
||||
{
|
||||
DebugConsole.ThrowError("Tried to remove a null character from CrewManager.\n" + Environment.StackTrace);
|
||||
DebugConsole.ThrowError("Tried to remove a null character from CrewManager.\n" + Environment.StackTrace.CleanupStackTrace());
|
||||
return;
|
||||
}
|
||||
characters.Remove(character);
|
||||
@@ -567,7 +577,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (!IsSinglePlayer)
|
||||
{
|
||||
DebugConsole.ThrowError("Cannot add messages to single player chat box in multiplayer mode!\n" + Environment.StackTrace);
|
||||
DebugConsole.ThrowError("Cannot add messages to single player chat box in multiplayer mode!\n" + Environment.StackTrace.CleanupStackTrace());
|
||||
return;
|
||||
}
|
||||
if (string.IsNullOrEmpty(text)) { return; }
|
||||
@@ -583,7 +593,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (!IsSinglePlayer)
|
||||
{
|
||||
DebugConsole.ThrowError("Cannot add messages to single player chat box in multiplayer mode!\n" + Environment.StackTrace);
|
||||
DebugConsole.ThrowError("Cannot add messages to single player chat box in multiplayer mode!\n" + Environment.StackTrace.CleanupStackTrace());
|
||||
return;
|
||||
}
|
||||
if (string.IsNullOrEmpty(message.Text)) { return; }
|
||||
@@ -675,8 +685,7 @@ namespace Barotrauma
|
||||
AddOrder(new Order(order.Prefab ?? order, hull, null, orderGiver), order.FadeOutTime);
|
||||
if (IsSinglePlayer)
|
||||
{
|
||||
orderGiver.Speak(
|
||||
order.GetChatMessage("", hull.DisplayName, givingOrderToSelf: character == orderGiver), ChatMessageType.Order);
|
||||
orderGiver.Speak(order.GetChatMessage("", hull.DisplayName, givingOrderToSelf: character == orderGiver), ChatMessageType.Order);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -692,12 +701,11 @@ namespace Barotrauma
|
||||
if (IsSinglePlayer)
|
||||
{
|
||||
character.SetOrder(order, option, orderGiver, speak: orderGiver != character);
|
||||
orderGiver?.Speak(
|
||||
order.GetChatMessage(character.Name, orderGiver.CurrentHull?.DisplayName, givingOrderToSelf: character == orderGiver, orderOption: option), null);
|
||||
orderGiver?.Speak(order.GetChatMessage(character.Name, orderGiver.CurrentHull?.DisplayName, givingOrderToSelf: character == orderGiver, orderOption: option), null);
|
||||
}
|
||||
else if (orderGiver != null)
|
||||
{
|
||||
OrderChatMessage msg = new OrderChatMessage(order, option, order?.TargetEntity ?? order?.TargetItemComponent?.Item, character, orderGiver);
|
||||
OrderChatMessage msg = new OrderChatMessage(order, option, order?.TargetSpatialEntity ?? order?.TargetItemComponent?.Item as ISpatialEntity, character, orderGiver);
|
||||
GameMain.Client?.SendChatMessage(msg);
|
||||
}
|
||||
}
|
||||
@@ -1290,7 +1298,7 @@ namespace Barotrauma
|
||||
{
|
||||
CreateCommandUI(HUDLayoutSettings.BottomRightInfoArea.Contains(PlayerInput.MousePosition) ? Character.Controlled : GUI.MouseOn?.UserData as Character);
|
||||
}
|
||||
GUI.PlayUISound(GUISoundType.PopupMenu);
|
||||
SoundPlayer.PlayUISound(GUISoundType.PopupMenu);
|
||||
clicklessSelectionActive = isOpeningClick = true;
|
||||
}
|
||||
|
||||
@@ -1524,14 +1532,15 @@ namespace Barotrauma
|
||||
new Vector2(-crewArea.Rect.Width - HUDLayoutSettings.Padding, 0.0f),
|
||||
Vector2.Zero,
|
||||
crewListOpenState).ToPoint();
|
||||
crewListOpenState = ToggleCrewListOpen ?
|
||||
|
||||
crewListOpenState = IsCrewMenuOpen ?
|
||||
Math.Min(crewListOpenState + deltaTime * 2.0f, 1.0f) :
|
||||
Math.Max(crewListOpenState - deltaTime * 2.0f, 0.0f);
|
||||
|
||||
if (GUI.KeyboardDispatcher.Subscriber == null && PlayerInput.KeyHit(InputType.CrewOrders))
|
||||
{
|
||||
GUI.PlayUISound(GUISoundType.PopupMenu);
|
||||
ToggleCrewListOpen = !ToggleCrewListOpen;
|
||||
SoundPlayer.PlayUISound(GUISoundType.PopupMenu);
|
||||
IsCrewMenuOpen = !IsCrewMenuOpen;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1589,8 +1598,8 @@ namespace Barotrauma
|
||||
private Hull hullContext;
|
||||
private bool isContextual;
|
||||
private readonly List<Order> contextualOrders = new List<Order>();
|
||||
private Point shortcutCenterNodeOffset;
|
||||
private const int maxShortcutNodeCount = 4;
|
||||
private Point shorcutCenterNodeOffset;
|
||||
private const int maxShortCutNodeCount = 4;
|
||||
|
||||
private bool WasCommandInterfaceDisabledThisUpdate { get; set; }
|
||||
private bool CanIssueOrders
|
||||
@@ -1773,7 +1782,7 @@ namespace Barotrauma
|
||||
returnNodeMargin = returnNodeSize.X * 0.5f;
|
||||
|
||||
nodeDistance = (int)(150 * GUI.Scale);
|
||||
shortcutCenterNodeOffset = new Point(0, (int)(1.25f * nodeDistance));
|
||||
shorcutCenterNodeOffset = new Point(0, (int)(1.25f * nodeDistance));
|
||||
}
|
||||
|
||||
private List<OrderCategory> GetAvailableCategories()
|
||||
@@ -2057,7 +2066,7 @@ namespace Barotrauma
|
||||
|
||||
shortcutNodes.Clear();
|
||||
|
||||
if (shortcutNodes.Count < maxShortcutNodeCount && sub.GetItems(false).Find(i => i.HasTag("reactor") && !i.NonInteractable)?.GetComponent<Reactor>() is Reactor reactor)
|
||||
if (shortcutNodes.Count < maxShortCutNodeCount && 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
|
||||
@@ -2075,7 +2084,7 @@ namespace Barotrauma
|
||||
// TODO: Reconsider the conditions as bot captain can have the nav term selected without operating it
|
||||
// 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 < maxShortcutNodeCount && (Character.Controlled == null || Character.Controlled.Info?.Job?.Prefab != JobPrefab.Get("captain")) &&
|
||||
if (shortcutNodes.Count < maxShortCutNodeCount && (Character.Controlled == null || Character.Controlled.Info?.Job?.Prefab != JobPrefab.Get("captain")) &&
|
||||
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)
|
||||
{
|
||||
@@ -2085,7 +2094,7 @@ namespace Barotrauma
|
||||
|
||||
// If player is not a security officer AND invaders are reported
|
||||
// --> Create shorcut node for Fight Intruders order
|
||||
if (shortcutNodes.Count < maxShortcutNodeCount && (Character.Controlled == null || Character.Controlled.Info?.Job?.Prefab != JobPrefab.Get("securityofficer")) &&
|
||||
if (shortcutNodes.Count < maxShortCutNodeCount && (Character.Controlled == null || Character.Controlled.Info?.Job?.Prefab != JobPrefab.Get("securityofficer")) &&
|
||||
(Order.GetPrefab("reportintruders") is Order reportIntruders && ActiveOrders.Any(o => o.First.Prefab == reportIntruders)))
|
||||
{
|
||||
shortcutNodes.Add(
|
||||
@@ -2094,7 +2103,7 @@ namespace Barotrauma
|
||||
|
||||
// If player is not a mechanic AND a breach has been reported
|
||||
// --> Create shorcut node for Fix Leaks order
|
||||
if (shortcutNodes.Count < maxShortcutNodeCount && (Character.Controlled == null || Character.Controlled.Info?.Job?.Prefab != JobPrefab.Get("mechanic")) &&
|
||||
if (shortcutNodes.Count < maxShortCutNodeCount && (Character.Controlled == null || Character.Controlled.Info?.Job?.Prefab != JobPrefab.Get("mechanic")) &&
|
||||
(Order.GetPrefab("reportbreach") is Order reportBreach && ActiveOrders.Any(o => o.First.Prefab == reportBreach)))
|
||||
{
|
||||
shortcutNodes.Add(
|
||||
@@ -2103,7 +2112,7 @@ namespace Barotrauma
|
||||
|
||||
// If player is not an engineer AND broken devices have been reported
|
||||
// --> Create shortcut node for Repair Damaged Systems order
|
||||
if (shortcutNodes.Count < maxShortcutNodeCount && (Character.Controlled == null || Character.Controlled.Info?.Job?.Prefab != JobPrefab.Get("engineer")) &&
|
||||
if (shortcutNodes.Count < maxShortCutNodeCount && (Character.Controlled == null || Character.Controlled.Info?.Job?.Prefab != JobPrefab.Get("engineer")) &&
|
||||
(Order.GetPrefab("reportbrokendevices") is Order reportBrokenDevices && ActiveOrders.Any(o => o.First.Prefab == reportBrokenDevices)))
|
||||
{
|
||||
shortcutNodes.Add(
|
||||
@@ -2112,13 +2121,13 @@ namespace Barotrauma
|
||||
|
||||
// If fire is reported
|
||||
// --> Create shortcut node for Extinguish Fires order
|
||||
if (shortcutNodes.Count < maxShortcutNodeCount && ActiveOrders.Any(o=> o.First.Prefab == Order.GetPrefab("reportfire")))
|
||||
if (shortcutNodes.Count < maxShortCutNodeCount && ActiveOrders.Any(o=> o.First.Prefab == Order.GetPrefab("reportfire")))
|
||||
{
|
||||
shortcutNodes.Add(
|
||||
CreateOrderNode(shortcutNodeSize, null, Point.Zero, Order.GetPrefab("extinguishfires"), -1));
|
||||
}
|
||||
|
||||
if (shortcutNodes.Count < maxShortcutNodeCount && characterContext?.Info?.Job?.Prefab?.AppropriateOrders != null)
|
||||
if (shortcutNodes.Count < maxShortCutNodeCount && characterContext?.Info?.Job?.Prefab?.AppropriateOrders != null)
|
||||
{
|
||||
foreach (string orderIdentifier in characterContext.Info.Job.Prefab.AppropriateOrders)
|
||||
{
|
||||
@@ -2131,11 +2140,17 @@ namespace Barotrauma
|
||||
{
|
||||
shortcutNodes.Add(CreateOrderNode(shortcutNodeSize, null, Point.Zero, orderPrefab, -1));
|
||||
}
|
||||
if (shortcutNodes.Count >= maxShortcutNodeCount) { break; }
|
||||
if (shortcutNodes.Count >= maxShortCutNodeCount) { break; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (shortcutNodes.Count < maxShortCutNodeCount && characterContext != null && !characterContext.IsDismissed)
|
||||
{
|
||||
shortcutNodes.Add(
|
||||
CreateOrderNode(shortcutNodeSize, null, Point.Zero, dismissedOrderPrefab, -1));
|
||||
}
|
||||
|
||||
if (shortcutNodes.Count < 1) { return; }
|
||||
|
||||
shortcutCenterNode = new GUIButton(
|
||||
@@ -2148,7 +2163,7 @@ namespace Barotrauma
|
||||
c.PressedColor = c.Color;
|
||||
c.SelectedColor = c.Color;
|
||||
}
|
||||
shortcutCenterNode.RectTransform.MoveOverTime(shortcutCenterNodeOffset, CommandNodeAnimDuration);
|
||||
shortcutCenterNode.RectTransform.MoveOverTime(shorcutCenterNodeOffset, CommandNodeAnimDuration);
|
||||
|
||||
var nodeCountForCalculations = shortcutNodes.Count * 2 + 2;
|
||||
var offsets = MathUtils.GetPointsOnCircumference(Vector2.Zero, 0.75f * nodeDistance, nodeCountForCalculations);
|
||||
@@ -2156,7 +2171,7 @@ namespace Barotrauma
|
||||
for (int i = 0; i < shortcutNodes.Count; i++)
|
||||
{
|
||||
shortcutNodes[i].RectTransform.Parent = commandFrame.RectTransform;
|
||||
shortcutNodes[i].RectTransform.MoveOverTime(shortcutCenterNodeOffset + offsets[firstOffsetIndex - i].ToPoint(), CommandNodeAnimDuration);
|
||||
shortcutNodes[i].RectTransform.MoveOverTime(shorcutCenterNodeOffset + offsets[firstOffsetIndex - i].ToPoint(), CommandNodeAnimDuration);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2171,7 +2186,7 @@ namespace Barotrauma
|
||||
{
|
||||
order = orders[i];
|
||||
disableNode = !CanSomeoneHearCharacter() ||
|
||||
(order.MustSetTarget && (order.ItemComponentType != null || order.ItemIdentifiers.Length > 0) && order.GetMatchingItems(true).None());
|
||||
(order.MustSetTarget && (order.ItemComponentType != null || order.TargetItems.Length > 0) && order.GetMatchingItems(true).None());
|
||||
optionNodes.Add(new Tuple<GUIComponent, Keys>(
|
||||
CreateOrderNode(nodeSize, commandFrame.RectTransform, offsets[i].ToPoint(), order, (i + 1) % 10, disableNode: disableNode, checkIfOrderCanBeHeard: false),
|
||||
!disableNode ? Keys.D0 + (i + 1) % 10 : Keys.None));
|
||||
@@ -2190,13 +2205,14 @@ namespace Barotrauma
|
||||
// Check if targeting an item or a hull
|
||||
if (itemContext != null && !itemContext.NonInteractable)
|
||||
{
|
||||
ItemComponent targetComponent;
|
||||
foreach (Order p in Order.PrefabList)
|
||||
{
|
||||
if ((p.ItemIdentifiers.Length > 0 && (p.ItemIdentifiers.Contains(itemContext.Prefab.Identifier) || itemContext.HasTag(p.ItemIdentifiers))) ||
|
||||
(p.ItemComponentType != null && itemContext.Components.Any(c => c?.GetType() == p.ItemComponentType)))
|
||||
targetComponent = null;
|
||||
if ((p.TargetItems.Length > 0 && (p.TargetItems.Contains(itemContext.Prefab.Identifier) || itemContext.HasTag(p.TargetItems))) ||
|
||||
p.TryGetTargetItemComponent(itemContext, out targetComponent))
|
||||
{
|
||||
contextualOrders.Add(p.HasOptions ? p :
|
||||
new Order(p, itemContext, itemContext.Components.FirstOrDefault(c => c?.GetType() == p.ItemComponentType), Character.Controlled));
|
||||
contextualOrders.Add(p.HasOptions ? p : new Order(p, itemContext, targetComponent, Character.Controlled));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2205,8 +2221,8 @@ namespace Barotrauma
|
||||
var operateWeaponsPrefab = Order.GetPrefab(orderIdentifier);
|
||||
if (contextualOrders.None(o => o.Identifier.Equals(orderIdentifier)) && itemContext.Components.Any(c => c is Controller))
|
||||
{
|
||||
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));
|
||||
var turret = itemContext.GetConnectedComponents<Turret>().FirstOrDefault(c => operateWeaponsPrefab.TargetItems.Contains(c.Item.Prefab.Identifier)) ??
|
||||
itemContext.GetConnectedComponents<Turret>(recursive: true).FirstOrDefault(c => operateWeaponsPrefab.TargetItems.Contains(c.Item.Prefab.Identifier));
|
||||
if (turret != null) { contextualOrders.Add(new Order(operateWeaponsPrefab, turret.Item, turret, Character.Controlled)); }
|
||||
}
|
||||
|
||||
@@ -2214,14 +2230,17 @@ namespace Barotrauma
|
||||
orderIdentifier = "repairsystems";
|
||||
if (contextualOrders.None(o => o.Identifier.Equals(orderIdentifier)) && itemContext.Repairables.Any(r => itemContext.ConditionPercentage < r.RepairThreshold))
|
||||
{
|
||||
contextualOrders.Add(new Order(Order.GetPrefab(orderIdentifier), itemContext, null, Character.Controlled));
|
||||
if (itemContext.Repairables.Any(r => r != null && r.requiredSkills.Any(s => s != null && s.Identifier.Equals("electrical"))))
|
||||
{
|
||||
contextualOrders.Add(new Order(Order.GetPrefab("repairelectrical"), itemContext, null, Character.Controlled));
|
||||
contextualOrders.Add(new Order(Order.GetPrefab("repairelectrical"), itemContext, targetItem: null, Character.Controlled));
|
||||
}
|
||||
else if (itemContext.Repairables.Any(r => r != null && r.requiredSkills.Any(s => s != null && s.Identifier.Equals("mechanical"))))
|
||||
{
|
||||
contextualOrders.Add(new Order(Order.GetPrefab("repairmechanical"), itemContext, null, Character.Controlled));
|
||||
contextualOrders.Add(new Order(Order.GetPrefab("repairmechanical"), itemContext, targetItem: null, Character.Controlled));
|
||||
}
|
||||
else
|
||||
{
|
||||
contextualOrders.Add(new Order(Order.GetPrefab(orderIdentifier), itemContext, targetItem: null, Character.Controlled));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2235,23 +2254,29 @@ namespace Barotrauma
|
||||
|
||||
if (contextualOrders.None())
|
||||
{
|
||||
// If there are other crew members alive and there are no other contextual orders available, show the 'wait' order
|
||||
orderIdentifier = "wait";
|
||||
if (contextualOrders.None(o => o.Identifier.Equals(orderIdentifier)) && characters.Any(c => c != Character.Controlled))
|
||||
orderIdentifier = "cleanupitems";
|
||||
if (contextualOrders.None(o => o.Identifier.Equals(orderIdentifier)) && AIObjectiveCleanupItems.IsValidTarget(itemContext, Character.Controlled))
|
||||
{
|
||||
contextualOrders.Add(new Order(Order.GetPrefab(orderIdentifier), itemContext, null, Character.Controlled));
|
||||
contextualOrders.Add(new Order(Order.GetPrefab(orderIdentifier), itemContext, targetItem: null, Character.Controlled));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(hullContext != null)
|
||||
else if (hullContext != null)
|
||||
{
|
||||
contextualOrders.Add(new Order(Order.GetPrefab("fixleaks"), hullContext, null, Character.Controlled));
|
||||
contextualOrders.Add(new Order(Order.GetPrefab("fixleaks"), hullContext, targetItem: null, Character.Controlled));
|
||||
}
|
||||
|
||||
if (characters.Any(c => c != Character.Controlled))
|
||||
if (contextualOrders.None(o => o.Category != OrderCategory.Movement))
|
||||
{
|
||||
// Show 'follow' order only when there are no orders of other categories available
|
||||
if (contextualOrders.None(o => o.Category != OrderCategory.Movement))
|
||||
orderIdentifier = "wait";
|
||||
if (contextualOrders.None(o => o.Identifier.Equals(orderIdentifier)))
|
||||
{
|
||||
Vector2 position = GameMain.GameScreen.Cam.ScreenToWorld(PlayerInput.MousePosition);
|
||||
Hull hull = Hull.FindHull(position, guess: Character.Controlled?.CurrentHull);
|
||||
contextualOrders.Add(new Order(Order.GetPrefab(orderIdentifier), new OrderTarget(position, hull), Character.Controlled));
|
||||
}
|
||||
|
||||
if (characters.Any(c => c != Character.Controlled))
|
||||
{
|
||||
orderIdentifier = "follow";
|
||||
if (contextualOrders.None(o => o.Identifier.Equals(orderIdentifier)))
|
||||
@@ -2259,14 +2284,14 @@ namespace Barotrauma
|
||||
contextualOrders.Add(Order.GetPrefab(orderIdentifier));
|
||||
}
|
||||
}
|
||||
|
||||
// Show 'dismissed' order only when there are crew members with active orders
|
||||
orderIdentifier = "dismissed";
|
||||
if (contextualOrders.None(o => o.Identifier.Equals(orderIdentifier)) &&
|
||||
characters.Any(c => c.CurrentOrder != null && !c.CurrentOrder.Identifier.Equals(orderIdentifier)))
|
||||
{
|
||||
contextualOrders.Add(Order.GetPrefab(orderIdentifier));
|
||||
}
|
||||
}
|
||||
|
||||
// Show 'dismiss' order only when there are crew members with active orders
|
||||
orderIdentifier = "dismissed";
|
||||
if (contextualOrders.None(o => o.Identifier.Equals(orderIdentifier)) &&
|
||||
characters.Any(c => c.CurrentOrder != null && !c.CurrentOrder.Identifier.Equals(orderIdentifier)))
|
||||
{
|
||||
contextualOrders.Add(Order.GetPrefab(orderIdentifier));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2280,17 +2305,19 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: there's duplicate logic here and above -> would be better to refactor so that the conditions are only defined in one place
|
||||
public static bool DoesItemHaveContextualOrders(Item item)
|
||||
{
|
||||
if (Order.PrefabList.Any(o => o.ItemIdentifiers.Length > 0 && o.ItemIdentifiers.Contains(item.Prefab.Identifier))) { return true; }
|
||||
if (Order.PrefabList.Any(o => item.HasTag(o.ItemIdentifiers))) { return true; }
|
||||
if (Order.PrefabList.Any(o => o.ItemComponentType != null && item.Components.Any(c => c?.GetType() == o.ItemComponentType))) { return true; }
|
||||
if (Order.PrefabList.Any(o => o.TargetItems.Length > 0 && o.TargetItems.Contains(item.Prefab.Identifier))) { return true; }
|
||||
if (Order.PrefabList.Any(o => item.HasTag(o.TargetItems))) { return true; }
|
||||
if (Order.PrefabList.Any(o => o.TryGetTargetItemComponent(item, out _))) { return true; }
|
||||
if (AIObjectiveCleanupItems.IsValidTarget(item, Character.Controlled)) { return true; }
|
||||
|
||||
if (item.Repairables.Any(r => item.ConditionPercentage < r.RepairThreshold)) { return true; }
|
||||
var operateWeaponsPrefab = Order.GetPrefab("operateweapons");
|
||||
return item.Components.Any(c => c is Controller) &&
|
||||
(item.GetConnectedComponents<Turret>().Any(c => operateWeaponsPrefab.ItemIdentifiers.Contains(c.Item.Prefab.Identifier)) ||
|
||||
item.GetConnectedComponents<Turret>(recursive: true).Any(c => operateWeaponsPrefab.ItemIdentifiers.Contains(c.Item.Prefab.Identifier)));
|
||||
(item.GetConnectedComponents<Turret>().Any(c => operateWeaponsPrefab.TargetItems.Contains(c.Item.Prefab.Identifier)) ||
|
||||
item.GetConnectedComponents<Turret>(recursive: true).Any(c => operateWeaponsPrefab.TargetItems.Contains(c.Item.Prefab.Identifier)));
|
||||
}
|
||||
|
||||
private GUIButton CreateOrderNode(Point size, RectTransform parent, Point offset, Order order, int hotkey, bool disableNode = false, bool checkIfOrderCanBeHeard = true)
|
||||
@@ -2462,7 +2489,7 @@ namespace Barotrauma
|
||||
style: "GUITextBox")
|
||||
{
|
||||
UserData = new Tuple<Order, string>(
|
||||
item == null ? order : new Order(order, item, item.Components.FirstOrDefault(ic => ic.GetType() == order.ItemComponentType)),
|
||||
item == null ? order : new Order(order, item, order.GetTargetItemComponent(item)),
|
||||
order.Options[i]),
|
||||
Font = GUI.SmallFont,
|
||||
OnClicked = (_, userData) =>
|
||||
@@ -2479,7 +2506,7 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
var userData = new Tuple<Order, string>(item == null ? order : new Order(order, item, item.Components.FirstOrDefault(ic => ic.GetType() == order.ItemComponentType)), "");
|
||||
var userData = new Tuple<Order, string>(item == null ? order : new Order(order, item, order.GetTargetItemComponent(item)), "");
|
||||
optionElement = new GUIButton(
|
||||
new RectTransform(
|
||||
new Point((int)(50 * GUI.Scale)),
|
||||
@@ -2528,7 +2555,7 @@ namespace Barotrauma
|
||||
var item = itemContext != null ?
|
||||
(order.UseController ? itemContext.GetConnectedComponents<Turret>().FirstOrDefault()?.Item ?? itemContext.GetConnectedComponents<Turret>(recursive: true).FirstOrDefault()?.Item : itemContext) :
|
||||
(matchingItems.Count > 0 ? matchingItems[0] : null);
|
||||
var o = item == null || !order.IsPrefab ? order : new Order(order, item, item.Components.FirstOrDefault(ic => ic.GetType() == order.ItemComponentType));
|
||||
var o = item == null || !order.IsPrefab ? order : new Order(order, item, order.GetTargetItemComponent(item));
|
||||
var offsets = MathUtils.GetPointsOnCircumference(Vector2.Zero, nodeDistance,
|
||||
GetCircumferencePointCount(order.Options.Length),
|
||||
GetFirstNodeAngle(order.Options.Length));
|
||||
@@ -2754,7 +2781,7 @@ namespace Barotrauma
|
||||
|
||||
// Order icon
|
||||
GUIImage orderIcon;
|
||||
if (character.CurrentOrder != null && !character.CurrentOrder.Identifier.Equals("dismissed"))
|
||||
if (!character.IsDismissed)
|
||||
{
|
||||
orderIcon = new GUIImage(new RectTransform(new Vector2(1.2f), node.RectTransform, anchor: Anchor.Center), character.CurrentOrder.SymbolSprite, scaleToFit: true);
|
||||
var tooltip = character.CurrentOrder.Name;
|
||||
@@ -2910,7 +2937,7 @@ namespace Barotrauma
|
||||
{
|
||||
bearing = GetBearing(
|
||||
centerNode.RectTransform.AnimTargetPos.ToVector2(),
|
||||
shortcutCenterNodeOffset.ToVector2());
|
||||
shorcutCenterNodeOffset.ToVector2());
|
||||
}
|
||||
return nodeCount % 2 > 0 ?
|
||||
MathHelper.ToRadians(bearing + 360.0f / nodeCount / 2) :
|
||||
@@ -2997,8 +3024,7 @@ namespace Barotrauma
|
||||
#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 characters.FindAll(c => !c.IsDismissed).OrderBy(c => c.Info.DisplayName).ToList();
|
||||
}
|
||||
return GetCharactersSortedForOrder(order, order.Identifier != "follow").ToList();
|
||||
}
|
||||
@@ -3006,16 +3032,16 @@ namespace Barotrauma
|
||||
private IEnumerable<Character> GetCharactersSortedForOrder(Order order, bool includeSelf)
|
||||
{
|
||||
return characters.FindAll(c => Character.Controlled == null || ((includeSelf || c != Character.Controlled) && c.TeamID == Character.Controlled.TeamID))
|
||||
// 1. Prioritize those who are already ordered to operate the item target of the new 'operate' order
|
||||
.OrderByDescending(c => c.CurrentOrder != null && order.Category == OrderCategory.Operate && c.CurrentOrder.Identifier == order.Identifier && c.CurrentOrder.TargetEntity == order.TargetEntity)
|
||||
// 2. Prioritize those who are currently dismissed
|
||||
.ThenByDescending(c => c.CurrentOrder == null || c.CurrentOrder.Identifier == dismissedOrderPrefab.Identifier)
|
||||
// 3. Prioritize those who are not currently assigned with the same type of order (for example, when giving a 'Fix Leak' order, prioritize those who have a different order)
|
||||
.ThenBy(c => c.CurrentOrder != null && c.CurrentOrder.Identifier == order.Identifier && c.CurrentOrder.TargetEntity == order.TargetEntity)
|
||||
// 4. Prioritize those with the appropriate job for the order
|
||||
// 1. Prioritize those who are on the same submarine than the controlled character
|
||||
.OrderByDescending(c => Character.Controlled == null || c.Submarine == Character.Controlled.Submarine)
|
||||
// 2. Prioritize those who are already ordered to operate the item target of the new 'operate' order, or given the same maintenance order as now issued
|
||||
.ThenByDescending(c => c.CurrentOrder != null && c.CurrentOrder.Identifier == order.Identifier && (order.Category == OrderCategory.Maintenance || (order.Category == OrderCategory.Operate && c.CurrentOrder.TargetSpatialEntity == order.TargetSpatialEntity)))
|
||||
// 3. Prioritize those with the appropriate job for the order
|
||||
.ThenByDescending(c => order.HasAppropriateJob(c))
|
||||
// 5. Prioritize those with the lowest "weight" of the current order
|
||||
.ThenBy(c => c.CurrentOrder?.Weight)
|
||||
// 4. Prioritize bots over player controlled characters
|
||||
.ThenByDescending(c => c.IsBot)
|
||||
// 5. Use the priority value of the current objective
|
||||
.ThenBy(c => c.AIController?.ObjectiveManager.CurrentObjective?.Priority)
|
||||
// 6. Prioritize those with the best skill for the order
|
||||
.ThenByDescending(c => c.GetSkillLevel(order.AppropriateSkill));
|
||||
}
|
||||
|
||||
@@ -413,8 +413,6 @@ namespace Barotrauma
|
||||
|
||||
//--------------------------------------
|
||||
|
||||
bool save = false;
|
||||
|
||||
if (success)
|
||||
{
|
||||
if (leavingSub != Submarine.MainSub && !leavingSub.DockedTo.Contains(Submarine.MainSub))
|
||||
|
||||
@@ -161,7 +161,7 @@ namespace Barotrauma.Tutorials
|
||||
do { yield return null; } while (!captain_medicObjectiveSensor.MotionDetected);
|
||||
GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(captain_medic.Info.DisplayName, TextManager.Get("Captain.Radio.Medic"), ChatMessageType.Radio, null);
|
||||
yield return new WaitForSeconds(2f, false);
|
||||
GameMain.GameSession.CrewManager.ToggleCrewListOpen = true;
|
||||
GameMain.GameSession.CrewManager.AutoShowCrewList();
|
||||
GameMain.GameSession.CrewManager.AddCharacter(captain_medic);
|
||||
TriggerTutorialSegment(0, GameMain.Config.KeyBindText(InputType.Command));
|
||||
do
|
||||
|
||||
@@ -275,7 +275,7 @@ namespace Barotrauma.Tutorials
|
||||
GameMain.GameSession.CrewManager.AllowCharacterSwitch = false;
|
||||
GameMain.GameSession.CrewManager.AddCharacter(doctor);
|
||||
GameMain.GameSession.CrewManager.AddCharacter(patient1);
|
||||
GameMain.GameSession.CrewManager.ToggleCrewListOpen = true;
|
||||
GameMain.GameSession.CrewManager.AutoShowCrewList();
|
||||
patient1.CharacterHealth.UseHealthWindow = false;
|
||||
|
||||
yield return new WaitForSeconds(3.0f, false);
|
||||
|
||||
@@ -87,9 +87,9 @@ namespace Barotrauma.Tutorials
|
||||
radioSpeakerName = TextManager.Get("Tutorial.Radio.Speaker");
|
||||
engineer = Character.Controlled;
|
||||
|
||||
var toolbox = FindOrGiveItem(engineer, "toolbox");
|
||||
toolbox.Unequip(engineer);
|
||||
engineer.Inventory.RemoveItem(toolbox);
|
||||
var toolbelt = FindOrGiveItem(engineer, "toolbelt");
|
||||
toolbelt.Unequip(engineer);
|
||||
engineer.Inventory.RemoveItem(toolbelt);
|
||||
|
||||
var repairOrder = Order.GetPrefab("repairsystems");
|
||||
engineer_repairIcon = repairOrder.SymbolSprite;
|
||||
|
||||
@@ -87,9 +87,9 @@ namespace Barotrauma.Tutorials
|
||||
radioSpeakerName = TextManager.Get("Tutorial.Radio.Speaker");
|
||||
mechanic = Character.Controlled;
|
||||
|
||||
var toolbox = FindOrGiveItem(mechanic, "toolbox");
|
||||
toolbox.Unequip(mechanic);
|
||||
mechanic.Inventory.RemoveItem(toolbox);
|
||||
var toolbelt = FindOrGiveItem(mechanic, "toolbelt");
|
||||
toolbelt.Unequip(mechanic);
|
||||
mechanic.Inventory.RemoveItem(toolbelt);
|
||||
|
||||
var crowbar = FindOrGiveItem(mechanic, "crowbar");
|
||||
crowbar.Unequip(mechanic);
|
||||
|
||||
@@ -584,8 +584,8 @@ namespace Barotrauma.Tutorials
|
||||
}
|
||||
|
||||
infoBlock.RectTransform.NonScaledSize = new Point(infoBlock.Rect.Width, (int)(infoContent.Children.Sum(c => c.Rect.Height + infoContent.AbsoluteSpacing) / infoContent.RectTransform.RelativeSize.Y));
|
||||
|
||||
GUI.PlayUISound(GUISoundType.UIMessage);
|
||||
|
||||
SoundPlayer.PlayUISound(GUISoundType.UIMessage);
|
||||
|
||||
return background;
|
||||
}
|
||||
|
||||
@@ -1149,7 +1149,7 @@ namespace Barotrauma
|
||||
catch (Exception e)
|
||||
{
|
||||
DebugConsole.ThrowError("Failed to set voice capture mode.", e);
|
||||
GameAnalyticsManager.AddErrorEventOnce("SetVoiceCaptureMode", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, "Failed to set voice capture mode. " + e.Message + "\n" + e.StackTrace);
|
||||
GameAnalyticsManager.AddErrorEventOnce("SetVoiceCaptureMode", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, "Failed to set voice capture mode. " + e.Message + "\n" + e.StackTrace.CleanupStackTrace());
|
||||
VoiceSetting = VoiceMode.Disabled;
|
||||
}
|
||||
|
||||
|
||||
@@ -51,6 +51,7 @@ namespace Barotrauma
|
||||
limbSlotIcons.Add(InvSlotType.LeftHand, new Sprite("Content/UI/InventoryUIAtlas.png", new Rectangle(634, 0, 128, 128)));
|
||||
limbSlotIcons.Add(InvSlotType.RightHand, new Sprite("Content/UI/InventoryUIAtlas.png", new Rectangle(762, 0, 128, 128)));
|
||||
limbSlotIcons.Add(InvSlotType.OuterClothes, new Sprite("Content/UI/MainIconsAtlas.png", new Rectangle(256 + margin, 128 + margin, 128 - margin * 2, 128 - margin * 2)));
|
||||
limbSlotIcons.Add(InvSlotType.Bag, new Sprite("Content/UI/MainIconsAtlas.png", new Rectangle(256 + margin, 128 + margin, 128 - margin * 2, 128 - margin * 2)));
|
||||
}
|
||||
return limbSlotIcons;
|
||||
}
|
||||
@@ -922,12 +923,14 @@ namespace Barotrauma
|
||||
if (slotItem == item)
|
||||
{
|
||||
slot.ShowBorderHighlight(GUI.Style.Red, 0.1f, 0.4f);
|
||||
GUI.PlayUISound(GUISoundType.PickItem);
|
||||
SoundPlayer.PlayUISound(GUISoundType.PickItem);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SubEditorScreen.StoreCommand(new AddOrDeleteCommand(new List<MapEntity> { item }, true));
|
||||
|
||||
item.Remove();
|
||||
return;
|
||||
}
|
||||
@@ -1065,7 +1068,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
draggingItem = null;
|
||||
GUI.PlayUISound(success ? GUISoundType.PickItem : GUISoundType.PickItemFail);
|
||||
SoundPlayer.PlayUISound(success ? GUISoundType.PickItem : GUISoundType.PickItemFail);
|
||||
}
|
||||
|
||||
public void DrawOwn(SpriteBatch spriteBatch)
|
||||
|
||||
@@ -261,7 +261,23 @@ namespace Barotrauma.Items.Components
|
||||
if (!isNetworkMessage || open != PredictedState)
|
||||
{
|
||||
StopPicking(null);
|
||||
PlaySound(forcedOpen ? ActionType.OnPicked : ActionType.OnUse);
|
||||
ActionType actionType = ActionType.OnUse;
|
||||
if (forcedOpen)
|
||||
{
|
||||
actionType = ActionType.OnPicked;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (open && HasSoundsOfType[(int)ActionType.OnOpen])
|
||||
{
|
||||
actionType = ActionType.OnOpen;
|
||||
}
|
||||
else if (!open && HasSoundsOfType[(int)ActionType.OnClose])
|
||||
{
|
||||
actionType = ActionType.OnClose;
|
||||
}
|
||||
}
|
||||
PlaySound(actionType);
|
||||
if (isOpen) { stuck = MathHelper.Clamp(stuck - StuckReductionOnOpen, 0.0f, 100.0f); }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -263,7 +263,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
for (int i = 0; i < targetSections.Count; i++)
|
||||
{
|
||||
targetHull.SetSectionColorOrStrength(targetSections[i], color, sizeAdjustedSprayStrength * deltaTime, true, false);
|
||||
targetHull.IncreaseSectionColorOrStrength(targetSections[i], color, sizeAdjustedSprayStrength * deltaTime, true, false);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -52,6 +52,8 @@ namespace Barotrauma.Items.Components
|
||||
get { return sounds.Count > 0; }
|
||||
}
|
||||
|
||||
public bool[] HasSoundsOfType { get { return hasSoundsOfType; } }
|
||||
|
||||
private readonly bool[] hasSoundsOfType;
|
||||
private readonly Dictionary<ActionType, List<ItemSound>> sounds;
|
||||
private Dictionary<ActionType, SoundSelectionMode> soundSelectionModes;
|
||||
@@ -191,6 +193,12 @@ namespace Barotrauma.Items.Components
|
||||
private ItemSound loopingSound;
|
||||
private SoundChannel loopingSoundChannel;
|
||||
private List<SoundChannel> playingOneshotSoundChannels = new List<SoundChannel>();
|
||||
public ItemComponent ReplacedBy;
|
||||
|
||||
public ItemComponent GetReplacementOrThis()
|
||||
{
|
||||
return ReplacedBy?.GetReplacementOrThis() ?? this;
|
||||
}
|
||||
|
||||
public void UpdateSounds()
|
||||
{
|
||||
|
||||
@@ -26,29 +26,17 @@ namespace Barotrauma.Items.Components
|
||||
if (isHUDsHidden == value) { return; }
|
||||
if (value == true)
|
||||
{
|
||||
ToggleCrewArea(false, storeOriginalState: true);
|
||||
GameMain.GameSession?.CrewManager?.AutoHideCrewList();
|
||||
ToggleChatBox(false, storeOriginalState: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
ToggleCrewArea(crewAreaOriginalState, storeOriginalState: false);
|
||||
GameMain.GameSession?.CrewManager?.ResetCrewList();
|
||||
ToggleChatBox(chatBoxOriginalState, storeOriginalState: false);
|
||||
}
|
||||
isHUDsHidden = value;
|
||||
}
|
||||
|
||||
private void ToggleCrewArea(bool value, bool storeOriginalState)
|
||||
{
|
||||
var crewManager = GameMain.GameSession?.CrewManager;
|
||||
if (crewManager == null) { return; }
|
||||
|
||||
if (storeOriginalState)
|
||||
{
|
||||
crewAreaOriginalState = crewManager.ToggleCrewListOpen;
|
||||
}
|
||||
crewManager.ToggleCrewListOpen = value;
|
||||
}
|
||||
|
||||
private void ToggleChatBox(bool value, bool storeOriginalState)
|
||||
{
|
||||
var crewManager = GameMain.GameSession?.CrewManager;
|
||||
|
||||
@@ -17,7 +17,16 @@ namespace Barotrauma.Items.Components
|
||||
private GUITickBox autoControlIndicator;
|
||||
|
||||
private List<Pair<Vector2, ParticleEmitter>> pumpOutEmitters = new List<Pair<Vector2, ParticleEmitter>>();
|
||||
private List<Pair<Vector2, ParticleEmitter>> pumpInEmitters = new List<Pair<Vector2, ParticleEmitter>>();
|
||||
private List<Pair<Vector2, ParticleEmitter>> pumpInEmitters = new List<Pair<Vector2, ParticleEmitter>>();
|
||||
|
||||
public float CurrentBrokenVolume
|
||||
{
|
||||
get
|
||||
{
|
||||
if (item.ConditionPercentage > 10.0f || !IsActive) { return 0.0f; }
|
||||
return (1.0f - item.ConditionPercentage / 10.0f) * 100.0f;
|
||||
}
|
||||
}
|
||||
|
||||
partial void InitProjSpecific(XElement element)
|
||||
{
|
||||
|
||||
@@ -284,6 +284,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
Enabled = false,
|
||||
Selected = AutoTemp,
|
||||
ClickSound = GUISoundType.UISwitch,
|
||||
OnClicked = (button, data) =>
|
||||
{
|
||||
AutoTemp = !AutoTemp;
|
||||
|
||||
@@ -181,6 +181,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
Selected = false,
|
||||
Enabled = true,
|
||||
ClickSound = GUISoundType.UISwitch,
|
||||
OnClicked = (button, data) =>
|
||||
{
|
||||
button.Selected = !button.Selected;
|
||||
|
||||
@@ -123,6 +123,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
Selected = autoPilot,
|
||||
Enabled = true,
|
||||
ClickSound = GUISoundType.UISwitch,
|
||||
OnClicked = (button, data) =>
|
||||
{
|
||||
button.Selected = !button.Selected;
|
||||
|
||||
@@ -535,6 +535,9 @@ namespace Barotrauma.Items.Components
|
||||
nodes = nodePositions.ToList();
|
||||
UpdateSections();
|
||||
Drawable = nodes.Any();
|
||||
IsActive =
|
||||
(connections[0] == null ^ connections[1] == null) &&
|
||||
(item.ParentInventory is CharacterInventory characterInventory && ((characterInventory.Owner as Character)?.HasEquippedItem(item) ?? false));
|
||||
}
|
||||
|
||||
public void ClientWrite(IWriteMessage msg, object[] extraData = null)
|
||||
|
||||
@@ -35,6 +35,7 @@ namespace Barotrauma.Items.Components
|
||||
private RoundSound startMoveSound, endMoveSound, moveSound;
|
||||
|
||||
private SoundChannel moveSoundChannel;
|
||||
private Vector2 oldRotation = Vector2.Zero;
|
||||
|
||||
private Vector2 crosshairPos, crosshairPointerPos;
|
||||
|
||||
@@ -307,7 +308,11 @@ namespace Barotrauma.Items.Components
|
||||
if (!item.IsSelected) { return; }
|
||||
|
||||
Widget minRotationWidget = GetWidget("minrotation", spriteBatch, size: 10, initMethod: (widget) =>
|
||||
{
|
||||
{
|
||||
widget.Selected += () =>
|
||||
{
|
||||
oldRotation = RotationLimits;
|
||||
};
|
||||
widget.MouseDown += () =>
|
||||
{
|
||||
widget.color = GUI.Style.Green;
|
||||
@@ -317,6 +322,10 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
widget.color = Color.Yellow;
|
||||
item.CreateEditingHUD();
|
||||
if (SubEditorScreen.IsSubEditor())
|
||||
{
|
||||
SubEditorScreen.StoreCommand(new PropertyCommand(this, "RotationLimits", RotationLimits, oldRotation));
|
||||
}
|
||||
};
|
||||
widget.MouseHeld += (deltaTime) =>
|
||||
{
|
||||
@@ -345,10 +354,14 @@ namespace Barotrauma.Items.Components
|
||||
widget.DrawPos = GetDrawPos() + new Vector2((float)Math.Cos(minRotation), (float)Math.Sin(minRotation)) * widgetRadius;
|
||||
widget.Update(deltaTime);
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
Widget maxRotationWidget = GetWidget("maxrotation", spriteBatch, size: 10, initMethod: (widget) =>
|
||||
{
|
||||
widget.Selected += () =>
|
||||
{
|
||||
oldRotation = RotationLimits;
|
||||
};
|
||||
widget.MouseDown += () =>
|
||||
{
|
||||
widget.color = GUI.Style.Green;
|
||||
@@ -358,6 +371,10 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
widget.color = Color.Yellow;
|
||||
item.CreateEditingHUD();
|
||||
if (SubEditorScreen.IsSubEditor())
|
||||
{
|
||||
SubEditorScreen.StoreCommand(new PropertyCommand(this, "RotationLimits", RotationLimits, oldRotation));
|
||||
}
|
||||
};
|
||||
widget.MouseHeld += (deltaTime) =>
|
||||
{
|
||||
|
||||
@@ -3,7 +3,6 @@ using Barotrauma.Items.Components;
|
||||
using Barotrauma.Networking;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@@ -163,6 +162,8 @@ namespace Barotrauma
|
||||
|
||||
public static Inventory DraggingInventory;
|
||||
|
||||
public Inventory ReplacedBy;
|
||||
|
||||
public Rectangle BackgroundFrame { get; protected set; }
|
||||
|
||||
private ushort[] receivedItemIDs;
|
||||
@@ -317,6 +318,11 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public Inventory GetReplacementOrThiS()
|
||||
{
|
||||
return ReplacedBy?.GetReplacementOrThiS() ?? this;
|
||||
}
|
||||
|
||||
public virtual void CreateSlots()
|
||||
{
|
||||
slots = new InventorySlot[capacity];
|
||||
@@ -465,12 +471,15 @@ namespace Barotrauma
|
||||
{
|
||||
if (item != null)
|
||||
{
|
||||
if (mouseDrag) { item.OwnInventory?.DeleteAllItems(); }
|
||||
slot.ShowBorderHighlight(GUI.Style.Red, 0.1f, 0.4f);
|
||||
if (!mouseDrag)
|
||||
{
|
||||
GUI.PlayUISound(GUISoundType.PickItem);
|
||||
SoundPlayer.PlayUISound(GUISoundType.PickItem);
|
||||
}
|
||||
|
||||
SubEditorScreen.BulkItemBufferInUse = true;
|
||||
SubEditorScreen.BulkItemBuffer.Add(new AddOrDeleteCommand(new List<MapEntity> { item }, true));
|
||||
item.OwnInventory?.DeleteAllItems();
|
||||
item.Remove();
|
||||
}
|
||||
}
|
||||
@@ -996,10 +1005,19 @@ namespace Barotrauma
|
||||
Character.Controlled.FocusedItem.OwnInventory.CanBePut(draggingItem) &&
|
||||
Character.Controlled.FocusedItem.OwnInventory.TryPutItem(draggingItem, Character.Controlled))
|
||||
{
|
||||
GUI.PlayUISound(GUISoundType.PickItem);
|
||||
SoundPlayer.PlayUISound(GUISoundType.PickItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Screen.Selected is SubEditorScreen)
|
||||
{
|
||||
if (draggingItem?.ParentInventory != null)
|
||||
{
|
||||
SubEditorScreen.StoreCommand(new InventoryPlaceCommand(draggingItem.ParentInventory, new List<Item> { draggingItem }, true));
|
||||
}
|
||||
}
|
||||
|
||||
SoundPlayer.PlayUISound(GUISoundType.DropItem);
|
||||
bool removed = false;
|
||||
if (Screen.Selected is SubEditorScreen editor)
|
||||
{
|
||||
@@ -1025,14 +1043,16 @@ namespace Barotrauma
|
||||
{
|
||||
draggingItem.Drop(Character.Controlled);
|
||||
}
|
||||
|
||||
GUI.PlayUISound(removed ? GUISoundType.PickItem : GUISoundType.DropItem);
|
||||
|
||||
SoundPlayer.PlayUISound(removed ? GUISoundType.PickItem : GUISoundType.DropItem);
|
||||
}
|
||||
}
|
||||
else if (selectedSlot.ParentInventory.Items[selectedSlot.SlotIndex] != draggingItem)
|
||||
{
|
||||
Inventory oldInventory = draggingItem.ParentInventory;
|
||||
Inventory selectedInventory = selectedSlot.ParentInventory;
|
||||
int slotIndex = selectedSlot.SlotIndex;
|
||||
int oldSlot = oldInventory == null ? 0 : Array.IndexOf(oldInventory.Items, draggingItem);
|
||||
|
||||
//if attempting to drop into an invalid slot in the same inventory, try to move to the correct slot
|
||||
if (selectedInventory.Items[slotIndex] == null &&
|
||||
@@ -1051,17 +1071,21 @@ namespace Barotrauma
|
||||
}
|
||||
selectedInventory.slots[slotIndex].ShowBorderHighlight(GUI.Style.Red, 0.1f, 0.9f);
|
||||
}
|
||||
GUI.PlayUISound(GUISoundType.PickItem);
|
||||
SoundPlayer.PlayUISound(GUISoundType.PickItem);
|
||||
}
|
||||
else if (selectedInventory.TryPutItem(draggingItem, slotIndex, true, true, Character.Controlled))
|
||||
{
|
||||
if (SubEditorScreen.IsSubEditor())
|
||||
{
|
||||
SubEditorScreen.StoreCommand(new InventoryMoveCommand(oldInventory, selectedInventory, draggingItem, oldSlot, slotIndex));
|
||||
}
|
||||
if (selectedInventory.slots != null) { selectedInventory.slots[slotIndex].ShowBorderHighlight(Color.White, 0.1f, 0.4f); }
|
||||
GUI.PlayUISound(GUISoundType.PickItem);
|
||||
SoundPlayer.PlayUISound(GUISoundType.PickItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (selectedInventory.slots != null){ selectedInventory.slots[slotIndex].ShowBorderHighlight(GUI.Style.Red, 0.1f, 0.9f); }
|
||||
GUI.PlayUISound(GUISoundType.PickItemFail);
|
||||
SoundPlayer.PlayUISound(GUISoundType.PickItemFail);
|
||||
}
|
||||
selectedInventory.HideTimer = 2.0f;
|
||||
if (selectedSlot.ParentInventory?.Owner is Item parentItem && parentItem.ParentInventory != null)
|
||||
|
||||
@@ -542,7 +542,7 @@ namespace Barotrauma
|
||||
Spacing = (int)(25 * GUI.Scale)
|
||||
};
|
||||
|
||||
var itemEditor = new SerializableEntityEditor(listBox.Content.RectTransform, this, inGame, showName: true, titleFont: GUI.LargeFont);
|
||||
var itemEditor = new SerializableEntityEditor(listBox.Content.RectTransform, this, inGame, showName: true, titleFont: GUI.LargeFont) { UserData = this };
|
||||
itemEditor.Children.First().Color = Color.Black * 0.7f;
|
||||
if (!inGame)
|
||||
{
|
||||
@@ -663,7 +663,7 @@ namespace Barotrauma
|
||||
|
||||
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.02f), listBox.Content.RectTransform), style: "HorizontalLine");
|
||||
|
||||
var componentEditor = new SerializableEntityEditor(listBox.Content.RectTransform, ic, inGame, showName: !inGame, titleFont: GUI.SubHeadingFont);
|
||||
var componentEditor = new SerializableEntityEditor(listBox.Content.RectTransform, ic, inGame, showName: !inGame, titleFont: GUI.SubHeadingFont) { UserData = ic };
|
||||
componentEditor.Children.First().Color = Color.Black * 0.7f;
|
||||
|
||||
if (inGame)
|
||||
|
||||
@@ -97,10 +97,12 @@ namespace Barotrauma
|
||||
{
|
||||
if (potentialContainer?.OwnInventory?.TryPutItem(item, Character.Controlled) ?? false)
|
||||
{
|
||||
GUI.PlayUISound(GUISoundType.PickItem);
|
||||
SoundPlayer.PlayUISound(GUISoundType.PickItem);
|
||||
}
|
||||
}
|
||||
|
||||
SubEditorScreen.StoreCommand(new AddOrDeleteCommand(new List<MapEntity> {item}, false));
|
||||
|
||||
placePosition = Vector2.Zero;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -110,5 +110,7 @@ namespace Barotrauma
|
||||
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
|
||||
static partial void PlayTinnitusProjSpecific(float volume) => SoundPlayer.PlaySound("tinnitus", volume: volume);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,11 +11,18 @@ namespace Barotrauma
|
||||
|
||||
partial void UpdateProjSpecific(float growModifier)
|
||||
{
|
||||
EmitParticles(size, WorldPosition, hull, growModifier, OnChangeHull);
|
||||
if (this is DummyFireSource)
|
||||
{
|
||||
EmitParticles(size, WorldPosition, hull, growModifier, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitParticles(size, WorldPosition, hull, growModifier, OnChangeHull);
|
||||
}
|
||||
|
||||
lightSource.Color = new Color(1.0f, 0.45f, 0.3f) * Rand.Range(0.8f, 1.0f);
|
||||
if (Math.Abs((lightSource.Range * 0.2f) - Math.Max(size.X, size.Y)) > 1.0f) lightSource.Range = Math.Max(size.X, size.Y) * 5.0f;
|
||||
if (Vector2.DistanceSquared(lightSource.Position, position) > 5.0f) lightSource.Position = position + Vector2.UnitY * 30.0f;
|
||||
if (Math.Abs((lightSource.Range * 0.2f) - Math.Max(size.X, size.Y)) > 1.0f) { lightSource.Range = Math.Max(size.X, size.Y) * 5.0f; }
|
||||
if (Vector2.DistanceSquared(lightSource.Position, position) > 5.0f) { lightSource.Position = position + Vector2.UnitY * 30.0f; }
|
||||
}
|
||||
|
||||
public static void EmitParticles(Vector2 size, Vector2 worldPosition, Hull hull, float growModifier, Particle.OnChangeHullHandler onChangeHull = null)
|
||||
@@ -32,6 +39,8 @@ namespace Barotrauma
|
||||
(particlePos.X - (worldPosition.X + size.X / 2.0f)),
|
||||
(float)Math.Sqrt(size.X) * Rand.Range(0.0f, 15.0f) * growModifier);
|
||||
|
||||
particleVel.X = MathHelper.Clamp(particleVel.X, -200.0f, 200.0f);
|
||||
|
||||
var particle = GameMain.ParticleManager.CreateParticle("flame",
|
||||
particlePos, particleVel, 0.0f, hull);
|
||||
|
||||
|
||||
@@ -261,6 +261,13 @@ namespace Barotrauma
|
||||
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);
|
||||
}
|
||||
foreach (FireSource fs in FakeFireSources)
|
||||
{
|
||||
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.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);
|
||||
@@ -623,12 +630,18 @@ namespace Barotrauma
|
||||
for (int i = 0; i < decalCount; i++)
|
||||
{
|
||||
UInt32 decalId = message.ReadUInt32();
|
||||
int spriteIndex = message.ReadByte();
|
||||
float normalizedXPos = message.ReadRangedSingle(0.0f, 1.0f, 8);
|
||||
float normalizedYPos = message.ReadRangedSingle(0.0f, 1.0f, 8);
|
||||
float decalPosX = MathHelper.Lerp(rect.X, rect.Right, normalizedXPos);
|
||||
float decalPosY = MathHelper.Lerp(rect.Y - rect.Height, rect.Y, normalizedYPos);
|
||||
float decalScale = message.ReadRangedSingle(0.0f, 2.0f, 12);
|
||||
AddDecal(decalId, new Vector2(decalPosX, decalPosY), decalScale, isNetworkEvent: true);
|
||||
if (Submarine != null)
|
||||
{
|
||||
decalPosX += Submarine.Position.X;
|
||||
decalPosY += Submarine.Position.Y;
|
||||
}
|
||||
AddDecal(decalId, new Vector2(decalPosX, decalPosY), decalScale, isNetworkEvent: true, spriteIndex: spriteIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,7 +219,7 @@ namespace Barotrauma.Lights
|
||||
{
|
||||
if (!light.IsBackground) { continue; }
|
||||
light.DrawSprite(spriteBatch, cam);
|
||||
if (light.Color.A > 0 && light.Range > 0.0f) { light.DrawLightVolume(spriteBatch, lightEffect, transform); }
|
||||
light.DrawLightVolume(spriteBatch, lightEffect, transform);
|
||||
}
|
||||
GameMain.ParticleManager.Draw(spriteBatch, true, null, Particles.ParticleBlendState.Additive);
|
||||
spriteBatch.End();
|
||||
@@ -328,7 +328,7 @@ namespace Barotrauma.Lights
|
||||
foreach (LightSource light in activeLights)
|
||||
{
|
||||
if (light.IsBackground) { continue; }
|
||||
if (light.Color.A > 0 && light.Range > 0.0f) { light.DrawLightVolume(spriteBatch, lightEffect, transform); }
|
||||
light.DrawLightVolume(spriteBatch, lightEffect, transform);
|
||||
}
|
||||
|
||||
lightEffect.World = transform;
|
||||
|
||||
@@ -493,7 +493,7 @@ namespace Barotrauma.Lights
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (Range < 1.0f || Color.A < 0.01f) return null;
|
||||
if (Range < 1.0f || Color.A < 1) { return null; }
|
||||
|
||||
Vector2 drawPos = position;
|
||||
if (ParentSub != null) drawPos += ParentSub.DrawPosition;
|
||||
@@ -1134,6 +1134,8 @@ namespace Barotrauma.Lights
|
||||
|
||||
public void DrawLightVolume(SpriteBatch spriteBatch, BasicEffect lightEffect, Matrix transform)
|
||||
{
|
||||
if (Range < 1.0f || Color.A < 1) { return; }
|
||||
|
||||
if (CastShadows)
|
||||
{
|
||||
CheckHullsInRange();
|
||||
@@ -1158,7 +1160,6 @@ namespace Barotrauma.Lights
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (NeedsRecalculation)
|
||||
{
|
||||
var verts = FindRaycastHits();
|
||||
@@ -1168,7 +1169,6 @@ namespace Barotrauma.Lights
|
||||
NeedsRecalculation = false;
|
||||
}
|
||||
|
||||
|
||||
Vector2 offset = ParentSub == null ? Vector2.Zero : ParentSub.DrawPosition;
|
||||
lightEffect.World =
|
||||
Matrix.CreateTranslation(-new Vector3(position, 0.0f)) *
|
||||
|
||||
@@ -27,6 +27,9 @@ namespace Barotrauma
|
||||
|
||||
private static bool resizing;
|
||||
private int resizeDirX, resizeDirY;
|
||||
private Rectangle? prevRect;
|
||||
|
||||
public static bool SelectionChanged;
|
||||
|
||||
//which entities have been selected for editing
|
||||
private static List<MapEntity> selectedList = new List<MapEntity>();
|
||||
@@ -105,6 +108,11 @@ namespace Barotrauma
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used for undo/redo to determine what this item has been replaced with
|
||||
/// </summary>
|
||||
public MapEntity ReplacedBy;
|
||||
|
||||
public virtual void Draw(SpriteBatch spriteBatch, bool editing, bool back = true) { }
|
||||
|
||||
/// <summary>
|
||||
@@ -147,13 +155,13 @@ namespace Barotrauma
|
||||
}
|
||||
if (GUI.KeyboardDispatcher.Subscriber == null)
|
||||
{
|
||||
if (PlayerInput.KeyDown(Keys.Delete))
|
||||
if (PlayerInput.KeyHit(Keys.Delete))
|
||||
{
|
||||
selectedList.ForEach(e =>
|
||||
if (selectedList.Any())
|
||||
{
|
||||
//orphaned wires may already have been removed
|
||||
if (!e.Removed) { e.Remove(); }
|
||||
});
|
||||
SubEditorScreen.StoreCommand(new AddOrDeleteCommand(selectedList, true));
|
||||
}
|
||||
selectedList.ForEach(e => { if (!e.Removed) { e.Remove(); } });
|
||||
selectedList.Clear();
|
||||
}
|
||||
|
||||
@@ -217,30 +225,6 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (PlayerInput.KeyHit(Keys.Z))
|
||||
{
|
||||
SetPreviousRects(e => e.rectMemento.Undo());
|
||||
}
|
||||
else if (PlayerInput.KeyHit(Keys.R))
|
||||
{
|
||||
SetPreviousRects(e => e.rectMemento.Redo());
|
||||
}
|
||||
|
||||
void SetPreviousRects(Func<MapEntity, Rectangle> memoryMethod)
|
||||
{
|
||||
foreach (var e in SelectedList)
|
||||
{
|
||||
if (e.rectMemento != null)
|
||||
{
|
||||
Point diff = memoryMethod(e).Location - e.Rect.Location;
|
||||
// We have to call the move method, because there's a lot more than just storing the rect (in some cases)
|
||||
// We also have to reassign the rect, because the move method does not set the width and height. They might have changed too.
|
||||
// The Rect property is virtual and it's overridden for structs. Setting the rect via the property should automatically recreate the sections for resizable structures.
|
||||
e.Move(diff.ToVector2());
|
||||
e.Rect = e.rectMemento.Current;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -343,35 +327,38 @@ namespace Barotrauma
|
||||
//clone
|
||||
if (PlayerInput.IsCtrlDown())
|
||||
{
|
||||
var clones = Clone(selectedList);
|
||||
var clones = Clone(selectedList).Where(c => c != null).ToList();
|
||||
selectedList = clones;
|
||||
SubEditorScreen.StoreCommand(new AddOrDeleteCommand(clones, false));
|
||||
selectedList.ForEach(c => c.Move(moveAmount));
|
||||
}
|
||||
else // move
|
||||
{
|
||||
var oldRects = selectedList.Select(e => e.Rect).ToList();
|
||||
List<MapEntity> deposited = new List<MapEntity>();
|
||||
foreach (MapEntity e in selectedList)
|
||||
{
|
||||
if (e.rectMemento == null)
|
||||
{
|
||||
e.rectMemento = new Memento<Rectangle>();
|
||||
e.rectMemento.Store(e.Rect);
|
||||
}
|
||||
e.Move(moveAmount);
|
||||
|
||||
if (isShiftDown && e is Item item && targetContainer != null)
|
||||
{
|
||||
if (targetContainer.OwnInventory.TryPutItem(item, Character.Controlled))
|
||||
{
|
||||
GUI.PlayUISound(GUISoundType.DropItem);
|
||||
SoundPlayer.PlayUISound(GUISoundType.DropItem);
|
||||
deposited.Add(item);
|
||||
}
|
||||
else
|
||||
{
|
||||
GUI.PlayUISound(GUISoundType.PickItemFail);
|
||||
SoundPlayer.PlayUISound(GUISoundType.PickItemFail);
|
||||
}
|
||||
}
|
||||
e.rectMemento.Store(e.Rect);
|
||||
}
|
||||
|
||||
SubEditorScreen.StoreCommand(new TransformCommand(new List<MapEntity>(selectedList),selectedList.Select(entity => entity.Rect).ToList(), oldRects, false));
|
||||
if (deposited.Any() && deposited.Any(entity => entity is Item))
|
||||
{
|
||||
var depositedItems = deposited.Where(entity => entity is Item).Cast<Item>().ToList();
|
||||
SubEditorScreen.StoreCommand(new InventoryPlaceCommand(targetContainer.OwnInventory, depositedItems, false));
|
||||
}
|
||||
|
||||
deposited.ForEach(entity => { selectedList.Remove(entity); });
|
||||
@@ -492,6 +479,11 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public MapEntity GetReplacementOrThis()
|
||||
{
|
||||
return ReplacedBy?.GetReplacementOrThis() ?? this;
|
||||
}
|
||||
|
||||
public static Item GetPotentialContainer(Vector2 position, List<MapEntity> entities = null)
|
||||
{
|
||||
Item targetContainer = null;
|
||||
@@ -904,13 +896,12 @@ namespace Barotrauma
|
||||
public static void Cut(List<MapEntity> entities)
|
||||
{
|
||||
if (entities.Count == 0) { return; }
|
||||
|
||||
|
||||
SubEditorScreen.StoreCommand(new AddOrDeleteCommand(new List<MapEntity>(entities), true));
|
||||
|
||||
CopyEntities(entities);
|
||||
|
||||
entities.ForEach(e =>
|
||||
{
|
||||
e.Remove();
|
||||
});
|
||||
|
||||
entities.ForEach(e => { if (!e.Removed) { e.Remove(); } });
|
||||
entities.Clear();
|
||||
}
|
||||
|
||||
@@ -922,6 +913,7 @@ namespace Barotrauma
|
||||
Clone(copiedList);
|
||||
|
||||
var clones = mapEntityList.Except(prevEntities).ToList();
|
||||
SubEditorScreen.StoreCommand(new AddOrDeleteCommand(clones, false));
|
||||
var nonWireClones = clones.Where(c => !(c is Item item) || item.GetComponent<Wire>() == null);
|
||||
if (!nonWireClones.Any()) { nonWireClones = clones; }
|
||||
|
||||
@@ -1031,12 +1023,11 @@ namespace Barotrauma
|
||||
|
||||
if (resizing)
|
||||
{
|
||||
if (rectMemento == null)
|
||||
if (prevRect == null)
|
||||
{
|
||||
rectMemento = new Memento<Rectangle>();
|
||||
rectMemento.Store(Rect);
|
||||
prevRect = new Rectangle(Rect.Location, Rect.Size);
|
||||
}
|
||||
|
||||
|
||||
Vector2 placePosition = new Vector2(rect.X, rect.Y);
|
||||
Vector2 placeSize = new Vector2(rect.Width, rect.Height);
|
||||
|
||||
@@ -1079,9 +1070,15 @@ namespace Barotrauma
|
||||
|
||||
if (!PlayerInput.PrimaryMouseButtonHeld())
|
||||
{
|
||||
rectMemento.Store(Rect);
|
||||
resizing = false;
|
||||
Resized?.Invoke(rect);
|
||||
if (prevRect != null)
|
||||
{
|
||||
var newData = new List<Rectangle> { Rect };
|
||||
var oldData = new List<Rectangle> { prevRect.Value };
|
||||
SubEditorScreen.StoreCommand(new TransformCommand(new List<MapEntity> { this }, newData, oldData, true));
|
||||
}
|
||||
prevRect = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@ namespace Barotrauma
|
||||
int heightScaled = (int)(20 * GUI.Scale);
|
||||
editingHUD = new GUIFrame(new RectTransform(new Vector2(0.3f, 0.25f), GUI.Canvas, Anchor.CenterRight) { MinSize = new Point(400, 0) }) { UserData = this };
|
||||
GUIListBox listBox = new GUIListBox(new RectTransform(new Vector2(0.95f, 0.8f), editingHUD.RectTransform, Anchor.Center), style: null);
|
||||
var editor = new SerializableEntityEditor(listBox.Content.RectTransform, this, inGame, showName: true, titleFont: GUI.LargeFont);
|
||||
var editor = new SerializableEntityEditor(listBox.Content.RectTransform, this, inGame, showName: true, titleFont: GUI.LargeFont) { UserData = this };
|
||||
|
||||
if (Submarine.MainSub?.Info?.Type == SubmarineType.OutpostModule)
|
||||
{
|
||||
|
||||
@@ -56,11 +56,12 @@ namespace Barotrauma
|
||||
if (PlayerInput.PrimaryMouseButtonReleased())
|
||||
{
|
||||
newRect.Location -= MathUtils.ToPoint(Submarine.MainSub.Position);
|
||||
new Structure(newRect, this, Submarine.MainSub)
|
||||
var structure = new Structure(newRect, this, Submarine.MainSub)
|
||||
{
|
||||
Submarine = Submarine.MainSub
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
SubEditorScreen.StoreCommand(new AddOrDeleteCommand(new List<MapEntity> { structure }, false));
|
||||
selected = null;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -95,7 +95,7 @@ namespace Barotrauma
|
||||
{
|
||||
string errorMsg = "Error when loading round sound (" + element + ") - file path not set";
|
||||
DebugConsole.ThrowError(errorMsg);
|
||||
GameAnalyticsManager.AddErrorEventOnce("Submarine.LoadRoundSound:FilePathEmpty" + element.ToString(), GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg + "\n" + Environment.StackTrace);
|
||||
GameAnalyticsManager.AddErrorEventOnce("Submarine.LoadRoundSound:FilePathEmpty" + element.ToString(), GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg + "\n" + Environment.StackTrace.CleanupStackTrace());
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -107,7 +107,7 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
existingSound = roundSounds.Find(s => s.Filename == filename && s.Stream == stream)?.Sound;
|
||||
existingSound = roundSounds.Find(s => s.Filename == filename && s.Stream == stream && !s.Sound.Disposed)?.Sound;
|
||||
}
|
||||
|
||||
if (existingSound == null)
|
||||
@@ -121,7 +121,7 @@ namespace Barotrauma
|
||||
{
|
||||
string errorMsg = "Failed to load sound file \"" + filename + "\".";
|
||||
DebugConsole.ThrowError(errorMsg, e);
|
||||
GameAnalyticsManager.AddErrorEventOnce("Submarine.LoadRoundSound:FileNotFound" + filename, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg + "\n" + Environment.StackTrace);
|
||||
GameAnalyticsManager.AddErrorEventOnce("Submarine.LoadRoundSound:FileNotFound" + filename, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg + "\n" + Environment.StackTrace.CleanupStackTrace());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -132,6 +132,26 @@ namespace Barotrauma
|
||||
return newSound;
|
||||
}
|
||||
|
||||
public static void ReloadRoundSound(RoundSound roundSound)
|
||||
{
|
||||
Sound existingSound = roundSounds?.Find(s => s.Filename == roundSound.Filename && s.Stream == roundSound.Stream && !s.Sound.Disposed)?.Sound;
|
||||
if (existingSound == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
existingSound = GameMain.SoundManager.LoadSound(roundSound.Filename, roundSound.Stream);
|
||||
}
|
||||
catch (System.IO.FileNotFoundException e)
|
||||
{
|
||||
string errorMsg = "Failed to load sound file \"" + roundSound.Filename + "\".";
|
||||
DebugConsole.ThrowError(errorMsg, e);
|
||||
GameAnalyticsManager.AddErrorEventOnce("Submarine.LoadRoundSound:FileNotFound" + roundSound.Filename, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg + "\n" + Environment.StackTrace.CleanupStackTrace());
|
||||
return;
|
||||
}
|
||||
}
|
||||
roundSound.Sound = existingSound;
|
||||
}
|
||||
|
||||
private static void RemoveRoundSound(RoundSound roundSound)
|
||||
{
|
||||
roundSound.Sound?.Dispose();
|
||||
@@ -438,10 +458,15 @@ namespace Barotrauma
|
||||
public void CheckForErrors()
|
||||
{
|
||||
List<string> errorMsgs = new List<string>();
|
||||
List<SubEditorScreen.WarningType> warnings = new List<SubEditorScreen.WarningType>();
|
||||
|
||||
if (!Hull.hullList.Any())
|
||||
{
|
||||
errorMsgs.Add(TextManager.Get("NoHullsWarning"));
|
||||
if (!IsWarningSuppressed(SubEditorScreen.WarningType.NoWaypoints))
|
||||
{
|
||||
errorMsgs.Add(TextManager.Get("NoHullsWarning"));
|
||||
warnings.Add(SubEditorScreen.WarningType.NoHulls);
|
||||
}
|
||||
}
|
||||
|
||||
if (Info.Type != SubmarineType.OutpostModule ||
|
||||
@@ -449,7 +474,11 @@ namespace Barotrauma
|
||||
{
|
||||
if (!WayPoint.WayPointList.Any(wp => wp.ShouldBeSaved && wp.SpawnType == SpawnType.Path))
|
||||
{
|
||||
errorMsgs.Add(TextManager.Get("NoWaypointsWarning"));
|
||||
if (!IsWarningSuppressed(SubEditorScreen.WarningType.NoWaypoints))
|
||||
{
|
||||
errorMsgs.Add(TextManager.Get("NoWaypointsWarning"));
|
||||
warnings.Add(SubEditorScreen.WarningType.NoWaypoints);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -460,22 +489,38 @@ namespace Barotrauma
|
||||
if (item.GetComponent<Items.Components.Vent>() == null) { continue; }
|
||||
if (!item.linkedTo.Any())
|
||||
{
|
||||
errorMsgs.Add(TextManager.Get("DisconnectedVentsWarning"));
|
||||
if (!IsWarningSuppressed(SubEditorScreen.WarningType.DisconnectedVents))
|
||||
{
|
||||
errorMsgs.Add(TextManager.Get("DisconnectedVentsWarning"));
|
||||
warnings.Add(SubEditorScreen.WarningType.DisconnectedVents);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!WayPoint.WayPointList.Any(wp => wp.ShouldBeSaved && wp.SpawnType == SpawnType.Human))
|
||||
{
|
||||
errorMsgs.Add(TextManager.Get("NoHumanSpawnpointWarning"));
|
||||
if (!IsWarningSuppressed(SubEditorScreen.WarningType.NoHumanSpawnpoints))
|
||||
{
|
||||
errorMsgs.Add(TextManager.Get("NoHumanSpawnpointWarning"));
|
||||
warnings.Add(SubEditorScreen.WarningType.NoHumanSpawnpoints);
|
||||
}
|
||||
}
|
||||
if (WayPoint.WayPointList.Find(wp => wp.SpawnType == SpawnType.Cargo) == null)
|
||||
{
|
||||
errorMsgs.Add(TextManager.Get("NoCargoSpawnpointWarning"));
|
||||
if (!IsWarningSuppressed(SubEditorScreen.WarningType.NoCargoSpawnpoints))
|
||||
{
|
||||
errorMsgs.Add(TextManager.Get("NoCargoSpawnpointWarning"));
|
||||
warnings.Add(SubEditorScreen.WarningType.NoCargoSpawnpoints);
|
||||
}
|
||||
}
|
||||
if (!Item.ItemList.Any(it => it.GetComponent<Items.Components.Pump>() != null && it.HasTag("ballast")))
|
||||
{
|
||||
errorMsgs.Add(TextManager.Get("NoBallastTagsWarning"));
|
||||
if (!IsWarningSuppressed(SubEditorScreen.WarningType.NoBallastTag))
|
||||
{
|
||||
errorMsgs.Add(TextManager.Get("NoBallastTagsWarning"));
|
||||
warnings.Add(SubEditorScreen.WarningType.NoBallastTag);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (Info.Type == SubmarineType.OutpostModule)
|
||||
@@ -503,7 +548,11 @@ namespace Barotrauma
|
||||
|
||||
if (Gap.GapList.Any(g => g.linkedTo.Count == 0))
|
||||
{
|
||||
errorMsgs.Add(TextManager.Get("NonLinkedGapsWarning"));
|
||||
if (!IsWarningSuppressed(SubEditorScreen.WarningType.NonLinkedGaps))
|
||||
{
|
||||
errorMsgs.Add(TextManager.Get("NonLinkedGapsWarning"));
|
||||
warnings.Add(SubEditorScreen.WarningType.NonLinkedGaps);
|
||||
}
|
||||
}
|
||||
|
||||
int disabledItemLightCount = 0;
|
||||
@@ -515,12 +564,35 @@ namespace Barotrauma
|
||||
int count = GameMain.LightManager.Lights.Count(l => l.CastShadows) - disabledItemLightCount;
|
||||
if (count > 45)
|
||||
{
|
||||
errorMsgs.Add(TextManager.Get("subeditor.shadowcastinglightswarning"));
|
||||
if (!IsWarningSuppressed(SubEditorScreen.WarningType.TooManyLights))
|
||||
{
|
||||
errorMsgs.Add(TextManager.Get("subeditor.shadowcastinglightswarning"));
|
||||
warnings.Add(SubEditorScreen.WarningType.TooManyLights);
|
||||
}
|
||||
}
|
||||
|
||||
if (errorMsgs.Any())
|
||||
{
|
||||
new GUIMessageBox(TextManager.Get("Warning"), string.Join("\n\n", errorMsgs), new Vector2(0.25f, 0.0f), new Point(400, 200));
|
||||
GUIMessageBox msgBox = new GUIMessageBox(TextManager.Get("Warning"), string.Join("\n\n", errorMsgs), new Vector2(0.25f, 0.0f), new Point(400, 200));
|
||||
if (warnings.Any())
|
||||
{
|
||||
Point size = msgBox.RectTransform.NonScaledSize;
|
||||
GUITickBox suppress = new GUITickBox(new RectTransform(new Vector2(1f, 0.33f), msgBox.Content.RectTransform), TextManager.Get("editor.suppresswarnings"));
|
||||
msgBox.RectTransform.NonScaledSize = new Point(size.X, size.Y + suppress.RectTransform.NonScaledSize.Y);
|
||||
|
||||
msgBox.Buttons[0].OnClicked += (button, obj) =>
|
||||
{
|
||||
if (suppress.Selected)
|
||||
{
|
||||
foreach (SubEditorScreen.WarningType warning in warnings.Where(warning => !SubEditorScreen.SuppressedWarnings.Contains(warning)))
|
||||
{
|
||||
SubEditorScreen.SuppressedWarnings.Add(warning);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
foreach (MapEntity e in MapEntity.mapEntityList)
|
||||
@@ -556,6 +628,11 @@ namespace Barotrauma
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
bool IsWarningSuppressed(SubEditorScreen.WarningType type)
|
||||
{
|
||||
return SubEditorScreen.SuppressedWarnings.Contains(type);
|
||||
}
|
||||
}
|
||||
|
||||
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
|
||||
namespace Barotrauma.Networking
|
||||
{
|
||||
@@ -49,45 +49,53 @@ namespace Barotrauma.Networking
|
||||
Character targetCharacter = Entity.FindEntityByID(targetCharacterID) as Character;
|
||||
Entity targetEntity = Entity.FindEntityByID(msg.ReadUInt16());
|
||||
int optionIndex = msg.ReadByte();
|
||||
OrderTarget orderTargetPosition = null;
|
||||
if (msg.ReadBoolean())
|
||||
{
|
||||
var x = msg.ReadSingle();
|
||||
var y = msg.ReadSingle();
|
||||
var hull = Entity.FindEntityByID(msg.ReadUInt16()) as Hull;
|
||||
orderTargetPosition = new OrderTarget(new Vector2(x, y), hull, creatingFromExistingData: true);
|
||||
}
|
||||
|
||||
Order order = null;
|
||||
Order orderPrefab;
|
||||
if (orderIndex < 0 || orderIndex >= Order.PrefabList.Count)
|
||||
{
|
||||
DebugConsole.ThrowError("Invalid order message - order index out of bounds.");
|
||||
if (NetIdUtils.IdMoreRecent(ID, LastID)) LastID = ID;
|
||||
if (NetIdUtils.IdMoreRecent(ID, LastID)) { LastID = ID; }
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
order = Order.PrefabList[orderIndex];
|
||||
orderPrefab = Order.PrefabList[orderIndex];
|
||||
}
|
||||
string orderOption = "";
|
||||
if (optionIndex >= 0 && optionIndex < order.Options.Length)
|
||||
if (optionIndex >= 0 && optionIndex < orderPrefab.Options.Length)
|
||||
{
|
||||
orderOption = order.Options[optionIndex];
|
||||
orderOption = orderPrefab.Options[optionIndex];
|
||||
}
|
||||
txt = order.GetChatMessage(targetCharacter?.Name, senderCharacter?.CurrentHull?.DisplayName, givingOrderToSelf: targetCharacter == senderCharacter, orderOption: orderOption);
|
||||
txt = orderPrefab.GetChatMessage(targetCharacter?.Name, senderCharacter?.CurrentHull?.DisplayName, givingOrderToSelf: targetCharacter == senderCharacter, orderOption: orderOption);
|
||||
|
||||
if (GameMain.Client.GameStarted && Screen.Selected == GameMain.GameScreen)
|
||||
{
|
||||
var order = orderTargetPosition == null ?
|
||||
new Order(orderPrefab, targetEntity, orderPrefab.GetTargetItemComponent(targetEntity as Item), orderGiver: senderCharacter) :
|
||||
new Order(orderPrefab, orderTargetPosition, orderGiver: senderCharacter);
|
||||
|
||||
if (order.TargetAllCharacters)
|
||||
{
|
||||
GameMain.GameSession?.CrewManager?.AddOrder(
|
||||
new Order(order.Prefab, targetEntity, (targetEntity as Item)?.Components.FirstOrDefault(ic => ic.GetType() == order.ItemComponentType), orderGiver: senderCharacter),
|
||||
order.Prefab.FadeOutTime);
|
||||
GameMain.GameSession?.CrewManager?.AddOrder(order, orderPrefab.FadeOutTime);
|
||||
}
|
||||
else if (targetCharacter != null)
|
||||
{
|
||||
targetCharacter.SetOrder(
|
||||
new Order(order.Prefab, targetEntity, (targetEntity as Item)?.Components.FirstOrDefault(ic => ic.GetType() == order.ItemComponentType), orderGiver: senderCharacter),
|
||||
orderOption, senderCharacter);
|
||||
targetCharacter.SetOrder(order, orderOption, senderCharacter);
|
||||
}
|
||||
}
|
||||
|
||||
if (NetIdUtils.IdMoreRecent(ID, LastID))
|
||||
{
|
||||
GameMain.Client.AddChatMessage(
|
||||
new OrderChatMessage(order, orderOption, txt, targetEntity, targetCharacter, senderCharacter));
|
||||
new OrderChatMessage(orderPrefab, orderOption, txt, orderTargetPosition ?? targetEntity as ISpatialEntity, targetCharacter, senderCharacter));
|
||||
LastID = ID;
|
||||
}
|
||||
return;
|
||||
|
||||
@@ -608,10 +608,10 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
string errorMsg = "Error while reading a message from server. {" + e + "}. ";
|
||||
if (GameMain.Client == null) { errorMsg += "Client disposed."; }
|
||||
errorMsg += "\n" + e.StackTrace;
|
||||
errorMsg += "\n" + e.StackTrace.CleanupStackTrace();
|
||||
if (e.InnerException != null)
|
||||
{
|
||||
errorMsg += "\nInner exception: " + e.InnerException.Message + "\n" + e.InnerException.StackTrace;
|
||||
errorMsg += "\nInner exception: " + e.InnerException.Message + "\n" + e.InnerException.StackTrace.CleanupStackTrace();
|
||||
}
|
||||
GameAnalyticsManager.AddErrorEventOnce("GameClient.Update:CheckServerMessagesException" + e.TargetSite.ToString(), GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||
DebugConsole.ThrowError("Error while reading a message from server.", e);
|
||||
@@ -738,10 +738,10 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
string errorMsg = "Error while reading an ingame update message from server. {" + e + "}\n" + e.StackTrace;
|
||||
string errorMsg = "Error while reading an ingame update message from server. {" + e + "}\n" + e.StackTrace.CleanupStackTrace();
|
||||
if (e.InnerException != null)
|
||||
{
|
||||
errorMsg += "\nInner exception: " + e.InnerException.Message + "\n" + e.InnerException.StackTrace;
|
||||
errorMsg += "\nInner exception: " + e.InnerException.Message + "\n" + e.InnerException.StackTrace.CleanupStackTrace();
|
||||
}
|
||||
#if DEBUG
|
||||
DebugConsole.ThrowError("Error while reading an ingame update message from server.", e);
|
||||
@@ -755,7 +755,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
string errorMsg = "Failed to read a voice packet from the server (VoipClient == null). ";
|
||||
if (GameMain.Client == null) { errorMsg += "Client disposed. "; }
|
||||
errorMsg += "\n" + Environment.StackTrace;
|
||||
errorMsg += "\n" + Environment.StackTrace.CleanupStackTrace();
|
||||
GameAnalyticsManager.AddErrorEventOnce(
|
||||
"GameClient.ReadDataMessage:VoipClientNull",
|
||||
GameMain.Client == null ? GameAnalyticsSDK.Net.EGAErrorSeverity.Error : GameAnalyticsSDK.Net.EGAErrorSeverity.Warning,
|
||||
@@ -1124,7 +1124,7 @@ namespace Barotrauma.Networking
|
||||
else
|
||||
{
|
||||
DebugConsole.NewMessage("Not attempting to reconnect (DisconnectReason doesn't allow reconnection).");
|
||||
msg = TextManager.Get("DisconnectReason." + disconnectReason.ToString());
|
||||
msg = TextManager.Get("DisconnectReason." + disconnectReason.ToString()) + " ";
|
||||
|
||||
for (int i = 1; i < splitMsg.Length; i++)
|
||||
{
|
||||
@@ -1966,7 +1966,12 @@ namespace Barotrauma.Networking
|
||||
string selectShuttleName = inc.ReadString();
|
||||
string selectShuttleHash = inc.ReadString();
|
||||
|
||||
string campaignSubmarineIndexes = inc.ReadString();
|
||||
UInt16 campaignSubmarineIndexCount = inc.ReadUInt16();
|
||||
List<int> campaignSubIndices = new List<int>();
|
||||
for (int i = 0; i< campaignSubmarineIndexCount; i++)
|
||||
{
|
||||
campaignSubIndices.Add(inc.ReadUInt16());
|
||||
}
|
||||
|
||||
bool allowSubVoting = inc.ReadBoolean();
|
||||
bool allowModeVoting = inc.ReadBoolean();
|
||||
@@ -2022,22 +2027,16 @@ namespace Barotrauma.Networking
|
||||
if (GameMain.Client.IsServerOwner) RequestSelectMode(modeIndex);
|
||||
}
|
||||
|
||||
if (campaignSubmarineIndexes != null)
|
||||
if (campaignSubIndices != null)
|
||||
{
|
||||
string[] activeIndexes = campaignSubmarineIndexes.Split(';');
|
||||
|
||||
GameMain.NetLobbyScreen.CampaignSubmarines = new List<SubmarineInfo>();
|
||||
for (int i = 0; i < activeIndexes.Length; i++)
|
||||
foreach (UInt16 campaignSubIndex in campaignSubIndices)
|
||||
{
|
||||
int index;
|
||||
if (int.TryParse(activeIndexes[i], out index))
|
||||
SubmarineInfo sub = GameMain.Client.ServerSubmarines[campaignSubIndex];
|
||||
if (GameMain.NetLobbyScreen.CheckIfCampaignSubMatches(sub, "campaign"))
|
||||
{
|
||||
SubmarineInfo sub = GameMain.Client.ServerSubmarines[index];
|
||||
if (GameMain.NetLobbyScreen.CheckIfCampaignSubMatches(sub, "campaign"))
|
||||
{
|
||||
GameMain.NetLobbyScreen.CampaignSubmarines.Add(sub);
|
||||
}
|
||||
}
|
||||
GameMain.NetLobbyScreen.CampaignSubmarines.Add(sub);
|
||||
}
|
||||
}
|
||||
|
||||
if (HasPermission(ClientPermissions.ManageCampaign) && !gameStarted && GameMain.NetLobbyScreen?.CampaignSetupUI != null)
|
||||
@@ -2186,7 +2185,7 @@ namespace Barotrauma.Networking
|
||||
"Previous object was " + (prevBitLength) + " bits long (" + (prevByteLength) + " bytes)",
|
||||
" "
|
||||
};
|
||||
errorLines.Add(ex.StackTrace);
|
||||
errorLines.Add(ex.StackTrace.CleanupStackTrace());
|
||||
errorLines.Add(" ");
|
||||
if (prevObjHeader == ServerNetObject.ENTITY_EVENT || prevObjHeader == ServerNetObject.ENTITY_EVENT_INITIAL ||
|
||||
objHeader == ServerNetObject.ENTITY_EVENT || objHeader == ServerNetObject.ENTITY_EVENT_INITIAL)
|
||||
@@ -2721,7 +2720,7 @@ namespace Barotrauma.Networking
|
||||
MultiPlayerCampaign campaign = GameMain.GameSession.GameMode as MultiPlayerCampaign;
|
||||
if (campaign == null)
|
||||
{
|
||||
DebugConsole.ThrowError("Failed send campaign state to the server (no campaign active).\n" + Environment.StackTrace);
|
||||
DebugConsole.ThrowError("Failed send campaign state to the server (no campaign active).\n" + Environment.StackTrace.CleanupStackTrace());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2738,7 +2737,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(command))
|
||||
{
|
||||
DebugConsole.ThrowError("Cannot send an empty console command to the server!\n" + Environment.StackTrace);
|
||||
DebugConsole.ThrowError("Cannot send an empty console command to the server!\n" + Environment.StackTrace.CleanupStackTrace());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2778,7 +2777,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
if (subIndex < 0 || subIndex >= subList.Content.CountChildren)
|
||||
{
|
||||
DebugConsole.ThrowError("Submarine index out of bounds (" + subIndex + ")\n" + Environment.StackTrace);
|
||||
DebugConsole.ThrowError("Submarine index out of bounds (" + subIndex + ")\n" + Environment.StackTrace.CleanupStackTrace());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2818,7 +2817,7 @@ namespace Barotrauma.Networking
|
||||
if (!HasPermission(ClientPermissions.SelectMode)) return;
|
||||
if (modeIndex < 0 || modeIndex >= GameMain.NetLobbyScreen.ModeList.Content.CountChildren)
|
||||
{
|
||||
DebugConsole.ThrowError("Gamemode index out of bounds (" + modeIndex + ")\n" + Environment.StackTrace);
|
||||
DebugConsole.ThrowError("Gamemode index out of bounds (" + modeIndex + ")\n" + Environment.StackTrace.CleanupStackTrace());
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -53,12 +53,12 @@ namespace Barotrauma.Networking
|
||||
|
||||
if (((Entity)entity).Removed)
|
||||
{
|
||||
DebugConsole.ThrowError("Can't create an entity event for " + entity + " - the entity has been removed.\n" + Environment.StackTrace);
|
||||
DebugConsole.ThrowError("Can't create an entity event for " + entity + " - the entity has been removed.\n" + Environment.StackTrace.CleanupStackTrace());
|
||||
return;
|
||||
}
|
||||
if (((Entity)entity).IdFreed)
|
||||
{
|
||||
DebugConsole.ThrowError("Can't create an entity event for " + entity + " - the ID of the entity has been freed.\n" + Environment.StackTrace);
|
||||
DebugConsole.ThrowError("Can't create an entity event for " + entity + " - the ID of the entity has been freed.\n" + Environment.StackTrace.CleanupStackTrace());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -254,7 +254,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
catch (Exception e)
|
||||
{
|
||||
string errorMsg = "Failed to read event for entity \"" + entity.ToString() + "\" (" + e.Message + ")! (MidRoundSyncing: " + thisClient.MidRoundSyncing + ")\n" + e.StackTrace;
|
||||
string errorMsg = "Failed to read event for entity \"" + entity.ToString() + "\" (" + e.Message + ")! (MidRoundSyncing: " + thisClient.MidRoundSyncing + ")\n" + e.StackTrace.CleanupStackTrace();
|
||||
errorMsg += "\nPrevious entities:";
|
||||
for (int j = entities.Count - 2; j >= 0; j--)
|
||||
{
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Lidgren.Network;
|
||||
using System;
|
||||
using System;
|
||||
|
||||
namespace Barotrauma.Networking
|
||||
{
|
||||
@@ -11,10 +10,20 @@ namespace Barotrauma.Networking
|
||||
msg.Write(NetStateID);
|
||||
msg.Write((byte)ChatMessageType.Order);
|
||||
msg.Write((byte)Order.PrefabList.IndexOf(Order.Prefab));
|
||||
|
||||
msg.Write(TargetCharacter == null ? (UInt16)0 : TargetCharacter.ID);
|
||||
msg.Write(TargetEntity == null ? (UInt16)0 : TargetEntity.ID);
|
||||
msg.Write(TargetEntity is Entity ? (TargetEntity as Entity).ID : (UInt16)0);
|
||||
msg.Write((byte)Array.IndexOf(Order.Prefab.Options, OrderOption));
|
||||
if (TargetEntity is OrderTarget orderTarget)
|
||||
{
|
||||
msg.Write(true);
|
||||
msg.Write(orderTarget.Position.X);
|
||||
msg.Write(orderTarget.Position.Y);
|
||||
msg.Write(orderTarget.Hull == null ? (UInt16)0 : orderTarget.Hull.ID);
|
||||
}
|
||||
else
|
||||
{
|
||||
msg.Write(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,6 +162,7 @@ namespace Barotrauma.Networking
|
||||
disconnectMsg = $"DisconnectMessage.MissingContentPackages~[missingcontentpackages]={string.Join(", ", packageStrs)}";
|
||||
}
|
||||
Close(disconnectMsg, disableReconnect: true);
|
||||
OnDisconnectMessageReceived?.Invoke(DisconnectReason.MissingContentPackage + "/" + disconnectMsg);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -478,11 +478,14 @@ namespace Barotrauma.Steam
|
||||
}
|
||||
|
||||
if (rules.ContainsKey("gamestarted")) serverInfo.GameStarted = rules["gamestarted"] == "True";
|
||||
|
||||
if (rules.ContainsKey("gamemode"))
|
||||
{
|
||||
serverInfo.GameMode = rules["gamemode"];
|
||||
}
|
||||
if (rules.ContainsKey("playstyle") && Enum.TryParse(rules["playstyle"], out PlayStyle playStyle))
|
||||
{
|
||||
serverInfo.PlayStyle = playStyle;
|
||||
}
|
||||
|
||||
if (serverInfo.ContentPackageNames.Count != serverInfo.ContentPackageHashes.Count ||
|
||||
serverInfo.ContentPackageHashes.Count != serverInfo.ContentPackageWorkshopIds.Count)
|
||||
@@ -1297,7 +1300,7 @@ namespace Barotrauma.Steam
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
errorMsg = "Disabling the workshop item \"" + item?.Title + "\" failed. " + e.Message + "\n" + e.StackTrace;
|
||||
errorMsg = "Disabling the workshop item \"" + item?.Title + "\" failed. " + e.Message + "\n" + e.StackTrace.CleanupStackTrace();
|
||||
if (!noLog)
|
||||
{
|
||||
DebugConsole.NewMessage(errorMsg, Microsoft.Xna.Framework.Color.Red);
|
||||
@@ -1492,7 +1495,7 @@ namespace Barotrauma.Steam
|
||||
GameAnalyticsManager.AddErrorEventOnce(
|
||||
"SteamManager.AutoUpdateWorkshopItems:" + e.Message,
|
||||
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||
"Failed to autoupdate workshop item \"" + item.Title + "\". " + e.Message + "\n" + e.StackTrace);
|
||||
"Failed to autoupdate workshop item \"" + item.Title + "\". " + e.Message + "\n" + e.StackTrace.CleanupStackTrace());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace Barotrauma.Particles
|
||||
Prefab = prefab;
|
||||
}
|
||||
|
||||
public void Emit(float deltaTime, Vector2 position, Hull hullGuess = null, float angle = 0.0f, float particleRotation = 0.0f, float velocityMultiplier = 1.0f, float sizeMultiplier = 1.0f, float amountMultiplier = 1.0f, Color? colorMultiplier = null)
|
||||
public void Emit(float deltaTime, Vector2 position, Hull hullGuess = null, float angle = 0.0f, float particleRotation = 0.0f, float velocityMultiplier = 1.0f, float sizeMultiplier = 1.0f, float amountMultiplier = 1.0f, Color? colorMultiplier = null, ParticlePrefab overrideParticle = null)
|
||||
{
|
||||
emitTimer += deltaTime * amountMultiplier;
|
||||
burstEmitTimer -= deltaTime;
|
||||
@@ -33,7 +33,7 @@ namespace Barotrauma.Particles
|
||||
float emitInterval = 1.0f / Prefab.ParticlesPerSecond;
|
||||
while (emitTimer > emitInterval)
|
||||
{
|
||||
Emit(position, hullGuess, angle, particleRotation, velocityMultiplier, sizeMultiplier, colorMultiplier);
|
||||
Emit(position, hullGuess, angle, particleRotation, velocityMultiplier, sizeMultiplier, colorMultiplier, overrideParticle);
|
||||
emitTimer -= emitInterval;
|
||||
}
|
||||
}
|
||||
@@ -43,11 +43,11 @@ namespace Barotrauma.Particles
|
||||
burstEmitTimer = Prefab.EmitInterval;
|
||||
for (int i = 0; i < Prefab.ParticleAmount * amountMultiplier; i++)
|
||||
{
|
||||
Emit(position, hullGuess, angle, particleRotation, velocityMultiplier, sizeMultiplier, colorMultiplier);
|
||||
Emit(position, hullGuess, angle, particleRotation, velocityMultiplier, sizeMultiplier, colorMultiplier, overrideParticle);
|
||||
}
|
||||
}
|
||||
|
||||
private void Emit(Vector2 position, Hull hullGuess, float angle, float particleRotation, float velocityMultiplier, float sizeMultiplier, Color? colorMultiplier = null)
|
||||
private void Emit(Vector2 position, Hull hullGuess, float angle, float particleRotation, float velocityMultiplier, float sizeMultiplier, Color? colorMultiplier = null, ParticlePrefab overrideParticle = null)
|
||||
{
|
||||
angle += Rand.Range(Prefab.AngleMin, Prefab.AngleMax);
|
||||
|
||||
@@ -55,13 +55,20 @@ namespace Barotrauma.Particles
|
||||
Vector2 velocity = dir * Rand.Range(Prefab.VelocityMin, Prefab.VelocityMax) * velocityMultiplier;
|
||||
position += dir * Rand.Range(Prefab.DistanceMin, Prefab.DistanceMax);
|
||||
|
||||
var particle = GameMain.ParticleManager.CreateParticle(Prefab.ParticlePrefab, position, velocity, particleRotation, hullGuess, Prefab.DrawOnTop);
|
||||
var particle = GameMain.ParticleManager.CreateParticle(overrideParticle ?? Prefab.ParticlePrefab, position, velocity, particleRotation, hullGuess, Prefab.DrawOnTop);
|
||||
|
||||
if (particle != null)
|
||||
{
|
||||
particle.Size *= Rand.Range(Prefab.ScaleMin, Prefab.ScaleMax) * sizeMultiplier;
|
||||
particle.HighQualityCollisionDetection = Prefab.HighQualityCollisionDetection;
|
||||
if (colorMultiplier.HasValue) { particle.ColorMultiplier = colorMultiplier.Value.ToVector4(); }
|
||||
if (colorMultiplier.HasValue)
|
||||
{
|
||||
particle.ColorMultiplier = colorMultiplier.Value.ToVector4();
|
||||
}
|
||||
else if (Prefab.ColorMultiplier != Color.White)
|
||||
{
|
||||
particle.ColorMultiplier = Prefab.ColorMultiplier.ToVector4();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,6 +145,8 @@ namespace Barotrauma.Particles
|
||||
|
||||
public readonly bool CopyEntityAngle;
|
||||
|
||||
public readonly Color ColorMultiplier;
|
||||
|
||||
public bool DrawOnTop => forceDrawOnTop || ParticlePrefab.DrawOnTop;
|
||||
private readonly bool forceDrawOnTop;
|
||||
|
||||
@@ -204,11 +213,12 @@ namespace Barotrauma.Particles
|
||||
}
|
||||
|
||||
EmitInterval = element.GetAttributeFloat("emitinterval", 0.0f);
|
||||
ParticlesPerSecond = element.GetAttributeInt("particlespersecond", 0);
|
||||
ParticlesPerSecond = element.GetAttributeFloat("particlespersecond", 0);
|
||||
ParticleAmount = element.GetAttributeInt("particleamount", 0);
|
||||
HighQualityCollisionDetection = element.GetAttributeBool("highqualitycollisiondetection", false);
|
||||
CopyEntityAngle = element.GetAttributeBool("copyentityangle", false);
|
||||
forceDrawOnTop = element.GetAttributeBool("drawontop", false);
|
||||
forceDrawOnTop = element.GetAttributeBool("drawontop", false);
|
||||
ColorMultiplier = element.GetAttributeColor("colormultiplier", Color.White);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,7 +150,7 @@ namespace Barotrauma
|
||||
}
|
||||
sb.AppendLine("\n");
|
||||
sb.AppendLine("Game version " + GameMain.Version +
|
||||
" (" + AssemblyInfo.GetBuildString() + ", branch " + AssemblyInfo.GetGitBranch() + ", revision " + AssemblyInfo.GetGitRevision() + ")");
|
||||
" (" + AssemblyInfo.BuildString + ", branch " + AssemblyInfo.GitBranch + ", revision " + AssemblyInfo.GitRevision + ")");
|
||||
if (GameMain.Config != null)
|
||||
{
|
||||
sb.AppendLine("Graphics mode: " + GameMain.Config.GraphicsWidth + "x" + GameMain.Config.GraphicsHeight + " (" + GameMain.Config.WindowMode.ToString() + ")");
|
||||
@@ -219,7 +219,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
sb.AppendLine("Stack trace: ");
|
||||
sb.AppendLine(exception.StackTrace);
|
||||
sb.AppendLine(exception.StackTrace.CleanupStackTrace());
|
||||
sb.AppendLine("\n");
|
||||
|
||||
if (exception.InnerException != null)
|
||||
@@ -230,7 +230,7 @@ namespace Barotrauma
|
||||
sb.AppendLine("Target site: " + exception.InnerException.TargetSite.ToString());
|
||||
}
|
||||
sb.AppendLine("Stack trace: ");
|
||||
sb.AppendLine(exception.InnerException.StackTrace);
|
||||
sb.AppendLine(exception.InnerException.StackTrace.CleanupStackTrace());
|
||||
}
|
||||
|
||||
sb.AppendLine("Last debug messages:");
|
||||
|
||||
@@ -306,7 +306,7 @@ namespace Barotrauma.CharacterEditor
|
||||
var lastJoint = selectedJoints.LastOrDefault();
|
||||
if (lastJoint != null)
|
||||
{
|
||||
lastLimb = PlayerInput.KeyDown(Keys.LeftAlt) ? lastJoint.LimbB : lastJoint.LimbA;
|
||||
lastLimb = PlayerInput.KeyDown(Keys.LeftAlt) ? lastJoint.LimbA : lastJoint.LimbB;
|
||||
}
|
||||
}
|
||||
if (lastLimb != null)
|
||||
@@ -374,6 +374,14 @@ namespace Barotrauma.CharacterEditor
|
||||
if (Wizard.instance != null) { return; }
|
||||
spriteSheetRect = CalculateSpritesheetRectangle();
|
||||
// Handle shortcut keys
|
||||
if (PlayerInput.KeyHit(Keys.F1))
|
||||
{
|
||||
SetToggle(paramsToggle, !paramsToggle.Selected);
|
||||
}
|
||||
if (PlayerInput.KeyHit(Keys.F5))
|
||||
{
|
||||
RecreateRagdoll();
|
||||
}
|
||||
if (GUI.KeyboardDispatcher.Subscriber == null)
|
||||
{
|
||||
if (PlayerInput.KeyHit(Keys.D1))
|
||||
@@ -445,10 +453,6 @@ namespace Barotrauma.CharacterEditor
|
||||
{
|
||||
SetToggle(showCollidersToggle, !showCollidersToggle.Selected);
|
||||
}
|
||||
if (PlayerInput.KeyHit(Keys.Tab))
|
||||
{
|
||||
SetToggle(paramsToggle, !paramsToggle.Selected);
|
||||
}
|
||||
if (PlayerInput.KeyHit(Keys.L))
|
||||
{
|
||||
SetToggle(lightsToggle, !lightsToggle.Selected);
|
||||
@@ -469,10 +473,6 @@ namespace Barotrauma.CharacterEditor
|
||||
{
|
||||
SetToggle(ikToggle, !ikToggle.Selected);
|
||||
}
|
||||
if (PlayerInput.KeyHit(Keys.F5))
|
||||
{
|
||||
RecreateRagdoll();
|
||||
}
|
||||
}
|
||||
if (PlayerInput.KeyDown(InputType.Left) || PlayerInput.KeyDown(InputType.Right) || PlayerInput.KeyDown(InputType.Up) || PlayerInput.KeyDown(InputType.Down))
|
||||
{
|
||||
@@ -809,7 +809,13 @@ namespace Barotrauma.CharacterEditor
|
||||
else if (showColliders)
|
||||
{
|
||||
character.AnimController.Collider.DebugDraw(spriteBatch, Color.White, forceColor: true);
|
||||
character.AnimController.Limbs.ForEach(l => l.body.DebugDraw(spriteBatch, GUI.Style.Green, forceColor: true));
|
||||
foreach (var limb in character.AnimController.Limbs)
|
||||
{
|
||||
if (!limb.Hide)
|
||||
{
|
||||
limb.body.DebugDraw(spriteBatch, GUI.Style.Green, forceColor: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
spriteBatch.End();
|
||||
|
||||
@@ -935,7 +941,7 @@ namespace Barotrauma.CharacterEditor
|
||||
var lastJoint = selectedJoints.LastOrDefault();
|
||||
if (lastJoint != null)
|
||||
{
|
||||
lastLimb = PlayerInput.KeyDown(Keys.LeftAlt) ? lastJoint.LimbB : lastJoint.LimbA;
|
||||
lastLimb = PlayerInput.KeyDown(Keys.LeftAlt) ? lastJoint.LimbA : lastJoint.LimbB;
|
||||
}
|
||||
}
|
||||
if (lastLimb != null)
|
||||
@@ -953,14 +959,14 @@ namespace Barotrauma.CharacterEditor
|
||||
{
|
||||
UpdateOtherLimbs(lastLimb, l => TryUpdateSubParam(l.Params, "spriteorientation", angle));
|
||||
}
|
||||
}, circleRadius: 40, widgetSize: 15, rotationOffset: MathHelper.Pi, autoFreeze: false, rounding: 10);
|
||||
}, circleRadius: 40, widgetSize: 15, rotationOffset: 0, autoFreeze: false, rounding: 10);
|
||||
}
|
||||
else
|
||||
{
|
||||
var topLeft = spriteSheetControls.RectTransform.TopLeft;
|
||||
GUI.DrawString(spriteBatch, new Vector2(topLeft.X + 350 * GUI.xScale, GameMain.GraphicsHeight - 95 * GUI.yScale), GetCharacterEditorTranslation("SpriteSheetOrientation") + ":", Color.White, Color.Gray * 0.5f, 10, GUI.Font);
|
||||
DrawRadialWidget(spriteBatch, new Vector2(topLeft.X + 610 * GUI.xScale, GameMain.GraphicsHeight - 75 * GUI.yScale), RagdollParams.SpritesheetOrientation, string.Empty, Color.White,
|
||||
angle => TryUpdateRagdollParam("spritesheetorientation", angle), circleRadius: 40, widgetSize: 15, rotationOffset: MathHelper.Pi, autoFreeze: false, rounding: 10);
|
||||
angle => TryUpdateRagdollParam("spritesheetorientation", angle), circleRadius: 40, widgetSize: 15, rotationOffset: 0, autoFreeze: false, rounding: 10);
|
||||
}
|
||||
}
|
||||
// Debug
|
||||
@@ -2383,7 +2389,7 @@ namespace Barotrauma.CharacterEditor
|
||||
IEnumerable<Limb> limbs = selectedLimbs;
|
||||
if (limbs.None())
|
||||
{
|
||||
limbs = selectedJoints.Select(j => PlayerInput.KeyDown(Keys.LeftAlt) ? j.LimbB : j.LimbA);
|
||||
limbs = selectedJoints.Select(j => PlayerInput.KeyDown(Keys.LeftAlt) ? j.LimbA : j.LimbB);
|
||||
}
|
||||
foreach (var limb in limbs)
|
||||
{
|
||||
@@ -3499,12 +3505,8 @@ namespace Barotrauma.CharacterEditor
|
||||
limbJoint.UpperLimit += MathHelper.TwoPi;
|
||||
}
|
||||
}
|
||||
|
||||
if (limbJoint.UpperLimit - limbJoint.LowerLimit > MathHelper.TwoPi)
|
||||
{
|
||||
limbJoint.LowerLimit = MathUtils.WrapAnglePi(limbJoint.LowerLimit);
|
||||
limbJoint.UpperLimit = MathUtils.WrapAnglePi(limbJoint.UpperLimit);
|
||||
}
|
||||
limbJoint.LowerLimit = MathUtils.WrapAnglePi(limbJoint.LowerLimit);
|
||||
limbJoint.UpperLimit = MathUtils.WrapAnglePi(limbJoint.UpperLimit);
|
||||
}
|
||||
|
||||
private Limb GetClosestLimbOnRagdoll(Vector2 targetPos, Func<Limb, bool> filter = null)
|
||||
@@ -4392,7 +4394,7 @@ namespace Barotrauma.CharacterEditor
|
||||
|
||||
if (!altDown && editJoints && selectedJoints.Any() && jointCreationMode == JointCreationMode.None)
|
||||
{
|
||||
GUI.DrawString(spriteBatch, new Vector2(GameMain.GraphicsWidth / 2 - 180, 250), GetCharacterEditorTranslation("HoldLeftAltToManipulateJoint"), Color.White, Color.Black * 0.5f, 10, GUI.Font);
|
||||
GUI.DrawString(spriteBatch, new Vector2(GameMain.GraphicsWidth / 2 - 180, 100), GetCharacterEditorTranslation("HoldLeftAltToManipulateJoint"), Color.White, Color.Black * 0.5f, 10, GUI.Font);
|
||||
}
|
||||
|
||||
foreach (Limb limb in character.AnimController.Limbs)
|
||||
@@ -4450,11 +4452,11 @@ namespace Barotrauma.CharacterEditor
|
||||
}
|
||||
if (editJoints)
|
||||
{
|
||||
if (altDown && joint.BodyA == limb.body.FarseerBody)
|
||||
if (!altDown && joint.BodyA == limb.body.FarseerBody)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (!altDown && joint.BodyB == limb.body.FarseerBody)
|
||||
if (altDown && joint.BodyB == limb.body.FarseerBody)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -4465,7 +4467,13 @@ namespace Barotrauma.CharacterEditor
|
||||
{
|
||||
if (joint.LimitEnabled && jointCreationMode == JointCreationMode.None)
|
||||
{
|
||||
DrawJointLimitWidgets(spriteBatch, limb, joint, tformedJointPos, autoFreeze: true, allowPairEditing: true, rotationOffset: limb.Rotation, holdPosition: true);
|
||||
var otherBody = limb == joint.LimbA ? joint.LimbB : joint.LimbA;
|
||||
float rotation = -otherBody.Rotation + limb.Params.GetSpriteOrientation();
|
||||
if (character.AnimController.Dir < 0)
|
||||
{
|
||||
rotation -= MathHelper.Pi;
|
||||
}
|
||||
DrawJointLimitWidgets(spriteBatch, limb, joint, tformedJointPos, autoFreeze: true, allowPairEditing: true, rotationOffset: rotation, holdPosition: true);
|
||||
}
|
||||
// Is the direction inversed incorrectly?
|
||||
Vector2 to = tformedJointPos + VectorExtensions.ForwardFlipped(joint.LimbB.Rotation - joint.LimbB.Params.GetSpriteOrientation(), 20);
|
||||
@@ -4898,7 +4906,7 @@ namespace Barotrauma.CharacterEditor
|
||||
void RecalculateCollider(Limb l)
|
||||
{
|
||||
// We want the collider to be slightly smaller than the source rect, because the source rect is usually a bit bigger than the graphic.
|
||||
float multiplier = 0.85f;
|
||||
float multiplier = 0.9f;
|
||||
l.body.SetSize(new Vector2(ConvertUnits.ToSimUnits(width), ConvertUnits.ToSimUnits(height)) * l.Scale * RagdollParams.TextureScale * multiplier);
|
||||
TryUpdateLimbParam(l, "radius", ConvertUnits.ToDisplayUnits(l.body.radius / l.Params.Scale / RagdollParams.LimbScale / RagdollParams.TextureScale));
|
||||
TryUpdateLimbParam(l, "width", ConvertUnits.ToDisplayUnits(l.body.width / l.Params.Scale / RagdollParams.LimbScale / RagdollParams.TextureScale));
|
||||
@@ -5010,7 +5018,7 @@ namespace Barotrauma.CharacterEditor
|
||||
{
|
||||
if (joint.LimitEnabled && jointCreationMode == JointCreationMode.None)
|
||||
{
|
||||
DrawJointLimitWidgets(spriteBatch, limb, joint, tformedJointPos, autoFreeze: false, allowPairEditing: true, holdPosition: false);
|
||||
DrawJointLimitWidgets(spriteBatch, limb, joint, tformedJointPos, autoFreeze: false, allowPairEditing: true, holdPosition: false, rotationOffset: joint.LimbB.Params.GetSpriteOrientation());
|
||||
}
|
||||
if (jointSelectionWidget.IsControlled)
|
||||
{
|
||||
@@ -5071,7 +5079,7 @@ namespace Barotrauma.CharacterEditor
|
||||
|
||||
private void DrawJointLimitWidgets(SpriteBatch spriteBatch, Limb limb, LimbJoint joint, Vector2 drawPos, bool autoFreeze, bool allowPairEditing, bool holdPosition, float rotationOffset = 0)
|
||||
{
|
||||
rotationOffset -= limb.Params.GetSpriteOrientation();
|
||||
bool clockWise = joint.Params.ClockWiseRotation;
|
||||
Color angleColor = joint.UpperLimit - joint.LowerLimit > 0 ? GUI.Style.Green * 0.5f : GUI.Style.Red;
|
||||
DrawRadialWidget(spriteBatch, drawPos, MathHelper.ToDegrees(joint.UpperLimit), $"{joint.Params.Name}: {GetCharacterEditorTranslation("UpperLimit")}", Color.Cyan, angle =>
|
||||
{
|
||||
@@ -5111,7 +5119,7 @@ namespace Barotrauma.CharacterEditor
|
||||
DrawAngle(20, angleColor, 4);
|
||||
DrawAngle(40, Color.Cyan);
|
||||
GUI.DrawString(spriteBatch, drawPos, angle.FormatZeroDecimal(), Color.Black, backgroundColor: Color.Cyan, font: GUI.SmallFont);
|
||||
}, circleRadius: 40, rotationOffset: rotationOffset, displayAngle: false, clockWise: false, holdPosition: holdPosition);
|
||||
}, circleRadius: 40, rotationOffset: rotationOffset, displayAngle: false, clockWise: clockWise, holdPosition: holdPosition);
|
||||
DrawRadialWidget(spriteBatch, drawPos, MathHelper.ToDegrees(joint.LowerLimit), $"{joint.Params.Name}: {GetCharacterEditorTranslation("LowerLimit")}", Color.Yellow, angle =>
|
||||
{
|
||||
joint.LowerLimit = MathHelper.ToRadians(angle);
|
||||
@@ -5150,12 +5158,12 @@ namespace Barotrauma.CharacterEditor
|
||||
DrawAngle(20, angleColor, 4);
|
||||
DrawAngle(25, Color.Yellow);
|
||||
GUI.DrawString(spriteBatch, drawPos, angle.FormatZeroDecimal(), Color.Black, backgroundColor: Color.Yellow, font: GUI.SmallFont);
|
||||
}, circleRadius: 25, rotationOffset: rotationOffset, displayAngle: false, clockWise: false, holdPosition: holdPosition);
|
||||
}, circleRadius: 25, rotationOffset: rotationOffset, displayAngle: false, clockWise: clockWise, holdPosition: holdPosition);
|
||||
void DrawAngle(float radius, Color color, float thickness = 5)
|
||||
{
|
||||
float angle = joint.UpperLimit - joint.LowerLimit;
|
||||
ShapeExtensions.DrawSector(spriteBatch, drawPos, radius, angle, 40, color,
|
||||
offset: -rotationOffset - joint.UpperLimit + MathHelper.PiOver2, thickness: thickness);
|
||||
float offset = clockWise ? rotationOffset + joint.LowerLimit - MathHelper.PiOver2 : rotationOffset - joint.UpperLimit - MathHelper.PiOver2;
|
||||
ShapeExtensions.DrawSector(spriteBatch, drawPos, radius, angle, 40, color, offset: offset, thickness: thickness);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5244,8 +5252,8 @@ namespace Barotrauma.CharacterEditor
|
||||
{
|
||||
angle = 0;
|
||||
}
|
||||
float drawAngle = clockWise ? -angle : angle;
|
||||
var widgetDrawPos = drawPos + VectorExtensions.ForwardFlipped(MathHelper.ToRadians(drawAngle) + rotationOffset, circleRadius);
|
||||
float drawAngle = clockWise ? angle : -angle;
|
||||
var widgetDrawPos = drawPos + VectorExtensions.Forward(MathHelper.ToRadians(drawAngle) + rotationOffset - MathHelper.PiOver2, circleRadius);
|
||||
GUI.DrawLine(spriteBatch, drawPos, widgetDrawPos, color);
|
||||
DrawWidget(spriteBatch, widgetDrawPos, WidgetType.Rectangle, widgetSize, color, toolTip, () =>
|
||||
{
|
||||
@@ -5253,8 +5261,8 @@ namespace Barotrauma.CharacterEditor
|
||||
ShapeExtensions.DrawCircle(spriteBatch, drawPos, circleRadius, 40, color, thickness: 1);
|
||||
Vector2 d = PlayerInput.MousePosition - drawPos;
|
||||
float newAngle = clockWise
|
||||
? MathUtils.VectorToAngle(d) - MathHelper.PiOver2 + rotationOffset
|
||||
: -MathUtils.VectorToAngle(d) + MathHelper.PiOver2 - rotationOffset;
|
||||
? MathUtils.VectorToAngle(d) + MathHelper.PiOver2 - rotationOffset
|
||||
: -MathUtils.VectorToAngle(d) - MathHelper.PiOver2 + rotationOffset;
|
||||
angle = MathHelper.ToDegrees(wrapAnglePi ? MathUtils.WrapAnglePi(newAngle) : MathUtils.WrapAngleTwoPi(newAngle));
|
||||
angle = (float)Math.Round(angle / rounding) * rounding;
|
||||
if (angle >= 360 || angle <= -360) { angle = 0; }
|
||||
@@ -5263,7 +5271,7 @@ namespace Barotrauma.CharacterEditor
|
||||
GUI.DrawString(spriteBatch, drawPos, angle.FormatZeroDecimal(), Color.Black, backgroundColor: color, font: GUI.SmallFont);
|
||||
}
|
||||
onClick(angle);
|
||||
var zeroPos = drawPos + VectorExtensions.ForwardFlipped(rotationOffset, circleRadius);
|
||||
var zeroPos = drawPos + VectorExtensions.Forward(rotationOffset - MathHelper.PiOver2, circleRadius);
|
||||
GUI.DrawLine(spriteBatch, drawPos, zeroPos, GUI.Style.Red, width: 3);
|
||||
}, autoFreeze, holdPosition, onHovered: () =>
|
||||
{
|
||||
|
||||
@@ -335,6 +335,7 @@ namespace Barotrauma
|
||||
{
|
||||
base.Select();
|
||||
|
||||
GUI.PreventPauseMenuToggle = false;
|
||||
pointerLightSource = new LightSource(Vector2.Zero, 1000.0f, Color.White, submarine: null);
|
||||
GameMain.LightManager.AddLight(pointerLightSource);
|
||||
topPanel.ClearChildren();
|
||||
|
||||
@@ -424,6 +424,8 @@ namespace Barotrauma
|
||||
#region Selection
|
||||
public override void Select()
|
||||
{
|
||||
GUI.PreventPauseMenuToggle = false;
|
||||
|
||||
base.Select();
|
||||
|
||||
if (GameMain.Client != null)
|
||||
@@ -806,19 +808,6 @@ namespace Barotrauma
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool JoinServerClicked(GUIButton button, object obj)
|
||||
{
|
||||
GameMain.ServerListScreen.Select();
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool SteamWorkshopClicked(GUIButton button, object obj)
|
||||
{
|
||||
if (!Steam.SteamManager.IsInitialized) { return false; }
|
||||
GameMain.SteamWorkshopScreen.Select();
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool ChangeMaxPlayers(GUIButton button, object obj)
|
||||
{
|
||||
int.TryParse(maxPlayersBox.Text, out int currMaxPlayers);
|
||||
@@ -829,33 +818,10 @@ namespace Barotrauma
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool HostServerClicked(GUIButton button, object obj)
|
||||
private void StartServer()
|
||||
{
|
||||
string name = serverNameBox.Text;
|
||||
if (string.IsNullOrEmpty(name))
|
||||
{
|
||||
serverNameBox.Flash();
|
||||
return false;
|
||||
}
|
||||
|
||||
/*if (!int.TryParse(portBox.Text, out int port) || port < 0 || port > 65535)
|
||||
{
|
||||
portBox.Text = NetConfig.DefaultPort.ToString();
|
||||
portBox.Flash();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int queryPort = 0;
|
||||
#if USE_STEAM
|
||||
if (!int.TryParse(queryPortBox.Text, out queryPort) || queryPort < 0 || queryPort > 65535)
|
||||
{
|
||||
portBox.Text = NetConfig.DefaultQueryPort.ToString();
|
||||
portBox.Flash();
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
*/
|
||||
GameMain.NetLobbyScreen?.Release();
|
||||
GameMain.NetLobbyScreen = new NetLobbyScreen();
|
||||
try
|
||||
@@ -919,8 +885,6 @@ namespace Barotrauma
|
||||
{
|
||||
DebugConsole.ThrowError("Failed to start server", e);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool QuitClicked(GUIButton button, object obj)
|
||||
@@ -996,7 +960,7 @@ namespace Barotrauma
|
||||
GUI.Draw(Cam, spriteBatch);
|
||||
|
||||
#if !UNSTABLE
|
||||
string versionString = "Barotrauma v" + GameMain.Version + " (" + AssemblyInfo.GetBuildString() + ", branch " + AssemblyInfo.GetGitBranch() + ", revision " + AssemblyInfo.GetGitRevision() + ")";
|
||||
string versionString = "Barotrauma v" + GameMain.Version + " (" + AssemblyInfo.BuildString + ", branch " + AssemblyInfo.GitBranch + ", revision " + AssemblyInfo.GitRevision + ")";
|
||||
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)
|
||||
@@ -1062,7 +1026,7 @@ namespace Barotrauma
|
||||
GameAnalyticsManager.AddErrorEventOnce(
|
||||
"MainMenuScreen.StartGame:IOException" + selectedSub.Name,
|
||||
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||
"Copying the file \"" + selectedSub.FilePath + "\" failed.\n" + e.Message + "\n" + Environment.StackTrace);
|
||||
"Copying the file \"" + selectedSub.FilePath + "\" failed.\n" + e.Message + "\n" + Environment.StackTrace.CleanupStackTrace());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1334,7 +1298,35 @@ namespace Barotrauma
|
||||
|
||||
new GUIButton(new RectTransform(new Vector2(0.4f, 0.07f), content.RectTransform), TextManager.Get("StartServerButton"), style: "GUIButtonLarge")
|
||||
{
|
||||
OnClicked = HostServerClicked
|
||||
OnClicked = (btn, userdata) =>
|
||||
{
|
||||
string name = serverNameBox.Text;
|
||||
if (string.IsNullOrEmpty(name))
|
||||
{
|
||||
serverNameBox.Flash();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ForbiddenWordFilter.IsForbidden(name, out string forbiddenWord))
|
||||
{
|
||||
var msgBox = new GUIMessageBox("",
|
||||
TextManager.GetWithVariables("forbiddenservernameverification", new string[] { "[forbiddenword]", "[servername]" }, new string[] { forbiddenWord, name }),
|
||||
new string[] { TextManager.Get("yes"), TextManager.Get("no") });
|
||||
msgBox.Buttons[0].OnClicked += (_, __) =>
|
||||
{
|
||||
StartServer();
|
||||
msgBox.Close();
|
||||
return true;
|
||||
};
|
||||
msgBox.Buttons[1].OnClicked += msgBox.Close;
|
||||
}
|
||||
else
|
||||
{
|
||||
StartServer();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1169,7 +1169,7 @@ namespace Barotrauma
|
||||
|
||||
Character.Controlled = null;
|
||||
GameMain.LightManager.LosEnabled = false;
|
||||
|
||||
GUI.PreventPauseMenuToggle = false;
|
||||
CampaignCharacterDiscarded = false;
|
||||
|
||||
chatInput.Select();
|
||||
@@ -2799,7 +2799,7 @@ namespace Barotrauma
|
||||
var variantButton = CreateJobVariantButton(jobPrefab, variantIndex, images.Length, jobButton);
|
||||
variantButton.OnClicked = (btn, obj) =>
|
||||
{
|
||||
currSelected.Selected = false;
|
||||
if (currSelected != null) { currSelected.Selected = false; }
|
||||
int k = ((Pair<JobPrefab, int>)obj).Second;
|
||||
btn.Parent.UserData = obj;
|
||||
for (int j = 0; j < images.Length; j++)
|
||||
|
||||
@@ -153,6 +153,7 @@ namespace Barotrauma
|
||||
private GUITickBox filterVoip;
|
||||
private List<GUITickBox> playStyleTickBoxes;
|
||||
private List<GUITickBox> gameModeTickBoxes;
|
||||
private GUITickBox filterOffensive;
|
||||
|
||||
private string sortedBy;
|
||||
|
||||
@@ -325,7 +326,7 @@ namespace Barotrauma
|
||||
|
||||
filterSameVersion = new GUITickBox(new RectTransform(new Vector2(1.0f, elementHeight), filters.Content.RectTransform), TextManager.Get("FilterSameVersion"))
|
||||
{
|
||||
ToolTip = TextManager.Get("FilterSameVersion"),
|
||||
UserData = TextManager.Get("FilterSameVersion"),
|
||||
Selected = true,
|
||||
OnSelected = (tickBox) => { FilterServers(); return true; }
|
||||
};
|
||||
@@ -333,39 +334,47 @@ namespace Barotrauma
|
||||
|
||||
filterPassword = new GUITickBox(new RectTransform(new Vector2(1.0f, elementHeight), filters.Content.RectTransform), TextManager.Get("FilterPassword"))
|
||||
{
|
||||
ToolTip = TextManager.Get("FilterPassword"),
|
||||
UserData = TextManager.Get("FilterPassword"),
|
||||
OnSelected = (tickBox) => { FilterServers(); return true; }
|
||||
};
|
||||
filterTextList.Add(filterPassword.TextBlock);
|
||||
|
||||
filterIncompatible = new GUITickBox(new RectTransform(new Vector2(1.0f, elementHeight), filters.Content.RectTransform), TextManager.Get("FilterIncompatibleServers"))
|
||||
{
|
||||
ToolTip = TextManager.Get("FilterIncompatibleServers"),
|
||||
UserData = TextManager.Get("FilterIncompatibleServers"),
|
||||
OnSelected = (tickBox) => { FilterServers(); return true; }
|
||||
};
|
||||
filterTextList.Add(filterIncompatible.TextBlock);
|
||||
|
||||
filterFull = new GUITickBox(new RectTransform(new Vector2(1.0f, elementHeight), filters.Content.RectTransform), TextManager.Get("FilterFullServers"))
|
||||
{
|
||||
ToolTip = TextManager.Get("FilterFullServers"),
|
||||
UserData = TextManager.Get("FilterFullServers"),
|
||||
OnSelected = (tickBox) => { FilterServers(); return true; }
|
||||
};
|
||||
filterTextList.Add(filterFull.TextBlock);
|
||||
|
||||
filterEmpty = new GUITickBox(new RectTransform(new Vector2(1.0f, elementHeight), filters.Content.RectTransform), TextManager.Get("FilterEmptyServers"))
|
||||
{
|
||||
ToolTip = TextManager.Get("FilterEmptyServers"),
|
||||
UserData = TextManager.Get("FilterEmptyServers"),
|
||||
OnSelected = (tickBox) => { FilterServers(); return true; }
|
||||
};
|
||||
filterTextList.Add(filterEmpty.TextBlock);
|
||||
|
||||
filterWhitelisted = new GUITickBox(new RectTransform(new Vector2(1.0f, elementHeight), filters.Content.RectTransform), TextManager.Get("FilterWhitelistedServers"))
|
||||
{
|
||||
ToolTip = TextManager.Get("FilterWhitelistedServers"),
|
||||
UserData = TextManager.Get("FilterWhitelistedServers"),
|
||||
OnSelected = (tickBox) => { FilterServers(); return true; }
|
||||
};
|
||||
filterTextList.Add(filterWhitelisted.TextBlock);
|
||||
|
||||
filterOffensive = new GUITickBox(new RectTransform(new Vector2(1.0f, elementHeight), filters.Content.RectTransform), TextManager.Get("FilterOffensiveServers"))
|
||||
{
|
||||
UserData = TextManager.Get("FilterOffensiveServers"),
|
||||
ToolTip = TextManager.Get("FilterOffensiveServersToolTip"),
|
||||
OnSelected = (tickBox) => { FilterServers(); return true; }
|
||||
};
|
||||
filterTextList.Add(filterOffensive.TextBlock);
|
||||
|
||||
// Filter Tags
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), filters.Content.RectTransform), TextManager.Get("servertags"), font: GUI.SubHeadingFont)
|
||||
{
|
||||
@@ -374,35 +383,35 @@ namespace Barotrauma
|
||||
|
||||
filterKarma = new GUITickBox(new RectTransform(new Vector2(1.0f, elementHeight), filters.Content.RectTransform), TextManager.Get("servertag.karma.true"))
|
||||
{
|
||||
ToolTip = TextManager.Get("servertag.karma.true"),
|
||||
UserData = TextManager.Get("servertag.karma.true"),
|
||||
OnSelected = (tickBox) => { FilterServers(); return true; }
|
||||
};
|
||||
filterTextList.Add(filterKarma.TextBlock);
|
||||
|
||||
filterTraitor = new GUITickBox(new RectTransform(new Vector2(1.0f, elementHeight), filters.Content.RectTransform), TextManager.Get("servertag.traitors.true"))
|
||||
{
|
||||
ToolTip = TextManager.Get("servertag.traitors.true"),
|
||||
UserData = TextManager.Get("servertag.traitors.true"),
|
||||
OnSelected = (tickBox) => { FilterServers(); return true; }
|
||||
};
|
||||
filterTextList.Add(filterTraitor.TextBlock);
|
||||
|
||||
filterFriendlyFire = new GUITickBox(new RectTransform(new Vector2(1.0f, elementHeight), filters.Content.RectTransform), TextManager.Get("servertag.friendlyfire.false"))
|
||||
{
|
||||
ToolTip = TextManager.Get("servertag.friendlyfire.false"),
|
||||
UserData = TextManager.Get("servertag.friendlyfire.false"),
|
||||
OnSelected = (tickBox) => { FilterServers(); return true; }
|
||||
};
|
||||
filterTextList.Add(filterFriendlyFire.TextBlock);
|
||||
|
||||
filterVoip = new GUITickBox(new RectTransform(new Vector2(1.0f, elementHeight), filters.Content.RectTransform), TextManager.Get("servertag.voip.false"))
|
||||
{
|
||||
ToolTip = TextManager.Get("servertag.voip.false"),
|
||||
UserData = TextManager.Get("servertag.voip.false"),
|
||||
OnSelected = (tickBox) => { FilterServers(); return true; }
|
||||
};
|
||||
filterTextList.Add(filterVoip.TextBlock);
|
||||
|
||||
filterModded = new GUITickBox(new RectTransform(new Vector2(1.0f, elementHeight), filters.Content.RectTransform), TextManager.Get("servertag.modded.true"))
|
||||
{
|
||||
ToolTip = TextManager.Get("servertag.modded.true"),
|
||||
UserData = TextManager.Get("servertag.modded.true"),
|
||||
OnSelected = (tickBox) => { FilterServers(); return true; }
|
||||
};
|
||||
filterTextList.Add(filterModded.TextBlock);
|
||||
@@ -449,7 +458,9 @@ namespace Barotrauma
|
||||
filters.Content.RectTransform.SizeChanged += () =>
|
||||
{
|
||||
filters.Content.RectTransform.RecalculateChildren(true, true);
|
||||
filterTextList.ForEach(t => t.Text = t.ToolTip);
|
||||
filterTextList.ForEach(t => t.Text = t.Parent.Parent.UserData as string);
|
||||
gameModeTickBoxes.ForEach(tb => tb.Text = tb.ToolTip);
|
||||
playStyleTickBoxes.ForEach(tb => tb.Text = tb.ToolTip);
|
||||
GUITextBlock.AutoScaleAndNormalize(filterTextList, defaultScale: 1.0f);
|
||||
if (filterTextList[0].TextScale < 0.8f)
|
||||
{
|
||||
@@ -579,7 +590,7 @@ namespace Barotrauma
|
||||
{
|
||||
ClientNameBox.Flash();
|
||||
ClientNameBox.Select();
|
||||
GUI.PlayUISound(GUISoundType.PickItemFail);
|
||||
SoundPlayer.PlayUISound(GUISoundType.PickItemFail);
|
||||
return false;
|
||||
}
|
||||
ShowDirectJoinPrompt();
|
||||
@@ -1050,6 +1061,7 @@ namespace Barotrauma
|
||||
(!filterFull.Selected || serverInfo.PlayerCount < serverInfo.MaxPlayers) &&
|
||||
(!filterEmpty.Selected || serverInfo.PlayerCount > 0) &&
|
||||
(!filterWhitelisted.Selected || serverInfo.UsingWhiteList == true) &&
|
||||
(filterOffensive.Selected || !ForbiddenWordFilter.IsForbidden(serverInfo.ServerName)) &&
|
||||
(!filterKarma.Selected || serverInfo.KarmaEnabled == true) &&
|
||||
(!filterFriendlyFire.Selected || serverInfo.FriendlyFireEnabled == false) &&
|
||||
(!filterTraitor.Selected || serverInfo.TraitorsEnabled == YesNoMaybe.Yes || serverInfo.TraitorsEnabled == YesNoMaybe.Maybe) &&
|
||||
@@ -1406,7 +1418,7 @@ namespace Barotrauma
|
||||
#if DEBUG
|
||||
DebugConsole.ThrowError($"Failed to parse a Steam friend's connect command ({connectCommand})", e);
|
||||
#else
|
||||
DebugConsole.Log($"Failed to parse a Steam friend's connect command ({connectCommand})\n" + e.StackTrace);
|
||||
DebugConsole.Log($"Failed to parse a Steam friend's connect command ({connectCommand})\n" + e.StackTrace.CleanupStackTrace());
|
||||
#endif
|
||||
info.ConnectName = null;
|
||||
info.ConnectEndpoint = null;
|
||||
@@ -2109,7 +2121,7 @@ namespace Barotrauma
|
||||
{
|
||||
ClientNameBox.Flash();
|
||||
ClientNameBox.Select();
|
||||
GUI.PlayUISound(GUISoundType.PickItemFail);
|
||||
SoundPlayer.PlayUISound(GUISoundType.PickItemFail);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -1156,7 +1156,7 @@ namespace Barotrauma
|
||||
|
||||
if (itemContentPackage == null)
|
||||
{
|
||||
string errorMsg = "Failed to edit workshop item (content package null)\n" + Environment.StackTrace;
|
||||
string errorMsg = "Failed to edit workshop item (content package null)\n" + Environment.StackTrace.CleanupStackTrace();
|
||||
DebugConsole.ThrowError(errorMsg);
|
||||
GameAnalyticsManager.AddErrorEventOnce("SteamWorkshopScreen.ShowCreateItemFrame:ContentPackageNull", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||
return;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Barotrauma.Extensions;
|
||||
using Barotrauma.Extensions;
|
||||
using Barotrauma.Items.Components;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
@@ -33,6 +33,18 @@ namespace Barotrauma
|
||||
Default,
|
||||
Wiring
|
||||
}
|
||||
|
||||
public enum WarningType
|
||||
{
|
||||
NoWaypoints,
|
||||
NoHulls,
|
||||
DisconnectedVents,
|
||||
NoHumanSpawnpoints,
|
||||
NoCargoSpawnpoints,
|
||||
NoBallastTag,
|
||||
NonLinkedGaps,
|
||||
TooManyLights
|
||||
}
|
||||
|
||||
public static Vector2 MouseDragStart = Vector2.Zero;
|
||||
|
||||
@@ -85,11 +97,19 @@ namespace Barotrauma
|
||||
private GUIFrame previouslyUsedPanel;
|
||||
private GUIListBox previouslyUsedList;
|
||||
|
||||
private GUIFrame undoBufferPanel;
|
||||
private GUIListBox undoBufferList;
|
||||
|
||||
private GUIDropDown linkedSubBox;
|
||||
|
||||
private static GUIComponent autoSaveLabel;
|
||||
private static int maxAutoSaves = GameSettings.MaximumAutoSaves;
|
||||
|
||||
public static bool BulkItemBufferInUse;
|
||||
public static List<AddOrDeleteCommand> BulkItemBuffer = new List<AddOrDeleteCommand>();
|
||||
|
||||
public static List<WarningType> SuppressedWarnings = new List<WarningType>();
|
||||
|
||||
//a Character used for picking up and manipulating items
|
||||
private Character dummyCharacter;
|
||||
|
||||
@@ -109,12 +129,17 @@ namespace Barotrauma
|
||||
/// </summary>
|
||||
private Vector2 oldItemPosition;
|
||||
|
||||
/// <summary>
|
||||
/// Global undo/redo state for the sub editor and a selector index for it
|
||||
/// <see cref="Command"/>
|
||||
/// </summary>
|
||||
public static readonly List<Command> Commands = new List<Command>();
|
||||
private static int commandIndex;
|
||||
|
||||
private GUIFrame wiringToolPanel;
|
||||
|
||||
private DateTime editorSelectedTime;
|
||||
|
||||
private const string containerDeleteTag = "containerdelete";
|
||||
|
||||
private GUIImage previewImage;
|
||||
private GUILayoutGroup previewImageButtonHolder;
|
||||
|
||||
@@ -273,6 +298,7 @@ namespace Barotrauma
|
||||
OnClicked = (btn, userData) =>
|
||||
{
|
||||
previouslyUsedPanel.Visible = false;
|
||||
undoBufferPanel.Visible = false;
|
||||
showEntitiesPanel.Visible = !showEntitiesPanel.Visible;
|
||||
showEntitiesPanel.RectTransform.AbsoluteOffset = new Point(Math.Max(Math.Max(btn.Rect.X, entityCountPanel.Rect.Right), saveAssemblyFrame.Rect.Right), TopPanel.Rect.Height);
|
||||
return true;
|
||||
@@ -285,12 +311,26 @@ namespace Barotrauma
|
||||
OnClicked = (btn, userData) =>
|
||||
{
|
||||
showEntitiesPanel.Visible = false;
|
||||
undoBufferPanel.Visible = false;
|
||||
previouslyUsedPanel.Visible = !previouslyUsedPanel.Visible;
|
||||
previouslyUsedPanel.RectTransform.AbsoluteOffset = new Point(Math.Max(Math.Max(btn.Rect.X, entityCountPanel.Rect.Right), saveAssemblyFrame.Rect.Right), TopPanel.Rect.Height);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
var undoBufferButton = new GUIButton(new RectTransform(new Vector2(0.9f, 0.9f), paddedTopPanel.RectTransform, scaleBasis: ScaleBasis.BothHeight), "", style: "UndoHistoryButton")
|
||||
{
|
||||
ToolTip = TextManager.Get("Editor.UndoHistoryButton"),
|
||||
OnClicked = (btn, userData) =>
|
||||
{
|
||||
showEntitiesPanel.Visible = false;
|
||||
previouslyUsedPanel.Visible = false;
|
||||
undoBufferPanel.Visible = !undoBufferPanel.Visible;
|
||||
undoBufferPanel.RectTransform.AbsoluteOffset = new Point(Math.Max(Math.Max(btn.Rect.X, entityCountPanel.Rect.Right), saveAssemblyFrame.Rect.Right), TopPanel.Rect.Height);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
new GUIFrame(new RectTransform(new Vector2(0.01f, 0.9f), paddedTopPanel.RectTransform), style: "VerticalLine");
|
||||
|
||||
subNameLabel = new GUITextBlock(new RectTransform(new Vector2(0.3f, 0.9f), paddedTopPanel.RectTransform, Anchor.CenterLeft),
|
||||
@@ -407,6 +447,45 @@ namespace Barotrauma
|
||||
|
||||
//-----------------------------------------------
|
||||
|
||||
undoBufferPanel = new GUIFrame(new RectTransform(new Vector2(0.15f, 0.2f), GUI.Canvas) { MinSize = new Point(200, 200) })
|
||||
{
|
||||
Visible = false
|
||||
};
|
||||
undoBufferList = new GUIListBox(new RectTransform(new Vector2(0.925f, 0.9f), undoBufferPanel.RectTransform, Anchor.Center))
|
||||
{
|
||||
ScrollBarVisible = true,
|
||||
OnSelected = (_, userData) =>
|
||||
{
|
||||
int index;
|
||||
if (userData is Command command)
|
||||
{
|
||||
index = Commands.IndexOf(command);
|
||||
}
|
||||
else
|
||||
{
|
||||
index = -1;
|
||||
}
|
||||
|
||||
int diff = index- commandIndex;
|
||||
int amount = Math.Abs(diff);
|
||||
|
||||
if (diff >= 0)
|
||||
{
|
||||
Redo(amount + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
Undo(amount - 1);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
UpdateUndoHistoryPanel();
|
||||
|
||||
//-----------------------------------------------
|
||||
|
||||
showEntitiesPanel = new GUIFrame(new RectTransform(new Vector2(0.08f, 0.5f), GUI.Canvas)
|
||||
{
|
||||
MinSize = new Point(170, 0)
|
||||
@@ -885,6 +964,7 @@ namespace Barotrauma
|
||||
{
|
||||
base.Select();
|
||||
|
||||
GUI.PreventPauseMenuToggle = false;
|
||||
if (!Directory.Exists(autoSavePath))
|
||||
{
|
||||
System.IO.DirectoryInfo e = Directory.CreateDirectory(autoSavePath);
|
||||
@@ -1043,6 +1123,7 @@ namespace Barotrauma
|
||||
|
||||
MapEntity.DeselectAll();
|
||||
MapEntity.SelectionGroups.Clear();
|
||||
ClearUndoBuffer();
|
||||
|
||||
SetMode(Mode.Default);
|
||||
|
||||
@@ -1062,147 +1143,15 @@ namespace Barotrauma
|
||||
GameMain.World.ProcessChanges();
|
||||
}
|
||||
|
||||
if (GUIMessageBox.MessageBoxes.Any(mbox => (mbox as GUIMessageBox)?.Tag == containerDeleteTag))
|
||||
{
|
||||
for (int i = 0; i < GUIMessageBox.MessageBoxes.Count; i++)
|
||||
{
|
||||
GUIMessageBox box = GUIMessageBox.MessageBoxes[i] as GUIMessageBox;
|
||||
if (box != null && box.Tag != containerDeleteTag) continue;
|
||||
box?.Close();
|
||||
i--; // Take into account the message boxes removing themselves from the list when closed
|
||||
}
|
||||
}
|
||||
ClearFilter();
|
||||
}
|
||||
|
||||
public void HandleContainerContentsDeletion(Item itemToDelete, Inventory itemInventory)
|
||||
{
|
||||
string itemNames = string.Empty;
|
||||
|
||||
foreach (Item item in itemInventory.Items)
|
||||
{
|
||||
if (item == null) continue;
|
||||
itemNames += item.Name + "\n";
|
||||
}
|
||||
|
||||
if (itemNames.Length > 0)
|
||||
{
|
||||
// Multiple prompts open
|
||||
if (GUIMessageBox.MessageBoxes.Any(mbox => (mbox as GUIMessageBox)?.Tag == containerDeleteTag))
|
||||
{
|
||||
var msgBox = new GUIMessageBox(itemToDelete.Name, TextManager.Get("DeletingContainerWithItems") + itemNames, new[] { TextManager.Get("Yes"), TextManager.Get("No"), TextManager.Get("YesToAll"), TextManager.Get("NoToAll") }, tag: containerDeleteTag);
|
||||
|
||||
// Yes
|
||||
msgBox.Buttons[0].OnClicked = (btn, userdata) =>
|
||||
{
|
||||
itemInventory.DeleteAllItems();
|
||||
msgBox.Close();
|
||||
return true;
|
||||
};
|
||||
|
||||
// No
|
||||
msgBox.Buttons[1].OnClicked = (btn, userdata) =>
|
||||
{
|
||||
if (Selected == GameMain.SubEditorScreen)
|
||||
{
|
||||
foreach (Item item in itemInventory.Items)
|
||||
{
|
||||
item?.Drop(null);
|
||||
}
|
||||
}
|
||||
else // If current screen is not subeditor, delete anyway to avoid lingering objects
|
||||
{
|
||||
itemInventory.DeleteAllItems();
|
||||
}
|
||||
|
||||
msgBox.Close();
|
||||
return true;
|
||||
};
|
||||
|
||||
// Yes to All
|
||||
msgBox.Buttons[2].OnClicked = (btn, userdata) =>
|
||||
{
|
||||
for (int i = 0; i < GUIMessageBox.MessageBoxes.Count; i++)
|
||||
{
|
||||
GUIMessageBox box = GUIMessageBox.MessageBoxes[i] as GUIMessageBox;
|
||||
if (box?.Tag != msgBox.Tag || box == msgBox) continue;
|
||||
GUIButton button = box?.Buttons[0];
|
||||
button?.OnClicked(button, button.UserData);
|
||||
i--; // Take into account the message boxes removing themselves from the list when closed
|
||||
}
|
||||
|
||||
itemInventory.DeleteAllItems();
|
||||
msgBox.Close();
|
||||
return true;
|
||||
};
|
||||
|
||||
// No to all
|
||||
msgBox.Buttons[3].OnClicked = (btn, userdata) =>
|
||||
{
|
||||
for (int i = 0; i < GUIMessageBox.MessageBoxes.Count; i++)
|
||||
{
|
||||
GUIMessageBox box = GUIMessageBox.MessageBoxes[i] as GUIMessageBox;
|
||||
if (box?.Tag != msgBox.Tag || box == msgBox) continue;
|
||||
GUIButton button = box?.Buttons[1];
|
||||
button?.OnClicked(button, button.UserData);
|
||||
i--; // Take into account the message boxes removing themselves from the list when closed
|
||||
}
|
||||
|
||||
if (Selected == GameMain.SubEditorScreen)
|
||||
{
|
||||
foreach (Item item in itemInventory.Items)
|
||||
{
|
||||
item?.Drop(null);
|
||||
}
|
||||
}
|
||||
else // If current screen is not subeditor, delete anyway to avoid lingering objects
|
||||
{
|
||||
itemInventory.DeleteAllItems();
|
||||
}
|
||||
|
||||
msgBox.Close();
|
||||
return true;
|
||||
};
|
||||
}
|
||||
else // Single prompt
|
||||
{
|
||||
var msgBox = new GUIMessageBox(itemToDelete.Name, TextManager.Get("DeletingContainerWithItems") + itemNames, new[] { TextManager.Get("Yes"), TextManager.Get("No") }, tag: containerDeleteTag);
|
||||
|
||||
// Yes
|
||||
msgBox.Buttons[0].OnClicked = (btn, userdata) =>
|
||||
{
|
||||
itemInventory.DeleteAllItems();
|
||||
msgBox.Close();
|
||||
return true;
|
||||
};
|
||||
|
||||
// No
|
||||
msgBox.Buttons[1].OnClicked = (btn, userdata) =>
|
||||
{
|
||||
if (Selected == GameMain.SubEditorScreen)
|
||||
{
|
||||
foreach (Item item in itemInventory.Items)
|
||||
{
|
||||
item?.Drop(null);
|
||||
}
|
||||
}
|
||||
else // If current screen is not subeditor, delete anyway to avoid lingering objects
|
||||
{
|
||||
itemInventory.DeleteAllItems();
|
||||
}
|
||||
|
||||
msgBox.Close();
|
||||
return true;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateDummyCharacter()
|
||||
{
|
||||
if (dummyCharacter != null) RemoveDummyCharacter();
|
||||
|
||||
dummyCharacter = Character.Create(CharacterPrefab.HumanSpeciesName, Vector2.Zero, "", hasAi: false);
|
||||
dummyCharacter.Info.Name = "Galldren";
|
||||
|
||||
//make space for the entity menu
|
||||
for (int i = 0; i < dummyCharacter.Inventory.SlotPositions.Length; i++)
|
||||
@@ -2609,7 +2558,7 @@ namespace Barotrauma
|
||||
var selectedSub = new Submarine(selectedSubInfo);
|
||||
Submarine.MainSub = selectedSub;
|
||||
Submarine.MainSub.UpdateTransform(interpolate: false);
|
||||
|
||||
ClearUndoBuffer();
|
||||
CreateDummyCharacter();
|
||||
|
||||
string name = Submarine.MainSub.Info.Name;
|
||||
@@ -2790,6 +2739,7 @@ namespace Barotrauma
|
||||
|
||||
MapEntity.DeselectAll();
|
||||
MapEntity.FilteredSelectedList.Clear();
|
||||
ClearUndoBuffer();
|
||||
|
||||
CreateDummyCharacter();
|
||||
if (newMode == Mode.Wiring)
|
||||
@@ -2922,7 +2872,7 @@ namespace Barotrauma
|
||||
CreateBackgroundColorPicker();
|
||||
break;
|
||||
case "selectsame":
|
||||
IEnumerable<MapEntity> matching = MapEntity.mapEntityList.Where(e => targets.Any(t => t.prefab.Identifier == e.prefab.Identifier) && !MapEntity.SelectedList.Contains(e));
|
||||
IEnumerable<MapEntity> matching = MapEntity.mapEntityList.Where(e => e.prefab != null && targets.Any(t => t.prefab.Identifier == e.prefab.Identifier) && !MapEntity.SelectedList.Contains(e));
|
||||
MapEntity.SelectedList.AddRange(matching);
|
||||
break;
|
||||
case "copy":
|
||||
@@ -2935,7 +2885,8 @@ namespace Barotrauma
|
||||
MapEntity.Paste(cam.ScreenToWorld(contextMenu.Rect.Location.ToVector2()));
|
||||
break;
|
||||
case "delete":
|
||||
targets.ForEach(me => { me.Remove(); });
|
||||
StoreCommand(new AddOrDeleteCommand(targets, true));
|
||||
targets.ForEach(me => { if (!me.Removed) { me.Remove(); }});
|
||||
break;
|
||||
case "open" when target != null:
|
||||
OpenItem(target);
|
||||
@@ -3234,7 +3185,13 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
});
|
||||
GUI.PlayUISound(spawnedItem ? GUISoundType.PickItem : GUISoundType.PickItemFail);
|
||||
|
||||
List<MapEntity> placedEntities = itemInstance.Where(it => !it.Removed).Cast<MapEntity>().ToList();
|
||||
if (placedEntities.Any())
|
||||
{
|
||||
StoreCommand(new AddOrDeleteCommand(placedEntities, false));
|
||||
}
|
||||
SoundPlayer.PlayUISound(spawnedItem ? GUISoundType.PickItem : GUISoundType.PickItemFail);
|
||||
break;
|
||||
}
|
||||
case ItemPrefab itemPrefab when PlayerInput.IsShiftDown():
|
||||
@@ -3243,12 +3200,17 @@ namespace Barotrauma
|
||||
if (!inv.TryPutItem(item, dummyCharacter))
|
||||
{
|
||||
// We failed, remove the item so it doesn't stay at x:0,y:0
|
||||
GUI.PlayUISound(GUISoundType.PickItemFail);
|
||||
SoundPlayer.PlayUISound(GUISoundType.PickItemFail);
|
||||
item.Remove();
|
||||
}
|
||||
else
|
||||
{
|
||||
GUI.PlayUISound(GUISoundType.PickItem);
|
||||
SoundPlayer.PlayUISound(GUISoundType.PickItem);
|
||||
}
|
||||
|
||||
if (!item.Removed)
|
||||
{
|
||||
StoreCommand(new AddOrDeleteCommand(new List<MapEntity> { item }, false));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -3257,7 +3219,7 @@ namespace Barotrauma
|
||||
{
|
||||
// Place the item into our hands
|
||||
DraggedItemPrefab = (MapEntityPrefab) obj;
|
||||
GUI.PlayUISound(GUISoundType.PickItem);
|
||||
SoundPlayer.PlayUISound(GUISoundType.PickItem);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -3265,7 +3227,7 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
GUI.PlayUISound(GUISoundType.PickItem);
|
||||
SoundPlayer.PlayUISound(GUISoundType.PickItem);
|
||||
MapEntityPrefab.SelectPrefab(obj);
|
||||
}
|
||||
|
||||
@@ -3611,6 +3573,7 @@ namespace Barotrauma
|
||||
EntityMenu.AddToGUIUpdateList();
|
||||
showEntitiesPanel.AddToGUIUpdateList();
|
||||
previouslyUsedPanel.AddToGUIUpdateList();
|
||||
undoBufferPanel.AddToGUIUpdateList();
|
||||
entityCountPanel.AddToGUIUpdateList();
|
||||
TopPanel.AddToGUIUpdateList();
|
||||
|
||||
@@ -3655,10 +3618,7 @@ namespace Barotrauma
|
||||
/// </summary>
|
||||
private bool IsMouseOnEditorGUI()
|
||||
{
|
||||
if (GUI.MouseOn == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (GUI.MouseOn == null) { return false; }
|
||||
|
||||
return (EntityMenu?.MouseRect.Contains(PlayerInput.MousePosition) ?? false)
|
||||
|| (entityCountPanel?.MouseRect.Contains(PlayerInput.MousePosition) ?? false)
|
||||
@@ -3666,6 +3626,91 @@ namespace Barotrauma
|
||||
|| (TopPanel?.MouseRect.Contains(PlayerInput.MousePosition) ?? false);
|
||||
}
|
||||
|
||||
private static void Redo(int amount)
|
||||
{
|
||||
for (int i = 0; i < amount; i++)
|
||||
{
|
||||
if (commandIndex < Commands.Count)
|
||||
{
|
||||
Command command = Commands[commandIndex++];
|
||||
command.Execute();
|
||||
}
|
||||
}
|
||||
GameMain.SubEditorScreen.UpdateUndoHistoryPanel();
|
||||
}
|
||||
|
||||
private static void Undo(int amount)
|
||||
{
|
||||
for (int i = 0; i < amount; i++)
|
||||
{
|
||||
if (commandIndex > 0)
|
||||
{
|
||||
Command command = Commands[--commandIndex];
|
||||
command.UnExecute();
|
||||
}
|
||||
}
|
||||
GameMain.SubEditorScreen.UpdateUndoHistoryPanel();
|
||||
}
|
||||
|
||||
private static void ClearUndoBuffer()
|
||||
{
|
||||
SerializableEntityEditor.PropertyChangesActive = false;
|
||||
SerializableEntityEditor.CommandBuffer = null;
|
||||
Commands.ForEach(cmd => cmd.Cleanup());
|
||||
Commands.Clear();
|
||||
commandIndex = 0;
|
||||
GameMain.SubEditorScreen.UpdateUndoHistoryPanel();
|
||||
}
|
||||
|
||||
public static void StoreCommand(Command command)
|
||||
{
|
||||
if (commandIndex != Commands.Count)
|
||||
{
|
||||
Commands.RemoveRange(commandIndex, Commands.Count - commandIndex);
|
||||
}
|
||||
Commands.Add(command);
|
||||
commandIndex++;
|
||||
|
||||
// Start removing old commands
|
||||
if (Commands.Count > Math.Clamp(GameSettings.SubEditorMaxUndoBuffer, 1, 10240))
|
||||
{
|
||||
Commands.First()?.Cleanup();
|
||||
Commands.RemoveRange(0, 1);
|
||||
commandIndex = Commands.Count;
|
||||
}
|
||||
|
||||
GameMain.SubEditorScreen.UpdateUndoHistoryPanel();
|
||||
}
|
||||
|
||||
public void UpdateUndoHistoryPanel()
|
||||
{
|
||||
if (undoBufferPanel == null) { return; }
|
||||
|
||||
undoBufferList.Content.Children.ForEachMod(component =>
|
||||
{
|
||||
undoBufferList.Content.RemoveChild(component);
|
||||
});
|
||||
|
||||
for (int i = 0; i < Commands.Count; i++)
|
||||
{
|
||||
Command command = Commands[i];
|
||||
string description = command.GetDescription();
|
||||
CreateTextBlock(description, description, i + 1, command).RectTransform.SetAsFirstChild();
|
||||
}
|
||||
|
||||
CreateTextBlock(TextManager.Get("undo.beginning"), TextManager.Get("undo.beginningtooltip"), 0, null);
|
||||
|
||||
GUITextBlock CreateTextBlock(string name, string description, int index, Command command)
|
||||
{
|
||||
return new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), undoBufferList.Content.RectTransform) { MinSize = new Point(0, 15) },
|
||||
ToolBox.LimitString(name, GUI.SmallFont, undoBufferList.Content.Rect.Width), font: GUI.SmallFont, textColor: index == commandIndex ? GUI.Style.Green : (Color?) null)
|
||||
{
|
||||
UserData = command,
|
||||
ToolTip = description
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allows the game to run logic such as updating the world,
|
||||
/// checking for collisions, gathering input, and playing audio.
|
||||
@@ -3745,7 +3790,32 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (undoBufferPanel.Visible)
|
||||
{
|
||||
undoBufferList.Deselect();
|
||||
}
|
||||
|
||||
if (GUI.KeyboardDispatcher.Subscriber == null
|
||||
|| MapEntity.EditingHUD != null
|
||||
&& GUI.KeyboardDispatcher.Subscriber is GUIComponent sub
|
||||
&& MapEntity.EditingHUD.Children.Contains(sub))
|
||||
{
|
||||
if (PlayerInput.IsCtrlDown() && !WiringMode)
|
||||
{
|
||||
if (PlayerInput.KeyHit(Keys.Z))
|
||||
{
|
||||
// Ctrl+Shift+Z redos while Ctrl+Z undos
|
||||
if (PlayerInput.IsShiftDown()) { Redo(1); } else { Undo(1); }
|
||||
}
|
||||
|
||||
// ctrl+Y redo
|
||||
if (PlayerInput.KeyHit(Keys.Y))
|
||||
{
|
||||
Redo(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (GUI.KeyboardDispatcher.Subscriber == null)
|
||||
{
|
||||
@@ -4019,9 +4089,15 @@ namespace Barotrauma
|
||||
newItem.Remove();
|
||||
}
|
||||
|
||||
if (!newItem.Removed)
|
||||
{
|
||||
BulkItemBufferInUse = true;
|
||||
BulkItemBuffer.Add(new AddOrDeleteCommand(new List<MapEntity> { newItem }, false));
|
||||
}
|
||||
|
||||
if (!dragginMouse)
|
||||
{
|
||||
GUI.PlayUISound(spawnedItem ? GUISoundType.PickItem : GUISoundType.PickItemFail);
|
||||
SoundPlayer.PlayUISound(spawnedItem ? GUISoundType.PickItem : GUISoundType.PickItemFail);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4083,14 +4159,41 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<MapEntity> placedEntities = itemInstance.Where(it => !it.Removed).Cast<MapEntity>().ToList();
|
||||
if (placedEntities.Any())
|
||||
{
|
||||
BulkItemBufferInUse = true;
|
||||
BulkItemBuffer.Add(new AddOrDeleteCommand(placedEntities, false));
|
||||
}
|
||||
}
|
||||
}
|
||||
GUI.PlayUISound(spawnedItems ? GUISoundType.PickItem : GUISoundType.PickItemFail);
|
||||
|
||||
SoundPlayer.PlayUISound(spawnedItems ? GUISoundType.PickItem : GUISoundType.PickItemFail);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (BulkItemBufferInUse && PlayerInput.PrimaryMouseButtonReleased() && BulkItemBuffer.Any())
|
||||
{
|
||||
AddOrDeleteCommand master = BulkItemBuffer[0];
|
||||
for (int i = 1; i < BulkItemBuffer.Count; i++)
|
||||
{
|
||||
AddOrDeleteCommand command = BulkItemBuffer[i];
|
||||
command.MergeInto(master);
|
||||
}
|
||||
|
||||
StoreCommand(master);
|
||||
BulkItemBuffer.Clear();
|
||||
BulkItemBufferInUse = false;
|
||||
}
|
||||
|
||||
if (SerializableEntityEditor.PropertyChangesActive && (SerializableEntityEditor.NextCommandPush < DateTime.Now || MapEntity.EditingHUD == null))
|
||||
{
|
||||
SerializableEntityEditor.CommitCommandBuffer();
|
||||
}
|
||||
|
||||
// Update our mouse dragging state so we can easily slide thru slots while holding the mouse button down to place lots of items
|
||||
if (PlayerInput.PrimaryMouseButtonHeld())
|
||||
{
|
||||
|
||||
@@ -18,6 +18,11 @@ namespace Barotrauma
|
||||
public static List<string> MissingLocalizations = new List<string>();
|
||||
#endif
|
||||
|
||||
public static bool LockEditing;
|
||||
public static bool PropertyChangesActive;
|
||||
public static DateTime NextCommandPush;
|
||||
public static Tuple<SerializableProperty, PropertyCommand> CommandBuffer;
|
||||
|
||||
public int ContentHeight
|
||||
{
|
||||
get
|
||||
@@ -1091,10 +1096,67 @@ namespace Barotrauma
|
||||
|
||||
private bool SetPropertyValue(SerializableProperty property, object entity, object value)
|
||||
{
|
||||
MultiSetProperties(property, entity, value);
|
||||
if (LockEditing) { return false; }
|
||||
|
||||
object oldData = property.GetValue(entity);
|
||||
// some properties have null as the default string value
|
||||
if (oldData == null && value is string) { oldData = ""; }
|
||||
if (entity is ISerializableEntity sEntity && Screen.Selected is SubEditorScreen && !Equals(oldData, value))
|
||||
{
|
||||
List<ISerializableEntity> entities = new List<ISerializableEntity> { sEntity };
|
||||
Dictionary<ISerializableEntity, object> affected = MultiSetProperties(property, entity, value);
|
||||
|
||||
Dictionary<object, List<ISerializableEntity>> oldValues = new Dictionary<object, List<ISerializableEntity>> {{ oldData, new List<ISerializableEntity> { sEntity }}};
|
||||
|
||||
affected.ForEach(aEntity =>
|
||||
{
|
||||
var (item, oldVal) = aEntity;
|
||||
entities.Add(item);
|
||||
|
||||
if (!oldValues.ContainsKey(oldVal))
|
||||
{
|
||||
oldValues.Add(oldVal, new List<ISerializableEntity> { item });
|
||||
}
|
||||
else
|
||||
{
|
||||
oldValues[oldVal].Add(item);
|
||||
}
|
||||
});
|
||||
|
||||
PropertyCommand cmd = new PropertyCommand(entities, property.Name, value, oldValues);
|
||||
if (CommandBuffer != null)
|
||||
{
|
||||
if (CommandBuffer.Item1 == property && CommandBuffer.Item2.PropertyCount == cmd.PropertyCount)
|
||||
{
|
||||
if (!CommandBuffer.Item2.MergeInto(cmd))
|
||||
{
|
||||
CommitCommandBuffer();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CommitCommandBuffer();
|
||||
}
|
||||
}
|
||||
|
||||
NextCommandPush = DateTime.Now.AddSeconds(1);
|
||||
CommandBuffer = Tuple.Create(property, cmd);
|
||||
PropertyChangesActive = true;
|
||||
}
|
||||
|
||||
return property.TrySetValue(entity, value);
|
||||
}
|
||||
|
||||
public static void CommitCommandBuffer()
|
||||
{
|
||||
if (CommandBuffer != null)
|
||||
{
|
||||
SubEditorScreen.StoreCommand(CommandBuffer.Item2);
|
||||
}
|
||||
CommandBuffer = null;
|
||||
PropertyChangesActive = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets common shared properties to all selected map entities in sub editor.
|
||||
/// Only works client side while in the sub editor and when parentObject is ItemComponent, Item or Structure.
|
||||
@@ -1103,10 +1165,12 @@ namespace Barotrauma
|
||||
/// <param name="parentObject"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <remarks>The function has the same parameters as <see cref="SetValue"/></remarks>
|
||||
private void MultiSetProperties(SerializableProperty property, object parentObject, object value)
|
||||
private Dictionary<ISerializableEntity, object> MultiSetProperties(SerializableProperty property, object parentObject, object value)
|
||||
{
|
||||
if (!(Screen.Selected is SubEditorScreen) || MapEntity.SelectedList.Count <= 1) { return; }
|
||||
if (!(parentObject is ItemComponent || parentObject is Item || parentObject is Structure || parentObject is Hull)) { return; }
|
||||
Dictionary<ISerializableEntity, object> affected = new Dictionary<ISerializableEntity, object>();
|
||||
|
||||
if (!(Screen.Selected is SubEditorScreen) || MapEntity.SelectedList.Count <= 1) { return affected; }
|
||||
if (!(parentObject is ItemComponent || parentObject is Item || parentObject is Structure || parentObject is Hull)) { return affected; }
|
||||
|
||||
foreach (var entity in MapEntity.SelectedList.Where(entity => entity != parentObject))
|
||||
{
|
||||
@@ -1115,35 +1179,36 @@ namespace Barotrauma
|
||||
case Hull _:
|
||||
case Structure _:
|
||||
case Item _:
|
||||
{
|
||||
if (entity.GetType() == parentObject.GetType())
|
||||
{
|
||||
{
|
||||
affected.Add((ISerializableEntity) entity, property.GetValue(entity));
|
||||
property.PropertyInfo.SetValue(entity, value);
|
||||
}
|
||||
else if (entity is ISerializableEntity sEntity && sEntity.SerializableProperties != null)
|
||||
{
|
||||
var props = sEntity.SerializableProperties;
|
||||
|
||||
|
||||
if (props.TryGetValue(property.NameToLowerInvariant, out SerializableProperty foundProp))
|
||||
{
|
||||
affected.Add(sEntity, foundProp.GetValue(sEntity));
|
||||
foundProp.PropertyInfo.SetValue(entity, value);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ItemComponent _ when entity is Item item:
|
||||
{
|
||||
foreach (var component in item.Components)
|
||||
{
|
||||
if (component.GetType() == parentObject.GetType() && component != parentObject)
|
||||
{
|
||||
{
|
||||
affected.Add(component, property.GetValue(component));
|
||||
property.PropertyInfo.SetValue(component, value);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return affected;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -275,7 +275,7 @@ namespace Barotrauma.Sounds
|
||||
{
|
||||
if (value < 0.25f || value > 4.0f)
|
||||
{
|
||||
DebugConsole.ThrowError($"Frequency multiplier out of range: {value}" + Environment.StackTrace);
|
||||
DebugConsole.ThrowError($"Frequency multiplier out of range: {value}" + Environment.StackTrace.CleanupStackTrace());
|
||||
}
|
||||
frequencyMultiplier = Math.Clamp(value, 0.25f, 4.0f);
|
||||
|
||||
|
||||
@@ -79,6 +79,11 @@ namespace Barotrauma
|
||||
private static float ambientSoundTimer;
|
||||
private static Vector2 ambientSoundInterval = new Vector2(20.0f, 40.0f); //x = min, y = max
|
||||
|
||||
private static SoundChannel hullSoundChannel;
|
||||
private static Hull hullSoundSource;
|
||||
private static float hullSoundTimer;
|
||||
private static Vector2 hullSoundInterval = new Vector2(45.0f, 90.0f); //x = min, y = max
|
||||
|
||||
//misc
|
||||
public static List<Sound> FlowSounds = new List<Sound>();
|
||||
public static List<Sound> SplashSounds = new List<Sound>();
|
||||
@@ -94,11 +99,16 @@ namespace Barotrauma
|
||||
private static float[] fireVolumeRight;
|
||||
|
||||
const float FireSoundRange = 1000.0f;
|
||||
const float FireSoundMediumLimit = 100.0f;
|
||||
const float FireSoundLargeLimit = 200.0f; //switch to large fire sound when the size of a firesource is above this
|
||||
const int fireSizes = 3;
|
||||
private static string[] fireSoundTags = new string[fireSizes] { "fire", "firemedium", "firelarge" };
|
||||
|
||||
// TODO: could use a dictionary to split up the list into smaller lists of same type?
|
||||
private static List<DamageSound> damageSounds;
|
||||
|
||||
private static Dictionary<GUISoundType, List<Sound>> guiSounds;
|
||||
|
||||
private static Sound startUpSound;
|
||||
|
||||
public static bool Initialized;
|
||||
@@ -163,6 +173,7 @@ namespace Barotrauma
|
||||
List<KeyValuePair<string, Sound>> miscSoundList = new List<KeyValuePair<string, Sound>>();
|
||||
damageSounds ??= new List<DamageSound>();
|
||||
musicClips ??= new List<BackgroundMusic>();
|
||||
guiSounds ??= new Dictionary<GUISoundType, List<Sound>>();
|
||||
|
||||
bool firstWaterAmbienceLoaded = false;
|
||||
|
||||
@@ -250,6 +261,21 @@ namespace Barotrauma
|
||||
damageSoundType,
|
||||
soundElement.GetAttributeString("requiredtag", "")));
|
||||
|
||||
break;
|
||||
case "guisound":
|
||||
Sound guiSound = GameMain.SoundManager.LoadSound(soundElement, stream: false);
|
||||
if (guiSound == null) { continue; }
|
||||
if (Enum.TryParse(soundElement.GetAttributeString("guisoundtype", null), true, out GUISoundType soundType))
|
||||
{
|
||||
if (guiSounds.ContainsKey(soundType))
|
||||
{
|
||||
guiSounds[soundType].Add(guiSound);
|
||||
}
|
||||
else
|
||||
{
|
||||
guiSounds.Add(soundType, new List<Sound>() { guiSound });
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Sound sound = GameMain.SoundManager.LoadSound(soundElement, false);
|
||||
@@ -294,6 +320,15 @@ namespace Barotrauma
|
||||
});
|
||||
damageSounds.RemoveAll(s => s.sound.Disposed);
|
||||
|
||||
guiSounds.ForEach(kvp =>
|
||||
{
|
||||
kvp.Value?.ForEach(s =>
|
||||
{
|
||||
if (!soundElements.Any(e => SoundElementsEquivalent(s.XElement, e))) { s.Dispose(); }
|
||||
});
|
||||
});
|
||||
guiSounds.ForEach(kvp => kvp.Value?.RemoveAll(s => s.Disposed));
|
||||
|
||||
miscSounds?.ForEach(g => g.ForEach(s =>
|
||||
{
|
||||
if (!soundElements.Any(e => SoundElementsEquivalent(s.XElement, e))) { s.Dispose(); }
|
||||
@@ -305,9 +340,9 @@ namespace Barotrauma
|
||||
flowVolumeLeft = new float[FlowSounds.Count];
|
||||
flowVolumeRight = new float[FlowSounds.Count];
|
||||
|
||||
fireSoundChannels = new SoundChannel[2];
|
||||
fireVolumeLeft = new float[2];
|
||||
fireVolumeRight = new float[2];
|
||||
fireSoundChannels = new SoundChannel[fireSizes];
|
||||
fireVolumeLeft = new float[fireSizes];
|
||||
fireVolumeRight = new float[fireSizes];
|
||||
|
||||
miscSounds = miscSoundList.ToLookup(kvp => kvp.Key, kvp => kvp.Value);
|
||||
|
||||
@@ -319,7 +354,6 @@ namespace Barotrauma
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static void Update(float deltaTime)
|
||||
{
|
||||
if (!Initialized) { return; }
|
||||
@@ -355,6 +389,12 @@ namespace Barotrauma
|
||||
}
|
||||
fireVolumeLeft[0] = 0.0f; fireVolumeLeft[1] = 0.0f;
|
||||
fireVolumeRight[0] = 0.0f; fireVolumeRight[1] = 0.0f;
|
||||
if (hullSoundChannel != null)
|
||||
{
|
||||
hullSoundChannel.FadeOutAndDispose();
|
||||
hullSoundChannel = null;
|
||||
hullSoundSource = null;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -372,6 +412,7 @@ namespace Barotrauma
|
||||
UpdateWaterAmbience(ambienceVolume, deltaTime);
|
||||
UpdateWaterFlowSounds(deltaTime);
|
||||
UpdateRandomAmbience(deltaTime);
|
||||
UpdateHullSounds(deltaTime);
|
||||
UpdateFireSounds(deltaTime);
|
||||
}
|
||||
|
||||
@@ -429,6 +470,9 @@ namespace Barotrauma
|
||||
break;
|
||||
}
|
||||
|
||||
// Consider the volume set in sounds.xml
|
||||
if (sound != null) { volume *= sound.BaseGain; }
|
||||
|
||||
if ((waterAmbienceChannels[i] == null || !waterAmbienceChannels[i].IsPlaying) && volume > 0.01f)
|
||||
{
|
||||
waterAmbienceChannels[i] = sound.Play(volume, "waterambience");
|
||||
@@ -490,6 +534,20 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
if (Character.Controlled?.CharacterHealth?.GetAffliction("psychosis") is AfflictionPsychosis psychosis)
|
||||
{
|
||||
if (psychosis.CurrentFloodType == AfflictionPsychosis.FloodType.Minor)
|
||||
{
|
||||
targetFlowLeft[0] = Math.Max(targetFlowLeft[0], 1.0f);
|
||||
targetFlowRight[0] = Math.Max(targetFlowRight[0], 1.0f);
|
||||
}
|
||||
else if (psychosis.CurrentFloodType == AfflictionPsychosis.FloodType.Major)
|
||||
{
|
||||
targetFlowLeft[FlowSounds.Count - 1] = Math.Max(targetFlowLeft[FlowSounds.Count - 1], 1.0f);
|
||||
targetFlowRight[FlowSounds.Count - 1] = Math.Max(targetFlowRight[FlowSounds.Count - 1], 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < FlowSounds.Count; i++)
|
||||
{
|
||||
flowVolumeLeft[i] = (targetFlowLeft[i] < flowVolumeLeft[i]) ?
|
||||
@@ -534,33 +592,11 @@ namespace Barotrauma
|
||||
{
|
||||
foreach (FireSource fs in hull.FireSources)
|
||||
{
|
||||
Vector2 diff = fs.WorldPosition + fs.Size / 2 - listenerPos;
|
||||
if (Math.Abs(diff.X) < FireSoundRange && Math.Abs(diff.Y) < FireSoundRange)
|
||||
{
|
||||
Vector2 diffLeft = (fs.WorldPosition + new Vector2(fs.Size.X, fs.Size.Y / 2)) - listenerPos;
|
||||
if (Math.Abs(diff.X) < fs.Size.X / 2.0f) { diffLeft.X = 0.0f; }
|
||||
if (diffLeft.X <= 0)
|
||||
{
|
||||
float distFallOffLeft = diffLeft.Length() / FireSoundRange;
|
||||
if (distFallOffLeft < 0.99f)
|
||||
{
|
||||
fireVolumeLeft[0] += (1.0f - distFallOffLeft);
|
||||
if (fs.Size.X > FireSoundLargeLimit) fireVolumeLeft[1] += (1.0f - distFallOffLeft) * ((fs.Size.X - FireSoundLargeLimit) / FireSoundLargeLimit);
|
||||
}
|
||||
}
|
||||
|
||||
Vector2 diffRight = (fs.WorldPosition + new Vector2(0.0f, fs.Size.Y / 2)) - listenerPos;
|
||||
if (Math.Abs(diff.X) < fs.Size.X / 2.0f) { diffRight.X = 0.0f; }
|
||||
if (diffRight.X >= 0)
|
||||
{
|
||||
float distFallOffRight = diffRight.Length() / FireSoundRange;
|
||||
if (distFallOffRight < 0.99f)
|
||||
{
|
||||
fireVolumeRight[0] += 1.0f - distFallOffRight;
|
||||
if (fs.Size.X > FireSoundLargeLimit) fireVolumeRight[1] += (1.0f - distFallOffRight) * ((fs.Size.X - FireSoundLargeLimit) / FireSoundLargeLimit);
|
||||
}
|
||||
}
|
||||
}
|
||||
AddFireVolume(fs);
|
||||
}
|
||||
foreach (FireSource fs in hull.FakeFireSources)
|
||||
{
|
||||
AddFireVolume(fs);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -579,13 +615,58 @@ namespace Barotrauma
|
||||
Vector2 soundPos = new Vector2(GameMain.SoundManager.ListenerPosition.X + (fireVolumeRight[i] - fireVolumeLeft[i]) * 100, GameMain.SoundManager.ListenerPosition.Y);
|
||||
if (fireSoundChannels[i] == null || !fireSoundChannels[i].IsPlaying)
|
||||
{
|
||||
fireSoundChannels[i] = GetSound(i == 0 ? "fire" : "firelarge").Play(1.0f, FlowSoundRange, soundPos);
|
||||
fireSoundChannels[i] = GetSound(fireSoundTags[i]).Play(1.0f, FlowSoundRange, soundPos);
|
||||
fireSoundChannels[i].Looping = true;
|
||||
}
|
||||
fireSoundChannels[i].Gain = Math.Max(fireVolumeRight[i], fireVolumeLeft[i]);
|
||||
fireSoundChannels[i].Position = new Vector3(soundPos, 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
void AddFireVolume(FireSource fs)
|
||||
{
|
||||
Vector2 diff = fs.WorldPosition + fs.Size / 2 - listenerPos;
|
||||
if (Math.Abs(diff.X) < FireSoundRange && Math.Abs(diff.Y) < FireSoundRange)
|
||||
{
|
||||
Vector2 diffLeft = (fs.WorldPosition + new Vector2(fs.Size.X, fs.Size.Y / 2)) - listenerPos;
|
||||
if (Math.Abs(diff.X) < fs.Size.X / 2.0f) { diffLeft.X = 0.0f; }
|
||||
if (diffLeft.X <= 0)
|
||||
{
|
||||
float distFallOffLeft = diffLeft.Length() / FireSoundRange;
|
||||
if (distFallOffLeft < 0.99f)
|
||||
{
|
||||
fireVolumeLeft[0] += (1.0f - distFallOffLeft);
|
||||
if (fs.Size.X > FireSoundLargeLimit)
|
||||
{
|
||||
fireVolumeLeft[2] += (1.0f - distFallOffLeft) * ((fs.Size.X - FireSoundLargeLimit) / FireSoundLargeLimit);
|
||||
}
|
||||
else if (fs.Size.X > FireSoundMediumLimit)
|
||||
{
|
||||
fireVolumeLeft[1] += (1.0f - distFallOffLeft) * ((fs.Size.X - FireSoundMediumLimit) / FireSoundMediumLimit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Vector2 diffRight = (fs.WorldPosition + new Vector2(0.0f, fs.Size.Y / 2)) - listenerPos;
|
||||
if (Math.Abs(diff.X) < fs.Size.X / 2.0f) { diffRight.X = 0.0f; }
|
||||
if (diffRight.X >= 0)
|
||||
{
|
||||
float distFallOffRight = diffRight.Length() / FireSoundRange;
|
||||
if (distFallOffRight < 0.99f)
|
||||
{
|
||||
fireVolumeRight[0] += 1.0f - distFallOffRight;
|
||||
if (fs.Size.X > FireSoundLargeLimit)
|
||||
{
|
||||
fireVolumeRight[2] += (1.0f - distFallOffRight) * ((fs.Size.X - FireSoundLargeLimit) / FireSoundLargeLimit);
|
||||
}
|
||||
else if (fs.Size.X > FireSoundMediumLimit)
|
||||
{
|
||||
fireVolumeRight[1] += (1.0f - distFallOffRight) * ((fs.Size.X - FireSoundMediumLimit) / FireSoundMediumLimit);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void UpdateRandomAmbience(float deltaTime)
|
||||
@@ -606,6 +687,40 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
private static void UpdateHullSounds(float deltaTime)
|
||||
{
|
||||
if (hullSoundChannel != null && hullSoundChannel.IsPlaying && hullSoundSource != null)
|
||||
{
|
||||
hullSoundChannel.Position = new Vector3(hullSoundSource.WorldPosition, 0.0f);
|
||||
hullSoundChannel.Gain = GetHullSoundVolume(hullSoundSource.Submarine);
|
||||
}
|
||||
|
||||
if (hullSoundTimer > 0.0f)
|
||||
{
|
||||
hullSoundTimer -= deltaTime;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!Level.IsLoadedOutpost && Character.Controlled?.CurrentHull?.Submarine is Submarine sub &&
|
||||
sub.Info != null && !sub.Info.IsOutpost)
|
||||
{
|
||||
hullSoundSource = Character.Controlled.CurrentHull;
|
||||
hullSoundChannel = PlaySound("hull", hullSoundSource.WorldPosition, volume: GetHullSoundVolume(sub), range: 1500.0f);
|
||||
hullSoundTimer = Rand.Range(hullSoundInterval.X, hullSoundInterval.Y);
|
||||
}
|
||||
else
|
||||
{
|
||||
hullSoundTimer = 5.0f;
|
||||
}
|
||||
}
|
||||
|
||||
static float GetHullSoundVolume(Submarine sub)
|
||||
{
|
||||
var depth = Level.Loaded == null ? 0.0f : Math.Abs(sub.Position.Y - Level.Loaded.Size.Y) * Physics.DisplayToRealWorldRatio;
|
||||
return Math.Clamp((depth - 800.0f) / 1500.0f, 0.4f, 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
public static Sound GetSound(string soundTag)
|
||||
{
|
||||
var matchingSounds = miscSounds[soundTag].ToList();
|
||||
@@ -637,8 +752,8 @@ namespace Barotrauma
|
||||
{
|
||||
if (sound == null)
|
||||
{
|
||||
string errorMsg = "Error in SoundPlayer.PlaySound (sound was null)\n" + Environment.StackTrace;
|
||||
GameAnalyticsManager.AddErrorEventOnce("SoundPlayer.PlaySound:SoundNull" + Environment.StackTrace, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||
string errorMsg = "Error in SoundPlayer.PlaySound (sound was null)\n" + Environment.StackTrace.CleanupStackTrace();
|
||||
GameAnalyticsManager.AddErrorEventOnce("SoundPlayer.PlaySound:SoundNull" + Environment.StackTrace.CleanupStackTrace(), GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -830,6 +945,18 @@ namespace Barotrauma
|
||||
{
|
||||
return "wreck";
|
||||
}
|
||||
|
||||
if (Level.IsLoadedOutpost && Character.Controlled.Submarine == Level.Loaded.StartOutpost)
|
||||
{
|
||||
// Only return music type for specific outpost types to not assume that
|
||||
// every outpost type has an associated music track (switch-case for future tracks)
|
||||
var locationType = Level.Loaded.StartLocation?.Type?.Identifier?.ToLowerInvariant();
|
||||
switch (locationType)
|
||||
{
|
||||
case "research":
|
||||
return locationType;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Submarine targetSubmarine = Character.Controlled?.Submarine;
|
||||
@@ -952,6 +1079,16 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
tempList.GetRandom().sound?.Play(1.0f, range, position, muffle: ShouldMuffleSound(Character.Controlled, position, range, null));
|
||||
}
|
||||
}
|
||||
|
||||
public static void PlayUISound(GUISoundType soundType)
|
||||
{
|
||||
if (guiSounds == null || guiSounds.Count < 1) { return; }
|
||||
if (guiSounds.TryGetValue(soundType, out List<Sound> sounds))
|
||||
{
|
||||
if (sounds == null || sounds.Count < 1) { return; }
|
||||
sounds.GetRandom()?.Play(null, "ui");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,8 +67,8 @@ namespace Barotrauma
|
||||
{
|
||||
if (sound?.Sound == null)
|
||||
{
|
||||
string errorMsg = $"Error in StatusEffect.ApplyProjSpecific1 (sound \"{sound?.Filename ?? "unknown"}\" was null)\n" + Environment.StackTrace;
|
||||
GameAnalyticsManager.AddErrorEventOnce("StatusEffect.ApplyProjSpecific:SoundNull1" + Environment.StackTrace, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||
string errorMsg = $"Error in StatusEffect.ApplyProjSpecific1 (sound \"{sound?.Filename ?? "unknown"}\" was null)\n" + Environment.StackTrace.CleanupStackTrace();
|
||||
GameAnalyticsManager.AddErrorEventOnce("StatusEffect.ApplyProjSpecific:SoundNull1" + Environment.StackTrace.CleanupStackTrace(), GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||
return;
|
||||
}
|
||||
soundChannel = SoundPlayer.PlaySound(sound.Sound, worldPosition, sound.Volume, sound.Range, hullGuess: hull);
|
||||
@@ -93,10 +93,14 @@ namespace Barotrauma
|
||||
var selectedSound = sounds[selectedSoundIndex];
|
||||
if (selectedSound?.Sound == null)
|
||||
{
|
||||
string errorMsg = $"Error in StatusEffect.ApplyProjSpecific2 (sound \"{selectedSound?.Filename ?? "unknown"}\" was null)\n" + Environment.StackTrace;
|
||||
GameAnalyticsManager.AddErrorEventOnce("StatusEffect.ApplyProjSpecific:SoundNull2" + Environment.StackTrace, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||
string errorMsg = $"Error in StatusEffect.ApplyProjSpecific2 (sound \"{selectedSound?.Filename ?? "unknown"}\" was null)\n" + Environment.StackTrace.CleanupStackTrace();
|
||||
GameAnalyticsManager.AddErrorEventOnce("StatusEffect.ApplyProjSpecific:SoundNull2" + Environment.StackTrace.CleanupStackTrace(), GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||
return;
|
||||
}
|
||||
if (selectedSound.Sound.Disposed)
|
||||
{
|
||||
Submarine.ReloadRoundSound(selectedSound);
|
||||
}
|
||||
soundChannel = SoundPlayer.PlaySound(selectedSound.Sound, worldPosition, selectedSound.Volume, selectedSound.Range, hullGuess: hull);
|
||||
if (soundChannel != null) { soundChannel.Looping = loopSound; }
|
||||
}
|
||||
|
||||
559
Barotrauma/BarotraumaClient/ClientSource/SubEditorCommands.cs
Normal file
559
Barotrauma/BarotraumaClient/ClientSource/SubEditorCommands.cs
Normal file
@@ -0,0 +1,559 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using Barotrauma.Items.Components;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
internal readonly struct InventorySlotItem
|
||||
{
|
||||
public readonly int Slot;
|
||||
public readonly Item Item;
|
||||
|
||||
public InventorySlotItem(int slot, Item item)
|
||||
{
|
||||
Slot = slot;
|
||||
Item = item;
|
||||
}
|
||||
|
||||
public void Deconstruct(out int slot, out Item item)
|
||||
{
|
||||
slot = Slot;
|
||||
item = Item;
|
||||
}
|
||||
}
|
||||
|
||||
internal abstract partial class Command
|
||||
{
|
||||
public abstract string GetDescription();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A command for setting and reverting a MapEntity rectangle
|
||||
/// <see cref="SubEditorScreen"/>
|
||||
/// <see cref="MapEntity"/>
|
||||
/// </summary>
|
||||
internal class TransformCommand : Command
|
||||
{
|
||||
private readonly List<MapEntity> Receivers;
|
||||
private readonly List<Rectangle> NewData;
|
||||
private readonly List<Rectangle> OldData;
|
||||
private readonly bool Resized;
|
||||
|
||||
/// <summary>
|
||||
/// A command for setting and reverting a MapEntity rectangle
|
||||
/// </summary>
|
||||
/// <param name="receivers">Entities whose rectangle has been altered</param>
|
||||
/// <param name="newData">The new rectangle that is or will be applied to the map entity</param>
|
||||
/// <param name="oldData">Old rectangle the map entity had before</param>
|
||||
/// <param name="resized">If the transform was resized or not</param>
|
||||
/// <remarks>
|
||||
/// All lists should be equal in length, for every receiver there should be a corresponding entry at the same position in newData and oldData.
|
||||
/// </remarks>
|
||||
public TransformCommand(List<MapEntity> receivers, List<Rectangle> newData, List<Rectangle> oldData, bool resized)
|
||||
{
|
||||
Receivers = receivers;
|
||||
NewData = newData;
|
||||
OldData = oldData;
|
||||
Resized = resized;
|
||||
}
|
||||
|
||||
public override void Execute() => SetRects(NewData);
|
||||
public override void UnExecute() => SetRects(OldData);
|
||||
|
||||
public override void Cleanup()
|
||||
{
|
||||
NewData.Clear();
|
||||
OldData.Clear();
|
||||
Receivers.Clear();
|
||||
}
|
||||
|
||||
private void SetRects(IReadOnlyList<Rectangle> rects)
|
||||
{
|
||||
if (Receivers.Count != rects.Count)
|
||||
{
|
||||
DebugConsole.ThrowError($"Receivers.Count did not match Rects.Count ({Receivers.Count} vs {rects.Count}).");
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < rects.Count; i++)
|
||||
{
|
||||
MapEntity entity = Receivers[i].GetReplacementOrThis();
|
||||
Rectangle Rect = rects[i];
|
||||
Vector2 diff = Rect.Location.ToVector2() - entity.Rect.Location.ToVector2();
|
||||
entity.Move(diff);
|
||||
entity.Rect = Rect;
|
||||
}
|
||||
}
|
||||
|
||||
public override string GetDescription()
|
||||
{
|
||||
if (Resized)
|
||||
{
|
||||
return TextManager.GetWithVariable("Undo.ResizedItem", "[item]", Receivers.FirstOrDefault()?.Name);
|
||||
}
|
||||
|
||||
return Receivers.Count > 1
|
||||
? TextManager.GetWithVariable("Undo.MovedItemsMultiple", "[count]", Receivers.Count.ToString())
|
||||
: TextManager.GetWithVariable("Undo.MovedItem", "[item]", Receivers.FirstOrDefault()?.Name);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A command that removes and unremoves map entities
|
||||
/// <see cref="ItemPrefab"/>
|
||||
/// <see cref="StructurePrefab"/>
|
||||
/// <seealso cref="SubEditorScreen"/>
|
||||
/// </summary>
|
||||
internal class AddOrDeleteCommand : Command
|
||||
{
|
||||
private readonly Dictionary<InventorySlotItem, Inventory> PreviousInventories = new Dictionary<InventorySlotItem, Inventory>();
|
||||
private readonly List<MapEntity> Receivers;
|
||||
private readonly List<MapEntity> CloneList;
|
||||
private readonly bool WasDeleted;
|
||||
private readonly List<AddOrDeleteCommand> ContainedItemsCommand = new List<AddOrDeleteCommand>();
|
||||
|
||||
/// <summary>
|
||||
/// Creates a command where all entities share the same state.
|
||||
/// </summary>
|
||||
/// <param name="receivers">Entities that were deleted or added</param>
|
||||
/// <param name="wasDeleted">Whether or not all entities are or are going to be deleted</param>
|
||||
public AddOrDeleteCommand(List<MapEntity> receivers, bool wasDeleted)
|
||||
{
|
||||
WasDeleted = wasDeleted;
|
||||
Receivers = receivers;
|
||||
|
||||
try
|
||||
{
|
||||
foreach (MapEntity receiver in receivers)
|
||||
{
|
||||
if (receiver is Item it && it.ParentInventory != null)
|
||||
{
|
||||
PreviousInventories.Add(new InventorySlotItem(Array.IndexOf(it.ParentInventory.Items, it), it), it.ParentInventory);
|
||||
}
|
||||
}
|
||||
|
||||
List<MapEntity> clonedTargets = MapEntity.Clone(receivers);
|
||||
|
||||
List<MapEntity> itemsToDelete = new List<MapEntity>();
|
||||
foreach (MapEntity receiver in Receivers)
|
||||
{
|
||||
if (receiver is Item it)
|
||||
{
|
||||
foreach (ItemContainer component in it.GetComponents<ItemContainer>())
|
||||
{
|
||||
if (component.Inventory == null) { continue; }
|
||||
|
||||
itemsToDelete.AddRange(component.Inventory.Items.Where(item => item != null && !item.Removed));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (itemsToDelete.Any())
|
||||
{
|
||||
ContainedItemsCommand.Add(new AddOrDeleteCommand(itemsToDelete, true));
|
||||
foreach (MapEntity item in itemsToDelete)
|
||||
{
|
||||
if (item != null && !item.Removed)
|
||||
{
|
||||
item.Remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (MapEntity clone in clonedTargets)
|
||||
{
|
||||
clone.ShallowRemove();
|
||||
if (clone is Item it)
|
||||
{
|
||||
foreach (ItemContainer container in it.GetComponents<ItemContainer>())
|
||||
{
|
||||
container.Inventory?.DeleteAllItems();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CloneList = clonedTargets;
|
||||
}
|
||||
// This should never happen except if we decide to make a new type of MapEntity that isn't finished yet
|
||||
catch (Exception e)
|
||||
{
|
||||
Receivers = new List<MapEntity>();
|
||||
CloneList = new List<MapEntity>();
|
||||
DebugConsole.ThrowError("Could not store object", e);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Execute()
|
||||
{
|
||||
DeleteUndelete(true);
|
||||
ContainedItemsCommand?.ForEach(cmd => cmd.Execute());
|
||||
}
|
||||
|
||||
public override void UnExecute()
|
||||
{
|
||||
DeleteUndelete(false);
|
||||
ContainedItemsCommand?.ForEach(cmd => cmd.UnExecute());
|
||||
}
|
||||
|
||||
public override void Cleanup()
|
||||
{
|
||||
foreach (MapEntity entity in CloneList)
|
||||
{
|
||||
if (!entity.Removed)
|
||||
{
|
||||
entity.Remove();
|
||||
}
|
||||
}
|
||||
|
||||
CloneList?.Clear();
|
||||
Receivers.Clear();
|
||||
PreviousInventories?.Clear();
|
||||
ContainedItemsCommand?.ForEach(cmd => cmd.Cleanup());
|
||||
}
|
||||
|
||||
private void DeleteUndelete(bool redo)
|
||||
{
|
||||
bool wasDeleted = WasDeleted;
|
||||
|
||||
// We are redoing instead of undoing, flip the behavior
|
||||
if (redo) { wasDeleted = !wasDeleted; }
|
||||
|
||||
if (wasDeleted)
|
||||
{
|
||||
Debug.Assert(Receivers.All(entity => entity.GetReplacementOrThis().Removed), "Tried to redo a deletion but some items were not deleted");
|
||||
|
||||
List<MapEntity> clones = MapEntity.Clone(CloneList);
|
||||
for (int i = 0; i < Math.Min(Receivers.Count, clones.Count); i++)
|
||||
{
|
||||
MapEntity clone = clones[i];
|
||||
MapEntity receiver = Receivers[i];
|
||||
|
||||
if (receiver.GetReplacementOrThis() is Item item && clone is Item cloneItem)
|
||||
{
|
||||
foreach (ItemComponent ic in item.Components)
|
||||
{
|
||||
int index = item.GetComponentIndex(ic);
|
||||
ItemComponent component = cloneItem.Components.ElementAtOrDefault(index);
|
||||
switch (component)
|
||||
{
|
||||
case null:
|
||||
continue;
|
||||
case ItemContainer newContainer when newContainer.Inventory != null && ic is ItemContainer itemContainer && itemContainer.Inventory != null:
|
||||
itemContainer.Inventory.GetReplacementOrThiS().ReplacedBy = newContainer.Inventory;
|
||||
goto default;
|
||||
default:
|
||||
ic.GetReplacementOrThis().ReplacedBy = component;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
receiver.GetReplacementOrThis().ReplacedBy = clone;
|
||||
|
||||
if (clone is Item it)
|
||||
{
|
||||
foreach (var (slotRef, inventory) in PreviousInventories)
|
||||
{
|
||||
if (slotRef.Item == receiver)
|
||||
{
|
||||
inventory.GetReplacementOrThiS().TryPutItem(it, slotRef.Slot, false, false, null, createNetworkEvent: false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (MapEntity clone in clones)
|
||||
{
|
||||
clone.Submarine = Submarine.MainSub;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (MapEntity t in Receivers)
|
||||
{
|
||||
MapEntity receiver = t.GetReplacementOrThis();
|
||||
if (!receiver.Removed)
|
||||
{
|
||||
receiver.Remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void MergeInto(AddOrDeleteCommand master)
|
||||
{
|
||||
master.Receivers.AddRange(Receivers);
|
||||
master.CloneList.AddRange(CloneList);
|
||||
master.ContainedItemsCommand.AddRange(ContainedItemsCommand);
|
||||
foreach (var (slot, item) in PreviousInventories)
|
||||
{
|
||||
master.PreviousInventories.Add(slot, item);
|
||||
}
|
||||
}
|
||||
|
||||
public override string GetDescription()
|
||||
{
|
||||
if (WasDeleted)
|
||||
{
|
||||
return Receivers.Count > 1
|
||||
? TextManager.GetWithVariable("Undo.RemovedItemsMultiple", "[count]", Receivers.Count.ToString())
|
||||
: TextManager.GetWithVariable("Undo.RemovedItem", "[item]", Receivers.FirstOrDefault()?.Name);
|
||||
}
|
||||
|
||||
return Receivers.Count > 1
|
||||
? TextManager.GetWithVariable("Undo.AddedItemsMultiple", "[count]", Receivers.Count.ToString())
|
||||
: TextManager.GetWithVariable("Undo.AddedItem", "[item]", Receivers.FirstOrDefault()?.Name);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A command that places or drops items out of inventories
|
||||
/// </summary>
|
||||
/// <see cref="Inventory"/>
|
||||
/// <see cref="MapEntity"/>
|
||||
internal class InventoryPlaceCommand : Command
|
||||
{
|
||||
private readonly Inventory Inventory;
|
||||
private readonly List<InventorySlotItem> Receivers;
|
||||
private readonly bool wasDropped;
|
||||
|
||||
public InventoryPlaceCommand(Inventory inventory, List<Item> items, bool dropped)
|
||||
{
|
||||
Inventory = inventory;
|
||||
Receivers = items.Select(item => new InventorySlotItem(Array.IndexOf(inventory.Items, item), item)).ToList();
|
||||
wasDropped = dropped;
|
||||
}
|
||||
|
||||
public override void Execute() => ContainUncontain(false);
|
||||
public override void UnExecute() => ContainUncontain(true);
|
||||
|
||||
public override void Cleanup()
|
||||
{
|
||||
Receivers.Clear();
|
||||
}
|
||||
|
||||
private void ContainUncontain(bool drop)
|
||||
{
|
||||
// flip the behavior if the item was dropped instead of inserted
|
||||
if (wasDropped) { drop = !drop; }
|
||||
|
||||
foreach (var (slot, receiver) in Receivers)
|
||||
{
|
||||
Item item = (Item) receiver.GetReplacementOrThis();
|
||||
|
||||
if (drop)
|
||||
{
|
||||
item.Drop(null, createNetworkEvent: false);
|
||||
}
|
||||
else
|
||||
{
|
||||
Inventory.GetReplacementOrThiS().TryPutItem(item, slot, false, false, null, createNetworkEvent: false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override string GetDescription()
|
||||
{
|
||||
if (wasDropped)
|
||||
{
|
||||
return TextManager.GetWithVariable("Undo.DroppedItem", "[item]", Receivers.FirstOrDefault().Item.Name);
|
||||
}
|
||||
|
||||
string container = "[ERROR]";
|
||||
|
||||
if (Inventory.Owner is Item item)
|
||||
{
|
||||
container = item.Name;
|
||||
}
|
||||
|
||||
return Receivers.Count > 1
|
||||
? TextManager.GetWithVariables("Undo.ContainedItemsMultiple", new[] { "[count]", "[container]" }, new[] { Receivers.Count.ToString(), container })
|
||||
: TextManager.GetWithVariables("Undo.ContainedItem", new[] { "[item]", "[container]" }, new[] { Receivers.FirstOrDefault().Item.Name, container });
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A command that sets item properties
|
||||
/// </summary>
|
||||
internal class PropertyCommand : Command
|
||||
{
|
||||
private Dictionary<object, List<ISerializableEntity>> OldProperties;
|
||||
private readonly List<ISerializableEntity> Receivers;
|
||||
private readonly string PropertyName;
|
||||
private readonly object NewProperties;
|
||||
private string sanitizedProperty;
|
||||
|
||||
public readonly int PropertyCount;
|
||||
|
||||
/// <summary>
|
||||
/// A command that sets item properties
|
||||
/// </summary>
|
||||
/// <param name="receivers">Affected entities</param>
|
||||
/// <param name="propertyName">Real property name, not all lowercase</param>
|
||||
/// <param name="newData"></param>
|
||||
/// <param name="oldData"></param>
|
||||
public PropertyCommand(List<ISerializableEntity> receivers, string propertyName, object newData, Dictionary<object, List<ISerializableEntity>> oldData)
|
||||
{
|
||||
Receivers = receivers;
|
||||
PropertyName = propertyName;
|
||||
OldProperties = oldData;
|
||||
NewProperties = newData;
|
||||
PropertyCount = receivers.Count;
|
||||
SanitizeProperty();
|
||||
}
|
||||
|
||||
public PropertyCommand(ISerializableEntity receiver, string propertyName, object newData, object oldData)
|
||||
{
|
||||
Receivers = new List<ISerializableEntity> { receiver };
|
||||
PropertyName = propertyName;
|
||||
OldProperties = new Dictionary<object, List<ISerializableEntity>> { { oldData, Receivers } };
|
||||
NewProperties = newData;
|
||||
PropertyCount = 1;
|
||||
SanitizeProperty();
|
||||
}
|
||||
|
||||
public bool MergeInto(PropertyCommand master)
|
||||
{
|
||||
if (!master.Receivers.SequenceEqual(Receivers)) { return false; }
|
||||
master.OldProperties = OldProperties;
|
||||
return true;
|
||||
}
|
||||
|
||||
private void SanitizeProperty()
|
||||
{
|
||||
sanitizedProperty = NewProperties switch
|
||||
{
|
||||
float f => f.FormatSingleDecimal(),
|
||||
Point point => XMLExtensions.PointToString(point),
|
||||
Vector2 vector2 => vector2.FormatZeroDecimal(),
|
||||
Vector3 vector3 => vector3.FormatSingleDecimal(),
|
||||
Vector4 vector4 => vector4.FormatSingleDecimal(),
|
||||
Color color => XMLExtensions.ColorToString(color),
|
||||
Rectangle rectangle => XMLExtensions.RectToString(rectangle),
|
||||
_ => NewProperties.ToString()
|
||||
};
|
||||
}
|
||||
|
||||
public override void Execute() => SetProperties(false);
|
||||
public override void UnExecute() => SetProperties(true);
|
||||
|
||||
public override void Cleanup()
|
||||
{
|
||||
Receivers.Clear();
|
||||
OldProperties.Clear();
|
||||
}
|
||||
|
||||
private void SetProperties(bool undo)
|
||||
{
|
||||
foreach (ISerializableEntity t in Receivers)
|
||||
{
|
||||
ISerializableEntity receiver;
|
||||
switch (t)
|
||||
{
|
||||
case MapEntity me when me.GetReplacementOrThis() is ISerializableEntity sEntity:
|
||||
receiver = sEntity;
|
||||
break;
|
||||
case ItemComponent ic when ic.GetReplacementOrThis() is ISerializableEntity sItemComponent:
|
||||
receiver = sItemComponent;
|
||||
break;
|
||||
default:
|
||||
receiver = t;
|
||||
break;
|
||||
}
|
||||
|
||||
object data = NewProperties;
|
||||
|
||||
if (undo)
|
||||
{
|
||||
foreach (var (key, value) in OldProperties)
|
||||
{
|
||||
if (value.Contains(t)) { data = key; }
|
||||
}
|
||||
}
|
||||
|
||||
if (receiver.SerializableProperties != null)
|
||||
{
|
||||
Dictionary<string, SerializableProperty> props = receiver.SerializableProperties;
|
||||
|
||||
if (props.TryGetValue(PropertyName.ToLowerInvariant(), out SerializableProperty prop))
|
||||
{
|
||||
prop.TrySetValue(receiver, data);
|
||||
// Update the editing hud
|
||||
if (MapEntity.EditingHUD == null || (MapEntity.EditingHUD.UserData != receiver && (receiver is ItemComponent ic && MapEntity.EditingHUD.UserData != ic.Item))) { continue; }
|
||||
|
||||
GUIListBox list = MapEntity.EditingHUD.GetChild<GUIListBox>();
|
||||
if (list == null) { continue; }
|
||||
|
||||
IEnumerable<SerializableEntityEditor> editors = list.Content.FindChildren(comp => comp is SerializableEntityEditor).Cast<SerializableEntityEditor>();
|
||||
SerializableEntityEditor.LockEditing = true;
|
||||
foreach (SerializableEntityEditor editor in editors)
|
||||
{
|
||||
if (editor.UserData == receiver && editor.Fields.TryGetValue(PropertyName, out GUIComponent[] _))
|
||||
{
|
||||
editor.UpdateValue(prop, data);
|
||||
}
|
||||
}
|
||||
|
||||
SerializableEntityEditor.LockEditing = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override string GetDescription()
|
||||
{
|
||||
return Receivers.Count > 1
|
||||
? TextManager.GetWithVariables("Undo.ChangedPropertyMultiple", new[] { "[property]", "[count]", "[value]" }, new[] { PropertyName, Receivers.Count.ToString(), sanitizedProperty })
|
||||
: TextManager.GetWithVariables("Undo.ChangedProperty", new[] { "[property]", "[item]", "[value]" }, new[] { PropertyName, Receivers.FirstOrDefault()?.Name, sanitizedProperty });
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A command that moves items around in inventories
|
||||
/// </summary>
|
||||
/// <see cref="oldInventory"/>
|
||||
/// <see cref="MapEntity"/>
|
||||
internal class InventoryMoveCommand : Command
|
||||
{
|
||||
private readonly Inventory oldInventory;
|
||||
private readonly Inventory newInventory;
|
||||
private readonly int oldSlot;
|
||||
private readonly int newSlot;
|
||||
private readonly Item targetItem;
|
||||
|
||||
public InventoryMoveCommand(Inventory oldInventory, Inventory newInventory, Item item, int oldSlot, int newSlot)
|
||||
{
|
||||
this.newInventory = newInventory;
|
||||
this.oldInventory = oldInventory;
|
||||
this.oldSlot = oldSlot;
|
||||
this.newSlot = newSlot;
|
||||
targetItem = item;
|
||||
}
|
||||
|
||||
public override void Execute()
|
||||
{
|
||||
if (targetItem.GetReplacementOrThis() is Item item)
|
||||
{
|
||||
newInventory?.GetReplacementOrThiS().TryPutItem(item, newSlot, true, false, null, createNetworkEvent: false);
|
||||
}
|
||||
}
|
||||
|
||||
public override void UnExecute()
|
||||
{
|
||||
if (targetItem.GetReplacementOrThis() is Item item)
|
||||
{
|
||||
oldInventory?.GetReplacementOrThiS().TryPutItem(item, oldSlot, true, false, null, createNetworkEvent: false);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Cleanup() { }
|
||||
|
||||
public override string GetDescription()
|
||||
{
|
||||
return TextManager.GetWithVariable("Undo.MovedItem", "[item]", targetItem.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -142,10 +142,10 @@ namespace Barotrauma
|
||||
if (gradient.Length == 0)
|
||||
{
|
||||
#if DEBUG
|
||||
DebugConsole.ThrowError("Empty color array passed to the GradientLerp method.\n" + Environment.StackTrace);
|
||||
DebugConsole.ThrowError("Empty color array passed to the GradientLerp method.\n" + Environment.StackTrace.CleanupStackTrace());
|
||||
#endif
|
||||
GameAnalyticsManager.AddErrorEventOnce("ToolBox.GradientLerp:EmptyColorArray", GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||
"Empty color array passed to the GradientLerp method.\n" + Environment.StackTrace);
|
||||
"Empty color array passed to the GradientLerp method.\n" + Environment.StackTrace.CleanupStackTrace());
|
||||
return Color.Black;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<RootNamespace>Barotrauma</RootNamespace>
|
||||
<Authors>FakeFish, Undertow Games</Authors>
|
||||
<Product>Barotrauma</Product>
|
||||
<Version>0.10.5.1</Version>
|
||||
<Version>0.10.600.0</Version>
|
||||
<Copyright>Copyright © FakeFish 2018-2020</Copyright>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<AssemblyName>Barotrauma</AssemblyName>
|
||||
@@ -178,6 +178,10 @@
|
||||
<_Parameter1>GitBranch</_Parameter1>
|
||||
<_Parameter2>$(BuildBranch)</_Parameter2>
|
||||
</AssemblyAttributes>
|
||||
<AssemblyAttributes Include="AssemblyMetadata">
|
||||
<_Parameter1>ProjectDir</_Parameter1>
|
||||
<_Parameter2>$(ProjectDir)</_Parameter2>
|
||||
</AssemblyAttributes>
|
||||
</ItemGroup>
|
||||
<!-- writes the attribute to the customAssemblyInfo file -->
|
||||
<WriteCodeFragment Language="C#" OutputFile="$(CustomAssemblyInfoFile)" AssemblyAttributes="@(AssemblyAttributes)" />
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<RootNamespace>Barotrauma</RootNamespace>
|
||||
<Authors>FakeFish, Undertow Games</Authors>
|
||||
<Product>Barotrauma</Product>
|
||||
<Version>0.10.5.1</Version>
|
||||
<Version>0.10.600.0</Version>
|
||||
<Copyright>Copyright © FakeFish 2018-2020</Copyright>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<AssemblyName>Barotrauma</AssemblyName>
|
||||
@@ -180,6 +180,10 @@
|
||||
<_Parameter1>GitBranch</_Parameter1>
|
||||
<_Parameter2>$(BuildBranch)</_Parameter2>
|
||||
</AssemblyAttributes>
|
||||
<AssemblyAttributes Include="AssemblyMetadata">
|
||||
<_Parameter1>ProjectDir</_Parameter1>
|
||||
<_Parameter2>$(ProjectDir)</_Parameter2>
|
||||
</AssemblyAttributes>
|
||||
</ItemGroup>
|
||||
<!-- writes the attribute to the customAssemblyInfo file -->
|
||||
<WriteCodeFragment Language="C#" OutputFile="$(CustomAssemblyInfoFile)" AssemblyAttributes="@(AssemblyAttributes)" />
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<RootNamespace>Barotrauma</RootNamespace>
|
||||
<Authors>FakeFish, Undertow Games</Authors>
|
||||
<Product>Barotrauma</Product>
|
||||
<Version>0.10.5.1</Version>
|
||||
<Version>0.10.600.0</Version>
|
||||
<Copyright>Copyright © FakeFish 2018-2020</Copyright>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<AssemblyName>Barotrauma</AssemblyName>
|
||||
@@ -209,6 +209,10 @@
|
||||
<_Parameter1>GitBranch</_Parameter1>
|
||||
<_Parameter2>$(BuildBranch)</_Parameter2>
|
||||
</AssemblyAttributes>
|
||||
<AssemblyAttributes Include="AssemblyMetadata">
|
||||
<_Parameter1>ProjectDir</_Parameter1>
|
||||
<_Parameter2>$(ProjectDir)</_Parameter2>
|
||||
</AssemblyAttributes>
|
||||
</ItemGroup>
|
||||
<!-- writes the attribute to the customAssemblyInfo file -->
|
||||
<WriteCodeFragment Language="C#" OutputFile="$(CustomAssemblyInfoFile)" AssemblyAttributes="@(AssemblyAttributes)" />
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<RootNamespace>Barotrauma</RootNamespace>
|
||||
<Authors>FakeFish, Undertow Games</Authors>
|
||||
<Product>Barotrauma Dedicated Server</Product>
|
||||
<Version>0.10.5.1</Version>
|
||||
<Version>0.10.600.0</Version>
|
||||
<Copyright>Copyright © FakeFish 2018-2020</Copyright>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<AssemblyName>DedicatedServer</AssemblyName>
|
||||
@@ -127,6 +127,10 @@
|
||||
<_Parameter1>GitBranch</_Parameter1>
|
||||
<_Parameter2>$(BuildBranch)</_Parameter2>
|
||||
</AssemblyAttributes>
|
||||
<AssemblyAttributes Include="AssemblyMetadata">
|
||||
<_Parameter1>ProjectDir</_Parameter1>
|
||||
<_Parameter2>$(ProjectDir)</_Parameter2>
|
||||
</AssemblyAttributes>
|
||||
</ItemGroup>
|
||||
<!-- writes the attribute to the customAssemblyInfo file -->
|
||||
<WriteCodeFragment Language="C#" OutputFile="$(CustomAssemblyInfoFile)" AssemblyAttributes="@(AssemblyAttributes)" />
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<RootNamespace>Barotrauma</RootNamespace>
|
||||
<Authors>FakeFish, Undertow Games</Authors>
|
||||
<Product>Barotrauma Dedicated Server</Product>
|
||||
<Version>0.10.5.1</Version>
|
||||
<Version>0.10.600.0</Version>
|
||||
<Copyright>Copyright © FakeFish 2018-2020</Copyright>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<AssemblyName>DedicatedServer</AssemblyName>
|
||||
@@ -140,6 +140,10 @@
|
||||
<_Parameter1>GitBranch</_Parameter1>
|
||||
<_Parameter2>$(BuildBranch)</_Parameter2>
|
||||
</AssemblyAttributes>
|
||||
<AssemblyAttributes Include="AssemblyMetadata">
|
||||
<_Parameter1>ProjectDir</_Parameter1>
|
||||
<_Parameter2>$(ProjectDir)</_Parameter2>
|
||||
</AssemblyAttributes>
|
||||
</ItemGroup>
|
||||
<!-- writes the attribute to the customAssemblyInfo file -->
|
||||
<WriteCodeFragment Language="C#" OutputFile="$(CustomAssemblyInfoFile)" AssemblyAttributes="@(AssemblyAttributes)" />
|
||||
|
||||
@@ -528,19 +528,19 @@ namespace Barotrauma
|
||||
{
|
||||
msg.Write(true);
|
||||
msg.Write((byte)Order.PrefabList.IndexOf(info.CurrentOrder.Prefab));
|
||||
msg.Write(info.CurrentOrder.TargetEntity == null ? (UInt16)0 :
|
||||
info.CurrentOrder.TargetEntity.ID);
|
||||
if (info.CurrentOrder.OrderGiver != null)
|
||||
msg.Write(info.CurrentOrder.TargetEntity == null ? (UInt16)0 : info.CurrentOrder.TargetEntity.ID);
|
||||
var hasOrderGiver = info.CurrentOrder.OrderGiver != null;
|
||||
msg.Write(hasOrderGiver);
|
||||
if (hasOrderGiver) { msg.Write(info.CurrentOrder.OrderGiver.ID); }
|
||||
msg.Write((byte)(string.IsNullOrWhiteSpace(info.CurrentOrderOption) ? 0 : Array.IndexOf(info.CurrentOrder.Prefab.Options, info.CurrentOrderOption)));
|
||||
var hasTargetPosition = info.CurrentOrder.TargetPosition != null;
|
||||
msg.Write(hasTargetPosition);
|
||||
if (hasTargetPosition)
|
||||
{
|
||||
msg.Write(true);
|
||||
msg.Write(info.CurrentOrder.OrderGiver.ID);
|
||||
msg.Write(info.CurrentOrder.TargetPosition.Position.X);
|
||||
msg.Write(info.CurrentOrder.TargetPosition.Position.Y);
|
||||
msg.Write(info.CurrentOrder.TargetPosition.Hull == null ? (UInt16)0 : info.CurrentOrder.TargetPosition.Hull.ID);
|
||||
}
|
||||
else
|
||||
{
|
||||
msg.Write(false);
|
||||
}
|
||||
msg.Write((byte)(string.IsNullOrWhiteSpace(info.CurrentOrderOption) ? 0 :
|
||||
Array.IndexOf(info.CurrentOrder.Prefab.Options, info.CurrentOrderOption)));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -247,7 +247,7 @@ namespace Barotrauma
|
||||
catch (Exception e)
|
||||
{
|
||||
string errorMsg = "Failed to write input to command line (window width: " + Console.WindowWidth + ", window height: " + Console.WindowHeight + ")\n"
|
||||
+ e.Message + "\n" + e.StackTrace;
|
||||
+ e.Message + "\n" + e.StackTrace.CleanupStackTrace();
|
||||
GameAnalyticsManager.AddErrorEventOnce("DebugConsole.RewriteInputToCommandLine", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||
}
|
||||
}
|
||||
@@ -1352,7 +1352,7 @@ namespace Barotrauma
|
||||
ServerEntityEvent ev = GameMain.Server.EntityEventManager.Events[Convert.ToUInt16(args[0])];
|
||||
if (ev != null)
|
||||
{
|
||||
NewMessage(ev.StackTrace, Color.Lime);
|
||||
NewMessage(ev.StackTrace.CleanupStackTrace(), Color.Lime);
|
||||
}
|
||||
}));
|
||||
|
||||
|
||||
@@ -694,6 +694,10 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
pendingHireInfos.Add(match);
|
||||
if (pendingHireInfos.Count + CrewManager.CharacterInfos.Count() >= CrewManager.MaxCrewSize)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
location.HireManager.PendingHires = pendingHireInfos;
|
||||
}
|
||||
|
||||
@@ -67,8 +67,26 @@ namespace Barotrauma.Items.Components
|
||||
if (!CheckCharacterSuccess(c.Character))
|
||||
{
|
||||
item.CreateServerEvent(this);
|
||||
c.Character.SelectedItems[0]?.GetComponent<Wire>()?.CreateNetworkEvent();
|
||||
c.Character.SelectedItems[1]?.GetComponent<Wire>()?.CreateNetworkEvent();
|
||||
c.Character.Inventory?.CreateNetworkEvent();
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
var selectedWire = c.Character.SelectedItems[i]?.GetComponent<Wire>();
|
||||
if (selectedWire == null) { continue; }
|
||||
|
||||
selectedWire.CreateNetworkEvent();
|
||||
var panel1 = selectedWire.Connections[0]?.ConnectionPanel;
|
||||
if (panel1 != null && panel1 != this) { panel1.item.CreateServerEvent(panel1); }
|
||||
var panel2 = selectedWire.Connections[1]?.ConnectionPanel;
|
||||
if (panel2 != null && panel2 != this) { panel2.item.CreateServerEvent(panel2); }
|
||||
|
||||
CoroutineManager.InvokeAfter(() =>
|
||||
{
|
||||
item.CreateServerEvent(this);
|
||||
if (panel1 != null && panel1 != this) { panel1.item.CreateServerEvent(panel1); }
|
||||
if (panel2 != null && panel2 != this) { panel2.item.CreateServerEvent(panel2); }
|
||||
if (!selectedWire.Item.Removed) { selectedWire.CreateNetworkEvent(); }
|
||||
}, 1.0f);
|
||||
}
|
||||
GameMain.Server?.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.ApplyStatusEffect, ActionType.OnFailure, this, c.Character.ID });
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -371,7 +371,7 @@ namespace Barotrauma
|
||||
|
||||
if (!ItemList.Contains(this))
|
||||
{
|
||||
string errorMsg = "Attempted to create a network event for an item (" + Name + ") that hasn't been fully initialized yet.\n" + Environment.StackTrace;
|
||||
string errorMsg = "Attempted to create a network event for an item (" + Name + ") that hasn't been fully initialized yet.\n" + Environment.StackTrace.CleanupStackTrace();
|
||||
DebugConsole.ThrowError(errorMsg);
|
||||
GameAnalyticsManager.AddErrorEventOnce("Item.CreateServerEvent:EventForUninitializedItem" + Name + ID, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||
return;
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace Barotrauma
|
||||
private float lastSentVolume, lastSentOxygen, lastSentFireCount;
|
||||
private float sendUpdateTimer;
|
||||
|
||||
private bool decalsChanged;
|
||||
private bool decalUpdatePending;
|
||||
|
||||
public override bool IsMouseOn(Vector2 position)
|
||||
{
|
||||
@@ -32,27 +32,21 @@ namespace Barotrauma
|
||||
return;
|
||||
}
|
||||
|
||||
if (decalsChanged)
|
||||
{
|
||||
GameMain.NetworkMember.CreateEntityEvent(this, new object[] { false });
|
||||
lastSentVolume = waterVolume;
|
||||
lastSentOxygen = OxygenPercentage;
|
||||
lastSentFireCount = FireSources.Count;
|
||||
sendUpdateTimer = NetConfig.HullUpdateInterval;
|
||||
decalsChanged = false;
|
||||
return;
|
||||
}
|
||||
|
||||
sendUpdateTimer -= deltaTime;
|
||||
//update client hulls if the amount of water has changed by >10%
|
||||
//or if oxygen percentage has changed by 5%
|
||||
if (Math.Abs(lastSentVolume - waterVolume) > Volume * 0.1f || Math.Abs(lastSentOxygen - OxygenPercentage) > 5f ||
|
||||
lastSentFireCount != FireSources.Count || FireSources.Count > 0 ||
|
||||
pendingSectionUpdates.Count > 0 ||
|
||||
sendUpdateTimer < -NetConfig.SparseHullUpdateInterval)
|
||||
sendUpdateTimer < -NetConfig.SparseHullUpdateInterval ||
|
||||
decalUpdatePending)
|
||||
{
|
||||
if (sendUpdateTimer < 0.0f)
|
||||
{
|
||||
if (decalUpdatePending)
|
||||
{
|
||||
GameMain.NetworkMember.CreateEntityEvent(this, new object[] { false });
|
||||
}
|
||||
if (pendingSectionUpdates.Count > 0)
|
||||
{
|
||||
foreach (int pendingSectionUpdate in pendingSectionUpdates)
|
||||
@@ -120,8 +114,9 @@ namespace Barotrauma
|
||||
foreach (Decal decal in decals)
|
||||
{
|
||||
message.Write(decal.Prefab.UIntIdentifier);
|
||||
float normalizedXPos = MathHelper.Clamp(MathUtils.InverseLerp(rect.X, rect.Right, decal.Position.X), 0.0f, 1.0f);
|
||||
float normalizedYPos = MathHelper.Clamp(MathUtils.InverseLerp(rect.Y - rect.Height, rect.Y, decal.Position.Y), 0.0f, 1.0f);
|
||||
message.Write((byte)decal.SpriteIndex);
|
||||
float normalizedXPos = MathHelper.Clamp(MathUtils.InverseLerp(0.0f, rect.Width, decal.CenterPosition.X), 0.0f, 1.0f);
|
||||
float normalizedYPos = MathHelper.Clamp(MathUtils.InverseLerp(-rect.Height, 0.0f, decal.CenterPosition.Y), 0.0f, 1.0f);
|
||||
message.WriteRangedSingle(normalizedXPos, 0.0f, 1.0f, 8);
|
||||
message.WriteRangedSingle(normalizedYPos, 0.0f, 1.0f, 8);
|
||||
message.WriteRangedSingle(decal.Scale, 0f, 2f, 12);
|
||||
|
||||
@@ -332,7 +332,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
catch (Exception e)
|
||||
{
|
||||
string errorMsg = "Error while writing banlist. {" + e + "}\n" + e.StackTrace;
|
||||
string errorMsg = "Error while writing banlist. {" + e + "}\n" + e.StackTrace.CleanupStackTrace();
|
||||
GameAnalyticsManager.AddErrorEventOnce("Banlist.ServerAdminWrite", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||
throw;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
using Barotrauma.Items.Components;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Barotrauma.Networking
|
||||
@@ -14,19 +12,25 @@ namespace Barotrauma.Networking
|
||||
|
||||
UInt16 ID = msg.ReadUInt16();
|
||||
ChatMessageType type = (ChatMessageType)msg.ReadByte();
|
||||
string txt = "";
|
||||
string txt;
|
||||
|
||||
int orderIndex = -1;
|
||||
Character orderTargetCharacter = null;
|
||||
Entity orderTargetEntity = null;
|
||||
int orderOptionIndex = -1;
|
||||
OrderChatMessage orderMsg = null;
|
||||
OrderTarget orderTargetPosition = null;
|
||||
if (type == ChatMessageType.Order)
|
||||
{
|
||||
orderIndex = msg.ReadByte();
|
||||
int orderIndex = msg.ReadByte();
|
||||
orderTargetCharacter = Entity.FindEntityByID(msg.ReadUInt16()) as Character;
|
||||
orderTargetEntity = Entity.FindEntityByID(msg.ReadUInt16()) as Entity;
|
||||
orderOptionIndex = msg.ReadByte();
|
||||
int orderOptionIndex = msg.ReadByte();
|
||||
if (msg.ReadBoolean())
|
||||
{
|
||||
var x = msg.ReadSingle();
|
||||
var y = msg.ReadSingle();
|
||||
var hull = Entity.FindEntityByID(msg.ReadUInt16()) as Hull;
|
||||
orderTargetPosition = new OrderTarget(new Vector2(x, y), hull, true);
|
||||
}
|
||||
|
||||
if (orderIndex < 0 || orderIndex >= Order.PrefabList.Count)
|
||||
{
|
||||
@@ -37,7 +41,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
Order order = Order.PrefabList[orderIndex];
|
||||
string orderOption = orderOptionIndex < 0 || orderOptionIndex >= order.Options.Length ? "" : order.Options[orderOptionIndex];
|
||||
orderMsg = new OrderChatMessage(order, orderOption, orderTargetEntity, orderTargetCharacter, c.Character);
|
||||
orderMsg = new OrderChatMessage(order, orderOption, orderTargetPosition ?? orderTargetEntity as ISpatialEntity, orderTargetCharacter, c.Character);
|
||||
txt = orderMsg.Text;
|
||||
}
|
||||
else
|
||||
@@ -114,20 +118,14 @@ namespace Barotrauma.Networking
|
||||
|
||||
if (type == ChatMessageType.Order)
|
||||
{
|
||||
if (c.Character == null || c.Character.SpeechImpediment >= 100.0f || c.Character.IsDead) return;
|
||||
|
||||
ChatMessageType messageType = CanUseRadio(orderMsg.Sender) ? ChatMessageType.Radio : ChatMessageType.Default;
|
||||
if (orderMsg.Order.TargetAllCharacters)
|
||||
if (c.Character == null || c.Character.SpeechImpediment >= 100.0f || c.Character.IsDead) { return; }
|
||||
if (!orderMsg.Order.TargetAllCharacters && orderTargetCharacter != null)
|
||||
{
|
||||
//do nothing
|
||||
var order = orderTargetPosition == null ?
|
||||
new Order(orderMsg.Order.Prefab, orderTargetEntity, orderMsg.Order.Prefab?.GetTargetItemComponent(orderTargetEntity as Item), orderMsg.Sender) :
|
||||
new Order(orderMsg.Order.Prefab, orderTargetPosition, orderMsg.Sender);
|
||||
orderTargetCharacter.SetOrder(order, orderMsg.OrderOption, orderMsg.Sender);
|
||||
}
|
||||
else if (orderTargetCharacter != null)
|
||||
{
|
||||
orderTargetCharacter.SetOrder(
|
||||
new Order(orderMsg.Order.Prefab, orderTargetEntity, (orderTargetEntity as Item)?.Components.FirstOrDefault(ic => ic.GetType() == orderMsg.Order.ItemComponentType)),
|
||||
orderMsg.OrderOption, orderMsg.Sender);
|
||||
}
|
||||
|
||||
GameMain.Server.SendOrderChatMessage(orderMsg);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -272,7 +272,7 @@ namespace Barotrauma.Networking
|
||||
GameAnalyticsManager.AddErrorEventOnce(
|
||||
"FileSender.Update:Exception",
|
||||
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||
"FileSender threw an exception when trying to send data:\n" + e.Message + "\n" + e.StackTrace);
|
||||
"FileSender threw an exception when trying to send data:\n" + e.Message + "\n" + e.StackTrace.CleanupStackTrace());
|
||||
transfer.Status = FileTransferStatus.Error;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -615,14 +615,14 @@ namespace Barotrauma.Networking
|
||||
DebugConsole.ThrowError("Failed to write a network message for the client \"" + c.Name + "\"!", e);
|
||||
|
||||
string errorMsg = "Failed to write a network message for the client \"" + c.Name + "\"! (MidRoundSyncing: " + c.NeedsMidRoundSync + ")\n"
|
||||
+ e.Message + "\n" + e.StackTrace;
|
||||
+ e.Message + "\n" + e.StackTrace.CleanupStackTrace();
|
||||
if (e.InnerException != null)
|
||||
{
|
||||
errorMsg += "\nInner exception: " + e.InnerException.Message + "\n" + e.InnerException.StackTrace;
|
||||
errorMsg += "\nInner exception: " + e.InnerException.Message + "\n" + e.InnerException.StackTrace.CleanupStackTrace();
|
||||
}
|
||||
|
||||
GameAnalyticsManager.AddErrorEventOnce(
|
||||
"GameServer.Update:ClientWriteFailed" + e.StackTrace,
|
||||
"GameServer.Update:ClientWriteFailed" + e.StackTrace.CleanupStackTrace(),
|
||||
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||
errorMsg);
|
||||
}
|
||||
@@ -1796,7 +1796,7 @@ namespace Barotrauma.Networking
|
||||
outmsg.Write(GameMain.NetLobbyScreen.SelectedShuttle.Name);
|
||||
outmsg.Write(GameMain.NetLobbyScreen.SelectedShuttle.MD5Hash.ToString());
|
||||
|
||||
string campaignSubmarineIndexes = string.Empty;
|
||||
List<int> campaignSubIndices = new List<int>();
|
||||
if (GameMain.NetLobbyScreen.SelectedMode == GameModePreset.MultiPlayerCampaign)
|
||||
{
|
||||
List<SubmarineInfo> subList = GameMain.NetLobbyScreen.GetSubList();
|
||||
@@ -1804,17 +1804,15 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
if (GameMain.NetLobbyScreen.CampaignSubmarines.Contains(subList[i]))
|
||||
{
|
||||
campaignSubmarineIndexes += i.ToString();
|
||||
campaignSubmarineIndexes += ";";
|
||||
campaignSubIndices.Add(i);
|
||||
}
|
||||
}
|
||||
|
||||
if (campaignSubmarineIndexes.Length > 0)
|
||||
{
|
||||
campaignSubmarineIndexes.Trim(';');
|
||||
}
|
||||
}
|
||||
outmsg.Write(campaignSubmarineIndexes);
|
||||
outmsg.Write((UInt16)campaignSubIndices.Count);
|
||||
foreach (int campaignSubIndex in campaignSubIndices)
|
||||
{
|
||||
outmsg.Write((UInt16)campaignSubIndex);
|
||||
}
|
||||
|
||||
outmsg.Write(serverSettings.Voting.AllowSubVoting);
|
||||
outmsg.Write(serverSettings.Voting.AllowModeVoting);
|
||||
@@ -2437,7 +2435,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
if (GameSettings.VerboseLogging)
|
||||
{
|
||||
Log("Ending the round...\n" + Environment.StackTrace, ServerLog.MessageType.ServerMessage);
|
||||
Log("Ending the round...\n" + Environment.StackTrace.CleanupStackTrace(), ServerLog.MessageType.ServerMessage);
|
||||
|
||||
}
|
||||
else
|
||||
@@ -2772,7 +2770,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
if (recipient == null)
|
||||
{
|
||||
string errorMsg = "Attempted to send a chat message to a null client.\n" + Environment.StackTrace;
|
||||
string errorMsg = "Attempted to send a chat message to a null client.\n" + Environment.StackTrace.CleanupStackTrace();
|
||||
DebugConsole.ThrowError(errorMsg);
|
||||
GameAnalyticsManager.AddErrorEventOnce("GameServer.SendDirectChatMessage:ClientNull", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||
return;
|
||||
@@ -3069,12 +3067,13 @@ namespace Barotrauma.Networking
|
||||
|
||||
Client.UpdateKickVotes(connectedClients);
|
||||
|
||||
int minimumKickVotes = Math.Max(1, (int)(connectedClients.Count * serverSettings.KickVoteRequiredRatio));
|
||||
var clientsToKick = connectedClients.FindAll(c =>
|
||||
c.Connection != OwnerConnection &&
|
||||
!c.HasPermission(ClientPermissions.Kick) &&
|
||||
!c.HasPermission(ClientPermissions.Ban) &&
|
||||
!c.HasPermission(ClientPermissions.Unban) &&
|
||||
c.KickVoteCount >= connectedClients.Count * serverSettings.KickVoteRequiredRatio);
|
||||
c.KickVoteCount >= minimumKickVotes);
|
||||
foreach (Client c in clientsToKick)
|
||||
{
|
||||
var previousPlayer = previousPlayers.Find(p => p.MatchesClient(c));
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace Barotrauma.Networking
|
||||
createTime = Timing.TotalTime;
|
||||
|
||||
#if DEBUG
|
||||
StackTrace = Environment.StackTrace.ToString();
|
||||
StackTrace = Environment.StackTrace.CleanupStackTrace();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -121,12 +121,12 @@ namespace Barotrauma.Networking
|
||||
|
||||
if (((Entity)entity).Removed && !(entity is Level))
|
||||
{
|
||||
DebugConsole.ThrowError("Can't create an entity event for " + entity + " - the entity has been removed.\n"+Environment.StackTrace);
|
||||
DebugConsole.ThrowError("Can't create an entity event for " + entity + " - the entity has been removed.\n"+Environment.StackTrace.CleanupStackTrace());
|
||||
return;
|
||||
}
|
||||
if (((Entity)entity).IdFreed)
|
||||
{
|
||||
DebugConsole.ThrowError("Can't create an entity event for " + entity + " - the ID of the entity has been freed.\n"+Environment.StackTrace);
|
||||
DebugConsole.ThrowError("Can't create an entity event for " + entity + " - the ID of the entity has been freed.\n"+Environment.StackTrace.CleanupStackTrace());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -197,12 +197,12 @@ namespace Barotrauma.Networking
|
||||
if (GameSettings.VerboseLogging)
|
||||
{
|
||||
string errorMsg = "Failed to read server event for entity \"" + entityName + "\"!";
|
||||
GameServer.Log(errorMsg + "\n" + e.StackTrace, ServerLog.MessageType.Error);
|
||||
GameServer.Log(errorMsg + "\n" + e.StackTrace.CleanupStackTrace(), ServerLog.MessageType.Error);
|
||||
DebugConsole.ThrowError(errorMsg, e);
|
||||
}
|
||||
GameAnalyticsManager.AddErrorEventOnce("ServerEntityEventManager.Read:ReadFailed" + entityName,
|
||||
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||
"Failed to read server event for entity \"" + entityName + "\"!\n" + e.StackTrace);
|
||||
"Failed to read server event for entity \"" + entityName + "\"!\n" + e.StackTrace.CleanupStackTrace());
|
||||
}
|
||||
|
||||
bufferedEvent.IsProcessed = true;
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Barotrauma.Networking
|
||||
{
|
||||
@@ -21,8 +19,19 @@ namespace Barotrauma.Networking
|
||||
|
||||
msg.Write((byte)Order.PrefabList.IndexOf(Order.Prefab));
|
||||
msg.Write(TargetCharacter == null ? (UInt16)0 : TargetCharacter.ID);
|
||||
msg.Write(TargetEntity == null ? (UInt16)0 : TargetEntity.ID);
|
||||
msg.Write(TargetEntity is Entity ? (TargetEntity as Entity).ID : (UInt16)0);
|
||||
msg.Write((byte)Array.IndexOf(Order.Prefab.Options, OrderOption));
|
||||
if (TargetEntity is OrderTarget orderTarget)
|
||||
{
|
||||
msg.Write(true);
|
||||
msg.Write(orderTarget.Position.X);
|
||||
msg.Write(orderTarget.Position.Y);
|
||||
msg.Write(orderTarget.Hull == null ? (UInt16)0 : orderTarget.Hull.ID);
|
||||
}
|
||||
else
|
||||
{
|
||||
msg.Write(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,7 +124,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
catch (Exception e)
|
||||
{
|
||||
string errorMsg = "Server failed to read an incoming message. {" + e + "}\n" + e.StackTrace;
|
||||
string errorMsg = "Server failed to read an incoming message. {" + e + "}\n" + e.StackTrace.CleanupStackTrace();
|
||||
GameAnalyticsManager.AddErrorEventOnce("LidgrenServerPeer.Update:ClientReadException" + e.TargetSite.ToString(), GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||
#if DEBUG
|
||||
DebugConsole.ThrowError(errorMsg);
|
||||
|
||||
@@ -87,7 +87,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
if (!Client.IsValidName(name, serverSettings))
|
||||
{
|
||||
RemovePendingClient(pendingClient, DisconnectReason.InvalidName, "The name \"" + name + "\" is invalid");
|
||||
RemovePendingClient(pendingClient, DisconnectReason.InvalidName, "");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -101,7 +101,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
catch (Exception e)
|
||||
{
|
||||
string errorMsg = "Server failed to read an incoming message. {" + e + "}\n" + e.StackTrace;
|
||||
string errorMsg = "Server failed to read an incoming message. {" + e + "}\n" + e.StackTrace.CleanupStackTrace();
|
||||
GameAnalyticsManager.AddErrorEventOnce("SteamP2PServerPeer.Update:ClientReadException" + e.TargetSite.ToString(), GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||
#if DEBUG
|
||||
DebugConsole.ThrowError(errorMsg);
|
||||
@@ -293,9 +293,9 @@ namespace Barotrauma.Networking
|
||||
if (!started) { return; }
|
||||
|
||||
if (!(conn is SteamP2PConnection steamp2pConn)) { return; }
|
||||
if (sendDisconnectMessage) { SendDisconnectMessage(steamp2pConn.SteamID, msg); }
|
||||
if (connectedClients.Contains(steamp2pConn))
|
||||
{
|
||||
if (sendDisconnectMessage) SendDisconnectMessage(steamp2pConn.SteamID, msg);
|
||||
steamp2pConn.Status = NetworkConnectionStatus.Disconnected;
|
||||
connectedClients.Remove(steamp2pConn);
|
||||
OnDisconnect?.Invoke(conn, msg);
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace Barotrauma
|
||||
setLinuxEnv();
|
||||
#endif
|
||||
Console.WriteLine("Barotrauma Dedicated Server " + GameMain.Version +
|
||||
" (" + AssemblyInfo.GetBuildString() + ", branch " + AssemblyInfo.GetGitBranch() + ", revision " + AssemblyInfo.GetGitRevision() + ")");
|
||||
" (" + AssemblyInfo.BuildString + ", branch " + AssemblyInfo.GitBranch + ", revision " + AssemblyInfo.GitRevision + ")");
|
||||
|
||||
string executableDir = Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location);
|
||||
Directory.SetCurrentDirectory(executableDir);
|
||||
@@ -99,7 +99,7 @@ namespace Barotrauma
|
||||
sb.AppendLine("\n");
|
||||
sb.AppendLine("Barotrauma seems to have crashed. Sorry for the inconvenience! ");
|
||||
sb.AppendLine("\n");
|
||||
sb.AppendLine("Game version " + GameMain.Version + " (" + AssemblyInfo.GetBuildString() + ", branch " + AssemblyInfo.GetGitBranch() + ", revision " + AssemblyInfo.GetGitRevision() + ")");
|
||||
sb.AppendLine("Game version " + GameMain.Version + " (" + AssemblyInfo.BuildString + ", branch " + AssemblyInfo.GitBranch + ", revision " + AssemblyInfo.GitRevision + ")");
|
||||
if (GameMain.Config != null)
|
||||
{
|
||||
sb.AppendLine("Language: " + (GameMain.Config.Language ?? "none"));
|
||||
@@ -124,7 +124,7 @@ namespace Barotrauma
|
||||
sb.AppendLine("Exception: " + exception.Message + " (" + exception.GetType().ToString() + ")");
|
||||
sb.AppendLine("Target site: " +exception.TargetSite.ToString());
|
||||
sb.AppendLine("Stack trace: ");
|
||||
sb.AppendLine(exception.StackTrace);
|
||||
sb.AppendLine(exception.StackTrace.CleanupStackTrace());
|
||||
sb.AppendLine("\n");
|
||||
|
||||
if (exception.InnerException != null)
|
||||
@@ -135,7 +135,7 @@ namespace Barotrauma
|
||||
sb.AppendLine("Target site: " + exception.InnerException.TargetSite.ToString());
|
||||
}
|
||||
sb.AppendLine("Stack trace: ");
|
||||
sb.AppendLine(exception.InnerException.StackTrace);
|
||||
sb.AppendLine(exception.InnerException.StackTrace.CleanupStackTrace());
|
||||
}
|
||||
|
||||
sb.AppendLine("Last debug messages:");
|
||||
|
||||
@@ -261,7 +261,7 @@ namespace Barotrauma
|
||||
|
||||
if (GameMain.Server.ServerSettings.SubSelectionMode == SelectionMode.Random)
|
||||
{
|
||||
var nonShuttles = SubmarineInfo.SavedSubmarines.Where(c => !c.HasTag(SubmarineTag.Shuttle) && !c.HasTag(SubmarineTag.HideInMenus)).ToList();
|
||||
var nonShuttles = SubmarineInfo.SavedSubmarines.Where(c => !c.HasTag(SubmarineTag.Shuttle) && !c.HasTag(SubmarineTag.HideInMenus) && c.IsPlayer).ToList();
|
||||
SelectedSub = nonShuttles[Rand.Range(0, nonShuttles.Count)];
|
||||
}
|
||||
if (GameMain.Server.ServerSettings.ModeSelectionMode == SelectionMode.Random)
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<RootNamespace>Barotrauma</RootNamespace>
|
||||
<Authors>FakeFish, Undertow Games</Authors>
|
||||
<Product>Barotrauma Dedicated Server</Product>
|
||||
<Version>0.10.5.1</Version>
|
||||
<Version>0.10.600.0</Version>
|
||||
<Copyright>Copyright © FakeFish 2018-2020</Copyright>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<AssemblyName>DedicatedServer</AssemblyName>
|
||||
@@ -135,6 +135,10 @@
|
||||
<_Parameter1>GitBranch</_Parameter1>
|
||||
<_Parameter2>$(BuildBranch)</_Parameter2>
|
||||
</AssemblyAttributes>
|
||||
<AssemblyAttributes Include="AssemblyMetadata">
|
||||
<_Parameter1>ProjectDir</_Parameter1>
|
||||
<_Parameter2>$(ProjectDir)</_Parameter2>
|
||||
</AssemblyAttributes>
|
||||
</ItemGroup>
|
||||
<!-- writes the attribute to the customAssemblyInfo file -->
|
||||
<WriteCodeFragment Language="C#" OutputFile="$(CustomAssemblyInfoFile)" AssemblyAttributes="@(AssemblyAttributes)" />
|
||||
|
||||
@@ -80,17 +80,19 @@
|
||||
<Character file="Content/Characters/Legacycrawler/Legacycrawler.xml" />
|
||||
<Character file="Content/Characters/Legacymoloch/Legacymoloch.xml" />
|
||||
<Character file="Content/Characters/Legacytigerthresher/Legacytigerthresher.xml" />
|
||||
<Character file="Content/Characters/Legacywatcher/Legacywatcher.xml" />
|
||||
<Character file="Content/Characters/Mudraptor/Mudraptor.xml" />
|
||||
<Character file="Content/Characters/Mudraptor_unarmored/Mudraptor_unarmored.xml" />
|
||||
<Character file="Content/Characters/Mantis/Mantis.xml" />
|
||||
<Character file="Content/Characters/Moloch/Moloch.xml" />
|
||||
<Character file="Content/Characters/Moloch_m/Moloch_m.xml" />
|
||||
<Character file="Content/Characters/Molochblack/Molochblack.xml" />
|
||||
<Character file="Content/Characters/Molochbaby/Molochbaby.xml" />
|
||||
<Character file="Content/Characters/Watcher/Watcher.xml" />
|
||||
<Character file="Content/Characters/Tigerthresher/Tigerthresher.xml" />
|
||||
<Character file="Content/Characters/Bonethresher/Bonethresher.xml" />
|
||||
<Character file="Content/Characters/Leucocyte/Leucocyte.xml" />
|
||||
<Character file="Content/Characters/Terminalcell/Terminalcell.xml" />
|
||||
<Character file="Content/Characters/Watcher/Watcher.xml" />
|
||||
<Wreck file="Content/Map/Wrecks/Dugong_Wrecked.sub" />
|
||||
<Wreck file="Content/Map/Wrecks/Kastrull_Wrecked.sub" />
|
||||
<Wreck file="Content/Map/Wrecks/Berilia_Wrecked.sub" />
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user