From 66367309f0971784ee98a1943fc004710805d02d Mon Sep 17 00:00:00 2001 From: ShadowCommander <10494922+ShadowCommander@users.noreply.github.com> Date: Sun, 16 Aug 2020 05:23:34 -0700 Subject: [PATCH 01/21] Add args.Handled for in simulation hotkeys (#1657) --- Content.Client/State/GameScreenBase.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Content.Client/State/GameScreenBase.cs b/Content.Client/State/GameScreenBase.cs index 1372dacce5..64e62d2b16 100644 --- a/Content.Client/State/GameScreenBase.cs +++ b/Content.Client/State/GameScreenBase.cs @@ -226,7 +226,10 @@ namespace Content.Client.State // client side command handlers will always be sent the local player session. var session = PlayerManager.LocalPlayer.Session; - inputSys.HandleInputCommand(session, func, message); + if (inputSys.HandleInputCommand(session, func, message)) + { + args.Handle(); + } } } } From f61d55a63de40c3460e49177a687fee6a9f070f6 Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Sun, 16 Aug 2020 14:20:16 +0200 Subject: [PATCH 02/21] Disable airlock "walk by" fix. It makes it hard to walk through double doors so I'd rather have this be disabled. --- .../Components/Doors/ServerDoorComponent.cs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/Content.Server/GameObjects/Components/Doors/ServerDoorComponent.cs b/Content.Server/GameObjects/Components/Doors/ServerDoorComponent.cs index bcd49e5c89..7f4228b272 100644 --- a/Content.Server/GameObjects/Components/Doors/ServerDoorComponent.cs +++ b/Content.Server/GameObjects/Components/Doors/ServerDoorComponent.cs @@ -58,8 +58,7 @@ namespace Content.Server.GameObjects.Components.Doors private const float DoorStunTime = 5f; protected bool Safety = true; - [ViewVariables] - private bool _occludes; + [ViewVariables] private bool _occludes; public override void ExposeData(ObjectSerializer serializer) { @@ -111,18 +110,25 @@ namespace Content.Server.GameObjects.Components.Doors { return; } + + // Disabled because it makes it suck hard to walk through double doors. + if (entity.HasComponent(typeof(SpeciesComponent))) { if (!entity.TryGetComponent(out var mover)) return; + /* // TODO: temporary hack to fix the physics system raising collision events akwardly. // E.g. when moving parallel to a door by going off the side of a wall. var (walking, sprinting) = mover.VelocityDir; // Also TODO: walking and sprint dir are added together here // instead of calculating their contribution correctly. var dotProduct = Vector2.Dot((sprinting + walking).Normalized, (entity.Transform.WorldPosition - Owner.Transform.WorldPosition).Normalized); - if (dotProduct <= -0.9f) + if (dotProduct <= -0.85f) TryOpen(entity); + */ + + TryOpen(entity); } } @@ -144,6 +150,7 @@ namespace Content.Server.GameObjects.Components.Doors { return true; } + return accessReader.IsAllowed(user); } @@ -204,6 +211,7 @@ namespace Content.Server.GameObjects.Components.Doors { return true; } + return accessReader.IsAllowed(user); } @@ -214,6 +222,7 @@ namespace Content.Server.GameObjects.Components.Doors Deny(); return; } + Close(); } @@ -242,6 +251,7 @@ namespace Content.Server.GameObjects.Components.Doors stun.Paralyze(DoorStunTime); hitSomeone = true; } + // If we hit someone, open up after stun (opens right when stun ends) if (hitSomeone) { From 3e87e24028de1aa6db978e073c0c85dfacd8b118 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Aguilera=20Puerto?= Date: Sun, 16 Aug 2020 16:24:27 +0200 Subject: [PATCH 03/21] Optimizes atmos further by using rented arrays where applicable --- Content.Server/Atmos/TileAtmosphere.cs | 92 ++++++++++++++++---------- SpaceStation14.sln.DotSettings | 1 + 2 files changed, 57 insertions(+), 36 deletions(-) diff --git a/Content.Server/Atmos/TileAtmosphere.cs b/Content.Server/Atmos/TileAtmosphere.cs index 8e634a1c7d..cddfc3ee96 100644 --- a/Content.Server/Atmos/TileAtmosphere.cs +++ b/Content.Server/Atmos/TileAtmosphere.cs @@ -332,32 +332,40 @@ namespace Content.Server.Atmos var tile = tiles[i]; tile._tileAtmosInfo.FastDone = true; if (!(tile._tileAtmosInfo.MoleDelta > 0)) continue; - var eligibleDirections = new List(); - var amtEligibleAdj = 0; + var eligibleDirections = ArrayPool.Shared.Rent(4); + var eligibleDirectionCount = 0; foreach (var direction in Cardinal) { if (!tile._adjacentTiles.TryGetValue(direction, out var tile2)) continue; - // skip anything that isn't part of our current processing block. Original one didn't do this unfortunately, which probably cause some massive lag. + // skip anything that isn't part of our current processing block. if (tile2._tileAtmosInfo.FastDone || tile2._tileAtmosInfo.LastQueueCycle != queueCycle) continue; - eligibleDirections.Add(direction); - amtEligibleAdj++; + eligibleDirections[eligibleDirectionCount++] = direction; } - if (amtEligibleAdj <= 0) + if (eligibleDirectionCount <= 0) continue; // Oof we've painted ourselves into a corner. Bad luck. Next part will handle this. - var molesToMove = tile._tileAtmosInfo.MoleDelta / amtEligibleAdj; + var molesToMove = tile._tileAtmosInfo.MoleDelta / eligibleDirectionCount; foreach (var direction in Cardinal) { - if (eligibleDirections.Contains(direction) || - !tile._adjacentTiles.TryGetValue(direction, out var tile2)) continue; + var hasDirection = false; + for (var j = 0; j < eligibleDirectionCount; j++) + { + if (eligibleDirections[j] != direction) continue; + hasDirection = true; + break; + } + + if (hasDirection || !tile._adjacentTiles.TryGetValue(direction, out var tile2)) continue; tile.AdjustEqMovement(direction, molesToMove); tile._tileAtmosInfo.MoleDelta -= molesToMove; tile2._tileAtmosInfo.MoleDelta += molesToMove; } + + ArrayPool.Shared.Return(eligibleDirections); } giverTilesLength = 0; @@ -446,7 +454,7 @@ namespace Content.Server.Atmos } } - ArrayPool.Shared.Return(queue, true); + ArrayPool.Shared.Return(queue); } else { @@ -516,7 +524,7 @@ namespace Content.Server.Atmos } } - ArrayPool.Shared.Return(queue, true); + ArrayPool.Shared.Return(queue); } for (var i = 0; i < tileCount; i++) @@ -537,9 +545,9 @@ namespace Content.Server.Atmos } } - ArrayPool.Shared.Return(tiles, true); - ArrayPool.Shared.Return(giverTiles, true); - ArrayPool.Shared.Return(takerTiles, true); + ArrayPool.Shared.Return(tiles); + ArrayPool.Shared.Return(giverTiles); + ArrayPool.Shared.Return(takerTiles); } } @@ -925,16 +933,22 @@ namespace Content.Server.Atmos public void ExplosivelyDepressurize(int cycleNum) { if (Air == null) return; + + const int limit = Atmospherics.ZumosTileLimit; + var totalGasesRemoved = 0f; var queueCycle = ++_gridAtmosphereComponent.EqualizationQueueCycleControl; - var tiles = new List(); - var spaceTiles = new List(); - tiles.Add(this); + var tiles = ArrayPool.Shared.Rent(limit); + var spaceTiles = ArrayPool.Shared.Rent(limit); + + var tileCount = 0; + var spaceTileCount = 0; + + tiles[tileCount++] = this; ResetTileAtmosInfo(); _tileAtmosInfo.LastQueueCycle = queueCycle; - var tileCount = 1; for (var i = 0; i < tileCount; i++) { var tile = tiles[i]; @@ -942,40 +956,44 @@ namespace Content.Server.Atmos tile._tileAtmosInfo.CurrentTransferDirection = Direction.Invalid; if (tile.Air.Immutable) { - spaceTiles.Add(tile); + spaceTiles[spaceTileCount++] = tile; tile.PressureSpecificTarget = tile; } else { - if (i > Atmospherics.ZumosTileLimit) continue; foreach (var direction in Cardinal) { if (!tile._adjacentTiles.TryGetValue(direction, out var tile2)) continue; - if (tile2?.Air == null) continue; + if (tile2.Air == null) continue; if (tile2._tileAtmosInfo.LastQueueCycle == queueCycle) continue; + tile.ConsiderFirelocks(tile2); - if (tile._adjacentTiles[direction]?.Air != null) - { - tile2.ResetTileAtmosInfo(); - tile2._tileAtmosInfo.LastQueueCycle = queueCycle; - tiles.Add(tile2); - tileCount++; - } + + // The firelocks might have closed on us. + if (tile._adjacentTiles[direction]?.Air == null) continue; + tile2.ResetTileAtmosInfo(); + tile2._tileAtmosInfo.LastQueueCycle = queueCycle; + tiles[tileCount++] = tile2; } } + + if (tileCount >= limit || spaceTileCount >= limit) + break; } var queueCycleSlow = ++_gridAtmosphereComponent.EqualizationQueueCycleControl; - var progressionOrder = new List(); - foreach (var tile in spaceTiles) + var progressionOrder = ArrayPool.Shared.Rent(limit * 2); + var progressionCount = 0; + + for (var i = 0; i < spaceTileCount; i++) { - progressionOrder.Add(tile); + var tile = spaceTiles[i]; + progressionOrder[progressionCount++] = tile; tile._tileAtmosInfo.LastSlowQueueCycle = queueCycleSlow; tile._tileAtmosInfo.CurrentTransferDirection = Direction.Invalid; } - var progressionCount = progressionOrder.Count; - for (int i = 0; i < progressionCount; i++) + for (var i = 0; i < progressionCount; i++) { var tile = progressionOrder[i]; foreach (var direction in Cardinal) @@ -988,8 +1006,7 @@ namespace Content.Server.Atmos tile2._tileAtmosInfo.CurrentTransferAmount = 0; tile2.PressureSpecificTarget = tile.PressureSpecificTarget; tile2._tileAtmosInfo.LastSlowQueueCycle = queueCycleSlow; - progressionOrder.Add(tile2); - progressionCount++; + progressionOrder[progressionCount++] = tile2; } } @@ -1017,6 +1034,10 @@ namespace Content.Server.Atmos tile.UpdateVisuals(); tile.HandleDecompressionFloorRip(sum); } + + ArrayPool.Shared.Return(tiles); + ArrayPool.Shared.Return(spaceTiles); + ArrayPool.Shared.Return(progressionOrder); } private void HandleDecompressionFloorRip(float sum) @@ -1029,7 +1050,6 @@ namespace Content.Server.Atmos private void ConsiderFirelocks(TileAtmosphere other) { // TODO ATMOS firelocks! - //throw new NotImplementedException(); } private void React() diff --git a/SpaceStation14.sln.DotSettings b/SpaceStation14.sln.DotSettings index c93412bf8d..14abc1df09 100644 --- a/SpaceStation14.sln.DotSettings +++ b/SpaceStation14.sln.DotSettings @@ -51,6 +51,7 @@ <data><IncludeFilters /><ExcludeFilters><Filter ModuleMask="Lidgren.Network" ModuleVersionMask="*" ClassMask="*" FunctionMask="*" IsEnabled="True" /></ExcludeFilters></data> True True + True True True True From 1068269db0e3371f64749635248e73622e38d88f Mon Sep 17 00:00:00 2001 From: DrSmugleaf Date: Sun, 16 Aug 2020 16:26:07 +0200 Subject: [PATCH 04/21] Fix pointing by ghosts being visible to the living (#1715) --- .../GameObjects/EntitySystems/PointingSystem.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Content.Server/GameObjects/EntitySystems/PointingSystem.cs b/Content.Server/GameObjects/EntitySystems/PointingSystem.cs index 898ed90475..d27857954f 100644 --- a/Content.Server/GameObjects/EntitySystems/PointingSystem.cs +++ b/Content.Server/GameObjects/EntitySystems/PointingSystem.cs @@ -6,6 +6,7 @@ using Content.Shared.GameObjects.EntitySystems; using Content.Shared.Input; using Content.Shared.Interfaces; using JetBrains.Annotations; +using Robust.Server.GameObjects.Components; using Robust.Server.Interfaces.Player; using Robust.Server.Player; using Robust.Shared.Enums; @@ -113,7 +114,13 @@ namespace Content.Server.GameObjects.EntitySystems var viewers = _playerManager.GetPlayersInRange(player.Transform.GridPosition, 15); - EntityManager.SpawnEntity("pointingarrow", coords); + var arrow = EntityManager.SpawnEntity("pointingarrow", coords); + + if (player.TryGetComponent(out VisibilityComponent playerVisibility)) + { + var arrowVisibility = arrow.EnsureComponent(); + arrowVisibility.Layer = playerVisibility.Layer; + } string selfMessage; string viewerMessage; From d58d84096b935f7cc64f85824c7977a2c7f2d870 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Aguilera=20Puerto?= <6766154+Zumorica@users.noreply.github.com> Date: Sun, 16 Aug 2020 16:30:52 +0200 Subject: [PATCH 05/21] Adds mobCheck to a bunch of inventory/hands methods (#1704) * Adds mobCheck to a bunch of inventory/hands methods, fix not being able to strip dead bodies * Address review --- .../Components/GUI/HandsComponent.cs | 46 +++++++++++-------- .../Components/GUI/InventoryComponent.cs | 35 +++++++------- .../Components/GUI/StrippableComponent.cs | 18 ++++---- .../Items/Clothing/ClothingComponent.cs | 2 +- .../Components/Items/IHandsComponent.cs | 23 ++++++---- 5 files changed, 70 insertions(+), 54 deletions(-) diff --git a/Content.Server/GameObjects/Components/GUI/HandsComponent.cs b/Content.Server/GameObjects/Components/GUI/HandsComponent.cs index ea75c7f382..f5403a6928 100644 --- a/Content.Server/GameObjects/Components/GUI/HandsComponent.cs +++ b/Content.Server/GameObjects/Components/GUI/HandsComponent.cs @@ -11,6 +11,7 @@ using Content.Server.Interfaces.GameObjects.Components.Interaction; using Content.Server.Interfaces.GameObjects.Components.Items; using Content.Shared.GameObjects.Components.Items; using Content.Shared.GameObjects.Components.Mobs; +using Content.Shared.GameObjects.EntitySystems; using Content.Shared.Health.BodySystem; using Content.Shared.Physics; using Robust.Server.GameObjects; @@ -140,11 +141,11 @@ namespace Content.Server.GameObjects.Components.GUI } } - public bool PutInHand(ItemComponent item) + public bool PutInHand(ItemComponent item, bool mobCheck = true) { foreach (var hand in ActivePriorityEnumerable()) { - if (PutInHand(item, hand, false)) + if (PutInHand(item, hand, false, mobCheck)) { OnItemChanged?.Invoke(); @@ -155,10 +156,10 @@ namespace Content.Server.GameObjects.Components.GUI return false; } - public bool PutInHand(ItemComponent item, string index, bool fallback = true) + public bool PutInHand(ItemComponent item, string index, bool fallback = true, bool mobChecks = true) { var hand = GetHand(index); - if (!CanPutInHand(item, index) || hand == null) + if (!CanPutInHand(item, index, mobChecks) || hand == null) { return fallback && PutInHand(item); } @@ -176,19 +177,23 @@ namespace Content.Server.GameObjects.Components.GUI return success; } - public void PutInHandOrDrop(ItemComponent item) + public void PutInHandOrDrop(ItemComponent item, bool mobCheck = true) { - if (!PutInHand(item)) + if (!PutInHand(item, mobCheck)) { item.Owner.Transform.GridPosition = Owner.Transform.GridPosition; } } - public bool CanPutInHand(ItemComponent item) + public bool CanPutInHand(ItemComponent item, bool mobCheck = true) { + if (mobCheck && !ActionBlockerSystem.CanPickup(Owner)) + return false; + foreach (var handName in ActivePriorityEnumerable()) { - if (CanPutInHand(item, handName)) + // We already did a mobCheck, so let's not waste cycles. + if (CanPutInHand(item, handName, false)) { return true; } @@ -197,8 +202,11 @@ namespace Content.Server.GameObjects.Components.GUI return false; } - public bool CanPutInHand(ItemComponent item, string index) + public bool CanPutInHand(ItemComponent item, string index, bool mobCheck = true) { + if (mobCheck && !ActionBlockerSystem.CanPickup(Owner)) + return false; + return GetHand(index)?.Container.CanInsert(item.Owner) == true; } @@ -284,17 +292,17 @@ namespace Content.Server.GameObjects.Components.GUI return Drop(slot, coords, doMobChecks); } - public bool Drop(string slot, bool doMobChecks = true) + public bool Drop(string slot, bool mobChecks = true) { var hand = GetHand(slot); - if (!CanDrop(slot) || hand?.Entity == null) + if (!CanDrop(slot, mobChecks) || hand?.Entity == null) { return false; } var item = hand.Entity.GetComponent(); - if (!DroppedInteraction(item, doMobChecks)) + if (!DroppedInteraction(item, mobChecks)) return false; if (!hand.Container.Remove(hand.Entity)) @@ -321,7 +329,7 @@ namespace Content.Server.GameObjects.Components.GUI return true; } - public bool Drop(IEntity entity, bool doMobChecks = true) + public bool Drop(IEntity entity, bool mobChecks = true) { if (entity == null) { @@ -333,7 +341,7 @@ namespace Content.Server.GameObjects.Components.GUI throw new ArgumentException("Entity must be held in one of our hands.", nameof(entity)); } - return Drop(slot, doMobChecks); + return Drop(slot, mobChecks); } public bool Drop(string slot, BaseContainer targetContainer, bool doMobChecks = true) @@ -409,13 +417,15 @@ namespace Content.Server.GameObjects.Components.GUI /// /// True if there is an item in the slot and it can be dropped, false otherwise. /// - public bool CanDrop(string name) + public bool CanDrop(string name, bool mobCheck = true) { var hand = GetHand(name); - if (hand?.Entity == null) - { + + if (mobCheck && !ActionBlockerSystem.CanDrop(Owner)) + return false; + + if (hand?.Entity == null) return false; - } return hand.Container.CanRemove(hand.Entity); } diff --git a/Content.Server/GameObjects/Components/GUI/InventoryComponent.cs b/Content.Server/GameObjects/Components/GUI/InventoryComponent.cs index 1d1e52b6a2..57ab715eb5 100644 --- a/Content.Server/GameObjects/Components/GUI/InventoryComponent.cs +++ b/Content.Server/GameObjects/Components/GUI/InventoryComponent.cs @@ -173,9 +173,10 @@ namespace Content.Server.GameObjects.Components.GUI /// /// The slot to put the item in. /// The item to insert into the slot. + /// Whether to perform an ActionBlocker check to the entity. /// The translated reason why the item cannot be equipped, if this function returns false. Can be null. /// True if the item was successfully inserted, false otherwise. - public bool Equip(Slots slot, ItemComponent item, out string reason) + public bool Equip(Slots slot, ItemComponent item, bool mobCheck, out string reason) { if (item == null) { @@ -183,7 +184,7 @@ namespace Content.Server.GameObjects.Components.GUI "Clothing must be passed here. To remove some clothing from a slot, use Unequip()"); } - if (!CanEquip(slot, item, out reason)) + if (!CanEquip(slot, item, mobCheck, out reason)) { return false; } @@ -203,9 +204,9 @@ namespace Content.Server.GameObjects.Components.GUI return true; } - public bool Equip(Slots slot, ItemComponent item) => Equip(slot, item, out var _); + public bool Equip(Slots slot, ItemComponent item, bool mobCheck = true) => Equip(slot, item, mobCheck, out var _); - public bool Equip(Slots slot, IEntity entity) => Equip(slot, entity.GetComponent()); + public bool Equip(Slots slot, IEntity entity, bool mobCheck = true) => Equip(slot, entity.GetComponent(), mobCheck); /// /// Checks whether an item can be put in the specified slot. @@ -214,12 +215,12 @@ namespace Content.Server.GameObjects.Components.GUI /// The item to check for. /// The translated reason why the item cannot be equiped, if this function returns false. Can be null. /// True if the item can be inserted into the specified slot. - public bool CanEquip(Slots slot, ItemComponent item, out string reason) + public bool CanEquip(Slots slot, ItemComponent item, bool mobCheck, out string reason) { var pass = false; reason = null; - if (!ActionBlockerSystem.CanEquip(Owner)) + if (mobCheck && !ActionBlockerSystem.CanEquip(Owner)) return false; if (item is ClothingComponent clothing) @@ -248,18 +249,19 @@ namespace Content.Server.GameObjects.Components.GUI return pass && _slotContainers[slot].CanInsert(item.Owner); } - public bool CanEquip(Slots slot, ItemComponent item) => CanEquip(slot, item, out var _); + public bool CanEquip(Slots slot, ItemComponent item, bool mobCheck = true) => CanEquip(slot, item, mobCheck, out var _); - public bool CanEquip(Slots slot, IEntity entity) => CanEquip(slot, entity.GetComponent()); + public bool CanEquip(Slots slot, IEntity entity, bool mobCheck = true) => CanEquip(slot, entity.GetComponent(), mobCheck); /// /// Drops the item in a slot. /// /// The slot to drop the item from. /// True if an item was dropped, false otherwise. - public bool Unequip(Slots slot) + /// Whether to perform an ActionBlocker check to the entity. + public bool Unequip(Slots slot, bool mobCheck = true) { - if (!CanUnequip(slot)) + if (!CanUnequip(slot, mobCheck)) { return false; } @@ -288,16 +290,17 @@ namespace Content.Server.GameObjects.Components.GUI /// Checks whether an item can be dropped from the specified slot. /// /// The slot to check for. + /// Whether to perform an ActionBlocker check to the entity. /// /// True if there is an item in the slot and it can be dropped, false otherwise. /// - public bool CanUnequip(Slots slot) + public bool CanUnequip(Slots slot, bool mobCheck = true) { - if (!ActionBlockerSystem.CanUnequip(Owner)) + if (mobCheck && !ActionBlockerSystem.CanUnequip(Owner)) return false; - var InventorySlot = _slotContainers[slot]; - return InventorySlot.ContainedEntity != null && InventorySlot.CanRemove(InventorySlot.ContainedEntity); + var inventorySlot = _slotContainers[slot]; + return inventorySlot.ContainedEntity != null && inventorySlot.CanRemove(inventorySlot.ContainedEntity); } /// @@ -398,7 +401,7 @@ namespace Content.Server.GameObjects.Components.GUI if (activeHand != null && activeHand.Owner.TryGetComponent(out ItemComponent clothing)) { hands.Drop(hands.ActiveHand); - if (!Equip(msg.Inventoryslot, clothing, out var reason)) + if (!Equip(msg.Inventoryslot, clothing, true, out var reason)) { hands.PutInHand(clothing); @@ -434,7 +437,7 @@ namespace Content.Server.GameObjects.Components.GUI var activeHand = hands.GetActiveHand; if (activeHand != null && GetSlotItem(msg.Inventoryslot) == null) { - var canEquip = CanEquip(msg.Inventoryslot, activeHand, out var reason); + var canEquip = CanEquip(msg.Inventoryslot, activeHand, true, out var reason); _hoverEntity = new KeyValuePair(msg.Inventoryslot, (activeHand.Owner.Uid, canEquip)); Dirty(); diff --git a/Content.Server/GameObjects/Components/GUI/StrippableComponent.cs b/Content.Server/GameObjects/Components/GUI/StrippableComponent.cs index e045fd2b5a..0363fee424 100644 --- a/Content.Server/GameObjects/Components/GUI/StrippableComponent.cs +++ b/Content.Server/GameObjects/Components/GUI/StrippableComponent.cs @@ -137,7 +137,7 @@ namespace Content.Server.GameObjects.Components.GUI return false; } - if (!inventory.CanEquip(slot, item)) + if (!inventory.CanEquip(slot, item, false)) { _notifyManager.PopupMessageCursor(user, Loc.GetString("{0:They} cannot equip that there!", Owner)); return false; @@ -162,7 +162,7 @@ namespace Content.Server.GameObjects.Components.GUI if (result != DoAfterStatus.Finished) return; userHands.Drop(item!.Owner, false); - inventory.Equip(slot, item!.Owner); + inventory.Equip(slot, item!.Owner, false); UpdateSubscribed(); } @@ -202,7 +202,7 @@ namespace Content.Server.GameObjects.Components.GUI return false; } - if (!hands.CanPutInHand(item, hand)) + if (!hands.CanPutInHand(item, hand, false)) { _notifyManager.PopupMessageCursor(user, Loc.GetString("{0:They} cannot put that there!", Owner)); return false; @@ -227,7 +227,7 @@ namespace Content.Server.GameObjects.Components.GUI if (result != DoAfterStatus.Finished) return; userHands.Drop(hand, false); - hands.PutInHand(item, hand, false); + hands.PutInHand(item!, hand, false, false); UpdateSubscribed(); } @@ -253,7 +253,7 @@ namespace Content.Server.GameObjects.Components.GUI return false; } - if (!inventory.CanUnequip(slot)) + if (!inventory.CanUnequip(slot, false)) { _notifyManager.PopupMessageCursor(user, Loc.GetString("{0:They} cannot unequip that!", Owner)); return false; @@ -277,7 +277,7 @@ namespace Content.Server.GameObjects.Components.GUI if (result != DoAfterStatus.Finished) return; var item = inventory.GetSlotItem(slot); - inventory.Unequip(slot); + inventory.Unequip(slot, false); userHands.PutInHandOrDrop(item); UpdateSubscribed(); } @@ -304,7 +304,7 @@ namespace Content.Server.GameObjects.Components.GUI return false; } - if (!hands.CanDrop(hand)) + if (!hands.CanDrop(hand, false)) { _notifyManager.PopupMessageCursor(user, Loc.GetString("{0:They} cannot drop that!", Owner)); return false; @@ -329,7 +329,7 @@ namespace Content.Server.GameObjects.Components.GUI var item = hands.GetItem(hand); hands.Drop(hand, false); - userHands.PutInHandOrDrop(item); + userHands.PutInHandOrDrop(item!); UpdateSubscribed(); } @@ -364,8 +364,6 @@ namespace Content.Server.GameObjects.Components.GUI else TakeItemFromHands(user, handMessage.Hand); break; - default: - break; } } } diff --git a/Content.Server/GameObjects/Components/Items/Clothing/ClothingComponent.cs b/Content.Server/GameObjects/Components/Items/Clothing/ClothingComponent.cs index a94c5982bc..7de3236ec9 100644 --- a/Content.Server/GameObjects/Components/Items/Clothing/ClothingComponent.cs +++ b/Content.Server/GameObjects/Components/Items/Clothing/ClothingComponent.cs @@ -112,7 +112,7 @@ namespace Content.Server.GameObjects.Components.Items.Clothing private bool TryEquip(InventoryComponent inv, Slots slot, IEntity user) { - if (!inv.Equip(slot, this, out var reason)) + if (!inv.Equip(slot, this, true, out var reason)) { if (reason != null) _serverNotifyManager.PopupMessage(Owner, user, reason); diff --git a/Content.Server/Interfaces/GameObjects/Components/Items/IHandsComponent.cs b/Content.Server/Interfaces/GameObjects/Components/Items/IHandsComponent.cs index e716533285..5765098531 100644 --- a/Content.Server/Interfaces/GameObjects/Components/Items/IHandsComponent.cs +++ b/Content.Server/Interfaces/GameObjects/Components/Items/IHandsComponent.cs @@ -61,8 +61,9 @@ namespace Content.Server.Interfaces.GameObjects.Components.Items /// Puts an item into any empty hand, preferring the active hand. /// /// The item to put in a hand. + /// Whether to perform an ActionBlocker check to the entity. /// True if the item was inserted, false otherwise. - bool PutInHand(ItemComponent item); + bool PutInHand(ItemComponent item, bool mobCheck = true); /// /// Puts an item into a specific hand. @@ -71,24 +72,27 @@ namespace Content.Server.Interfaces.GameObjects.Components.Items /// The name of the hand to put the item into. /// /// If true and the provided hand is full, the method will fall back to + /// Whether to perform an ActionBlocker check to the entity. /// /// True if the item was inserted into a hand, false otherwise. - bool PutInHand(ItemComponent item, string index, bool fallback=true); + bool PutInHand(ItemComponent item, string index, bool fallback=true, bool mobCheck = true); /// /// Checks to see if an item can be put in any hand. /// /// The item to check for. + /// Whether to perform an ActionBlocker check to the entity. /// True if the item can be inserted, false otherwise. - bool CanPutInHand(ItemComponent item); + bool CanPutInHand(ItemComponent item, bool mobCheck = true); /// /// Checks to see if an item can be put in the specified hand. /// /// The item to check for. /// The name for the hand to check for. + /// Whether to perform an ActionBlocker check to the entity. /// True if the item can be inserted, false otherwise. - bool CanPutInHand(ItemComponent item, string index); + bool CanPutInHand(ItemComponent item, string index, bool mobCheck = true); /// /// Finds the hand slot holding the specified entity, if any. @@ -107,15 +111,15 @@ namespace Content.Server.Interfaces.GameObjects.Components.Items /// Drops the item contained in the slot to the same position as our entity. /// /// The slot of which to drop to drop the item. - /// Whether to check the for the mob or not. + /// Whether to check the for the mob or not. /// True on success, false if something blocked the drop. - bool Drop(string slot, bool doMobChecks = true); + bool Drop(string slot, bool mobChecks = true); /// /// Drops an item held by one of our hand slots to the same position as our owning entity. /// /// The item to drop. - /// Whether to check the for the mob or not. + /// Whether to check the for the mob or not. /// True on success, false if something blocked the drop. /// /// Thrown if is null. @@ -123,7 +127,7 @@ namespace Content.Server.Interfaces.GameObjects.Components.Items /// /// Thrown if is not actually held in any hand. /// - bool Drop(IEntity entity, bool doMobChecks = true); + bool Drop(IEntity entity, bool mobChecks = true); /// /// Drops the item in a slot. @@ -194,10 +198,11 @@ namespace Content.Server.Interfaces.GameObjects.Components.Items /// Checks whether the item in the specified hand can be dropped. /// /// The hand to check for. + /// Whether to perform an ActionBlocker check to the entity. /// /// True if the item can be dropped, false if the hand is empty or the item in the hand cannot be dropped. /// - bool CanDrop(string name); + bool CanDrop(string name, bool mobCheck = true); /// /// Adds a new hand to this hands component. From 83567c1bd9047e9a116a7de99d2c53f7d8aa9970 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Aguilera=20Puerto?= Date: Sun, 16 Aug 2020 17:08:27 +0200 Subject: [PATCH 06/21] Improves MindComponent's description. Force ghost without body return when commiting suicide. --- Content.Server/Chat/ChatCommands.cs | 8 +++++++- .../GameObjects/Components/Mobs/MindComponent.cs | 3 ++- Content.Server/Observer/Ghost.cs | 3 ++- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/Content.Server/Chat/ChatCommands.cs b/Content.Server/Chat/ChatCommands.cs index 9d3ff7c995..a6c5404f59 100644 --- a/Content.Server/Chat/ChatCommands.cs +++ b/Content.Server/Chat/ChatCommands.cs @@ -1,10 +1,12 @@ -using System.Linq; +using System; +using System.Linq; using Content.Server.GameObjects.Components.Damage; using Content.Server.GameObjects.Components.GUI; using Content.Server.GameObjects.Components.Items.Storage; using Content.Server.GameObjects.Components.Observer; using Content.Server.Interfaces.Chat; using Content.Server.Interfaces.GameObjects; +using Content.Server.Observer; using Content.Server.Players; using Content.Shared.GameObjects.Components.Damage; using Robust.Server.Interfaces.Console; @@ -168,6 +170,10 @@ namespace Content.Server.Chat // Default suicide, bite your tongue chat.EntityMe(owner, Loc.GetString("is attempting to bite {0:their} own tongue, looks like {0:theyre} trying to commit suicide!", owner)); //TODO: theyre macro dmgComponent.TakeDamage(DamageType.Brute, 500, owner, owner); //TODO: dmg value needs to be a max damage of some sorts + + // Prevent the player from returning to the body. Yes, this is an ugly hack. + var ghost = new Ghost(){CanReturn = false}; + ghost.Execute(shell, player, Array.Empty()); } } } diff --git a/Content.Server/GameObjects/Components/Mobs/MindComponent.cs b/Content.Server/GameObjects/Components/Mobs/MindComponent.cs index d148490bd9..fe033e2231 100644 --- a/Content.Server/GameObjects/Components/Mobs/MindComponent.cs +++ b/Content.Server/GameObjects/Components/Mobs/MindComponent.cs @@ -137,7 +137,8 @@ namespace Content.Server.GameObjects.Components.Mobs } else if (Mind?.Session == null) { - message.AddMarkup("[color=yellow]" + Loc.GetString("{0:They} {0:have} a blank, absent-minded stare and appears completely unresponsive to anything. {0:They} may snap out of it soon.", Owner) + "[/color]"); + if(!dead) + message.AddMarkup("[color=yellow]" + Loc.GetString("{0:They} {0:have} a blank, absent-minded stare and appears completely unresponsive to anything. {0:They} may snap out of it soon.", Owner) + "[/color]"); } } } diff --git a/Content.Server/Observer/Ghost.cs b/Content.Server/Observer/Ghost.cs index 80480b958a..004f5951ee 100644 --- a/Content.Server/Observer/Ghost.cs +++ b/Content.Server/Observer/Ghost.cs @@ -17,6 +17,7 @@ namespace Content.Server.Observer public string Command => "ghost"; public string Description => "Give up on life and become a ghost."; public string Help => "ghost"; + public bool CanReturn { get; set; } = true; public void Execute(IConsoleShell shell, IPlayerSession player, string[] args) { @@ -27,7 +28,7 @@ namespace Content.Server.Observer } var mind = player.ContentData().Mind; - var canReturn = player.AttachedEntity != null; + var canReturn = player.AttachedEntity != null && CanReturn; var name = player.AttachedEntity?.Name ?? player.Name; if (player.AttachedEntity != null && player.AttachedEntity.HasComponent()) From 327c3b92adf8d8b9321b8812606f6e6b766c6ce6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Aguilera=20Puerto?= Date: Sun, 16 Aug 2020 18:18:42 +0200 Subject: [PATCH 07/21] Adds conditional spawners for ammunition. Still needs to be mapped in. --- .../Markers/gamemode_conditional_spawners.yml | 133 ++++++++++++++++++ .../Interface/Misc/markers.rsi/meta.json | 47 ++++++- .../Interface/Misc/markers.rsi/spawner_ai.png | Bin 5382 -> 1115 bytes .../markers.rsi/spawner_launcher_ammo.png | Bin 0 -> 445 bytes .../Misc/markers.rsi/spawner_magnum_ammo.png | Bin 0 -> 614 bytes .../Misc/markers.rsi/spawner_pistol_ammo.png | Bin 0 -> 636 bytes .../Misc/markers.rsi/spawner_rifle_ammo.png | Bin 0 -> 482 bytes .../Misc/markers.rsi/spawner_shotgun_ammo.png | Bin 0 -> 469 bytes .../Misc/markers.rsi/spawner_trash.png | Bin 663 -> 551 bytes .../Misc/markers.rsi/spawner_xenoai.png | Bin 5530 -> 1111 bytes 10 files changed, 179 insertions(+), 1 deletion(-) create mode 100644 Resources/Textures/Interface/Misc/markers.rsi/spawner_launcher_ammo.png create mode 100644 Resources/Textures/Interface/Misc/markers.rsi/spawner_magnum_ammo.png create mode 100644 Resources/Textures/Interface/Misc/markers.rsi/spawner_pistol_ammo.png create mode 100644 Resources/Textures/Interface/Misc/markers.rsi/spawner_rifle_ammo.png create mode 100644 Resources/Textures/Interface/Misc/markers.rsi/spawner_shotgun_ammo.png diff --git a/Resources/Prototypes/Entities/Effects/Markers/gamemode_conditional_spawners.yml b/Resources/Prototypes/Entities/Effects/Markers/gamemode_conditional_spawners.yml index f5a840c392..b203903616 100644 --- a/Resources/Prototypes/Entities/Effects/Markers/gamemode_conditional_spawners.yml +++ b/Resources/Prototypes/Entities/Effects/Markers/gamemode_conditional_spawners.yml @@ -260,6 +260,139 @@ - ExGrenade - GrenadeFlashBang - SyndieMiniBomb + - GrenadeFlash + - GrenadeBlast + - GrenadeFrag + - GrenadeBaton chance: 0.75 gameRules: - RuleSuspicion + +- type: entity + name: Suspicion Sniper Spawner + id: SuspicionSniperSpawner + parent: BaseConditionalSpawner + components: + - type: Sprite + netsync: false + visible: false + sprite: Interface/Misc/markers.rsi + state: spawner_sniper + - type: Icon + sprite: Interface/Misc/markers.rsi + state: spawner_sniper + - type: ConditionalSpawner + prototypes: + - SniperBoltGun + - SniperBoltGunWood + - SniperHeavy + chance: 0.75 + gameRules: + - RuleSuspicion + +- type: entity + name: Suspicion Rifle Ammo Spawner + id: SuspicionRifleMagazineSpawner + parent: BaseConditionalSpawner + components: + - type: Sprite + netsync: false + visible: false + sprite: Interface/Misc/markers.rsi + state: spawner_rifle_ammo + - type: Icon + sprite: Interface/Misc/markers.rsi + state: spawner_rifle_ammo + - type: ConditionalSpawner + prototypes: + - MagazineSRifle + - MagazineClRifle + - MagazineLRifle + chance: 0.95 + gameRules: + - RuleSuspicion + +- type: entity + name: Suspicion Shotgun Ammo Spawner + id: SuspicionShotgunMagazineSpawner + parent: BaseConditionalSpawner + components: + - type: Sprite + netsync: false + visible: false + sprite: Interface/Misc/markers.rsi + state: spawner_shotgun_ammo + - type: Icon + sprite: Interface/Misc/markers.rsi + state: spawner_shotgun_ammo + - type: ConditionalSpawner + prototypes: + - MagazineShotgun + chance: 0.95 + gameRules: + - RuleSuspicion + +- type: entity + name: Suspicion Pistol Ammo Spawner + id: SuspicionPistolMagazineSpawner + parent: BaseConditionalSpawner + components: + - type: Sprite + netsync: false + visible: false + sprite: Interface/Misc/markers.rsi + state: spawner_pistol_ammo + - type: Icon + sprite: Interface/Misc/markers.rsi + state: spawner_pistol_ammo + - type: ConditionalSpawner + prototypes: + - MagazinePistol + - MagazineHCPistol + - MagazinePistolSmg + - MagazineClRiflePistol + chance: 0.95 + gameRules: + - RuleSuspicion + +- type: entity + name: Suspicion Magnum Ammo Spawner + id: SuspicionMagnumMagazineSpawner + parent: BaseConditionalSpawner + components: + - type: Sprite + netsync: false + visible: false + sprite: Interface/Misc/markers.rsi + state: spawner_magnum_ammo + - type: Icon + sprite: Interface/Misc/markers.rsi + state: spawner_magnum_ammo + - type: ConditionalSpawner + prototypes: + - MagazineMagnum + - MagazineMagnumSmg + chance: 0.95 + gameRules: + - RuleSuspicion + +- type: entity + name: Suspicion Launcher Ammo Spawner + id: SuspicionLauncherAmmoSpawner + parent: BaseConditionalSpawner + components: + - type: Sprite + netsync: false + visible: false + sprite: Interface/Misc/markers.rsi + state: spawner_launcher_ammo + - type: Icon + sprite: Interface/Misc/markers.rsi + state: spawner_launcher_ammo + - type: ConditionalSpawner + prototypes: + - RocketAmmo + - GrenadeFrag + chance: 0.95 + gameRules: + - RuleSuspicion diff --git a/Resources/Textures/Interface/Misc/markers.rsi/meta.json b/Resources/Textures/Interface/Misc/markers.rsi/meta.json index a1fa3f2b53..3c58904297 100644 --- a/Resources/Textures/Interface/Misc/markers.rsi/meta.json +++ b/Resources/Textures/Interface/Misc/markers.rsi/meta.json @@ -403,6 +403,24 @@ ] ] }, + { + "name": "spawner_launcher_ammo", + "directions": 1, + "delays": [ + [ + 1.0 + ] + ] + }, + { + "name": "spawner_magnum_ammo", + "directions": 1, + "delays": [ + [ + 1.0 + ] + ] + }, { "name": "spawner_melee", "directions": 1, @@ -421,6 +439,15 @@ ] ] }, + { + "name": "spawner_pistol_ammo", + "directions": 1, + "delays": [ + [ + 1.0 + ] + ] + }, { "name": "spawner_revolver", "directions": 1, @@ -439,6 +466,15 @@ ] ] }, + { + "name": "spawner_rifle_ammo", + "directions": 1, + "delays": [ + [ + 1.0 + ] + ] + }, { "name": "spawner_shotgun", "directions": 1, @@ -448,6 +484,15 @@ ] ] }, + { + "name": "spawner_shotgun_ammo", + "directions": 1, + "delays": [ + [ + 1.0 + ] + ] + }, { "name": "spawner_smg", "directions": 1, @@ -466,7 +511,7 @@ ] ] }, - { + { "name": "spawner_trash", "directions": 1, "delays": [ diff --git a/Resources/Textures/Interface/Misc/markers.rsi/spawner_ai.png b/Resources/Textures/Interface/Misc/markers.rsi/spawner_ai.png index c9d18bf907da994aacb7765b42b4422e7811f372..6e7304d7620a88cd5bf564669cd6db3674b554e5 100644 GIT binary patch delta 1095 zcmV-N1i1T#D%%K#Wrv>a1rE*WASB-sIZB*nuDC_vf7R{r-OU+~4oO|5JkUUw_4PnHvTH1R@SIr${wY zi9FB;Jw3bhlYm>uW8W>P>*3*H zfhmbpBe#C)kw`U0%Z;sk&AxpZ*&S%$?W73E=Fy{az5q1WV*ALU6t!2`+$(r7iQk$o z%X(dh2*}mbr+4i>*9Hd%rMtUZwjDl+z5bo;oja`-3V(CraOx_zUxIayhv(+!neNhd zS?0#6R0>=RFpKSPUV?y5;uK#{%{Od!b~4w{z`=_bQ51#gE)6vrV!BI1Q55?7`*oM9 zD)u#hWeeN}0eCC0jCj4=ud5^J@ld*;&Ij5D3uH(xMNl9^&hKlW#j;VKR|oe0==L z2mr6S?kuu$=vfYWs{s8!fB)o3?vIU8Gd2coZ3F@V5aE_%C*hqADxRt2_WWPAPQX$G zK7Ze?d`kZK;Uk$F4av}%_oThOT~t+-D~*jJAgSxuMO9T9ZfYuV6~9|D5zCfQLubAO z;MngGG}nnDt8h4M^fgT*JaLwxF8$>^_TkR!TH->oAYlHaYHcS_Rn@Rcr_;tg05CE# zLO6VOPtS0PqSWL)Z_5J%#N%WMuRrKY>cOFSMY91c4QN$6s) zvNAaVJC#hyYa>U%q3<+k>m;m;(!G^YCM4{ggv*k(1-R7}TRd+srpwx)7(9_kkVqtU z!I;hMC8mi4P0OgEXjF!xQE|K7;`jT-@AnHpuJ3lcC1+zdW*HKBIX5sMA|m%P892)NyDnVguAdzp-gh@2Z3upm(^wi2tix7XCUudmNhYRyjUe*j=HkZ+_mc)b7s N002ovPDHLkV1kBP5AOf~ literal 5382 zcmV+h75VCkP) zaB^>EX>4U6ba`-PAZ2)IW&i+q+O3&clH5A7ME|jhUIH-#%fV>YJ9x|Q;~+C@kV?AO z>?u`6CMN*l9v&Vnv;ObD+x&-r!TMxE%q7*7F8+lYs%z|&>;6~IZ+nIF`}}jyDZYO> zZr&#xhdf()uJV z&x6Ku;hDGhjE_=_U{?F zuP3&>)-TI>e)gVa?{%-Pg+xTt!>AK%`+5u)c0%sYZHZ6jC$gW9Jv_FU_tOHPN;CV+@!RtB5u8(@VH;ZF_)4z=iG zh%u&^V==MDmV62+rj&A$$hGWq$T6p!bICQg;!7y8q>@W1wY2K0M+0L`HP=#WZOxg+ zK#gZLu5TRauKON(?5XEodhKmMpAkkJY2;Bx9c{YlCo(b9%(Kio+p=b%6f3N_(#or> zy4r?o+wZXBPCM_i>uzt<9#nt%{0r3VgPJ=?>AL(zjiV;#*CVXtBnmSSbHRdm76K63 z3A3x%5S)+`W>6rKza3_qHvFx@-opSo&gCM7ze)a)_3??8u+9r<(S$ zHQx{X!)+X`v~iA^FJjQB z4BVSoK!X7}ftTG8uy<~oIhw$TY5ONa*^m7ZnqG-&Z$xCktp*e3eyx2_L@q5E=3h|B zg!Ak*ea%E@bCuUs)^`%+g^r@*x(JaEN$ae(#wQ*tkV?h;OdQuHYx6NLzQD!Y{eqz# znBc1SWo6$>Ogq}xr-`%2)z@rxg+w*9opidgrb{LjAA4wi%{~ZCo&Yd5GC!6k+BUM? zmqi7JX?PeQHT|xJQED8 z5xCbTJrfz-SE5kW0-J;4ljj^_nc=AmsznxG(}a*$>I#T$BNZ;&*gDKcDcVC&-hkV$ zaGM+N4Q&4oaB?rL?hfXfICZUUX1+3q`2^-&EMxW=$CPsIoNeW4`;^y+AbNoI_pG6C zL;8q@SpYN=Hf+~9)&&@C)q8;{+MVW#$a*p+x=1HNGX)PjQDOIf+Ci!gi;PajUo4~qqv(N#U9mH_m6cl7wWcJa zPv~`{BL~uuXAr(GNEhl){h;!|!f86$ziSnHR#HZY?3hSU$V0@^Kf~78CEWl(|Q&-3wee^e*Q7xHwzFpU| zwOMmdhYGib_$Un-OC(i2a{2Nh2{NcvNwZ~WHXdk{?v5Z)-ZWRwFqwpoCza8#4)T4E zp76Q7yTxr|t{vMH;|-K29+Cx8w8!a?jTCFh))CxXl^PjJ4Y2Jo&9)cVR!P0fg%Bn( zngqg)43u~?PC*tjwUE{(5dZ1n2st`C{Oib5Ij5aGz=kLc&z7=Lmjs+>`n`$DQHA_0O}Y@h*`}aayIOl3pxQgm69myfUd|}42(YAhWnly{45#X4rKt8hgH^WG!?odx4tW} zw(|{l{gkJ##q)>lQ55q@QhrjDRiIO%_H$jsCe<=fD5jSwx=Kxwdl-icqb{$5aj$pq zuuLd>lxr(ULB-j_v`F^NfluscgU8rGiXBwkZQBNs1u(LFdZ>#3BHb?3-lI&&C@COa zn92{gZhgG`TxaPb33Egi+B92aLs{$u4n)>%Dj?Kq;zh1j*3RJpfSj@fc%&M^&XN-d zTc;ZbVT0~XzYe)tPsl$GFdR3Ry*(L6I|7q2LvTrzg61-`nptdA@egu7yO;oG%5Bfw z;UblQnU(NBvT@V-x5n%H)_giZ5=glgQMA<0H3lwVP0A_`7e5L-2v^Eo2?u6h-QWA%|wgW!y7ZL~pnBLcx~CKef!}^8xH~54CqSHpELD zIwa~CF*jWnz&nhQS#=>=%3I2Yqv$!))iRI{7Wu@k%5qBaS(_&qDj<<~S*H+7VG-hd z(OZm;C}dU0NP_re2x?W+h>nJhNbdAz!#j{CjyM{IffW!Q@$|#@9+AO_352|6Gh@Xl zpaR=MmqvLWXww`X-{6VsUsUAYn%|u0s$|0>&?I`zSVUH37v&>MDX`m^m3StLrqP|@ zy>PXtWuerh{3sxH(GATWFIY%U(>kh=d^}~K-KI`QIdE72 zujzZUO8KVIrK2gh7frqvtRD}Fw{A3K$En~SUkV+p9oIKs@YB|OKR|DT-RyW->erxD z^)wc%$_>xmIT595da0$dk+j6BGHQIKoO_vgbo^o)`c()zjW9hq4U~Ec{LH}n&>vE2 zT-_lL95O`Ci>EH(2Wk<4pj)triA^UB@SA&3jIof^U!W6##oOv7c4FF0@WaX$+*(}> zv+hVGDu%*lsXY~u5};(RqQgyZl0e!*qfO*g?WNK}w3Nm%wF);+XMQ49 zrpyCR*@#?Fw=nB%%{pGE{Hg)w&*DIcwQS6u?0Mf%=+u1ru?>MB@;c4MPKNHYhF*{f z9XKB2F$TLOgn>r?;MdWUMRlgFs9q+UY2(C}@AONU7Ne$g-;sIsx_($9NvjdTwV(1f zb&(@O{G<@fOGJy*Rus%le8^1Z^2`-OfoWHJNR+6EI0-!Pg8AFxs=FJW784hCv}|pL zqxmJ#0BFvwd?ZC~EA<`@y`g`aYC3vQzFg_2!RBED_Gu@?pB8N~2y9u3BcVAZINnNL z2N4J-ek?(SS9mr$kVcJ$3CDC$iVgk5B8lY)WptSvra4iomoHF{QwtzCP68YVynGXj z(n|<5h~5R_%xp*%%*qNV2l(~FV;>1eCSy}wL-x1yGpGK{48K(Tt2J&O{c7ISOb57M z4gW6O>ohvidcWxz?fR>2GxBRT9*;)jfX2ckn(n8!zvy)wVtN`pTryF=+ZDA5kyRw= zl)77^?lfP^Wmw1p{BC@^?LN;3^>;)KX{}XyMs#Ko@4nWvP2H%4+5|&b8Pk?^Ev!QxA)KDC%nhgrg3`b+cY z2J>(IWma=pStjL({tRKiF57fS-_5Cq9#tD1tR{qn})r}n`7+cyqBy>Kvpc;kRWh=3TM4x24b0+FbEk~-|? z&Ee^NjC!Rd&+Sy#x~dJi8PKm<0T-RT+WxRq z+3Hn3)maz%S7((g`PaT{ zu5aD)@eTw*CVB+2ad`+CPKO1X@UuDftMQc!^+vfpr&u?{(BC3(-%;Ob$QU%Vcavr) z_nPuJ@6c}rfea`}eGv`?K>{WwO)ryp+z?a~kp+_%W9T5ArA0jT;(2Gt7PFxy+D@*R zQ_!Cb-gc8-9qN{8&H+DTITuHIad8qe zy4BabJd)lOK6mS3;&OVtD>rCh^I@vaD^acR{E^~=D`7lT`T92sO4F`=rZLv^w!D&nYB zC_;r$E41oha_NWAq#;RhaTHt&4t^|F9bBAsb#N5~!4D88M<+!WDe-?vp+&3*$NhMB z?{W7I5b9;7SzTj*rrTyZnGmzN6*2IN9z+qwC_*x`j9E!aq2u_vhmWs!ah}!r+@B+) z<}C*JMB*7{m^Se`@zkbmaNZ}5u#&72pA(OmbV1@rt}7nDaW1+n@XUyrNzV~Sh{a+X zD{ah5rbawT98)!&@`bF&D(5ZETDi)a_v9}O=Jn+zuG1Vu5(`*_1Q80V*gzRJ;h;##$LRx*p{`Olz`-FfT%_!^4)5-5@9p0+&HjD>aK3V;1V!TE00006VoOIv0RI60 z0RN!9r;`8x010qNS#tmY3ljhU3ljkVnw%H_000McNliru`>9ln`GPAi;d6&TP=O#2hOi-u87zqb`02+z z0H!Ppp7u)^1Ix&TtQ@dHA_Me6Pfw0~5^!s|;4|d#@UXy?1gnu-KlMnk8ndO}i`f?X z_7?VR#?iprF%gi>qeta@7HGPK_mM`)Yp=4oTkw1mzcpQ!^|}rbkgKOp=d3>61_uYF zySrPq6}N<6|IYHtZN&*>a^i6ODtBIjb*Gc(=I5F2(sMM^@9}sX>6AN`HU9VNzAazUHs2CR{lJ@RoNOak+R< zS4Yh0q;_?c!v_wasw$ri|ADHixZQ4=o10A=*O4RW`qyQ_EfIKrex6iE2Uo6LV`~3? z0M-Wwal73Bri{g6hQZp}t}?A8flqusshgQ$CY1u<*NO_(YHN9MaS?!pg#}YLI|9o$ zZlGxzx~|Kf2)z98A*52oYHA1s0t&!gMWJzZ75n4I)YsRWx@H764a`I$VJQOkQj>?m zVE~R_y2No1Mn=rJ`ed?*m6MH|H~D^RYi|Sup5Brb)=qU2exZ@Yf6a01W9>1)t zP(M3s>UzCiT3T9mcEKauop17O=POJ`Uwc+)8L4;e%PQu$1DxRt2&itQyE1(2E->!U0e*fVknH%-X(3$t7y}eyDO_M8) zjUpiN>(@ooG#PGcDsdFQTQU*LmQh1zz69Xd?I61SM4nb45HS0?t`nFz%TSkba~}IJ zSoT0t%9c@CSE}B20!`CQtwbVWo&x|QBO?R?XLofC+pU5V2HMEkVv$J1w8{_(L%7xG zwx);7dSVwvX~9)wo=7A@AP`WpN$lJomMW_P5wKFp*e#@QP%&2OvlI#2zf?vQy~@i) z!d{eh5%6M1Z2q`4pZ4Mg`QXuLlxQ@X15;>hH$F?0V!6pO6bi{uC?pPtLp&ajcsw2f zNcSBMhop6^`n3Ebd2V1pL`3c6ICY?$cc;z9=y2NPlk21XNO{2*OSkPqSJqKtkKNfQSK2NQ8&P;lUai6fZ6 zq%r4Ez#c_&(5uIrG|e^dJ-=V>-rgTr&G4i}rYGS+nl+)#oFqzvCbXHML{}Ozq0O90 z^h}som}%0)(kv4uVl(0ZjE&+lAmeqk2r!8v)&?ggu4^KmcuL=d2e{w{FPh^AlyBAY z2>_Mj5w&_ILb|NoD4Oef2Ch>;V4~^%h)yDGs0>b_L?*X}BfcV}Y6TfKp%|#27iIon zW7^K-jsO_F_?%wcvAh4O(#B!{6ro$br`_rWeX=9E&(RTZ3MIvaV!&^F0K;iJj}JiS zaflFu2y8amt==@Rvz?~h>i?Mo+BE>b)&VF}u;=WM&2DjanC9yCGeQw!z*F~a{uC@M z-VCKoYN8*A_>E13c#n|6;+m1{Zx~ZN(S^wBQfzfIvbr5xJ&;&ElC9#Q^nZ`#b2|M0 n#bmaFm8)5}gXu_uX&}A&i=&+GgXOlNifKnj~QASzHv=tK=2|GDpAn1|y2gL@@LUL5nP-}$%# z_zte_KMFql-xh{>eGacbF#&|vw=2?cH)y!PamWk>rC6WFWLC6RR9~j(|wSY&rq51>C%~gJJFnfRpy~((oJsp@`z;)~GgdCfi^F zv^cr(UK$Rmb0BG2tuBIDpRn`6m`1h9-q8UU&L;+6E^#K?e82V>2s4rohj|?+XKC=g zqXS;Q_(`MM+D=6H)kS!hZ0otV$Ls~nImeQg&P|~q;MwZpsEB6dhiC9L#Y3|QC!<_C<>lkQtZl5Yx7(-PxQyC_ z>mXcbYI9?Na>)^|=Ieaeb~!()Dna5vrshTf$nZg4B|gB WQc3H!`QrZo0000(;vkqY6u15b`J?(5bhLEr;2=r{i$Mxe=v3p-ty{)( zNKcbX?nf_Y+Xv;~df)dxxeIp};4l@EJ$i-&cqL{bls)M{Vh}>vvoO#lh9HzZnSr4R zh^;+MLTG!LfN1Q|#9;eci*FR7*T0cJu!82}CjdhL!%E&!eaX!Y5<_uZ;?UZ@`qHsWLnr)!t`sc1j-&;|hVWnd)=l-075>;u)kyDp3Z#mTY)Cp&xu zGmxJLbW1LVvk<)gjSm12-fqYNpy6(*S9R*ka)l5z0EKY(FWBkYih&HQ3t+~FV2GG- z7wEiOXrH!}gNs_PGNcy-m?8gR2Eoa=*DKi}UP^a+Ew3rq{f7x#u$ND>Vu5M>ho=Gk Y0D4{LE&xuH8UO$Q07*qoM6N<$f>nFi2><{9 literal 0 HcmV?d00001 diff --git a/Resources/Textures/Interface/Misc/markers.rsi/spawner_shotgun_ammo.png b/Resources/Textures/Interface/Misc/markers.rsi/spawner_shotgun_ammo.png new file mode 100644 index 0000000000000000000000000000000000000000..2c341f221888cff724d484873717cf11cfa63ba1 GIT binary patch literal 469 zcmV;`0V@89P)Z-VslDB%hO~cHm46L zbeKrYsnbMiE*&No=2(P4TZ(CjwBJWb2-AyisVvm0rk01%-J>0IS=w7N;lB zxPfw>M7>irmHgW&E=X%dCIB!l!*?aiSMP(dnXHehSP7g}vgC?2N@nt2i-BcU?Q$@wI`n=zHUAeMo`af~bj%I(@T+sbi2=yOrb1K_@oC>&;D z3Ch^}mp3I=VL*6rOW8V_u6t4s&9*a-t{c+o4?8g+JZJ`{5V8w|2SVvwP9r)QLD>5s zAc2{1sdA0|r+AW8xoJ%deR{pu3jAsiA%VF!t*cmIC?600000 LNkvXXu0mjfO3==t literal 0 HcmV?d00001 diff --git a/Resources/Textures/Interface/Misc/markers.rsi/spawner_trash.png b/Resources/Textures/Interface/Misc/markers.rsi/spawner_trash.png index b92ba56c3d6787c907e6c6b2da408cc8075117c5..0a685dc041cc75a123b97bf270d728a93d0f68b1 100644 GIT binary patch delta 527 zcmV+q0`UEp1*Zg%BYy$zNkl6%!`2YxYUg6-S{p5~Ilr0TWGG!gN1ztTgpP-v*G{o}p2=??W2?cyTh zcSCTu!&ag!h<`;5bp>tUHCyU7&iCM>uDE)4i1Ube*j*2l1&Pp56e)`g()_}Pw`C_j zh{)$kR>1_b$ZQ{FW-Aeq^}fBgb$h>;;B)(Xh8#d-C1Obr)bzpvn5So?RiciNDC)Y+ z&pf(qPh*seNX4RE#Te4vMH?>G*N43fcWV!G;Yk%F`F~#MotPeH1p^{Vb~tD+!z|f` zh#o=D3b-IwD9gH$19%&iKAtlvZB&SYh>;i*_JPZdWly|JIv9)18+O7$2%v`*Zfrzn zHn5k-zj`3~@zcxqkDdo-iFog^{Kka$|Ck&neB{^ca>8u;3Cs!h4^Fe>y;&1L R82|tP00>D%PDHLkV1fZG`DFkA delta 639 zcmV-_0)YLe1eXPnBYyw^b5ch_0Itp)=>Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi z!vFvd!vV){sAK>D0xU^HK~z{r%~c6d=8<&L@Mo%=JVN zE64J3S2*qjamV)qSBT69*Un20x-N=W{0>4%HwbfvL4K8mcLc$w*&mC4mFEVcVBwkc zUl))w&%Dx-m_jav_vbisG6!ru+-a)|T-!JZfLMdbO9UlIDTD{%GlRn_dwwQUc-#7b zE~L!{@`45hPJaTh1X>Uv7u*!60t;?SeFcNS%FCpIr1FQImPl~SYmJ*T1A*CyZstwP2ucjv57v6f0?P)R1#(&=sDXg#M8h>TCb*x_6G<>r z`u)J}wlQ204}0Mx118QYw_ugE&NyDM&zZvp@TiQTjV#4KeShL0fJPku(`@5LX(B~S zb{)Iglz9AZP~cdQ8RIxE!v^T^`8&}5u&j+|O-B!&9r+9daVBnp1cvnePH145hSt}b z(0n_BI2P}_#bu6h$2J32f{J0Taq)B94dRw~#V}{%a9g}$n6o-OAzm@e`J{NoUvS=r ZbKeHpFo>>3@002ovPDHLkV1m^^AqfBg diff --git a/Resources/Textures/Interface/Misc/markers.rsi/spawner_xenoai.png b/Resources/Textures/Interface/Misc/markers.rsi/spawner_xenoai.png index 7b0db41b65adc0da4275491af5488b64b25924bf..4f64d33046accca6bfafa294920ee273b4af692d 100644 GIT binary patch delta 1091 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 From d55ace72e46cc6b4485e3dd51f70b2ea9c3ccf0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Aguilera=20Puerto?= Date: Sun, 16 Aug 2020 18:24:36 +0200 Subject: [PATCH 08/21] Fix duplicate prototype, increase most conditional spawners' chance of spawning --- .../Markers/gamemode_conditional_spawners.yml | 36 ++++--------------- 1 file changed, 7 insertions(+), 29 deletions(-) diff --git a/Resources/Prototypes/Entities/Effects/Markers/gamemode_conditional_spawners.yml b/Resources/Prototypes/Entities/Effects/Markers/gamemode_conditional_spawners.yml index b203903616..1fe1cb94e2 100644 --- a/Resources/Prototypes/Entities/Effects/Markers/gamemode_conditional_spawners.yml +++ b/Resources/Prototypes/Entities/Effects/Markers/gamemode_conditional_spawners.yml @@ -71,7 +71,7 @@ - PistolMolly - PistolOlivaw - PistolPaco - chance: 0.75 + chance: 0.95 gameRules: - RuleSuspicion @@ -96,7 +96,7 @@ - ToolboxEmergency - CrowbarRed - Stunbaton - chance: 0.75 + chance: 0.95 gameRules: - RuleSuspicion @@ -118,7 +118,7 @@ - RevolverDeckard - RevolverInspector - RevolverMateba - chance: 0.75 + chance: 0.95 gameRules: - RuleSuspicion @@ -144,7 +144,7 @@ - ShotgunRegulator - ShotgunPump - ShotgunSawn - chance: 0.75 + chance: 0.95 gameRules: - RuleSuspicion @@ -169,7 +169,7 @@ - SmgStraylight - SmgWt550 - SmgZoric - chance: 0.75 + chance: 0.95 gameRules: - RuleSuspicion @@ -191,7 +191,7 @@ - SniperBoltGun - SniperBoltGunWood - SniperHeavy - chance: 0.75 + chance: 0.95 gameRules: - RuleSuspicion @@ -217,7 +217,7 @@ - LaserCannon - XrayCannon - TaserGun - chance: 0.75 + chance: 0.85 gameRules: - RuleSuspicion @@ -268,28 +268,6 @@ gameRules: - RuleSuspicion -- type: entity - name: Suspicion Sniper Spawner - id: SuspicionSniperSpawner - parent: BaseConditionalSpawner - components: - - type: Sprite - netsync: false - visible: false - sprite: Interface/Misc/markers.rsi - state: spawner_sniper - - type: Icon - sprite: Interface/Misc/markers.rsi - state: spawner_sniper - - type: ConditionalSpawner - prototypes: - - SniperBoltGun - - SniperBoltGunWood - - SniperHeavy - chance: 0.75 - gameRules: - - RuleSuspicion - - type: entity name: Suspicion Rifle Ammo Spawner id: SuspicionRifleMagazineSpawner From fa49eb58953ab5053b4e440d280c111ad78ec967 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Aguilera=20Puerto?= Date: Sun, 16 Aug 2020 18:35:47 +0200 Subject: [PATCH 09/21] Adds more weapon/ammo SSS spawners to Saltern. --- Resources/Maps/saltern.yml | 318 ++++++++++++++++++++++++++++++++++++- 1 file changed, 312 insertions(+), 6 deletions(-) diff --git a/Resources/Maps/saltern.yml b/Resources/Maps/saltern.yml index e387f022c3..f3ccd2b9b1 100644 --- a/Resources/Maps/saltern.yml +++ b/Resources/Maps/saltern.yml @@ -33466,10 +33466,10 @@ entities: rot: -1.5707963267948966 rad type: Transform - uid: 2877 - type: TrashSpawner + type: SuspicionPistolMagazineSpawner components: - parent: 15 - pos: -21.5,-12.5 + pos: -35.5,0.5 rot: -1.5707963267948966 rad type: Transform - uid: 2878 @@ -37344,7 +37344,6 @@ entities: pos: -13.672081,21.719378 rot: -1.5707963267948966 rad type: Transform - - type: BatteryBarrel - anchored: False type: Collidable - containers: @@ -37371,7 +37370,6 @@ entities: pos: -14.515831,21.735003 rot: -1.5707963267948966 rad type: Transform - - type: BatteryBarrel - anchored: False type: Collidable - containers: @@ -37840,10 +37838,10 @@ entities: type: Robust.Server.GameObjects.Components.Container.Container type: ContainerContainer - uid: 3282 - type: metal_wall + type: SuspicionPistolSpawner components: - parent: 15 - pos: 13.293709,-8.309891 + pos: 8.5,-4.5 rot: -1.5707963267948966 rad type: Transform - uid: 3283 @@ -38099,4 +38097,312 @@ entities: type: Transform - anchored: False type: Collidable +- uid: 3310 + type: SuspicionShotgunMagazineSpawner + components: + - parent: 15 + pos: -6.5,-3.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3311 + type: SuspicionShotgunMagazineSpawner + components: + - parent: 15 + pos: -7.5,-3.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3312 + type: SuspicionShotgunSpawner + components: + - parent: 15 + pos: -7.5,-6.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3313 + type: SuspicionSniperSpawner + components: + - parent: 15 + pos: -8.5,-12.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3314 + type: SuspicionRifleMagazineSpawner + components: + - parent: 15 + pos: -13.5,-6.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3315 + type: SuspicionGrenadesSpawner + components: + - parent: 15 + pos: 15.5,-0.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3316 + type: SuspicionGrenadesSpawner + components: + - parent: 15 + pos: 18.5,1.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3317 + type: SuspicionHitscanSpawner + components: + - parent: 15 + pos: 25.5,0.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3318 + type: SuspicionGrenadesSpawner + components: + - parent: 15 + pos: 0.5,-15.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3319 + type: SuspicionGrenadesSpawner + components: + - parent: 15 + pos: -8.5,-17.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3320 + type: SuspicionMagnumMagazineSpawner + components: + - parent: 15 + pos: 14.5,-2.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3321 + type: SuspicionRevolverSpawner + components: + - parent: 15 + pos: 15.5,-3.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3322 + type: SuspicionMagnumMagazineSpawner + components: + - parent: 15 + pos: 16.5,7.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3323 + type: SuspicionSMGSpawner + components: + - parent: 15 + pos: -7.5,8.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3324 + type: SuspicionRifleMagazineSpawner + components: + - parent: 15 + pos: -7.5,7.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3325 + type: SuspicionShotgunSpawner + components: + - parent: 15 + pos: -29.5,-5.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3326 + type: SuspicionShotgunMagazineSpawner + components: + - parent: 15 + pos: -30.5,-4.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3327 + type: SuspicionShotgunMagazineSpawner + components: + - parent: 15 + pos: -29.5,-4.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3328 + type: SuspicionPistolMagazineSpawner + components: + - parent: 15 + pos: -3.5,0.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3329 + type: SuspicionPistolMagazineSpawner + components: + - parent: 15 + pos: -10.5,1.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3330 + type: SuspicionPistolMagazineSpawner + components: + - parent: 15 + pos: -9.5,6.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3331 + type: SuspicionPistolMagazineSpawner + components: + - parent: 15 + pos: -29.5,9.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3332 + type: SuspicionPistolMagazineSpawner + components: + - parent: 15 + pos: -31.5,13.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3333 + type: SuspicionPistolSpawner + components: + - parent: 15 + pos: -5.5,24.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3334 + type: SuspicionPistolSpawner + components: + - parent: 15 + pos: -10.5,-0.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3335 + type: SuspicionHitscanSpawner + components: + - parent: 15 + pos: -14.5,18.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3336 + type: SuspicionRevolverSpawner + components: + - parent: 15 + pos: -14.5,19.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3337 + type: SuspicionPistolSpawner + components: + - parent: 15 + pos: -13.5,18.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3338 + type: SuspicionRifleSpawner + components: + - parent: 15 + pos: -13.5,19.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3339 + type: SuspicionSMGSpawner + components: + - parent: 15 + pos: -13.5,20.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3340 + type: SuspicionShotgunSpawner + components: + - parent: 15 + pos: -12.5,20.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3341 + type: SuspicionSniperSpawner + components: + - parent: 15 + pos: -12.5,19.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3342 + type: SuspicionLaunchersSpawner + components: + - parent: 15 + pos: -12.5,18.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3343 + type: SuspicionGrenadesSpawner + components: + - parent: 15 + pos: -11.5,20.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3344 + type: SuspicionGrenadesSpawner + components: + - parent: 15 + pos: -11.5,19.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3345 + type: SuspicionGrenadesSpawner + components: + - parent: 15 + pos: -11.5,18.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3346 + type: SuspicionShotgunMagazineSpawner + components: + - parent: 15 + pos: -35.5,-7.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3347 + type: SuspicionShotgunMagazineSpawner + components: + - parent: 15 + pos: -35.5,-6.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3348 + type: SuspicionRifleMagazineSpawner + components: + - parent: 15 + pos: -35.5,-4.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3349 + type: SuspicionRifleMagazineSpawner + components: + - parent: 15 + pos: -35.5,-3.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3350 + type: SuspicionPistolMagazineSpawner + components: + - parent: 15 + pos: -35.5,-0.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3351 + type: SuspicionShotgunMagazineSpawner + components: + - parent: 15 + pos: -23.5,-13.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3352 + type: SuspicionShotgunSpawner + components: + - parent: 15 + pos: -15.5,-14.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3353 + type: SuspicionHitscanSpawner + components: + - parent: 15 + pos: -15.5,-11.5 + rot: -1.5707963267948966 rad + type: Transform ... From 772eb2c966afee091826adf6fa3ec354081eaa6f Mon Sep 17 00:00:00 2001 From: DrSmugleaf Date: Sun, 16 Aug 2020 18:41:16 +0200 Subject: [PATCH 10/21] Fix SSS role being repeated in the examine tooltip (#1714) --- .../Suspicion/SuspicionRoleComponent.cs | 42 +++++++++++++++++++ .../GamePresets/PresetSuspicion.cs | 5 ++- .../GameTicking/GameRules/RuleSuspicion.cs | 24 +---------- 3 files changed, 48 insertions(+), 23 deletions(-) create mode 100644 Content.Server/GameObjects/Components/Suspicion/SuspicionRoleComponent.cs diff --git a/Content.Server/GameObjects/Components/Suspicion/SuspicionRoleComponent.cs b/Content.Server/GameObjects/Components/Suspicion/SuspicionRoleComponent.cs new file mode 100644 index 0000000000..833169a223 --- /dev/null +++ b/Content.Server/GameObjects/Components/Suspicion/SuspicionRoleComponent.cs @@ -0,0 +1,42 @@ +using Content.Server.GameObjects.Components.Mobs; +using Content.Server.Mobs.Roles; +using Content.Shared.GameObjects.EntitySystems; +using Robust.Shared.GameObjects; +using Robust.Shared.Localization; +using Robust.Shared.Utility; + +namespace Content.Server.GameObjects.Components.Suspicion +{ + [RegisterComponent] + public class SuspicionRoleComponent : Component, IExamine + { + public override string Name => "SuspicionRole"; + + public bool IsDead() + { + return Owner.TryGetComponent(out SpeciesComponent species) && + species.CurrentDamageState is DeadState; + } + + public bool IsTraitor() + { + return Owner.TryGetComponent(out MindComponent mind) && + mind.HasMind && + mind.Mind!.HasRole(); + } + + void IExamine.Examine(FormattedMessage message, bool inDetailsRange) + { + if (!IsDead()) + { + return; + } + + var tooltip = IsTraitor() + ? Loc.GetString($"They were a [color=red]traitor[/color]!") + : Loc.GetString($"They were an [color=green]innocent[/color]!"); + + message.AddMarkup(tooltip); + } + } +} diff --git a/Content.Server/GameTicking/GamePresets/PresetSuspicion.cs b/Content.Server/GameTicking/GamePresets/PresetSuspicion.cs index bd2f43a13d..1f6e0437ca 100644 --- a/Content.Server/GameTicking/GamePresets/PresetSuspicion.cs +++ b/Content.Server/GameTicking/GamePresets/PresetSuspicion.cs @@ -10,11 +10,12 @@ using Robust.Shared.Prototypes; using Robust.Shared.Random; using System.Collections.Generic; using System.Linq; +using Content.Server.GameObjects.Components.Suspicion; using Content.Shared.Roles; +using Robust.Shared.GameObjects; using Robust.Shared.Log; using Robust.Shared.Maths; - namespace Content.Server.GameTicking.GamePresets { public class PresetSuspicion : GamePreset @@ -54,6 +55,8 @@ namespace Content.Server.GameTicking.GamePresets { prefList.Add(player); } + + player.AttachedEntity?.EnsureComponent(); } var numTraitors = FloatMath.Clamp(readyPlayers.Count % PlayersPerTraitor, diff --git a/Content.Server/GameTicking/GameRules/RuleSuspicion.cs b/Content.Server/GameTicking/GameRules/RuleSuspicion.cs index 34ddc50f78..a3d830412e 100644 --- a/Content.Server/GameTicking/GameRules/RuleSuspicion.cs +++ b/Content.Server/GameTicking/GameRules/RuleSuspicion.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Threading; using Content.Server.GameObjects.Components.Mobs; using Content.Server.Interfaces.Chat; @@ -7,7 +7,6 @@ using Content.Server.Mobs.Roles; using Content.Server.Players; using Robust.Server.Interfaces.Player; using Robust.Shared.GameObjects; -using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.IoC; using Timer = Robust.Shared.Timers.Timer; @@ -24,7 +23,6 @@ namespace Content.Server.GameTicking.GameRules #pragma warning disable 649 [Dependency] private readonly IPlayerManager _playerManager; [Dependency] private readonly IChatManager _chatManager; - [Dependency] private readonly IEntityManager _entityManager; [Dependency] private readonly IGameTicker _gameTicker; #pragma warning restore 649 @@ -32,28 +30,9 @@ namespace Content.Server.GameTicking.GameRules public override void Added() { - _entityManager.EventBus.SubscribeEvent(EventSource.Local, this, _onMobDamageStateChanged); - Timer.SpawnRepeating(DeadCheckDelay, _checkWinConditions, _checkTimerCancel.Token); } - private void _onMobDamageStateChanged(MobDamageStateChangedMessage message) - { - var owner = message.Species.Owner; - - if (!(message.Species.CurrentDamageState is DeadState)) - return; - - if (!owner.TryGetComponent(out var mind)) - return; - - if (!mind.HasMind) - return; - - message.Species.Owner.Description += - mind.Mind.HasRole() ? "\nThey were a traitor!" : "\nThey were an innocent!"; - } - public override void Removed() { base.Removed(); @@ -78,6 +57,7 @@ namespace Content.Server.GameTicking.GameRules { continue; } + if (playerSession.ContentData().Mind.HasRole()) traitorsAlive++; else From dbeb89a5e54ed58bfb36fd50c0f032819709033e Mon Sep 17 00:00:00 2001 From: DrSmugleaf Date: Sun, 16 Aug 2020 18:51:21 +0200 Subject: [PATCH 11/21] Fix pulling not stopping when going into a container (#1712) --- .../Components/GUI/HandsComponent.cs | 55 ++++++++++--------- .../EntitySystems/Click/InteractionSystem.cs | 1 + Content.Server/GlobalVerbs/PullingVerb.cs | 1 + .../Components/Items/SharedHandsComponent.cs | 24 +++++++- .../EntitySystems/SharedMoverSystem.cs | 1 + .../Physics/{ => Pull}/PullController.cs | 54 ++++++++++++++++-- Content.Shared/Physics/Pull/PullMessage.cs | 19 +++++++ .../Physics/Pull/PullStartedMessage.cs | 12 ++++ .../Physics/Pull/PullStoppedMessage.cs | 12 ++++ 9 files changed, 146 insertions(+), 33 deletions(-) rename Content.Shared/Physics/{ => Pull}/PullController.cs (68%) create mode 100644 Content.Shared/Physics/Pull/PullMessage.cs create mode 100644 Content.Shared/Physics/Pull/PullStartedMessage.cs create mode 100644 Content.Shared/Physics/Pull/PullStoppedMessage.cs diff --git a/Content.Server/GameObjects/Components/GUI/HandsComponent.cs b/Content.Server/GameObjects/Components/GUI/HandsComponent.cs index f5403a6928..a7c0c49289 100644 --- a/Content.Server/GameObjects/Components/GUI/HandsComponent.cs +++ b/Content.Server/GameObjects/Components/GUI/HandsComponent.cs @@ -13,7 +13,7 @@ using Content.Shared.GameObjects.Components.Items; using Content.Shared.GameObjects.Components.Mobs; using Content.Shared.GameObjects.EntitySystems; using Content.Shared.Health.BodySystem; -using Content.Shared.Physics; +using Content.Shared.Physics.Pull; using Robust.Server.GameObjects; using Robust.Server.GameObjects.Components.Container; using Robust.Server.GameObjects.EntitySystemMessages; @@ -547,15 +547,9 @@ namespace Content.Server.GameObjects.Components.GUI return; } - var isOwnerContained = ContainerHelpers.TryGetContainer(Owner, out var ownerContainer); - var isPullableContained = ContainerHelpers.TryGetContainer(pullable.Owner, out var pullableContainer); - - if (isOwnerContained || isPullableContained) + if (!Owner.IsInSameOrNoContainer(pullable.Owner)) { - if (ownerContainer != pullableContainer) - { - return; - } + return; } if (IsPulling) @@ -564,10 +558,8 @@ namespace Content.Server.GameObjects.Components.GUI } PulledObject = pullable.Owner.GetComponent(); - var controller = PulledObject!.EnsureController(); - controller!.StartPull(Owner.GetComponent()); - - AddPullingStatuses(); + var controller = PulledObject.EnsureController(); + controller.StartPull(Owner.GetComponent()); } public void MovePulledObject(GridCoordinates puller, GridCoordinates to) @@ -579,6 +571,27 @@ namespace Content.Server.GameObjects.Components.GUI } } + public override void HandleMessage(ComponentMessage message, IComponent? component) + { + base.HandleMessage(message, component); + + if (!(message is PullMessage pullMessage) || + pullMessage.Puller.Owner != Owner) + { + return; + } + + switch (message) + { + case PullStartedMessage msg: + AddPullingStatuses(msg.Pulled.Owner); + break; + case PullStoppedMessage msg: + RemovePullingStatuses(msg.Pulled.Owner); + break; + } + } + public override void HandleNetworkMessage(ComponentMessage message, INetChannel channel, ICommonSession? session = null) { base.HandleNetworkMessage(message, channel, session); @@ -689,10 +702,9 @@ namespace Content.Server.GameObjects.Components.GUI } } - private void AddPullingStatuses() + private void AddPullingStatuses(IEntity pulled) { - if (PulledObject?.Owner != null && - PulledObject.Owner.TryGetComponent(out ServerStatusEffectsComponent pulledStatus)) + if (pulled.TryGetComponent(out ServerStatusEffectsComponent pulledStatus)) { pulledStatus.ChangeStatusEffectIcon(StatusEffect.Pulled, "/Textures/Interface/StatusEffects/Pull/pulled.png"); @@ -705,10 +717,9 @@ namespace Content.Server.GameObjects.Components.GUI } } - private void RemovePullingStatuses() + private void RemovePullingStatuses(IEntity pulled) { - if (PulledObject?.Owner != null && - PulledObject.Owner.TryGetComponent(out ServerStatusEffectsComponent pulledStatus)) + if (pulled.TryGetComponent(out ServerStatusEffectsComponent pulledStatus)) { pulledStatus.RemoveStatusEffect(StatusEffect.Pulled); } @@ -719,12 +730,6 @@ namespace Content.Server.GameObjects.Components.GUI } } - public override void StopPull() - { - RemovePullingStatuses(); - base.StopPull(); - } - void IBodyPartAdded.BodyPartAdded(BodyPartAddedEventArgs eventArgs) { if (eventArgs.Part.PartType != BodyPartType.Hand) diff --git a/Content.Server/GameObjects/EntitySystems/Click/InteractionSystem.cs b/Content.Server/GameObjects/EntitySystems/Click/InteractionSystem.cs index 478f0123d2..41640a0fac 100644 --- a/Content.Server/GameObjects/EntitySystems/Click/InteractionSystem.cs +++ b/Content.Server/GameObjects/EntitySystems/Click/InteractionSystem.cs @@ -12,6 +12,7 @@ using Content.Shared.GameObjects.EntitySystems; using Content.Shared.Input; using Content.Shared.Interfaces.GameObjects.Components; using Content.Shared.Physics; +using Content.Shared.Physics.Pull; using JetBrains.Annotations; using Robust.Server.GameObjects; using Robust.Server.Interfaces.Player; diff --git a/Content.Server/GlobalVerbs/PullingVerb.cs b/Content.Server/GlobalVerbs/PullingVerb.cs index 0b864eb075..6213d443a5 100644 --- a/Content.Server/GlobalVerbs/PullingVerb.cs +++ b/Content.Server/GlobalVerbs/PullingVerb.cs @@ -4,6 +4,7 @@ using Content.Shared.GameObjects.Components.Items; using Content.Shared.GameObjects.EntitySystems; using Content.Shared.GameObjects.Verbs; using Content.Shared.Physics; +using Content.Shared.Physics.Pull; using Robust.Server.Interfaces.GameObjects; using Robust.Shared.GameObjects.Components; using Robust.Shared.Interfaces.GameObjects; diff --git a/Content.Shared/GameObjects/Components/Items/SharedHandsComponent.cs b/Content.Shared/GameObjects/Components/Items/SharedHandsComponent.cs index 47a15e5f10..02919bcf8e 100644 --- a/Content.Shared/GameObjects/Components/Items/SharedHandsComponent.cs +++ b/Content.Shared/GameObjects/Components/Items/SharedHandsComponent.cs @@ -1,8 +1,9 @@ #nullable enable using System; -using Content.Shared.Physics; +using Content.Shared.Physics.Pull; using Robust.Shared.GameObjects; using Robust.Shared.GameObjects.Components; +using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Serialization; using Robust.Shared.ViewVariables; @@ -26,8 +27,27 @@ namespace Content.Shared.GameObjects.Components.Items { controller.StopPull(); } + } - PulledObject = null; + public override void HandleMessage(ComponentMessage message, IComponent? component) + { + base.HandleMessage(message, component); + + if (!(message is PullMessage pullMessage) || + pullMessage.Puller.Owner != Owner) + { + return; + } + + switch (message) + { + case PullStartedMessage msg: + PulledObject = msg.Pulled; + break; + case PullStoppedMessage _: + PulledObject = null; + break; + } } } diff --git a/Content.Shared/GameObjects/EntitySystems/SharedMoverSystem.cs b/Content.Shared/GameObjects/EntitySystems/SharedMoverSystem.cs index 7c9a4537a2..49f77ad735 100644 --- a/Content.Shared/GameObjects/EntitySystems/SharedMoverSystem.cs +++ b/Content.Shared/GameObjects/EntitySystems/SharedMoverSystem.cs @@ -3,6 +3,7 @@ using System.Diagnostics.CodeAnalysis; using Content.Shared.GameObjects.Components.Items; using Content.Shared.GameObjects.Components.Movement; using Content.Shared.Physics; +using Content.Shared.Physics.Pull; using Robust.Shared.Configuration; using Robust.Shared.GameObjects; using Robust.Shared.GameObjects.Components; diff --git a/Content.Shared/Physics/PullController.cs b/Content.Shared/Physics/Pull/PullController.cs similarity index 68% rename from Content.Shared/Physics/PullController.cs rename to Content.Shared/Physics/Pull/PullController.cs index c0ea728571..02b199a345 100644 --- a/Content.Shared/Physics/PullController.cs +++ b/Content.Shared/Physics/Pull/PullController.cs @@ -1,15 +1,16 @@ #nullable enable using System; -using Content.Shared.GameObjects.Components.Items; using Content.Shared.GameObjects.EntitySystems; +using Robust.Shared.Containers; using Robust.Shared.GameObjects.Components; using Robust.Shared.Interfaces.Map; using Robust.Shared.IoC; using Robust.Shared.Map; using Robust.Shared.Maths; using Robust.Shared.Physics; +using Robust.Shared.Utility; -namespace Content.Shared.Physics +namespace Content.Shared.Physics.Pull { public class PullController : VirtualController { @@ -25,15 +26,50 @@ namespace Content.Shared.Physics public ICollidableComponent? Puller => _puller; - public void StartPull(ICollidableComponent? pull) + public void StartPull(ICollidableComponent puller) { - _puller = pull; + DebugTools.AssertNotNull(puller); + + if (_puller == puller) + { + return; + } + + _puller = puller; + + if (ControlledComponent == null) + { + return; + } + + var message = new PullStartedMessage(this, _puller, ControlledComponent); + + _puller.Owner.SendMessage(null, message); + ControlledComponent.Owner.SendMessage(null, message); } public void StopPull() { + var oldPuller = _puller; + + if (oldPuller == null) + { + return; + } + _puller = null; - ControlledComponent?.TryRemoveController(); + + if (ControlledComponent == null) + { + return; + } + + var message = new PullStoppedMessage(this, oldPuller, ControlledComponent); + + oldPuller.Owner.SendMessage(null, message); + ControlledComponent.Owner.SendMessage(null, message); + + ControlledComponent.TryRemoveController(); } public void TryMoveTo(GridCoordinates from, GridCoordinates to) @@ -68,12 +104,18 @@ namespace Content.Shared.Physics return; } + if (!_puller.Owner.IsInSameOrNoContainer(ControlledComponent.Owner)) + { + StopPull(); + return; + } + // Are we outside of pulling range? var dist = _puller.Owner.Transform.WorldPosition - ControlledComponent.Owner.Transform.WorldPosition; if (dist.Length > DistBeforeStopPull) { - _puller.Owner.GetComponent().StopPull(); + StopPull(); } else if (_movingTo.HasValue) { diff --git a/Content.Shared/Physics/Pull/PullMessage.cs b/Content.Shared/Physics/Pull/PullMessage.cs new file mode 100644 index 0000000000..811eae404e --- /dev/null +++ b/Content.Shared/Physics/Pull/PullMessage.cs @@ -0,0 +1,19 @@ +using Robust.Shared.GameObjects; +using Robust.Shared.GameObjects.Components; + +namespace Content.Shared.Physics.Pull +{ + public class PullMessage : ComponentMessage + { + public readonly PullController Controller; + public readonly ICollidableComponent Puller; + public readonly ICollidableComponent Pulled; + + protected PullMessage(PullController controller, ICollidableComponent puller, ICollidableComponent pulled) + { + Controller = controller; + Puller = puller; + Pulled = pulled; + } + } +} diff --git a/Content.Shared/Physics/Pull/PullStartedMessage.cs b/Content.Shared/Physics/Pull/PullStartedMessage.cs new file mode 100644 index 0000000000..263c0b8db1 --- /dev/null +++ b/Content.Shared/Physics/Pull/PullStartedMessage.cs @@ -0,0 +1,12 @@ +using Robust.Shared.GameObjects.Components; + +namespace Content.Shared.Physics.Pull +{ + public class PullStartedMessage : PullMessage + { + public PullStartedMessage(PullController controller, ICollidableComponent puller, ICollidableComponent pulled) : + base(controller, puller, pulled) + { + } + } +} diff --git a/Content.Shared/Physics/Pull/PullStoppedMessage.cs b/Content.Shared/Physics/Pull/PullStoppedMessage.cs new file mode 100644 index 0000000000..c018558341 --- /dev/null +++ b/Content.Shared/Physics/Pull/PullStoppedMessage.cs @@ -0,0 +1,12 @@ +using Robust.Shared.GameObjects.Components; + +namespace Content.Shared.Physics.Pull +{ + public class PullStoppedMessage : PullMessage + { + public PullStoppedMessage(PullController controller, ICollidableComponent puller, ICollidableComponent pulled) : + base(controller, puller, pulled) + { + } + } +} From 4ef8bc962e3f34ee3d4a49f445d4aa81e9bee960 Mon Sep 17 00:00:00 2001 From: Exp Date: Sun, 16 Aug 2020 19:31:59 +0200 Subject: [PATCH 12/21] Fix RoundEndMsg being retarded and writing 0 as length (#1721) --- Content.Shared/SharedGameTicker.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Content.Shared/SharedGameTicker.cs b/Content.Shared/SharedGameTicker.cs index cd16b79191..5952c35f3e 100644 --- a/Content.Shared/SharedGameTicker.cs +++ b/Content.Shared/SharedGameTicker.cs @@ -214,7 +214,7 @@ namespace Content.Shared buffer.Write(RoundDuration.Seconds); - buffer.Write(PlayerCount); + buffer.Write(AllPlayersEndInfo.Count); foreach(var playerEndInfo in AllPlayersEndInfo) { buffer.Write(playerEndInfo.PlayerOOCName); From ac9d40b606dabcd48a0477d348cb6f45a10d4809 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Aguilera=20Puerto?= Date: Sun, 16 Aug 2020 19:35:50 +0200 Subject: [PATCH 13/21] Fix suspicion crash on forcing 0 players readied --- Content.Server/GameTicking/GamePresets/PresetSuspicion.cs | 6 ++++++ Content.Shared/SharedGameTicker.cs | 6 +++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/Content.Server/GameTicking/GamePresets/PresetSuspicion.cs b/Content.Server/GameTicking/GamePresets/PresetSuspicion.cs index 1f6e0437ca..fc09cc14a3 100644 --- a/Content.Server/GameTicking/GamePresets/PresetSuspicion.cs +++ b/Content.Server/GameTicking/GamePresets/PresetSuspicion.cs @@ -41,6 +41,12 @@ namespace Content.Server.GameTicking.GamePresets return false; } + if (readyPlayers.Count == 0) + { + _chatManager.DispatchServerAnnouncement($"No players readied up! Can't start Suspicion."); + return false; + } + var list = new List(readyPlayers); var prefList = new List(); diff --git a/Content.Shared/SharedGameTicker.cs b/Content.Shared/SharedGameTicker.cs index 5952c35f3e..846598dfbf 100644 --- a/Content.Shared/SharedGameTicker.cs +++ b/Content.Shared/SharedGameTicker.cs @@ -176,7 +176,7 @@ namespace Content.Shared public TimeSpan RoundDuration; - public uint PlayerCount; + public int PlayerCount; public List AllPlayersEndInfo; @@ -189,9 +189,9 @@ namespace Content.Shared var seconds = buffer.ReadInt32(); RoundDuration = new TimeSpan(hours, mins, seconds); - PlayerCount = buffer.ReadUInt32(); + PlayerCount = buffer.ReadInt32(); AllPlayersEndInfo = new List(); - for(var i = 0; i < PlayerCount + 1; i++) + for(var i = 0; i < PlayerCount; i++) { var readPlayerData = new RoundEndPlayerInfo { From 3293dc44599b1da75d6e41b414870aafd6b18d84 Mon Sep 17 00:00:00 2001 From: Exp Date: Sun, 16 Aug 2020 20:54:33 +0200 Subject: [PATCH 14/21] -Move pointing to common (#1718) -Remove some duplicate keyfunctions --- Content.Client/Input/ContentContexts.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Content.Client/Input/ContentContexts.cs b/Content.Client/Input/ContentContexts.cs index 1250627a4f..89ddd64268 100644 --- a/Content.Client/Input/ContentContexts.cs +++ b/Content.Client/Input/ContentContexts.cs @@ -19,6 +19,7 @@ namespace Content.Client.Input common.AddFunction(ContentKeyFunctions.OpenTutorial); common.AddFunction(ContentKeyFunctions.TakeScreenshot); common.AddFunction(ContentKeyFunctions.TakeScreenshotNoUI); + common.AddFunction(ContentKeyFunctions.Point); var human = contexts.GetContext("human"); human.AddFunction(ContentKeyFunctions.SwapHands); @@ -37,9 +38,6 @@ namespace Content.Client.Input human.AddFunction(ContentKeyFunctions.MouseMiddle); human.AddFunction(ContentKeyFunctions.ToggleCombatMode); human.AddFunction(ContentKeyFunctions.WideAttack); - human.AddFunction(ContentKeyFunctions.Point); - human.AddFunction(ContentKeyFunctions.TryPullObject); - human.AddFunction(ContentKeyFunctions.MovePulledObject); var ghost = contexts.New("ghost", "common"); ghost.AddFunction(EngineKeyFunctions.MoveUp); From 9fb6afd08bca4e0992918aef3ff6d418a9522916 Mon Sep 17 00:00:00 2001 From: DrSmugleaf Date: Sun, 16 Aug 2020 21:08:05 +0200 Subject: [PATCH 15/21] Fix pulled physics objects not being woken up when the puller moves (#1720) --- .../Components/GUI/HandsComponent.cs | 20 +++++++++++++++++++ Content.Shared/Physics/Pull/PullController.cs | 6 ++++++ 2 files changed, 26 insertions(+) diff --git a/Content.Server/GameObjects/Components/GUI/HandsComponent.cs b/Content.Server/GameObjects/Components/GUI/HandsComponent.cs index a7c0c49289..6336845970 100644 --- a/Content.Server/GameObjects/Components/GUI/HandsComponent.cs +++ b/Content.Server/GameObjects/Components/GUI/HandsComponent.cs @@ -20,6 +20,7 @@ using Robust.Server.GameObjects.EntitySystemMessages; using Robust.Shared.Containers; using Robust.Shared.GameObjects; using Robust.Shared.GameObjects.Components; +using Robust.Shared.GameObjects.Components.Transform; using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.Network; using Robust.Shared.IoC; @@ -571,6 +572,21 @@ namespace Content.Server.GameObjects.Components.GUI } } + private void MoveEvent(MoveEvent moveEvent) + { + if (moveEvent.Sender != Owner) + { + return; + } + + if (!IsPulling) + { + return; + } + + PulledObject!.WakeBody(); + } + public override void HandleMessage(ComponentMessage message, IComponent? component) { base.HandleMessage(message, component); @@ -584,9 +600,13 @@ namespace Content.Server.GameObjects.Components.GUI switch (message) { case PullStartedMessage msg: + Owner.EntityManager.EventBus.SubscribeEvent(EventSource.Local, this, MoveEvent); + AddPullingStatuses(msg.Pulled.Owner); break; case PullStoppedMessage msg: + Owner.EntityManager.EventBus.UnsubscribeEvent(EventSource.Local, this); + RemovePullingStatuses(msg.Pulled.Owner); break; } diff --git a/Content.Shared/Physics/Pull/PullController.cs b/Content.Shared/Physics/Pull/PullController.cs index 02b199a345..8bb76473be 100644 --- a/Content.Shared/Physics/Pull/PullController.cs +++ b/Content.Shared/Physics/Pull/PullController.cs @@ -42,6 +42,8 @@ namespace Content.Shared.Physics.Pull return; } + ControlledComponent.WakeBody(); + var message = new PullStartedMessage(this, _puller, ControlledComponent); _puller.Owner.SendMessage(null, message); @@ -64,6 +66,8 @@ namespace Content.Shared.Physics.Pull return; } + ControlledComponent.WakeBody(); + var message = new PullStoppedMessage(this, oldPuller, ControlledComponent); oldPuller.Owner.SendMessage(null, message); @@ -86,6 +90,8 @@ namespace Content.Shared.Physics.Pull return; } + ControlledComponent.WakeBody(); + var dist = _puller.Owner.Transform.GridPosition.Position - to.Position; if (Math.Sqrt(dist.LengthSquared) > DistBeforeStopPull || From da23890eabbddc8a1888d377c72f401b1157f778 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Aguilera=20Puerto?= Date: Sun, 16 Aug 2020 21:09:14 +0200 Subject: [PATCH 16/21] Update submodule --- RobustToolbox | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RobustToolbox b/RobustToolbox index 1934428c95..688ec89d43 160000 --- a/RobustToolbox +++ b/RobustToolbox @@ -1 +1 @@ -Subproject commit 1934428c95d44210cfc9c155c7d15405d4a374c4 +Subproject commit 688ec89d43b707a9f6c26c2ac348ee019d9a33e6 From 9dc884fa4650a3277ef13cc71805289c21c89922 Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Sun, 16 Aug 2020 23:36:21 +0200 Subject: [PATCH 17/21] Update submodule. --- RobustToolbox | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RobustToolbox b/RobustToolbox index 688ec89d43..c72ea7194e 160000 --- a/RobustToolbox +++ b/RobustToolbox @@ -1 +1 @@ -Subproject commit 688ec89d43b707a9f6c26c2ac348ee019d9a33e6 +Subproject commit c72ea7194e08bba42371a06e353bcd79f5a7c7cc From d04ad6ec85ad924e07204d2e87f53d8f5b2ee2a1 Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Sun, 16 Aug 2020 23:36:50 +0200 Subject: [PATCH 18/21] Request window attention when round starts/restarts. --- .../GameTicking/ClientGameTicker.cs | 6 +++++ Content.Server/GameTicking/GameTicker.cs | 14 ++++++++++ Content.Server/Players/PlayerSessionExt.cs | 14 ++++++++++ .../NetMessages/MsgRequestWindowAttention.cs | 27 +++++++++++++++++++ Content.Shared/SharedGameTicker.cs | 1 + 5 files changed, 62 insertions(+) create mode 100644 Content.Server/Players/PlayerSessionExt.cs create mode 100644 Content.Shared/Network/NetMessages/MsgRequestWindowAttention.cs diff --git a/Content.Client/GameTicking/ClientGameTicker.cs b/Content.Client/GameTicking/ClientGameTicker.cs index a80f606215..cab0608a93 100644 --- a/Content.Client/GameTicking/ClientGameTicker.cs +++ b/Content.Client/GameTicking/ClientGameTicker.cs @@ -3,6 +3,8 @@ using Content.Client.Interfaces; using Content.Client.State; using Content.Client.UserInterface; using Content.Shared; +using Content.Shared.Network.NetMessages; +using Robust.Client.Interfaces.Graphics; using Robust.Client.Interfaces.State; using Robust.Shared.Interfaces.Network; using Robust.Shared.IoC; @@ -39,6 +41,10 @@ namespace Content.Client.GameTicking _netManager.RegisterNetMessage(nameof(MsgTickerLobbyInfo), LobbyInfo); _netManager.RegisterNetMessage(nameof(MsgTickerLobbyCountdown), LobbyCountdown); _netManager.RegisterNetMessage(nameof(MsgRoundEndMessage), RoundEnd); + _netManager.RegisterNetMessage(nameof(MsgRequestWindowAttention), msg => + { + IoCManager.Resolve().RequestWindowAttention(); + }); _initialized = true; } diff --git a/Content.Server/GameTicking/GameTicker.cs b/Content.Server/GameTicking/GameTicker.cs index bef68e027d..006740fc38 100644 --- a/Content.Server/GameTicking/GameTicker.cs +++ b/Content.Server/GameTicking/GameTicker.cs @@ -24,6 +24,7 @@ using Content.Server.Players; using Content.Shared; using Content.Shared.Chat; using Content.Shared.GameObjects.Components.PDA; +using Content.Shared.Network.NetMessages; using Content.Shared.Preferences; using Content.Shared.Roles; using Prometheus; @@ -137,6 +138,7 @@ namespace Content.Server.GameTicking _netManager.RegisterNetMessage(nameof(MsgTickerLobbyInfo)); _netManager.RegisterNetMessage(nameof(MsgTickerLobbyCountdown)); _netManager.RegisterNetMessage(nameof(MsgRoundEndMessage)); + _netManager.RegisterNetMessage(nameof(MsgRequestWindowAttention)); SetStartPreset(_configurationManager.GetCVar("game.defaultpreset")); @@ -206,6 +208,16 @@ namespace Content.Server.GameTicking _roundStartTimeUtc = DateTime.UtcNow + LobbyDuration; _sendStatusToAll(); + + ReqWindowAttentionAll(); + } + } + + private void ReqWindowAttentionAll() + { + foreach (var player in _playerManager.GetAllPlayers()) + { + player.RequestWindowAttention(); } } @@ -284,6 +296,7 @@ namespace Content.Server.GameTicking _roundStartTimeSpan = IoCManager.Resolve().RealTime; _sendStatusToAll(); + ReqWindowAttentionAll(); } private void SendServerMessage(string message) @@ -621,6 +634,7 @@ namespace Content.Server.GameTicking _playerJoinLobby(player); } + EntitySystem.Get().ResettingCleanup(); EntitySystem.Get().ResettingCleanup(); EntitySystem.Get().ResettingCleanup(); EntitySystem.Get().ResetLayouts(); diff --git a/Content.Server/Players/PlayerSessionExt.cs b/Content.Server/Players/PlayerSessionExt.cs new file mode 100644 index 0000000000..3b06788869 --- /dev/null +++ b/Content.Server/Players/PlayerSessionExt.cs @@ -0,0 +1,14 @@ +using Content.Shared.Network.NetMessages; +using Robust.Server.Interfaces.Player; + +namespace Content.Server.Players +{ + public static class PlayerSessionExt + { + public static void RequestWindowAttention(this IPlayerSession session) + { + var msg = session.ConnectedClient.CreateNetMessage(); + session.ConnectedClient.SendMessage(msg); + } + } +} diff --git a/Content.Shared/Network/NetMessages/MsgRequestWindowAttention.cs b/Content.Shared/Network/NetMessages/MsgRequestWindowAttention.cs new file mode 100644 index 0000000000..e14ca862e5 --- /dev/null +++ b/Content.Shared/Network/NetMessages/MsgRequestWindowAttention.cs @@ -0,0 +1,27 @@ +using Lidgren.Network; +using Robust.Shared.Interfaces.Network; +using Robust.Shared.Network; + +namespace Content.Shared.Network.NetMessages +{ + public sealed class MsgRequestWindowAttention : NetMessage + { + #region REQUIRED + + public const MsgGroups GROUP = MsgGroups.Command; + public const string NAME = nameof(MsgRequestWindowAttention); + public MsgRequestWindowAttention(INetChannel channel) : base(NAME, GROUP) { } + + #endregion + + public override void ReadFromBuffer(NetIncomingMessage buffer) + { + // Nothing + } + + public override void WriteToBuffer(NetOutgoingMessage buffer) + { + // Nothing + } + } +} diff --git a/Content.Shared/SharedGameTicker.cs b/Content.Shared/SharedGameTicker.cs index 846598dfbf..669a6acb93 100644 --- a/Content.Shared/SharedGameTicker.cs +++ b/Content.Shared/SharedGameTicker.cs @@ -152,6 +152,7 @@ namespace Content.Shared } } + public struct RoundEndPlayerInfo { public string PlayerOOCName; From 0ea8844491d508cad6e2113594ad9309dc8717e5 Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Sun, 16 Aug 2020 23:40:52 +0200 Subject: [PATCH 19/21] I blame rider for this. --- Content.Server/GameTicking/GameTicker.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/Content.Server/GameTicking/GameTicker.cs b/Content.Server/GameTicking/GameTicker.cs index 006740fc38..42bd24d44c 100644 --- a/Content.Server/GameTicking/GameTicker.cs +++ b/Content.Server/GameTicking/GameTicker.cs @@ -634,7 +634,6 @@ namespace Content.Server.GameTicking _playerJoinLobby(player); } - EntitySystem.Get().ResettingCleanup(); EntitySystem.Get().ResettingCleanup(); EntitySystem.Get().ResettingCleanup(); EntitySystem.Get().ResetLayouts(); From 12d94f28a1568f1f407773c8e66e28378415909c Mon Sep 17 00:00:00 2001 From: DrSmugleaf Date: Sun, 16 Aug 2020 23:47:33 +0200 Subject: [PATCH 20/21] Fix duplicate OOC console message (#1724) --- Content.Client/Chat/ChatManager.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/Content.Client/Chat/ChatManager.cs b/Content.Client/Chat/ChatManager.cs index 1cf96367a6..21be7769ae 100644 --- a/Content.Client/Chat/ChatManager.cs +++ b/Content.Client/Chat/ChatManager.cs @@ -323,8 +323,6 @@ namespace Content.Client.Chat private void _onChatMessage(MsgChatMessage msg) { - Logger.Debug($"{msg.Channel}: {msg.Message}"); - // Log all incoming chat to repopulate when filter is un-toggled var storedMessage = new StoredChatMessage(msg); filteredHistory.Add(storedMessage); From 58b9ac10c251acfbe7fff948c36696adbd77e964 Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Sun, 16 Aug 2020 23:49:20 +0200 Subject: [PATCH 21/21] Fix right-click verbs. --- .../GameObjects/EntitySystems/VerbSystem.cs | 13 +++++++++++-- Content.Shared/GameObjects/Verbs/Verb.cs | 1 + 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/Content.Server/GameObjects/EntitySystems/VerbSystem.cs b/Content.Server/GameObjects/EntitySystems/VerbSystem.cs index 6de086226a..761681b1ac 100644 --- a/Content.Server/GameObjects/EntitySystems/VerbSystem.cs +++ b/Content.Server/GameObjects/EntitySystems/VerbSystem.cs @@ -113,8 +113,17 @@ namespace Content.Server.GameObjects.EntitySystems if (verb.RequireInteractionRange && !VerbUtility.InVerbUseRange(userEntity, entity)) continue; - if (verb.BlockedByContainers && !userEntity.IsInSameOrNoContainer(entity)) - continue; + if (verb.BlockedByContainers) + { + if (!userEntity.IsInSameOrNoContainer(entity)) + { + if (!ContainerHelpers.TryGetContainer(entity, out var container) || + container.Owner != userEntity) + { + continue; + } + } + } var verbData = verb.GetData(userEntity, component); if (verbData.IsInvisible) diff --git a/Content.Shared/GameObjects/Verbs/Verb.cs b/Content.Shared/GameObjects/Verbs/Verb.cs index 99cf50b24d..723f90f1f3 100644 --- a/Content.Shared/GameObjects/Verbs/Verb.cs +++ b/Content.Shared/GameObjects/Verbs/Verb.cs @@ -23,6 +23,7 @@ namespace Content.Shared.GameObjects.Verbs /// /// If true, this verb requires both the user and the entity on which /// this verb resides to be in the same container or no container. + /// OR the user can be the entity's container /// public virtual bool BlockedByContainers => true;