diff --git a/Content.Client/IgnoredComponents.cs b/Content.Client/IgnoredComponents.cs index 213c907773..f134c6dd15 100644 --- a/Content.Client/IgnoredComponents.cs +++ b/Content.Client/IgnoredComponents.cs @@ -195,7 +195,6 @@ namespace Content.Client "ContainmentField", "Emitter", "SingularityGenerator", - "EmitterBoltComponent", "ParticleProjectile", "ParticleAcceleratorControlBox", "ParticleAcceleratorEmitter", diff --git a/Content.Server/GameObjects/Components/AnchorableComponent.cs b/Content.Server/GameObjects/Components/AnchorableComponent.cs index bba1e91b22..af5de39bd7 100644 --- a/Content.Server/GameObjects/Components/AnchorableComponent.cs +++ b/Content.Server/GameObjects/Components/AnchorableComponent.cs @@ -1,4 +1,5 @@ #nullable enable +using System; using System.Diagnostics.CodeAnalysis; using System.Threading.Tasks; using Content.Server.GameObjects.Components.Interactable; @@ -74,6 +75,10 @@ namespace Content.Server.GameObjects.Components var physics = Owner.GetComponent(); physics.BodyType = BodyType.Static; + // Snap rotation to cardinal (multiple of 90) + var rot = Owner.Transform.LocalRotation; + Owner.Transform.LocalRotation = Math.Round(rot / (Math.PI / 2)) * (Math.PI / 2); + if (Owner.TryGetComponent(out PullableComponent? pullableComponent)) { if (pullableComponent.Puller != null) diff --git a/Content.Server/GameObjects/Components/Projectiles/EmitterBoltComponent.cs b/Content.Server/GameObjects/Components/Projectiles/EmitterBoltComponent.cs deleted file mode 100644 index 95ce080262..0000000000 --- a/Content.Server/GameObjects/Components/Projectiles/EmitterBoltComponent.cs +++ /dev/null @@ -1,10 +0,0 @@ -using Robust.Shared.GameObjects; - -namespace Content.Server.GameObjects.Components.Projectiles -{ - [RegisterComponent] - public class EmitterBoltComponent : Component - { - public override string Name => "EmitterBoltComponent"; - } -} diff --git a/Content.Server/GameObjects/Components/Singularity/ContainmentFieldConnection.cs b/Content.Server/GameObjects/Components/Singularity/ContainmentFieldConnection.cs index 48a3286922..fbb2bc3690 100644 --- a/Content.Server/GameObjects/Components/Singularity/ContainmentFieldConnection.cs +++ b/Content.Server/GameObjects/Components/Singularity/ContainmentFieldConnection.cs @@ -62,7 +62,7 @@ namespace Content.Server.GameObjects.Components.Singularity } containmentFieldComponent.Parent = this; - newEnt.Transform.WorldRotation = dirVec.ToAngle(); + newEnt.Transform.WorldRotation = dirVec.ToWorldAngle(); _fields.Add(newEnt); currentOffset += dirVec; diff --git a/Content.Server/GameObjects/Components/Singularity/ContainmentFieldGeneratorComponent.cs b/Content.Server/GameObjects/Components/Singularity/ContainmentFieldGeneratorComponent.cs index c050b7a44f..0ed970f06b 100644 --- a/Content.Server/GameObjects/Components/Singularity/ContainmentFieldGeneratorComponent.cs +++ b/Content.Server/GameObjects/Components/Singularity/ContainmentFieldGeneratorComponent.cs @@ -2,8 +2,7 @@ using System; using System.Diagnostics.CodeAnalysis; using System.Linq; -using Content.Server.GameObjects.Components.Projectiles; -using Content.Server.Utility; +using Content.Shared.GameObjects.Components.Tag; using Content.Shared.Physics; using Robust.Shared.GameObjects; using Robust.Shared.IoC; @@ -85,11 +84,7 @@ namespace Content.Server.GameObjects.Components.Singularity private void OnAnchoredChanged() { - if(_collidableComponent?.Anchored == true) - { - Owner.SnapToGrid(); - } - else + if(_collidableComponent?.Anchored != true) { _connection1?.Item2.Dispose(); _connection2?.Item2.Dispose(); @@ -186,8 +181,7 @@ namespace Content.Server.GameObjects.Components.Singularity void IStartCollide.CollideWith(IPhysBody ourBody, IPhysBody otherBody, in Manifold manifold) { - if (otherBody.Entity.HasComponent()) - { + if(otherBody.Entity.HasTag("EmitterBolt")) { ReceivePower(4); } } diff --git a/Content.Server/GameObjects/Components/Singularity/EmitterComponent.cs b/Content.Server/GameObjects/Components/Singularity/EmitterComponent.cs index d83ca52354..950fe392f5 100644 --- a/Content.Server/GameObjects/Components/Singularity/EmitterComponent.cs +++ b/Content.Server/GameObjects/Components/Singularity/EmitterComponent.cs @@ -1,3 +1,4 @@ +#nullable enable using System; using System.Threading; using System.Threading.Tasks; @@ -5,7 +6,7 @@ using Content.Server.GameObjects.Components.Access; using Content.Server.GameObjects.Components.Power.PowerNetComponents; using Content.Server.GameObjects.Components.Projectiles; using Content.Server.Interfaces; -using Content.Server.Utility; +using Content.Shared.Audio; using Content.Shared.GameObjects.Components.Singularity; using Content.Shared.Interfaces; using Content.Shared.Interfaces.GameObjects.Components; @@ -48,6 +49,11 @@ namespace Content.Server.GameObjects.Components.Singularity [ViewVariables] private bool _isPowered; [ViewVariables] private bool _isLocked; + // For the "emitter fired" sound + private const float Variation = 0.25f; + private const float Volume = 0.5f; + private const float Distance = 3f; + [ViewVariables(VVAccess.ReadWrite)] private int _fireShotCounter; [ViewVariables(VVAccess.ReadWrite)] [DataField("fireSound")] private string _fireSound = "/Audio/Weapons/emitter.ogg"; @@ -67,6 +73,7 @@ namespace Content.Server.GameObjects.Components.Singularity Logger.Error($"EmitterComponent {Owner} created with no PowerConsumerComponent"); return; } + _powerConsumer.OnReceivedPowerChanged += OnReceivedPowerChanged; } @@ -91,19 +98,26 @@ namespace Content.Server.GameObjects.Components.Singularity { if (_isLocked) { - Owner.PopupMessage(eventArgs.User, Loc.GetString("{0:TheName} is access locked!", Owner)); + Owner.PopupMessage(eventArgs.User, Loc.GetString("comp-emitter-access-locked", ("target", Owner))); return; } - if (!_isOn) + if (Owner.TryGetComponent(out PhysicsComponent? phys) && phys.Anchored) { - SwitchOn(); - Owner.PopupMessage(eventArgs.User, Loc.GetString("{0:TheName} turns on.", Owner)); + if (!_isOn) + { + SwitchOn(); + Owner.PopupMessage(eventArgs.User, Loc.GetString("comp-emitter-turned-on", ("target", Owner))); + } + else + { + SwitchOff(); + Owner.PopupMessage(eventArgs.User, Loc.GetString("comp-emitter-turned-off", ("target", Owner))); + } } else { - SwitchOff(); - Owner.PopupMessage(eventArgs.User, Loc.GetString("{0:TheName} turns off.", Owner)); + Owner.PopupMessage(eventArgs.User, Loc.GetString("comp-emitter-not-anchored", ("target", Owner))); } } @@ -120,18 +134,18 @@ namespace Content.Server.GameObjects.Components.Singularity if (_isLocked) { - Owner.PopupMessage(eventArgs.User, Loc.GetString("You lock {0:TheName}.", Owner)); + Owner.PopupMessage(eventArgs.User, Loc.GetString("comp-emitter-lock", ("target", Owner))); } else { - Owner.PopupMessage(eventArgs.User, Loc.GetString("You unlock {0:TheName}.", Owner)); + Owner.PopupMessage(eventArgs.User, Loc.GetString("comp-emitter-unlock", ("target", Owner))); } UpdateAppearance(); } else { - Owner.PopupMessage(eventArgs.User, Loc.GetString("Access denied.")); + Owner.PopupMessage(eventArgs.User, Loc.GetString("comp-emitter-access-denied")); } return Task.FromResult(true); @@ -222,7 +236,7 @@ namespace Content.Server.GameObjects.Components.Singularity if (!projectile.TryGetComponent(out var physicsComponent)) { - Logger.Error("Emitter tried firing a bolt, but it was spawned without a CollidableComponent"); + Logger.Error("Emitter tried firing a bolt, but it was spawned without a PhysicsComponent"); return; } @@ -238,13 +252,13 @@ namespace Content.Server.GameObjects.Components.Singularity physicsComponent .LinearVelocity = Owner.Transform.WorldRotation.ToWorldVec() * 20f; - projectile.Transform.WorldRotation = Owner.Transform.WorldRotation; // TODO: Move to projectile's code. Timer.Spawn(3000, () => projectile.Delete()); - EntitySystem.Get().PlayFromEntity(_fireSound, Owner); + EntitySystem.Get().PlayFromEntity(_fireSound, Owner, + AudioHelpers.WithVariation(Variation).WithVolume(Volume).WithMaxDistance(Distance)); } private void UpdateAppearance() diff --git a/Resources/Locale/en-US/components/emitter-component.ftl b/Resources/Locale/en-US/components/emitter-component.ftl new file mode 100644 index 0000000000..55b280e133 --- /dev/null +++ b/Resources/Locale/en-US/components/emitter-component.ftl @@ -0,0 +1,20 @@ +### EmitterComponent + +# Shows when attempting to turn the emitter on or off without proper access +comp-emitter-access-locked = The {$target} is access locked! + +# Shows when attempting to lock or unlock the emitter without proper access +comp-emitter-access-denied = Access denied. + +# Shows when locking/unlocking the emitter +comp-emitter-lock = You lock the {$target}. + +comp-emitter-unlock = You unlock the {$target}. + +# Shows when turning the emitter on/off +comp-emitter-turned-on = The {$target} turns on. + +comp-emitter-turned-off = The {$target} turns off. + +# Shows if the user attempts to activate the emitter while it's un-anchored. +comp-emitter-not-anchored = The {$target} isn't anchored to the ground! diff --git a/Resources/Locale/en-US/entities/emitter.ftl b/Resources/Locale/en-US/entities/emitter.ftl new file mode 100644 index 0000000000..00d53d55ab --- /dev/null +++ b/Resources/Locale/en-US/entities/emitter.ftl @@ -0,0 +1,4 @@ +### Emitter entity prototype data. + +ent-emitter = emitter + .desc = A machine that fires bolts of energy, used for powering containment fields at a safe distance. diff --git a/Resources/Maps/saltern.yml b/Resources/Maps/saltern.yml index 8e101403da..2340e7c396 100644 --- a/Resources/Maps/saltern.yml +++ b/Resources/Maps/saltern.yml @@ -43182,76 +43182,82 @@ entities: - uid: 4401 type: Emitter components: - - rot: 4.371139006309477E-08 rad - pos: 45.5,-17.5 + - pos: 45.5,-17.5 parent: 853 type: Transform - uid: 4402 type: Emitter components: - - rot: 4.371139006309477E-08 rad - pos: 49.5,-17.5 + - pos: 49.5,-17.5 parent: 853 type: Transform - uid: 4403 type: Emitter components: - - rot: 4.371139006309477E-08 rad - pos: 53.5,-17.5 + - pos: 53.5,-17.5 parent: 853 type: Transform - uid: 4404 type: Emitter components: - - pos: 56.5,-20.5 + - rot: -1.5707963267948966 rad + pos: 56.5,-20.5 parent: 853 type: Transform - uid: 4405 type: Emitter components: - - pos: 56.5,-24.5 + - rot: -1.5707963267948966 rad + pos: 56.5,-24.5 parent: 853 type: Transform - uid: 4406 type: Emitter components: - - pos: 56.5,-28.5 + - rot: -1.5707963267948966 rad + pos: 56.5,-28.5 parent: 853 type: Transform - uid: 4407 type: Emitter components: - - pos: 53.5,-31.5 + - rot: 3.141592653589793 rad + pos: 53.5,-31.5 parent: 853 type: Transform - uid: 4408 type: Emitter components: - - pos: 49.5,-31.5 + - rot: 3.141592653589793 rad + pos: 49.5,-31.5 parent: 853 type: Transform - uid: 4409 type: Emitter components: - - pos: 45.5,-31.5 + - rot: 3.141592653589793 rad + pos: 45.5,-31.5 parent: 853 type: Transform - uid: 4410 type: Emitter components: - - pos: 42.5,-28.5 + - rot: 1.5707963267948966 rad + pos: 42.5,-28.5 parent: 853 type: Transform - uid: 4411 type: Emitter components: - - pos: 42.5,-24.5 + - rot: 1.5707963267948966 rad + pos: 42.5,-24.5 parent: 853 type: Transform - uid: 4412 type: Emitter components: - - pos: 42.5,-20.5 + - rot: 1.5707963267948966 rad + pos: 42.5,-20.5 parent: 853 type: Transform - uid: 4413 diff --git a/Resources/Prototypes/Entities/Constructible/Specific/Engines/Singularity/collector.yml b/Resources/Prototypes/Entities/Constructible/Specific/Engines/Singularity/collector.yml index df860464ae..0c7bb30a2b 100644 --- a/Resources/Prototypes/Entities/Constructible/Specific/Engines/Singularity/collector.yml +++ b/Resources/Prototypes/Entities/Constructible/Specific/Engines/Singularity/collector.yml @@ -8,7 +8,7 @@ - type: Clickable - type: InteractionOutline - type: Physics - bodyType: Dynamic + bodyType: Static mass: 25 fixtures: - shape: diff --git a/Resources/Prototypes/Entities/Constructible/Specific/Engines/Singularity/containment.yml b/Resources/Prototypes/Entities/Constructible/Specific/Engines/Singularity/containment.yml index 6fdabea35b..c703be969f 100644 --- a/Resources/Prototypes/Entities/Constructible/Specific/Engines/Singularity/containment.yml +++ b/Resources/Prototypes/Entities/Constructible/Specific/Engines/Singularity/containment.yml @@ -8,7 +8,7 @@ - type: InteractionOutline - type: Clickable - type: Physics - bodyType: Dynamic + bodyType: Static mass: 25 fixtures: - shape: diff --git a/Resources/Prototypes/Entities/Constructible/Specific/Engines/Singularity/emitter.yml b/Resources/Prototypes/Entities/Constructible/Specific/Engines/Singularity/emitter.yml index d0cf67dfc2..48ae79cd15 100644 --- a/Resources/Prototypes/Entities/Constructible/Specific/Engines/Singularity/emitter.yml +++ b/Resources/Prototypes/Entities/Constructible/Specific/Engines/Singularity/emitter.yml @@ -1,6 +1,4 @@ - type: entity - name: emitter - description: "A machine that fires bolts of energy, used for powering containment fields at a safe distance." id: Emitter placement: mode: SnapgridCenter @@ -8,12 +6,12 @@ - type: Clickable - type: InteractionOutline - type: Physics - mass: 25 - bodyType: Dynamic + mass: 100 + bodyType: Static fixtures: - shape: !type:PhysShapeAabb - bounds: "-0.5, -0.5, 0.5, 0.5" + bounds: "-0.25, -0.25, 0.25, 0.25" layer: - Impassable - MobImpassable @@ -43,6 +41,23 @@ nodes: - !type:AdjacentNode nodeGroupID: MVPower + - type: Damageable + resistances: metallicResistances + - type: Destructible + thresholds: + - trigger: + !type:DamageTrigger + damage: 200 + behaviors: + - !type:PlaySoundBehavior + sound: /Audio/Effects/metalbreak.ogg + - !type:SpawnEntitiesBehavior + spawn: + SheetSteel1: + min: 5 + max: 5 + - !type:DoActsBehavior + acts: [ "Destruction" ] - type: Anchorable snap: true - type: Pullable @@ -53,23 +68,3 @@ - type: AccessReader access: [[ "Engineering" ]] -- type: entity - name: Emitter Bolt - description: "A bolt of energy." - id: EmitterBolt - parent: BulletBase - components: - - type: Sprite - sprite: Constructible/Power/Singularity/emitter.rsi - state: '' - layers: - - state: projectile - shader: unshaded - - type: Icon - sprite: Constructible/Power/Singularity/emitter.rsi - state: projectile - - type: EmitterBoltComponent - - type: Projectile - soundHit: /Audio/Weapons/Guns/Hits/bullet_hit.ogg - damages: - Heat: 20 diff --git a/Resources/Prototypes/Entities/Constructible/Specific/Engines/Singularity/generator.yml b/Resources/Prototypes/Entities/Constructible/Specific/Engines/Singularity/generator.yml index 94847d1dfb..1409bf45d8 100644 --- a/Resources/Prototypes/Entities/Constructible/Specific/Engines/Singularity/generator.yml +++ b/Resources/Prototypes/Entities/Constructible/Specific/Engines/Singularity/generator.yml @@ -12,7 +12,7 @@ - type: InteractionOutline - type: Clickable - type: Physics - bodyType: Dynamic + bodyType: Static mass: 25 fixtures: - shape: diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/projectiles.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/projectiles.yml index bb917b9793..42cf16a064 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/projectiles.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/projectiles.yml @@ -73,11 +73,29 @@ - type: StunnableProjectile paralyzeAmount: 2 +# Energy projectiles - type: entity - name : taser + name : taser bolt id: BulletTaser + parent: BulletBase abstract: true components: + - type: Sprite + directional: false + sprite: Objects/Weapons/Guns/Projectiles/spark.rsi + color: "#ffff33" + layers: + - state: spark + shader: unshaded + - type: Physics + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.2,-0.2,0.2,0.2" + hard: false + mask: + - Impassable + - MobImpassable - type: Ammo isProjectile: true ammoVelocity: 20 @@ -89,22 +107,35 @@ - type: StunnableProjectile stunAmount: 5 knockdownAmount: 5 + +- type: entity + name: emitter bolt + id: EmitterBolt + parent: BulletBase + abstract: true + components: - type: Sprite - noRot: false - sprite: Objects/Weapons/Guns/Projectiles/spark.rsi color: "#ffff33" - layers: - - state: spark - shader: unshaded + sprite: Constructible/Power/Singularity/emitter.rsi + state: 'projectile' - type: Physics - bodyType: Dynamic fixtures: - shape: !type:PhysShapeAabb bounds: "-0.2,-0.2,0.2,0.2" hard: false - layer: 32 - mask: 30 + layer: + - Impassable + - MobImpassable + mask: + - Opaque + - type: Projectile + soundHit: /Audio/Weapons/Guns/Hits/bullet_hit.ogg + damages: + Heat: 20 + - type: Tag + tags: + - EmitterBolt # Launcher projectiles (grenade / rocket) - type: entity diff --git a/Resources/Prototypes/tags.yml b/Resources/Prototypes/tags.yml index 538f6e920c..576b057a1f 100644 --- a/Resources/Prototypes/tags.yml +++ b/Resources/Prototypes/tags.yml @@ -45,3 +45,6 @@ - type: Tag id: Write + +- type: Tag + id: EmitterBolt