diff --git a/Content.Benchmarks/Content.Benchmarks.csproj b/Content.Benchmarks/Content.Benchmarks.csproj index 700556482f..2eedacc7f0 100644 --- a/Content.Benchmarks/Content.Benchmarks.csproj +++ b/Content.Benchmarks/Content.Benchmarks.csproj @@ -11,7 +11,7 @@ 8 - + diff --git a/Content.Client/GameObjects/Components/Chemistry/ChemMaster/ChemMasterWindow.cs b/Content.Client/GameObjects/Components/Chemistry/ChemMaster/ChemMasterWindow.cs index a204c63124..3a2dece8e9 100644 --- a/Content.Client/GameObjects/Components/Chemistry/ChemMaster/ChemMasterWindow.cs +++ b/Content.Client/GameObjects/Components/Chemistry/ChemMaster/ChemMasterWindow.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using Content.Client.UserInterface; @@ -273,6 +273,34 @@ namespace Content.Client.GameObjects.Components.Chemistry.ChemMaster var castState = (ChemMasterBoundUserInterfaceState) state; Title = castState.DispenserName; UpdatePanelInfo(castState); + if (Contents.Children != null) + { + SetButtonDisabledRecursive(Contents, !castState.HasPower); + EjectButton.Disabled = !castState.HasBeaker; + } + } + + /// + /// This searches recursively through all the children of "parent" + /// and sets the Disabled value of any buttons found to "val" + /// + /// The control which childrens get searched + /// The value to which disabled gets set + private void SetButtonDisabledRecursive(Control parent, bool val) + { + foreach (var child in parent.Children) + { + if (child is Button but) + { + but.Disabled = val; + continue; + } + + if (child.Children != null) + { + SetButtonDisabledRecursive(child, val); + } + } } /// diff --git a/Content.Client/GameObjects/Components/Chemistry/ReagentDispenser/ReagentDispenserBoundUserInterface.cs b/Content.Client/GameObjects/Components/Chemistry/ReagentDispenser/ReagentDispenserBoundUserInterface.cs index 8f362cc49a..1aabef19dc 100644 --- a/Content.Client/GameObjects/Components/Chemistry/ReagentDispenser/ReagentDispenserBoundUserInterface.cs +++ b/Content.Client/GameObjects/Components/Chemistry/ReagentDispenser/ReagentDispenserBoundUserInterface.cs @@ -72,8 +72,8 @@ namespace Content.Client.GameObjects.Components.Chemistry var castState = (ReagentDispenserBoundUserInterfaceState)state; _lastState = castState; - _window?.UpdateState(castState); //Update window state UpdateReagentsList(castState.Inventory); //Update reagents list & reagent button actions + _window?.UpdateState(castState); //Update window state } /// diff --git a/Content.Client/GameObjects/Components/Chemistry/ReagentDispenser/ReagentDispenserWindow.cs b/Content.Client/GameObjects/Components/Chemistry/ReagentDispenser/ReagentDispenserWindow.cs index fade17e84c..66b5fd693f 100644 --- a/Content.Client/GameObjects/Components/Chemistry/ReagentDispenser/ReagentDispenserWindow.cs +++ b/Content.Client/GameObjects/Components/Chemistry/ReagentDispenser/ReagentDispenserWindow.cs @@ -161,6 +161,29 @@ namespace Content.Client.GameObjects.Components.Chemistry } } + /// + /// This searches recursively through all the children of "parent" + /// and sets the Disabled value of any buttons found to "val" + /// + /// The control which childrens get searched + /// The value to which disabled gets set + private void SetButtonDisabledRecursive(Control parent, bool val) + { + foreach (var child in parent.Children) + { + if (child is Button but) + { + but.Disabled = val; + continue; + } + + if (child.Children != null) + { + SetButtonDisabledRecursive(child, val); + } + } + } + /// /// Update the UI state when new state data is received from the server. /// @@ -171,6 +194,20 @@ namespace Content.Client.GameObjects.Components.Chemistry Title = castState.DispenserName; UpdateContainerInfo(castState); + // Disable all buttons if not powered + if (Contents.Children != null) + { + SetButtonDisabledRecursive(Contents, !castState.HasPower); + EjectButton.Disabled = false; + } + + // Disable the Clear & Eject button if no beaker + if (!castState.HasBeaker) + { + ClearButton.Disabled = true; + EjectButton.Disabled = true; + } + switch (castState.SelectedDispenseAmount.Int()) { case 1: diff --git a/Content.Client/GameObjects/Components/RadiatingLightComponent.cs b/Content.Client/GameObjects/Components/RadiatingLightComponent.cs new file mode 100644 index 0000000000..76b57f2fb4 --- /dev/null +++ b/Content.Client/GameObjects/Components/RadiatingLightComponent.cs @@ -0,0 +1,46 @@ +using System; +using Robust.Client.Animations; +using Robust.Client.GameObjects; +using Robust.Client.GameObjects.Components.Animations; +using Robust.Shared.Animations; +using Robust.Shared.GameObjects; +using Robust.Shared.Maths; + +namespace Content.Client.GameObjects.Components +{ + [RegisterComponent] + public class RadiatingLightComponent : Component + { + public override string Name => "RadiatingLight"; + + protected override void Startup() + { + base.Startup(); + + var animation = new Animation + { + Length = TimeSpan.FromSeconds(4), + AnimationTracks = + { + new AnimationTrackComponentProperty + { + ComponentType = typeof(PointLightComponent), + InterpolationMode = AnimationInterpolationMode.Linear, + Property = nameof(PointLightComponent.Radius), + KeyFrames = + { + new AnimationTrackProperty.KeyFrame(3.0f, 0), + new AnimationTrackProperty.KeyFrame(2.0f, 1), + new AnimationTrackProperty.KeyFrame(3.0f, 2) + } + } + } + }; + + var playerComponent = Owner.EnsureComponent(); + playerComponent.Play(animation, "emergency"); + + playerComponent.AnimationCompleted += s => playerComponent.Play(animation, s); + } + } +} diff --git a/Content.IntegrationTests/Tests/Atmos/ConstantsTest.cs b/Content.IntegrationTests/Tests/Atmos/ConstantsTest.cs new file mode 100644 index 0000000000..eac4460b8c --- /dev/null +++ b/Content.IntegrationTests/Tests/Atmos/ConstantsTest.cs @@ -0,0 +1,25 @@ +using System; +using System.Linq; +using Content.Shared.Atmos; +using NUnit.Framework; + +namespace Content.IntegrationTests.Tests.Atmos +{ + [TestFixture] + [TestOf(typeof(Atmospherics))] + public class ConstantsTest : ContentIntegrationTest + { + [Test] + public void TotalGasesTest() + { + var server = StartServerDummyTicker(); + + server.Post(() => + { + Assert.That(Atmospherics.Gases.Count(), Is.EqualTo(Atmospherics.TotalNumberOfGases)); + + Assert.That(Enum.GetValues(typeof(Gas)).Length, Is.EqualTo(Atmospherics.TotalNumberOfGases)); + }); + } + } +} diff --git a/Content.Server/Atmos/AtmosCommands.cs b/Content.Server/Atmos/AtmosCommands.cs index c38f586c86..29525acaae 100644 --- a/Content.Server/Atmos/AtmosCommands.cs +++ b/Content.Server/Atmos/AtmosCommands.cs @@ -302,7 +302,7 @@ namespace Content.Server.Atmos var moles = 0f; foreach (var tile in gam) { - if (tile.Air.Immutable) continue; + if (tile.Air == null || tile.Air.Immutable) continue; tiles++; moles += tile.Air.TotalMoles; tile.Air.RemoveRatio(1f); diff --git a/Content.Server/GameObjects/Components/Atmos/GasAnalyzerComponent.cs b/Content.Server/GameObjects/Components/Atmos/GasAnalyzerComponent.cs index 0e5bd87125..777d238060 100644 --- a/Content.Server/GameObjects/Components/Atmos/GasAnalyzerComponent.cs +++ b/Content.Server/GameObjects/Components/Atmos/GasAnalyzerComponent.cs @@ -2,37 +2,39 @@ using Content.Server.GameObjects.EntitySystems; using Content.Server.Interfaces; using Content.Server.Interfaces.GameObjects.Components.Items; +using Content.Server.Utility; using Content.Shared.Atmos; using Content.Shared.GameObjects.Components; using Content.Shared.GameObjects.EntitySystems; -using Content.Shared.Interfaces; using Content.Shared.Interfaces.GameObjects.Components; -using Content.Shared.Utility; using Robust.Server.GameObjects.Components.UserInterface; using Robust.Server.Interfaces.GameObjects; using Robust.Server.Interfaces.Player; using Robust.Shared.GameObjects; using Robust.Shared.GameObjects.Systems; +using Robust.Shared.Interfaces.Map; using Robust.Shared.IoC; using Robust.Shared.Localization; using Robust.Shared.Map; -using Robust.Shared.Utility; -using System; +using Robust.Shared.Maths; using System.Collections.Generic; namespace Content.Server.GameObjects.Components.Atmos { [RegisterComponent] - public class GasAnalyzerComponent : SharedGasAnalyzerComponent, IAfterInteract, IDropped + public class GasAnalyzerComponent : SharedGasAnalyzerComponent, IAfterInteract, IDropped, IUse { #pragma warning disable 649 [Dependency] private IServerNotifyManager _notifyManager = default!; + [Dependency] private IMapManager _mapManager = default!; #pragma warning restore 649 private BoundUserInterface _userInterface = default!; private GasAnalyzerDanger _pressureDanger; private float _timeSinceSync; - private const float TimeBetweenSyncs = 10f; + private const float TimeBetweenSyncs = 2f; + private bool _checkPlayer = false; // Check at the player pos or at some other tile? + private GridCoordinates? _position; // The tile that we scanned public override void Initialize() { @@ -49,9 +51,28 @@ namespace Content.Server.GameObjects.Components.Atmos /// /// Call this from other components to open the gas analyzer UI. + /// Uses the player position. /// + /// The session to open the ui for public void OpenInterface(IPlayerSession session) { + _checkPlayer = true; + _position = null; + _userInterface.Open(session); + UpdateUserInterface(); + Resync(); + } + + /// + /// Call this from other components to open the gas analyzer UI. + /// Uses a given position. + /// + /// The session to open the ui for + /// The position to analyze the gas + public void OpenInterface(IPlayerSession session, GridCoordinates pos) + { + _checkPlayer = false; + _position = pos; _userInterface.Open(session); UpdateUserInterface(); Resync(); @@ -59,6 +80,7 @@ namespace Content.Server.GameObjects.Components.Atmos public void CloseInterface(IPlayerSession session) { + _position = null; _userInterface.Close(session); Resync(); } @@ -69,6 +91,7 @@ namespace Content.Server.GameObjects.Components.Atmos if (_timeSinceSync > TimeBetweenSyncs) { Resync(); + UpdateUserInterface(); } } @@ -103,9 +126,35 @@ namespace Content.Server.GameObjects.Components.Atmos private void UpdateUserInterface() { string? error = null; - var gam = EntitySystem.Get().GetGridAtmosphere(Owner.Transform.GridID); - var tile = gam?.GetTile(Owner.Transform.GridPosition).Air; + // Check if the player is still holding the gas analyzer => if not, don't update + foreach (var session in _userInterface.SubscribedSessions) + { + if (session.AttachedEntity == null) + return; + + if (!session.AttachedEntity.TryGetComponent(out IHandsComponent handsComponent)) + return; + + var activeHandEntity = handsComponent?.GetActiveHand?.Owner; + if (activeHandEntity == null || !activeHandEntity.TryGetComponent(out GasAnalyzerComponent gasAnalyzer)) + { + return; + } + } + + var pos = Owner.Transform.GridPosition; + if (!_checkPlayer && _position.HasValue) + { + // Check if position is out of range => don't update + if (!_position.Value.InRange(_mapManager, pos, SharedInteractionSystem.InteractionRange)) + return; + + pos = _position.Value; + } + + var gam = EntitySystem.Get().GetGridAtmosphere(pos.GridID); + var tile = gam?.GetTile(pos).Air; if (tile == null) { error = "No Atmosphere!"; @@ -172,13 +221,21 @@ namespace Content.Server.GameObjects.Components.Atmos void IAfterInteract.AfterInteract(AfterInteractEventArgs eventArgs) { + if (!eventArgs.CanReach) + { + _notifyManager.PopupMessage(eventArgs.User, eventArgs.User, Loc.GetString("You can't reach there!")); + return; + } + if (eventArgs.User.TryGetComponent(out IActorComponent actor)) { - OpenInterface(actor.playerSession); + OpenInterface(actor.playerSession, eventArgs.ClickLocation); //TODO: show other sprite when ui open? } } + + void IDropped.Dropped(DroppedEventArgs eventArgs) { if (eventArgs.User.TryGetComponent(out IActorComponent actor)) @@ -187,5 +244,16 @@ namespace Content.Server.GameObjects.Components.Atmos //TODO: if other sprite is shown, change again } } + + bool IUse.UseEntity(UseEntityEventArgs eventArgs) + { + if (eventArgs.User.TryGetComponent(out IActorComponent actor)) + { + OpenInterface(actor.playerSession); + //TODO: show other sprite when ui open? + return true; + } + return false; + } } } diff --git a/Content.Server/GameObjects/Components/Atmos/GridAtmosphereComponent.cs b/Content.Server/GameObjects/Components/Atmos/GridAtmosphereComponent.cs index 91bdd4b6cd..ea05c19642 100644 --- a/Content.Server/GameObjects/Components/Atmos/GridAtmosphereComponent.cs +++ b/Content.Server/GameObjects/Components/Atmos/GridAtmosphereComponent.cs @@ -13,7 +13,6 @@ using Robust.Shared.GameObjects.Components.Transform; using Robust.Shared.Interfaces.Map; using Robust.Shared.Interfaces.Timing; using Robust.Shared.IoC; -using Robust.Shared.Log; using Robust.Shared.Map; using Robust.Shared.Maths; using Robust.Shared.Serialization; @@ -191,7 +190,7 @@ namespace Content.Server.GameObjects.Components.Atmos tile.UpdateAdjacent(); tile.UpdateVisuals(); - foreach (var direction in Cardinal()) + foreach (var direction in Cardinal) { var otherIndices = indices.Offset(direction); var otherTile = GetTile(otherIndices); @@ -306,7 +305,7 @@ namespace Content.Server.GameObjects.Components.Atmos public Dictionary GetAdjacentTiles(MapIndices indices) { var sides = new Dictionary(); - foreach (var dir in Cardinal()) + foreach (var dir in Cardinal) { var side = indices.Offset(dir); var tile = GetTile(side); @@ -475,8 +474,8 @@ namespace Content.Server.GameObjects.Components.Atmos return null; } - private static IEnumerable Cardinal() => - new[] + private static readonly Direction[] Cardinal = + new [] { Direction.North, Direction.East, Direction.South, Direction.West }; diff --git a/Content.Server/GameObjects/Components/Chemistry/ChemMasterComponent.cs b/Content.Server/GameObjects/Components/Chemistry/ChemMasterComponent.cs index 2f7caaf156..4f20a0c4e9 100644 --- a/Content.Server/GameObjects/Components/Chemistry/ChemMasterComponent.cs +++ b/Content.Server/GameObjects/Components/Chemistry/ChemMasterComponent.cs @@ -83,6 +83,7 @@ namespace Content.Server.GameObjects.Components.Chemistry _beakerContainer = ContainerManagerComponent.Ensure($"{Name}-reagentContainerContainer", Owner); _powerReceiver = Owner.GetComponent(); + _powerReceiver.OnPowerStateChanged += OnPowerChanged; //BufferSolution = Owner.BufferSolution BufferSolution.Solution = new Solution(); @@ -91,6 +92,11 @@ namespace Content.Server.GameObjects.Components.Chemistry UpdateUserInterface(); } + private void OnPowerChanged(object sender, PowerStateEventArgs e) + { + UpdateUserInterface(); + } + /// /// Handles ui messages from the client. For things such as button presses /// which interact with the world and require server action. @@ -98,10 +104,16 @@ namespace Content.Server.GameObjects.Components.Chemistry /// A user interface message from the client. private void OnUiReceiveMessage(ServerBoundUserInterfaceMessage obj) { - if (!PlayerCanUseChemMaster(obj.Session.AttachedEntity)) + var msg = (UiActionMessage) obj.Message; + var needsPower = msg.action switch + { + UiAction.Eject => false, + _ => true, + }; + + if (!PlayerCanUseChemMaster(obj.Session.AttachedEntity, needsPower)) return; - var msg = (UiActionMessage) obj.Message; switch (msg.action) { case UiAction.Eject: @@ -134,7 +146,7 @@ namespace Content.Server.GameObjects.Components.Chemistry /// /// The player entity. /// Returns true if the entity can use the chem master, and false if it cannot. - private bool PlayerCanUseChemMaster(IEntity playerEntity) + private bool PlayerCanUseChemMaster(IEntity playerEntity, bool needsPower = true) { //Need player entity to check if they are still able to use the chem master if (playerEntity == null) @@ -143,7 +155,7 @@ namespace Content.Server.GameObjects.Components.Chemistry if (!ActionBlockerSystem.CanInteract(playerEntity) || !ActionBlockerSystem.CanUse(playerEntity)) return false; //Check if device is powered - if (!Powered) + if (needsPower && !Powered) return false; return true; @@ -158,12 +170,12 @@ namespace Content.Server.GameObjects.Components.Chemistry var beaker = _beakerContainer.ContainedEntity; if (beaker == null) { - return new ChemMasterBoundUserInterfaceState(false, ReagentUnit.New(0), ReagentUnit.New(0), + return new ChemMasterBoundUserInterfaceState(Powered, false, ReagentUnit.New(0), ReagentUnit.New(0), "", Owner.Name, null, BufferSolution.ReagentList.ToList(), BufferModeTransfer, BufferSolution.CurrentVolume, BufferSolution.MaxVolume); } var solution = beaker.GetComponent(); - return new ChemMasterBoundUserInterfaceState(true, solution.CurrentVolume, solution.MaxVolume, + return new ChemMasterBoundUserInterfaceState(Powered, true, solution.CurrentVolume, solution.MaxVolume, beaker.Name, Owner.Name, solution.ReagentList.ToList(), BufferSolution.ReagentList.ToList(), BufferModeTransfer, BufferSolution.CurrentVolume, BufferSolution.MaxVolume); } @@ -252,9 +264,15 @@ namespace Content.Server.GameObjects.Components.Chemistry { var random = IoCManager.Resolve(); + if (BufferSolution.CurrentVolume == 0) + return; + if (action == UiAction.CreateBottles) { var individualVolume = BufferSolution.CurrentVolume / ReagentUnit.New(bottleAmount); + if (individualVolume < ReagentUnit.New(1)) + return; + var actualVolume = ReagentUnit.Min(individualVolume, ReagentUnit.New(30)); for (int i = 0; i < bottleAmount; i++) { @@ -289,6 +307,9 @@ namespace Content.Server.GameObjects.Components.Chemistry else //Pills { var individualVolume = BufferSolution.CurrentVolume / ReagentUnit.New(pillAmount); + if (individualVolume < ReagentUnit.New(1)) + return; + var actualVolume = ReagentUnit.Min(individualVolume, ReagentUnit.New(50)); for (int i = 0; i < pillAmount; i++) { @@ -341,9 +362,6 @@ namespace Content.Server.GameObjects.Components.Chemistry return; } - if (!Powered) - return; - var activeHandEntity = hands.GetActiveHand?.Owner; if (activeHandEntity == null) { diff --git a/Content.Server/GameObjects/Components/Chemistry/ReagentDispenserComponent.cs b/Content.Server/GameObjects/Components/Chemistry/ReagentDispenserComponent.cs index f9a698e717..a9c384dafb 100644 --- a/Content.Server/GameObjects/Components/Chemistry/ReagentDispenserComponent.cs +++ b/Content.Server/GameObjects/Components/Chemistry/ReagentDispenserComponent.cs @@ -80,6 +80,7 @@ namespace Content.Server.GameObjects.Components.Chemistry _beakerContainer = ContainerManagerComponent.Ensure($"{Name}-reagentContainerContainer", Owner); _powerReceiver = Owner.GetComponent(); + _powerReceiver.OnPowerStateChanged += OnPowerChanged; InitializeFromPrototype(); UpdateUserInterface(); @@ -105,6 +106,11 @@ namespace Content.Server.GameObjects.Components.Chemistry } } + private void OnPowerChanged(object sender, PowerStateEventArgs e) + { + UpdateUserInterface(); + } + /// /// Handles ui messages from the client. For things such as button presses /// which interact with the world and require server action. @@ -112,10 +118,16 @@ namespace Content.Server.GameObjects.Components.Chemistry /// A user interface message from the client. private void OnUiReceiveMessage(ServerBoundUserInterfaceMessage obj) { - if(!PlayerCanUseDispenser(obj.Session.AttachedEntity)) + var msg = (UiButtonPressedMessage) obj.Message; + var needsPower = msg.Button switch + { + UiButton.Eject => false, + _ => true, + }; + + if(!PlayerCanUseDispenser(obj.Session.AttachedEntity, needsPower)) return; - var msg = (UiButtonPressedMessage) obj.Message; switch (msg.Button) { case UiButton.Eject: @@ -161,7 +173,7 @@ namespace Content.Server.GameObjects.Components.Chemistry /// /// The player entity. /// Returns true if the entity can use the dispenser, and false if it cannot. - private bool PlayerCanUseDispenser(IEntity playerEntity) + private bool PlayerCanUseDispenser(IEntity playerEntity, bool needsPower = true) { //Need player entity to check if they are still able to use the dispenser if (playerEntity == null) @@ -170,7 +182,7 @@ namespace Content.Server.GameObjects.Components.Chemistry if (!ActionBlockerSystem.CanInteract(playerEntity) || !ActionBlockerSystem.CanUse(playerEntity)) return false; //Check if device is powered - if (!Powered) + if (needsPower && !Powered) return false; return true; @@ -185,12 +197,12 @@ namespace Content.Server.GameObjects.Components.Chemistry var beaker = _beakerContainer.ContainedEntity; if (beaker == null) { - return new ReagentDispenserBoundUserInterfaceState(false, ReagentUnit.New(0), ReagentUnit.New(0), + return new ReagentDispenserBoundUserInterfaceState(Powered, false, ReagentUnit.New(0), ReagentUnit.New(0), "", Inventory, Owner.Name, null, _dispenseAmount); } var solution = beaker.GetComponent(); - return new ReagentDispenserBoundUserInterfaceState(true, solution.CurrentVolume, solution.MaxVolume, + return new ReagentDispenserBoundUserInterfaceState(Powered, true, solution.CurrentVolume, solution.MaxVolume, beaker.Name, Inventory, Owner.Name, solution.ReagentList.ToList(), _dispenseAmount); } @@ -263,9 +275,6 @@ namespace Content.Server.GameObjects.Components.Chemistry return; } - if (!Powered) - return; - var activeHandEntity = hands.GetActiveHand?.Owner; if (activeHandEntity == null) { diff --git a/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/PathfindingSystem.cs b/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/PathfindingSystem.cs index 6443a5e0b2..385954b9d6 100644 --- a/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/PathfindingSystem.cs +++ b/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/PathfindingSystem.cs @@ -37,9 +37,9 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding public IReadOnlyDictionary> Graph => _graph; private readonly Dictionary> _graph = new Dictionary>(); - + private readonly PathfindingJobQueue _pathfindingQueue = new PathfindingJobQueue(); - + // Queued pathfinding graph updates private readonly Queue _collidableUpdateQueue = new Queue(); private readonly Queue _moveUpdateQueue = new Queue(); @@ -50,11 +50,11 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding private readonly Dictionary _lastKnownPositions = new Dictionary(); public const int TrackedCollisionLayers = (int) - (CollisionGroup.Impassable | + (CollisionGroup.Impassable | CollisionGroup.MobImpassable | - CollisionGroup.SmallImpassable | + CollisionGroup.SmallImpassable | CollisionGroup.VaultImpassable); - + /// /// Ask for the pathfinder to gimme somethin /// @@ -83,7 +83,7 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding private void ProcessGraphUpdates() { var totalUpdates = 0; - + foreach (var update in _collidableUpdateQueue) { var entity = _entitymanager.GetEntity(update.Owner); @@ -98,7 +98,7 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding totalUpdates++; } - + _collidableUpdateQueue.Clear(); foreach (var update in _accessReaderUpdateQueue) @@ -115,7 +115,7 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding totalUpdates++; } - + _accessReaderUpdateQueue.Clear(); foreach (var tile in _tileUpdateQueue) @@ -123,10 +123,10 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding HandleTileUpdate(tile); totalUpdates++; } - + _tileUpdateQueue.Clear(); var moveUpdateCount = Math.Max(50 - totalUpdates, 0); - + // Other updates are high priority so for this we'll just defer it if there's a spike (explosion, etc.) // If the move updates grow too large then we'll just do it if (_moveUpdateQueue.Count > 100) @@ -135,12 +135,12 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding } moveUpdateCount = Math.Min(moveUpdateCount, _moveUpdateQueue.Count); - + for (var i = 0; i < moveUpdateCount; i++) { HandleCollidableMove(_moveUpdateQueue.Dequeue()); } - + DebugTools.Assert(_moveUpdateQueue.Count < 1000); } @@ -171,10 +171,10 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding { _graph.Add(gridId, new Dictionary()); } - + _graph[gridId].Add(indices, newChunk); newChunk.Initialize(_mapManager.GetGrid(gridId)); - + return newChunk; } @@ -204,6 +204,9 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding public override void Initialize() { + // TODO: Remove this once the memory leaks are solved. + return; + SubscribeLocalEvent(QueueCollisionChangeMessage); SubscribeLocalEvent(QueueMoveEvent); SubscribeLocalEvent(QueueAccessChangeMessage); @@ -221,12 +224,12 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding UnsubscribeLocalEvent(); UnsubscribeLocalEvent(); UnsubscribeLocalEvent(); - + _mapManager.OnGridRemoved -= HandleGridRemoval; _mapManager.GridChanged -= QueueGridChange; _mapManager.TileChanged -= QueueTileChange; } - + private void HandleTileUpdate(TileRef tile) { var node = GetNode(tile); @@ -280,7 +283,7 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding { return; } - + var grid = _mapManager.GetGrid(entity.Transform.GridID); var tileRef = grid.GetTileRef(entity.Transform.GridPosition); @@ -313,7 +316,7 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding private void HandleCollidableMove(MoveEvent moveEvent) { var entityUid = moveEvent.Sender.Uid; - + if (!_lastKnownPositions.TryGetValue(entityUid, out var oldNode)) { return; @@ -326,7 +329,7 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding HandleEntityRemove(moveEvent.Sender); return; } - + var newTile = _mapManager.GetGrid(moveEvent.NewPosition.GridID).GetTileRef(moveEvent.NewPosition); if (oldNode == null || oldNode.TileRef == newTile) @@ -365,7 +368,7 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding } var access = AccessReader.FindAccessTags(entity); - + foreach (var reader in node.AccessReaders) { if (!reader.IsAllowed(access)) diff --git a/Content.Server/IgnoredComponents.cs b/Content.Server/IgnoredComponents.cs index f40975a84c..4aa536c30d 100644 --- a/Content.Server/IgnoredComponents.cs +++ b/Content.Server/IgnoredComponents.cs @@ -20,6 +20,7 @@ "EmergencyLight", "Clickable", "CanSeeGases", + "RadiatingLight", }; } diff --git a/Content.Shared/Atmos/Atmospherics.cs b/Content.Shared/Atmos/Atmospherics.cs index 9e8252c585..4659ab2441 100644 --- a/Content.Shared/Atmos/Atmospherics.cs +++ b/Content.Shared/Atmos/Atmospherics.cs @@ -59,7 +59,7 @@ namespace Content.Shared.Atmos public const float CellVolume = 2500f; /// - /// Moles in a 2.5 m^3 cell at 101.325 Pa and 20ºC + /// Moles in a 2.5 m^3 cell at 101.325 kPa and 20ºC /// public const float MolesCellStandard = (OneAtmosphere * CellVolume / (T20C * R)); diff --git a/Content.Shared/GameObjects/Components/Chemistry/ChemMaster/SharedChemMasterComponent.cs b/Content.Shared/GameObjects/Components/Chemistry/ChemMaster/SharedChemMasterComponent.cs index 793e842886..8a4f630fb0 100644 --- a/Content.Shared/GameObjects/Components/Chemistry/ChemMaster/SharedChemMasterComponent.cs +++ b/Content.Shared/GameObjects/Components/Chemistry/ChemMaster/SharedChemMasterComponent.cs @@ -1,4 +1,4 @@ -#nullable enable +#nullable enable using System; using System.Collections.Generic; using Content.Shared.Chemistry; @@ -19,6 +19,7 @@ namespace Content.Shared.GameObjects.Components.Chemistry [Serializable, NetSerializable] public class ChemMasterBoundUserInterfaceState : BoundUserInterfaceState { + public readonly bool HasPower; public readonly bool HasBeaker; public readonly ReagentUnit BeakerCurrentVolume; public readonly ReagentUnit BeakerMaxVolume; @@ -39,9 +40,10 @@ namespace Content.Shared.GameObjects.Components.Chemistry public readonly ReagentUnit BufferCurrentVolume; public readonly ReagentUnit BufferMaxVolume; - public ChemMasterBoundUserInterfaceState(bool hasBeaker, ReagentUnit beakerCurrentVolume, ReagentUnit beakerMaxVolume, string containerName, + public ChemMasterBoundUserInterfaceState(bool hasPower, bool hasBeaker, ReagentUnit beakerCurrentVolume, ReagentUnit beakerMaxVolume, string containerName, string dispenserName, List containerReagents, List bufferReagents, bool bufferModeTransfer, ReagentUnit bufferCurrentVolume, ReagentUnit bufferMaxVolume) { + HasPower = hasPower; HasBeaker = hasBeaker; BeakerCurrentVolume = beakerCurrentVolume; BeakerMaxVolume = beakerMaxVolume; diff --git a/Content.Shared/GameObjects/Components/Chemistry/ReagentDispenser/SharedReagentDispenserComponent.cs b/Content.Shared/GameObjects/Components/Chemistry/ReagentDispenser/SharedReagentDispenserComponent.cs index d9ff0581dd..b2d094a5d0 100644 --- a/Content.Shared/GameObjects/Components/Chemistry/ReagentDispenser/SharedReagentDispenserComponent.cs +++ b/Content.Shared/GameObjects/Components/Chemistry/ReagentDispenser/SharedReagentDispenserComponent.cs @@ -25,6 +25,7 @@ namespace Content.Shared.GameObjects.Components.Chemistry [Serializable, NetSerializable] public class ReagentDispenserBoundUserInterfaceState : BoundUserInterfaceState { + public readonly bool HasPower; public readonly bool HasBeaker; public readonly ReagentUnit BeakerCurrentVolume; public readonly ReagentUnit BeakerMaxVolume; @@ -40,9 +41,10 @@ namespace Content.Shared.GameObjects.Components.Chemistry public readonly string DispenserName; public readonly ReagentUnit SelectedDispenseAmount; - public ReagentDispenserBoundUserInterfaceState(bool hasBeaker, ReagentUnit beakerCurrentVolume, ReagentUnit beakerMaxVolume, string containerName, + public ReagentDispenserBoundUserInterfaceState(bool hasPower, bool hasBeaker, ReagentUnit beakerCurrentVolume, ReagentUnit beakerMaxVolume, string containerName, List inventory, string dispenserName, List containerReagents, ReagentUnit selectedDispenseAmount) { + HasPower = hasPower; HasBeaker = hasBeaker; BeakerCurrentVolume = beakerCurrentVolume; BeakerMaxVolume = beakerMaxVolume; diff --git a/Resources/Prototypes/Entities/Objects/Tools/lantern.yml b/Resources/Prototypes/Entities/Objects/Tools/lantern.yml new file mode 100644 index 0000000000..e1346cac53 --- /dev/null +++ b/Resources/Prototypes/Entities/Objects/Tools/lantern.yml @@ -0,0 +1,27 @@ +- type: entity + name: lantern + parent: BaseItem + id: lantern + description: The holy light guides the way + components: + - type: HandheldLight + - type: Sprite + sprite: Objects/Tools/lantern.rsi + layers: + - state: lantern + - state: lantern-on + shader: unshaded + visible: false + - type: Icon + sprite: Objects/Tools/lantern.rsi + state: lantern + - type: Item + sprite: Objects/Tools/lantern.rsi + HeldPrefix: off + - type: PointLight + enabled: false + radius: 3 + energy: 2.5 + color: "#FFC458" + - type: RadiatingLight + - type: LoopingSound diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Explosives/grenades.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Explosives/grenades.yml index 8eb1973058..3e945ab5aa 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Explosives/grenades.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Explosives/grenades.yml @@ -86,3 +86,33 @@ visuals: - type: TimerTriggerVisualizer countdown_sound: /Audio/Effects/countdown.ogg + +- type: entity + name: the nuclear option + description: Please don't throw it, think of the children. + parent: BaseItem + id: NuclearGrenade + components: + - type: Sprite + sprite: Objects/Weapons/Grenades/nukenade.rsi + layers: + - state: icon + map: ["enum.TriggerVisualLayers.Base"] + - type: Icon + sprite: Objects/Weapons/Grenades/nukenade.rsi + state: icon + - type: Item + size: 5 + - type: OnUseTimerTrigger + delay: 5 + - type: Explosive + devastationRange: 25 + heavyImpactRange: 25 + flashRange: 50 + - type: Damageable + - type: Destructible + thresholdvalue: 50 + - type: Appearance + visuals: + - type: TimerTriggerVisualizer + countdown_sound: /Audio/Effects/countdown.ogg diff --git a/Resources/Textures/Objects/Tools/lantern.rsi/lantern-on.png b/Resources/Textures/Objects/Tools/lantern.rsi/lantern-on.png new file mode 100644 index 0000000000..7573695619 Binary files /dev/null and b/Resources/Textures/Objects/Tools/lantern.rsi/lantern-on.png differ diff --git a/Resources/Textures/Objects/Tools/lantern.rsi/lantern.png b/Resources/Textures/Objects/Tools/lantern.rsi/lantern.png new file mode 100644 index 0000000000..d9f5bd0bbb Binary files /dev/null and b/Resources/Textures/Objects/Tools/lantern.rsi/lantern.png differ diff --git a/Resources/Textures/Objects/Tools/lantern.rsi/meta.json b/Resources/Textures/Objects/Tools/lantern.rsi/meta.json new file mode 100644 index 0000000000..2205be15d5 --- /dev/null +++ b/Resources/Textures/Objects/Tools/lantern.rsi/meta.json @@ -0,0 +1,101 @@ +{ + "version": 1, + "license": "CC BY-SA 3.0", + "copyright": "Taken from https://github.com/tgstation/tgstation at commit 9bebd81ae0b0a7f952b59886a765c681205de31f", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "lantern", + "directions": 1, + "delays": [ + [ + 1.0 + ] + ] + }, + { + "name": "lantern-on", + "directions": 1, + "delays": [ + [ + 1.0 + ] + ] + }, + { + "name": "off-inhand-left", + "directions": 4, + "delays": [ + [ + 1 + ], + [ + 1 + ], + [ + 1 + ], + [ + 1 + ] + ] + }, + { + "name": "off-inhand-right", + "directions": 4, + "delays": [ + [ + 1 + ], + [ + 1 + ], + [ + 1 + ], + [ + 1 + ] + ] + }, + { + "name": "on-inhand-left", + "directions": 4, + "delays": [ + [ + 1 + ], + [ + 1 + ], + [ + 1 + ], + [ + 1 + ] + ] + }, + { + "name": "on-inhand-right", + "directions": 4, + "delays": [ + [ + 1 + ], + [ + 1 + ], + [ + 1 + ], + [ + 1 + ] + ] + } + ] +} diff --git a/Resources/Textures/Objects/Tools/lantern.rsi/off-inhand-left.png b/Resources/Textures/Objects/Tools/lantern.rsi/off-inhand-left.png new file mode 100644 index 0000000000..d38b5e8c64 Binary files /dev/null and b/Resources/Textures/Objects/Tools/lantern.rsi/off-inhand-left.png differ diff --git a/Resources/Textures/Objects/Tools/lantern.rsi/off-inhand-right.png b/Resources/Textures/Objects/Tools/lantern.rsi/off-inhand-right.png new file mode 100644 index 0000000000..de8ce0ad50 Binary files /dev/null and b/Resources/Textures/Objects/Tools/lantern.rsi/off-inhand-right.png differ diff --git a/Resources/Textures/Objects/Tools/lantern.rsi/on-inhand-left.png b/Resources/Textures/Objects/Tools/lantern.rsi/on-inhand-left.png new file mode 100644 index 0000000000..d38b5e8c64 Binary files /dev/null and b/Resources/Textures/Objects/Tools/lantern.rsi/on-inhand-left.png differ diff --git a/Resources/Textures/Objects/Tools/lantern.rsi/on-inhand-right.png b/Resources/Textures/Objects/Tools/lantern.rsi/on-inhand-right.png new file mode 100644 index 0000000000..de8ce0ad50 Binary files /dev/null and b/Resources/Textures/Objects/Tools/lantern.rsi/on-inhand-right.png differ diff --git a/Resources/Textures/Objects/Weapons/Grenades/nukenade.rsi/icon.png b/Resources/Textures/Objects/Weapons/Grenades/nukenade.rsi/icon.png new file mode 100644 index 0000000000..d6e9ebe4fb Binary files /dev/null and b/Resources/Textures/Objects/Weapons/Grenades/nukenade.rsi/icon.png differ diff --git a/Resources/Textures/Objects/Weapons/Grenades/nukenade.rsi/meta.json b/Resources/Textures/Objects/Weapons/Grenades/nukenade.rsi/meta.json new file mode 100644 index 0000000000..198dbe1347 --- /dev/null +++ b/Resources/Textures/Objects/Weapons/Grenades/nukenade.rsi/meta.json @@ -0,0 +1,25 @@ +{ + "version": 1, + "size": { + "x": 32, + "y": 32 + }, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from https://github.com/vgstation-coders/vgstation13/icons/obj/grenade.dmi at commit 8c96d52deed1eeea28a16334eea549369d7f9974", + "states": [ + { + "name": "icon", + "directions": 1, + "delays": [ + [1.0] + ] + }, + { + "name": "primed", + "directions": 1, + "delays": [ + [0.2, 0.2] + ] + } + ] +} diff --git a/Resources/Textures/Objects/Weapons/Grenades/nukenade.rsi/primed.png b/Resources/Textures/Objects/Weapons/Grenades/nukenade.rsi/primed.png new file mode 100644 index 0000000000..6938870e05 Binary files /dev/null and b/Resources/Textures/Objects/Weapons/Grenades/nukenade.rsi/primed.png differ diff --git a/RobustToolbox b/RobustToolbox index 6c3c22affe..64a3916c04 160000 --- a/RobustToolbox +++ b/RobustToolbox @@ -1 +1 @@ -Subproject commit 6c3c22affec7dfadf8c1216ec9398256ceb34a2a +Subproject commit 64a3916c04daecf44b4617f2e8755900326957f0 diff --git a/SpaceStation14.sln b/SpaceStation14.sln index 13082efa99..99f3ac6702 100644 --- a/SpaceStation14.sln +++ b/SpaceStation14.sln @@ -69,9 +69,11 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{DDD55F86 RobustToolbox\Tools\download_natives.py = RobustToolbox\Tools\download_natives.py EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lidgren.Network.UnitTests", "RobustToolbox\Lidgren.Network.UnitTests\Lidgren.Network.UnitTests.csproj", "{682E3140-4F27-4ECB-8029-D436319DDC48}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Lidgren.Network.UnitTests", "RobustToolbox\Lidgren.Network.UnitTests\Lidgren.Network.UnitTests.csproj", "{682E3140-4F27-4ECB-8029-D436319DDC48}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetSerializer", "RobustToolbox\NetSerializer\NetSerializer\NetSerializer.csproj", "{7B9472D3-79D4-48D1-9B22-BCDE518FE842}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetSerializer", "RobustToolbox\NetSerializer\NetSerializer\NetSerializer.csproj", "{7B9472D3-79D4-48D1-9B22-BCDE518FE842}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Robust.Physics", "RobustToolbox\Robust.Physics\Robust.Physics.csproj", "{3BC34700-882F-426B-82BB-56D5708B5E0D}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -79,68 +81,68 @@ Global Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {C899FCA4-7037-4E49-ABC2-44DE72487110}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C899FCA4-7037-4E49-ABC2-44DE72487110}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7AC832A1-2461-4EB5-AC26-26F6AFFA9E46}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7AC832A1-2461-4EB5-AC26-26F6AFFA9E46}.Release|Any CPU.Build.0 = Release|Any CPU - {7AC832A1-2461-4EB5-AC26-26F6AFFA9E46}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7AC832A1-2461-4EB5-AC26-26F6AFFA9E46}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A2E5F175-78AF-4DDD-8F97-E2D2552372ED}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A2E5F175-78AF-4DDD-8F97-E2D2552372ED}.Release|Any CPU.Build.0 = Release|Any CPU - {A2E5F175-78AF-4DDD-8F97-E2D2552372ED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A2E5F175-78AF-4DDD-8F97-E2D2552372ED}.Debug|Any CPU.Build.0 = Debug|Any CPU - {AB7AF1C8-30FF-4436-9DF0-179BE5B0C132}.Release|Any CPU.ActiveCfg = Release|Any CPU - {AB7AF1C8-30FF-4436-9DF0-179BE5B0C132}.Release|Any CPU.Build.0 = Release|Any CPU - {AB7AF1C8-30FF-4436-9DF0-179BE5B0C132}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {AB7AF1C8-30FF-4436-9DF0-179BE5B0C132}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B38DBBD0-04C2-4D1A-84E2-B3446F6ADF2A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B38DBBD0-04C2-4D1A-84E2-B3446F6ADF2A}.Release|Any CPU.Build.0 = Release|Any CPU - {B38DBBD0-04C2-4D1A-84E2-B3446F6ADF2A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B38DBBD0-04C2-4D1A-84E2-B3446F6ADF2A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {45C9B43F-305D-4651-9863-F6384CBC847F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {45C9B43F-305D-4651-9863-F6384CBC847F}.Release|Any CPU.Build.0 = Release|Any CPU - {45C9B43F-305D-4651-9863-F6384CBC847F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {45C9B43F-305D-4651-9863-F6384CBC847F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {26AEEBB3-DDE7-443A-9F43-7BC7F4ACF6B5}.Release|Any CPU.ActiveCfg = Release|Any CPU - {26AEEBB3-DDE7-443A-9F43-7BC7F4ACF6B5}.Release|Any CPU.Build.0 = Release|Any CPU {26AEEBB3-DDE7-443A-9F43-7BC7F4ACF6B5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {26AEEBB3-DDE7-443A-9F43-7BC7F4ACF6B5}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8EDF4429-251A-416D-BB68-93F227191BCF}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8EDF4429-251A-416D-BB68-93F227191BCF}.Release|Any CPU.Build.0 = Release|Any CPU + {26AEEBB3-DDE7-443A-9F43-7BC7F4ACF6B5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {26AEEBB3-DDE7-443A-9F43-7BC7F4ACF6B5}.Release|Any CPU.Build.0 = Release|Any CPU + {B38DBBD0-04C2-4D1A-84E2-B3446F6ADF2A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B38DBBD0-04C2-4D1A-84E2-B3446F6ADF2A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B38DBBD0-04C2-4D1A-84E2-B3446F6ADF2A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B38DBBD0-04C2-4D1A-84E2-B3446F6ADF2A}.Release|Any CPU.Build.0 = Release|Any CPU + {A2E5F175-78AF-4DDD-8F97-E2D2552372ED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A2E5F175-78AF-4DDD-8F97-E2D2552372ED}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A2E5F175-78AF-4DDD-8F97-E2D2552372ED}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A2E5F175-78AF-4DDD-8F97-E2D2552372ED}.Release|Any CPU.Build.0 = Release|Any CPU + {C899FCA4-7037-4E49-ABC2-44DE72487110}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C899FCA4-7037-4E49-ABC2-44DE72487110}.Release|Any CPU.ActiveCfg = Release|Any CPU {8EDF4429-251A-416D-BB68-93F227191BCF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8EDF4429-251A-416D-BB68-93F227191BCF}.Debug|Any CPU.Build.0 = Debug|Any CPU - {59250BAF-0000-0000-0000-000000000000}.Release|Any CPU.ActiveCfg = Release|Any CPU - {59250BAF-0000-0000-0000-000000000000}.Release|Any CPU.Build.0 = Release|Any CPU + {8EDF4429-251A-416D-BB68-93F227191BCF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8EDF4429-251A-416D-BB68-93F227191BCF}.Release|Any CPU.Build.0 = Release|Any CPU {59250BAF-0000-0000-0000-000000000000}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {59250BAF-0000-0000-0000-000000000000}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4809F412-3132-419E-BF9D-CCF7593C3533}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4809F412-3132-419E-BF9D-CCF7593C3533}.Release|Any CPU.Build.0 = Release|Any CPU - {4809F412-3132-419E-BF9D-CCF7593C3533}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4809F412-3132-419E-BF9D-CCF7593C3533}.Debug|Any CPU.Build.0 = Debug|Any CPU - {83429BD6-6358-4B18-BE51-401DF8EA2673}.Release|Any CPU.ActiveCfg = Release|Any CPU - {83429BD6-6358-4B18-BE51-401DF8EA2673}.Release|Any CPU.Build.0 = Release|Any CPU + {59250BAF-0000-0000-0000-000000000000}.Release|Any CPU.ActiveCfg = Release|Any CPU + {59250BAF-0000-0000-0000-000000000000}.Release|Any CPU.Build.0 = Release|Any CPU {83429BD6-6358-4B18-BE51-401DF8EA2673}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {83429BD6-6358-4B18-BE51-401DF8EA2673}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B04AAE71-0000-0000-0000-000000000000}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B04AAE71-0000-0000-0000-000000000000}.Release|Any CPU.Build.0 = Release|Any CPU + {83429BD6-6358-4B18-BE51-401DF8EA2673}.Release|Any CPU.ActiveCfg = Release|Any CPU + {83429BD6-6358-4B18-BE51-401DF8EA2673}.Release|Any CPU.Build.0 = Release|Any CPU {B04AAE71-0000-0000-0000-000000000000}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B04AAE71-0000-0000-0000-000000000000}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0529F740-0000-0000-0000-000000000000}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0529F740-0000-0000-0000-000000000000}.Release|Any CPU.Build.0 = Release|Any CPU - {0529F740-0000-0000-0000-000000000000}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0529F740-0000-0000-0000-000000000000}.Debug|Any CPU.Build.0 = Debug|Any CPU - {93F23A82-00C5-4572-964E-E7C9457726D4}.Release|Any CPU.ActiveCfg = Release|Any CPU - {93F23A82-00C5-4572-964E-E7C9457726D4}.Release|Any CPU.Build.0 = Release|Any CPU + {B04AAE71-0000-0000-0000-000000000000}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B04AAE71-0000-0000-0000-000000000000}.Release|Any CPU.Build.0 = Release|Any CPU {93F23A82-00C5-4572-964E-E7C9457726D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {93F23A82-00C5-4572-964E-E7C9457726D4}.Debug|Any CPU.Build.0 = Debug|Any CPU - {41B450C0-A361-4CD7-8121-7072B8995CFC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {41B450C0-A361-4CD7-8121-7072B8995CFC}.Release|Any CPU.Build.0 = Release|Any CPU - {41B450C0-A361-4CD7-8121-7072B8995CFC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {41B450C0-A361-4CD7-8121-7072B8995CFC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F0ADA779-40B8-4F7E-BA6C-CDB19F3065D9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F0ADA779-40B8-4F7E-BA6C-CDB19F3065D9}.Release|Any CPU.Build.0 = Release|Any CPU + {93F23A82-00C5-4572-964E-E7C9457726D4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {93F23A82-00C5-4572-964E-E7C9457726D4}.Release|Any CPU.Build.0 = Release|Any CPU {F0ADA779-40B8-4F7E-BA6C-CDB19F3065D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F0ADA779-40B8-4F7E-BA6C-CDB19F3065D9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F0ADA779-40B8-4F7E-BA6C-CDB19F3065D9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F0ADA779-40B8-4F7E-BA6C-CDB19F3065D9}.Release|Any CPU.Build.0 = Release|Any CPU + {0529F740-0000-0000-0000-000000000000}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0529F740-0000-0000-0000-000000000000}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0529F740-0000-0000-0000-000000000000}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0529F740-0000-0000-0000-000000000000}.Release|Any CPU.Build.0 = Release|Any CPU + {AB7AF1C8-30FF-4436-9DF0-179BE5B0C132}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AB7AF1C8-30FF-4436-9DF0-179BE5B0C132}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AB7AF1C8-30FF-4436-9DF0-179BE5B0C132}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AB7AF1C8-30FF-4436-9DF0-179BE5B0C132}.Release|Any CPU.Build.0 = Release|Any CPU + {7AC832A1-2461-4EB5-AC26-26F6AFFA9E46}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7AC832A1-2461-4EB5-AC26-26F6AFFA9E46}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7AC832A1-2461-4EB5-AC26-26F6AFFA9E46}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7AC832A1-2461-4EB5-AC26-26F6AFFA9E46}.Release|Any CPU.Build.0 = Release|Any CPU + {4809F412-3132-419E-BF9D-CCF7593C3533}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4809F412-3132-419E-BF9D-CCF7593C3533}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4809F412-3132-419E-BF9D-CCF7593C3533}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4809F412-3132-419E-BF9D-CCF7593C3533}.Release|Any CPU.Build.0 = Release|Any CPU + {45C9B43F-305D-4651-9863-F6384CBC847F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {45C9B43F-305D-4651-9863-F6384CBC847F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {45C9B43F-305D-4651-9863-F6384CBC847F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {45C9B43F-305D-4651-9863-F6384CBC847F}.Release|Any CPU.Build.0 = Release|Any CPU + {41B450C0-A361-4CD7-8121-7072B8995CFC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {41B450C0-A361-4CD7-8121-7072B8995CFC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {41B450C0-A361-4CD7-8121-7072B8995CFC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {41B450C0-A361-4CD7-8121-7072B8995CFC}.Release|Any CPU.Build.0 = Release|Any CPU {682E3140-4F27-4ECB-8029-D436319DDC48}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {682E3140-4F27-4ECB-8029-D436319DDC48}.Debug|Any CPU.Build.0 = Debug|Any CPU {682E3140-4F27-4ECB-8029-D436319DDC48}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -149,6 +151,10 @@ Global {7B9472D3-79D4-48D1-9B22-BCDE518FE842}.Debug|Any CPU.Build.0 = Debug|Any CPU {7B9472D3-79D4-48D1-9B22-BCDE518FE842}.Release|Any CPU.ActiveCfg = Release|Any CPU {7B9472D3-79D4-48D1-9B22-BCDE518FE842}.Release|Any CPU.Build.0 = Release|Any CPU + {3BC34700-882F-426B-82BB-56D5708B5E0D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3BC34700-882F-426B-82BB-56D5708B5E0D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3BC34700-882F-426B-82BB-56D5708B5E0D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3BC34700-882F-426B-82BB-56D5708B5E0D}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -167,6 +173,7 @@ Global {DDD55F86-0406-42E5-8443-93EDC6BB2D75} = {83B4CBBA-547A-42F0-A7CD-8A67D93196CE} {682E3140-4F27-4ECB-8029-D436319DDC48} = {83B4CBBA-547A-42F0-A7CD-8A67D93196CE} {7B9472D3-79D4-48D1-9B22-BCDE518FE842} = {83B4CBBA-547A-42F0-A7CD-8A67D93196CE} + {3BC34700-882F-426B-82BB-56D5708B5E0D} = {83B4CBBA-547A-42F0-A7CD-8A67D93196CE} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {AA37ED9F-F8D6-468E-A101-658AD605B09A}