Skia Tweaks + Removes Nightvision form Lathes (#4308)

* Adds Direction Requests

* Fix

* Fixed EntryPoint, added back Sec Lathe, and added as a Salvage Points item

* Moved SpecOpsGoggles to appease gods

* Give Skia Thermal Vision

* Removed thermals from research.

* Removed thermal vision, added comment
This commit is contained in:
William Lemon 2025-09-07 18:11:07 +10:00 committed by GitHub
parent 01c83ba76b
commit 75a995a730
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
29 changed files with 346 additions and 33 deletions

View File

@ -39,6 +39,7 @@ using Robust.Shared.Prototypes;
using Robust.Shared.Replays;
using Robust.Shared.Timing;
using Content.Client._NF.Emp.Overlays; // Frontier
using Content.Client._RMC14.Xenonids.Screech; // RMC14
namespace Content.Client.Entry
{
@ -173,6 +174,7 @@ namespace Content.Client.Entry
_overlayManager.AddOverlay(new SingularityOverlay());
_overlayManager.AddOverlay(new RadiationPulseOverlay());
_overlayManager.AddOverlay(new RMCXenoScreechShockWaveOverlay()); // RMC14
_overlayManager.AddOverlay(new EmpBlastOverlay()); // Frontier
_chatManager.Initialize();
_clientPreferencesManager.Initialize();

View File

@ -80,6 +80,7 @@ public sealed class ThermalVisionOverlay : Overlay
_lightEntity ??= _entity.SpawnAttachedTo(null, playerXform.Coordinates);
_transform.SetParent(_lightEntity.Value, player.Value);
var light = _entity.EnsureComponent<PointLightComponent>(_lightEntity.Value);
light.NetSyncEnabled = false; // DeltaV - Desync this component
_light.SetRadius(_lightEntity.Value, LightRadius, light);
_light.SetEnergy(_lightEntity.Value, alpha, light);
_light.SetColor(_lightEntity.Value, Comp.Color, light);

View File

@ -0,0 +1,43 @@
using Content.Shared._RMC14.Effect;
using Robust.Client.GameObjects;
using Robust.Shared.Timing;
namespace Content.Client._RMC14.Effect;
public sealed class RMCEffectSystem : SharedRMCEffectSystem
{
// Most effects are pretty large and flashy so we're dividing the opacity of the parent by 3 before applying it to the effect.
private const int OpacityDivider = 3;
[Dependency] private readonly IGameTiming _timing = default!;
public override void FrameUpdate(float frameTime)
{
var time = _timing.CurTime;
var query = EntityQueryEnumerator<EffectAlphaAnimationComponent, SpriteComponent>();
while (query.MoveNext(out var effect, out var sprite))
{
if (effect.SpawnedAt is not { } spawned)
continue;
var alpha = MathHelper.Lerp((spawned + effect.Delay).TotalSeconds, spawned.TotalSeconds, time.TotalSeconds);
sprite.Color = sprite.Color.WithAlpha((float) alpha);
}
var query2 = EntityQueryEnumerator<RMCEffectComponent>();
while (query2.MoveNext(out var uid, out var effect))
{
var parent = Transform(uid).ParentUid;
if (!TryComp(parent, out SpriteComponent? parentSprite))
return;
if (!TryComp(uid, out SpriteComponent? sprite))
return;
// Only apply the reduced opacity to the effect if the parent's opacity is < 1.
if (sprite.Color.A < 1)
sprite.Color = sprite.Color.WithAlpha(parentSprite.Color.A / OpacityDivider);
}
}
}

View File

@ -0,0 +1,77 @@
using System.Numerics;
using Content.Shared._RMC14.Xenonids.Screech;
using Robust.Client.Graphics;
using Robust.Shared.Enums;
using Robust.Shared.Prototypes;
namespace Content.Client._RMC14.Xenonids.Screech;
public sealed class RMCXenoScreechShockWaveOverlay : Overlay, IEntityEventSubscriber
{
[Dependency] private readonly IEntityManager _entMan = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
private SharedTransformSystem? _xformSystem;
public override OverlaySpace Space => OverlaySpace.WorldSpace;
public override bool RequestScreenTexture => true;
private readonly ShaderInstance _shader;
public RMCXenoScreechShockWaveOverlay()
{
IoCManager.InjectDependencies(this);
_shader = _prototypeManager.Index<ShaderPrototype>("RMCXenoScreechShockWave").Instance().Duplicate();
}
private Vector2 _position;
private float _waveStrength;
private float _waveSpeed;
private float _downScale;
protected override bool BeforeDraw(in OverlayDrawArgs args)
{
if (args.Viewport.Eye == null || _xformSystem is null && !_entMan.TrySystem(out _xformSystem))
return false;
var query = _entMan.EntityQueryEnumerator<RMCXenoScreechShockWaveComponent, TransformComponent>();
if (query.MoveNext(out var uid, out var distortion, out var xform))
{
if (xform.MapID != args.MapId)
return false;
var mapPos = _xformSystem.GetWorldPosition(uid);
var tempCoords = args.Viewport.WorldToLocal(mapPos);
// normalized coords, 0 - 1 plane. This is pure hell, we subtract 1 because fragment calculates from the bottom and local goes from the top of the viewport
tempCoords.Y = 1 - (tempCoords.Y / args.Viewport.Size.Y);
tempCoords.X /= args.Viewport.Size.X;
_position = tempCoords;
_waveStrength = distortion.WaveStrength;
_waveSpeed = distortion.WaveSpeed;
_downScale = distortion.DownScale;
return true;
}
return false;
}
protected override void Draw(in OverlayDrawArgs args)
{
if (ScreenTexture == null || args.Viewport.Eye == null)
return;
_shader?.SetParameter("position", _position);
_shader?.SetParameter("waveSpeed", _waveSpeed);
_shader?.SetParameter("downScale", _downScale);
_shader?.SetParameter("waveStrength", _waveStrength);
_shader?.SetParameter("SCREEN_TEXTURE", ScreenTexture);
var worldHandle = args.WorldHandle;
worldHandle.UseShader(_shader);
worldHandle.DrawRect(args.WorldBounds, Color.White);
worldHandle.UseShader(null);
}
}

View File

@ -1,6 +1,7 @@
using Content.Shared._DV.Abilities;
using Content.Shared.Abilities.Psionics;
using Content.Shared.Actions;
using Content.Shared.Coordinates;
using Robust.Server.Audio;
namespace Content.Server._DV.Abilities;
@ -50,6 +51,9 @@ public sealed partial class PsychokineticScreamPowerSystem : EntitySystem
_audio.PlayPvs(entity.Comp.AbilitySound, entity);
_shatterLights.ShatterLightsAround(entity.Owner, entity.Comp.Radius, entity.Comp.LineOfSight);
SpawnAttachedTo(entity.Comp.Effect, entity.Owner.ToCoordinates());
args.Handled = true;
}

View File

@ -2,6 +2,7 @@ using Content.Server.Light.Components;
using Content.Server.Light.EntitySystems;
using Content.Shared._DV.Abilities;
using Content.Shared.Actions;
using Content.Shared.Coordinates;
using Content.Shared.Physics;
using Robust.Server.Audio;
using Robust.Shared.Map;
@ -52,6 +53,8 @@ public sealed partial class ShatterLightsAbilitySystem : EntitySystem
_audio.PlayPvs(entity.Comp.AbilitySound, entity);
ShatterLightsAround(entity.Owner, entity.Comp.Radius, entity.Comp.LineOfSight);
SpawnAttachedTo(entity.Comp.Effect, entity.Owner.ToCoordinates());
args.Handled = true;
}

