From e6e09b5f4e543d86ed12d9adfd91a0f2aace4d22 Mon Sep 17 00:00:00 2001 From: Roudenn Date: Mon, 28 Oct 2024 11:14:35 +0300 Subject: [PATCH 1/9] Add Blob Storage + rewrite code --- Content.Client/Backmen/Blob/BlobTileSystem.cs | 3 +- Content.Server/Backmen/Blob/BlobTileSystem.cs | 483 ------------------ .../Blob/Components/BlobFactoryComponent.cs | 36 -- .../Blob/{ => Systems}/BlobCarrierSystem.cs | 2 +- .../{ => Systems}/BlobCoreActionSystem.cs | 77 ++- .../Blob/{ => Systems}/BlobCoreSystem.cs | 191 ++++--- .../Blob/{ => Systems}/BlobFactorySystem.cs | 44 +- .../Blob/{ => Systems}/BlobMobSystem.cs | 22 +- .../Blob/{ => Systems}/BlobNodeSystem.cs | 12 +- .../Blob/{ => Systems}/BlobObserverMover.cs | 3 +- .../Blob/{ => Systems}/BlobObserverSystem.cs | 17 +- .../Blob/{ => Systems}/BlobResourceSystem.cs | 22 +- .../Backmen/Blob/Systems/BlobStorageSystem.cs | 39 ++ .../Backmen/Blob/Systems/BlobTileSystem.cs | 243 +++++++++ .../Blob/{ => Systems}/BlobbernautSystem.cs | 2 +- .../Blob/{ => Systems}/ZombieBlobSystem.cs | 7 +- .../Rules/Components/BlobRuleComponent.cs | 3 +- .../Systems/BlobCaptureObjectiveSystem.cs | 70 +++ .../Body/Components/RespiratorComponent.cs | 2 +- .../Backmen/Blob/BlobTypedStorage.cs | 8 - .../Blob/Components/BlobCoreComponent.cs | 23 +- .../Blob/Components/BlobFactoryComponent.cs | 33 ++ .../Blob/Components/BlobNodeComponent.cs | 2 - .../Blob/Components/BlobObserverComponent.cs | 54 +- .../Blob/Components/BlobResourceComponent.cs | 4 +- .../Blob/Components/BlobStorageComponent.cs | 13 + .../Blob/Components/BlobTileComponent.cs | 13 +- .../BlobUpgradeableTileComponent.cs | 11 + .../Backmen/Blob/SharedBlobTileSystem.cs | 30 +- Resources/Locale/ru-RU/backmen/blob/blob.ftl | 10 +- .../Prototypes/_Backmen/Actions/blob.yml | 20 + .../Entities/Mobs/NPCs/blob/blob_tiles.yml | 69 ++- .../Actions/blob.rsi/blobStorage.png | Bin 0 -> 3111 bytes .../Interface/Actions/blob.rsi/meta.json | 3 + .../Blob/blob.rsi/blob_storage_overlay.png | Bin 0 -> 992 bytes .../Mobs/Aliens/Blob/blob.rsi/meta.json | 19 + 36 files changed, 764 insertions(+), 826 deletions(-) delete mode 100644 Content.Server/Backmen/Blob/BlobTileSystem.cs delete mode 100644 Content.Server/Backmen/Blob/Components/BlobFactoryComponent.cs rename Content.Server/Backmen/Blob/{ => Systems}/BlobCarrierSystem.cs (99%) rename Content.Server/Backmen/Blob/{ => Systems}/BlobCoreActionSystem.cs (87%) rename Content.Server/Backmen/Blob/{ => Systems}/BlobCoreSystem.cs (84%) rename Content.Server/Backmen/Blob/{ => Systems}/BlobFactorySystem.cs (84%) rename Content.Server/Backmen/Blob/{ => Systems}/BlobMobSystem.cs (83%) rename Content.Server/Backmen/Blob/{ => Systems}/BlobNodeSystem.cs (91%) rename Content.Server/Backmen/Blob/{ => Systems}/BlobObserverMover.cs (97%) rename Content.Server/Backmen/Blob/{ => Systems}/BlobObserverSystem.cs (96%) rename Content.Server/Backmen/Blob/{ => Systems}/BlobResourceSystem.cs (77%) create mode 100644 Content.Server/Backmen/Blob/Systems/BlobStorageSystem.cs create mode 100644 Content.Server/Backmen/Blob/Systems/BlobTileSystem.cs rename Content.Server/Backmen/Blob/{ => Systems}/BlobbernautSystem.cs (98%) rename Content.Server/Backmen/Blob/{ => Systems}/ZombieBlobSystem.cs (98%) create mode 100644 Content.Server/Backmen/Objectives/Systems/BlobCaptureObjectiveSystem.cs create mode 100644 Content.Shared/Backmen/Blob/Components/BlobFactoryComponent.cs rename {Content.Server => Content.Shared}/Backmen/Blob/Components/BlobResourceComponent.cs (57%) create mode 100644 Content.Shared/Backmen/Blob/Components/BlobStorageComponent.cs create mode 100644 Content.Shared/Backmen/Blob/Components/BlobUpgradeableTileComponent.cs create mode 100644 Resources/Textures/Backmen/Interface/Actions/blob.rsi/blobStorage.png create mode 100644 Resources/Textures/Backmen/Mobs/Aliens/Blob/blob.rsi/blob_storage_overlay.png diff --git a/Content.Client/Backmen/Blob/BlobTileSystem.cs b/Content.Client/Backmen/Blob/BlobTileSystem.cs index 652d910feec..9452800d9c6 100644 --- a/Content.Client/Backmen/Blob/BlobTileSystem.cs +++ b/Content.Client/Backmen/Blob/BlobTileSystem.cs @@ -2,13 +2,12 @@ using Content.Shared.Backmen.Blob; using Content.Shared.Backmen.Blob.Components; using Robust.Client.GameObjects; -using Robust.Shared.GameStates; namespace Content.Client.Backmen.Blob; public sealed class BlobTileSystem : SharedBlobTileSystem { - protected override void TryUpgrade(Entity target, Entity core, EntityUid observer) { } + protected override void TryUpgrade(Entity target, Entity core, EntityUid observer) { } } public sealed class BlobTileVisualizerSystem : VisualizerSystem diff --git a/Content.Server/Backmen/Blob/BlobTileSystem.cs b/Content.Server/Backmen/Blob/BlobTileSystem.cs deleted file mode 100644 index 72adf342817..00000000000 --- a/Content.Server/Backmen/Blob/BlobTileSystem.cs +++ /dev/null @@ -1,483 +0,0 @@ -using System.Diagnostics; -using System.Linq; -using System.Numerics; -using Content.Server.Construction.Components; -using Content.Server.Destructible; -using Content.Server.Emp; -using Content.Server.Flash; -using Content.Shared.Backmen.Blob; -using Content.Shared.Backmen.Blob.Components; -using Content.Shared.Damage; -using Content.Shared.Destructible; -using Content.Shared.FixedPoint; -using Content.Shared.Mobs; -using Content.Shared.Mobs.Components; -using Content.Shared.Mobs.Systems; -using Content.Shared.NPC.Components; -using Content.Shared.NPC.Prototypes; -using Content.Shared.NPC.Systems; -using Robust.Server.Audio; -using Robust.Server.GameObjects; -using Robust.Shared.Audio; -using Robust.Shared.Map.Components; -using Robust.Shared.Player; -using Robust.Shared.Random; - -namespace Content.Server.Backmen.Blob; - -public sealed class BlobTileSystem : SharedBlobTileSystem -{ - [Dependency] private readonly DamageableSystem _damageableSystem = default!; - [Dependency] private readonly BlobCoreSystem _blobCoreSystem = default!; - [Dependency] private readonly AudioSystem _audioSystem = default!; - [Dependency] private readonly EmpSystem _empSystem = default!; - [Dependency] private readonly MapSystem _mapSystem = default!; - [Dependency] private readonly TransformSystem _transform = default!; - [Dependency] private readonly IRobustRandom _random = default!; - [Dependency] private readonly NpcFactionSystem _npcFactionSystem = default!; - [Dependency] private readonly MobStateSystem _mobState = default!; - - private EntityQuery _blobCoreQuery; - - [ValidatePrototypeId] - private const string BlobFaction = "Blob"; - - public override void Initialize() - { - base.Initialize(); - - SubscribeLocalEvent(OnMapInit); - SubscribeLocalEvent(OnDestruction); - SubscribeLocalEvent(OnPulsed); - SubscribeLocalEvent(OnFlashAttempt); - SubscribeLocalEvent(OnTerminate); - - _blobCoreQuery = GetEntityQuery(); - } - - private void OnMapInit(Entity ent, ref MapInitEvent args) - { - var faction = EnsureComp(ent); - Entity factionEnt = (ent, faction); - - _npcFactionSystem.ClearFactions(factionEnt, false); - _npcFactionSystem.AddFaction(factionEnt, BlobFaction, true); - - // make alive - true for npc combat - EnsureComp(ent); - } - - private void OnTerminate(EntityUid uid, BlobTileComponent component, EntityTerminatingEvent args) - { - if (TerminatingOrDeleted(component.Core)) - return; - - component.Core!.Value.Comp.BlobTiles.Remove(uid); - } - - private void OnFlashAttempt(EntityUid uid, BlobTileComponent component, FlashAttemptEvent args) - { - if (args.Used == null || MetaData(args.Used.Value).EntityPrototype?.ID != "GrenadeFlashBang") - return; - - if (component.BlobTileType == BlobTileType.Normal) - { - _damageableSystem.TryChangeDamage(uid, component.FlashDamage); - } - } - - private void OnDestruction(EntityUid uid, BlobTileComponent component, DestructionEventArgs args) - { - if ( - TerminatingOrDeleted(component.Core) || - !_blobCoreQuery.TryComp(component.Core, out var blobCoreComponent) - ) - return; - - if (blobCoreComponent.CurrentChem == BlobChemType.ElectromagneticWeb) - { - _empSystem.EmpPulse(_transform.GetMapCoordinates(uid), 3f, 50f, 3f); - } - } - - private void OnPulsed(EntityUid uid, BlobTileComponent component, BlobTileGetPulseEvent args) - { - if (component.Core == null) - return; - - var core = component.Core.Value; - - if (core.Comp.CurrentChem == BlobChemType.RegenerativeMateria) - { - var healCore = new DamageSpecifier(); - foreach (var keyValuePair in component.HealthOfPulse.DamageDict) - { - healCore.DamageDict.Add(keyValuePair.Key, keyValuePair.Value * 5); - } - - _damageableSystem.TryChangeDamage(uid, healCore); - } - else - { - _damageableSystem.TryChangeDamage(uid, component.HealthOfPulse); - } - - if (!args.Handled) - return; - - var xform = Transform(uid); - - if (!TryComp(xform.GridUid, out var grid)) - { - return; - } - - var nearNode = _blobCoreSystem.GetNearNode(xform.Coordinates, core.Comp.TilesRadiusLimit); - - if (nearNode == null) - return; - - var mobTile = _mapSystem.GetTileRef(xform.GridUid.Value, grid, xform.Coordinates); - - var mobAdjacentTiles = new[] - { - mobTile.GridIndices.Offset(Direction.East), - mobTile.GridIndices.Offset(Direction.West), - mobTile.GridIndices.Offset(Direction.North), - mobTile.GridIndices.Offset(Direction.South), - }; - - _random.Shuffle(mobAdjacentTiles); - - var localPos = xform.Coordinates.Position; - - var radius = 1.0f; - - var innerTiles = _mapSystem.GetLocalTilesIntersecting(xform.GridUid.Value, - grid, - new Box2(localPos + new Vector2(-radius, -radius), localPos + new Vector2(radius, radius))) - .ToArray(); - - foreach (var innerTile in innerTiles) - { - if (!mobAdjacentTiles.Contains(innerTile.GridIndices)) - { - continue; - } - - foreach (var ent in _mapSystem.GetAnchoredEntities(xform.GridUid.Value, grid, innerTile.GridIndices)) - { - if (!HasComp(ent) || !HasComp(ent)) - continue; - - DoLunge(uid, ent); - _damageableSystem.TryChangeDamage(ent, core.Comp.ChemDamageDict[core.Comp.CurrentChem]); - _audioSystem.PlayPvs(core.Comp.AttackSound, uid, AudioParams.Default); - args.Handled = true; - return; - } - - var spawn = true; - foreach (var ent in _mapSystem.GetAnchoredEntities(xform.GridUid.Value, grid, innerTile.GridIndices)) - { - if (!HasComp(ent)) - continue; - spawn = false; - break; - } - - if (!spawn) - continue; - - var location = _mapSystem.ToCoordinates(xform.GridUid.Value, innerTile.GridIndices, grid); - - if (_blobCoreSystem.TransformBlobTile(null, - core, - nearNode, - BlobTileType.Normal, - location)) - return; - } - } - - protected override void TryUpgrade(Entity target, Entity core, EntityUid observer) - { - var coords = Transform(target).Coordinates; - - if (target.Comp.BlobTileType == BlobTileType.Reflective) - return; - - var nearNode = _blobCoreSystem.GetNearNode(coords, core.Comp.TilesRadiusLimit); - if (nearNode == null) - return; - - var ev = new BlobTransformTileActionEvent( - performer: observer, - target: coords, - transformFrom: target.Comp.BlobTileType, - tileType: BlobTileType.Invalid, - requireNode: false); - - ev.TileType = ev.TransformFrom switch - { - BlobTileType.Normal => BlobTileType.Strong, - BlobTileType.Strong => BlobTileType.Reflective, - _ => BlobTileType.Invalid - }; - - RaiseLocalEvent(core, ev); - } - - /* This work very bad. - I replace invisible - wall to teleportation observer - if he moving away from blob tile */ - - // private void OnStartup(EntityUid uid, BlobCellComponent component, ComponentStartup args) - // { - // var xform = Transform(uid); - // var radius = 2.5f; - // var wallSpacing = 1.5f; // Расстояние между стенами и центральной областью - // - // if (!_map.TryGetGrid(xform.GridUid, out var grid)) - // { - // return; - // } - // - // var localpos = xform.Coordinates.Position; - // - // // Получаем тайлы в области с радиусом 2.5 - // var allTiles = grid.GetLocalTilesIntersecting( - // new Box2(localpos + new Vector2(-radius, -radius), localpos + new Vector2(radius, radius))).ToArray(); - // - // // Получаем тайлы в области с радиусом 1.5 - // var innerTiles = grid.GetLocalTilesIntersecting( - // new Box2(localpos + new Vector2(-wallSpacing, -wallSpacing), localpos + new Vector2(wallSpacing, wallSpacing))).ToArray(); - // - // foreach (var tileref in innerTiles) - // { - // foreach (var ent in grid.GetAnchoredEntities(tileref.GridIndices)) - // { - // if (HasComp(ent)) - // QueueDel(ent); - // if (HasComp(ent)) - // { - // var blockTiles = grid.GetLocalTilesIntersecting( - // new Box2(Transform(ent).Coordinates.Position + new Vector2(-wallSpacing, -wallSpacing), - // Transform(ent).Coordinates.Position + new Vector2(wallSpacing, wallSpacing))).ToArray(); - // allTiles = allTiles.Except(blockTiles).ToArray(); - // } - // } - // } - // - // var outerTiles = allTiles.Except(innerTiles).ToArray(); - // - // foreach (var tileRef in outerTiles) - // { - // foreach (var ent in grid.GetAnchoredEntities(tileRef.GridIndices)) - // { - // if (HasComp(ent)) - // { - // var blockTiles = grid.GetLocalTilesIntersecting( - // new Box2(Transform(ent).Coordinates.Position + new Vector2(-wallSpacing, -wallSpacing), - // Transform(ent).Coordinates.Position + new Vector2(wallSpacing, wallSpacing))).ToArray(); - // outerTiles = outerTiles.Except(blockTiles).ToArray(); - // } - // } - // } - // - // foreach (var tileRef in outerTiles) - // { - // var spawn = true; - // foreach (var ent in grid.GetAnchoredEntities(tileRef.GridIndices)) - // { - // if (HasComp(ent)) - // { - // spawn = false; - // break; - // } - // } - // if (spawn) - // EntityManager.SpawnEntity("BlobBorder", tileRef.GridIndices.ToEntityCoordinates(xform.GridUid.Value, _map)); - // } - // } - - // private void OnDestruction(EntityUid uid, BlobTileComponent component, DestructionEventArgs args) - // { - // var xform = Transform(uid); - // var radius = 1.0f; - // - // if (!_map.TryGetGrid(xform.GridUid, out var grid)) - // { - // return; - // } - // - // var localPos = xform.Coordinates.Position; - // - // var innerTiles = grid.GetLocalTilesIntersecting( - // new Box2(localPos + new Vector2(-radius, -radius), localPos + new Vector2(radius, radius)), false).ToArray(); - // - // var centerTile = grid.GetLocalTilesIntersecting( - // new Box2(localPos, localPos)).ToArray(); - // - // innerTiles = innerTiles.Except(centerTile).ToArray(); - // - // foreach (var tileref in innerTiles) - // { - // foreach (var ent in grid.GetAnchoredEntities(tileref.GridIndices)) - // { - // if (!HasComp(ent)) - // continue; - // var blockTiles = grid.GetLocalTilesIntersecting( - // new Box2(Transform(ent).Coordinates.Position + new Vector2(-radius, -radius), - // Transform(ent).Coordinates.Position + new Vector2(radius, radius)), false).ToArray(); - // - // var tilesToRemove = new List(); - // - // foreach (var blockTile in blockTiles) - // { - // tilesToRemove.Add(blockTile); - // } - // - // innerTiles = innerTiles.Except(tilesToRemove).ToArray(); - // } - // } - // - // foreach (var tileRef in innerTiles) - // { - // foreach (var ent in grid.GetAnchoredEntities(tileRef.GridIndices)) - // { - // if (HasComp(ent)) - // { - // QueueDel(ent); - // } - // } - // } - // - // EntityManager.SpawnEntity(component.BlobBorder, xform.Coordinates); - // } - // - // private void OnStartup(EntityUid uid, BlobTileComponent component, ComponentStartup args) - // { - // var xform = Transform(uid); - // var wallSpacing = 1.0f; - // - // if (!_map.TryGetGrid(xform.GridUid, out var grid)) - // { - // return; - // } - // - // var localPos = xform.Coordinates.Position; - // - // var innerTiles = grid.GetLocalTilesIntersecting( - // new Box2(localPos + new Vector2(-wallSpacing, -wallSpacing), localPos + new Vector2(wallSpacing, wallSpacing)), false).ToArray(); - // - // var centerTile = grid.GetLocalTilesIntersecting( - // new Box2(localPos, localPos)).ToArray(); - // - // foreach (var tileRef in centerTile) - // { - // foreach (var ent in grid.GetAnchoredEntities(tileRef.GridIndices)) - // { - // if (HasComp(ent)) - // QueueDel(ent); - // } - // } - // innerTiles = innerTiles.Except(centerTile).ToArray(); - // - // foreach (var tileref in innerTiles) - // { - // var spaceNear = false; - // var hasBlobTile = false; - // foreach (var ent in grid.GetAnchoredEntities(tileref.GridIndices)) - // { - // if (!HasComp(ent)) - // continue; - // var blockTiles = grid.GetLocalTilesIntersecting( - // new Box2(Transform(ent).Coordinates.Position + new Vector2(-wallSpacing, -wallSpacing), - // Transform(ent).Coordinates.Position + new Vector2(wallSpacing, wallSpacing)), false).ToArray(); - // - // var tilesToRemove = new List(); - // - // foreach (var blockTile in blockTiles) - // { - // if (blockTile.Tile.IsEmpty) - // { - // spaceNear = true; - // } - // else - // { - // tilesToRemove.Add(blockTile); - // } - // } - // - // innerTiles = innerTiles.Except(tilesToRemove).ToArray(); - // - // hasBlobTile = true; - // } - // - // if (!hasBlobTile || spaceNear) - // continue; - // { - // foreach (var ent in grid.GetAnchoredEntities(tileref.GridIndices)) - // { - // if (HasComp(ent)) - // { - // QueueDel(ent); - // } - // } - // } - // } - // - // var spaceNearCenter = false; - // - // foreach (var tileRef in innerTiles) - // { - // var spawn = true; - // if (tileRef.Tile.IsEmpty) - // { - // spaceNearCenter = true; - // spawn = false; - // } - // if (grid.GetAnchoredEntities(tileRef.GridIndices).Any(ent => HasComp(ent))) - // { - // spawn = false; - // } - // if (spawn) - // EntityManager.SpawnEntity(component.BlobBorder, tileRef.GridIndices.ToEntityCoordinates(xform.GridUid.Value, _map)); - // } - // if (spaceNearCenter) - // { - // EntityManager.SpawnEntity(component.BlobBorder, xform.Coordinates); - // } - // } - public void SwapSpecials(Entity from, Entity to) - { - (from.Comp.BlobFactory, to.Comp.BlobFactory) = (to.Comp.BlobFactory, from.Comp.BlobFactory); - (from.Comp.BlobResource, to.Comp.BlobResource) = (to.Comp.BlobResource, from.Comp.BlobResource); - Dirty(from); - Dirty(to); - } - - public bool IsEmptySpecial(Entity node, BlobTileType tile) - { - return tile switch - { - BlobTileType.Factory => node.Comp.BlobFactory == null || TerminatingOrDeleted(node.Comp.BlobFactory), - BlobTileType.Resource => node.Comp.BlobResource == null || TerminatingOrDeleted(node.Comp.BlobResource), - _ => false - }; - } - - public void DoLunge(EntityUid from, EntityUid target) - { - if(!TransformQuery.TryComp(from, out var userXform)) - return; - - var targetPos = _transform.GetWorldPosition(target); - var localPos = Vector2.Transform(targetPos, _transform.GetInvWorldMatrix(userXform)); - localPos = userXform.LocalRotation.RotateVec(localPos); - - RaiseNetworkEvent(new BlobAttackEvent(GetNetEntity(from), GetNetEntity(target), localPos), Filter.Pvs(from)); - } -} diff --git a/Content.Server/Backmen/Blob/Components/BlobFactoryComponent.cs b/Content.Server/Backmen/Blob/Components/BlobFactoryComponent.cs deleted file mode 100644 index 6113b3e239c..00000000000 --- a/Content.Server/Backmen/Blob/Components/BlobFactoryComponent.cs +++ /dev/null @@ -1,36 +0,0 @@ -using Content.Shared.Backmen.Blob.Components; -using Robust.Shared.Prototypes; - -namespace Content.Server.Backmen.Blob.Components; - -[RegisterComponent] -public sealed partial class BlobFactoryComponent : Component -{ - [ViewVariables(VVAccess.ReadOnly)] - public float SpawnedCount = 0; - - [DataField("spawnLimit"), ViewVariables(VVAccess.ReadWrite)] - public float SpawnLimit = 3; - - [DataField("blobSporeId"), ViewVariables(VVAccess.ReadWrite)] - public EntProtoId Pod = "MobBlobPod"; - - [DataField("blobbernautId"), ViewVariables(VVAccess.ReadWrite)] - public EntProtoId BlobbernautId = "MobBlobBlobbernaut"; - - [ViewVariables(VVAccess.ReadOnly)] - public EntityUid? Blobbernaut = default!; - - [ViewVariables(VVAccess.ReadOnly)] - public List BlobPods = new (); - - [DataField] - public int Accumulator = 0; - - [DataField] - public int AccumulateToSpawn = 3; -} - -public sealed class ProduceBlobbernautEvent : EntityEventArgs -{ -} diff --git a/Content.Server/Backmen/Blob/BlobCarrierSystem.cs b/Content.Server/Backmen/Blob/Systems/BlobCarrierSystem.cs similarity index 99% rename from Content.Server/Backmen/Blob/BlobCarrierSystem.cs rename to Content.Server/Backmen/Blob/Systems/BlobCarrierSystem.cs index 4b38e9d6582..b36ef3cfd8d 100644 --- a/Content.Server/Backmen/Blob/BlobCarrierSystem.cs +++ b/Content.Server/Backmen/Blob/Systems/BlobCarrierSystem.cs @@ -14,7 +14,7 @@ using Robust.Shared.Player; using Robust.Shared.Prototypes; -namespace Content.Server.Backmen.Blob; +namespace Content.Server.Backmen.Blob.Systems; public sealed class BlobCarrierSystem : SharedBlobCarrierSystem { diff --git a/Content.Server/Backmen/Blob/BlobCoreActionSystem.cs b/Content.Server/Backmen/Blob/Systems/BlobCoreActionSystem.cs similarity index 87% rename from Content.Server/Backmen/Blob/BlobCoreActionSystem.cs rename to Content.Server/Backmen/Blob/Systems/BlobCoreActionSystem.cs index ac028666441..b09f43cbc57 100644 --- a/Content.Server/Backmen/Blob/BlobCoreActionSystem.cs +++ b/Content.Server/Backmen/Blob/Systems/BlobCoreActionSystem.cs @@ -1,10 +1,8 @@ using System.Linq; -using System.Numerics; using System.Threading; using System.Threading.Tasks; using Content.Server.Atmos.Components; using Content.Server.Atmos.EntitySystems; -using Content.Server.Backmen.Blob.Components; using Content.Server.Destructible; using Content.Server.Emp; using Content.Server.Explosion.EntitySystems; @@ -25,12 +23,12 @@ using Robust.Shared.CPUJob.JobQueues.Queues; using Robust.Shared.Map; using Robust.Shared.Map.Components; -using Robust.Shared.Player; +using Robust.Shared.Physics.Components; using Robust.Shared.Random; using Robust.Shared.Timing; using Robust.Shared.Utility; -namespace Content.Server.Backmen.Blob; +namespace Content.Server.Backmen.Blob.Systems; public sealed class BlobCoreActionSystem : SharedBlobCoreActionSystem { @@ -97,6 +95,7 @@ private void BlobInteract(Entity observer, Entity observer, Entity(args.Target)) + if (fromTile == null || node == null) + return; + + #region Handle Attack + + // Get the solid anchored target on a tile. + var targetEnts = _mapSystem.GetAnchoredEntities(gridUid.Value, grid, targetTile.GridIndices); + bool growTile = true; + foreach (var targetEntity in targetEnts) { - if (_tileQuery.TryComp(args.Target.Value, out var tileComp) && tileComp.Core != null) - return; + if (TryComp(targetEntity, out var physics) && + physics is { Hard: true, CanCollide: true } && + HasComp(targetEntity)) + { + target = targetEntity; + } - var target = args.Target; - if (fromTile != null && HasComp(target) && !HasComp(target) && !HasComp(target)) + if (_tileQuery.HasComp(targetEntity)) { - BlobTargetAttack(core, fromTile.Value, target.Value); - return; + growTile = false; + target = args.Target; + break; } } - #endregion - var targetTile = _mapSystem.GetTileRef(gridUid.Value, grid, location); - - var targetTileEmpty = false; - if (targetTile.Tile.IsEmpty) + // Handle target attack. + // Only hard objects should be attacked. + if (target != null && + TryComp(target, out var physicsTarget) && + physicsTarget is { Hard: true, CanCollide: true } && + HasComp(target) && + !HasComp(target)) { - if (!_canGrowInSpace) + // Things that we can't attack, including our own tiles. + if (HasComp(target) || + HasComp(target) || + _tileQuery.TryComp(target, out var targetComp) && targetComp.Core != null) return; - targetTileEmpty = true; + BlobTargetAttack(core, fromTile.Value, target.Value); + return; } - if (_mapSystem.GetAnchoredEntities(gridUid.Value, grid, targetTile.GridIndices).Any(_tileQuery.HasComponent)) - { + if (!growTile) return; - } - var node = _blobCoreSystem.GetNearNode(location, core.Comp.TilesRadiusLimit); + #endregion - if (fromTile != null && node == null) - _popup.PopupCoordinates(Loc.GetString("blob-target-nearby-not-node"), location, args.User, PopupType.Large); + var targetTileEmpty = false; + if (targetTile.Tile.IsEmpty) + { + if (!_canGrowInSpace) + return; - if (fromTile == null || node == null) - return; + targetTileEmpty = true; + } // This code doesn't work. // If you can debug this, please do and fix it. diff --git a/Content.Server/Backmen/Blob/BlobCoreSystem.cs b/Content.Server/Backmen/Blob/Systems/BlobCoreSystem.cs similarity index 84% rename from Content.Server/Backmen/Blob/BlobCoreSystem.cs rename to Content.Server/Backmen/Blob/Systems/BlobCoreSystem.cs index ede273cb1e3..9a24056df47 100644 --- a/Content.Server/Backmen/Blob/BlobCoreSystem.cs +++ b/Content.Server/Backmen/Blob/Systems/BlobCoreSystem.cs @@ -4,9 +4,7 @@ using System.Threading.Tasks; using Content.Server.Actions; using Content.Server.AlertLevel; -using Content.Server.Backmen.Blob.Components; using Content.Server.Backmen.GameTicking.Rules.Components; -using Content.Server.Backmen.Objectives; using Content.Server.Explosion.EntitySystems; using Content.Server.GameTicking; using Content.Server.RoundEnd; @@ -21,7 +19,6 @@ using Content.Shared.Explosion.Components; using Content.Shared.FixedPoint; using Content.Shared.GameTicking.Components; -using Content.Shared.Objectives.Components; using Content.Shared.Popups; using Content.Shared.Store; using Content.Shared.Store.Components; @@ -34,7 +31,7 @@ using Robust.Shared.Network; using Robust.Shared.Player; -namespace Content.Server.Backmen.Blob; +namespace Content.Server.Backmen.Blob.Systems; public sealed class BlobCoreSystem : EntitySystem { @@ -47,7 +44,6 @@ public sealed class BlobCoreSystem : EntitySystem [Dependency] private readonly StationSystem _stationSystem = default!; [Dependency] private readonly AlertLevelSystem _alertLevelSystem = default!; [Dependency] private readonly RoundEndSystem _roundEndSystem = default!; - [Dependency] private readonly MetaDataSystem _metaDataSystem = default!; [Dependency] private readonly ActionsSystem _action = default!; [Dependency] private readonly MapSystem _mapSystem = default!; [Dependency] private readonly StoreSystem _storeSystem = default!; @@ -75,12 +71,7 @@ public override void Initialize() SubscribeLocalEvent(OnDamaged); SubscribeLocalEvent(OnTerminating); SubscribeLocalEvent(OnTileTransform); - SubscribeLocalEvent(OnPlayerAttached); - SubscribeLocalEvent(OnBlobCaptureProgress); - SubscribeLocalEvent(OnBlobCaptureInfo); - SubscribeLocalEvent(OnBlobCaptureInfoAdd); - _tile = GetEntityQuery(); _factory = GetEntityQuery(); @@ -90,7 +81,7 @@ public override void Initialize() private const double KillCoreJobTime = 0.5; private readonly JobQueue _killCoreJobQueue = new(KillCoreJobTime); - public sealed class KillBlobCore( + private sealed class KillBlobCore( BlobCoreSystem system, EntityUid? station, Entity ent, @@ -129,6 +120,12 @@ private void OnStartup(EntityUid uid, BlobCoreComponent component, ComponentStar var store = EnsureComp(uid); store.CurrencyWhitelist.Add(BlobMoney); + _storeSystem.TryAddCurrency(new Dictionary + { + { BlobMoney, FixedPoint2.Zero } + }, + uid, + store); UpdateAllAlerts((uid, component)); ChangeChem(uid, component.DefaultChem, component); @@ -178,57 +175,6 @@ private void OnTileTransform(EntityUid uid, BlobCoreComponent blobCoreComponent, #endregion - #region Objective - - private void OnBlobCaptureInfoAdd(Entity ent, ref ObjectiveAssignedEvent args) - { - if (args.Mind.OwnedEntity == null) - { - args.Cancelled = true; - return; - } - if (!TryComp(args.Mind.OwnedEntity, out var blobObserverComponent) - || !HasComp(blobObserverComponent.Core)) - { - args.Cancelled = true; - return; - } - - var station = _stationSystem.GetOwningStation(blobObserverComponent.Core); - if (station == null) - { - args.Cancelled = true; - return; - } - - ent.Comp.Target = CompOrNull(station)?.StageTheEnd ?? StationBlobConfigComponent.DefaultStageEnd; - } - - private void OnBlobCaptureInfo(EntityUid uid, BlobCaptureConditionComponent component, ref ObjectiveAfterAssignEvent args) - { - _metaDataSystem.SetEntityName(uid,Loc.GetString("objective-condition-blob-capture-title")); - _metaDataSystem.SetEntityDescription(uid,Loc.GetString("objective-condition-blob-capture-description", ("count", component.Target))); - } - - private void OnBlobCaptureProgress(EntityUid uid, BlobCaptureConditionComponent component, ref ObjectiveGetProgressEvent args) - { - if (!TryComp(args.Mind.OwnedEntity, out var blobObserverComponent) - || !TryComp(blobObserverComponent.Core, out var blobCoreComponent)) - { - args.Progress = 0; - return; - } - - var target = component.Target; - args.Progress = 0; - - if (target != 0) - args.Progress = MathF.Min((float) blobCoreComponent.BlobTiles.Count / target, 1f); - else - args.Progress = 1f; - } - #endregion - public void UpdateAllAlerts(Entity core, StoreComponent? store = null) { if (!Resolve(core, ref store)) @@ -313,7 +259,7 @@ public void ChangeChem(EntityUid uid, BlobChemType newChem, BlobCoreComponent? c } } - private void ChangeBlobEntChem(EntityUid uid, BlobChemType newChem) + public void ChangeBlobEntChem(EntityUid uid, BlobChemType newChem) { switch (newChem) { @@ -347,6 +293,9 @@ public bool TransformBlobTile( BlobTileType newBlobTile, EntityCoordinates coordinates) { + if (newBlobTile == BlobTileType.Invalid) + return false; + if (oldTileUid != null) { if (oldTileUid.Value.Comp.Core != blobCore) @@ -366,9 +315,11 @@ public bool TransformBlobTile( ConnectBlobTile((blobTileUid, blobTileComp), blobCore, nearNode); ChangeBlobEntChem(blobTileUid, blobCoreComp.CurrentChem); - Dirty(blobTileUid, blobTileComp); + var ev = new BlobTransformTileEvent(); + RaiseLocalEvent(blobTileUid, ev); + return true; } @@ -405,9 +356,19 @@ public void ConnectBlobTile( node.Value.Comp.BlobResource = tile; Dirty(node.Value); break; + case BlobTileType.Storage: + node.Value.Comp.BlobStorage = tile; + Dirty(node.Value); + break; + case BlobTileType.Turret: + node.Value.Comp.BlobTurret = tile; + Dirty(node.Value); + break; } } + #region Transform Tile Event + public bool TryGetTargetBlobTile(WorldTargetActionEvent args, out Entity? blobTile) { blobTile = null; @@ -441,11 +402,10 @@ public bool TryGetTargetBlobTile(WorldTargetActionEvent args, out Entity tile, - Entity? node, - bool requireNode, - BlobTransformTileActionEvent args) + BlobTransformTileActionEvent args, + out Entity? node) { var coords = Transform(tile).Coordinates; @@ -453,34 +413,35 @@ public bool CheckValidBlobTile( var checkTile = args.TransformFrom; var performer = args.Performer; + node = args.NodeSearchRadius != null ? GetNearNode(coords, args.NodeSearchRadius.Value) : null; + + // Base checks if (tile.Comp.Core == null || tile.Comp.BlobTileType == newTile || - tile.Comp.BlobTileType == BlobTileType.Core || - tile.Comp.BlobTileType != checkTile) - { - _popup.PopupCoordinates(Loc.GetString("blob-target-normal-blob-invalid"), coords, performer, PopupType.Large); + tile.Comp.BlobTileType == BlobTileType.Core) return false; - } - - var core = tile.Comp.Core.Value; if (checkTile == BlobTileType.Invalid) return true; - // Handle node spawn - if (newTile == BlobTileType.Node) + if (tile.Comp.BlobTileType != checkTile) + { + _popup.PopupCoordinates(Loc.GetString("blob-target-normal-blob-invalid"), coords, performer, PopupType.Large); + return false; + } + + // Handle Tile search + if (args.TileSearchRadius != null) { - if (GetNearNode(coords, core.Comp.NodeRadiusLimit) == null) + if (GetNearTile(newTile, coords, args.TileSearchRadius.Value) == null) return true; - _popup.PopupCoordinates(Loc.GetString("blob-target-close-to-node"), coords, performer, PopupType.Large); + _popup.PopupCoordinates(Loc.GetString("blob-target-close-to-tile"), coords, performer, PopupType.Large); return false; } - if (!requireNode) - return true; - - if (node == null) + // Handle Node search & connection + if (node == null && args.NodeSearchRadius != null) { _popup.PopupCoordinates(Loc.GetString("blob-target-nearby-not-node"), coords, @@ -489,26 +450,27 @@ public bool CheckValidBlobTile( return false; } - if (_blobTile.IsEmptySpecial(node.Value, newTile)) - return true; + if (node != null && !_blobTile.IsEmptySpecial(node.Value, newTile)) + { + _popup.PopupCoordinates(Loc.GetString("blob-target-already-connected"), + coords, + performer, + PopupType.Large); + return false; + } - _popup.PopupCoordinates(Loc.GetString("blob-target-already-connected"), - coords, - performer, - PopupType.Large); - return false; + return true; } - public void TransformSpecialTile(Entity blobCore, BlobTransformTileActionEvent args) + private void TransformSpecialTile(Entity blobCore, BlobTransformTileActionEvent args) { if (!TryGetTargetBlobTile(args, out var blobTile) || blobTile?.Comp.Core == null) return; var coords = Transform(blobTile.Value).Coordinates; var tileType = args.TileType; - var nearNode = GetNearNode(coords); - if (!CheckValidBlobTile(blobTile.Value, nearNode, args.RequireNode, args)) + if (!CheckValidBlobTile(blobTile.Value, args, out var nearNode)) return; if (!TryUseAbility(blobCore, blobCore.Comp.BlobTileCosts[tileType], coords)) @@ -522,6 +484,8 @@ public void TransformSpecialTile(Entity blobCore, BlobTransfo coords); } + #endregion + public void RemoveBlobTile(Entity tile, Entity core) { QueueDel(tile); @@ -613,6 +577,10 @@ public bool ChangeBlobPoint(Entity core, FixedPoint2 amount, if (!_pointsChange.TryEnterWriteLock(1000)) return false; + // You can't have more points than your max amount + if (core.Comp.MaxStorageAmount < store.Balance[BlobMoney] + amount) + amount = core.Comp.MaxStorageAmount - store.Balance[BlobMoney]; + if (_storeSystem.TryAddCurrency(new Dictionary { { BlobMoney, amount } @@ -648,19 +616,19 @@ public bool TryUseAbility(Entity core, FixedPoint2 abilityCos if (observer == null) return false; + coordinates ??= Transform(observer.Value).Coordinates; + if (money < abilityCost) { - _popup.PopupEntity(Loc.GetString( + _popup.PopupCoordinates(Loc.GetString( "blob-not-enough-resources", ("point", abilityCost.Int() - money.Int())), - observer.Value, + coordinates.Value, observer.Value, PopupType.Large); return false; } - coordinates ??= Transform(observer.Value).Coordinates; - _popup.PopupCoordinates( Loc.GetString("blob-spent-resource", ("point", abilityCost.Int())), coordinates.Value, @@ -680,6 +648,23 @@ public bool TryUseAbility(Entity core, FixedPoint2 abilityCos public Entity? GetNearNode( EntityCoordinates coords, float radius = 3f) + { + // Core IS in fact a node, so we need to also check it + var nodeEnt = + GetNearTile(BlobTileType.Node, coords, radius) ?? + GetNearTile(BlobTileType.Core, coords, radius); + + if (!_node.TryComp(nodeEnt, out var nodeComp)) + return null; + + Entity node = (nodeEnt.Value.Owner, nodeComp); + return node; + } + + public Entity? GetNearTile( + BlobTileType tileType, + EntityCoordinates coords, + float radius = 3f) { var gridUid = _transform.GetGrid(coords)!.Value; @@ -687,7 +672,7 @@ public bool TryUseAbility(Entity core, FixedPoint2 abilityCos return null; var nearestDistance = float.MaxValue; - var nodeComponent = new BlobNodeComponent(); + var tileComponent = new BlobTileComponent(); var nearestEntityUid = EntityUid.Invalid; var innerTiles = _mapSystem.GetLocalTilesIntersecting( @@ -702,8 +687,12 @@ public bool TryUseAbility(Entity core, FixedPoint2 abilityCos { foreach (var ent in _mapSystem.GetAnchoredEntities(gridUid, grid, tileRef.GridIndices)) { - if (!_node.TryComp(ent, out var nodeComp)) + if (!_tile.TryComp(ent, out var tileComp)) continue; + + if (tileComp.BlobTileType != tileType) + continue; + var tileCords = Transform(ent).Coordinates; var distance = Vector2.Distance(coords.Position, tileCords.Position); @@ -712,10 +701,10 @@ public bool TryUseAbility(Entity core, FixedPoint2 abilityCos nearestDistance = distance; nearestEntityUid = ent; - nodeComponent = nodeComp; + tileComponent = tileComp; } } - return nearestDistance > radius ? null : (nearestEntityUid, nodeComponent); + return nearestDistance > radius ? null : (nearestEntityUid, tileComponent); } } diff --git a/Content.Server/Backmen/Blob/BlobFactorySystem.cs b/Content.Server/Backmen/Blob/Systems/BlobFactorySystem.cs similarity index 84% rename from Content.Server/Backmen/Blob/BlobFactorySystem.cs rename to Content.Server/Backmen/Blob/Systems/BlobFactorySystem.cs index 6d7878024ed..773316a86c8 100644 --- a/Content.Server/Backmen/Blob/BlobFactorySystem.cs +++ b/Content.Server/Backmen/Blob/Systems/BlobFactorySystem.cs @@ -1,8 +1,4 @@ -using Content.Server.Backmen.Blob.Components; -using Content.Server.Popups; -using Content.Shared.Backmen.Blob; using Content.Shared.Backmen.Blob.Components; -using Content.Shared.Backmen.Blob.NPC.BlobPod; using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.Reagent; using Content.Shared.Damage; @@ -11,15 +7,15 @@ using Content.Shared.FixedPoint; using Content.Shared.Weapons.Melee; using Robust.Shared.Prototypes; -using Robust.Shared.Timing; -namespace Content.Server.Backmen.Blob; +namespace Content.Server.Backmen.Blob.Systems; public sealed class BlobFactorySystem : EntitySystem { - [Dependency] private readonly PopupSystem _popup = default!; [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + private EntityQuery _tile; + private EntityQuery _core; public override void Initialize() { @@ -29,6 +25,8 @@ public override void Initialize() SubscribeLocalEvent(OnProduceBlobbernaut); SubscribeLocalEvent(OnDestruction); + _tile = GetEntityQuery(); + _core = GetEntityQuery(); } private void OnDestruction(EntityUid uid, BlobFactoryComponent component, DestructionEventArgs args) @@ -44,10 +42,10 @@ private void OnProduceBlobbernaut(EntityUid uid, BlobFactoryComponent component, if (component.Blobbernaut != null) return; - if (!TryComp(uid, out var blobTileComponent) || blobTileComponent.Core == null) + if (!_tile.TryComp(uid, out var blobTileComponent) || blobTileComponent.Core == null) return; - if (!TryComp(blobTileComponent.Core, out var blobCoreComponent)) + if (!_core.TryComp(blobTileComponent.Core, out var blobCoreComponent)) return; var xform = Transform(uid); @@ -104,7 +102,8 @@ private void FillSmokeGas(Entity ent, BlobChemType currentChem blobGas.AddSolution(new Solution(Phlogiston, FixedPoint2.New(30)) { Temperature = 1000 - },_prototypeManager); + }, + _prototypeManager); break; case BlobChemType.ReactiveSpines: blobGas.AddSolution(new Solution(Mold, FixedPoint2.New(30)),_prototypeManager); @@ -116,7 +115,8 @@ private void FillSmokeGas(Entity ent, BlobChemType currentChem blobGas.AddSolution(new Solution(Lexorin, FixedPoint2.New(30)) { Temperature = 1000 - },_prototypeManager); + }, + _prototypeManager); break; case BlobChemType.ElectromagneticWeb: blobGas.AddSolution(new Solution(Aluminium, FixedPoint2.New(10)){ CanReact = false },_prototypeManager); @@ -131,30 +131,30 @@ private void FillSmokeGas(Entity ent, BlobChemType currentChem private void OnPulsed(EntityUid uid, BlobFactoryComponent component, BlobSpecialGetPulseEvent args) { - if (!TryComp(uid, out var blobTileComponent) || blobTileComponent.Core == null) + if (component.SpawnedCount >= component.MaxPods) return; - if (!TryComp(blobTileComponent.Core, out var blobCoreComponent)) - return; - - if (component.SpawnedCount >= component.SpawnLimit) - return; - - var xform = Transform(uid); - if (component.Accumulator < component.AccumulateToSpawn) { component.Accumulator++; return; } + if (!_tile.TryComp(uid, out var blobTileComponent) || blobTileComponent.Core == null) + return; + + if (!_core.TryComp(blobTileComponent.Core, out var blobCoreComponent)) + return; + + var core = blobTileComponent.Core.Value; + var xform = Transform(uid); + var pod = Spawn(component.Pod, xform.Coordinates); component.BlobPods.Add(pod); var blobPod = EnsureComp(pod); - blobPod.Core = blobTileComponent.Core.Value; + blobPod.Core = core; FillSmokeGas((pod,blobPod), blobCoreComponent.CurrentChem); - //smokeOnTrigger.SmokeColor = blobCoreComponent.ChemСolors[blobCoreComponent.CurrentChem]; component.SpawnedCount += 1; component.Accumulator = 0; } diff --git a/Content.Server/Backmen/Blob/BlobMobSystem.cs b/Content.Server/Backmen/Blob/Systems/BlobMobSystem.cs similarity index 83% rename from Content.Server/Backmen/Blob/BlobMobSystem.cs rename to Content.Server/Backmen/Blob/Systems/BlobMobSystem.cs index 127f331ad40..c67762ab076 100644 --- a/Content.Server/Backmen/Blob/BlobMobSystem.cs +++ b/Content.Server/Backmen/Blob/Systems/BlobMobSystem.cs @@ -1,34 +1,18 @@ -using System.Numerics; -using Content.Server.Backmen.Blob.Components; using Content.Server.Backmen.Language; -using Content.Server.Backmen.Language.Events; using Content.Server.Chat.Systems; -using Content.Server.Explosion.EntitySystems; -using Content.Server.Fluids.EntitySystems; -using Content.Server.Popups; using Content.Server.Radio; using Content.Server.Radio.Components; using Content.Server.Radio.EntitySystems; using Content.Shared.Backmen.Blob; -using Content.Shared.Backmen.Blob.Chemistry; using Content.Shared.Backmen.Blob.Components; using Content.Shared.Backmen.Language; using Content.Shared.Chat; -using Content.Shared.Chemistry.Components; using Content.Shared.Damage; -using Content.Shared.Interaction.Events; -using Content.Shared.Popups; using Content.Shared.Speech; -using Robust.Shared.Audio; -using Robust.Shared.Audio.Systems; -using Robust.Shared.Map; using Robust.Shared.Network; using Robust.Shared.Player; -using Robust.Shared.Prototypes; -using Robust.Shared.Random; -using Robust.Shared.Utility; -namespace Content.Server.Backmen.Blob; +namespace Content.Server.Backmen.Blob.Systems; public sealed class BlobMobSystem : SharedBlobMobSystem { @@ -36,7 +20,6 @@ public sealed class BlobMobSystem : SharedBlobMobSystem [Dependency] private readonly DamageableSystem _damageableSystem = default!; [Dependency] private readonly INetManager _netMan = default!; [Dependency] private readonly RadioSystem _radioSystem = default!; - private EntityQuery _activeBSpeak; public override void Initialize() { @@ -51,9 +34,6 @@ public override void Initialize() SubscribeLocalEvent(OnSpokeCan, after: new []{ typeof(SpeechSystem) }); SubscribeLocalEvent(OnSpoke, before: new []{ typeof(RadioSystem), typeof(HeadsetSystem) }); SubscribeLocalEvent(OnIntrinsicReceive); - //SubscribeLocalEvent(HandleSmokeTrigger); - - _activeBSpeak = GetEntityQuery(); } private void OnIntrinsicReceive(Entity ent, ref RadioReceiveEvent args) diff --git a/Content.Server/Backmen/Blob/BlobNodeSystem.cs b/Content.Server/Backmen/Blob/Systems/BlobNodeSystem.cs similarity index 91% rename from Content.Server/Backmen/Blob/BlobNodeSystem.cs rename to Content.Server/Backmen/Blob/Systems/BlobNodeSystem.cs index b9ef643555d..cd5088d746b 100644 --- a/Content.Server/Backmen/Blob/BlobNodeSystem.cs +++ b/Content.Server/Backmen/Blob/Systems/BlobNodeSystem.cs @@ -12,7 +12,7 @@ using Robust.Shared.Player; using Robust.Shared.Random; -namespace Content.Server.Backmen.Blob; +namespace Content.Server.Backmen.Blob.Systems; public sealed class BlobNodeSystem : EntitySystem { @@ -90,11 +90,19 @@ private IEnumerable> GetSpecialBlobsTiles(BlobNodeComp { yield return (component.BlobResource.Value, tileResourceComponent); } + if (!TerminatingOrDeleted(component.BlobStorage) && _tileQuery.TryComp(component.BlobStorage, out var tileStorageComponent)) + { + yield return (component.BlobStorage.Value, tileStorageComponent); + } + if (!TerminatingOrDeleted(component.BlobTurret) && _tileQuery.TryComp(component.BlobTurret, out var tileTurretComponent)) + { + yield return (component.BlobTurret.Value, tileTurretComponent); + } } private void OnDestruction(EntityUid uid, BlobNodeComponent component, DestructionEventArgs args) { - if (!TryComp(uid, out var tileComp) || + if (!_tileQuery.TryGetComponent(uid, out var tileComp) || tileComp.BlobTileType != BlobTileType.Node || tileComp.Core == null) return; diff --git a/Content.Server/Backmen/Blob/BlobObserverMover.cs b/Content.Server/Backmen/Blob/Systems/BlobObserverMover.cs similarity index 97% rename from Content.Server/Backmen/Blob/BlobObserverMover.cs rename to Content.Server/Backmen/Blob/Systems/BlobObserverMover.cs index 783ca13a252..5fad37270a8 100644 --- a/Content.Server/Backmen/Blob/BlobObserverMover.cs +++ b/Content.Server/Backmen/Blob/Systems/BlobObserverMover.cs @@ -1,13 +1,12 @@ using System.Threading; using System.Threading.Tasks; using Content.Shared.ActionBlocker; -using Content.Shared.Backmen.Blob; using Content.Shared.Backmen.Blob.Components; using Robust.Shared.CPUJob.JobQueues; using Robust.Shared.Map; using Robust.Shared.Timing; -namespace Content.Server.Backmen.Blob; +namespace Content.Server.Backmen.Blob.Systems; public sealed class BlobObserverMover : Job { diff --git a/Content.Server/Backmen/Blob/BlobObserverSystem.cs b/Content.Server/Backmen/Blob/Systems/BlobObserverSystem.cs similarity index 96% rename from Content.Server/Backmen/Blob/BlobObserverSystem.cs rename to Content.Server/Backmen/Blob/Systems/BlobObserverSystem.cs index 2dc417bd821..01fbd71caa3 100644 --- a/Content.Server/Backmen/Blob/BlobObserverSystem.cs +++ b/Content.Server/Backmen/Blob/Systems/BlobObserverSystem.cs @@ -1,16 +1,11 @@ using System.Linq; -using System.Numerics; using Content.Server.Actions; -using Content.Server.Backmen.Blob.Components; -using Content.Server.Backmen.Blob.Roles; using Content.Server.Backmen.GameTicking.Rules.Components; using Content.Server.Chat.Managers; using Content.Server.Hands.Systems; using Content.Server.Mind; using Content.Server.Roles; using Content.Shared.ActionBlocker; -using Content.Shared.Actions; -using Content.Shared.Alert; using Content.Shared.Backmen.Blob; using Content.Shared.Backmen.Blob.Components; using Content.Shared.Coordinates.Helpers; @@ -25,7 +20,7 @@ using Robust.Shared.Player; using Robust.Shared.Prototypes; -namespace Content.Server.Backmen.Blob; +namespace Content.Server.Backmen.Blob.Systems; public sealed class BlobObserverSystem : SharedBlobObserverSystem { @@ -55,7 +50,6 @@ public sealed class BlobObserverSystem : SharedBlobObserverSystem [ValidatePrototypeId] private const string BlobCaptureObjective = "BlobCaptureObjective"; [ValidatePrototypeId] private const string MobObserverBlobController = "MobObserverBlobController"; - [ValidatePrototypeId] private const string BlobHealth = "BlobHealth"; public override void Initialize() { @@ -210,10 +204,10 @@ private void OnChemSelected(EntityUid uid, BlobObserverComponent component, Blob if (component.SelectedChemId == args.SelectedId) return; - if (!ChangeChem(uid, args.SelectedId, component)) + if (!_blobCoreSystem.TryUseAbility(component.Core.Value, blobCoreComponent.SwapChemCost)) return; - _blobCoreSystem.TryUseAbility(component.Core.Value, blobCoreComponent.SwapChemCost); + ChangeChem(uid, args.SelectedId, component); } private bool ChangeChem(EntityUid uid, BlobChemType newChem, BlobObserverComponent component) @@ -313,7 +307,10 @@ private void OnSplitCore(EntityUid uid, } } - if (blobTile == null || !HasComp(blobTile)) + if (blobTile == null || + !HasComp(blobTile) || + !TryComp(blobTile, out var blobTileComp) || + blobTileComp.BlobTileType == BlobTileType.Core) { _popup.PopupEntity(Loc.GetString("blob-target-node-blob-invalid"), args.Performer, args.Performer, PopupType.Large); args.Handled = true; diff --git a/Content.Server/Backmen/Blob/BlobResourceSystem.cs b/Content.Server/Backmen/Blob/Systems/BlobResourceSystem.cs similarity index 77% rename from Content.Server/Backmen/Blob/BlobResourceSystem.cs rename to Content.Server/Backmen/Blob/Systems/BlobResourceSystem.cs index ce4d028ec0b..2d6cb08d6d5 100644 --- a/Content.Server/Backmen/Blob/BlobResourceSystem.cs +++ b/Content.Server/Backmen/Blob/Systems/BlobResourceSystem.cs @@ -1,10 +1,8 @@ using Content.Server.Backmen.Blob.Components; -using Content.Shared.Backmen.Blob; using Content.Shared.Backmen.Blob.Components; -using Content.Shared.FixedPoint; using Content.Shared.Popups; -namespace Content.Server.Backmen.Blob; +namespace Content.Server.Backmen.Blob.Systems; public sealed class BlobResourceSystem : EntitySystem { @@ -33,11 +31,6 @@ private void OnPulsed(EntityUid uid, BlobResourceComponent component, T args) blobCoreComponent.Observer == null) return; - _popup.PopupEntity(Loc.GetString("blob-get-resource", ("point", component.PointsPerPulsed)), - uid, - blobCoreComponent.Observer.Value, - PopupType.LargeGreen); - var points = component.PointsPerPulsed; if (blobCoreComponent.CurrentChem == BlobChemType.RegenerativeMateria) @@ -45,12 +38,11 @@ private void OnPulsed(EntityUid uid, BlobResourceComponent component, T args) points += 1; } - if (_blobCoreSystem.ChangeBlobPoint(blobTileComponent.Core.Value, points)) - { - _popup.PopupClient(Loc.GetString("blob-get-resource", ("point", points)), - uid, - blobCoreComponent.Observer.Value, - PopupType.LargeGreen); - } + _popup.PopupEntity(Loc.GetString("blob-get-resource", ("point", points)), + uid, + blobCoreComponent.Observer.Value, + PopupType.LargeGreen); + + _blobCoreSystem.ChangeBlobPoint(blobTileComponent.Core.Value, points); } } diff --git a/Content.Server/Backmen/Blob/Systems/BlobStorageSystem.cs b/Content.Server/Backmen/Blob/Systems/BlobStorageSystem.cs new file mode 100644 index 00000000000..c67899dd1e5 --- /dev/null +++ b/Content.Server/Backmen/Blob/Systems/BlobStorageSystem.cs @@ -0,0 +1,39 @@ +using Content.Shared.Backmen.Blob.Components; +using Content.Shared.Destructible; + +namespace Content.Server.Backmen.Blob.Systems; + +public sealed class BlobStorageSystem : EntitySystem +{ + [Dependency] private readonly BlobCoreSystem _blobCore = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnTransformed); + SubscribeLocalEvent(KillStorage); + SubscribeLocalEvent(KillStorage); + } + + private void OnTransformed(Entity ent, ref BlobTransformTileEvent args) + { + if (!TryComp(ent, out var tileComp) || + tileComp.Core == null || + TerminatingOrDeleted(tileComp.Core.Value.Owner)) + return; + + tileComp.Core.Value.Comp.MaxStorageAmount += ent.Comp.AddTotalStorage; + } + + private void KillStorage(EntityUid uid, BlobStorageComponent component, T args) + { + if (!TryComp(uid, out var tileComp) || + tileComp.Core == null || + TerminatingOrDeleted(tileComp.Core.Value.Owner)) + return; + + tileComp.Core.Value.Comp.MaxStorageAmount -= component.AddTotalStorage; + _blobCore.ChangeBlobPoint(tileComp.Core.Value, -component.DeleteOnRemove); + } +} diff --git a/Content.Server/Backmen/Blob/Systems/BlobTileSystem.cs b/Content.Server/Backmen/Blob/Systems/BlobTileSystem.cs new file mode 100644 index 00000000000..764468ab1a0 --- /dev/null +++ b/Content.Server/Backmen/Blob/Systems/BlobTileSystem.cs @@ -0,0 +1,243 @@ +using System.Linq; +using System.Numerics; +using Content.Server.Construction.Components; +using Content.Server.Destructible; +using Content.Server.Emp; +using Content.Server.Flash; +using Content.Shared.Backmen.Blob; +using Content.Shared.Backmen.Blob.Components; +using Content.Shared.Damage; +using Content.Shared.Destructible; +using Content.Shared.Mobs.Components; +using Content.Shared.NPC.Components; +using Content.Shared.NPC.Prototypes; +using Content.Shared.NPC.Systems; +using Robust.Server.Audio; +using Robust.Server.GameObjects; +using Robust.Shared.Audio; +using Robust.Shared.Map.Components; +using Robust.Shared.Player; +using Robust.Shared.Random; + +namespace Content.Server.Backmen.Blob.Systems; + +public sealed class BlobTileSystem : SharedBlobTileSystem +{ + [Dependency] private readonly DamageableSystem _damageableSystem = default!; + [Dependency] private readonly BlobCoreSystem _blobCoreSystem = default!; + [Dependency] private readonly AudioSystem _audioSystem = default!; + [Dependency] private readonly EmpSystem _empSystem = default!; + [Dependency] private readonly MapSystem _mapSystem = default!; + [Dependency] private readonly TransformSystem _transform = default!; + [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly NpcFactionSystem _npcFactionSystem = default!; + + private EntityQuery _blobCoreQuery; + + [ValidatePrototypeId] + private const string BlobFaction = "Blob"; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnMapInit); + SubscribeLocalEvent(OnDestruction); + SubscribeLocalEvent(OnPulsed); + SubscribeLocalEvent(OnFlashAttempt); + SubscribeLocalEvent(OnTerminate); + + _blobCoreQuery = GetEntityQuery(); + } + + private void OnMapInit(Entity ent, ref MapInitEvent args) + { + var faction = EnsureComp(ent); + Entity factionEnt = (ent, faction); + + _npcFactionSystem.ClearFactions(factionEnt, false); + _npcFactionSystem.AddFaction(factionEnt, BlobFaction); + + // make alive - true for npc combat + EnsureComp(ent); + EnsureComp(ent); + } + + private void OnTerminate(EntityUid uid, BlobTileComponent component, EntityTerminatingEvent args) + { + if (TerminatingOrDeleted(component.Core)) + return; + + component.Core!.Value.Comp.BlobTiles.Remove(uid); + } + + private void OnFlashAttempt(EntityUid uid, BlobTileComponent component, FlashAttemptEvent args) + { + if (args.Used == null || MetaData(args.Used.Value).EntityPrototype?.ID != "GrenadeFlashBang") + return; + + // THINK FAST CHUKKLENUTS + if (component.BlobTileType == BlobTileType.Normal) + { + _damageableSystem.TryChangeDamage(uid, component.FlashDamage); + } + } + + private void OnDestruction(EntityUid uid, BlobTileComponent component, DestructionEventArgs args) + { + if (TerminatingOrDeleted(component.Core) || + !_blobCoreQuery.TryComp(component.Core, out var blobCoreComponent)) + return; + + if (blobCoreComponent.CurrentChem == BlobChemType.ElectromagneticWeb) + { + _empSystem.EmpPulse(_transform.GetMapCoordinates(uid), 3f, 50f, 3f); + } + } + + private void OnPulsed(EntityUid uid, BlobTileComponent component, BlobTileGetPulseEvent args) + { + if (component.Core == null) + return; + + var core = component.Core.Value; + var xform = Transform(uid); + + HealTile((uid, component), core); + + if (!args.Handled) + return; + + if (!TryComp(xform.GridUid, out var grid)) + { + return; + } + + var nearNode = _blobCoreSystem.GetNearNode(xform.Coordinates, core.Comp.TilesRadiusLimit); + + if (nearNode == null) + return; + + var mobTile = _mapSystem.GetTileRef(xform.GridUid.Value, grid, xform.Coordinates); + + var mobAdjacentTiles = new[] + { + mobTile.GridIndices.Offset(Direction.East), + mobTile.GridIndices.Offset(Direction.West), + mobTile.GridIndices.Offset(Direction.North), + mobTile.GridIndices.Offset(Direction.South), + }; + + _random.Shuffle(mobAdjacentTiles); + + var localPos = xform.Coordinates.Position; + + var radius = 1.0f; + + var innerTiles = _mapSystem.GetLocalTilesIntersecting(xform.GridUid.Value, + grid, + new Box2(localPos + new Vector2(-radius, -radius), localPos + new Vector2(radius, radius))) + .ToArray(); + + foreach (var innerTile in innerTiles) + { + if (!mobAdjacentTiles.Contains(innerTile.GridIndices)) + { + continue; + } + + foreach (var ent in _mapSystem.GetAnchoredEntities(xform.GridUid.Value, grid, innerTile.GridIndices)) + { + if (!HasComp(ent) || !HasComp(ent)) + continue; + + DoLunge(uid, ent); + _damageableSystem.TryChangeDamage(ent, core.Comp.ChemDamageDict[core.Comp.CurrentChem]); + _audioSystem.PlayPvs(core.Comp.AttackSound, uid, AudioParams.Default); + args.Handled = true; + return; + } + + var spawn = true; + foreach (var ent in _mapSystem.GetAnchoredEntities(xform.GridUid.Value, grid, innerTile.GridIndices)) + { + if (!HasComp(ent)) + continue; + spawn = false; + break; + } + + if (!spawn) + continue; + + var location = _mapSystem.ToCoordinates(xform.GridUid.Value, innerTile.GridIndices, grid); + + if (_blobCoreSystem.TransformBlobTile(null, + core, + nearNode, + BlobTileType.Normal, + location)) + return; + } + } + + private void HealTile(Entity ent, Entity core) + { + var healCore = ent.Comp.HealthOfPulse; + + if (core.Comp.CurrentChem == BlobChemType.RegenerativeMateria) + { + foreach (var keyValuePair in ent.Comp.HealthOfPulse.DamageDict) + { + healCore.DamageDict.Add(keyValuePair.Key, keyValuePair.Value * 2); + } + } + + _damageableSystem.TryChangeDamage(ent, healCore); + } + + protected override void TryUpgrade(Entity target, Entity core, EntityUid observer) + { + var ev = new BlobTransformTileActionEvent( + performer: observer, + target: Transform(target).Coordinates, + transformFrom: target.Comp1.BlobTileType, + tileType: target.Comp2.TransformTo); + + RaiseLocalEvent(core, ev); + } + + public void SwapSpecials(Entity from, Entity to) + { + (from.Comp.BlobFactory, to.Comp.BlobFactory) = (to.Comp.BlobFactory, from.Comp.BlobFactory); + (from.Comp.BlobResource, to.Comp.BlobResource) = (to.Comp.BlobResource, from.Comp.BlobResource); + (from.Comp.BlobStorage, to.Comp.BlobStorage) = (to.Comp.BlobStorage, from.Comp.BlobStorage); + (from.Comp.BlobTurret, to.Comp.BlobTurret) = (to.Comp.BlobTurret, from.Comp.BlobTurret); + Dirty(from); + Dirty(to); + } + + public bool IsEmptySpecial(Entity node, BlobTileType tile) + { + return tile switch + { + BlobTileType.Factory => node.Comp.BlobFactory == null || TerminatingOrDeleted(node.Comp.BlobFactory), + BlobTileType.Resource => node.Comp.BlobResource == null || TerminatingOrDeleted(node.Comp.BlobResource), + BlobTileType.Storage => node.Comp.BlobStorage == null || TerminatingOrDeleted(node.Comp.BlobStorage), + BlobTileType.Turret => node.Comp.BlobTurret == null || TerminatingOrDeleted(node.Comp.BlobTurret), + _ => false + }; + } + + public void DoLunge(EntityUid from, EntityUid target) + { + if(!TransformQuery.TryComp(from, out var userXform)) + return; + + var targetPos = _transform.GetWorldPosition(target); + var localPos = Vector2.Transform(targetPos, _transform.GetInvWorldMatrix(userXform)); + localPos = userXform.LocalRotation.RotateVec(localPos); + + RaiseNetworkEvent(new BlobAttackEvent(GetNetEntity(from), GetNetEntity(target), localPos), Filter.Pvs(from)); + } +} diff --git a/Content.Server/Backmen/Blob/BlobbernautSystem.cs b/Content.Server/Backmen/Blob/Systems/BlobbernautSystem.cs similarity index 98% rename from Content.Server/Backmen/Blob/BlobbernautSystem.cs rename to Content.Server/Backmen/Blob/Systems/BlobbernautSystem.cs index 9dfc337f203..f59836d7945 100644 --- a/Content.Server/Backmen/Blob/BlobbernautSystem.cs +++ b/Content.Server/Backmen/Blob/Systems/BlobbernautSystem.cs @@ -15,7 +15,7 @@ using Robust.Shared.Random; using Robust.Shared.Timing; -namespace Content.Server.Backmen.Blob; +namespace Content.Server.Backmen.Blob.Systems; public sealed class BlobbernautSystem : SharedBlobbernautSystem { diff --git a/Content.Server/Backmen/Blob/ZombieBlobSystem.cs b/Content.Server/Backmen/Blob/Systems/ZombieBlobSystem.cs similarity index 98% rename from Content.Server/Backmen/Blob/ZombieBlobSystem.cs rename to Content.Server/Backmen/Blob/Systems/ZombieBlobSystem.cs index 0155a6a6a3c..b67e7081046 100644 --- a/Content.Server/Backmen/Blob/ZombieBlobSystem.cs +++ b/Content.Server/Backmen/Blob/Systems/ZombieBlobSystem.cs @@ -1,5 +1,4 @@ -using Content.Server.Atmos; -using Content.Server.Atmos.Components; +using Content.Server.Atmos.Components; using Content.Server.Backmen.Blob.Components; using Content.Server.Backmen.Body.Components; using Content.Server.Body.Components; @@ -8,10 +7,8 @@ using Content.Server.Explosion.EntitySystems; using Content.Server.Mind; using Content.Server.NPC; -using Content.Server.NPC.Components; using Content.Server.NPC.HTN; using Content.Server.NPC.Systems; -using Content.Server.Roles; using Content.Server.Speech.Components; using Content.Server.Temperature.Components; using Content.Shared.Atmos; @@ -34,7 +31,7 @@ using Robust.Shared.Player; using Robust.Shared.Prototypes; -namespace Content.Server.Backmen.Blob; +namespace Content.Server.Backmen.Blob.Systems; public sealed class ZombieBlobSystem : SharedZombieBlobSystem { diff --git a/Content.Server/Backmen/GameTicking/Rules/Components/BlobRuleComponent.cs b/Content.Server/Backmen/GameTicking/Rules/Components/BlobRuleComponent.cs index f8195cb31ed..baaceae8cc4 100644 --- a/Content.Server/Backmen/GameTicking/Rules/Components/BlobRuleComponent.cs +++ b/Content.Server/Backmen/GameTicking/Rules/Components/BlobRuleComponent.cs @@ -1,5 +1,4 @@ -using Content.Server.Backmen.Blob; -using Content.Shared.Backmen.Blob.Components; +using Content.Server.Backmen.Blob.Systems; using Content.Shared.Mind; using Robust.Shared.Audio; diff --git a/Content.Server/Backmen/Objectives/Systems/BlobCaptureObjectiveSystem.cs b/Content.Server/Backmen/Objectives/Systems/BlobCaptureObjectiveSystem.cs new file mode 100644 index 00000000000..7d5f288e85f --- /dev/null +++ b/Content.Server/Backmen/Objectives/Systems/BlobCaptureObjectiveSystem.cs @@ -0,0 +1,70 @@ +using Content.Server.Backmen.Blob.Components; +using Content.Server.Station.Systems; +using Content.Shared.Backmen.Blob.Components; +using Content.Shared.Objectives.Components; + +namespace Content.Server.Backmen.Objectives.Systems; + +public sealed class BlobCaptureObjectiveSystem : EntitySystem +{ + [Dependency] private readonly StationSystem _stationSystem = default!; + [Dependency] private readonly MetaDataSystem _metaDataSystem = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnBlobCaptureProgress); + SubscribeLocalEvent(OnBlobCaptureInfo); + SubscribeLocalEvent(OnBlobCaptureInfoAdd); + } + + + private void OnBlobCaptureInfoAdd(Entity ent, ref ObjectiveAssignedEvent args) + { + if (args.Mind.OwnedEntity == null) + { + args.Cancelled = true; + return; + } + if (!TryComp(args.Mind.OwnedEntity, out var blobObserverComponent) + || !HasComp(blobObserverComponent.Core)) + { + args.Cancelled = true; + return; + } + + var station = _stationSystem.GetOwningStation(blobObserverComponent.Core); + if (station == null) + { + args.Cancelled = true; + return; + } + + ent.Comp.Target = CompOrNull(station)?.StageTheEnd ?? StationBlobConfigComponent.DefaultStageEnd; + } + + private void OnBlobCaptureInfo(EntityUid uid, BlobCaptureConditionComponent component, ref ObjectiveAfterAssignEvent args) + { + _metaDataSystem.SetEntityName(uid,Loc.GetString("objective-condition-blob-capture-title")); + _metaDataSystem.SetEntityDescription(uid,Loc.GetString("objective-condition-blob-capture-description", ("count", component.Target))); + } + + private void OnBlobCaptureProgress(EntityUid uid, BlobCaptureConditionComponent component, ref ObjectiveGetProgressEvent args) + { + if (!TryComp(args.Mind.OwnedEntity, out var blobObserverComponent) + || !TryComp(blobObserverComponent.Core, out var blobCoreComponent)) + { + args.Progress = 0; + return; + } + + var target = component.Target; + args.Progress = 0; + + if (target != 0) + args.Progress = MathF.Min((float) blobCoreComponent.BlobTiles.Count / target, 1f); + else + args.Progress = 1f; + } +} diff --git a/Content.Server/Body/Components/RespiratorComponent.cs b/Content.Server/Body/Components/RespiratorComponent.cs index 8ae3c19a2ae..7a6a633e777 100644 --- a/Content.Server/Body/Components/RespiratorComponent.cs +++ b/Content.Server/Body/Components/RespiratorComponent.cs @@ -81,7 +81,7 @@ public sealed partial class RespiratorComponent : Component /// /// Whether the entity is immuned to pressure (i.e possess the PressureImmunity component) /// - [ViewVariables, Access(typeof(Backmen.Blob.ZombieBlobSystem))] + [ViewVariables, Access(typeof(Backmen.Blob.Systems.ZombieBlobSystem))] public bool HasImmunity = false; } } diff --git a/Content.Shared/Backmen/Blob/BlobTypedStorage.cs b/Content.Shared/Backmen/Blob/BlobTypedStorage.cs index 232d1f1a458..50af9a809b1 100644 --- a/Content.Shared/Backmen/Blob/BlobTypedStorage.cs +++ b/Content.Shared/Backmen/Blob/BlobTypedStorage.cs @@ -26,12 +26,10 @@ public abstract partial class BlobTypedStorage : IEnumerable Reflective, BlobTileType.Strong => Strong, BlobTileType.Normal => Normal, - /* BlobTileType.Storage => Storage, BlobTileType.Turret => Turret, - */ _ => throw new ArgumentOutOfRangeException(nameof(type), $"Unknown tile type: {type}") }; set @@ -80,14 +76,12 @@ public T this[BlobTileType type] case BlobTileType.Normal: Normal = value; break; - /* case BlobTileType.Storage: Storage = value; break; case BlobTileType.Turret: Turret = value; break; - */ default: throw new ArgumentOutOfRangeException(nameof(type), $"Unknown tile type: {type}"); } @@ -109,10 +103,8 @@ public IEnumerator> GetEnumerator() yield return new KeyValuePair(BlobTileType.Reflective, Reflective); yield return new KeyValuePair(BlobTileType.Strong, Strong); yield return new KeyValuePair(BlobTileType.Normal, Normal); - /* yield return new KeyValuePair(BlobTileType.Storage, Storage); yield return new KeyValuePair(BlobTileType.Turret, Turret); - */ } IEnumerator IEnumerable.GetEnumerator() diff --git a/Content.Shared/Backmen/Blob/Components/BlobCoreComponent.cs b/Content.Shared/Backmen/Blob/Components/BlobCoreComponent.cs index 53aa4b253aa..c56f73e539b 100644 --- a/Content.Shared/Backmen/Blob/Components/BlobCoreComponent.cs +++ b/Content.Shared/Backmen/Blob/Components/BlobCoreComponent.cs @@ -30,6 +30,9 @@ public sealed partial class BlobCoreComponent : Component [ViewVariables] public BlobChemType CurrentChem = BlobChemType.ReactiveSpines; + [ViewVariables] + public FixedPoint2 MaxStorageAmount = 200; + #endregion #region Balance @@ -46,6 +49,9 @@ public sealed partial class BlobCoreComponent : Component [DataField] public bool CanSplit = true; + [DataField] + public float TilesRadiusLimit = 9f; + #endregion #region Damage Specifiers @@ -145,9 +151,8 @@ public sealed partial class BlobCoreComponent : Component {BlobTileType.Reflective, 15}, {BlobTileType.Strong, 15}, {BlobTileType.Normal, 6}, - /* {BlobTileType.Storage, 50}, - {BlobTileType.Turret, 75},*/ + {BlobTileType.Turret, 75}, }; [DataField] @@ -164,16 +169,6 @@ public sealed partial class BlobCoreComponent : Component #endregion - #region Blob Ranges - - [DataField] - public float NodeRadiusLimit = 5f; - - [DataField] - public float TilesRadiusLimit = 9f; - - #endregion - #region Prototypes [DataField] @@ -186,8 +181,8 @@ public sealed partial class BlobCoreComponent : Component {BlobTileType.Strong, "StrongBlobTile"}, {BlobTileType.Normal, "NormalBlobTile"}, {BlobTileType.Invalid, "NormalBlobTile"}, // wtf - //{BlobTileType.Storage, "StorageBlobTile"}, - //{BlobTileType.Turret, "TurretBlobTile"}, + {BlobTileType.Storage, "StorageBlobTile"}, + {BlobTileType.Turret, "TurretBlobTile"}, {BlobTileType.Core, "CoreBlobTile"}, }; diff --git a/Content.Shared/Backmen/Blob/Components/BlobFactoryComponent.cs b/Content.Shared/Backmen/Blob/Components/BlobFactoryComponent.cs new file mode 100644 index 00000000000..09743f6bf8a --- /dev/null +++ b/Content.Shared/Backmen/Blob/Components/BlobFactoryComponent.cs @@ -0,0 +1,33 @@ +using Robust.Shared.Prototypes; + +namespace Content.Shared.Backmen.Blob.Components; + +[RegisterComponent] +public sealed partial class BlobFactoryComponent : Component +{ + [DataField] + public int MaxPods = 3; + + [DataField] + public int AccumulateToSpawn = 4; + + [DataField] + public EntProtoId Pod = "MobBlobPod"; + + [DataField] + public EntProtoId BlobbernautId = "MobBlobBlobbernaut"; + + [ViewVariables(VVAccess.ReadOnly)] + public EntityUid? Blobbernaut = default!; + + [ViewVariables(VVAccess.ReadOnly)] + public HashSet BlobPods = []; + + [ViewVariables(VVAccess.ReadOnly)] + public int SpawnedCount = 0; + + [ViewVariables(VVAccess.ReadOnly)] + public int Accumulator; +} + +public sealed class ProduceBlobbernautEvent : EntityEventArgs; diff --git a/Content.Shared/Backmen/Blob/Components/BlobNodeComponent.cs b/Content.Shared/Backmen/Blob/Components/BlobNodeComponent.cs index af499f5a700..b7bd4db0a94 100644 --- a/Content.Shared/Backmen/Blob/Components/BlobNodeComponent.cs +++ b/Content.Shared/Backmen/Blob/Components/BlobNodeComponent.cs @@ -20,12 +20,10 @@ public sealed partial class BlobNodeComponent : Component public EntityUid? BlobResource = null; [ViewVariables(VVAccess.ReadOnly), AutoNetworkedField] public EntityUid? BlobFactory = null; - /* [ViewVariables(VVAccess.ReadOnly), AutoNetworkedField] public EntityUid? BlobStorage = null; [ViewVariables(VVAccess.ReadOnly), AutoNetworkedField] public EntityUid? BlobTurret = null; - */ } public sealed class BlobTileGetPulseEvent : HandledEntityEventArgs diff --git a/Content.Shared/Backmen/Blob/Components/BlobObserverComponent.cs b/Content.Shared/Backmen/Blob/Components/BlobObserverComponent.cs index 05244571492..d4d94ed1052 100644 --- a/Content.Shared/Backmen/Blob/Components/BlobObserverComponent.cs +++ b/Content.Shared/Backmen/Blob/Components/BlobObserverComponent.cs @@ -1,11 +1,6 @@ using Content.Shared.Actions; -using Content.Shared.Antag; -using Content.Shared.Damage; -using Content.Shared.FixedPoint; -using Content.Shared.StatusIcon; using Robust.Shared.GameStates; using Robust.Shared.Map; -using Robust.Shared.Prototypes; using Robust.Shared.Serialization; namespace Content.Shared.Backmen.Blob.Components; @@ -16,7 +11,7 @@ public sealed partial class BlobObserverControllerComponent : Component public Entity Blob; } -[RegisterComponent, NetworkedComponent, AutoGenerateComponentState(false)] +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] public sealed partial class BlobObserverComponent : Component { [ViewVariables] @@ -60,6 +55,9 @@ public enum BlobChemSwapUiKey : byte Key } +/// +/// Tries to transform the Target blob tile in other type, making checks for Node and/or similar tiles. +/// public sealed partial class BlobTransformTileActionEvent : WorldTargetActionEvent { /// @@ -76,42 +74,30 @@ public sealed partial class BlobTransformTileActionEvent : WorldTargetActionEven public BlobTileType TileType = BlobTileType.Invalid; /// - /// Does this tile requires node nearby. + /// If specified, tries to find a blob node + /// in given radius and returns back if failed. /// [DataField] - public bool RequireNode = true; + public float? NodeSearchRadius; - public BlobTransformTileActionEvent(EntityUid performer, EntityCoordinates target, BlobTileType transformFrom, BlobTileType tileType, bool requireNode) : this() + /// + /// If specified, tries to find a tile of the same type + /// in given radius and returns back if failed. + /// + [DataField] + public float? TileSearchRadius; + + public BlobTransformTileActionEvent(EntityUid performer, EntityCoordinates target, BlobTileType transformFrom, BlobTileType tileType) { Performer = performer; Target = target; TransformFrom = transformFrom; TileType = tileType; - RequireNode = requireNode; } } -public sealed partial class BlobCreateBlobbernautActionEvent : WorldTargetActionEvent -{ - -} - -public sealed partial class BlobSplitCoreActionEvent : WorldTargetActionEvent -{ - -} - -public sealed partial class BlobSwapCoreActionEvent : WorldTargetActionEvent -{ - -} - -public sealed partial class BlobToCoreActionEvent : InstantActionEvent -{ - -} - -public sealed partial class BlobSwapChemActionEvent : InstantActionEvent -{ - -} +public sealed partial class BlobCreateBlobbernautActionEvent : WorldTargetActionEvent; +public sealed partial class BlobSplitCoreActionEvent : WorldTargetActionEvent; +public sealed partial class BlobSwapCoreActionEvent : WorldTargetActionEvent; +public sealed partial class BlobToCoreActionEvent : InstantActionEvent; +public sealed partial class BlobSwapChemActionEvent : InstantActionEvent; diff --git a/Content.Server/Backmen/Blob/Components/BlobResourceComponent.cs b/Content.Shared/Backmen/Blob/Components/BlobResourceComponent.cs similarity index 57% rename from Content.Server/Backmen/Blob/Components/BlobResourceComponent.cs rename to Content.Shared/Backmen/Blob/Components/BlobResourceComponent.cs index 4e7711ecc66..6b9b559aa3e 100644 --- a/Content.Server/Backmen/Blob/Components/BlobResourceComponent.cs +++ b/Content.Shared/Backmen/Blob/Components/BlobResourceComponent.cs @@ -1,10 +1,10 @@ using Content.Shared.FixedPoint; -namespace Content.Server.Backmen.Blob.Components; +namespace Content.Shared.Backmen.Blob.Components; [RegisterComponent] public sealed partial class BlobResourceComponent : Component { - [ViewVariables(VVAccess.ReadWrite), DataField("pointsPerPulsed")] + [DataField] public FixedPoint2 PointsPerPulsed = 3; } diff --git a/Content.Shared/Backmen/Blob/Components/BlobStorageComponent.cs b/Content.Shared/Backmen/Blob/Components/BlobStorageComponent.cs new file mode 100644 index 00000000000..5166a682e6c --- /dev/null +++ b/Content.Shared/Backmen/Blob/Components/BlobStorageComponent.cs @@ -0,0 +1,13 @@ +using Content.Shared.FixedPoint; + +namespace Content.Shared.Backmen.Blob.Components; + +[RegisterComponent] +public sealed partial class BlobStorageComponent : Component +{ + [DataField] + public FixedPoint2 AddTotalStorage = 100; + + [DataField] + public FixedPoint2 DeleteOnRemove = 50; +} diff --git a/Content.Shared/Backmen/Blob/Components/BlobTileComponent.cs b/Content.Shared/Backmen/Blob/Components/BlobTileComponent.cs index 8ac7953fba8..302f03dc2b4 100644 --- a/Content.Shared/Backmen/Blob/Components/BlobTileComponent.cs +++ b/Content.Shared/Backmen/Blob/Components/BlobTileComponent.cs @@ -16,6 +16,9 @@ public sealed partial class BlobTileComponent : Component [DataField] public bool ReturnCost = true; + [DataField] + public FixedPoint2 PulseHealCost = 0.2; + [DataField(required: true)] public BlobTileType BlobTileType = BlobTileType.Invalid; @@ -38,7 +41,7 @@ public sealed partial class BlobTileComponent : Component { DamageDict = new Dictionary { - { "Heat", 24 }, + { "Heat", 12 }, // Makes normal tile 1 HP away from death } }; } @@ -51,11 +54,15 @@ public enum BlobTileType : byte Strong, Reflective, Resource, - /* Storage, Turret, - */ Node, Factory, Core, } + + +/// +/// Raised after the blob tile was successfully transformed. +/// +public sealed partial class BlobTransformTileEvent : EntityEventArgs; diff --git a/Content.Shared/Backmen/Blob/Components/BlobUpgradeableTileComponent.cs b/Content.Shared/Backmen/Blob/Components/BlobUpgradeableTileComponent.cs new file mode 100644 index 00000000000..28a59780a05 --- /dev/null +++ b/Content.Shared/Backmen/Blob/Components/BlobUpgradeableTileComponent.cs @@ -0,0 +1,11 @@ +namespace Content.Shared.Backmen.Blob.Components; + +[RegisterComponent] +public sealed partial class BlobUpgradeableTileComponent : Component +{ + [DataField] + public BlobTileType TransformTo = BlobTileType.Invalid; + + [DataField] + public LocId Locale = "error"; +} diff --git a/Content.Shared/Backmen/Blob/SharedBlobTileSystem.cs b/Content.Shared/Backmen/Blob/SharedBlobTileSystem.cs index 275fdf21546..2e79aa9164a 100644 --- a/Content.Shared/Backmen/Blob/SharedBlobTileSystem.cs +++ b/Content.Shared/Backmen/Blob/SharedBlobTileSystem.cs @@ -8,43 +8,37 @@ public abstract class SharedBlobTileSystem : EntitySystem protected EntityQuery ObserverQuery; protected EntityQuery CoreQuery; protected EntityQuery TransformQuery; + protected EntityQuery TileQuery; public override void Initialize() { base.Initialize(); - SubscribeLocalEvent>(AddUpgradeVerb); + SubscribeLocalEvent>(AddUpgradeVerb); ObserverQuery = GetEntityQuery(); CoreQuery = GetEntityQuery(); TransformQuery = GetEntityQuery(); + TileQuery = GetEntityQuery(); } - protected abstract void TryUpgrade(Entity target, Entity core, EntityUid observer); + protected abstract void TryUpgrade(Entity target, Entity core, EntityUid observer); - private void AddUpgradeVerb(EntityUid uid, BlobTileComponent component, GetVerbsEvent args) + private void AddUpgradeVerb(EntityUid uid, BlobUpgradeableTileComponent comp, GetVerbsEvent args) { - if (!ObserverQuery.TryGetComponent(args.User, out var ghostBlobComponent)) - return; - - if (ghostBlobComponent.Core == null || + if (!ObserverQuery.TryGetComponent(args.User, out var ghostBlobComponent) || + !TileQuery.TryGetComponent(uid, out var component) || + TransformQuery.TryGetComponent(uid, out var transformComponent) && !transformComponent.Anchored || + ghostBlobComponent.Core == null || component.Core == null || !CoreQuery.HasComponent(ghostBlobComponent.Core.Value)) return; - if (TransformQuery.TryGetComponent(uid, out var transformComponent) && !transformComponent.Anchored) - return; - - var verbName = component.BlobTileType switch - { - BlobTileType.Normal => Loc.GetString("blob-verb-upgrade-to-strong"), - BlobTileType.Strong => Loc.GetString("blob-verb-upgrade-to-reflective"), - _ => Loc.GetString("blob-verb-upgrade") - }; + var verbName = Loc.GetString(comp.Locale); AlternativeVerb verb = new() { - Act = () => TryUpgrade((uid, component), ghostBlobComponent.Core.Value, args.User), - Text = verbName + Act = () => TryUpgrade((uid, component, comp), ghostBlobComponent.Core.Value, args.User), + Text = verbName, }; args.Verbs.Add(verb); } diff --git a/Resources/Locale/ru-RU/backmen/blob/blob.ftl b/Resources/Locale/ru-RU/backmen/blob/blob.ftl index 598bc47ae20..b3e58918d82 100644 --- a/Resources/Locale/ru-RU/backmen/blob/blob.ftl +++ b/Resources/Locale/ru-RU/backmen/blob/blob.ftl @@ -3,7 +3,7 @@ blob-target-normal-blob-invalid = Неподходящий тип блоба. blob-target-factory-blob-invalid = Неподходящий тип блоба, необходимо выбрать фабрику. blob-target-node-blob-invalid = Неподходящий тип блоба, необходимо выбрать узел. blob-target-nearby-not-node = Рядом нету узла или ядра. -blob-target-close-to-node = Слишком близко к другому узлу. +blob-target-close-to-tile = Слишком близко к другой клетке данного типа. blob-target-already-produce-blobbernaut = Данная фабрика уже произвела блоббернаута. blob-target-already-connected = К узлу уже привязан блоб данного типа. blob-cant-split = Вы не можете разделить ядро. @@ -57,8 +57,12 @@ blob-alert-detect = На станции была обнаружена биоло blob-alert-critical = Биологическая угроза достигла критической массы, вам отправлены коды от ядерной боеголовки, вы должны немедленно взорвать станцию. # Actions -blob-create-factory-action-name = Создать блоб фабрику (80) -blob-create-factory-action-desc = Превращает выбраного нормального блоба в фабрику, которая способна произвести 3 споры и блоббернаута, если рядом есть узел или ядро. +blob-create-factory-action-name = Создать блоб фабрику (40) +blob-create-factory-action-desc = Превращает выбраного нормального блоба в фабрику, которая способна производить различных преспешников блоба, если рядом есть узел или ядро. +blob-create-storage-action-name = Создать блоб хранилище (50) +blob-create-storage-action-desc = Превращает выбраного нормального блоба в хранилище, которое расширяет максимальное количество ресурсов которое может иметь блоб. +blob-create-turret-action-name = Создать блоб турель (75) +blob-create-turret-action-desc = Превращает выбраного нормального блоба в турель, которая стреляет по врагам своими мелкими спорами, расходуя очки. blob-create-resource-action-name = Создать ресурсный блоб (60) blob-create-resource-action-desc = Превращает выбраного нормального блоба в ресурсного блоба который будет производить ресурсы если рядом есть узлы или ядро. blob-produce-blobbernaut-action-name = Произвести блоббернаута на фабрике (60) diff --git a/Resources/Prototypes/_Backmen/Actions/blob.yml b/Resources/Prototypes/_Backmen/Actions/blob.yml index e213f744117..25fc4fd1e55 100644 --- a/Resources/Prototypes/_Backmen/Actions/blob.yml +++ b/Resources/Prototypes/_Backmen/Actions/blob.yml @@ -10,6 +10,7 @@ event: !type:BlobTransformTileActionEvent transformFrom: Normal tileType: Factory + nodeSearchRadius: 3.0 itemIconStyle: BigAction range: 200 useDelay: 0.5 @@ -26,6 +27,24 @@ event: !type:BlobTransformTileActionEvent transformFrom: Normal tileType: Resource + nodeSearchRadius: 3.0 + itemIconStyle: BigAction + range: 200 + useDelay: 0.5 + +- type: entity + id: ActionCreateBlobStorage + name: blob-create-storage-action-name + description: blob-create-storage-action-desc + components: + - type: WorldTargetAction + icon: + sprite: Backmen/Interface/Actions/blob.rsi + state: blobStorage + event: !type:BlobTransformTileActionEvent + transformFrom: Normal + tileType: Storage + nodeSearchRadius: 3.0 itemIconStyle: BigAction range: 200 useDelay: 0.5 @@ -42,6 +61,7 @@ event: !type:BlobTransformTileActionEvent transformFrom: Normal tileType: Node + tileSearchRadius: 4.5 itemIconStyle: BigAction range: 200 useDelay: 0.5 diff --git a/Resources/Prototypes/_Backmen/Entities/Mobs/NPCs/blob/blob_tiles.yml b/Resources/Prototypes/_Backmen/Entities/Mobs/NPCs/blob/blob_tiles.yml index df7ab51c1a1..ca0193f6178 100644 --- a/Resources/Prototypes/_Backmen/Entities/Mobs/NPCs/blob/blob_tiles.yml +++ b/Resources/Prototypes/_Backmen/Entities/Mobs/NPCs/blob/blob_tiles.yml @@ -39,6 +39,9 @@ Heat: 1 - type: BlobTile blobTileType: Normal + - type: BlobUpgradeableTile + transformTo: Strong + locale: blob-verb-upgrade-to-strong - type: Destructible thresholds: - trigger: @@ -130,17 +133,18 @@ resource: 60 factory: 80 node: 50 - reflective: 15 + reflective: 20 strong: 15 normal: 6 -# storage: 50 -# turret: 75 + storage: 50 + turret: 75 actionPrototypes: - ActionSwapBlobChem - ActionTeleportBlobToCore - ActionCreateBlobFactory - ActionCreateBlobResource - ActionCreateBlobNode + - ActionCreateBlobStorage - ActionCreateBlobbernaut - ActionSplitBlobCore - ActionSwapBlobCore @@ -289,32 +293,75 @@ - type: entity parent: BaseBlob - id: StrongBlobTile - name: StrongBlobTile - description: The basis of defensive positions has not only a strength of 6 times, this tile is also capable of withstanding various gases in order to become an atmospheric technician to protect the core, for example, from plasma that the enemy can set on fire. + id: StorageBlobTile + name: Storage Blob + description: Stores blob points in itself, expanding the maximum amount of points that the blob can have. categories: [ HideSpawnMenu ] components: - - type: Airtight + - type: Temperature + heatDamage: + types: + Heat: 5 + coldDamage: {} + coldDamageThreshold: 0 + - type: Flammable + fireSpread: true + damage: + types: + Heat: 1 - type: BlobTile - blobTileType: Strong + blobTileType: Storage - type: Destructible thresholds: - trigger: !type:DamageTrigger - damage: 150 + damage: 100 behaviors: - !type:DoActsBehavior acts: [ "Destruction" ] + - type: BlobStorage - type: Sprite sprite: Backmen/Mobs/Aliens/Blob/blob.rsi drawdepth: BlobTiles layers: - map: [ "enum.DamageStateVisualLayers.Base" ] - state: blob_shield + state: blob_special - map: [ "enum.DamageStateVisualLayers.BaseUnshaded" ] - state: blob_glow + state: blob_glow_special + - state: blob_storage_overlay # shader: unshaded +- type: entity + parent: BaseBlob + id: StrongBlobTile + name: StrongBlobTile + description: The basis of defensive positions has not only a strength of 6 times, this tile is also capable of withstanding various gases in order to become an atmospheric technician to protect the core, for example, from plasma that the enemy can set on fire. + categories: [ HideSpawnMenu ] + components: + - type: Airtight + - type: BlobTile + blobTileType: Strong + - type: BlobUpgradeableTile + transformTo: Reflective + locale: blob-verb-upgrade-to-reflective + - type: Destructible + thresholds: + - trigger: + !type:DamageTrigger + damage: 150 + behaviors: + - !type:DoActsBehavior + acts: [ "Destruction" ] + - type: Sprite + sprite: Backmen/Mobs/Aliens/Blob/blob.rsi + drawdepth: BlobTiles + layers: + - map: [ "enum.DamageStateVisualLayers.Base" ] + state: blob_shield + - map: [ "enum.DamageStateVisualLayers.BaseUnshaded" ] + state: blob_glow +# shader: unshaded + - type: entity parent: BaseBlob id: ReflectiveBlobTile diff --git a/Resources/Textures/Backmen/Interface/Actions/blob.rsi/blobStorage.png b/Resources/Textures/Backmen/Interface/Actions/blob.rsi/blobStorage.png new file mode 100644 index 0000000000000000000000000000000000000000..77a9dcc1faf3f2a0355395c7baab87c788aa3e73 GIT binary patch literal 3111 zcmV+?4A}FDP)Px=;Ymb6R9J;|mPw3d*ICE^XSl<=_rCk4dNt2O4^`FO?!gImY-A#$kOYK4L5Lk7 zA+}5sQY54-*uVlQ3l@TSJ%)rzgP9<@s8(wEbPcb z;4gif|F`(*obUe~9cG$ljWH4C{Z0AFfPax5c%`U z3qwMDXbcGit+iH4>o`_gaRyREDj^UDgC-~qNQcS7EccjT&?#`XnRc{BDusjr4L-Z( z@!56cj&EVZ5K^1jcw%ggp)@XV@_-V1n5~(P#gWEt{#@5<_cSt2uJ7L%jLJ~s@f)JT zm<}~j5|hxehP20$No$lj-9u^zE%a=c_~cdTs07feo2zfD4x71T)9k8;prPaJ7&jlk z)l0*M4hwU_^G7(MzD9V$BG-}xfXPB)IYpqg$y3J?8YV}k9GL_lj)CS8Lg_%lhA?f$ zdL0c&1}*^7z}&iv{DOgARblu2KBQqYcq1I8DPhJ#jckd@=U;NewV#Ezc245X%{a}J zVa;C(m>&N|J1?k3Y^6$hWd7jN?Y@^=GT+$g`Dlh`!FMz7 z6s+9CovrQ|4Kmxc!@!iBb7FyPgc13Jy5>P~fI^0l8X9F!WA*Ccy3h7xMi6uk@M9qI zEKl!;%(0abd%$Fg;r<=Mp<&>yz!~Omh2rYGwu+YssHLWDRnFD_E59@ObJ3;RUHKjZ zQ=E$kfRdb%Sp6zrdhh!}(QyhfE>PlxTp+MKmLT+F8D}&M0W5_YJ01g06SF@C2n%>7 z0eW4+o!Fq=v+2Xrvs}}^Twi?JZdofgQ#^A)V`U9uSn4irJp@Y~yI?u6ZC{P@8WVDI zU1psegYHnO6QR*lMrr|BWkF>%a<+z*65N!)EMQp^4i~_96+wv?N{OkJmhlx}TRV{z*tB1wwi^MLPz~*FU{q`Pb)PQUO{wYu~G=cyK0ThNn$tDEZ2+Nj2hX-hWV3w z=uo3pA3~l`D`2`H$|KIVmaYnO*ih))UwYVHLsqUN*|`cuaA`q=xU?_9&}JHXw0K(hm! zx^-YH#c0J&L}k9|Hx^DZz0z6j35JW$^1L_7Evdnn@|0yo8o%~CmBly)o*0eX%t?>g zvjiOiPdtY8Pl58kj?bw5PoMM_M}cb>0Z$QB0xZm#u)Ml)n6+gvCs)2s^(?0Tm8vzfU7rE}D7d1@KM{C%5 z%4%r~{?TCRezT^6bZYOpiRs9k?=r-UaNhw&KgW5ne(nFD1A~E$z7=Ar0d%51D_@^f ztp}m*J;T`1tE}7qz`ft?9e=sn)Vx>Mkevh7FD{t|=^VMl!b2~w`0aOj(mA|RrxtAvX-!()V_|eNdSS}3! zdw_n-pof~F%=qFIgBK|zc2Wwuin?(!X4~fAY%c_xKX0p|aE~j=VB(Lzlaapyg<@af z&CL);$Ar;w=#Ud1^#O8$Yv26jA^P+UJo@KTl$~Rgd;l)cF&GYO9JTj=H&clO43`#x zp#uK)?+B*w&YryAF=W)zp}US^u?hK-?cv9d&#<+lF*p&4T98Jf3Ne7}KkR3Yy%G>$kHuFVJcZ(V-4U8}2q+1{94Ug}Re zf?&GZ14GL5^TNrEl53m5J9`c6Y!Jo+w{l{ak6Tx>c=cWH*c+AL6+&-dVk`ur6=1bY zSQ!JRG6stN5amn^d-4puc?EZxBR>mVzd=ZYgUr`gPiDunW0By6inEqMy-gS&BWL!y z;R{3XKS3hnW-FGZ5<@A@?lv)Yx^ZUpH3I+I&v)jBzNWr>qs9F&UTuxCt;< z!?Zbsk)mH_D8>w!1^@w+1SWh!_FUadmK#&!zr@C0`Gf2$2Rp54f6O#@?}dRJHmMgH zyen)r+k2GR+~+zSex>^C)D3|g*WkM$ZlC3AjnnyudsCa^6JCPaP{U0)1``4!S%$)h zMO0pi&0$x@Y)_bA9|Zvs_&h`OV}+Bq+Wdp3{t4$oq#8N~kE|S*k{Ba7%5vd=VG!{! z_fl|WH7BrpXmpPLC%4spF}+dSUwoT$u6x5&#s)`RCp5Zt@K~&!{!G#IPRx1eq+}hk z*UjJbZD5c9X92(%Fv$_kaV&IF(X!h!`5S|o=F0{u8+g(_(`Bg@FgV6ZtCb4#8_^Zt z<47Z8Xy&ar(jrmBAxV?PiP1nr%@o$C3GDc3rZqS%zIIZC6Kz=LQqx+Rvhmj_BYZu; z3yqi>dcb0 zm%lhH@9l8?@LqeWZ!lwq6T$#+&T(996S~>1Z%zk@b0$iD1|RMXP`MBKMf$DNtn)*6 zTRzP0zENn?kr#sP+Jj}vxFcPsO>70#{er!$j(}@rGb-bi0!|3J1dzN_bX*1rtD04`ubk> zy_;?~s2kZGt^_QG@BLe3Bq2p)69*WCSCrp2Y#}ea;BwA6Uj551q!7v8oB7+VW@03c z%C4_VB*o6X5Y?W-QW036>)X9|qq=Pd`t9ny$-&PwejAa2~07P9K$h(YKPBwl4>~5Bx@gm|rQ@uXJy0kBrXJdv)R`;+oi^d=W3hjD*z*Bs zW?DuQ1Oo7rUk3qToPl{|=KG^uf`Ims4#FNqPKjkQIc~N0R2PgXBGLe34B$ovrd#H= zm1P_ZNJFB24N=sm)EkB8c?=Lh5ChG9-AyA({ujPx&nn^@KRCt{2-7!uZK@`UEHvys0AmS7tDh`k)P1@8{5h-Xb&X5D393W?~Xk8dl zxu!{x#tjFcir4}Nxq(=~q;MV{mN8*wci$4}|7*Ym{AOo%*D1cYBLV;b0001B#-;wj z*R}wOfP3& z?=JqnKArztQ}p1k#`9yybwX#w=$M+Y((c3r>Dfuz)r)wWoKx+h;G zbqrzsuyMkIj$x_e zWU1q9>JPiFA4U_^;@>tlC7&b+tXnvVOUC zTlE0|00000000000002IOj%(fO(<_}`}<^Fo1xwR`C+bE$++^tZf(0=>wLb_hKX2g zzHZY~@v%qs54*0P`zYt^Y-qR$MX$YV{?4J_3%hpO65b6`)RvC6V7*bqbLCFHNDb*| zWz{4xJr!SmQu@4Ctobp-(%9vGu@p&Hz@js-?G6-y-{ zDoqLd!L)Af#umw=Uep+2m5(oPn4^o3yNy(;*yM}YwaEei00000000000001Z`Lcsq z<$R`<>l5+e15>TXp~0|l3{}RFoegaxsjLTY{kUQkrsC=vLsB;M?qas`ZJqto%h@xU z+k8y$^s?RZKYpyP zzWEsH`}j-m54fCt7*);1S5fqw*Sf_-j(!#X!|yBi-KxI!q!kl6IzMwaB8zty`In?y zkbd~YCO>x@rxcpO4<}zl= O0000 Date: Sat, 30 Nov 2024 14:46:21 +0300 Subject: [PATCH 2/9] The Rebalance --- .../Backmen/Blob/Systems/BlobCoreSystem.cs | 6 ++-- .../_Backmen/Damage/modifier_sets.yml | 36 +++++++++++-------- .../Entities/Mobs/NPCs/blob/blob_tiles.yml | 24 ++++++++----- 3 files changed, 40 insertions(+), 26 deletions(-) diff --git a/Content.Server/Backmen/Blob/Systems/BlobCoreSystem.cs b/Content.Server/Backmen/Blob/Systems/BlobCoreSystem.cs index 9a24056df47..a266e03fba7 100644 --- a/Content.Server/Backmen/Blob/Systems/BlobCoreSystem.cs +++ b/Content.Server/Backmen/Blob/Systems/BlobCoreSystem.cs @@ -264,14 +264,14 @@ public void ChangeBlobEntChem(EntityUid uid, BlobChemType newChem) switch (newChem) { case BlobChemType.ExplosiveLattice: - _damageable.SetDamageModifierSetId(uid, "ExplosiveLatticeBlob"); + //_damageable.SetDamageModifierSetId(uid, "ExplosiveLatticeBlob"); _explosionSystem.SetExplosionResistance(uid, 0f, EnsureComp(uid)); break; case BlobChemType.ElectromagneticWeb: - _damageable.SetDamageModifierSetId(uid, "ElectromagneticWebBlob"); + //_damageable.SetDamageModifierSetId(uid, "ElectromagneticWebBlob"); break; default: - _damageable.SetDamageModifierSetId(uid, "BaseBlob"); + //_damageable.SetDamageModifierSetId(uid, "BaseBlob"); break; } } diff --git a/Resources/Prototypes/_Backmen/Damage/modifier_sets.yml b/Resources/Prototypes/_Backmen/Damage/modifier_sets.yml index 70a06017ae5..9d28c14f94f 100644 --- a/Resources/Prototypes/_Backmen/Damage/modifier_sets.yml +++ b/Resources/Prototypes/_Backmen/Damage/modifier_sets.yml @@ -77,10 +77,10 @@ - type: damageModifierSet id: BaseBlob # ReactiveSpines coefficients: - Blunt: 0.25 - Slash: 0.25 - Piercing: 0.25 - Heat: 2.00 + Blunt: 0.30 + Slash: 0.40 + Piercing: 0.40 + Heat: 3.00 - type: damageModifierSet id: ElectromagneticWebBlob # Explosive Lattice @@ -101,20 +101,28 @@ Shock: 1.50 - type: damageModifierSet - id: BlobMob # Blob mobs + id: BlobMob coefficients: - Blunt: 0.5 - Slash: 0.5 - Piercing: 0.5 - Heat: 1.5 + Blunt: 0.50 + Slash: 0.50 + Piercing: 0.50 + Heat: 1.50 - type: damageModifierSet - id: BlobReflective # If it reflects lasers, then it must be fragile? + id: BlobStrong # Strong against melee and weak against lasers. coefficients: - Blunt: 0.9 - Slash: 0.9 - Piercing: 0.9 - Heat: 1.5 + Blunt: 0.20 + Slash: 0.20 + Piercing: 0.20 + Heat: 2.00 + +- type: damageModifierSet + id: BlobReflective # Defence against lasers, but weak against melee damage. + coefficients: + Blunt: 1.00 # Weak for melee damages + Slash: 1.10 + Piercing: 1.00 + Heat: 1.10 # Good against heat - type: damageModifierSet id: HardLightBarrier diff --git a/Resources/Prototypes/_Backmen/Entities/Mobs/NPCs/blob/blob_tiles.yml b/Resources/Prototypes/_Backmen/Entities/Mobs/NPCs/blob/blob_tiles.yml index ca0193f6178..034f652eb94 100644 --- a/Resources/Prototypes/_Backmen/Entities/Mobs/NPCs/blob/blob_tiles.yml +++ b/Resources/Prototypes/_Backmen/Entities/Mobs/NPCs/blob/blob_tiles.yml @@ -46,7 +46,7 @@ thresholds: - trigger: !type:DamageTrigger - damage: 25 + damage: 40 behaviors: - !type:DoActsBehavior acts: [ "Destruction" ] @@ -107,7 +107,7 @@ thresholds: - trigger: !type:DamageTrigger - damage: 400 + damage: 250 behaviors: - !type:DoActsBehavior acts: [ "Destruction" ] @@ -197,7 +197,7 @@ thresholds: - trigger: !type:DamageTrigger - damage: 120 + damage: 80 behaviors: - !type:DoActsBehavior acts: [ "Destruction" ] @@ -235,7 +235,7 @@ thresholds: - trigger: !type:DamageTrigger - damage: 90 + damage: 80 behaviors: - !type:DoActsBehavior acts: [ "Destruction" ] @@ -275,7 +275,7 @@ thresholds: - trigger: !type:DamageTrigger - damage: 150 + damage: 100 behaviors: - !type:DoActsBehavior acts: [ "Destruction" ] @@ -315,7 +315,7 @@ thresholds: - trigger: !type:DamageTrigger - damage: 100 + damage: 80 behaviors: - !type:DoActsBehavior acts: [ "Destruction" ] @@ -344,11 +344,14 @@ - type: BlobUpgradeableTile transformTo: Reflective locale: blob-verb-upgrade-to-reflective + - type: Damageable + damageContainer: Blob + damageModifierSet: BlobStrong - type: Destructible thresholds: - trigger: !type:DamageTrigger - damage: 150 + damage: 100 behaviors: - !type:DoActsBehavior acts: [ "Destruction" ] @@ -372,6 +375,9 @@ - type: Airtight - type: BlobTile blobTileType: Reflective + - type: Damageable + damageContainer: Blob + damageModifierSet: BlobReflective - type: Destructible thresholds: - trigger: @@ -381,8 +387,8 @@ - !type:DoActsBehavior acts: [ "Destruction" ] - type: Reflect - reflectProb: 0.6 - spread: 20 + reflectProb: 0.5 + spread: 40 reflects: - Energy - type: Sprite From 69a990e1c60445031c8679be0c4edff496d4bfeb Mon Sep 17 00:00:00 2001 From: Roudenn Date: Sat, 30 Nov 2024 14:55:42 +0300 Subject: [PATCH 3/9] fix --- Content.Shared/Backmen/Blob/BlobTypedStorage.cs | 12 ++++++------ .../Backmen/Blob/Components/BlobCoreComponent.cs | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Content.Shared/Backmen/Blob/BlobTypedStorage.cs b/Content.Shared/Backmen/Blob/BlobTypedStorage.cs index 50af9a809b1..533159d6019 100644 --- a/Content.Shared/Backmen/Blob/BlobTypedStorage.cs +++ b/Content.Shared/Backmen/Blob/BlobTypedStorage.cs @@ -28,8 +28,8 @@ public abstract partial class BlobTypedStorage : IEnumerable Strong, BlobTileType.Normal => Normal, BlobTileType.Storage => Storage, - BlobTileType.Turret => Turret, + //BlobTileType.Turret => Turret, _ => throw new ArgumentOutOfRangeException(nameof(type), $"Unknown tile type: {type}") }; set @@ -79,9 +79,9 @@ public T this[BlobTileType type] case BlobTileType.Storage: Storage = value; break; - case BlobTileType.Turret: + /*case BlobTileType.Turret: Turret = value; - break; + break;*/ default: throw new ArgumentOutOfRangeException(nameof(type), $"Unknown tile type: {type}"); } @@ -104,7 +104,7 @@ public IEnumerator> GetEnumerator() yield return new KeyValuePair(BlobTileType.Strong, Strong); yield return new KeyValuePair(BlobTileType.Normal, Normal); yield return new KeyValuePair(BlobTileType.Storage, Storage); - yield return new KeyValuePair(BlobTileType.Turret, Turret); + //yield return new KeyValuePair(BlobTileType.Turret, Turret); } IEnumerator IEnumerable.GetEnumerator() diff --git a/Content.Shared/Backmen/Blob/Components/BlobCoreComponent.cs b/Content.Shared/Backmen/Blob/Components/BlobCoreComponent.cs index c56f73e539b..9f38332802d 100644 --- a/Content.Shared/Backmen/Blob/Components/BlobCoreComponent.cs +++ b/Content.Shared/Backmen/Blob/Components/BlobCoreComponent.cs @@ -182,7 +182,7 @@ public sealed partial class BlobCoreComponent : Component {BlobTileType.Normal, "NormalBlobTile"}, {BlobTileType.Invalid, "NormalBlobTile"}, // wtf {BlobTileType.Storage, "StorageBlobTile"}, - {BlobTileType.Turret, "TurretBlobTile"}, + //{BlobTileType.Turret, "TurretBlobTile"}, {BlobTileType.Core, "CoreBlobTile"}, }; From 9e45c4a2c8ff59dcedba02af19a8cb968dd1df2b Mon Sep 17 00:00:00 2001 From: Roudenn Date: Sun, 1 Dec 2024 11:44:32 +0300 Subject: [PATCH 4/9] Update blob_tiles.yml --- .../Prototypes/_Backmen/Entities/Mobs/NPCs/blob/blob_tiles.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Resources/Prototypes/_Backmen/Entities/Mobs/NPCs/blob/blob_tiles.yml b/Resources/Prototypes/_Backmen/Entities/Mobs/NPCs/blob/blob_tiles.yml index 034f652eb94..07ae843bd35 100644 --- a/Resources/Prototypes/_Backmen/Entities/Mobs/NPCs/blob/blob_tiles.yml +++ b/Resources/Prototypes/_Backmen/Entities/Mobs/NPCs/blob/blob_tiles.yml @@ -137,7 +137,7 @@ strong: 15 normal: 6 storage: 50 - turret: 75 + #turret: 75 actionPrototypes: - ActionSwapBlobChem - ActionTeleportBlobToCore From 2127521cbee691a5dc7f91f5f2024bd88567474c Mon Sep 17 00:00:00 2001 From: Roudenn Date: Sun, 1 Dec 2024 11:53:44 +0300 Subject: [PATCH 5/9] Update BlobCoreComponent.cs --- Content.Shared/Backmen/Blob/Components/BlobCoreComponent.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Content.Shared/Backmen/Blob/Components/BlobCoreComponent.cs b/Content.Shared/Backmen/Blob/Components/BlobCoreComponent.cs index 9f38332802d..c38e0563725 100644 --- a/Content.Shared/Backmen/Blob/Components/BlobCoreComponent.cs +++ b/Content.Shared/Backmen/Blob/Components/BlobCoreComponent.cs @@ -152,7 +152,7 @@ public sealed partial class BlobCoreComponent : Component {BlobTileType.Strong, 15}, {BlobTileType.Normal, 6}, {BlobTileType.Storage, 50}, - {BlobTileType.Turret, 75}, + //{BlobTileType.Turret, 75}, }; [DataField] From 0fd3245fa00da51c6e06ecbf35991ef914ed88c1 Mon Sep 17 00:00:00 2001 From: Roudenn Date: Sun, 1 Dec 2024 11:58:32 +0300 Subject: [PATCH 6/9] Update throwing_stars.yml --- .../_Backmen/Entities/Objects/Throwable/throwing_stars.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Resources/Prototypes/_Backmen/Entities/Objects/Throwable/throwing_stars.yml b/Resources/Prototypes/_Backmen/Entities/Objects/Throwable/throwing_stars.yml index b3020ca5737..9e3c83f260e 100644 --- a/Resources/Prototypes/_Backmen/Entities/Objects/Throwable/throwing_stars.yml +++ b/Resources/Prototypes/_Backmen/Entities/Objects/Throwable/throwing_stars.yml @@ -10,4 +10,4 @@ map: ["base"] - type: TimedDespawn lifetime: 30 - + - type: HolidayVisuals From e9d8017bd0217927cde6956a05e02c15b2a882a4 Mon Sep 17 00:00:00 2001 From: Roudenn Date: Sun, 1 Dec 2024 11:59:33 +0300 Subject: [PATCH 7/9] Revert "Update throwing_stars.yml" This reverts commit 0fd3245fa00da51c6e06ecbf35991ef914ed88c1. --- .../_Backmen/Entities/Objects/Throwable/throwing_stars.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Resources/Prototypes/_Backmen/Entities/Objects/Throwable/throwing_stars.yml b/Resources/Prototypes/_Backmen/Entities/Objects/Throwable/throwing_stars.yml index 9e3c83f260e..b3020ca5737 100644 --- a/Resources/Prototypes/_Backmen/Entities/Objects/Throwable/throwing_stars.yml +++ b/Resources/Prototypes/_Backmen/Entities/Objects/Throwable/throwing_stars.yml @@ -10,4 +10,4 @@ map: ["base"] - type: TimedDespawn lifetime: 30 - - type: HolidayVisuals + From d687108da526d655164e35004c40ca3afc5c4f43 Mon Sep 17 00:00:00 2001 From: Roudenn Date: Wed, 1 Jan 2025 22:10:30 +0300 Subject: [PATCH 8/9] coolish features --- .../Backmen/Blob/NPC/BlobPod/BlobPodSystem.cs | 2 +- .../Blob/Systems/BlobCoreActionSystem.cs | 10 +-- .../Backmen/Blob/Systems/BlobCoreSystem.cs | 9 +-- .../Backmen/Blob/Systems/BlobTileSystem.cs | 14 ----- .../GameTicking/Rules/BlobRuleSystem.cs | 60 ++++++++++++------ .../Blob/Components/BlobCoreComponent.cs | 2 +- .../Blob/Components/BlobStorageComponent.cs | 4 +- Resources/Locale/en-US/blob/blob.ftl | 12 +++- Resources/Locale/ru-RU/backmen/blob/blob.ftl | 11 +++- .../_Backmen/Damage/modifier_sets.yml | 28 ++------- .../Entities/Mobs/NPCs/blob/blob_tiles.yml | 63 ++++++++++--------- 11 files changed, 107 insertions(+), 108 deletions(-) diff --git a/Content.Server/Backmen/Blob/NPC/BlobPod/BlobPodSystem.cs b/Content.Server/Backmen/Blob/NPC/BlobPod/BlobPodSystem.cs index 944d15683cb..98326fcf0e6 100644 --- a/Content.Server/Backmen/Blob/NPC/BlobPod/BlobPodSystem.cs +++ b/Content.Server/Backmen/Blob/NPC/BlobPod/BlobPodSystem.cs @@ -75,7 +75,7 @@ private void OnDestruction(EntityUid uid, BlobPodComponent component, Destructio return; if (blobCoreComponent.CurrentChem == BlobChemType.ExplosiveLattice) { - _explosionSystem.QueueExplosion(uid, blobCoreComponent.BlobExplosive, 4, 1, 2, maxTileBreak: 0); + _explosionSystem.QueueExplosion(uid, blobCoreComponent.BlobExplosive, 4, 1, 2, maxTileBreak: 0, user: uid); } } diff --git a/Content.Server/Backmen/Blob/Systems/BlobCoreActionSystem.cs b/Content.Server/Backmen/Blob/Systems/BlobCoreActionSystem.cs index b09f43cbc57..cef35df3405 100644 --- a/Content.Server/Backmen/Blob/Systems/BlobCoreActionSystem.cs +++ b/Content.Server/Backmen/Blob/Systems/BlobCoreActionSystem.cs @@ -13,6 +13,8 @@ using Content.Shared.Damage; using Content.Shared.Interaction; using Content.Shared.Item; +using Content.Shared.Mobs; +using Content.Shared.Mobs.Components; using Content.Shared.Popups; using Content.Shared.SubFloor; using Robust.Server.Audio; @@ -46,6 +48,7 @@ public sealed class BlobCoreActionSystem : SharedBlobCoreActionSystem [Dependency] private readonly DamageableSystem _damageableSystem = default!; [Dependency] private readonly MapSystem _mapSystem = default!; [Dependency] private readonly IMapManager _mapManager = default!; + [Dependency] private readonly EntityLookupSystem _lookup = default!; [Dependency] private readonly BlobTileSystem _blobTileSystem = default!; //[Dependency] private readonly GridFixtureSystem _gridFixture = default!; @@ -119,8 +122,6 @@ private void BlobInteract(Entity observer, Entity observer, Entity observer, Entity ent, Entity(uid)); - break; - case BlobChemType.ElectromagneticWeb: - //_damageable.SetDamageModifierSetId(uid, "ElectromagneticWebBlob"); + _explosionSystem.SetExplosionResistance(uid, 0.1f, EnsureComp(uid)); break; default: - //_damageable.SetDamageModifierSetId(uid, "BaseBlob"); + _explosionSystem.SetExplosionResistance(uid, 0.7f, EnsureComp(uid)); break; } } diff --git a/Content.Server/Backmen/Blob/Systems/BlobTileSystem.cs b/Content.Server/Backmen/Blob/Systems/BlobTileSystem.cs index 764468ab1a0..63b1c8f3efd 100644 --- a/Content.Server/Backmen/Blob/Systems/BlobTileSystem.cs +++ b/Content.Server/Backmen/Blob/Systems/BlobTileSystem.cs @@ -3,7 +3,6 @@ using Content.Server.Construction.Components; using Content.Server.Destructible; using Content.Server.Emp; -using Content.Server.Flash; using Content.Shared.Backmen.Blob; using Content.Shared.Backmen.Blob.Components; using Content.Shared.Damage; @@ -44,7 +43,6 @@ public override void Initialize() SubscribeLocalEvent(OnMapInit); SubscribeLocalEvent(OnDestruction); SubscribeLocalEvent(OnPulsed); - SubscribeLocalEvent(OnFlashAttempt); SubscribeLocalEvent(OnTerminate); _blobCoreQuery = GetEntityQuery(); @@ -71,18 +69,6 @@ private void OnTerminate(EntityUid uid, BlobTileComponent component, EntityTermi component.Core!.Value.Comp.BlobTiles.Remove(uid); } - private void OnFlashAttempt(EntityUid uid, BlobTileComponent component, FlashAttemptEvent args) - { - if (args.Used == null || MetaData(args.Used.Value).EntityPrototype?.ID != "GrenadeFlashBang") - return; - - // THINK FAST CHUKKLENUTS - if (component.BlobTileType == BlobTileType.Normal) - { - _damageableSystem.TryChangeDamage(uid, component.FlashDamage); - } - } - private void OnDestruction(EntityUid uid, BlobTileComponent component, DestructionEventArgs args) { if (TerminatingOrDeleted(component.Core) || diff --git a/Content.Server/Backmen/GameTicking/Rules/BlobRuleSystem.cs b/Content.Server/Backmen/GameTicking/Rules/BlobRuleSystem.cs index fd0ad4c7f9e..fb5ac68d88f 100644 --- a/Content.Server/Backmen/GameTicking/Rules/BlobRuleSystem.cs +++ b/Content.Server/Backmen/GameTicking/Rules/BlobRuleSystem.cs @@ -187,6 +187,8 @@ private void CheckChangeStage( } } + private const string BlobIssuer = "objective-issuer-blob"; + protected override void AppendRoundEndText( EntityUid uid, BlobRuleComponent blob, @@ -194,9 +196,38 @@ protected override void AppendRoundEndText( ref RoundEndTextAppendEvent ev) { if (blob.Blobs.Count < 1) - return; + return; // no blob no fun var result = Loc.GetString("blob-round-end-result", ("blobCount", blob.Blobs.Count)); + var totalPercentage = 0f; + + // Get the total amount of blob tiles + foreach (var (mindId, mind) in blob.Blobs) + { + var objectives = mind.Objectives.ToArray(); + + foreach (var objective in objectives) + { + var comp = Comp(objective); + if (comp.Issuer != BlobIssuer) + continue; + + var info = _objectivesSystem.GetInfo(objective, mindId, mind); + totalPercentage += info?.Progress ?? 0; + } + } + + if (totalPercentage >= 0.99f) + { + result += "\n" + Loc.GetString("blob-end-victory"); + } + else + { + result += "\n" + Loc.GetString("blob-end-fail"); + result += "\n" + Loc.GetString("blob-end-fail-progress", ("progress", (int) (totalPercentage * 100))); + } + + result += "\n"; // yeah this is duplicated from traitor rules lol, there needs to be a generic rewrite where it just goes through all minds with objectives foreach (var (mindId, mind) in blob.Blobs) @@ -242,8 +273,11 @@ protected override void AppendRoundEndText( else if (name != null) result += "\n" + Loc.GetString("blob-was-a-blob-with-objectives-named", ("name", name)); - foreach (var objectiveGroup in objectives.GroupBy(o => Comp(o).LocIssuer)) + foreach (var objectiveGroup in objectives.GroupBy(o => Comp(o).Issuer == BlobIssuer)) { + if (!objectiveGroup.Key) + continue; + foreach (var objective in objectiveGroup) { @@ -251,26 +285,12 @@ protected override void AppendRoundEndText( if (info == null) continue; - var objectiveTitle = info.Value.Title; var progress = info.Value.Progress; - if (progress > 0.99f) - { - result += "\n- " + Loc.GetString( - "objective-condition-success", - ("condition", objectiveTitle), - ("markupColor", "green") - ); - } - else - { - result += "\n- " + Loc.GetString( - "objective-condition-fail", - ("condition", objectiveTitle), - ("progress", (int) (progress * 100)), - ("markupColor", "red") - ); - } + result += "\n- " + Loc.GetString( + "blob-objective-percentage", + ("progress", (int) (progress * 100)) + ); } } } diff --git a/Content.Shared/Backmen/Blob/Components/BlobCoreComponent.cs b/Content.Shared/Backmen/Blob/Components/BlobCoreComponent.cs index c38e0563725..5fa71c07d90 100644 --- a/Content.Shared/Backmen/Blob/Components/BlobCoreComponent.cs +++ b/Content.Shared/Backmen/Blob/Components/BlobCoreComponent.cs @@ -31,7 +31,7 @@ public sealed partial class BlobCoreComponent : Component public BlobChemType CurrentChem = BlobChemType.ReactiveSpines; [ViewVariables] - public FixedPoint2 MaxStorageAmount = 200; + public FixedPoint2 MaxStorageAmount = 500; #endregion diff --git a/Content.Shared/Backmen/Blob/Components/BlobStorageComponent.cs b/Content.Shared/Backmen/Blob/Components/BlobStorageComponent.cs index 5166a682e6c..e1c9a868d73 100644 --- a/Content.Shared/Backmen/Blob/Components/BlobStorageComponent.cs +++ b/Content.Shared/Backmen/Blob/Components/BlobStorageComponent.cs @@ -6,8 +6,8 @@ namespace Content.Shared.Backmen.Blob.Components; public sealed partial class BlobStorageComponent : Component { [DataField] - public FixedPoint2 AddTotalStorage = 100; + public FixedPoint2 AddTotalStorage = 200; [DataField] - public FixedPoint2 DeleteOnRemove = 50; + public FixedPoint2 DeleteOnRemove = 60; } diff --git a/Resources/Locale/en-US/blob/blob.ftl b/Resources/Locale/en-US/blob/blob.ftl index 816717e109b..6ada6c66919 100644 --- a/Resources/Locale/en-US/blob/blob.ftl +++ b/Resources/Locale/en-US/blob/blob.ftl @@ -17,6 +17,7 @@ blob-spent-resource = -{ $point } blobberaut-not-on-blob-tile = You are dying while not on blob tiles. blobberaut-factory-destroy = You are dying because your factory blob was destroyed. carrier-blob-alert = You have { $second } seconds left before transformation. +blob-core-under-attack = Your core is under attack! blob-mob-zombify-second-start = { $pod } starts turning you into a zombie. blob-mob-zombify-third-start = { $pod } starts turning { $target } into a zombie. @@ -112,11 +113,16 @@ blob-user-was-a-blob = [color=gray]{$user}[/color] was a blob. blob-user-was-a-blob-named = [color=White]{$name}[/color] ([color=gray]{$user}[/color]) was a blob. blob-was-a-blob-named = [color=White]{$name}[/color] was a blob. +blob-objective-percentage = It captured [color=White]{ $progress }%[/color] to the victory. +blob-end-victory = [color=Red]Blob(s) successfully absorbed the station![/color] +blob-end-fail = [color=Green]Blob(s) failed to absorb the station.[/color] +blob-end-fail-progress = All blobs captured [color=Yellow]{ $progress }%[/color] to the victory. + preset-blob-objective-issuer-blob = [color=#33cc00]Blob[/color] -blob-user-was-a-blob-with-objectives = [color=gray]{$user}[/color] was a blob who had the following objectives: -blob-user-was-a-blob-with-objectives-named = [color=White]{$name}[/color] ([color=gray]{$user}[/color]) was a blob who had the following objectives: -blob-was-a-blob-with-objectives-named = [color=White]{$name}[/color] was a blob who had the following objectives: +blob-user-was-a-blob-with-objectives = [color=gray]{$user}[/color] was a blob: +blob-user-was-a-blob-with-objectives-named = [color=White]{$name}[/color] ([color=gray]{$user}[/color]) was a blob: +blob-was-a-blob-with-objectives-named = [color=White]{$name}[/color] was a blob: # Objectivies objective-condition-blob-capture-title = Take over the station diff --git a/Resources/Locale/ru-RU/backmen/blob/blob.ftl b/Resources/Locale/ru-RU/backmen/blob/blob.ftl index b3e58918d82..9f59e0988f1 100644 --- a/Resources/Locale/ru-RU/backmen/blob/blob.ftl +++ b/Resources/Locale/ru-RU/backmen/blob/blob.ftl @@ -18,6 +18,7 @@ blob-mob-zombify-second-start = { $pod } начинает превращать blob-mob-zombify-third-start = { $pod } начинает превращать { $target } в зомби! blob-mob-zombify-second-end = { $pod } превращает вас в зомби! blob-mob-zombify-third-end = { $pod } превращает { $target } в зомби! +blob-core-under-attack = Ваше ядро находится под атакой! # UI blob-chem-swap-ui-window-name = Смена химиката @@ -125,9 +126,13 @@ blob-user-was-a-blob = [color=gray]{ $user }[/color] был блобом. blob-user-was-a-blob-named = [color=White]{ $name }[/color] ([color=gray]{ $user }[/color]) был блобом. blob-was-a-blob-named = [color=White]{ $name }[/color] был блобом. preset-blob-objective-issuer-blob = [color=#33cc00]Блоб[/color] -blob-user-was-a-blob-with-objectives = [color=gray]{ $user }[/color] был блобом и имел следующие цели: -blob-user-was-a-blob-with-objectives-named = [color=White]{ $name }[/color] ([color=gray]{ $user }[/color]) был блобом и имел следующие цели: -blob-was-a-blob-with-objectives-named = [color=White]{ $name }[/color] был блобом и имел следующие цели: +blob-user-was-a-blob-with-objectives = [color=gray]{ $user }[/color] был блобом: +blob-user-was-a-blob-with-objectives-named = [color=White]{ $name }[/color] ([color=gray]{ $user }[/color]) был блобом: +blob-was-a-blob-with-objectives-named = [color=White]{ $name }[/color] был блобом: +blob-objective-percentage = Он захватил [color=White]{ $progress }%[/color] до победы. +blob-end-victory = [color=Red]Блоб(ы) успешно поглотил станцию![/color] +blob-end-fail = [color=Green]Блоб(ы) не смог поглотить станцию.[/color] +blob-end-fail-progress = Суммарно было захвачено [color=Yellow]{ $progress }%[/color] до победы. # Objectivies objective-condition-blob-capture-title = Захватить станцию diff --git a/Resources/Prototypes/_Backmen/Damage/modifier_sets.yml b/Resources/Prototypes/_Backmen/Damage/modifier_sets.yml index 9d28c14f94f..e120ea5f9d0 100644 --- a/Resources/Prototypes/_Backmen/Damage/modifier_sets.yml +++ b/Resources/Prototypes/_Backmen/Damage/modifier_sets.yml @@ -82,24 +82,6 @@ Piercing: 0.40 Heat: 3.00 -- type: damageModifierSet - id: ElectromagneticWebBlob # Explosive Lattice - coefficients: - Blunt: 0.50 - Slash: 0.50 - Piercing: 0.50 - Heat: 2.50 - Shock: 0.50 - -- type: damageModifierSet - id: ExplosiveLatticeBlob # Explosive Lattice - coefficients: - Blunt: 0.25 - Slash: 0.25 - Piercing: 0.25 - Heat: 3.00 - Shock: 1.50 - - type: damageModifierSet id: BlobMob coefficients: @@ -111,9 +93,9 @@ - type: damageModifierSet id: BlobStrong # Strong against melee and weak against lasers. coefficients: - Blunt: 0.20 - Slash: 0.20 - Piercing: 0.20 + Blunt: 0.40 + Slash: 0.40 + Piercing: 0.30 Heat: 2.00 - type: damageModifierSet @@ -121,8 +103,8 @@ coefficients: Blunt: 1.00 # Weak for melee damages Slash: 1.10 - Piercing: 1.00 - Heat: 1.10 # Good against heat + Piercing: 0.90 + Heat: 0.80 # Good against heat - type: damageModifierSet id: HardLightBarrier diff --git a/Resources/Prototypes/_Backmen/Entities/Mobs/NPCs/blob/blob_tiles.yml b/Resources/Prototypes/_Backmen/Entities/Mobs/NPCs/blob/blob_tiles.yml index 07ae843bd35..83ece1fa5a4 100644 --- a/Resources/Prototypes/_Backmen/Entities/Mobs/NPCs/blob/blob_tiles.yml +++ b/Resources/Prototypes/_Backmen/Entities/Mobs/NPCs/blob/blob_tiles.yml @@ -107,7 +107,7 @@ thresholds: - trigger: !type:DamageTrigger - damage: 250 + damage: 500 behaviors: - !type:DoActsBehavior acts: [ "Destruction" ] @@ -351,7 +351,7 @@ thresholds: - trigger: !type:DamageTrigger - damage: 100 + damage: 150 behaviors: - !type:DoActsBehavior acts: [ "Destruction" ] @@ -372,31 +372,34 @@ description: Upgrading a fortified cell in which they pay less strength for the ability to reflect only energy projectiles and lasers with a 90% chance. categories: [ HideSpawnMenu ] components: - - type: Airtight - - type: BlobTile - blobTileType: Reflective - - type: Damageable - damageContainer: Blob - damageModifierSet: BlobReflective - - type: Destructible - thresholds: - - trigger: - !type:DamageTrigger - damage: 100 - behaviors: - - !type:DoActsBehavior - acts: [ "Destruction" ] - - type: Reflect - reflectProb: 0.5 - spread: 40 - reflects: - - Energy - - type: Sprite - sprite: Backmen/Mobs/Aliens/Blob/blob.rsi - drawdepth: BlobTiles - layers: - - map: [ "enum.DamageStateVisualLayers.Base" ] - state: blob_shield - - map: [ "enum.DamageStateVisualLayers.BaseUnshaded" ] - state: blob_glow - shader: unshaded + - type: Airtight + - type: BlobTile + blobTileType: Reflective + - type: BlobUpgradeableTile + transformTo: Strong + locale: blob-verb-upgrade-to-strong + - type: Damageable + damageContainer: Blob + damageModifierSet: BlobReflective + - type: Destructible + thresholds: + - trigger: + !type:DamageTrigger + damage: 150 + behaviors: + - !type:DoActsBehavior + acts: [ "Destruction" ] + - type: Reflect + reflectProb: 0.5 + spread: 40 + reflects: + - Energy + - type: Sprite + sprite: Backmen/Mobs/Aliens/Blob/blob.rsi + drawdepth: BlobTiles + layers: + - map: [ "enum.DamageStateVisualLayers.Base" ] + state: blob_shield + - map: [ "enum.DamageStateVisualLayers.BaseUnshaded" ] + state: blob_glow + shader: unshaded From d852d543d4721abe0579e049cc2dd7587b82841c Mon Sep 17 00:00:00 2001 From: Roudenn Date: Wed, 1 Jan 2025 22:11:50 +0300 Subject: [PATCH 9/9] Update BlobStorageComponent.cs --- Content.Shared/Backmen/Blob/Components/BlobStorageComponent.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Content.Shared/Backmen/Blob/Components/BlobStorageComponent.cs b/Content.Shared/Backmen/Blob/Components/BlobStorageComponent.cs index e1c9a868d73..eb09529fe72 100644 --- a/Content.Shared/Backmen/Blob/Components/BlobStorageComponent.cs +++ b/Content.Shared/Backmen/Blob/Components/BlobStorageComponent.cs @@ -6,7 +6,7 @@ namespace Content.Shared.Backmen.Blob.Components; public sealed partial class BlobStorageComponent : Component { [DataField] - public FixedPoint2 AddTotalStorage = 200; + public FixedPoint2 AddTotalStorage = 100; [DataField] public FixedPoint2 DeleteOnRemove = 60;