Merge remote-tracking branch 'upstream/master' into ups
This commit is contained in:
@@ -30,7 +30,7 @@ public sealed partial class IdCardConsoleComponent : Component
|
||||
public readonly List<ProtoId<AccessLevelPrototype>> AccessList;
|
||||
public readonly ProtoId<AccessLevelPrototype> JobPrototype;
|
||||
public readonly string? SelectedIcon; //WD-EDIT
|
||||
|
||||
|
||||
public WriteToTargetIdMessage(string fullName, string jobTitle, List<ProtoId<AccessLevelPrototype>> accessList, ProtoId<AccessLevelPrototype> jobPrototype,
|
||||
string? selectedIcon)
|
||||
{
|
||||
@@ -79,63 +79,35 @@ public sealed partial class IdCardConsoleComponent : Component
|
||||
"Theatre"
|
||||
};
|
||||
|
||||
//WD-EDIT
|
||||
[DataField("jobIcons")]
|
||||
public List<string> JobIcons = new()
|
||||
// WD edit
|
||||
[DataField, AutoNetworkedField]
|
||||
public List<List<ProtoId<AccessLevelPrototype>>> AccessLevelsConsole = new()
|
||||
{
|
||||
"AtmosphericTechnician",
|
||||
"Bartender",
|
||||
"Borg",
|
||||
"Botanist",
|
||||
"Boxer",
|
||||
"Brigmedic",
|
||||
"Captain",
|
||||
"CargoTechnician",
|
||||
"Chaplain",
|
||||
"Chef",
|
||||
"Chemist",
|
||||
"ChiefEngineer",
|
||||
"ChiefMedicalOfficer",
|
||||
"Clown",
|
||||
"CustomId",
|
||||
"Detective",
|
||||
"Geneticist",
|
||||
"HeadOfPersonnel",
|
||||
"HeadOfSecurity",
|
||||
"Inspector",
|
||||
"Janitor",
|
||||
"Lawyer",
|
||||
"Librarian",
|
||||
"MedicalDoctor",
|
||||
"MedicalIntern",
|
||||
"Mime",
|
||||
"Musician",
|
||||
"Paramedic",
|
||||
"Passenger",
|
||||
"Psychologist",
|
||||
"QuarterMaster",
|
||||
"Reporter",
|
||||
"ResearchAssistant",
|
||||
"ResearchDirector",
|
||||
"Roboticist",
|
||||
"Scientist",
|
||||
"SecurityCadet",
|
||||
"SecurityOfficer",
|
||||
"SeniorEngineer",
|
||||
"SeniorOfficer",
|
||||
"SeniorPhysician",
|
||||
"SeniorResearcher",
|
||||
"ServiceWorker",
|
||||
"ShaftMiner",
|
||||
"StationEngineer",
|
||||
"TechnicalAssistant",
|
||||
"Virologist",
|
||||
"Visitor",
|
||||
"Warden",
|
||||
"Zookeeper"
|
||||
new List<ProtoId<AccessLevelPrototype>> {"Captain", "HeadOfPersonnel", "HeadOfSecurity", "ChiefMedicalOfficer", "ChiefEngineer", "ResearchDirector", "Quartermaster", "Command"}, // Command
|
||||
new List<ProtoId<AccessLevelPrototype>> {"Armory", "Brig", "Security","Detective", "Lawyer"}, // Security
|
||||
new List<ProtoId<AccessLevelPrototype>> {"Chemistry", "Cryogenics", "Medical"}, // Medical
|
||||
new List<ProtoId<AccessLevelPrototype>> {"Atmospherics", "Engineering", "External", "Maintenance"}, // Engineering
|
||||
new List<ProtoId<AccessLevelPrototype>> {"Research"}, // Researching
|
||||
new List<ProtoId<AccessLevelPrototype>> {"Cargo", "Salvage"}, // Cargo
|
||||
new List<ProtoId<AccessLevelPrototype>> { "Service", "Theatre", "Bar", "Chapel", "Hydroponics", "Janitor", "Kitchen"} // Service
|
||||
};
|
||||
|
||||
//WD-EDIT
|
||||
// Command, Service, Security, Medical, Engineering, Researching, Cargo,
|
||||
[DataField("jobIcons")]
|
||||
public List<List<string>> JobIcons = new()
|
||||
{
|
||||
new List<string> {"Captain", "HeadOfPersonnel", "HeadOfSecurity", "ChiefMedicalOfficer", "ChiefEngineer", "ResearchDirector", "QuarterMaster", "Inspector"},
|
||||
new List<string> {"HeadOfPersonnel", "Lawyer", "Clown", "Bartender", "Reporter", "Chef", "Botanist", "ServiceWorker", "Zookeeper", "Musician", "Librarian", "Janitor", "Chaplain", "Mime", "Boxer", "Passenger", "Visitor", "Borg", "CustomId"},
|
||||
new List<string> {"HeadOfSecurity", "Warden", "SeniorOfficer", "SecurityOfficer", "Detective", "SecurityCadet", "Brigmedic", "Lawyer"},
|
||||
new List<string> {"ChiefMedicalOfficer", "SeniorPhysician", "Paramedic", "Chemist", "MedicalDoctor", "Virologist", "Geneticist", "MedicalIntern", "Psychologist"},
|
||||
new List<string> {"ChiefEngineer", "SeniorEngineer", "AtmosphericTechnician", "StationEngineer", "TechnicalAssistant"},
|
||||
new List<string> {"ResearchDirector", "SeniorResearcher", "Scientist", "Roboticist", "ResearchAssistant"},
|
||||
new List<string> {"QuarterMaster", "ShaftMiner", "CargoTechnician"},
|
||||
};
|
||||
// WD EDIT END
|
||||
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class IdCardConsoleBoundUserInterfaceState : BoundUserInterfaceState
|
||||
{
|
||||
@@ -150,7 +122,7 @@ public sealed partial class IdCardConsoleComponent : Component
|
||||
public readonly List<ProtoId<AccessLevelPrototype>>? AllowedModifyAccessList;
|
||||
public readonly ProtoId<AccessLevelPrototype> TargetIdJobPrototype;
|
||||
public readonly string? TargetIdJobIcon; //WD-EDIT
|
||||
|
||||
|
||||
public IdCardConsoleBoundUserInterfaceState(
|
||||
bool isPrivilegedIdPresent,
|
||||
bool isPrivilegedIdAuthorized,
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
using Robust.Shared.GameStates;
|
||||
|
||||
namespace Content.Shared.Clothing.Components;
|
||||
|
||||
/// <summary>
|
||||
/// Disables client-side physics prediction for this entity.
|
||||
/// Without this, movement with <see cref="PilotedClothingSystem"/> is very rubberbandy.
|
||||
/// </summary>
|
||||
[RegisterComponent, NetworkedComponent]
|
||||
public sealed partial class PilotedByClothingComponent : Component
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
using Content.Shared.Whitelist;
|
||||
using Robust.Shared.GameStates;
|
||||
|
||||
namespace Content.Shared.Clothing.Components;
|
||||
|
||||
/// <summary>
|
||||
/// Allows an entity stored in this clothing item to pass inputs to the entity wearing it.
|
||||
/// </summary>
|
||||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
|
||||
public sealed partial class PilotedClothingComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// Whitelist for entities that are allowed to act as pilots when inside this entity.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public EntityWhitelist? PilotWhitelist;
|
||||
|
||||
/// <summary>
|
||||
/// Should movement input be relayed from the pilot to the target?
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public bool RelayMovement = true;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Reference to the entity contained in the clothing and acting as pilot.
|
||||
/// </summary>
|
||||
[DataField, AutoNetworkedField]
|
||||
public EntityUid? Pilot;
|
||||
|
||||
/// <summary>
|
||||
/// Reference to the entity wearing this clothing who will be controlled by the pilot.
|
||||
/// </summary>
|
||||
[DataField, AutoNetworkedField]
|
||||
public EntityUid? Wearer;
|
||||
|
||||
public bool IsActive => Pilot != null && Wearer != null;
|
||||
}
|
||||
168
Content.Shared/Clothing/EntitySystems/PilotedClothingSystem.cs
Normal file
168
Content.Shared/Clothing/EntitySystems/PilotedClothingSystem.cs
Normal file
@@ -0,0 +1,168 @@
|
||||
using Content.Shared.Clothing.Components;
|
||||
using Content.Shared.Inventory.Events;
|
||||
using Content.Shared.Movement.Components;
|
||||
using Content.Shared.Movement.Systems;
|
||||
using Content.Shared.Storage;
|
||||
using Content.Shared.Whitelist;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Shared.Clothing.EntitySystems;
|
||||
|
||||
public sealed partial class PilotedClothingSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IGameTiming _timing = default!;
|
||||
[Dependency] private readonly SharedMoverController _moverController = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<PilotedClothingComponent, EntInsertedIntoContainerMessage>(OnEntInserted);
|
||||
SubscribeLocalEvent<PilotedClothingComponent, EntRemovedFromContainerMessage>(OnEntRemoved);
|
||||
SubscribeLocalEvent<PilotedClothingComponent, GotEquippedEvent>(OnEquipped);
|
||||
SubscribeLocalEvent<PilotedClothingComponent, GotUnequippedEvent>(OnUnequipped);
|
||||
}
|
||||
|
||||
private void OnEntInserted(Entity<PilotedClothingComponent> entity, ref EntInsertedIntoContainerMessage args)
|
||||
{
|
||||
// Make sure the entity was actually inserted into storage and not a different container.
|
||||
if (!TryComp(entity, out StorageComponent? storage) || args.Container != storage.Container)
|
||||
return;
|
||||
|
||||
// Check potential pilot against whitelist, if one exists.
|
||||
if (entity.Comp.PilotWhitelist?.IsValid(args.Entity, EntityManager) is false)
|
||||
return;
|
||||
|
||||
entity.Comp.Pilot = args.Entity;
|
||||
Dirty(entity);
|
||||
|
||||
// Attempt to setup control link, if Pilot and Wearer are both present.
|
||||
StartPiloting(entity);
|
||||
}
|
||||
|
||||
private void OnEntRemoved(Entity<PilotedClothingComponent> entity, ref EntRemovedFromContainerMessage args)
|
||||
{
|
||||
// Make sure the removed entity is actually the pilot.
|
||||
if (args.Entity != entity.Comp.Pilot)
|
||||
return;
|
||||
|
||||
StopPiloting(entity);
|
||||
entity.Comp.Pilot = null;
|
||||
Dirty(entity);
|
||||
}
|
||||
|
||||
private void OnEquipped(Entity<PilotedClothingComponent> entity, ref GotEquippedEvent args)
|
||||
{
|
||||
if (!TryComp(entity, out ClothingComponent? clothing))
|
||||
return;
|
||||
|
||||
// Make sure the clothing item was equipped to the right slot, and not just held in a hand.
|
||||
var isCorrectSlot = (clothing.Slots & args.SlotFlags) != Inventory.SlotFlags.NONE;
|
||||
if (!isCorrectSlot)
|
||||
return;
|
||||
|
||||
entity.Comp.Wearer = args.Equipee;
|
||||
Dirty(entity);
|
||||
|
||||
// Attempt to setup control link, if Pilot and Wearer are both present.
|
||||
StartPiloting(entity);
|
||||
}
|
||||
|
||||
private void OnUnequipped(Entity<PilotedClothingComponent> entity, ref GotUnequippedEvent args)
|
||||
{
|
||||
StopPiloting(entity);
|
||||
|
||||
entity.Comp.Wearer = null;
|
||||
Dirty(entity);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to establish movement/interaction relay connection(s) from Pilot to Wearer.
|
||||
/// If either is missing, fails and returns false.
|
||||
/// </summary>
|
||||
private bool StartPiloting(Entity<PilotedClothingComponent> entity)
|
||||
{
|
||||
// Make sure we have both a Pilot and a Wearer
|
||||
if (entity.Comp.Pilot == null || entity.Comp.Wearer == null)
|
||||
return false;
|
||||
|
||||
if (!_timing.IsFirstTimePredicted)
|
||||
return false;
|
||||
|
||||
var pilotEnt = entity.Comp.Pilot.Value;
|
||||
var wearerEnt = entity.Comp.Wearer.Value;
|
||||
|
||||
// Add component to block prediction of wearer
|
||||
EnsureComp<PilotedByClothingComponent>(wearerEnt);
|
||||
|
||||
if (entity.Comp.RelayMovement)
|
||||
{
|
||||
// Establish movement input relay.
|
||||
_moverController.SetRelay(pilotEnt, wearerEnt);
|
||||
}
|
||||
|
||||
var pilotEv = new StartedPilotingClothingEvent(entity, wearerEnt);
|
||||
RaiseLocalEvent(pilotEnt, ref pilotEv);
|
||||
|
||||
var wearerEv = new StartingBeingPilotedByClothing(entity, pilotEnt);
|
||||
RaiseLocalEvent(wearerEnt, ref wearerEv);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes components from the Pilot and Wearer to stop the control relay.
|
||||
/// Returns false if a connection does not already exist.
|
||||
/// </summary>
|
||||
private bool StopPiloting(Entity<PilotedClothingComponent> entity)
|
||||
{
|
||||
if (entity.Comp.Pilot == null || entity.Comp.Wearer == null)
|
||||
return false;
|
||||
|
||||
// Clean up components on the Pilot
|
||||
var pilotEnt = entity.Comp.Pilot.Value;
|
||||
RemCompDeferred<RelayInputMoverComponent>(pilotEnt);
|
||||
|
||||
// Clean up components on the Wearer
|
||||
var wearerEnt = entity.Comp.Wearer.Value;
|
||||
RemCompDeferred<MovementRelayTargetComponent>(wearerEnt);
|
||||
RemCompDeferred<PilotedByClothingComponent>(wearerEnt);
|
||||
|
||||
// Raise an event on the Pilot
|
||||
var pilotEv = new StoppedPilotingClothingEvent(entity, wearerEnt);
|
||||
RaiseLocalEvent(pilotEnt, ref pilotEv);
|
||||
|
||||
// Raise an event on the Wearer
|
||||
var wearerEv = new StoppedBeingPilotedByClothing(entity, pilotEnt);
|
||||
RaiseLocalEvent(wearerEnt, ref wearerEv);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raised on the Pilot when they gain control of the Wearer.
|
||||
/// </summary>
|
||||
[ByRefEvent]
|
||||
public record struct StartedPilotingClothingEvent(EntityUid Clothing, EntityUid Wearer);
|
||||
|
||||
/// <summary>
|
||||
/// Raised on the Pilot when they lose control of the Wearer,
|
||||
/// due to the Pilot exiting the clothing or the clothing being unequipped by the Wearer.
|
||||
/// </summary>
|
||||
[ByRefEvent]
|
||||
public record struct StoppedPilotingClothingEvent(EntityUid Clothing, EntityUid Wearer);
|
||||
|
||||
/// <summary>
|
||||
/// Raised on the Wearer when the Pilot gains control of them.
|
||||
/// </summary>
|
||||
[ByRefEvent]
|
||||
public record struct StartingBeingPilotedByClothing(EntityUid Clothing, EntityUid Pilot);
|
||||
|
||||
/// <summary>
|
||||
/// Raised on the Wearer when the Pilot loses control of them
|
||||
/// due to the Pilot exiting the clothing or the clothing being unequipped by the Wearer.
|
||||
/// </summary>
|
||||
[ByRefEvent]
|
||||
public record struct StoppedBeingPilotedByClothing(EntityUid Clothing, EntityUid Pilot);
|
||||
@@ -1,3 +1,4 @@
|
||||
using Content.Shared._White.Lighting;
|
||||
using Content.Shared.Doors.Components;
|
||||
using Content.Shared.Popups;
|
||||
using Content.Shared.Prying.Components;
|
||||
@@ -120,6 +121,7 @@ public abstract class SharedAirlockSystem : EntitySystem
|
||||
|
||||
public void UpdateEmergencyLightStatus(EntityUid uid, AirlockComponent component)
|
||||
{
|
||||
RaiseLocalEvent(uid, new DoorlightsChangedEvent(DoorVisuals.EmergencyLights, component.EmergencyAccess));
|
||||
Appearance.SetData(uid, DoorVisuals.EmergencyLights, component.EmergencyAccess);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using Content.Shared._White.Lighting;
|
||||
using Content.Shared.Doors.Components;
|
||||
using Content.Shared.Prying.Components;
|
||||
|
||||
@@ -55,7 +56,8 @@ public abstract partial class SharedDoorSystem
|
||||
|
||||
public void UpdateBoltLightStatus(Entity<DoorBoltComponent> ent)
|
||||
{
|
||||
AppearanceSystem.SetData(ent, DoorVisuals.BoltLights, GetBoltLightsVisible(ent));
|
||||
var value = GetBoltLightsVisible(ent);
|
||||
AppearanceSystem.SetData(ent, DoorVisuals.BoltLights, value);
|
||||
}
|
||||
|
||||
public bool GetBoltLightsVisible(Entity<DoorBoltComponent> ent)
|
||||
@@ -84,6 +86,8 @@ public abstract partial class SharedDoorSystem
|
||||
Dirty(ent, ent.Comp);
|
||||
UpdateBoltLightStatus(ent);
|
||||
|
||||
RaiseLocalEvent(ent, new DoorlightsChangedEvent(DoorVisuals.BoltLights, value), true);
|
||||
|
||||
var sound = value ? ent.Comp.BoltDownSound : ent.Comp.BoltUpSound;
|
||||
if (predicted)
|
||||
Audio.PlayPredicted(sound, ent, user: user);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Linq;
|
||||
using Content.Shared._White.Cult.Structures;
|
||||
using Content.Shared._White.Keyhole.Components;
|
||||
using Content.Shared._White.Lighting;
|
||||
using Content.Shared.Access.Components;
|
||||
using Content.Shared.Access.Systems;
|
||||
using Content.Shared.Administration.Logs;
|
||||
@@ -116,6 +117,8 @@ public abstract partial class SharedDoorSystem : EntitySystem
|
||||
|| door.State == DoorState.Opening && !door.Partial;
|
||||
|
||||
SetCollidable(ent, collidable, door);
|
||||
|
||||
RaiseLocalEvent(ent, new DoorlightsChangedEvent(door.State, true), true);
|
||||
AppearanceSystem.SetData(ent, DoorVisuals.State, door.State);
|
||||
}
|
||||
|
||||
@@ -164,6 +167,8 @@ public abstract partial class SharedDoorSystem : EntitySystem
|
||||
_activeDoors.Add(ent);
|
||||
|
||||
RaiseLocalEvent(ent, new DoorStateChangedEvent(door.State));
|
||||
RaiseLocalEvent(ent, new DoorlightsChangedEvent(door.State, true), true);
|
||||
|
||||
AppearanceSystem.SetData(ent, DoorVisuals.State, door.State);
|
||||
}
|
||||
|
||||
@@ -212,7 +217,10 @@ public abstract partial class SharedDoorSystem : EntitySystem
|
||||
|
||||
door.State = state;
|
||||
Dirty(uid, door);
|
||||
|
||||
RaiseLocalEvent(uid, new DoorStateChangedEvent(state));
|
||||
RaiseLocalEvent(uid, new DoorlightsChangedEvent(door.State, true), true);
|
||||
|
||||
AppearanceSystem.SetData(uid, DoorVisuals.State, door.State);
|
||||
return true;
|
||||
}
|
||||
@@ -516,6 +524,8 @@ public abstract partial class SharedDoorSystem : EntitySystem
|
||||
{
|
||||
door.NextStateChange = GameTiming.CurTime + door.OpenTimeTwo;
|
||||
door.State = DoorState.Opening;
|
||||
|
||||
RaiseLocalEvent(uid, new DoorlightsChangedEvent(door.State, true), true);
|
||||
AppearanceSystem.SetData(uid, DoorVisuals.State, DoorState.Opening);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Content.Shared.DoAfter;
|
||||
using Content.Shared.DoAfter;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Prototypes;
|
||||
@@ -20,6 +20,12 @@ public sealed partial class HandTeleporterComponent : Component
|
||||
[ViewVariables, DataField("secondPortal")]
|
||||
public EntityUid? SecondPortal = null;
|
||||
|
||||
/// <summary>
|
||||
/// Portals can't be placed on different grids?
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public bool AllowPortalsOnDifferentGrids;
|
||||
|
||||
[DataField("firstPortalPrototype", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||
public string FirstPortalPrototype = "PortalRed";
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Linq;
|
||||
using Content.Shared._White.Wizard.Timestop;
|
||||
using Content.Shared.Administration.Logs;
|
||||
using Content.Shared.Database;
|
||||
using Content.Shared.Gravity;
|
||||
@@ -25,6 +26,7 @@ namespace Content.Shared.Throwing
|
||||
[Dependency] private readonly SharedGravitySystem _gravity = default!;
|
||||
|
||||
private const string ThrowingFixture = "throw-fixture";
|
||||
private readonly HashSet<(EntityUid, EntityUid)> _processed = new (); // WD edit
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -65,7 +67,14 @@ namespace Content.Shared.Throwing
|
||||
if (args.OtherEntity == component.Thrower)
|
||||
return;
|
||||
|
||||
// WD edit start
|
||||
var collisionPair = (uid, args.OtherEntity);
|
||||
if (_processed.Contains(collisionPair))
|
||||
return;
|
||||
// WD edit end
|
||||
|
||||
ThrowCollideInteraction(component, args.OurEntity, args.OtherEntity);
|
||||
_processed.Add(collisionPair);
|
||||
}
|
||||
|
||||
private void PreventCollision(EntityUid uid, ThrownItemComponent component, ref PreventCollideEvent args)
|
||||
@@ -78,6 +87,8 @@ namespace Content.Shared.Throwing
|
||||
|
||||
private void OnSleep(EntityUid uid, ThrownItemComponent thrownItem, ref PhysicsSleepEvent @event)
|
||||
{
|
||||
if (HasComp<FrozenComponent>(uid)) // WD
|
||||
return;
|
||||
StopThrow(uid, thrownItem);
|
||||
}
|
||||
|
||||
@@ -110,6 +121,7 @@ namespace Content.Shared.Throwing
|
||||
|
||||
EntityManager.EventBus.RaiseLocalEvent(uid, new StopThrowEvent { User = thrownItemComponent.Thrower }, true);
|
||||
EntityManager.RemoveComponent<ThrownItemComponent>(uid);
|
||||
_processed.Clear(); // WD edit
|
||||
}
|
||||
|
||||
public void LandComponent(EntityUid uid, ThrownItemComponent thrownItem, PhysicsComponent physics, bool playSound)
|
||||
|
||||
13
Content.Shared/_White/Lighting/AppearanceChangedEvent.cs
Normal file
13
Content.Shared/_White/Lighting/AppearanceChangedEvent.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
namespace Content.Shared._White.Lighting;
|
||||
|
||||
public sealed class DoorlightsChangedEvent : EntityEventArgs
|
||||
{
|
||||
public Enum? State;
|
||||
public bool Value;
|
||||
|
||||
public DoorlightsChangedEvent(Enum? key, bool value)
|
||||
{
|
||||
State = key;
|
||||
Value = value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using Robust.Shared.GameStates;
|
||||
|
||||
namespace Content.Shared._White.Lighting.PointLight.Airlock;
|
||||
|
||||
[RegisterComponent, NetworkedComponent]
|
||||
public sealed partial class PointLightAirlockComponent : Component
|
||||
{
|
||||
[ViewVariables]
|
||||
public string RedColor = "#D56C6C";
|
||||
|
||||
[ViewVariables]
|
||||
public string BlueColor = "#7F93C0";
|
||||
|
||||
[ViewVariables]
|
||||
public string YellowColor = "#BDC07F";
|
||||
|
||||
[ViewVariables]
|
||||
public string GreenColor = "#7FC080";
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
using Content.Shared.Doors.Components;
|
||||
|
||||
namespace Content.Shared._White.Lighting.PointLight.Airlock;
|
||||
|
||||
//TODO: Когда-нибудь починить эту хуйню: Когда дверь открыта на аварийный доступ и ее болтируют, то свет будет желтым, хотя должен быть красным из-за болтов.
|
||||
|
||||
public sealed class SharedPointLightAirlockSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly SharedPointLightSystem _pointLightSystem = default!;
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<PointLightAirlockComponent, DoorlightsChangedEvent>(OnDoorLightChanged);
|
||||
}
|
||||
|
||||
public void ToggleLight(EntityUid uid, string hex, bool enable = true)
|
||||
{
|
||||
if (!_pointLightSystem.TryGetLight(uid, out var pointLightComponent))
|
||||
return;
|
||||
|
||||
if (enable)
|
||||
{
|
||||
var color = Color.FromHex(hex);
|
||||
_pointLightSystem.SetColor(uid, color, pointLightComponent);
|
||||
}
|
||||
|
||||
_pointLightSystem.SetEnabled(uid, enable, pointLightComponent);
|
||||
|
||||
RaiseLocalEvent(uid, new PointLightToggleEvent(enable), true);
|
||||
}
|
||||
|
||||
public void OnDoorLightChanged(EntityUid uid, PointLightAirlockComponent component, DoorlightsChangedEvent args)
|
||||
{
|
||||
if (!TryComp<DoorComponent>(uid, out var door))
|
||||
return;
|
||||
|
||||
if (TryComp<AirlockComponent>(uid, out var airlockComponent) && airlockComponent.EmergencyAccess && args.Value && args.State is not DoorVisuals.EmergencyLights && args.State != null)
|
||||
return; // While emergency access lights must be yellow no matter what
|
||||
|
||||
switch (args.State)
|
||||
{
|
||||
case DoorVisuals.BoltLights:
|
||||
if (args.Value)
|
||||
ToggleLight(uid, component.RedColor);
|
||||
else
|
||||
RaiseLocalEvent(uid, new DoorlightsChangedEvent(door.State, true));
|
||||
break;
|
||||
|
||||
case DoorState.Denying:
|
||||
ToggleLight(uid, component.RedColor);
|
||||
break;
|
||||
|
||||
case DoorState.Closed:
|
||||
ToggleLight(uid, component.BlueColor);
|
||||
break;
|
||||
|
||||
case DoorVisuals.EmergencyLights:
|
||||
if (args.Value)
|
||||
ToggleLight(uid, component.YellowColor);
|
||||
else
|
||||
RaiseLocalEvent(uid, new DoorlightsChangedEvent(door.State, true));
|
||||
break;
|
||||
|
||||
case DoorState.Open:
|
||||
ToggleLight(uid, component.BlueColor);
|
||||
break;
|
||||
|
||||
case DoorState.Opening:
|
||||
ToggleLight(uid, component.GreenColor);
|
||||
break;
|
||||
|
||||
case DoorState.Closing:
|
||||
ToggleLight(uid, component.GreenColor);
|
||||
break;
|
||||
|
||||
default:
|
||||
ToggleLight(uid, "", false);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using Robust.Shared.GameStates;
|
||||
|
||||
namespace Content.Shared._White.Lighting.PointLight.Locker;
|
||||
|
||||
[RegisterComponent, NetworkedComponent]
|
||||
public sealed partial class PointLightLockerComponent : Component
|
||||
{
|
||||
[DataField, ViewVariables]
|
||||
public string RedColor = "#D56C6C";
|
||||
|
||||
[DataField, ViewVariables]
|
||||
public string GreenColor = "#7FC080";
|
||||
|
||||
[DataField, ViewVariables]
|
||||
public float ReduceEnergyOnOpen = 0.1f;
|
||||
|
||||
[DataField, ViewVariables]
|
||||
public float ReduceRadiusOnOpen = 0.1f;
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
using Content.Shared.Lock;
|
||||
using Content.Shared.Storage.Components;
|
||||
|
||||
namespace Content.Shared._White.Lighting.PointLight.Locker;
|
||||
|
||||
public sealed class PointLightLockerSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly SharedPointLightSystem _pointLightSystem = default!;
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<PointLightLockerComponent, ComponentInit>(OnComponentInit);
|
||||
|
||||
SubscribeLocalEvent<PointLightLockerComponent, LockToggledEvent>(OnLockToggled);
|
||||
SubscribeLocalEvent<PointLightLockerComponent, StorageAfterOpenEvent>(OnStorageAfterOpen);
|
||||
SubscribeLocalEvent<PointLightLockerComponent, StorageAfterCloseEvent>(OnStorageAfterClose);
|
||||
}
|
||||
|
||||
public void ToggleLight(EntityUid uid, string hex, bool enable = true)
|
||||
{
|
||||
if (!_pointLightSystem.TryGetLight(uid, out var pointLightComponent))
|
||||
return;
|
||||
|
||||
if (enable)
|
||||
{
|
||||
var color = Color.FromHex(hex);
|
||||
_pointLightSystem.SetColor(uid, color, pointLightComponent);
|
||||
}
|
||||
|
||||
_pointLightSystem.SetEnabled(uid, enable, pointLightComponent);
|
||||
|
||||
RaiseLocalEvent(uid, new PointLightToggleEvent(enable), true);
|
||||
}
|
||||
|
||||
public void OnComponentInit(EntityUid uid, PointLightLockerComponent component, ComponentInit args)
|
||||
{
|
||||
if (!TryComp<LockComponent>(uid, out var locker))
|
||||
return;
|
||||
|
||||
ToggleLight(uid, locker.Locked ? component.RedColor : component.GreenColor, true);
|
||||
}
|
||||
|
||||
public void OnLockToggled(EntityUid uid, PointLightLockerComponent component, LockToggledEvent args)
|
||||
{
|
||||
ToggleLight(uid, args.Locked ? component.RedColor : component.GreenColor, true);
|
||||
}
|
||||
|
||||
public void OnStorageAfterOpen(EntityUid uid, PointLightLockerComponent component, StorageAfterOpenEvent args)
|
||||
{
|
||||
ChangeLightOnDoorToggled(uid, component, true);
|
||||
}
|
||||
|
||||
public void OnStorageAfterClose(EntityUid uid, PointLightLockerComponent component, StorageAfterCloseEvent args)
|
||||
{
|
||||
ChangeLightOnDoorToggled(uid, component, false);
|
||||
}
|
||||
|
||||
public void ChangeLightOnDoorToggled(EntityUid uid, PointLightLockerComponent component, bool status)
|
||||
{
|
||||
if (!_pointLightSystem.TryGetLight(uid, out var pointLightComponent))
|
||||
return;
|
||||
|
||||
var factor = status ? 1f : -1f;
|
||||
|
||||
_pointLightSystem.SetEnergy(uid, pointLightComponent.Energy - component.ReduceEnergyOnOpen * factor);
|
||||
_pointLightSystem.SetRadius(uid, pointLightComponent.Radius- component.ReduceRadiusOnOpen * factor);
|
||||
|
||||
RaiseLocalEvent(uid, new PointLightToggleEvent(true), true);
|
||||
}
|
||||
}
|
||||
9
Content.Shared/_White/NiceIdCards/IdCardsVisuals.cs
Normal file
9
Content.Shared/_White/NiceIdCards/IdCardsVisuals.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared._White.NiceIdCards;
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public enum IdVisuals : byte
|
||||
{
|
||||
State
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace Content.Shared._White.WeaponModules;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class AimModuleComponent : BaseModuleComponent
|
||||
{
|
||||
[ViewVariables(VVAccess.ReadWrite), DataField("divisor")]
|
||||
public float Divisor = 0.3F;
|
||||
}
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace Content.Shared._White.WeaponModules;
|
||||
|
||||
|
||||
[RegisterComponent, NetworkedComponent]
|
||||
public partial class BaseModuleComponent : Component
|
||||
{
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
namespace Content.Shared._White.WeaponModules;
|
||||
|
||||
/// <summary>
|
||||
/// This is used for...
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
public sealed partial class FlameHiderModuleComponent : BaseModuleComponent
|
||||
{
|
||||
|
||||
@@ -20,7 +20,8 @@ public partial class WeaponModulesComponent : Component
|
||||
public enum ModuleVisualState : byte
|
||||
{
|
||||
BarrelModule,
|
||||
HandGuardModule
|
||||
HandGuardModule,
|
||||
AimModule
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
using Robust.Shared.GameStates;
|
||||
|
||||
namespace Content.Shared._White.Wizard.Timestop;
|
||||
|
||||
[RegisterComponent, NetworkedComponent]
|
||||
public sealed partial class FreezeContactsComponent : Component
|
||||
{
|
||||
}
|
||||
183
Content.Shared/_White/Wizard/Timestop/FreezeContactsSystem.cs
Normal file
183
Content.Shared/_White/Wizard/Timestop/FreezeContactsSystem.cs
Normal file
@@ -0,0 +1,183 @@
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using Content.Shared.ActionBlocker;
|
||||
using Content.Shared.Emoting;
|
||||
using Content.Shared.Hands;
|
||||
using Content.Shared.Interaction.Events;
|
||||
using Content.Shared.Inventory.Events;
|
||||
using Content.Shared.Item;
|
||||
using Content.Shared.Movement.Events;
|
||||
using Content.Shared.Speech;
|
||||
using Content.Shared.Throwing;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.Physics;
|
||||
using Robust.Shared.Physics.Components;
|
||||
using Robust.Shared.Physics.Events;
|
||||
using Robust.Shared.Physics.Systems;
|
||||
using Robust.Shared.Spawners;
|
||||
|
||||
namespace Content.Shared._White.Wizard.Timestop;
|
||||
|
||||
public sealed class FreezeContactsSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly SharedPhysicsSystem _physics = default!;
|
||||
[Dependency] private readonly SharedContainerSystem _container = default!;
|
||||
[Dependency] private readonly ActionBlockerSystem _blocker = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<FreezeContactsComponent, StartCollideEvent>(OnEntityEnter);
|
||||
SubscribeLocalEvent<FreezeContactsComponent, EndCollideEvent>(OnEntityExit);
|
||||
SubscribeLocalEvent<FrozenComponent, ComponentInit>(OnInit);
|
||||
SubscribeLocalEvent<FrozenComponent, ComponentRemove>(OnRemove);
|
||||
SubscribeLocalEvent<FrozenComponent, PreventCollideEvent>(OnPreventCollide);
|
||||
SubscribeLocalEvent<FrozenComponent, EntGotInsertedIntoContainerMessage>(OnGetInserted);
|
||||
|
||||
SubscribeLocalEvent<FrozenComponent, SpeakAttemptEvent>(OnAttempt);
|
||||
SubscribeLocalEvent<FrozenComponent, EmoteAttemptEvent>(OnAttempt);
|
||||
SubscribeLocalEvent<FrozenComponent, ChangeDirectionAttemptEvent>(OnAttempt);
|
||||
SubscribeLocalEvent<FrozenComponent, UpdateCanMoveEvent>(OnMoveAttempt);
|
||||
SubscribeLocalEvent<FrozenComponent, InteractionAttemptEvent>(OnAttempt);
|
||||
SubscribeLocalEvent<FrozenComponent, UseAttemptEvent>(OnAttempt);
|
||||
SubscribeLocalEvent<FrozenComponent, ThrowAttemptEvent>(OnAttempt);
|
||||
SubscribeLocalEvent<FrozenComponent, DropAttemptEvent>(OnAttempt);
|
||||
SubscribeLocalEvent<FrozenComponent, AttackAttemptEvent>(OnAttempt);
|
||||
SubscribeLocalEvent<FrozenComponent, PickupAttemptEvent>(OnAttempt);
|
||||
SubscribeLocalEvent<FrozenComponent, IsEquippingAttemptEvent>(OnEquipAttempt);
|
||||
SubscribeLocalEvent<FrozenComponent, IsUnequippingAttemptEvent>(OnUnequipAttempt);
|
||||
}
|
||||
|
||||
private void OnMoveAttempt(EntityUid uid, FrozenComponent component, UpdateCanMoveEvent args)
|
||||
{
|
||||
if (component.LifeStage > ComponentLifeStage.Running)
|
||||
return;
|
||||
|
||||
args.Cancel();
|
||||
}
|
||||
|
||||
private void OnAttempt(EntityUid uid, FrozenComponent component, CancellableEntityEventArgs args)
|
||||
{
|
||||
args.Cancel();
|
||||
}
|
||||
|
||||
private void OnEquipAttempt(EntityUid uid, FrozenComponent component, IsEquippingAttemptEvent args)
|
||||
{
|
||||
// is this a self-equip, or are they being stripped?
|
||||
if (args.Equipee == uid)
|
||||
args.Cancel();
|
||||
}
|
||||
|
||||
private void OnUnequipAttempt(EntityUid uid, FrozenComponent component, IsUnequippingAttemptEvent args)
|
||||
{
|
||||
// is this a self-equip, or are they being stripped?
|
||||
if (args.Unequipee == uid)
|
||||
args.Cancel();
|
||||
}
|
||||
|
||||
private void OnGetInserted(Entity<FrozenComponent> ent, ref EntGotInsertedIntoContainerMessage args)
|
||||
{
|
||||
RemCompDeferred<FrozenComponent>(ent);
|
||||
}
|
||||
|
||||
private void OnPreventCollide(Entity<FrozenComponent> ent, ref PreventCollideEvent args)
|
||||
{
|
||||
if (args.OurBody.BodyType == BodyType.Dynamic && !HasComp<FreezeContactsComponent>(args.OtherEntity))
|
||||
args.Cancelled = true;
|
||||
}
|
||||
|
||||
private void OnRemove(Entity<FrozenComponent> ent, ref ComponentRemove args)
|
||||
{
|
||||
var (uid, comp) = ent;
|
||||
|
||||
_blocker.UpdateCanMove(uid);
|
||||
|
||||
if (_container.IsEntityOrParentInContainer(uid))
|
||||
return;
|
||||
|
||||
if (!TryComp(uid, out PhysicsComponent? physics))
|
||||
return;
|
||||
|
||||
_physics.SetLinearVelocity(uid, comp.OldLinearVelocity, false, body: physics);
|
||||
_physics.SetAngularVelocity(uid, comp.OldAngularVelocity, body: physics);
|
||||
}
|
||||
|
||||
private void OnInit(Entity<FrozenComponent> ent, ref ComponentInit args)
|
||||
{
|
||||
var (uid, comp) = ent;
|
||||
|
||||
_blocker.UpdateCanMove(uid);
|
||||
|
||||
if (!TryComp(uid, out PhysicsComponent? physics))
|
||||
return;
|
||||
|
||||
comp.OldLinearVelocity = physics.LinearVelocity;
|
||||
comp.OldAngularVelocity = physics.AngularVelocity;
|
||||
|
||||
_physics.SetLinearVelocity(uid, Vector2.Zero, false, body: physics);
|
||||
_physics.SetAngularVelocity(uid, 0f, body: physics);
|
||||
}
|
||||
|
||||
public override void Update(float frameTime)
|
||||
{
|
||||
base.Update(frameTime);
|
||||
|
||||
var query = AllEntityQuery<FrozenComponent, FixturesComponent, PhysicsComponent>();
|
||||
|
||||
while (query.MoveNext(out var uid, out var frozen, out var fixtures, out var physics))
|
||||
{
|
||||
frozen.Lifetime -= frameTime;
|
||||
|
||||
if (physics.LinearVelocity != Vector2.Zero)
|
||||
_physics.SetLinearVelocity(uid, Vector2.Zero, manager: fixtures, body: physics);
|
||||
|
||||
if (physics.AngularVelocity != 0f)
|
||||
_physics.SetAngularVelocity(uid, 0f, manager: fixtures, body: physics);
|
||||
|
||||
if (frozen.Lifetime > 0)
|
||||
continue;
|
||||
|
||||
RemCompDeferred<FrozenComponent>(uid);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnEntityExit(Entity<FreezeContactsComponent> ent, ref EndCollideEvent args)
|
||||
{
|
||||
if (IsTouchingFrozenContacts(args.OtherEntity, args.OtherBody))
|
||||
return;
|
||||
|
||||
RemCompDeferred<FrozenComponent>(args.OtherEntity);
|
||||
}
|
||||
|
||||
private void OnEntityEnter(Entity<FreezeContactsComponent> ent, ref StartCollideEvent args)
|
||||
{
|
||||
var hadFrozen = HasComp<FrozenComponent>(args.OtherEntity);
|
||||
var frozen = EnsureComp<FrozenComponent>(args.OtherEntity);
|
||||
|
||||
if (!TryComp(ent, out TimedDespawnComponent? timedDespawn))
|
||||
return;
|
||||
|
||||
frozen.Lifetime = timedDespawn.Lifetime;
|
||||
|
||||
if (TryComp(args.OtherEntity, out TimedDespawnComponent? otherTimedDespawn))
|
||||
otherTimedDespawn.Lifetime += timedDespawn.Lifetime;
|
||||
|
||||
if (hadFrozen)
|
||||
return;
|
||||
|
||||
if (!TryComp(args.OtherEntity, out ThrownItemComponent? thrownItem))
|
||||
return;
|
||||
|
||||
if (thrownItem.LandTime != null)
|
||||
thrownItem.LandTime = thrownItem.LandTime.Value + TimeSpan.FromSeconds(timedDespawn.Lifetime);
|
||||
|
||||
if (thrownItem.ThrownTime != null)
|
||||
thrownItem.ThrownTime = thrownItem.ThrownTime.Value + TimeSpan.FromSeconds(timedDespawn.Lifetime);
|
||||
}
|
||||
|
||||
private bool IsTouchingFrozenContacts(EntityUid uid, PhysicsComponent body)
|
||||
{
|
||||
return _physics.GetContactingEntities(uid, body).Any(HasComp<FreezeContactsComponent>);
|
||||
}
|
||||
}
|
||||
17
Content.Shared/_White/Wizard/Timestop/FrozenComponent.cs
Normal file
17
Content.Shared/_White/Wizard/Timestop/FrozenComponent.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using System.Numerics;
|
||||
using Robust.Shared.GameStates;
|
||||
|
||||
namespace Content.Shared._White.Wizard.Timestop;
|
||||
|
||||
[RegisterComponent, NetworkedComponent]
|
||||
public sealed partial class FrozenComponent : Component
|
||||
{
|
||||
[ViewVariables]
|
||||
public float Lifetime = 10f;
|
||||
|
||||
[ViewVariables]
|
||||
public Vector2 OldLinearVelocity;
|
||||
|
||||
[ViewVariables]
|
||||
public float OldAngularVelocity;
|
||||
}
|
||||
@@ -184,4 +184,13 @@ public sealed partial class MindswapSpellEvent : EntityTargetActionEvent, ISpeak
|
||||
public string? Speech { get; private set; }
|
||||
}
|
||||
|
||||
public sealed partial class StopTimeSpellEvent : InstantActionEvent, ISpeakSpell
|
||||
{
|
||||
[DataField("prototype", required: true, customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||
public string Prototype = default!;
|
||||
|
||||
[DataField("speech")]
|
||||
public string? Speech { get; private set; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
Reference in New Issue
Block a user