View File

@ -0,0 +1,5 @@
using Content.Shared._RMC14.Effect;
namespace Content.Server._RMC14.Effect;
public sealed class RMCEffectSystem : SharedRMCEffectSystem;

View File

@ -37,6 +37,12 @@ public sealed partial class PsychokineticScreamPowerComponent : Component
/// </summary>
[DataField]
public SoundSpecifier AbilitySound = new SoundPathSpecifier("/Audio/_DV/Effects/creepyshriek.ogg");
/// <summary>
/// The effect to spawn when the ability is used.
/// </summary>
[DataField]
public EntProtoId Effect = "CMEffectScreech";
}
public sealed partial class ShatterLightsActionEvent : InstantActionEvent;

View File

@ -37,6 +37,12 @@ public sealed partial class ShatterLightsAbilityComponent : Component
/// </summary>
[DataField]
public SoundSpecifier AbilitySound = new SoundPathSpecifier("/Audio/_DV/Effects/creepyshriek.ogg");
/// <summary>
/// The effect to spawn when the ability is used.
/// </summary>
[DataField]
public EntProtoId Effect = "CMEffectScreech";
}
public sealed partial class ShatterLightsActionEvent : InstantActionEvent;

View File

@ -0,0 +1,14 @@
using Robust.Shared.GameStates;
namespace Content.Shared._RMC14.Effect;
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
[Access(typeof(SharedRMCEffectSystem))]
public sealed partial class EffectAlphaAnimationComponent : Component
{
[DataField, AutoNetworkedField]
public TimeSpan? SpawnedAt;
[DataField, AutoNetworkedField]
public TimeSpan Delay = TimeSpan.FromSeconds(1);
}

