From 781e266fc2e6fe28791ed70f5f0f1667c73c46d8 Mon Sep 17 00:00:00 2001 From: Aviu00 <93730715+Aviu00@users.noreply.github.com> Date: Fri, 19 Jul 2024 16:27:01 +0000 Subject: [PATCH] =?UTF-8?q?=D0=A2=D0=B5=D1=80=D0=BC=D0=B0=D0=BB=D0=BA?= =?UTF-8?q?=D0=B8=20(#466)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * - add: Rewrite night vision. * - add: Thermals. * - remove: Remove stuff from maps. * - fix: Descriptions. --- Content.Client/Gameplay/GameplayStateBase.cs | 8 ++ .../Weapons/Melee/MeleeWeaponSystem.cs | 4 +- .../Weapons/Ranged/Systems/GunSystem.cs | 2 +- .../_White/Overlays/NightVisionOverlay.cs | 37 ++++-- .../_White/Overlays/NightVisionSystem.cs | 18 ++- .../_White/Overlays/ThermalVisionOverlay.cs | 103 +++++++++++++++++ .../_White/Overlays/ThermalVisionSystem.cs | 109 ++++++++++++++++++ .../Changeling/ChangelingSystem.Abilities.cs | 15 +++ .../Changeling/ChangelingSystem.Shop.cs | 1 + .../_Miracle/Systems/ThermalVisionSystem.cs | 7 ++ .../Systems/SharedThermalVisionSystem.cs | 60 ++++++++++ .../_White/Overlays/BaseNvOverlayComponent.cs | 19 +++ .../_White/Overlays/NightVisionComponent.cs | 13 +-- .../Overlays/TemporaryNightVisionComponent.cs | 13 +-- .../TemporaryThermalVisionComponent.cs | 10 ++ .../_White/Overlays/ThermalVisionComponent.cs | 29 +++++ .../Locale/ru-RU/research/technologies.ftl | 1 + .../Locale/ru-RU/store/uplink-catalog.ftl | 3 + .../ru-RU/white/actions/thermal-vision.ftl | 2 + .../white/changeling/changeling-entities.ftl | 2 +- Resources/Maps/Dungeon/snowy_labs.yml | 15 --- Resources/Maps/atlas.yml | 9 -- Resources/Maps/bagel.yml | 17 --- Resources/Maps/fland.yml | 22 ---- Resources/Maps/marathon.yml | 12 -- Resources/Maps/meta.yml | 12 -- Resources/Maps/packed.yml | 7 -- .../Entities/Clothing/Eyes/glasses.yml | 29 ++++- .../Clothing/Head/hardsuit-helmets.yml | 1 + .../Entities/Markers/Spawners/techspawner.yml | 1 + .../Entities/Structures/Machines/lathe.yml | 1 + .../Prototypes/Procedural/salvage_loot.yml | 2 + Resources/Prototypes/_White/Actions/types.yml | 14 +++ .../Prototypes/_White/Catalog/uplink.yml | 32 +++++ .../_White/Recipes/lathe_recipes.yml | 10 ++ .../_White/Research/experimental.yml | 12 ++ 36 files changed, 514 insertions(+), 138 deletions(-) create mode 100644 Content.Client/_White/Overlays/ThermalVisionOverlay.cs create mode 100644 Content.Client/_White/Overlays/ThermalVisionSystem.cs create mode 100644 Content.Server/_Miracle/Systems/ThermalVisionSystem.cs create mode 100644 Content.Shared/_Miracle/Systems/SharedThermalVisionSystem.cs create mode 100644 Content.Shared/_White/Overlays/BaseNvOverlayComponent.cs create mode 100644 Content.Shared/_White/Overlays/TemporaryThermalVisionComponent.cs create mode 100644 Content.Shared/_White/Overlays/ThermalVisionComponent.cs create mode 100644 Resources/Locale/ru-RU/white/actions/thermal-vision.ftl diff --git a/Content.Client/Gameplay/GameplayStateBase.cs b/Content.Client/Gameplay/GameplayStateBase.cs index 6236cd8e95..cfcb6367e9 100644 --- a/Content.Client/Gameplay/GameplayStateBase.cs +++ b/Content.Client/Gameplay/GameplayStateBase.cs @@ -2,6 +2,7 @@ using System.Linq; using System.Numerics; using Content.Client.Clickable; using Content.Client.UserInterface; +using Content.Shared.Damage; using Content.Shared.Input; using Robust.Client.ComponentTrees; using Robust.Client.GameObjects; @@ -102,6 +103,13 @@ namespace Content.Client.Gameplay return first.IsValid() ? first : null; } + public EntityUid? GetDamageableClickedEntity(MapCoordinates coordinates) // WD + { + var first = GetClickableEntities(coordinates) + .FirstOrDefault(e => _entityManager.HasComponent(e)); + return first.IsValid() ? first : null; + } + public IEnumerable GetClickableEntities(EntityCoordinates coordinates) { return GetClickableEntities(coordinates.ToMap(_entityManager, _entitySystemManager.GetEntitySystem())); diff --git a/Content.Client/Weapons/Melee/MeleeWeaponSystem.cs b/Content.Client/Weapons/Melee/MeleeWeaponSystem.cs index 0298b5de46..bb96d478e3 100644 --- a/Content.Client/Weapons/Melee/MeleeWeaponSystem.cs +++ b/Content.Client/Weapons/Melee/MeleeWeaponSystem.cs @@ -121,7 +121,7 @@ public sealed partial class MeleeWeaponSystem : SharedMeleeWeaponSystem if (_stateManager.CurrentState is GameplayStateBase screen) { - target = screen.GetClickedEntity(mousePos); + target = screen.GetDamageableClickedEntity(mousePos); // WD EDIT } EntityManager.RaisePredictiveEvent(new DisarmAttackEvent(GetNetEntity(target), GetNetCoordinates(coordinates))); @@ -169,7 +169,7 @@ public sealed partial class MeleeWeaponSystem : SharedMeleeWeaponSystem if (_stateManager.CurrentState is GameplayStateBase screen) { - target = screen.GetClickedEntity(mousePos); + target = screen.GetDamageableClickedEntity(mousePos); // WD EDIT } // Don't light-attack if interaction will be handling this instead diff --git a/Content.Client/Weapons/Ranged/Systems/GunSystem.cs b/Content.Client/Weapons/Ranged/Systems/GunSystem.cs index b095ff9eb4..2426d39872 100644 --- a/Content.Client/Weapons/Ranged/Systems/GunSystem.cs +++ b/Content.Client/Weapons/Ranged/Systems/GunSystem.cs @@ -190,7 +190,7 @@ public sealed partial class GunSystem : SharedGunSystem EntityUid? shootingTarget = null; if (_state.CurrentState is GameplayStateBase screen) - shootingTarget = screen.GetClickedEntity(mousePos); + shootingTarget = screen.GetDamageableClickedEntity(mousePos); EntityManager.RaisePredictiveEvent(new RequestShootEvent { diff --git a/Content.Client/_White/Overlays/NightVisionOverlay.cs b/Content.Client/_White/Overlays/NightVisionOverlay.cs index ffc98c1294..0ed82b8d4d 100644 --- a/Content.Client/_White/Overlays/NightVisionOverlay.cs +++ b/Content.Client/_White/Overlays/NightVisionOverlay.cs @@ -31,23 +31,28 @@ namespace Content.Client._White.Overlays var handle = args.WorldHandle; + if (_playerManager.LocalEntity == null) + return; + + var uid = _playerManager.LocalEntity.Value; + Color? color = null; - if (_entityManager.TryGetComponent(_playerManager.LocalSession?.AttachedEntity, - out var component) && component.IsActive) + if (_entityManager.TryGetComponent(uid, out var component) && component.IsActive) { - _shader.SetParameter("tint", component.Tint); - _shader.SetParameter("luminance_threshold", component.Strength); - _shader.SetParameter("noise_amount", component.Noise); - color = component.Color; + color = SetParameters(component); } - else if (_entityManager.TryGetComponent( - _playerManager.LocalSession?.AttachedEntity, out var tempNvComp)) + else if (_entityManager.TryGetComponent(uid, out var thermal) && thermal.IsActive) { - _shader.SetParameter("tint", tempNvComp.Tint); - _shader.SetParameter("luminance_threshold", tempNvComp.Strength); - _shader.SetParameter("noise_amount", tempNvComp.Noise); - color = tempNvComp.Color; + color = SetParameters(thermal); + } + else if (_entityManager.TryGetComponent(uid, out var tempNvComp)) + { + color = SetParameters(tempNvComp); + } + else if (_entityManager.TryGetComponent(uid, out var tempThermal)) + { + color = SetParameters(tempThermal); } if (color == null) @@ -59,5 +64,13 @@ namespace Content.Client._White.Overlays handle.DrawRect(args.WorldBounds, color.Value); handle.UseShader(null); } + + private Color SetParameters(BaseNvOverlayComponent component) + { + _shader.SetParameter("tint", component.Tint); + _shader.SetParameter("luminance_threshold", component.Strength); + _shader.SetParameter("noise_amount", component.Noise); + return component.Color; + } } } diff --git a/Content.Client/_White/Overlays/NightVisionSystem.cs b/Content.Client/_White/Overlays/NightVisionSystem.cs index 00934c5765..92d7d88ac3 100644 --- a/Content.Client/_White/Overlays/NightVisionSystem.cs +++ b/Content.Client/_White/Overlays/NightVisionSystem.cs @@ -72,6 +72,7 @@ public sealed class NightVisionSystem : SharedNightVisionSystem if (_player.LocalSession != player) return; + UpdateOverlay(active); UpdateNightVision(active); } @@ -80,16 +81,31 @@ public sealed class NightVisionSystem : SharedNightVisionSystem if (_player.LocalSession?.AttachedEntity != uid) return; + UpdateOverlay(active); UpdateNightVision(active); } - private void UpdateNightVision(bool active) + public void UpdateOverlay(bool active) { + if (_player.LocalEntity == null) + { + _overlayMan.RemoveOverlay(_overlay); + return; + } + + var uid = _player.LocalEntity.Value; + active |= TryComp(uid, out var nv) && nv.IsActive || + TryComp(uid, out var thermal) && thermal.IsActive || + HasComp(uid) || + HasComp(uid); if (active) _overlayMan.AddOverlay(_overlay); else _overlayMan.RemoveOverlay(_overlay); + } + private void UpdateNightVision(bool active) + { _lightManager.DrawLighting = !active; } diff --git a/Content.Client/_White/Overlays/ThermalVisionOverlay.cs b/Content.Client/_White/Overlays/ThermalVisionOverlay.cs new file mode 100644 index 0000000000..ace9bfaf5a --- /dev/null +++ b/Content.Client/_White/Overlays/ThermalVisionOverlay.cs @@ -0,0 +1,103 @@ +using System.Linq; +using System.Numerics; +using Content.Shared._White.Overlays; +using Content.Shared.Body.Components; +using Robust.Client.GameObjects; +using Robust.Client.Graphics; +using Robust.Client.Player; +using Robust.Shared.Enums; +using Robust.Shared.Map; + +namespace Content.Client._White.Overlays; + +public sealed class ThermalVisionOverlay : Overlay +{ + [Dependency] private readonly IEntityManager _entity = default!; + [Dependency] private readonly IPlayerManager _players = default!; + + private readonly ContainerSystem _container; + private readonly TransformSystem _transform; + private readonly OccluderSystem _occluder; + + public override OverlaySpace Space => OverlaySpace.WorldSpace; + + private readonly List _entries = new(); + + public ThermalVisionOverlay() + { + IoCManager.InjectDependencies(this); + + _container = _entity.System(); + _transform = _entity.System(); + _occluder = _entity.System(); + ZIndex = -1; + } + + protected override void Draw(in OverlayDrawArgs args) + { + if (_players.LocalEntity == null) + return; + + var ent = _players.LocalEntity.Value; + + if ((!_entity.TryGetComponent(ent, out ThermalVisionComponent? component) || !component.IsActive) && + !_entity.HasComponent(ent)) + { + return; + } + + if (HasOccluders(ent)) + return; + + var handle = args.WorldHandle; + var eye = args.Viewport.Eye; + var eyeRot = eye?.Rotation ?? default; + + _entries.Clear(); + var entities = _entity.EntityQueryEnumerator(); + while (entities.MoveNext(out var uid, out _, out var sprite, out var xform)) + { + if (HasOccluders(uid)) + continue; + + _entries.Add(new NightVisionRenderEntry((uid, sprite, xform), + eye?.Position.MapId, + eyeRot)); + } + + foreach (var entry in _entries) + { + Render(entry.Ent, entry.Map, handle, entry.EyeRot); + } + + handle.SetTransform(Matrix3.Identity); + } + + private void Render(Entity ent, + MapId? map, + DrawingHandleWorld handle, + Angle eyeRot) + { + var (uid, sprite, xform) = ent; + if (xform.MapID != map || _container.IsEntityOrParentInContainer(uid)) + return; + + var position = _transform.GetWorldPosition(xform); + var rotation = _transform.GetWorldRotation(xform); + + sprite.Render(handle, eyeRot, rotation, position: position); + } + + private bool HasOccluders(EntityUid ent) + { + var mapCoordinates = _transform.GetMapCoordinates(ent); + var occluders = _occluder.QueryAabb(mapCoordinates.MapId, + Box2.CenteredAround(mapCoordinates.Position, new Vector2(0.4f, 0.4f))); + return occluders.Any(o => o.Component.Enabled); + } +} + +public record struct NightVisionRenderEntry( + (EntityUid, SpriteComponent, TransformComponent) Ent, + MapId? Map, + Angle EyeRot); diff --git a/Content.Client/_White/Overlays/ThermalVisionSystem.cs b/Content.Client/_White/Overlays/ThermalVisionSystem.cs new file mode 100644 index 0000000000..42457c0bb5 --- /dev/null +++ b/Content.Client/_White/Overlays/ThermalVisionSystem.cs @@ -0,0 +1,109 @@ +using Content.Shared._Miracle.Systems; +using Content.Shared.GameTicking; +using Content.Shared._White.Overlays; +using Robust.Client.Graphics; +using Robust.Client.Player; +using Robust.Shared.Player; + +namespace Content.Client._White.Overlays; + +public sealed class ThermalVisionSystem : SharedThermalVisionSystem +{ + [Dependency] private readonly IPlayerManager _player = default!; + [Dependency] private readonly IOverlayManager _overlayMan = default!; + [Dependency] private readonly NightVisionSystem _nv = default!; + + private ThermalVisionOverlay _overlay = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnPlayerAttached); + SubscribeLocalEvent(OnPlayerDetached); + SubscribeLocalEvent(OnRestart); + + SubscribeLocalEvent(OnTempInit); + SubscribeLocalEvent(OnTempRemove); + SubscribeLocalEvent(OnTempPlayerAttached); + SubscribeLocalEvent(OnTempPlayerDetached); + + _overlay = new ThermalVisionOverlay(); + } + + private void OnTempPlayerAttached(Entity ent, ref PlayerAttachedEvent args) + { + UpdateThermalVision(args.Player, true); + } + + private void OnTempPlayerDetached(Entity ent, ref PlayerDetachedEvent args) + { + UpdateThermalVision(args.Player, false); + } + + private void OnTempRemove(Entity ent, ref ComponentRemove args) + { + if (TryComp(ent, out ThermalVisionComponent? thermalVision) && thermalVision.IsActive) + return; + + UpdateThermalVision(ent, false); + } + + private void OnTempInit(Entity ent, ref ComponentInit args) + { + UpdateThermalVision(ent, true); + } + + private void OnPlayerAttached(EntityUid uid, ThermalVisionComponent component, PlayerAttachedEvent args) + { + if (!component.IsActive && HasComp(args.Entity)) + return; + + UpdateThermalVision(args.Player, component.IsActive); + } + + private void OnPlayerDetached(EntityUid uid, ThermalVisionComponent component, PlayerDetachedEvent args) + { + UpdateThermalVision(args.Player, false); + } + + private void UpdateThermalVision(ICommonSession player, bool active) + { + if (_player.LocalSession != player) + return; + + _nv.UpdateOverlay(active); + UpdateThermalVision(active); + } + + protected override void UpdateThermalVision(EntityUid uid, bool active) + { + if (_player.LocalSession?.AttachedEntity != uid) + return; + + _nv.UpdateOverlay(active); + UpdateThermalVision(active); + } + + public void UpdateThermalVision(bool active) + { + if (_player.LocalEntity == null) + { + _overlayMan.RemoveOverlay(_overlay); + return; + } + + var uid = _player.LocalEntity.Value; + active |= TryComp(uid, out var thermal) && thermal.IsActive || + HasComp(uid); + if (active) + _overlayMan.AddOverlay(_overlay); + else + _overlayMan.RemoveOverlay(_overlay); + } + + private void OnRestart(RoundRestartCleanupEvent ev) + { + _overlayMan.RemoveOverlay(_overlay); + } +} diff --git a/Content.Server/Changeling/ChangelingSystem.Abilities.cs b/Content.Server/Changeling/ChangelingSystem.Abilities.cs index 8e87a63927..b9e765d626 100644 --- a/Content.Server/Changeling/ChangelingSystem.Abilities.cs +++ b/Content.Server/Changeling/ChangelingSystem.Abilities.cs @@ -672,12 +672,14 @@ public sealed partial class ChangelingSystem if (HasComp(ent)) { RemComp(ent); + RemComp(ent); EnsureComp(ent); EnsureComp(ent); return; } EnsureComp(ent); + EnsureComp(ent); RemComp(ent); RemComp(ent); } @@ -1054,6 +1056,19 @@ public sealed partial class ChangelingSystem EntityManager.AddComponent(to, toAdd); } + if (TryComp(from, out TemporaryThermalVisionComponent? thermal)) + { + var toAdd = new TemporaryThermalVisionComponent + { + Color = thermal.Color, + Tint = thermal.Tint, + Strength = thermal.Strength, + Noise = thermal.Noise + }; + + EntityManager.AddComponent(to, toAdd); + } + if (TryComp(from, out NpcFactionMemberComponent? factionMember)) { _faction.ClearFactions(to); diff --git a/Content.Server/Changeling/ChangelingSystem.Shop.cs b/Content.Server/Changeling/ChangelingSystem.Shop.cs index ddf691767c..9dbc95fc55 100644 --- a/Content.Server/Changeling/ChangelingSystem.Shop.cs +++ b/Content.Server/Changeling/ChangelingSystem.Shop.cs @@ -28,6 +28,7 @@ public sealed partial class ChangelingSystem RemComp(ent); RemComp(ent); RemComp(ent); + RemComp(ent); RemComp(ent); foreach (var hand in _handsSystem.EnumerateHands(ent)) diff --git a/Content.Server/_Miracle/Systems/ThermalVisionSystem.cs b/Content.Server/_Miracle/Systems/ThermalVisionSystem.cs new file mode 100644 index 0000000000..5d13e52fa7 --- /dev/null +++ b/Content.Server/_Miracle/Systems/ThermalVisionSystem.cs @@ -0,0 +1,7 @@ +using Content.Shared._Miracle.Systems; + +namespace Content.Server._Miracle.Systems; + +public sealed class ThermalVisionSystem : SharedThermalVisionSystem +{ +} diff --git a/Content.Shared/_Miracle/Systems/SharedThermalVisionSystem.cs b/Content.Shared/_Miracle/Systems/SharedThermalVisionSystem.cs new file mode 100644 index 0000000000..08bc64675a --- /dev/null +++ b/Content.Shared/_Miracle/Systems/SharedThermalVisionSystem.cs @@ -0,0 +1,60 @@ +using Content.Shared._White.Overlays; +using Content.Shared.Actions; +using Robust.Shared.Audio.Systems; +using Robust.Shared.Timing; + +namespace Content.Shared._Miracle.Systems; + +public abstract class SharedThermalVisionSystem : EntitySystem +{ + [Dependency] private readonly SharedAudioSystem _audio = default!; + [Dependency] private readonly SharedActionsSystem _actions = default!; + [Dependency] private readonly IGameTiming _timing = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnToggle); + SubscribeLocalEvent(OnInit); + SubscribeLocalEvent(OnRemove); + } + + private void OnRemove(EntityUid uid, ThermalVisionComponent component, ComponentRemove args) + { + _actions.RemoveAction(uid, component.ToggleActionEntity); + + if (HasComp(uid)) + return; + + UpdateThermalVision(uid, false); + } + + private void OnInit(EntityUid uid, ThermalVisionComponent component, ComponentInit args) + { + _actions.AddAction(uid, ref component.ToggleActionEntity, component.ToggleAction); + + if (!component.IsActive && HasComp(uid)) + return; + + UpdateThermalVision(uid, component.IsActive); + } + + protected virtual void UpdateThermalVision(EntityUid uid, bool active) { } + + private void OnToggle(EntityUid uid, ThermalVisionComponent component, ToggleThermalVisionEvent args) + { + if (!_timing.IsFirstTimePredicted) + return; + + component.IsActive = !component.IsActive; + _audio.PlayPredicted(component.ToggleSound, uid, uid); + + args.Handled = true; + + if (!component.IsActive && HasComp(uid)) + return; + + UpdateThermalVision(uid, component.IsActive); + } +} diff --git a/Content.Shared/_White/Overlays/BaseNvOverlayComponent.cs b/Content.Shared/_White/Overlays/BaseNvOverlayComponent.cs new file mode 100644 index 0000000000..40901f39a9 --- /dev/null +++ b/Content.Shared/_White/Overlays/BaseNvOverlayComponent.cs @@ -0,0 +1,19 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared._White.Overlays; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +public abstract partial class BaseNvOverlayComponent : Component +{ + [DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField] + public virtual Vector3 Tint { get; set; } = new(0.3f, 0.3f, 0.3f); + + [DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField] + public virtual float Strength { get; set; } = 2f; + + [DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField] + public virtual float Noise { get; set; } = 0.5f; + + [DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField] + public virtual Color Color { get; set; } = Color.FromHex("#98FB98"); +} diff --git a/Content.Shared/_White/Overlays/NightVisionComponent.cs b/Content.Shared/_White/Overlays/NightVisionComponent.cs index 54f0baeea6..3ffb5b860d 100644 --- a/Content.Shared/_White/Overlays/NightVisionComponent.cs +++ b/Content.Shared/_White/Overlays/NightVisionComponent.cs @@ -6,19 +6,10 @@ using Robust.Shared.Prototypes; namespace Content.Shared._White.Overlays; [RegisterComponent, NetworkedComponent, AutoGenerateComponentState] -public sealed partial class NightVisionComponent : Component +public sealed partial class NightVisionComponent : BaseNvOverlayComponent { [DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField] - public Vector3 Tint = new(0.3f, 0.3f, 0.3f); - - [DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField] - public float Strength = 2f; - - [DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField] - public float Noise = 0.5f; - - [DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField] - public Color Color = Color.FromHex("#98FB98"); + public override Color Color { get; set; } = Color.FromHex("#98FB98"); [DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField] public bool IsActive = true; diff --git a/Content.Shared/_White/Overlays/TemporaryNightVisionComponent.cs b/Content.Shared/_White/Overlays/TemporaryNightVisionComponent.cs index cc4d4aba22..141480b517 100644 --- a/Content.Shared/_White/Overlays/TemporaryNightVisionComponent.cs +++ b/Content.Shared/_White/Overlays/TemporaryNightVisionComponent.cs @@ -3,17 +3,8 @@ using Robust.Shared.GameStates; namespace Content.Shared._White.Overlays; [RegisterComponent, NetworkedComponent, AutoGenerateComponentState] -public sealed partial class TemporaryNightVisionComponent : Component +public sealed partial class TemporaryNightVisionComponent : BaseNvOverlayComponent { [DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField] - public Vector3 Tint = new(0.3f, 0.3f, 0.3f); - - [DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField] - public float Strength = 2f; - - [DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField] - public float Noise = 0.5f; - - [DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField] - public Color Color = Color.FromHex("#FB9898"); + public override Color Color { get; set; } = Color.FromHex("#FB9898"); } diff --git a/Content.Shared/_White/Overlays/TemporaryThermalVisionComponent.cs b/Content.Shared/_White/Overlays/TemporaryThermalVisionComponent.cs new file mode 100644 index 0000000000..1a8dc8eb1c --- /dev/null +++ b/Content.Shared/_White/Overlays/TemporaryThermalVisionComponent.cs @@ -0,0 +1,10 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared._White.Overlays; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +public sealed partial class TemporaryThermalVisionComponent : BaseNvOverlayComponent +{ + [DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField] + public override Color Color { get; set; } = Color.FromHex("#FB9898"); +} diff --git a/Content.Shared/_White/Overlays/ThermalVisionComponent.cs b/Content.Shared/_White/Overlays/ThermalVisionComponent.cs new file mode 100644 index 0000000000..cbd786d225 --- /dev/null +++ b/Content.Shared/_White/Overlays/ThermalVisionComponent.cs @@ -0,0 +1,29 @@ +using Content.Shared.Actions; +using Robust.Shared.Audio; +using Robust.Shared.GameStates; +using Robust.Shared.Prototypes; + +namespace Content.Shared._White.Overlays; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +public sealed partial class ThermalVisionComponent : BaseNvOverlayComponent +{ + [DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField] + public override Color Color { get; set; } = Color.FromHex("#F84742"); + + [DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField] + public bool IsActive = true; + + [DataField] + public SoundSpecifier? ToggleSound = new SoundPathSpecifier("/Audio/Items/flashlight_pda.ogg"); + + [DataField] + public EntProtoId? ToggleAction = "ToggleThermalVision"; + + [ViewVariables] + public EntityUid? ToggleActionEntity; +} + +public sealed partial class ToggleThermalVisionEvent : InstantActionEvent +{ +} diff --git a/Resources/Locale/ru-RU/research/technologies.ftl b/Resources/Locale/ru-RU/research/technologies.ftl index 065187db6a..6513155c8c 100644 --- a/Resources/Locale/ru-RU/research/technologies.ftl +++ b/Resources/Locale/ru-RU/research/technologies.ftl @@ -70,4 +70,5 @@ research-technology-advanced-spray = Продвинутые спреи research-technology-bluespace-cargo-transport = Блюспейс-транспортировка грузов research-technology-quantum-fiber-weaving = Плетение квантового волокна research-technology-night-vision = Технологии ночного видения +research-technology-thermal-vision = Технологии термального видения research-technology-bluespace-chemistry = Блюспейс химия diff --git a/Resources/Locale/ru-RU/store/uplink-catalog.ftl b/Resources/Locale/ru-RU/store/uplink-catalog.ftl index 32749b0a62..4c35d521d9 100644 --- a/Resources/Locale/ru-RU/store/uplink-catalog.ftl +++ b/Resources/Locale/ru-RU/store/uplink-catalog.ftl @@ -444,6 +444,9 @@ uplink-blood-dagger-desc = Критическая жажда: Кинжал Жа uplink-night-vision-name = ПНВ [Хамелеон] uplink-night-vision-desc = Теперь ты видишь во тьме! +uplink-thermal-vision-name = Оптический термальный сканер [Хамелеон] +uplink-thermal-vision-desc = Позволяет вам видеть существ через стены. + uplink-betrayal-knife-name = Предательский нож uplink-betrayal-knife-desc = Предательский нож позволяет пользователю телепортироваться на короткое расстояние, а также наносит значительные повреждения, пробивая броню противника, при ударе в спину. diff --git a/Resources/Locale/ru-RU/white/actions/thermal-vision.ftl b/Resources/Locale/ru-RU/white/actions/thermal-vision.ftl new file mode 100644 index 0000000000..df580d2b2f --- /dev/null +++ b/Resources/Locale/ru-RU/white/actions/thermal-vision.ftl @@ -0,0 +1,2 @@ +ent-ToggleThermalVision = Переключить термальное зрение. + .desc = Переключает термальное зрение. diff --git a/Resources/Locale/ru-RU/white/changeling/changeling-entities.ftl b/Resources/Locale/ru-RU/white/changeling/changeling-entities.ftl index 27f6c1e246..89f3a8eb2e 100644 --- a/Resources/Locale/ru-RU/white/changeling/changeling-entities.ftl +++ b/Resources/Locale/ru-RU/white/changeling/changeling-entities.ftl @@ -5,7 +5,7 @@ changeling-ability-biodegrade = Биоразложение changeling-ability-biodegrade-desc = Растворяет наручники и прочие сдерживающие элементы. Стоит 30 химикатов. changeling-ability-eyesight = Аугментация зрения -changeling-ability-eyesight-desc = Развивает переключаемое ночное зрение. Когда способность неактивна, защищает вас от флешек и яркого света, например от сварки. +changeling-ability-eyesight-desc = Развивает переключаемое ночное и термальное зрение. Когда способность неактивна, защищает вас от флешек и яркого света, например от сварки. changeling-ability-dissonant-shriek = Диссонирующий вопль changeling-ability-dissonant-shriek-desc = Испускает заряд ЭМИ, который нарушает работу всего оборудования вокруг. Стоит 20 химикатов. diff --git a/Resources/Maps/Dungeon/snowy_labs.yml b/Resources/Maps/Dungeon/snowy_labs.yml index 1211d7a664..66bd615ed1 100644 --- a/Resources/Maps/Dungeon/snowy_labs.yml +++ b/Resources/Maps/Dungeon/snowy_labs.yml @@ -7034,13 +7034,6 @@ entities: - type: Transform pos: 10.480986,45.607067 parent: 1653 -- proto: ClothingEyesGlassesThermal - entities: - - uid: 800 - components: - - type: Transform - pos: 6.5116234,25.568321 - parent: 1653 - proto: ClothingHandsGlovesLeather entities: - uid: 719 @@ -10731,14 +10724,6 @@ entities: rot: -1.5707963267948966 rad pos: 52.5,14.5 parent: 1653 -- proto: MagicalLamp - entities: - - uid: 1204 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 1.5085075,47.438328 - parent: 1653 - proto: MaintenanceFluffSpawner entities: - uid: 1245 diff --git a/Resources/Maps/atlas.yml b/Resources/Maps/atlas.yml index 1ce74026c9..f5c7f31418 100644 --- a/Resources/Maps/atlas.yml +++ b/Resources/Maps/atlas.yml @@ -18251,15 +18251,6 @@ entities: parent: 30 - type: Physics canCollide: False -- proto: ClothingEyesGlassesThermal - entities: - - uid: 7267 - components: - - type: Transform - pos: -31.624142,-1.1191435 - parent: 30 - - type: Physics - canCollide: False - proto: ClothingHandsGlovesColorYellow entities: - uid: 1668 diff --git a/Resources/Maps/bagel.yml b/Resources/Maps/bagel.yml index 3e86095fa4..7b8dd2e9ed 100644 --- a/Resources/Maps/bagel.yml +++ b/Resources/Maps/bagel.yml @@ -58677,23 +58677,6 @@ entities: - type: Transform pos: 14.470102,-43.56056 parent: 60 -- proto: ClothingEyesGlassesThermal - entities: - - uid: 15400 - components: - - type: Transform - pos: -17.455568,32.420967 - parent: 60 - - uid: 15402 - components: - - type: Transform - pos: -17.455568,32.624092 - parent: 60 - - uid: 23570 - components: - - type: Transform - pos: -62.52358,41.396984 - parent: 60 - proto: ClothingHandsGlovesBoxingBlue entities: - uid: 19920 diff --git a/Resources/Maps/fland.yml b/Resources/Maps/fland.yml index 28018bb4c8..89b2f86c15 100644 --- a/Resources/Maps/fland.yml +++ b/Resources/Maps/fland.yml @@ -93553,28 +93553,6 @@ entities: - type: Transform pos: 102.52885,13.515509 parent: 13329 -- proto: ClothingEyesGlassesThermal - entities: - - uid: 31732 - components: - - type: Transform - pos: 65.539406,-14.949457 - parent: 13329 - - uid: 31733 - components: - - type: Transform - pos: 70.49054,-5.808993 - parent: 13329 - - uid: 31734 - components: - - type: Transform - pos: 70.47884,-26.373547 - parent: 13329 - - uid: 31735 - components: - - type: Transform - pos: 70.57259,-26.498547 - parent: 13329 - proto: ClothingEyesHudBeer entities: - uid: 31731 diff --git a/Resources/Maps/marathon.yml b/Resources/Maps/marathon.yml index f6ce22872b..10eba2385c 100644 --- a/Resources/Maps/marathon.yml +++ b/Resources/Maps/marathon.yml @@ -51820,18 +51820,6 @@ entities: - type: Transform pos: 47.465996,44.649086 parent: 30 -- proto: ClothingEyesGlassesThermal - entities: - - uid: 9441 - components: - - type: Transform - pos: 5.522977,-23.530071 - parent: 30 - - uid: 10010 - components: - - type: Transform - pos: -13.542964,-45.170254 - parent: 30 - proto: ClothingEyesHudDiagnostic entities: - uid: 11291 diff --git a/Resources/Maps/meta.yml b/Resources/Maps/meta.yml index aab725e956..8c2236c71a 100644 --- a/Resources/Maps/meta.yml +++ b/Resources/Maps/meta.yml @@ -60170,18 +60170,6 @@ entities: - type: Transform pos: 66.56803,33.64219 parent: 5350 -- proto: ClothingEyesGlassesThermal - entities: - - uid: 23947 - components: - - type: Transform - pos: 55.407906,-5.421943 - parent: 5350 - - uid: 23948 - components: - - type: Transform - pos: 55.501656,-5.562568 - parent: 5350 - proto: ClothingEyesHudMedical entities: - uid: 14922 diff --git a/Resources/Maps/packed.yml b/Resources/Maps/packed.yml index cf8b8afe68..94efc6158a 100644 --- a/Resources/Maps/packed.yml +++ b/Resources/Maps/packed.yml @@ -32339,13 +32339,6 @@ entities: - type: Transform pos: 86.49675,1.6024053 parent: 2 -- proto: ClothingEyesGlassesThermal - entities: - - uid: 12673 - components: - - type: Transform - pos: 32.51945,-30.628448 - parent: 2 - proto: ClothingEyesHudDiagnostic entities: - uid: 11439 diff --git a/Resources/Prototypes/Entities/Clothing/Eyes/glasses.yml b/Resources/Prototypes/Entities/Clothing/Eyes/glasses.yml index e6c7626a6a..3191f44b3f 100644 --- a/Resources/Prototypes/Entities/Clothing/Eyes/glasses.yml +++ b/Resources/Prototypes/Entities/Clothing/Eyes/glasses.yml @@ -235,11 +235,30 @@ sprite: Clothing/Eyes/Glasses/thermal.rsi - type: Clothing sprite: Clothing/Eyes/Glasses/thermal.rsi - - type: Armor - modifiers: - coefficients: - Heat: 0.95 - - type: GroupExamine + - type: ClothingGrantComponent + component: + - type: ThermalVision + +- type: entity + parent: ClothingEyesGlassesThermal + id: ClothingEyesGlassesThermalSyndie + suffix: "Хамелеон" + components: + - type: ChameleonClothing + slot: [ eyes ] + default: ClothingEyesGlassesSunglasses + - type: UserInterface + interfaces: + - key: enum.ChameleonUiKey.Key + type: ChameleonBoundUserInterface + +- type: entity + parent: ClothingEyesGlassesThermalSyndie + id: ClothingEyesGlassesThermalNukie + suffix: "Хамелеон, Ядерные Оперативники" + components: + - type: ShowSyndicateIcons + - type: ShowSecurityIcons - type: entity parent: ClothingEyesBase diff --git a/Resources/Prototypes/Entities/Clothing/Head/hardsuit-helmets.yml b/Resources/Prototypes/Entities/Clothing/Head/hardsuit-helmets.yml index ded521045e..31b659e492 100644 --- a/Resources/Prototypes/Entities/Clothing/Head/hardsuit-helmets.yml +++ b/Resources/Prototypes/Entities/Clothing/Head/hardsuit-helmets.yml @@ -798,6 +798,7 @@ - type: ClothingGrantComponent component: - type: NightVision + - type: ThermalVision #MISC. HARDSUITS #Clown Hardsuit diff --git a/Resources/Prototypes/Entities/Markers/Spawners/techspawner.yml b/Resources/Prototypes/Entities/Markers/Spawners/techspawner.yml index d017841c8e..3a22d59307 100644 --- a/Resources/Prototypes/Entities/Markers/Spawners/techspawner.yml +++ b/Resources/Prototypes/Entities/Markers/Spawners/techspawner.yml @@ -601,6 +601,7 @@ - ExGrenade - SyndieMiniBomb - ClothingEyesNightVisionGogglesSyndie + - ClothingEyesGlassesThermalSyndie - ClothingOuterVestWeb - ClothingBackpackChameleonFill - CigPackSyndicate diff --git a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml index 2c49476b98..f3c5fe87c5 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml @@ -343,6 +343,7 @@ - FauxTileAstroSnow - OreBagOfHolding - ClothingEyesNightVisionGoggles # WD EDIT + - ClothingEyesGlassesThermal # WD EDIT - KitchenKnife # WD EDIT - ButchCleaver # WD EDIT - WeaponTempGun # WD EDIT diff --git a/Resources/Prototypes/Procedural/salvage_loot.yml b/Resources/Prototypes/Procedural/salvage_loot.yml index 17bfe7ad02..e24591becd 100644 --- a/Resources/Prototypes/Procedural/salvage_loot.yml +++ b/Resources/Prototypes/Procedural/salvage_loot.yml @@ -153,6 +153,8 @@ prob: 0.5 - proto: ClothingEyesNightVisionGoggles cost: 8 + - proto: ClothingEyesGlassesThermal + cost: 8 - proto: ClothingHandsGlovesCombat cost: 3 - proto: Katana diff --git a/Resources/Prototypes/_White/Actions/types.yml b/Resources/Prototypes/_White/Actions/types.yml index ca4129de2b..b5967a28b9 100644 --- a/Resources/Prototypes/_White/Actions/types.yml +++ b/Resources/Prototypes/_White/Actions/types.yml @@ -42,6 +42,20 @@ state: icon event: !type:ToggleNightVisionEvent +- type: entity + id: ToggleThermalVision + name: Toggle thermal vision. + description: Toggles thermal vision. + noSpawn: true + components: + - type: InstantAction + itemIconStyle: BigAction + priority: -20 + icon: + sprite: Clothing/Eyes/Glasses/thermal.rsi + state: icon + event: !type:ToggleThermalVisionEvent + - type: entity id: ToggleBodyCamera name: Toggle body camera. diff --git a/Resources/Prototypes/_White/Catalog/uplink.yml b/Resources/Prototypes/_White/Catalog/uplink.yml index 7140266856..5797124322 100644 --- a/Resources/Prototypes/_White/Catalog/uplink.yml +++ b/Resources/Prototypes/_White/Catalog/uplink.yml @@ -135,6 +135,38 @@ tags: - NukeOpsUplink +- type: listing + id: UplinkThermalGoggles + name: uplink-thermal-vision-name + description: uplink-thermal-vision-desc + productEntity: ClothingEyesGlassesThermalSyndie + icon: { sprite: Clothing/Eyes/Glasses/thermal.rsi, state: icon } + cost: + Telecrystal: 3 + categories: + - UplinkWearables + conditions: + - !type:StoreWhitelistCondition + blacklist: + tags: + - NukeOpsUplink + +- type: listing + id: UplinkThermalGogglesNukie + name: uplink-thermal-vision-name + description: uplink-thermal-vision-desc + productEntity: ClothingEyesGlassesThermalNukie + icon: { sprite: Clothing/Eyes/Glasses/thermal.rsi, state: icon } + cost: + Telecrystal: 3 + categories: + - UplinkWearables + conditions: + - !type:StoreWhitelistCondition + whitelist: + tags: + - NukeOpsUplink + #- type: listing # id: UplinkBattleAxe # name: Энергетической боевой топор diff --git a/Resources/Prototypes/_White/Recipes/lathe_recipes.yml b/Resources/Prototypes/_White/Recipes/lathe_recipes.yml index c975c5cb99..f62c31ee4b 100644 --- a/Resources/Prototypes/_White/Recipes/lathe_recipes.yml +++ b/Resources/Prototypes/_White/Recipes/lathe_recipes.yml @@ -22,6 +22,16 @@ Silver: 100 Gold: 100 +- type: latheRecipe + id: ClothingEyesGlassesThermal + result: ClothingEyesGlassesThermal + completetime: 2 + materials: + Steel: 200 + Glass: 100 + Silver: 100 + Gold: 100 + - type: latheRecipe id: WeaponTempGun result: WeaponTempGun diff --git a/Resources/Prototypes/_White/Research/experimental.yml b/Resources/Prototypes/_White/Research/experimental.yml index 4ed13340fb..bd57be222c 100644 --- a/Resources/Prototypes/_White/Research/experimental.yml +++ b/Resources/Prototypes/_White/Research/experimental.yml @@ -10,3 +10,15 @@ cost: 10000 recipeUnlocks: - ClothingEyesNightVisionGoggles + +- type: technology + id: ThermalVisionTech + name: research-technology-thermal-vision + icon: + sprite: Clothing/Eyes/Glasses/thermal.rsi + state: icon + discipline: Experimental + tier: 2 + cost: 10000 + recipeUnlocks: + - ClothingEyesGlassesThermal