Merge branch 'corvax-team:master' into master

This commit is contained in:
tau
2026-04-04 17:53:01 +03:00
committed by GitHub
65 changed files with 1230 additions and 245 deletions
@@ -1,6 +1,7 @@
using Robust.Client.Graphics;
using Robust.Shared.Enums;
using Robust.Shared.Prototypes;
using Content.Client._WL.Overlays; //Corvax-WL-Changes
namespace Content.Client.Overlays;
@@ -10,6 +11,9 @@ public sealed partial class BlackAndWhiteOverlay : Overlay
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IEntityManager _entManager = default!; //Corvax-WL-Changes
private readonly IgnoreGlobalOverlaysSystem _ignore; //Corvax-WL-Changes
public override OverlaySpace Space => OverlaySpace.WorldSpace;
public override bool RequestScreenTexture => true;
private readonly ShaderInstance _greyscaleShader;
@@ -19,8 +23,17 @@ public sealed partial class BlackAndWhiteOverlay : Overlay
IoCManager.InjectDependencies(this);
_greyscaleShader = _prototypeManager.Index(Shader).InstanceUnique();
ZIndex = 10; // draw this over the DamageOverlay, RainbowOverlay etc.
_ignore = _entManager.System<IgnoreGlobalOverlaysSystem>(); //Corvax-WL-Changes
}
//Corvax-WL-Changes-start
protected override bool BeforeDraw(in OverlayDrawArgs args)
{
return !_ignore.CheckIgnore(args.Viewport.Eye);
}
//Corvax-WL-Changes-end
protected override void Draw(in OverlayDrawArgs args)
{
if (ScreenTexture == null)
@@ -1,4 +1,4 @@
using System.Numerics;
using Content.Client._WL.Overlays;
using Content.Client.StatusIcon;
using Content.Client.UserInterface.Systems;
using Content.Shared.Damage.Components;
@@ -12,6 +12,7 @@ using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Shared.Enums;
using Robust.Shared.Prototypes;
using System.Numerics;
using static Robust.Shared.Maths.Color;
namespace Content.Client.Overlays;
@@ -30,7 +31,7 @@ public sealed class EntityHealthBarOverlay : Overlay
private readonly StatusIconSystem _statusIconSystem;
private readonly SpriteSystem _spriteSystem;
private readonly ProgressColorSystem _progressColor;
private readonly IgnoreGlobalOverlaysSystem _ignore; //Corvax-WL-Changes
public override OverlaySpace Space => OverlaySpace.WorldSpaceBelowFOV;
public HashSet<string> DamageContainers = new();
@@ -46,8 +47,16 @@ public sealed class EntityHealthBarOverlay : Overlay
_statusIconSystem = _entManager.System<StatusIconSystem>();
_spriteSystem = _entManager.System<SpriteSystem>();
_progressColor = _entManager.System<ProgressColorSystem>();
_ignore = _entManager.System<IgnoreGlobalOverlaysSystem>(); //Corvax-WL-Changes
}
//Corvax-WL-Changes-start
protected override bool BeforeDraw(in OverlayDrawArgs args)
{
return !_ignore.CheckIgnore(args.Viewport.Eye);
}
//Corvax-WL-Changes-end
protected override void Draw(in OverlayDrawArgs args)
{
var handle = args.WorldHandle;
+13
View File
@@ -1,6 +1,7 @@
using Robust.Client.Graphics;
using Robust.Shared.Enums;
using Robust.Shared.Prototypes;
using Content.Client._WL.Overlays; //Corvax-WL-Changes
namespace Content.Client.Overlays;
@@ -10,6 +11,9 @@ public sealed partial class NoirOverlay : Overlay
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IEntityManager _entManager = default!; //Corvax-WL-Changes
private readonly IgnoreGlobalOverlaysSystem _ignore; //Corvax-WL-Changes
public override OverlaySpace Space => OverlaySpace.WorldSpace;
public override bool RequestScreenTexture => true;
private readonly ShaderInstance _noirShader;
@@ -19,8 +23,17 @@ public sealed partial class NoirOverlay : Overlay
IoCManager.InjectDependencies(this);
_noirShader = _prototypeManager.Index(Shader).InstanceUnique();
ZIndex = 9; // draw this over the DamageOverlay, RainbowOverlay etc, but before the black and white shader
_ignore = _entManager.System<IgnoreGlobalOverlaysSystem>(); //Corvax-WL-Changes
}
//Corvax-WL-Changes-start
protected override bool BeforeDraw(in OverlayDrawArgs args)
{
return !_ignore.CheckIgnore(args.Viewport.Eye);
}
//Corvax-WL-Changes-end
protected override void Draw(in OverlayDrawArgs args)
{
if (ScreenTexture == null)
@@ -1,3 +1,4 @@
using Content.Client._WL.Overlays;
using Content.Shared.StatusIcon;
using Content.Shared.StatusIcon.Components;
using Robust.Client.GameObjects;
@@ -21,6 +22,7 @@ public sealed class StatusIconOverlay : Overlay
private readonly TransformSystem _transform;
private readonly StatusIconSystem _statusIcon;
private readonly ShaderInstance _unshadedShader;
private readonly IgnoreGlobalOverlaysSystem _ignore; //Corvax-WL-Changes
public override OverlaySpace Space => OverlaySpace.WorldSpaceBelowFOV;
@@ -32,8 +34,16 @@ public sealed class StatusIconOverlay : Overlay
_transform = _entity.System<TransformSystem>();
_statusIcon = _entity.System<StatusIconSystem>();
_unshadedShader = _prototype.Index(UnshadedShader).Instance();
_ignore = _entity.System<IgnoreGlobalOverlaysSystem>(); //Corvax-WL-Changes
}
//Corvax-WL-Changes-start
protected override bool BeforeDraw(in OverlayDrawArgs args)
{
return !_ignore.CheckIgnore(args.Viewport.Eye);
}
//Corvax-WL-Changes-end
protected override void Draw(in OverlayDrawArgs args)
{
var handle = args.WorldHandle;
@@ -0,0 +1,74 @@
using Content.Client._WL.Photo;
using Content.Shared._WL.Photo.Filters;
using Content.Shared.Humanoid;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Shared.Enums;
using System.Numerics;
namespace Content.Client._WL.Overlays;
public sealed partial class FaceCameraOverlay : Overlay
{
[Dependency] private readonly IEntityManager _entManager = default!;
private readonly PhotoSystem _photo;
private readonly SpriteSystem _sprite;
private readonly TransformSystem _transform;
public override OverlaySpace Space => OverlaySpace.WorldSpace;
public override bool RequestScreenTexture => true;
public FaceCameraOverlay()
{
IoCManager.InjectDependencies(this);
ZIndex = 9;
_photo = _entManager.System<PhotoSystem>();
_sprite = _entManager.System<SpriteSystem>();
_transform = _entManager.System<TransformSystem>();
}
protected override bool BeforeDraw(in OverlayDrawArgs args)
{
if (args.Viewport.Eye == null || !_photo.ActiveEyes.TryGetValue(args.Viewport.Eye, out var uid))
return false;
return _entManager.HasComponent<PhotoFaceFilterComponent>(uid);
}
protected override void Draw(in OverlayDrawArgs args)
{
if (ScreenTexture == null)
return;
if (args.Viewport.Eye == null || !_photo.ActiveEyes.TryGetValue(args.Viewport.Eye, out var uid) ||
!_entManager.TryGetComponent<PhotoFaceFilterComponent>(uid, out var filter))
return;
if (filter.Visual == null)
return;
const float scale = 1f;
var scaleMatrix = Matrix3Helpers.CreateScale(new Vector2(scale, scale));
var rotationMatrix = Matrix3Helpers.CreateRotation(-(args.Viewport.Eye?.Rotation ?? Angle.Zero));
var handle = args.WorldHandle;
var query = _entManager.EntityQueryEnumerator<HumanoidAppearanceComponent>();
while (query.MoveNext(out var ent, out _))
{
Vector2 deltaDir = (_transform.GetWorldRotation(ent) - _transform.GetWorldRotation(uid).Opposite()).ToVec();
if (MathF.Abs((float)deltaDir.ToAngle().Degrees) > 45f)
continue;
Vector2 worldPos = _transform.GetWorldPosition(ent);
var worldMatrix = Matrix3Helpers.CreateTranslation(worldPos);
var scaledWorld = Matrix3x2.Multiply(scaleMatrix, worldMatrix);
var matty = Matrix3x2.Multiply(rotationMatrix, scaledWorld);
handle.SetTransform(matty);
handle.DrawTexture(_sprite.Frame0(filter.Visual), new Vector2(-0.5f, -0.5f));
}
}
}
@@ -0,0 +1,75 @@
using Content.Client._WL.Photo;
using Content.Shared._WL.Photo.Filters;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Client.ResourceManagement;
using Robust.Shared.Enums;
using Robust.Shared.Prototypes;
using Robust.Shared.Timing;
using System.Numerics;
namespace Content.Client._WL.Overlays;
public sealed partial class GhostCameraOverlay : Overlay
{
private static readonly ProtoId<ShaderPrototype> Shader = "CameraGhost";
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IEntityManager _entManager = default!;
private readonly PhotoSystem _photo;
private readonly SpriteSystem _sprite;
public override OverlaySpace Space => OverlaySpace.WorldSpace;
public override bool RequestScreenTexture => true;
private readonly ShaderInstance _shader;
public GhostCameraOverlay()
{
IoCManager.InjectDependencies(this);
_shader = _prototypeManager.Index(Shader).InstanceUnique();
ZIndex = 9;
_photo = _entManager.System<PhotoSystem>();
_sprite = _entManager.System<SpriteSystem>();
}
protected override bool BeforeDraw(in OverlayDrawArgs args)
{
if (args.Viewport.Eye == null || !_photo.ActiveEyes.TryGetValue(args.Viewport.Eye, out var uid))
return false;
return _entManager.HasComponent<PhotoGhostFilterComponent>(uid);
}
protected override void Draw(in OverlayDrawArgs args)
{
if (ScreenTexture == null)
return;
if (args.Viewport.Eye == null || !_photo.ActiveEyes.TryGetValue(args.Viewport.Eye, out var uid) ||
!_entManager.TryGetComponent<PhotoGhostFilterComponent>(uid, out var filter))
return;
const float scale = 1f;
var scaleMatrix = Matrix3Helpers.CreateScale(new Vector2(scale, scale));
var rotationMatrix = Matrix3Helpers.CreateRotation(-(args.Viewport.Eye?.Rotation ?? Angle.Zero));
var handle = args.WorldHandle;
foreach (var worldPos in filter.ViewedGhosts)
{
var worldMatrix = Matrix3Helpers.CreateTranslation(worldPos);
var scaledWorld = Matrix3x2.Multiply(scaleMatrix, worldMatrix);
var matty = Matrix3x2.Multiply(rotationMatrix, scaledWorld);
handle.SetTransform(matty);
handle.DrawTexture(_sprite.Frame0(filter.Visual), new Vector2(-0.5f, -0.5f));
}
_shader.SetParameter("SCREEN_TEXTURE", ScreenTexture);
_shader.SetParameter("SCALE", args.Viewport.Eye?.Scale.Length() ?? 1f);
handle.SetTransform(Matrix3x2.Identity);
handle.UseShader(_shader);
handle.DrawRect(args.WorldBounds, Color.White);
handle.UseShader(null);
}
}
@@ -0,0 +1,37 @@
using Content.Shared._WL.Overlays;
using Robust.Shared.Graphics;
namespace Content.Client._WL.Overlays;
public sealed partial class IgnoreGlobalOverlaysSystem : EntitySystem
{
public Dictionary<IEye, EntityUid> IgnoreEyes = new();
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<IgnoreGlobalOverlaysComponent, ComponentInit>(OnComponentInit);
SubscribeLocalEvent<IgnoreGlobalOverlaysComponent, ComponentShutdown>(OnComponentShutdown);
}
private void OnComponentInit(EntityUid uid, IgnoreGlobalOverlaysComponent component, ComponentInit args)
{
if (EntityManager.TryGetComponent<EyeComponent>(uid, out var eye) && !IgnoreEyes.ContainsKey(eye.Eye))
IgnoreEyes.Add(eye.Eye, uid);
}
private void OnComponentShutdown(EntityUid uid, IgnoreGlobalOverlaysComponent component, ComponentShutdown args)
{
if (EntityManager.TryGetComponent<EyeComponent>(uid, out var eye) && IgnoreEyes.ContainsKey(eye.Eye))
IgnoreEyes.Remove(eye.Eye);
}
public bool CheckIgnore(IEye? eye)
{
if (eye == null)
return false;
return IgnoreEyes.ContainsKey(eye);
}
}
@@ -0,0 +1,94 @@
using Content.Client._WL.Photo;
using Content.Client.GameTicking.Managers;
using Content.Shared._WL.Photo.Filters;
using Robust.Client.Graphics;
using Robust.Client.ResourceManagement;
using Robust.Shared.Enums;
using Robust.Shared.Timing;
using System.Numerics;
namespace Content.Client._WL.Overlays;
public sealed partial class InfoCameraOverlay : Overlay
{
[Dependency] private readonly IEntityManager _entManager = default!;
[Dependency] private readonly IResourceCache _cache = default!;
[Dependency] private readonly IGameTiming _timing = default!;
private readonly PhotoSystem _photo;
private readonly ClientGameTicker _gameTicker;
private readonly VectorFont _baseFont;
public override OverlaySpace Space => OverlaySpace.WorldSpace;
public override bool RequestScreenTexture => true;
public InfoCameraOverlay()
{
IoCManager.InjectDependencies(this);
ZIndex = 9;
_photo = _entManager.System<PhotoSystem>();
_gameTicker = _entManager.System<ClientGameTicker>();
_baseFont = new VectorFont(_cache.GetResource<FontResource>("/Fonts/NotoSansDisplay/NotoSansDisplay-Regular.ttf"), 20);
}
protected override bool BeforeDraw(in OverlayDrawArgs args)
{
if (args.Viewport.Eye == null || !_photo.ActiveEyes.TryGetValue(args.Viewport.Eye, out var uid))
return false;
return _entManager.HasComponent<PhotoInfoFilterComponent>(uid);
}
protected override void Draw(in OverlayDrawArgs args)
{
if (ScreenTexture == null)
return;
if (args.Viewport.Eye == null || !_photo.ActiveEyes.TryGetValue(args.Viewport.Eye, out var uid) ||
!_entManager.TryGetComponent<PhotoInfoFilterComponent>(uid, out var filter))
return;
var handle = args.WorldHandle;
var worldMatrix = Matrix3Helpers.CreateTranslation(-args.WorldBounds.TopLeft);
Angle angle = args.Viewport.Eye?.Rotation ?? Angle.Zero;
Vector2 zoom = (args.Viewport.Eye?.Zoom ?? Vector2.One);
handle.SetTransform(args.WorldBounds.BottomLeft, -angle, zoom);
DrawSizeBar(handle, args.WorldBounds, zoom);
var stationTime = _timing.CurTime.Subtract(_gameTicker.RoundStartTimeSpan);
var timeString = stationTime.ToString("hh\\:mm\\:ss");
handle.SetTransform(args.WorldBounds.BottomLeft, -angle, zoom / 80f);
DrawString("1m", new Vector2(30f, 120f), handle);
DrawString(timeString, new Vector2(30f, 220f), handle);
}
private void DrawString(string text, Vector2 pos, DrawingHandleWorld handle)
{
float offset = 0;
foreach (var rune in text.EnumerateRunes())
offset += _baseFont.DrawChar(handle, rune, pos + new Vector2(offset, 0f), 2f, Color.White);
}
private void DrawSizeBar(DrawingHandleWorld handle, Box2Rotated worldBox, Vector2 zoom)
{
const float thickness = 0.1f;
handle.DrawRect(Box2.FromDimensions(0.4f, 0.5f, 6f, thickness), Color.White);
float screenWidth = worldBox.Box.Width / zoom.X;
float pos = 0f;
float cellSize = screenWidth / worldBox.Box.Width;
while (pos < 6f)
{
handle.DrawRect(Box2.FromDimensions(0.4f + pos, 0.2f + thickness / 2f, thickness, 0.6f), Color.White);
pos += cellSize;
}
}
}
@@ -0,0 +1,60 @@
using Content.Client._WL.Photo;
using Content.Shared._WL.Photo.Filters;
using Robust.Client.Graphics;
using Robust.Shared.Enums;
using Robust.Shared.Prototypes;
namespace Content.Client._WL.Overlays;
public sealed partial class ShaderCameraOverlay : Overlay
{
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IEntityManager _entManager = default!;
private readonly PhotoSystem _photo;
private Dictionary<ProtoId<ShaderPrototype>, ShaderInstance> _cachedShaders = new();
public override OverlaySpace Space => OverlaySpace.WorldSpace;
public override bool RequestScreenTexture => true;
public ShaderCameraOverlay()
{
IoCManager.InjectDependencies(this);
ZIndex = 9;
_photo = _entManager.System<PhotoSystem>();
}
protected override bool BeforeDraw(in OverlayDrawArgs args)
{
if (args.Viewport.Eye == null || !_photo.ActiveEyes.TryGetValue(args.Viewport.Eye, out var uid))
return false;
return _entManager.HasComponent<PhotoShaderFilterComponent>(uid);
}
protected override void Draw(in OverlayDrawArgs args)
{
if (ScreenTexture == null)
return;
if (args.Viewport.Eye == null || !_photo.ActiveEyes.TryGetValue(args.Viewport.Eye, out var uid) ||
!_entManager.TryGetComponent<PhotoShaderFilterComponent>(uid, out var filter))
return;
if (filter.Shader == null)
return;
ShaderInstance? shader;
if (!_cachedShaders.TryGetValue(filter.Shader, out shader))
{
shader = _prototypeManager.Index((ProtoId<ShaderPrototype>)filter.Shader).InstanceUnique();
_cachedShaders.Add(filter.Shader, shader);
}
var handle = args.WorldHandle;
shader.SetParameter("SCREEN_TEXTURE", ScreenTexture);
handle.UseShader(shader);
handle.DrawRect(args.WorldBounds, Color.White);
handle.UseShader(null);
}
}
@@ -0,0 +1,9 @@
namespace Content.Client._WL.Photo;
public abstract class ClientPhotoSystem : EntitySystem
{
public override void Initialize()
{
base.Initialize();
}
}
@@ -0,0 +1,112 @@
using Content.Client._WL.Overlays;
using Content.Shared._WL.Photo;
using Content.Shared._WL.Photo.Filters;
using Robust.Client.Graphics;
using Robust.Client.Player;
namespace Content.Client._WL.Photo.Filters;
public sealed partial class PhotoFilterSystem : EntitySystem
{
[Dependency] private readonly IOverlayManager _overlay = default!;
[Dependency] private readonly IPlayerManager _player = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<PhotoFilterBaseComponent, ComponentInit>(OnFilterInit);
SubscribeLocalEvent<PhotoFilterBaseComponent, ComponentShutdown>(OnFilterShutdown);
SubscribeLocalEvent<PhotoShaderFilterComponent, TogglePhotoFilterEvent>(OnToggleShaderFilter);
SubscribeLocalEvent<PhotoGhostFilterComponent, TogglePhotoFilterEvent>(OnToggleGhostFilter);
SubscribeLocalEvent<PhotoFaceFilterComponent, TogglePhotoFilterEvent>(OnToggleFaceFilter);
SubscribeLocalEvent<PhotoInfoFilterComponent, TogglePhotoFilterEvent>(OnToggleInfoFilter);
}
private void OnFilterInit(EntityUid uid, PhotoFilterBaseComponent component, ComponentInit args)
{
EnableFilter(uid);
}
private void OnFilterShutdown(EntityUid uid, PhotoFilterBaseComponent component, ComponentShutdown args)
{
DisableFilter(uid);
}
public void EnableFilter(EntityUid? uid)
{
if (uid == null || !CheckOverlay(uid.Value))
return;
var ev = new TogglePhotoFilterEvent(true);
RaiseLocalEvent(uid.Value, ev);
}
public void DisableFilter(EntityUid? uid)
{
if (uid == null || !CheckOverlay(uid.Value))
return;
var ev = new TogglePhotoFilterEvent(false);
RaiseLocalEvent(uid.Value, ev);
}
private bool CheckOverlay(EntityUid uid)
{
if (!EntityManager.TryGetComponent<PhotoCameraComponent>(uid, out var camera))
return false;
if (_player.LocalEntity != camera.User)
return false;
if (!EntityManager.TryGetComponent<PhotoFilterBaseComponent>(uid, out var filter) ||
filter.LifeStage >= ComponentLifeStage.Stopping)
return true;
return true;
}
//Different Filters handle
//Simple Shader Filter
private void OnToggleShaderFilter(EntityUid uid, PhotoShaderFilterComponent component, TogglePhotoFilterEvent args)
{
if (args.State)
_overlay.AddOverlay(new ShaderCameraOverlay());
else
_overlay.RemoveOverlay<ShaderCameraOverlay>();
}
//Ghost Filter
private void OnToggleGhostFilter(EntityUid uid, PhotoGhostFilterComponent component, TogglePhotoFilterEvent args)
{
if (args.State)
_overlay.AddOverlay(new GhostCameraOverlay());
else
_overlay.RemoveOverlay<GhostCameraOverlay>();
}
//Face Filter
private void OnToggleFaceFilter(EntityUid uid, PhotoFaceFilterComponent component, TogglePhotoFilterEvent args)
{
if (args.State)
_overlay.AddOverlay(new FaceCameraOverlay());
else
_overlay.RemoveOverlay<FaceCameraOverlay>();
}
//Info Filter
private void OnToggleInfoFilter(EntityUid uid, PhotoInfoFilterComponent component, TogglePhotoFilterEvent args)
{
if (args.State)
_overlay.AddOverlay(new InfoCameraOverlay());
else
_overlay.RemoveOverlay<InfoCameraOverlay>();
}
}
public record struct TogglePhotoFilterEvent(bool State)
{
public bool State = State;
}
+20 -11
View File
@@ -1,11 +1,16 @@
using Content.Client._WL.Photo.Filters;
using Content.Client._WL.Photo.UI;
using Content.Shared._WL.Photo;
using Robust.Shared.Graphics;
namespace Content.Client._WL.Photo;
public sealed partial class PhotoSystem : SharedPhotoSystem
{
[Dependency] private readonly PhotoFilterSystem _filter = default!;
public Dictionary<PhotoCameraComponent, PhotoCameraBoundUserInterface> ActiveCameras = new();
public Dictionary<IEye, EntityUid> ActiveEyes = new();
public override void Initialize()
{
@@ -22,19 +27,23 @@ public sealed partial class PhotoSystem : SharedPhotoSystem
}
}
public void OpenCameraUi(PhotoCameraComponent component, PhotoCameraBoundUserInterface window)
{
if (ActiveCameras.ContainsKey(component))
return;
ActiveCameras.Add(component, window);
}
public void CloseCameraUi(PhotoCameraComponent component)
public void OpenCameraUi(EntityUid? uid, PhotoCameraComponent component, PhotoCameraBoundUserInterface window)
{
if (!ActiveCameras.ContainsKey(component))
return;
ActiveCameras.Add(component, window);
ActiveCameras.Remove(component);
if (EntityManager.TryGetComponent<EyeComponent>(uid, out var eye) && !ActiveEyes.ContainsKey(eye.Eye))
ActiveEyes.Add(eye.Eye, uid.Value);
_filter.EnableFilter(uid);
}
public void CloseCameraUi(EntityUid? uid, PhotoCameraComponent component)
{
if (ActiveCameras.ContainsKey(component))
ActiveCameras.Remove(component);
if (EntityManager.TryGetComponent<EyeComponent>(uid, out var eye) && ActiveEyes.ContainsKey(eye.Eye))
ActiveEyes.Remove(eye.Eye);
}
}
@@ -1,9 +1,15 @@
using Content.Client.Decals.Overlays;
using Content.Client.Light;
using Content.Client.Parallax;
using Content.Shared._WL.Photo;
using Robust.Client.Audio;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Client.ResourceManagement;
using Robust.Client.UserInterface;
using Robust.Shared.Audio.Sources;
using Robust.Shared.Prototypes;
using System.Linq;
using System.Numerics;
namespace Content.Client._WL.Photo.UI;
@@ -68,7 +74,7 @@ public sealed class PhotoCameraBoundUserInterface : BoundUserInterface
if (EntMan.TryGetComponent<PhotoCameraComponent>(_cameraEntity, out var component))
{
_photoSystem.OpenCameraUi(component, this);
_photoSystem.OpenCameraUi(_cameraEntity, component, this);
UpdateControl(component, 1);
}
@@ -85,7 +91,7 @@ public sealed class PhotoCameraBoundUserInterface : BoundUserInterface
if (_cameraEntity != null)
{
if (EntMan.TryGetComponent<PhotoCameraComponent>(_cameraEntity, out var component))
_photoSystem.CloseCameraUi(component);
_photoSystem.CloseCameraUi(_cameraEntity, component);
_cameraEntity = null;
}
@@ -27,7 +27,7 @@
<BoxContainer Orientation="Horizontal" HorizontalExpand="True">
<!--Viewport Window-->
<Control MinWidth="236" MinHeight="236" Margin="22 44 0 0" Name="CameraViewBox">
<Control MinWidth="240" MinHeight="240" Margin="19.5 40 0 0" Name="CameraViewBox">
<viewport:ScalingViewport Name="CameraView"
VerticalExpand="True"
HorizontalExpand="True"
@@ -112,6 +112,7 @@ namespace Content.IntegrationTests.Tests
"CorvaxWLPrairie",
"CorvaxWLRenga",
"CorvaxWLRest",
"CorvaxWLBagel",
// WL-End
"Dev",
"TestTeg",
@@ -0,0 +1,43 @@
using Content.Shared._WL.Photo.Filters;
using Content.Shared.Coordinates;
using Content.Shared.Ghost;
using Robust.Server.GameObjects;
using Robust.Shared.Timing;
namespace Content.Server._WL.Photo.Filter;
public sealed partial class PhotoGhostFilterSystem : EntitySystem
{
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly TransformSystem _transform = default!;
[Dependency] private readonly EntityLookupSystem _lookup = default!;
public override void Initialize()
{
base.Initialize();
}
public override void Update(float frameTime)
{
base.Update(frameTime);
var now = _timing.CurTime;
var query = EntityQueryEnumerator<PhotoGhostFilterComponent>();
while (query.MoveNext(out var uid, out var comp))
{
if (now < comp.NextUpdateTime)
continue;
comp.ViewedGhosts.Clear();
comp.NextUpdateTime = now + comp.UpdateTime;
var entities = _lookup.GetEntitiesInRange(uid, comp.ViewRange);
foreach (var entity in entities)
{
if (HasComp<GhostComponent>(entity))
comp.ViewedGhosts.Add(_transform.ToWorldPosition(entity.ToCoordinates()));
}
Dirty(uid, comp);
}
}
}
+26 -17
View File
@@ -2,12 +2,14 @@ using Content.Server.Hands.Systems;
using Content.Server.Materials;
using Content.Server.Popups;
using Content.Shared._WL.Photo;
using Content.Shared._WL.Photo.Filters;
using Content.Shared.Interaction.Events;
using Content.Shared.Materials;
using Content.Shared.Timing;
using Content.Shared.UserInterface;
using Robust.Server.Audio;
using Robust.Server.GameObjects;
using Robust.Shared.Containers;
namespace Content.Server._WL.Photo;
@@ -29,7 +31,6 @@ public sealed partial class PhotoSystem : SharedPhotoSystem
base.Initialize();
SubscribeLocalEvent<PhotoCameraComponent, ActivatableUIOpenAttemptEvent>(OnOpenCameraInterfaceAttempt);
SubscribeLocalEvent<PhotoCameraComponent, AfterActivatableUIOpenEvent>(OnOpenCameraInterface);
Subs.BuiEvents<PhotoCameraComponent>(PhotoCameraUiKey.Key, subs =>
{
subs.Event<BoundUIClosedEvent>(OnCameraBoundUiClose);
@@ -39,6 +40,8 @@ public sealed partial class PhotoSystem : SharedPhotoSystem
SubscribeLocalEvent<PhotoCameraComponent, DroppedEvent>(OnCameraDropped);
SubscribeLocalEvent<PhotoCardComponent, AfterActivatableUIOpenEvent>(OnOpenCardInterface);
SubscribeLocalEvent<PhotoCameraComponent, EntInsertedIntoContainerMessage>(OnFilterInserted);
SubscribeLocalEvent<PhotoCameraComponent, EntRemovedFromContainerMessage>(OnFilterRemoved);
}
private void OnOpenCameraInterfaceAttempt(EntityUid uid, PhotoCameraComponent component, ActivatableUIOpenAttemptEvent args)
@@ -58,14 +61,6 @@ public sealed partial class PhotoSystem : SharedPhotoSystem
}
}
private void OnOpenCameraInterface(EntityUid uid, PhotoCameraComponent component, AfterActivatableUIOpenEvent args)
{
UpdateCameraInterface(uid, component);
component.User = args.User;
EnsureComp<PhotoCameraUserComponent>(args.User);
}
private void OnCameraBoundUiClose(EntityUid uid, PhotoCameraComponent component, BoundUIClosedEvent args)
{
if (component.User == null)
@@ -86,14 +81,6 @@ public sealed partial class PhotoSystem : SharedPhotoSystem
TryTakeImage(uid, component, message.Data);
}
private void UpdateCameraInterface(EntityUid uid, PhotoCameraComponent component, EntityUid? player = null)
{
bool hasPaper = _material.CanChangeMaterialAmount(uid, component.CardMaterial, -component.CardCost);
var state = new PhotoCameraUiState(GetNetEntity(uid), hasPaper);
_userInterface.SetUiState(uid, PhotoCameraUiKey.Key, state);
}
private void OnPaperInserted(EntityUid uid, PhotoCameraComponent component, MaterialAmountChangedEvent args)
{
UpdateCameraInterface(uid, component, component.User);
@@ -151,6 +138,28 @@ public sealed partial class PhotoSystem : SharedPhotoSystem
data[4] == 0x0D && data[5] == 0x0A && data[6] == 0x1A && data[7] == 0x0A;
}
private void OnFilterInserted(EntityUid uid, PhotoCameraComponent component, EntInsertedIntoContainerMessage args)
{
if (!TryComp<PhotoCameraFilterComponent>(args.Entity, out var filter))
return;
if (args.Container.ID != component.FilterSlot)
return;
EntityManager.AddComponents(uid, filter.FilterComponents);
}
private void OnFilterRemoved(EntityUid uid, PhotoCameraComponent component, EntRemovedFromContainerMessage args)
{
if (!TryComp<PhotoCameraFilterComponent>(args.Entity, out var filter))
return;
if (args.Container.ID != component.FilterSlot)
return;
EntityManager.RemoveComponents(uid, filter.FilterComponents);
}
// Photo Card
private void OnOpenCardInterface(EntityUid uid, PhotoCardComponent component, AfterActivatableUIOpenEvent args)
@@ -0,0 +1,7 @@
namespace Content.Shared._WL.Overlays;
[RegisterComponent]
public sealed partial class IgnoreGlobalOverlaysComponent : Component
{
}
@@ -0,0 +1,10 @@
using Robust.Shared.Prototypes;
namespace Content.Shared._WL.Photo.Filters;
[RegisterComponent]
public sealed partial class PhotoCameraFilterComponent : Component
{
[DataField()]
public ComponentRegistry FilterComponents = new();
}
@@ -0,0 +1,11 @@
using Robust.Shared.GameStates;
using Robust.Shared.Utility;
namespace Content.Shared._WL.Photo.Filters;
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
public sealed partial class PhotoFaceFilterComponent : Component
{
[DataField(required: true), AutoNetworkedField]
public SpriteSpecifier? Visual;
}
@@ -0,0 +1,12 @@
using Robust.Shared.GameStates;
using System;
using System.Collections.Generic;
using System.Text;
namespace Content.Shared._WL.Photo.Filters;
[RegisterComponent, NetworkedComponent]
public sealed partial class PhotoFilterBaseComponent : Component
{
}
@@ -0,0 +1,23 @@
using Robust.Shared.GameStates;
using Robust.Shared.Utility;
using System.Numerics;
namespace Content.Shared._WL.Photo.Filters;
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
public sealed partial class PhotoGhostFilterComponent : Component
{
[DataField, AutoNetworkedField]
public List<Vector2> ViewedGhosts = new();
[DataField, AutoNetworkedField]
public SpriteSpecifier Visual = new SpriteSpecifier.Texture(new("/Textures/_WL/Mobs/Ghost/black.png"));
[DataField]
public float ViewRange = 20f;
[DataField]
public TimeSpan UpdateTime = TimeSpan.FromSeconds(0.1f);
public TimeSpan NextUpdateTime;
}
@@ -0,0 +1,9 @@
using Robust.Shared.GameStates;
namespace Content.Shared._WL.Photo.Filters;
[RegisterComponent, NetworkedComponent]
public sealed partial class PhotoInfoFilterComponent : Component
{
}
@@ -0,0 +1,10 @@
using Robust.Shared.GameStates;
namespace Content.Shared._WL.Photo.Filters;
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
public sealed partial class PhotoShaderFilterComponent : Component
{
[DataField, AutoNetworkedField]
public string? Shader;
}
@@ -7,7 +7,7 @@ using System.Numerics;
namespace Content.Shared._WL.Photo;
[RegisterComponent]
public sealed partial class PhotoCameraComponent : Component
public partial class PhotoCameraComponent : Component
{
[DataField]
public Vector2 ViewBox = new Vector2(5, 5);
@@ -19,6 +19,7 @@ public sealed partial class PhotoCameraComponent : Component
[DataField]
public SoundSpecifier ErrorSound = new SoundPathSpecifier("/Audio/Machines/airlock_deny.ogg");
// Card
[DataField]
public string CardPrototype = "PhotoCard";
[DataField]
@@ -26,6 +27,10 @@ public sealed partial class PhotoCameraComponent : Component
[DataField]
public int CardCost = 100;
//Filter
[DataField]
public string FilterSlot = "filter";
[ViewVariables]
public EntityUid? User;
}
+20 -1
View File
@@ -3,12 +3,13 @@ using Content.Shared.Alert;
using Content.Shared.Examine;
using Content.Shared.Materials;
using Content.Shared.Movement.Events;
using Content.Shared.Shuttles.Components;
using Content.Shared.UserInterface;
namespace Content.Shared._WL.Photo;
public abstract partial class SharedPhotoSystem : EntitySystem
{
[Dependency] private readonly SharedUserInterfaceSystem _userInterface = default!;
[Dependency] private readonly ActionBlockerSystem _actionBlockerSystem = default!;
[Dependency] private readonly AlertsSystem _alerts = default!;
[Dependency] private readonly SharedMaterialStorageSystem _material = default!;
@@ -17,6 +18,8 @@ public abstract partial class SharedPhotoSystem : EntitySystem
{
base.Initialize();
SubscribeLocalEvent<PhotoCameraComponent, AfterActivatableUIOpenEvent>(OnOpenCameraInterface);
SubscribeLocalEvent<PhotoCameraComponent, ExaminedEvent>(OnCameraExamined);
SubscribeLocalEvent<PhotoCameraUserComponent, UpdateCanMoveEvent>(HandleMovementBlock);
@@ -24,6 +27,22 @@ public abstract partial class SharedPhotoSystem : EntitySystem
SubscribeLocalEvent<PhotoCameraUserComponent, ComponentShutdown>(OnShutdown);
}
private void OnOpenCameraInterface(EntityUid uid, PhotoCameraComponent component, AfterActivatableUIOpenEvent args)
{
UpdateCameraInterface(uid, component);
component.User = args.User;
EnsureComp<PhotoCameraUserComponent>(args.User);
}
protected virtual void UpdateCameraInterface(EntityUid uid, PhotoCameraComponent component, EntityUid? player = null)
{
bool hasPaper = _material.CanChangeMaterialAmount(uid, component.CardMaterial, -component.CardCost);
var state = new PhotoCameraUiState(GetNetEntity(uid), hasPaper);
_userInterface.SetUiState(uid, PhotoCameraUiKey.Key, state);
}
protected virtual void OnShutdown(EntityUid uid, PhotoCameraUserComponent component, ComponentShutdown args)
{
_actionBlockerSystem.UpdateCanMove(uid);
+2 -1
View File
@@ -1,3 +1,4 @@
photo-camera-not-holding = Требуется держать в руках
photo-camera-no-paper = Отсутствует бумага
photo-camera-examined-paper-left = Листов бумаги: { $count }
photo-camera-examined-paper-left = Листов бумаги: { $count }
photo-camera-filter-slot = фильтр
@@ -3,3 +3,25 @@ ent-PhotoCamera = фотоаппарат
ent-PhotoCard = фотография
.desc = Лист бумаги с напечатанным изображением.
ent-PhotoFilterPack = набор фильтров
.desc = Удобная стойка для хранения фото-фильтров.
ent-PhotoFilterPackFill = { ent-PhotoFilterPack }
.desc = { ent-PhotoFilterPack.desc }
.suffix = Полный
ent-PhotoFilterMonochrome = винтажный фильтр
.desc = Простой фильтр для камеры создающий винтажную атмосферу.
ent-PhotoFilterNightVision = ночной фильтр
.desc = Простой фильтр для камеры. Ночное зрение в комплект не входит.
ent-PhotoFilterCatEars = кошачий фильтр
.desc = Умный фильтр для камеры превращающий ваших коллег в котиков!.
ent-PhotoFilterInfo = информационный фильтр
.desc = Умный фильтр для камеры, идеально подходит для фото-отчётов.
ent-PhotoFilterGhost = выжженный фильтр
.desc = Старый фильтр для камеры.. Даёт очень странные возможности.
+47 -108
View File
@@ -2,10 +2,10 @@ meta:
format: 7
category: Map
engineVersion: 270.1.0
forkId: syndicate-wl
forkVersion: 3c7617e37a4857aab384e0e93c7cf7dec0672d35
time: 03/17/2026 19:00:52
entityCount: 26409
forkId: ""
forkVersion: ""
time: 03/29/2026 15:20:36
entityCount: 26406
maps:
- 943
grids:
@@ -17355,19 +17355,6 @@ entities:
- 21678
- type: Fixtures
fixtures: {}
- uid: 14880
components:
- type: Transform
rot: 3.141592653589793 rad
pos: -28.5,33.5
parent: 60
- type: DeviceList
devices:
- 5982
- 5984
- 14840
- type: Fixtures
fixtures: {}
- uid: 14924
components:
- type: Transform
@@ -17745,16 +17732,6 @@ entities:
- 15377
- type: Fixtures
fixtures: {}
- uid: 21615
components:
- type: Transform
pos: 1.5,6.5
parent: 21614
- type: DeviceList
devices:
- 21873
- type: Fixtures
fixtures: {}
- uid: 21616
components:
- type: Transform
@@ -19111,7 +19088,7 @@ entities:
- type: AccessReader
accessListsOriginal: []
- type: Door
secondsUntilStateChange: -281352.16
secondsUntilStateChange: -281439.2
state: Opening
- type: DeviceLinkSource
lastSignals:
@@ -20460,7 +20437,7 @@ entities:
pos: 16.5,-25.5
parent: 60
- type: Door
secondsUntilStateChange: -186488.95
secondsUntilStateChange: -186575.98
state: Opening
- type: DeviceLinkSource
lastSignals:
@@ -20747,7 +20724,7 @@ entities:
pos: 3.5,0.5
parent: 6138
- type: Door
secondsUntilStateChange: -144425.08
secondsUntilStateChange: -144512.11
state: Opening
- type: DeviceLinkSource
lastSignals:
@@ -21352,7 +21329,7 @@ entities:
pos: -50.5,6.5
parent: 60
- type: Door
secondsUntilStateChange: -219552.52
secondsUntilStateChange: -219639.55
state: Opening
- type: DeviceLinkSource
lastSignals:
@@ -21507,7 +21484,7 @@ entities:
pos: 0.5,-1.5
parent: 6138
- type: Door
secondsUntilStateChange: -150236.3
secondsUntilStateChange: -150323.33
state: Opening
- type: DeviceLinkSource
lastSignals:
@@ -21590,7 +21567,7 @@ entities:
pos: -7.5,23.5
parent: 60
- type: Door
secondsUntilStateChange: -125316.23
secondsUntilStateChange: -125403.26
state: Opening
- type: DeviceLinkSource
lastSignals:
@@ -21851,16 +21828,6 @@ entities:
- type: DeviceNetwork
deviceLists:
- 14871
- uid: 14840
components:
- type: Transform
pos: -29.5,35.5
parent: 60
- type: DeviceNetwork
configurators:
- invalid
deviceLists:
- 14880
- uid: 14842
components:
- type: Transform
@@ -78732,6 +78699,13 @@ entities:
parent: 60
- type: Fixtures
fixtures: {}
- uid: 1699
components:
- type: Transform
pos: -22.5,-11.5
parent: 60
- type: Fixtures
fixtures: {}
- uid: 11374
components:
- type: Transform
@@ -78746,25 +78720,6 @@ entities:
parent: 60
- type: Fixtures
fixtures: {}
- proto: DeployableBarrier
entities:
- uid: 1155
components:
- type: Transform
anchored: True
pos: -21.5,-11.5
parent: 60
- type: Physics
bodyType: Static
- type: Lock
locked: True
- type: PointLight
enabled: True
- uid: 1699
components:
- type: Transform
pos: -22.5,-11.5
parent: 60
- proto: DeskBell
entities:
- uid: 2388
@@ -86981,17 +86936,6 @@ entities:
- type: DeviceNetwork
deviceLists:
- 4733
- uid: 21873
components:
- type: Transform
rot: 3.141592653589793 rad
pos: 0.5,6.5
parent: 21614
- type: DeviceNetwork
configurators:
- invalid
deviceLists:
- 21615
- uid: 23877
components:
- type: Transform
@@ -87231,7 +87175,7 @@ entities:
- 8898
- 885
- type: Door
secondsUntilStateChange: -253504.5
secondsUntilStateChange: -253591.53
state: Closing
- uid: 1779
components:
@@ -87300,7 +87244,7 @@ entities:
pos: -20.5,-31.5
parent: 60
- type: Door
secondsUntilStateChange: -65693.68
secondsUntilStateChange: -65780.71
state: Closing
- uid: 2251
components:
@@ -87372,7 +87316,7 @@ entities:
pos: 41.5,-42.5
parent: 60
- type: Door
secondsUntilStateChange: -177434.69
secondsUntilStateChange: -177521.72
state: Closing
- uid: 3110
components:
@@ -88190,7 +88134,7 @@ entities:
pos: 53.5,-7.5
parent: 60
- type: Door
secondsUntilStateChange: -140475.78
secondsUntilStateChange: -140562.81
state: Closing
- type: Firelock
emergencyCloseCooldown: 13573.7864281
@@ -116636,19 +116580,6 @@ entities:
- 17088
- type: AtmosPipeColor
color: '#0055CCFF'
- uid: 5982
components:
- type: Transform
rot: 1.5707963267948966 rad
pos: -26.5,34.5
parent: 60
- type: DeviceNetwork
configurators:
- invalid
deviceLists:
- 14880
- type: AtmosPipeColor
color: '#0055CCFF'
- uid: 5988
components:
- type: Transform
@@ -118496,24 +118427,6 @@ entities:
pipeLayer: Tertiary
- type: AtmosPipeColor
color: '#990000FF'
- uid: 5984
components:
- type: Transform
rot: 1.5707963267948966 rad
pos: -29.5,34.5
parent: 60
- type: DeviceNetwork
configurators:
- invalid
deviceLists:
- 14880
- type: Construction
step: 1
edge: 0
- type: AtmosPipeLayers
pipeLayer: Tertiary
- type: AtmosPipeColor
color: '#990000FF'
- uid: 6097
components:
- type: Transform
@@ -150099,13 +150012,39 @@ entities:
- type: Transform
pos: -33.5,-14.5
parent: 60
- proto: SpawnPointSeniorEngineer
entities:
- uid: 14840
components:
- type: Transform
pos: 2.5,20.5
parent: 60
- proto: SpawnPointSeniorOfficer
entities:
- uid: 5982
components:
- type: Transform
pos: -26.5,-1.5
parent: 60
- uid: 24433
components:
- type: Transform
pos: -32.5,-12.5
parent: 60
- proto: SpawnPointSeniorPhysician
entities:
- uid: 5984
components:
- type: Transform
pos: 45.5,-13.5
parent: 60
- proto: SpawnPointSeniorResearcher
entities:
- uid: 1155
components:
- type: Transform
pos: -46.5,4.5
parent: 60
- proto: SpawnPointServiceWorker
entities:
- uid: 2327
@@ -263,7 +263,6 @@
weight: 1
- id: ClothingHandsGlovesConducting
weight: 0.1
- id: PhotoCamera #WL-Changes-Photo
# Uncommon Group
- !type:GroupSelector
weight: 23
@@ -291,6 +290,7 @@
children:
- id: DrinkSpaceGlue
- id: DrinkSpaceLube
- id: PhotoCamera #Corvax-WL-Changes
# Rare Group
- !type:GroupSelector
weight: 2
@@ -309,6 +309,11 @@
- id: SpectralLocator
- id: LidSalami
weight: 0.05
#Corvax-WL-Changes-start
- id: PhotoFilterMonochrome
- id: PhotoFilterNightVision
- id: PhotoFilterGhost
#Corvax-WL-Changes-end
- type: entity
name: Maint Loot Spawner
@@ -68,8 +68,9 @@
- DawInstrumentMachineCircuitboard
- MassMediaCircuitboard
- JukeboxCircuitBoard
- PhotoCameraRecipe #WL-Changes-Photo
# WL-Changes-start
- PhotoCameraRecipe
- PhotoFilterPackFill
- BassGuitarInstrumentRecipe
- ElectricGuitarInstrumentRecipe
- MicrophoneInstrumentRecipe
@@ -9,6 +9,7 @@
layers:
- state: camera
- type: Eye
- type: IgnoreGlobalOverlays
- type: PhotoCamera
- type: UseDelay
- type: ActivatableUI
@@ -21,6 +22,13 @@
whitelist:
tags:
- Paper
- type: ItemSlots
slots:
filter:
name: photo-camera-filter-slot
whitelist:
components:
- PhotoCameraFilter
- type: entity
name: "photo"
@@ -41,3 +49,140 @@
type: PhotoCardBoundUserInterface
- type: PhotoCard
- type: FaxableObject
- type: entity
id: PhotoFilterPack
parent: [ BoxCardboard, BaseBagOpenClose ]
name: "filter pack"
description: "A convenient thing for storing camera filters."
components:
- type: Sprite
sprite: _WL/Objects/Misc/filter_rack.rsi
layers:
- state: rack
- state: fill-0
map: ["enum.StorageFillLayers.Fill"]
- type: Item
size: Small
- type: Storage
grid:
- 0,0,3,1
- type: StorageFillVisualizer
maxFillLevels: 5
fillBaseName: fill
- type: entity
id: PhotoFilterPackFill
parent: PhotoFilterPack
suffix: Filled
components:
- type: EntityTableContainerFill
containers:
storagebase: !type:AllSelector
children:
- id: PhotoFilterMonochrome
- id: PhotoFilterNightVision
- id: PhotoFilterCatEars
- id: PhotoFilterInfo
- type: entity
name: 'vintage filter'
parent: BaseItem
id: PhotoFilterMonochrome
description: "A simple camera filter that gives a vintage atmosphere."
components:
- type: Sprite
sprite: _WL/Objects/Misc/camera.rsi
layers:
- state: filter
- state: filter-gray
- state: filter-top
color: "#a0da4b"
- type: PhotoCameraFilter
filterComponents:
- type: PhotoShaderFilter
shader: CameraMonochrome
- type: PhotoFilterBase
- type: entity
name: 'night filter'
parent: BaseItem
id: PhotoFilterNightVision
description: "A simple camera filter. Unfortunately, it doesn't provide night vision"
components:
- type: Sprite
sprite: _WL/Objects/Misc/camera.rsi
layers:
- state: filter
- state: filter-line
- state: filter-top
color: "#a0da4b"
- type: PhotoCameraFilter
filterComponents:
- type: PhotoShaderFilter
shader: CameraNightVision
- type: PhotoFilterBase
- type: entity
name: 'burned filter'
parent: BaseItem
id: PhotoFilterGhost
description: "Burnt camera filter.. giving a very strange ability."
components:
- type: Sprite
sprite: _WL/Objects/Misc/camera.rsi
layers:
- state: filter
- state: filter-ghost
- state: filter-top
color: "#e53c54"
- type: PhotoCameraFilter
filterComponents:
- type: PhotoGhostFilter
visual:
sprite: _WL/Effects/photo_filters.rsi
state: observer
- type: PhotoFilterBase
- type: entity
name: 'cat filter'
parent: BaseItem
id: PhotoFilterCatEars
description: "A smart camera filter that turns your colleagues into kittens!"
components:
- type: Sprite
sprite: _WL/Objects/Misc/camera.rsi
layers:
- state: filter
- state: filter-smart
- state: filter-top
color: "#d751cc"
- type: PhotoCameraFilter
filterComponents:
- type: PhotoFaceFilter
visual:
sprite: _WL/Effects/photo_filters.rsi
state: cat
- type: PhotoFilterBase
- type: entity
name: 'information filter'
parent: BaseItem
id: PhotoFilterInfo
description: "A smart camera filter, perfect for photo reports."
components:
- type: Sprite
sprite: _WL/Objects/Misc/camera.rsi
layers:
- state: filter
- state: filter-smart
- state: filter-top
color: "#d751cc"
- type: PhotoCameraFilter
filterComponents:
- type: PhotoInfoFilter
- type: PhotoFaceFilter
visual:
sprite: _WL/Effects/photo_filters.rsi
state: box
- type: PhotoFilterBase
@@ -1,18 +1,19 @@
- type: gameMapPool
id: WhitelistMapPool
maps:
# Highpop (25+ players)
# Highpop (25+ players)
- CorvaxWLRenga
- CorvaxWLRest
- CorvaxWLMarathon
- CorvaxWLBagel
# - CorvaxWLAlpha # 🔨
# BasePop (0-25 players)
- Bagel
# MidPop (14-25 players)
- CorvaxWLPaper
- CorvaxWLStraumur
- CorvaxWLKolter
- CorvaxWLMaus
# - CorvaxPearl # При условии, что Пёрл — обновляемая карта основы.
# - Amber # ?
- CorvaxTushkan # При условии, что Тушкан — обновляемая карта основы.
# LowPop (1-13 players)
- CorvaxWLNanoStation
# - CorvaxWLPrairie
- CorvaxWLMaus
@@ -1,83 +1,82 @@
# Special Map for Corvax - Whitelist
# - type: gameMap
# id: CorvaxWLBagel
# mapName: 'Багель'
# mapPath: /Maps/_WL/wl_bagel.yml
# maxRandomOffset: 0
# randomRotation: false
# minPlayers: 5
# maxPlayers: 30
# stations:
# CorvaxBagel:
# stationProto: StandardNanotrasenStation
# components:
# - type: StationNameSetup
# mapNameTemplate: '{0} Багель {1}'
# nameGenerator:
# !type:NanotrasenNameGenerator
# prefixCreator: 'AM'
# - type: StationEmergencyShuttle
# emergencyShuttlePath: /Maps/_WL/Shuttles/wl_bagel_evac.yml
# - type: StationJobs
# availableJobs:
#
# # command
# Captain: [ 1, 1 ]
# IAA: [ 1, 1 ]
# Quartermaster: [ 1, 1 ]
# ChiefEngineer: [ 1, 1 ]
# ChiefMedicalOfficer: [ 1, 1 ]
# ResearchDirector: [ 1, 1 ]
# HeadOfSecurity: [ 1, 1 ]
# HeadOfPersonnel: [ 1, 1 ]
# Adjutant: [ 1, 1 ]
#
# # cargo
# SalvageSpecialist: [ 3, 3 ]
# CargoTechnician: [ 2, 2 ]
#
# # engineering
# AtmosphericTechnician: [ 3, 3 ]
# SeniorEngineer: [ 1, 1 ]
# StationEngineer: [ 2, 2 ]
# TechnicalAssistant: [ 2, 2 ]
#
# # medical
# MedicalDoctor: [ 2, 2 ]
# SeniorPhysician: [ 1, 1 ]
# MedicalIntern: [ 2, 2 ]
# Psychologist: [ 1, 1 ]
# Paramedic: [ 1, 1 ]
# Chemist: [ 2, 2 ]
#
# # science
# SeniorResearcher: [ 1, 1 ]
# Scientist: [ 3, 3 ]
# ResearchAssistant: [ 2, 2 ]
#
# # security
# Warden: [ 1, 1 ]
# SecurityOfficer: [ 2, 2 ]
# SeniorOfficer: [ 1, 1 ]
# SecurityCadet: [ 2, 2 ]
# Detective: [ 1, 1 ]
# Brigmedic: [ 1, 1 ]
# Pilot: [ 2, 2 ]
#
# # service
# Bartender: [ 2, 2 ]
# Botanist: [ 2, 2 ]
# Chaplain: [ 1, 1 ]
# Chef: [ 2, 2 ]
# Clown: [ 1, 1 ]
# Janitor: [ 2, 2 ]
# Librarian: [ 1, 1 ]
# Mime: [ 1, 1 ]
# Musician: [ 1, 1 ]
# Reporter: [ 1, 1 ]
# ServiceWorker: [ 2, 2 ]
# Passenger: [ -1, -1 ]
#
# #silicon
# Borg: [ 2, 2 ]
# StationAi: [ 1, 1 ]
- type: gameMap
id: CorvaxWLBagel
mapName: 'Багель'
mapPath: /Maps/_WL/wl_bagel.yml
maxRandomOffset: 0
randomRotation: false
minPlayers: 25
stations:
CorvaxBagel:
stationProto: StandardNanotrasenStation
components:
- type: StationNameSetup
mapNameTemplate: '{0} Багель {1}'
nameGenerator:
!type:NanotrasenNameGenerator
prefixCreator: 'AM'
- type: StationEmergencyShuttle
emergencyShuttlePath: /Maps/_WL/Shuttles/wl_bagel_evac.yml
- type: StationJobs
availableJobs:
# command
Captain: [ 1, 1 ]
IAA: [ 1, 1 ]
Quartermaster: [ 1, 1 ]
ChiefEngineer: [ 1, 1 ]
ChiefMedicalOfficer: [ 1, 1 ]
ResearchDirector: [ 1, 1 ]
HeadOfSecurity: [ 1, 1 ]
HeadOfPersonnel: [ 1, 1 ]
Adjutant: [ 1, 1 ]
# cargo
SalvageSpecialist: [ 3, 3 ]
CargoTechnician: [ 2, 2 ]
# engineering
AtmosphericTechnician: [ 3, 3 ]
SeniorEngineer: [ 1, 1 ]
StationEngineer: [ 2, 2 ]
TechnicalAssistant: [ 2, 2 ]
# medical
MedicalDoctor: [ 2, 2 ]
SeniorPhysician: [ 1, 1 ]
MedicalIntern: [ 2, 2 ]
Psychologist: [ 1, 1 ]
Paramedic: [ 1, 1 ]
Chemist: [ 2, 2 ]
# science
SeniorResearcher: [ 1, 1 ]
Scientist: [ 3, 3 ]
ResearchAssistant: [ 2, 2 ]
# security
Warden: [ 1, 1 ]
SecurityOfficer: [ 2, 2 ]
SeniorOfficer: [ 1, 1 ]
SecurityCadet: [ 2, 2 ]
Detective: [ 1, 1 ]
Brigmedic: [ 1, 1 ]
Pilot: [ 2, 2 ]
# service
Bartender: [ 2, 2 ]
Botanist: [ 2, 2 ]
Chaplain: [ 1, 1 ]
Chef: [ 2, 2 ]
Clown: [ 1, 1 ]
Janitor: [ 2, 2 ]
Librarian: [ 1, 1 ]
Mime: [ 1, 1 ]
Musician: [ 1, 1 ]
Reporter: [ 1, 1 ]
ServiceWorker: [ 2, 2 ]
Passenger: [ -1, -1 ]
#silicon
Borg: [ 2, 2 ]
StationAi: [ 1, 1 ]
@@ -2,8 +2,7 @@
id: CorvaxWLMarathon
mapName: 'Марафон'
mapPath: /Maps/_WL/wl_marathon.yml
minPlayers: 15
maxPlayers: 55
minPlayers: 25
stations:
CorvaxWLMarathon:
stationProto: StandardNanotrasenStation
@@ -5,7 +5,7 @@
maxRandomOffset: 0
randomRotation: false
minPlayers: 0
maxPlayers: 40
maxPlayers: 20
stations:
CorvaxMaus:
stationProto: StandardNanotrasenStation
@@ -4,7 +4,7 @@
mapName: 'НаноСтейшн'
mapPath: /Maps/_WL/wl_nanostation.yml
minPlayers: 0
maxPlayers: 25
maxPlayers: 13
stations:
CorvaxNanoStation:
stationProto: StandardNanotrasenStation
@@ -5,7 +5,8 @@
mapPath: /Maps/_WL/wl_paper.yml
maxRandomOffset: 0
randomRotation: false
minPlayers: 0
minPlayers: 14
maxPlayers: 25
stations:
CorvaxPaper:
stationProto: StandardNanotrasenStation
@@ -6,7 +6,7 @@
maxRandomOffset: 0
randomRotation: false
minPlayers: 0
maxPlayers: 15
maxPlayers: 13
stations:
CorvaxPrairie:
stationProto: StandardNanotrasenStation
@@ -5,7 +5,7 @@
mapPath: /Maps/_WL/wl_rest.yml
maxRandomOffset: 0
randomRotation: false
minPlayers: 30
minPlayers: 25
stations:
CorvaxWLRest:
stationProto: StandardNanotrasenStation
@@ -49,7 +49,7 @@
Paramedic: [ 1, 1 ]
Chemist: [ 2, 2 ]
# science
# science
SeniorResearcher: [ 1, 1 ]
Scientist: [ 3, 3 ]
ResearchAssistant: [ 2, 2 ]
@@ -4,7 +4,8 @@
mapPath: /Maps/_WL/wl_straumur.yml
maxRandomOffset: 0
randomRotation: false
minPlayers: 20
minPlayers: 15
maxPlayers: 25
stations:
CorvaxWLStraumur:
stationProto: StandardNanotrasenStation
@@ -78,4 +79,4 @@
# silicon
StationAi: [ 1, 1 ]
Borg: [ 2, 2 ]
Borg: [ 2, 2 ]
@@ -90,6 +90,7 @@
id: Photo
recipes:
- PhotoCameraRecipe
- PhotoFilterPackFill
- type: latheRecipePack
id: SecBalaclavStatic
@@ -7,6 +7,16 @@
Glass: 250
Gold: 50
- type: latheRecipe
id: PhotoFilterPackFill
result: PhotoFilterPackFill
completetime: 5
materials:
Steel: 100
Glass: 200
Plastic: 200
Gold: 50
- type: latheRecipe
id: BassGuitarInstrumentRecipe
result: BassGuitarInstrument
@@ -0,0 +1,14 @@
- type: shader
id: CameraMonochrome
kind: source
path: "/Textures/_WL/Shaders/monochrome.swsl"
- type: shader
id: CameraNightVision
kind: source
path: "/Textures/_WL/Shaders/night.swsl"
- type: shader
id: CameraGhost
kind: source
path: "/Textures/_WL/Shaders/ghost.swsl"
Binary file not shown.

After

Width:  |  Height:  |  Size: 140 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 B

@@ -0,0 +1,20 @@
{
"version": 1,
"license": "CC-BY-SA-3.0",
"copyright": "Made with love by Misha_Unity",
"size": {
"x": 32,
"y": 32
},
"states": [
{
"name": "box"
},
{
"name": "cat"
},
{
"name": "observer"
}
]
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 314 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 362 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 285 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 194 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 304 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 251 B

@@ -12,6 +12,24 @@
},
{
"name": "card"
},
{
"name": "filter"
},
{
"name": "filter-top"
},
{
"name": "filter-gray"
},
{
"name": "filter-line"
},
{
"name": "filter-ghost"
},
{
"name": "filter-smart"
}
]
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 96 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 179 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 181 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 B

@@ -0,0 +1,29 @@
{
"version": 1,
"license": "CC-BY-SA-3.0",
"copyright": "Made with love by Misha_Unity",
"size": {
"x": 32,
"y": 32
},
"states": [
{
"name": "rack"
},
{
"name": "fill-0"
},
{
"name": "fill-1"
},
{
"name": "fill-2"
},
{
"name": "fill-3"
},
{
"name": "fill-4"
}
]
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 273 B

+58
View File
@@ -0,0 +1,58 @@
uniform highp float SCALE;
const highp vec4 baseColor = vec4(1.0, 0.05, 0.02, 0.5);
const highp vec4 darkColor = vec4(0.05, 0.05, 0.05, 0.5);
highp vec2 hash2(highp vec2 p)
{
p = vec2(dot(p, vec2(127.1, 311.7)),
dot(p, vec2(269.5, 183.3)));
return fract(sin(p) * 43758.5453123);
}
highp vec4 lerpColor(highp vec4 a, highp vec4 b, highp float x)
{
return (a * x + b * (1.0 - x));
}
highp vec2 voronoi(highp vec2 x)
{
highp vec2 n = floor(x);
highp vec2 f = fract(x);
highp float F1 = 1.0;
highp float F2 = 1.0;
for (int j = -1; j <= 1; j ++)
{
for (int i = -1; i <= 1; i ++)
{
highp vec2 g = vec2(float(i), float(j));
highp vec2 o = hash2(n + g);
highp vec2 r = g + o - f;
float d = dot(r, r);
if (d < F1)
{
F2 = F1;
F1 = d;
}
else if (d < F2)
{
F2 = d;
}
}
}
return vec2(sqrt(F1), sqrt(F2));
}
void fragment()
{
highp float scale = 10 / SCALE;
highp vec2 noise = voronoi(UV.xy * scale * (1.0 - UV.y) + vec2(TIME));
COLOR = lerpColor(baseColor, darkColor, noise.x * 2 - 0.5);
}
@@ -0,0 +1,17 @@
uniform sampler2D SCREEN_TEXTURE;
const highp float ColorFactor = 1.0;
const highp float MixFactor = 0.9;
const highp vec3 MixColor = vec3(0.7, 0.4, 0.1);
//Monochrome effect
void fragment()
{
highp vec4 color = zTextureSpec(SCREEN_TEXTURE, UV);
highp vec4 bw = vec4(vec3(zGrayscale(color.rgb) * ColorFactor + color.rgb * (1 - ColorFactor)), color.a);
bw.rgb = bw.rgb * MixFactor + MixColor.rgb * (1 - MixFactor);
COLOR = bw;
}
+24
View File
@@ -0,0 +1,24 @@
uniform sampler2D SCREEN_TEXTURE;
const highp vec3 MixColor = vec3(0.0, 0.9, 0.0);
highp float rand(highp vec2 v)
{
return fract(sin(dot(v, vec2(12.9898, 78.233))) * 43758.5453123);
}
highp vec4 lerpColor(highp vec4 a, highp vec4 b, highp float x)
{
return (a * x + b * (1.0 - x));
}
//Night Vision effect
void fragment()
{
highp vec4 color = zTextureSpec(SCREEN_TEXTURE, UV);
highp float bw = zGrayscale(color.rgb);
highp vec4 outColor = lerpColor(vec4(MixColor, 1.0), vec4(vec3(0.0), 1.0), bw - (rand(UV.xy * TIME) - 0.5) * 0.1);
COLOR = outColor;
}