View File

@ -0,0 +1,9 @@
using Robust.Shared.GameStates;
namespace Content.Shared._RMC14.Effect;
[RegisterComponent, NetworkedComponent]
public sealed partial class RMCEffectComponent : Component
{
}

View File

@ -0,0 +1,19 @@
using Robust.Shared.Timing;
namespace Content.Shared._RMC14.Effect;
public abstract class SharedRMCEffectSystem : EntitySystem
{
[Dependency] private readonly IGameTiming _timing = default!;
public override void Initialize()
{
SubscribeLocalEvent<EffectAlphaAnimationComponent, MapInitEvent>(OnAlphaAnimationMapInit);
}
private void OnAlphaAnimationMapInit(Entity<EffectAlphaAnimationComponent> ent, ref MapInitEvent args)
{
ent.Comp.SpawnedAt = _timing.CurTime;
Dirty(ent);
}
}

View File

@ -0,0 +1,27 @@
using Robust.Shared.GameStates;
namespace Content.Shared._RMC14.Xenonids.Screech;
[RegisterComponent, NetworkedComponent]
[AutoGenerateComponentState]
public sealed partial class RMCXenoScreechShockWaveComponent : Component
{
/// <summary>
/// The speed of each individual wave from the center axis.
/// </summary>
[DataField, AutoNetworkedField, ViewVariables(VVAccess.ReadWrite)]
public float WaveSpeed = 15.3f;
/// <summary>
/// The size of each wave in its width and distortion effect
/// </summary>
[DataField, AutoNetworkedField, ViewVariables(VVAccess.ReadWrite)]
public float WaveStrength = 1.0f;
/// <summary>
/// The scale of the effect, lower number means a larger total area while smaller numbers downscale it and reduce the effected area.
/// </summary>
[DataField, AutoNetworkedField, ViewVariables(VVAccess.ReadWrite)]
public float DownScale = 1.5f;
}

View File

@ -12,3 +12,9 @@ uplink-hardsuit-syndieelite-desc-deltav = An alternate version of the blood-red
uplink-cwpgorlex-name = Gorlex Cold Weather Poncho
uplink-cwpgorlex-desc = A warm poncho for extreme weather. Made of cut-proof fabric, and protects against freezing weapons as well.
uplink-night-vision-goggles-name = Night Vision Goggles
uplink-night-vision-goggles-desc = High-tech goggles that allow you to see in the dark.
uplink-thermal-goggles-name = Thermal Goggles
uplink-thermal-goggles-desc = High-tech goggles that allow you to see heat signatures. These ones look like Night Vision Goggles to avoid detection.

View File

