This repository has been archived by the owner on Nov 1, 2024. It is now read-only.
forked from new-frontiers-14/frontier-station-14
-
Notifications
You must be signed in to change notification settings - Fork 38
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'new-frontiers-14:master' into master
- Loading branch information
Showing
821 changed files
with
71,246 additions
and
33,863 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
namespace Content.Client.DeltaV.Harpy; | ||
|
||
[RegisterComponent] | ||
public sealed partial class HarpyVisualsComponent : Component | ||
{ } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
using Robust.Client.Graphics; | ||
using Robust.Client.Player; | ||
using Robust.Shared.Enums; | ||
using Robust.Shared.Prototypes; | ||
using Content.Shared.DeltaV.Abilities; | ||
|
||
namespace Content.Client.DeltaV.Overlays; | ||
|
||
public sealed partial class UltraVisionOverlay : Overlay | ||
{ | ||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!; | ||
[Dependency] private readonly IPlayerManager _playerManager = default!; | ||
[Dependency] IEntityManager _entityManager = default!; | ||
|
||
|
||
public override bool RequestScreenTexture => true; | ||
public override OverlaySpace Space => OverlaySpace.WorldSpace; | ||
private readonly ShaderInstance _ultraVisionShader; | ||
|
||
public UltraVisionOverlay() | ||
{ | ||
IoCManager.InjectDependencies(this); | ||
_ultraVisionShader = _prototypeManager.Index<ShaderPrototype>("UltraVision").Instance().Duplicate(); | ||
} | ||
|
||
protected override void Draw(in OverlayDrawArgs args) | ||
{ | ||
if (ScreenTexture == null) | ||
return; | ||
if (_playerManager.LocalPlayer?.ControlledEntity is not {Valid: true} player) | ||
return; | ||
if (!_entityManager.HasComponent<UltraVisionComponent>(player)) | ||
return; | ||
|
||
_ultraVisionShader?.SetParameter("SCREEN_TEXTURE", ScreenTexture); | ||
|
||
|
||
var worldHandle = args.WorldHandle; | ||
var viewport = args.WorldBounds; | ||
worldHandle.SetTransform(Matrix3.Identity); | ||
worldHandle.UseShader(_ultraVisionShader); | ||
worldHandle.DrawRect(viewport, Color.White); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
using Content.Shared.DeltaV.Abilities; | ||
using Robust.Client.Graphics; | ||
|
||
namespace Content.Client.DeltaV.Overlays; | ||
|
||
public sealed partial class UltraVisionSystem : EntitySystem | ||
{ | ||
[Dependency] private readonly IOverlayManager _overlayMan = default!; | ||
|
||
private UltraVisionOverlay _overlay = default!; | ||
|
||
public override void Initialize() | ||
{ | ||
base.Initialize(); | ||
|
||
SubscribeLocalEvent<UltraVisionComponent, ComponentInit>(OnUltraVisionInit); | ||
SubscribeLocalEvent<UltraVisionComponent, ComponentShutdown>(OnUltraVisionShutdown); | ||
|
||
_overlay = new(); | ||
} | ||
|
||
private void OnUltraVisionInit(EntityUid uid, UltraVisionComponent component, ComponentInit args) | ||
{ | ||
_overlayMan.AddOverlay(_overlay); | ||
} | ||
|
||
private void OnUltraVisionShutdown(EntityUid uid, UltraVisionComponent component, ComponentShutdown args) | ||
{ | ||
_overlayMan.RemoveOverlay(_overlay); | ||
} | ||
} |
36 changes: 36 additions & 0 deletions
36
Content.Server/Chemistry/ReagentEffects/DisintegrateArtifact.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
using Content.Server.Xenoarchaeology.XenoArtifacts; | ||
using Content.Shared.Chemistry.Reagent; | ||
using Robust.Shared.Prototypes; | ||
|
||
namespace Content.Server.Chemistry.ReagentEffects; | ||
|
||
public sealed partial class DisintegrateArtifact : ReagentEffect | ||
{ | ||
|
||
/// <summary> | ||
/// Disintegrate chance | ||
/// </summary> | ||
[DataField("probabilityMin"), ViewVariables(VVAccess.ReadWrite)] | ||
public float ProbabilityMax = 0.05f; | ||
|
||
/// <summary> | ||
/// Disintegrate chance | ||
/// </summary> | ||
[DataField("probabilityMax"), ViewVariables(VVAccess.ReadWrite)] | ||
public float ProbabilityMin = 0.15f; | ||
|
||
/// <summary> | ||
/// The range around the artifact that it will spawn the entity | ||
/// </summary> | ||
[DataField("range")] | ||
public float Range = 0.5f; | ||
|
||
public override void Effect(ReagentEffectArgs args) | ||
{ | ||
var artifact = args.EntityManager.EntitySysManager.GetEntitySystem<ArtifactSystem>(); | ||
artifact.DisintegrateArtifact(args.SolutionEntity, ProbabilityMin, ProbabilityMax, Range); | ||
} | ||
|
||
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) => | ||
null; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,180 @@ | ||
using Content.Server.Instruments; | ||
using Content.Server.Speech.Components; | ||
using Content.Server.UserInterface; | ||
using Content.Shared.Instruments; | ||
using Content.Shared.ActionBlocker; | ||
using Content.Shared.Damage; | ||
using Content.Shared.Damage.ForceSay; | ||
using Content.Shared.DeltaV.Harpy; | ||
using Content.Shared.FixedPoint; | ||
using Content.Shared.Inventory; | ||
using Content.Shared.Inventory.Events; | ||
using Content.Shared.Mobs; | ||
using Content.Shared.Popups; | ||
using Content.Shared.StatusEffect; | ||
using Content.Shared.Stunnable; | ||
using Content.Shared.UserInterface; | ||
using Content.Shared.Zombies; | ||
using Robust.Shared.Player; | ||
using Robust.Shared.Prototypes; | ||
using Content.Shared.DeltaV.Harpy.Components; | ||
|
||
namespace Content.Server.DeltaV.Harpy | ||
{ | ||
public sealed class HarpySingerSystem : EntitySystem | ||
{ | ||
[Dependency] private readonly InstrumentSystem _instrument = default!; | ||
[Dependency] private readonly SharedPopupSystem _popupSystem = default!; | ||
[Dependency] private readonly InventorySystem _inventorySystem = default!; | ||
[Dependency] private readonly ActionBlockerSystem _blocker = default!; | ||
[Dependency] private readonly IPrototypeManager _prototype = default!; | ||
[Dependency] private readonly SharedAppearanceSystem _appearance = default!; | ||
|
||
public override void Initialize() | ||
{ | ||
base.Initialize(); | ||
|
||
SubscribeLocalEvent<InstrumentComponent, MobStateChangedEvent>(OnMobStateChangedEvent); | ||
SubscribeLocalEvent<GotEquippedEvent>(OnEquip); | ||
SubscribeLocalEvent<EntityZombifiedEvent>(OnZombified); | ||
SubscribeLocalEvent<InstrumentComponent, KnockedDownEvent>(OnKnockedDown); | ||
SubscribeLocalEvent<InstrumentComponent, StunnedEvent>(OnStunned); | ||
SubscribeLocalEvent<InstrumentComponent, SleepStateChangedEvent>(OnSleep); | ||
SubscribeLocalEvent<InstrumentComponent, StatusEffectAddedEvent>(OnStatusEffect); | ||
SubscribeLocalEvent<InstrumentComponent, DamageChangedEvent>(OnDamageChanged); | ||
SubscribeLocalEvent<HarpySingerComponent, BoundUIClosedEvent>(OnBoundUIClosed); | ||
SubscribeLocalEvent<HarpySingerComponent, BoundUIOpenedEvent>(OnBoundUIOpened); | ||
|
||
// This is intended to intercept the UI event and stop the MIDI UI from opening if the | ||
// singer is unable to sing. Thus it needs to run before the ActivatableUISystem. | ||
SubscribeLocalEvent<HarpySingerComponent, OpenUiActionEvent>(OnInstrumentOpen, before: new[] { typeof(ActivatableUISystem) }); | ||
} | ||
|
||
private void OnEquip(GotEquippedEvent args) | ||
{ | ||
// Check if an item that makes the singer mumble is equipped to their face | ||
// (not their pockets!). As of writing, this should just be the muzzle. | ||
if (TryComp<AddAccentClothingComponent>(args.Equipment, out var accent) && | ||
accent.ReplacementPrototype == "mumble" && | ||
args.Slot == "mask") | ||
{ | ||
CloseMidiUi(args.Equipee); | ||
} | ||
} | ||
|
||
private void OnMobStateChangedEvent(EntityUid uid, InstrumentComponent component, MobStateChangedEvent args) | ||
{ | ||
if (args.NewMobState is MobState.Critical or MobState.Dead) | ||
CloseMidiUi(args.Target); | ||
} | ||
|
||
private void OnZombified(ref EntityZombifiedEvent args) | ||
{ | ||
CloseMidiUi(args.Target); | ||
} | ||
|
||
private void OnKnockedDown(EntityUid uid, InstrumentComponent component, ref KnockedDownEvent args) | ||
{ | ||
CloseMidiUi(uid); | ||
} | ||
|
||
private void OnStunned(EntityUid uid, InstrumentComponent component, ref StunnedEvent args) | ||
{ | ||
CloseMidiUi(uid); | ||
} | ||
|
||
private void OnSleep(EntityUid uid, InstrumentComponent component, ref SleepStateChangedEvent args) | ||
{ | ||
if (args.FellAsleep) | ||
CloseMidiUi(uid); | ||
} | ||
|
||
private void OnStatusEffect(EntityUid uid, InstrumentComponent component, StatusEffectAddedEvent args) | ||
{ | ||
if (args.Key == "Muted") | ||
CloseMidiUi(uid); | ||
} | ||
|
||
/// <summary> | ||
/// Almost a copy of Content.Server.Damage.ForceSay.DamageForceSaySystem.OnDamageChanged. | ||
/// Done so because DamageForceSaySystem doesn't output an event, and my understanding is | ||
/// that we don't want to change upstream code more than necessary to avoid merge conflicts | ||
/// and maintenance overhead. It still reuses the values from DamageForceSayComponent, so | ||
/// any tweaks to that will keep ForceSay consistent with singing interruptions. | ||
/// </summary> | ||
private void OnDamageChanged(EntityUid uid, InstrumentComponent instrumentComponent, DamageChangedEvent args) | ||
{ | ||
if (!TryComp<DamageForceSayComponent>(uid, out var component) || | ||
args.DamageDelta == null || | ||
!args.DamageIncreased || | ||
args.DamageDelta.GetTotal() < component.DamageThreshold || | ||
component.ValidDamageGroups == null) | ||
return; | ||
|
||
var totalApplicableDamage = FixedPoint2.Zero; | ||
foreach (var (group, value) in args.DamageDelta.GetDamagePerGroup(_prototype)) | ||
{ | ||
if (!component.ValidDamageGroups.Contains(group)) | ||
continue; | ||
|
||
totalApplicableDamage += value; | ||
} | ||
|
||
if (totalApplicableDamage >= component.DamageThreshold) | ||
CloseMidiUi(uid); | ||
} | ||
|
||
/// <summary> | ||
/// Closes the MIDI UI if it is open. | ||
/// </summary> | ||
private void CloseMidiUi(EntityUid uid) | ||
{ | ||
if (HasComp<ActiveInstrumentComponent>(uid) && | ||
TryComp<ActorComponent>(uid, out var actor)) | ||
{ | ||
_instrument.ToggleInstrumentUi(uid, actor.PlayerSession); | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// Prevent the player from opening the MIDI UI under some circumstances. | ||
/// </summary> | ||
private void OnInstrumentOpen(EntityUid uid, HarpySingerComponent component, OpenUiActionEvent args) | ||
{ | ||
// CanSpeak covers all reasons you can't talk, including being incapacitated | ||
// (crit/dead), asleep, or for any reason mute inclding glimmer or a mime's vow. | ||
var canNotSpeak = !_blocker.CanSpeak(uid); | ||
var zombified = TryComp<ZombieComponent>(uid, out var _); | ||
var muzzled = _inventorySystem.TryGetSlotEntity(uid, "mask", out var maskUid) && | ||
TryComp<AddAccentClothingComponent>(maskUid, out var accent) && | ||
accent.ReplacementPrototype == "mumble"; | ||
|
||
// Set this event as handled when the singer should be incapable of singing in order | ||
// to stop the ActivatableUISystem event from opening the MIDI UI. | ||
args.Handled = canNotSpeak || muzzled || zombified; | ||
|
||
// Tell the user that they can not sing. | ||
if (args.Handled) | ||
_popupSystem.PopupEntity(Loc.GetString("no-sing-while-no-speak"), uid, uid, PopupType.Medium); | ||
} | ||
|
||
private void OnBoundUIClosed(EntityUid uid, HarpySingerComponent component, BoundUIClosedEvent args) | ||
{ | ||
if (args.UiKey is not InstrumentUiKey) | ||
return; | ||
|
||
TryComp(uid, out AppearanceComponent? appearance); | ||
_appearance.SetData(uid, HarpyVisualLayers.Singing, SingingVisualLayer.False, appearance); | ||
} | ||
|
||
private void OnBoundUIOpened(EntityUid uid, HarpySingerComponent component, BoundUIOpenedEvent args) | ||
{ | ||
if (args.UiKey is not InstrumentUiKey) | ||
return; | ||
|
||
TryComp(uid, out AppearanceComponent? appearance); | ||
_appearance.SetData(uid, HarpyVisualLayers.Singing, SingingVisualLayer.True, appearance); | ||
|
||
} | ||
} | ||
} |
Oops, something went wrong.