@ -228,7 +228,6 @@
- Equipment
- FauxTiles
- Botany # DeltaV
- SpecOpsGoogles # DeltaV
- Surgery # Shitmed change
- type: EmagLatheRecipes
emagDynamicPacks:
@ -443,7 +442,6 @@
- SecurityRubberAmmoStatic
- PrisonerSoftsuits
- EVASuit
- SpecOpsGoogles
# End DeltaV Additions
dynamicPacks:
- SalvageSecurityBoards
@ -453,6 +451,7 @@
- SecurityExplosives
- SecurityAmmo
- SecurityWeapons
- SpecOpsGoogles # DeltaV
#- SecurityDisablers # DeltaV - made roundstart
- type: MaterialStorage
whitelist:

View File

@ -57,7 +57,7 @@
jumpsuit: ClothingUniformJumpsuitOperative
back: ClothingBackpackDuffelSyndicate
mask: ClothingMaskGasSyndicate
eyes: ClothingEyesNightVisionGogglesNukie # Goobstation
eyes: ClothingEyesHudSyndicate
ears: ClothingHeadsetAltSyndicate
gloves: ClothingHandsGlovesCombat
outerClothing: ClothingOuterHardsuitSyndie
@ -115,7 +115,7 @@
parent: SyndicateOperativeGearFull
equipment:
pocket2: AgentUplinkRadio45TC # DeltaV - allows them to buy Agent armor
eyes: ClothingEyesNightVisionGogglesNukie # Goobstation
eyes: ClothingEyesHudSyndicateAgent
outerClothing: ClothingOuterCoatCybersunWindbreaker # DeltaV - removal of armor
# shoes: ClothingShoesBootsMagSyndie # DeltaV - removal of armor
id: SyndiAgentPDA

View File

@ -63,3 +63,25 @@
Telecrystal: 2
categories:
- UplinkWearables
- type: listing
id: UplinkNightVisionGoggles
name: uplink-night-vision-goggles-name
description: uplink-night-vision-goggles-desc
icon: { sprite: _White/Clothing/Eyes/Goggles/nightvision.rsi, state: icon }
productEntity: ClothingEyesNightVisionGoggles
cost:
Telecrystal: 3
categories:
- UplinkWearables
- type: listing
id: UplinkThermalGoggles
name: uplink-thermal-goggles-name
description: uplink-thermal-goggles-desc
icon: { sprite: _White/Clothing/Eyes/Goggles/thermal.rsi, state: icon }
productEntity: ClothingEyesThermalVisionGogglesSyndie
cost:
Telecrystal: 5
categories:
- UplinkWearables

View File

@ -20,6 +20,8 @@
cost: 400
- id: ClothingEyesGlassesGarMeson
cost: 500
- id: ClothingEyesNightVisionGoggles
cost: 2000
- id: ClothingBeltSalvageWebbing
cost: 500
- id: PlasteelArmingSword

View File

@ -16,6 +16,9 @@
Base: skia
Dead:
Base: dead
- type: SlowOnDamage
speedModifierThresholds:
100: 0.9
- type: MobState
allowedStates:
- Alive
@ -27,15 +30,17 @@
- type: Damageable
damageModifierSet: ManifestedSpirit
damageContainer: BiologicalMetaphysical
- type: Armor
modifiers:
coefficients:
Blunt: 0.4
Slash: 0.4
Piercing: 0.4
Heat: 0.8
Radiation: 0.2
Caustic: 0.2
- type: Fixtures
fixtures:
fix1:
shape:
!type:PhysShapeCircle
radius: 0.35
density: 160
mask:
- SmallMobMask
layer:
- SmallMobLayer
- type: MovementSpeedModifier
baseWalkSpeed: 2.25
baseSprintSpeed: 3.75

View File

@ -89,7 +89,6 @@
- EngineeringWeapons
- FauxTiles
- Equipment
- SpecOpsGoogles
- UpgradeKits
- UpgradeKits_Goob
- EngineeringHardsuits
@ -131,7 +130,6 @@
dynamicPacks:
- Equipment
- Mining
- SpecOpsGoogles
- SalvageWeapons
- SalvageHardsuits
- type: Machine
@ -218,7 +216,6 @@
- ScienceEquipment
- ScienceClothing
- ScienceWeapons
- SpecOpsGoogles
- Chemistry
- PowerCells
- type: Machine

View File

@ -12,4 +12,3 @@
id: SpecOpsGoogles
recipes:
- ClothingEyesNightVisionGoggles
- ClothingEyesGlassesThermal

View File

@ -0,0 +1,5 @@
- type: entity
id: RMCBaseEffect
abstract: true
components:
- type: RMCEffect

View File

@ -0,0 +1,18 @@
- type: entity
# Just fades out with no movement animation
parent: RMCBaseEffect
id: CMEffectScreech
categories: [ HideSpawnMenu ]
components:
- type: TimedDespawn
lifetime: 3.2
- type: RMCXenoScreechShockWave
- type: Sprite
sprite: _RMC14/Effects/xeno_screech.rsi
noRot: true
state: screech
drawdepth: Effects
- type: EffectVisuals
- type: Tag
tags:
- HideContextMenu

View File

@ -0,0 +1,4 @@
- type: shader
id: RMCXenoScreechShockWave
kind: source
path: "/Textures/_RMC14/Shaders/screech_shock_wave.swsl"

View File

@ -74,9 +74,9 @@
description: A high-tech pair of thermal goggles.
components:
- type: Sprite
sprite: _White/Clothing/Eyes/Goggles/sthermals.rsi
sprite: _White/Clothing/Eyes/Goggles/nightvision.rsi # Look like standard NVs to avoid gank.
- type: Clothing
sprite: _White/Clothing/Eyes/Goggles/sthermals.rsi
sprite: _White/Clothing/Eyes/Goggles/nightvision.rsi
- type: ThermalVision
flashDurationMultiplier: 2
isEquipment: true

View File

@ -23,17 +23,3 @@
- ClothingEyesNightVisionGoggles
technologyPrerequisites:
- MagnetsTech
- type: technology
id: ThermalVisionTech
name: research-technology-thermal-vision
icon:
sprite: _White/Clothing/Eyes/Goggles/thermal.rsi
state: icon
discipline: Experimental
tier: 2
cost: 10000
recipeUnlocks:
- ClothingEyesGlassesThermal
technologyPrerequisites:
- MagnetsTech

View File

@ -0,0 +1,26 @@
{
"version": 1,
"license": "CC-BY-SA-3.0",
"copyright": "Taken from cmss13 at https://github.com/cmss13-devs/cmss13/blob/d5b119380250ea512db2a5319e36592c7f604250/icons/effects/xeno_screech.dmi",
"size": {
"x": 64,
"y": 64
},
"states": [
{
"name": "screech",
"delays": [
[
0.2,
0.2,
0.2,
0.2,
0.2,
0.2,
0.2,
0.2
]
]
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -0,0 +1,28 @@
uniform sampler2D SCREEN_TEXTURE;
uniform highp float waveStrength;
uniform highp vec2 position;
uniform highp float waveSpeed;
uniform highp float downScale;
void fragment()
{
highp vec2 st = UV;
highp vec2 WaveCentre = position;
highp float ratio = SCREEN_PIXEL_SIZE.y / SCREEN_PIXEL_SIZE.x * 0.5;
WaveCentre.y *= ratio;
highp float dist = distance(vec2(st.x, st.y * ratio), WaveCentre) * downScale;
highp float val = dist;
highp float a = 3.0;
highp float cosFuns = cos(val * 20.0 - TIME * waveSpeed);
highp float powFuns = pow(val * 2.5, a);
highp float limtedPowFuns = 0.5 * pow(a / (a + powFuns), 2.0);
highp float finalRes = smoothstep(0.0, 1.0, limtedPowFuns * cosFuns) * waveStrength;
highp vec3 col = finalRes * vec3(1.0);
st = st * 2.0 - 1.0;
st *= 1.0 + finalRes * 0.1;
st = st * 0.5 + 0.5;
highp vec4 texCol = zTextureSpec(SCREEN_TEXTURE, st);
texCol += (texCol * finalRes) / (dist * 10.0);
COLOR = texCol;
}