Merge remote-tracking branch 'upstream/master' into ups

This commit is contained in:
Jabak
2024-06-21 21:53:12 +03:00
103 changed files with 2092 additions and 340 deletions

View File

@@ -13,6 +13,7 @@ namespace Content.Client.Access.UI;
public sealed partial class AccessLevelControl : GridContainer
{
public readonly Dictionary<ProtoId<AccessLevelPrototype>, Button> ButtonsList = new();
public readonly List<Dictionary<ProtoId<AccessLevelPrototype>, Button>> ButtonGroups = new ();
public AccessLevelControl()
{
@@ -39,6 +40,61 @@ public sealed partial class AccessLevelControl : GridContainer
}
}
public void PopulateForConsole(List<List<ProtoId<AccessLevelPrototype>>> accessLevels, IPrototypeManager prototypeManager)
{
var departmentColors = new List<String> // Colors from StyleNano.cs
{
"ButtonColorCommandDepartment",
"ButtonColorSecurityDepartment",
"ButtonColorMedicalDepartment",
"ButtonColorEngineeringDepartment",
"ButtonColorResearchingDepartment",
"ButtonColorCargoDepartment",
"ButtonColorServiceDepartment"
};
var currentColorIndex = 0;
foreach (var department in accessLevels)
{
Dictionary<ProtoId<AccessLevelPrototype>, Button> buttons = new();
foreach (var access in department)
{
if (!prototypeManager.TryIndex(access, out var accessLevel))
{
Logger.Error($"Unable to find accesslevel for {access}");
continue;
}
var newButton = new Button
{
Text = accessLevel.GetAccessLevelName(),
ToggleMode = true,
};
newButton.AddStyleClass(departmentColors[currentColorIndex]);
buttons.Add(accessLevel.ID, newButton);
}
ButtonGroups.Add(buttons);
currentColorIndex++;
}
}
public void UpdateStateConsole(
List<ProtoId<AccessLevelPrototype>> pressedList,
List<ProtoId<AccessLevelPrototype>>? enabledList = null)
{
foreach (var department in ButtonGroups)
{
foreach (var (accessName, button) in department)
{
button.Pressed = pressedList.Contains(accessName);
button.Disabled = !(enabledList?.Contains(accessName) ?? true);
}
}
}
public void UpdateState(
List<ProtoId<AccessLevelPrototype>> pressedList,
List<ProtoId<AccessLevelPrototype>>? enabledList = null)

View File

@@ -23,15 +23,15 @@ namespace Content.Client.Access.UI
protected override void Open()
{
base.Open();
List<ProtoId<AccessLevelPrototype>> accessLevels;
List<List<ProtoId<AccessLevelPrototype>>> accessLevels;
if (EntMan.TryGetComponent<IdCardConsoleComponent>(Owner, out var idCard))
{
accessLevels = idCard.AccessLevels;
accessLevels = idCard.AccessLevelsConsole;
}
else
{
accessLevels = new List<ProtoId<AccessLevelPrototype>>();
accessLevels = new List<List<ProtoId<AccessLevelPrototype>>>();
_idCardConsoleSystem.Log.Error($"No IdCardConsole component found for {EntMan.ToPrettyString(Owner)}!");
}

View File

@@ -26,16 +26,13 @@
<Button Name="JobTitleSaveButton" Text="{Loc 'id-card-console-window-save-button'}" Disabled="True" />
</GridContainer>
<Control MinSize="0 8" />
<GridContainer Columns="2">
<Label Text="{Loc 'id-card-console-window-job-selection-label'}" />
<OptionButton Name="JobPresetOptionButton" />
</GridContainer>
<Control Name="AccessLevelControlContainer" />
<GridContainer Name="AccessLevelControlContainer" Columns="7" HorizontalExpand="True" HorizontalAlignment="Center" >
<!-- WD EDIT -->
</GridContainer>
<GridContainer Name="CurrentJobIcon" Columns="2">
<Label Text="Текущая выбранная иконка для роли: " />
</GridContainer>
<GridContainer Name="JobIconsGrid" Columns="10" HorizontalAlignment="Center">
<GridContainer Name="JobIconsGrid" HorizontalAlignment="Center">
<!-- Job icon buttons are generated in the code -->
</GridContainer>
<!-- WD EDIT END -->

View File

@@ -24,9 +24,11 @@ namespace Content.Client.Access.UI
private readonly IdCardConsoleBoundUserInterface _owner;
private AccessLevelControl _accessButtons = new();
private GridContainer _grid = default!;
private readonly AccessLevelControl _groupAccessButtons = new();
private readonly Dictionary<string, TextureButton> _jobIconButtons = new(); //WD-EDIT
private readonly List<string> _jobPrototypeIds = new();
private string _newJob = "";
private string? _lastFullName;
private string? _lastJobTitle;
@@ -36,7 +38,7 @@ namespace Content.Client.Access.UI
public IdCardConsoleWindow(
IdCardConsoleBoundUserInterface owner,
IPrototypeManager prototypeManager,
List<ProtoId<AccessLevelPrototype>> accessLevels)
List<List<ProtoId<AccessLevelPrototype>>> accessLevels)
{
RobustXamlLoader.Load(this);
IoCManager.InjectDependencies(this);
@@ -59,29 +61,26 @@ namespace Content.Client.Access.UI
JobTitleSaveButton.OnPressed += _ => SubmitData();
var jobs = _prototypeManager.EnumeratePrototypes<JobPrototype>().ToList();
jobs.Sort((x, y) => string.Compare(x.LocalizedName, y.LocalizedName, StringComparison.CurrentCulture));
_groupAccessButtons.PopulateForConsole(accessLevels, prototypeManager);
foreach (var job in jobs)
foreach (var department in _groupAccessButtons.ButtonGroups)
{
if (!job.OverrideConsoleVisibility.GetValueOrDefault(job.SetPreference))
var departmentGrid = new GridContainer {};
foreach (var button in department.Values)
{
continue;
departmentGrid.AddChild(button);
}
AccessLevelControlContainer.AddChild(departmentGrid);
}
_jobPrototypeIds.Add(job.ID);
JobPresetOptionButton.AddItem(Loc.GetString(job.Name), _jobPrototypeIds.Count - 1);
}
JobPresetOptionButton.OnItemSelected += SelectJobPreset;
_accessButtons.Populate(accessLevels, prototypeManager);
AccessLevelControlContainer.AddChild(_accessButtons);
foreach (var (id, button) in _accessButtons.ButtonsList)
foreach (var department in _groupAccessButtons.ButtonGroups)
{
foreach (var button in department.Values)
{
button.OnPressed += _ => SubmitData();
}
}
//WD-EDIT
if (!_entityManager.TryGetComponent<IdCardConsoleComponent>(owner.Owner, out var idConsoleComponent))
@@ -92,7 +91,13 @@ namespace Content.Client.Access.UI
if (rsi == null)
return;
foreach (var jobIcon in idConsoleComponent.JobIcons)
foreach (var department in idConsoleComponent.JobIcons)
{
_grid = new GridContainer
{
Columns = department.Count
};
foreach (var jobIcon in department)
{
var newButton = new TextureButton
{
@@ -102,21 +107,29 @@ namespace Content.Client.Access.UI
Scale = new Vector2(5, 5)
};
_jobIconButtons.Add(jobIcon, newButton);
_jobIconButtons.TryAdd(jobIcon, newButton);
newButton.OnPressed += _ =>
{
SelectJobPreset(jobIcon);
_newJob = jobIcon;
_lastJobIcon = "JobIcon" + jobIcon;
SubmitData();
};
JobIconsGrid.AddChild(newButton);
_grid.AddChild(newButton);
}
JobIconsGrid.AddChild(_grid);
}
//WD-EDIT
}
private void ClearAllAccess()
{
foreach (var button in _accessButtons.ButtonsList.Values)
foreach (var group in _groupAccessButtons.ButtonGroups)
{
foreach (var button in group.Values)
{
if (button.Pressed)
{
@@ -124,39 +137,42 @@ namespace Content.Client.Access.UI
}
}
}
}
private void SelectJobPreset(OptionButton.ItemSelectedEventArgs args)
private void SelectJobPreset(string jobName)
{
if (!_prototypeManager.TryIndex(_jobPrototypeIds[args.Id], out JobPrototype? job))
if (!_prototypeManager.TryIndex(jobName, out JobPrototype? job))
{
return;
}
JobTitleLineEdit.Text = Loc.GetString(job.Name);
args.Button.SelectId(args.Id);
ClearAllAccess();
// this is a sussy way to do this
foreach (var access in job.Access)
{
if (_accessButtons.ButtonsList.TryGetValue(access, out var button) && !button.Disabled)
foreach (var group in _groupAccessButtons.ButtonGroups)
{
if (group.TryGetValue(access, out var button) && !button.Disabled)
{
button.Pressed = true;
}
}
}
foreach (var group in job.AccessGroups)
{
if (!_prototypeManager.TryIndex(group, out AccessGroupPrototype? groupPrototype))
{
continue;
}
foreach (var access in groupPrototype.Tags)
{
if (_accessButtons.ButtonsList.TryGetValue(access, out var button) && !button.Disabled)
foreach (var buttonGroup in _groupAccessButtons.ButtonGroups)
{
if (buttonGroup.TryGetValue(access, out var button) && !button.Disabled)
button.Pressed = true;
}
}
@@ -204,19 +220,12 @@ namespace Content.Client.Access.UI
JobTitleSaveButton.Disabled = !interfaceEnabled || !jobTitleDirty;
JobPresetOptionButton.Disabled = !interfaceEnabled;
_accessButtons.UpdateState(state.TargetIdAccessList?.ToList() ??
_groupAccessButtons.UpdateStateConsole(state.TargetIdAccessList?.ToList() ??
new List<ProtoId<AccessLevelPrototype>>(),
state.AllowedModifyAccessList?.ToList() ??
new List<ProtoId<AccessLevelPrototype>>());
var jobIndex = _jobPrototypeIds.IndexOf(state.TargetIdJobPrototype);
if (jobIndex >= 0)
{
JobPresetOptionButton.SelectId(jobIndex);
}
//WD-EDIT
if (_resource.TryGetResource(new ResPath("/Textures/Interface/Misc/job_icons.rsi"), out RSIResource? rsi))
{
@@ -234,7 +243,6 @@ namespace Content.Client.Access.UI
: rsi.RSI.TryGetState("CustomId", out var customState)
? customState.Frame0
: null,
TextureScale = new Vector2(4, 4)
};
@@ -256,15 +264,18 @@ namespace Content.Client.Access.UI
private void SubmitData()
{
// Don't send this if it isn't dirty.
var jobProtoDirty = _lastJobProto != null &&
_jobPrototypeIds[JobPresetOptionButton.SelectedId] != _lastJobProto;
var jobProtoDirty = _lastJobProto != null && _newJob != _lastJobProto;
_owner.SubmitData(
FullNameLineEdit.Text,
JobTitleLineEdit.Text,
// Iterate over the buttons dictionary, filter by `Pressed`, only get key from the key/value pair
_accessButtons.ButtonsList.Where(x => x.Value.Pressed).Select(x => x.Key).ToList(),
jobProtoDirty ? _jobPrototypeIds[JobPresetOptionButton.SelectedId] : string.Empty,
_groupAccessButtons.ButtonGroups
.SelectMany(dict => dict)
.Where(x => x.Value.Pressed)
.Select(x => x.Key)
.ToList(),
jobProtoDirty ? _newJob : string.Empty,
_lastJobIcon);
}
}

View File

@@ -0,0 +1,19 @@
using Content.Shared.Clothing.Components;
using Robust.Client.Physics;
namespace Content.Client.Clothing.Systems;
public sealed partial class PilotedByClothingSystem : EntitySystem
{
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<PilotedByClothingComponent, UpdateIsPredictedEvent>(OnUpdatePredicted);
}
private void OnUpdatePredicted(Entity<PilotedByClothingComponent> entity, ref UpdateIsPredictedEvent args)
{
args.BlockPrediction = true;
}
}

View File

@@ -1,5 +1,4 @@
using Content.Client.Wires.Visualizers;
using Content.Shared.Doors;
using Content.Shared.Doors.Components;
using Content.Shared.Doors.Systems;
using Robust.Client.Animations;
@@ -113,6 +112,7 @@ public sealed class AirlockSystem : SharedAirlockSystem
args.Sprite.LayerSetVisible(DoorVisualLayers.BaseUnlit, unlitVisible);
args.Sprite.LayerSetVisible(DoorVisualLayers.BaseBolted, boltedVisible);
if (comp.EmergencyAccessLayer)
{
args.Sprite.LayerSetVisible(

View File

@@ -0,0 +1,31 @@
using Content.Client.GameTicking.Managers;
using Content.Shared.Administration;
using Content.Shared.GameTicking;
using Robust.Shared.Console;
using Robust.Shared.Network;
namespace Content.Client.GameTicking.Commands
{
[AnyCommand]
public sealed class ShowManifestCommand : IConsoleCommand
{
[Dependency] private readonly IEntitySystemManager _entitySystem = default!;
public string Command => "showmanifest";
public string Description => "Shows round end summary window";
public string Help => "Usage: showmanifest";
public void Execute(IConsoleShell shell, string argStr, string[] args)
{
var ticker = _entitySystem.GetEntitySystem<ClientGameTicker>();
var window = ticker._window;
if (!ticker.IsGameStarted && window != null)
{
window.OpenCentered();
return;
}
shell.WriteLine("You can't open manifest right now");
}
}
}

View File

@@ -23,7 +23,7 @@ namespace Content.Client.GameTicking.Managers
/// <summary>
/// The current round-end window. Could be used to support re-opening the window after closing it.
/// </summary>
private RoundEndSummaryWindow? _window;
public RoundEndSummaryWindow? _window;
[ViewVariables] public bool AreWeReady { get; private set; }
[ViewVariables] public bool IsGameStarted { get; private set; }

View File

@@ -158,6 +158,16 @@ namespace Content.Client.Stylesheets
public const string StyleClassButtonColorGreen = "ButtonColorGreen";
public const string StyleClassButtonColorPurple = "ButtonColorPurple";
// WD - HoP console
public static readonly Color ButtonColorCommand = Color.FromHex("#436BAD");
public static readonly Color ButtonColorSecurity = Color.FromHex("#BF5454");
public static readonly Color ButtonColorMedical = Color.FromHex("#4494C8");
public static readonly Color ButtonColorEngineering = Color.FromHex("#FDA55E");
public static readonly Color ButtonColorCargo = Color.FromHex("#9E6A34");
public static readonly Color ButtonColorResearching = Color.FromHex("#984EB4");
public static readonly Color ButtonColorService = Color.FromHex("#40A166");
public override Stylesheet Stylesheet { get; }
public StyleNano(IResourceCache resCache) : base(resCache)
@@ -1340,6 +1350,55 @@ namespace Content.Client.Stylesheets
{
new StyleProperty(Label.StylePropertyFont, notoSansDisplayBold14),
}),
// WD - HoP conlose
new StyleRule(
new SelectorElement(typeof(MenuButton), new[] {MenuButton.StyleClassRedTopButton}, null, new[] {Button.StylePseudoClassNormal}),
new[]
{
new StyleProperty(Button.StylePropertyModulateSelf, ButtonColorCommand),
}),
new StyleRule(
new SelectorElement(typeof(MenuButton), new[] {MenuButton.StyleClassRedTopButton}, null, new[] {Button.StylePseudoClassNormal}),
new[]
{
new StyleProperty(Button.StylePropertyModulateSelf, ButtonColorSecurity),
}),
new StyleRule(
new SelectorElement(typeof(MenuButton), new[] {MenuButton.StyleClassRedTopButton}, null, new[] {Button.StylePseudoClassNormal}),
new[]
{
new StyleProperty(Button.StylePropertyModulateSelf, ButtonColorMedical),
}),
new StyleRule(
new SelectorElement(typeof(MenuButton), new[] {MenuButton.StyleClassRedTopButton}, null, new[] {Button.StylePseudoClassNormal}),
new[]
{
new StyleProperty(Button.StylePropertyModulateSelf, ButtonColorEngineering),
}),
new StyleRule(
new SelectorElement(typeof(MenuButton), new[] {MenuButton.StyleClassRedTopButton}, null, new[] {Button.StylePseudoClassNormal}),
new[]
{
new StyleProperty(Button.StylePropertyModulateSelf, ButtonColorService),
}),
new StyleRule(
new SelectorElement(typeof(MenuButton), new[] {MenuButton.StyleClassRedTopButton}, null, new[] {Button.StylePseudoClassNormal}),
new[]
{
new StyleProperty(Button.StylePropertyModulateSelf, ButtonColorResearching),
}),
new StyleRule(
new SelectorElement(typeof(MenuButton), new[] {MenuButton.StyleClassRedTopButton}, null, new[] {Button.StylePseudoClassNormal}),
new[]
{
new StyleProperty(Button.StylePropertyModulateSelf, ButtonColorCargo),
}),
// NanoHeading
@@ -1576,6 +1635,44 @@ namespace Content.Client.Stylesheets
.Prop(Control.StylePropertyModulateSelf, ButtonColorHoveredRed),
// ---
// WD - HoP console
Element<Button>().Class("ButtonColorCommandDepartment")
.Prop(Control.StylePropertyModulateSelf, ButtonColorCommand),
Element<Button>().Class("ButtonColorCommandDepartment").Pseudo(ContainerButton.StylePseudoClassNormal)
.Prop(Control.StylePropertyModulateSelf, ButtonColorCommand),
Element<Button>().Class("ButtonColorSecurityDepartment")
.Prop(Control.StylePropertyModulateSelf, ButtonColorSecurity),
Element<Button>().Class("ButtonColorSecurityDepartment").Pseudo(ContainerButton.StylePseudoClassNormal)
.Prop(Control.StylePropertyModulateSelf, ButtonColorSecurity),
Element<Button>().Class("ButtonColorMedicalDepartment")
.Prop(Control.StylePropertyModulateSelf, ButtonColorMedical),
Element<Button>().Class("ButtonColorMedicalDepartment").Pseudo(ContainerButton.StylePseudoClassNormal)
.Prop(Control.StylePropertyModulateSelf, ButtonColorMedical),
Element<Button>().Class("ButtonColorEngineeringDepartment")
.Prop(Control.StylePropertyModulateSelf, ButtonColorEngineering),
Element<Button>().Class("ButtonColorEngineeringDepartment").Pseudo(ContainerButton.StylePseudoClassNormal)
.Prop(Control.StylePropertyModulateSelf, ButtonColorEngineering),
Element<Button>().Class("ButtonColorResearchingDepartment")
.Prop(Control.StylePropertyModulateSelf, ButtonColorResearching),
Element<Button>().Class("ButtonColorResearchingDepartment").Pseudo(ContainerButton.StylePseudoClassNormal)
.Prop(Control.StylePropertyModulateSelf, ButtonColorResearching),
Element<Button>().Class("ButtonColorServiceDepartment")
.Prop(Control.StylePropertyModulateSelf, ButtonColorService),
Element<Button>().Class("ButtonColorServiceDepartment").Pseudo(ContainerButton.StylePseudoClassNormal)
.Prop(Control.StylePropertyModulateSelf, ButtonColorService),
Element<Button>().Class("ButtonColorCargoDepartment")
.Prop(Control.StylePropertyModulateSelf, ButtonColorCargo),
Element<Button>().Class("ButtonColorCargoDepartment").Pseudo(ContainerButton.StylePseudoClassNormal)
.Prop(Control.StylePropertyModulateSelf, ButtonColorCargo),
// ---
// Green Button ---
Element<Button>().Class("ButtonColorGreen")
.Prop(Control.StylePropertyModulateSelf, ButtonColorGoodDefault),

View File

@@ -339,9 +339,9 @@ public sealed partial class GunSystem : SharedGunSystem
}
Lights.SetEnabled(uid, true, light);
Lights.SetRadius(uid, 2f, light);
Lights.SetRadius(uid, 1.4f, light);
Lights.SetColor(uid, Color.FromHex("#cc8e2b"), light);
Lights.SetEnergy(uid, 5f, light);
Lights.SetEnergy(uid, 0.7f, light);
var animTwo = new Animation()
{

View File

@@ -18,6 +18,7 @@ public sealed partial class WeaponModulesVisuals : VisualizerSystem<WeaponModule
args.Sprite.LayerSetVisible(ModuleVisualState.HandGuardModule, false);
args.Sprite.LayerSetVisible(ModuleVisualState.BarrelModule, false);
args.Sprite.LayerSetVisible(ModuleVisualState.AimModule, false);
if (AppearanceSystem.TryGetData<string>(uid, ModuleVisualState.HandGuardModule, out var handguardModule, args.Component) && handguardModule.Length != 0 && handguardModule != "none")
{
@@ -31,6 +32,12 @@ public sealed partial class WeaponModulesVisuals : VisualizerSystem<WeaponModule
args.Sprite.LayerSetVisible(ModuleVisualState.BarrelModule, true);
}
if (AppearanceSystem.TryGetData<string>(uid, ModuleVisualState.AimModule, out var aimModule, args.Component) && aimModule.Length != 0 && aimModule != "none")
{
args.Sprite.LayerSetState(ModuleVisualState.AimModule, aimModule);
args.Sprite.LayerSetVisible(ModuleVisualState.AimModule, true);
}
if (AppearanceSystem.TryGetData(uid, Modules.Light, out var data, args.Component))
{
if (TryComp<PointLightComponent>(uid, out var pointLightComponent))

View File

@@ -145,7 +145,12 @@ public sealed class IdCardConsoleSystem : SharedIdCardConsoleSystem
if (newJobIcon != null && _prototype.TryIndex<StatusIconPrototype>(newJobIcon, out var jobIcon)) // WD EDIT END
{
_idCard.TryChangeJobIcon(targetId, jobIcon, player: player);
_idCard.TryChangeJobDepartment(targetId, job!);
_idCard.TryChangeVisuals(targetId, newJobIcon);
}
if (job != null)
{
_idCard.TryChangeJobDepartment(targetId, job);
}
if (!newAccessList.TrueForAll(x => component.AccessLevels.Contains(x)))

View File

@@ -2,6 +2,7 @@ using System.Linq;
using Content.Server.Administration.Logs;
using Content.Server.Kitchen.Components;
using Content.Server.Popups;
using Content.Shared._White.NiceIdCards;
using Content.Shared.Access;
using Content.Shared.Access.Components;
using Content.Shared.Access.Systems;
@@ -9,6 +10,7 @@ using Content.Shared.Database;
using Content.Shared.Popups;
using Content.Shared.Roles;
using Content.Shared.StatusIcon;
using Robust.Server.GameObjects;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
@@ -21,6 +23,7 @@ public sealed class IdCardSystem : SharedIdCardSystem
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
[Dependency] private readonly MetaDataSystem _metaSystem = default!;
[Dependency] private readonly SharedAppearanceSystem _sharedAppearance = default!;
public override void Initialize()
{
@@ -144,6 +147,17 @@ public sealed class IdCardSystem : SharedIdCardSystem
return true;
}
public bool TryChangeVisuals(EntityUid uid, string jobIconName, IdCardComponent? id = null)
{
if (!Resolve(uid, ref id))
return false;
var name = jobIconName.Replace("JobIcon", "");
_sharedAppearance.SetData(uid, IdVisuals.State, name);
return true;
}
public bool TryChangeJobDepartment(EntityUid uid, JobPrototype job, IdCardComponent? id = null)
{
if (!Resolve(uid, ref id))

View File

@@ -30,17 +30,26 @@ namespace Content.Server.Chemistry.EntitySystems
[Dependency] private readonly ReactiveSystem _reactive = default!;
private const float ReactTime = 0.125f;
private readonly HashSet<(EntityUid, EntityUid)> _processed = new (); // WD edit
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<VaporComponent, StartCollideEvent>(HandleCollide);
SubscribeLocalEvent<VaporComponent, ComponentRemove>(OnDespawn); // WD edit
}
private void HandleCollide(Entity<VaporComponent> entity, ref StartCollideEvent args)
{
if (!EntityManager.TryGetComponent(entity.Owner, out SolutionContainerManagerComponent? contents)) return;
if (!EntityManager.TryGetComponent(entity.Owner, out SolutionContainerManagerComponent? contents))
return;
// WD edit start
var collisionPair = (entity.Owner, args.OtherEntity);
if (_processed.Contains(collisionPair))
return;
// WD edit end
foreach (var (_, soln) in _solutionContainerSystem.EnumerateSolutions((entity.Owner, contents)))
{
@@ -48,6 +57,8 @@ namespace Content.Server.Chemistry.EntitySystems
_reactive.DoEntityReaction(args.OtherEntity, solution, ReactionMethod.Touch);
}
_processed.Add(collisionPair); // WD edit
// Check for collision with a impassable object (e.g. wall) and stop
if ((args.OtherFixture.CollisionLayer & (int) CollisionGroup.Impassable) != 0 && args.OtherFixture.Hard)
{
@@ -55,6 +66,12 @@ namespace Content.Server.Chemistry.EntitySystems
}
}
// WD edit
private void OnDespawn(Entity<VaporComponent> entity, ref ComponentRemove args)
{
_processed.RemoveWhere(pair => pair.Item1 == entity.Owner);
}
public void Start(Entity<VaporComponent> vapor, TransformComponent vaporXform, Vector2 dir, float speed, MapCoordinates target, float aliveTime, EntityUid? user = null)
{
vapor.Comp.Active = true;

View File

@@ -1,3 +1,4 @@
using Content.Server.Body.Components;
using Content.Server.Body.Systems;
using Content.Shared.Chemistry.Components;
using Content.Shared.Devour;
@@ -15,6 +16,7 @@ public sealed class DevourSystem : SharedDevourSystem
base.Initialize();
SubscribeLocalEvent<DevourerComponent, DevourDoAfterEvent>(OnDoAfter);
SubscribeLocalEvent<DevourerComponent, BeingGibbedEvent>(OnGibContents);
}
private void OnDoAfter(EntityUid uid, DevourerComponent component, DevourDoAfterEvent args)
@@ -45,5 +47,15 @@ public sealed class DevourSystem : SharedDevourSystem
_audioSystem.PlayPvs(component.SoundDevour, uid);
}
private void OnGibContents(EntityUid uid, DevourerComponent component, ref BeingGibbedEvent args)
{
if (!component.ShouldStoreDevoured)
return;
// For some reason we have two different systems that should handle gibbing,
// and for some another reason GibbingSystem, which should empty all containers, doesn't get involved in this process
ContainerSystem.EmptyContainer(component.Stomach);
}
}

View File

@@ -1,7 +1,9 @@
using Content.Server.Administration.Logs;
using Content.Server.Popups;
using Content.Shared.DoAfter;
using Content.Shared.Database;
using Content.Shared.Interaction.Events;
using Content.Shared.Popups;
using Content.Shared.Teleportation.Components;
using Content.Shared.Teleportation.Systems;
using Robust.Server.Audio;
@@ -18,6 +20,7 @@ public sealed class HandTeleporterSystem : EntitySystem
[Dependency] private readonly LinkedEntitySystem _link = default!;
[Dependency] private readonly AudioSystem _audio = default!;
[Dependency] private readonly SharedDoAfterSystem _doafter = default!;
[Dependency] private readonly PopupSystem _popup = default!;
/// <inheritdoc/>
public override void Initialize()
@@ -92,6 +95,16 @@ public sealed class HandTeleporterSystem : EntitySystem
}
else if (Deleted(component.SecondPortal))
{
if (xform.ParentUid != xform.GridUid) // Still, don't portal.
return;
if (!component.AllowPortalsOnDifferentGrids && xform.ParentUid != Transform(component.FirstPortal!.Value).ParentUid)
{
// Whoops. Fizzle time. Crime time too because yippee I'm not refactoring this logic right now (I started to, I'm not going to.)
FizzlePortals(uid, component, user, true);
return;
}
var timeout = EnsureComp<PortalTimeoutComponent>(user);
timeout.EnteredPortal = null;
component.SecondPortal = Spawn(component.SecondPortalPrototype, Transform(user).Coordinates);
@@ -100,23 +113,33 @@ public sealed class HandTeleporterSystem : EntitySystem
_audio.PlayPvs(component.NewPortalSound, uid);
}
else
{
FizzlePortals(uid, component, user, false);
}
}
private void FizzlePortals(EntityUid uid, HandTeleporterComponent component, EntityUid user, bool instability)
{
// Logging
var portalStrings = "";
portalStrings += ToPrettyString(component.FirstPortal!.Value);
portalStrings += ToPrettyString(component.FirstPortal);
if (portalStrings != "")
portalStrings += " and ";
portalStrings += ToPrettyString(component.SecondPortal!.Value);
portalStrings += ToPrettyString(component.SecondPortal);
if (portalStrings != "")
_adminLogger.Add(LogType.EntityDelete, LogImpact.Low, $"{ToPrettyString(user):player} closed {portalStrings} with {ToPrettyString(uid)}");
// Clear both portals
QueueDel(component.FirstPortal!.Value);
QueueDel(component.SecondPortal!.Value);
if (!Deleted(component.FirstPortal))
QueueDel(component.FirstPortal.Value);
if (!Deleted(component.SecondPortal))
QueueDel(component.SecondPortal.Value);
component.FirstPortal = null;
component.SecondPortal = null;
_audio.PlayPvs(component.ClearPortalsSound, uid);
}
if (instability)
_popup.PopupEntity(Loc.GetString("handheld-teleporter-instability-fizzle"), uid, user, PopupType.MediumCaution);
}
}

View File

@@ -29,6 +29,7 @@ using Content.Shared._White.Mood;
using Content.Shared.Cloning;
using Content.Shared.Mind;
using Content.Shared.NPC.Systems;
using Robust.Server.Containers;
using Robust.Server.Player;
namespace Content.Server._White.Cult.GameRule;
@@ -50,6 +51,7 @@ public sealed class CultRuleSystem : GameRuleSystem<CultRuleComponent>
[Dependency] private readonly IPlayerManager _playerManager = default!;
[Dependency] private readonly GulagSystem _gulag = default!;
[Dependency] private readonly BloodSpearSystem _bloodSpear = default!;
[Dependency] private readonly ContainerSystem _container = default!;
private const int PlayerPerCultist = 10;
private int _minStartingCultists;
@@ -160,22 +162,18 @@ public sealed class CultRuleSystem : GameRuleSystem<CultRuleComponent>
private void OnCultistComponentInit(EntityUid uid, CultistComponent component, ComponentInit args)
{
RaiseLocalEvent(uid, new MoodEffectEvent("CultFocused"));
var query = QueryActiveRules();
while (query.MoveNext(out _, out var cult, out _))
{
if (!TryComp<MindContainerComponent>(uid, out var mindComponent))
return;
if (!mindComponent.HasMind)
return;
cult.CurrentCultists.Add(component);
var name = Name(uid);
if (TryComp<ActorComponent>(uid, out var actor) && !cult.CultistsCache.ContainsKey(name))
if (TryComp<ActorComponent>(uid, out var actor))
{
cult.CultistsCache.Add(name, actor.PlayerSession.Name);
cult.CultistsCache.TryAdd(name, actor.PlayerSession.Name);
}
UpdateCultistsAppearance(cult);
@@ -203,6 +201,14 @@ public sealed class CultRuleSystem : GameRuleSystem<CultRuleComponent>
while (query.MoveNext(out _, out var cult, out _))
{
cult.CurrentCultists.Remove(component);
}
if (!TerminatingOrDeleted(uid))
{
RemoveAllCultistItems(uid);
RemoveCultistAppearance(uid);
RaiseLocalEvent(uid, new MoodRemoveEffectEvent("CultFocused"));
}
_bloodSpear.DetachSpearFromUser((uid, component));
@@ -211,10 +217,8 @@ public sealed class CultRuleSystem : GameRuleSystem<CultRuleComponent>
_actions.RemoveAction(uid, GetEntity(empower));
}
RemoveCultistAppearance(uid);
CheckRoundShouldEnd();
}
}
private void OnCultistsStateChanged(EntityUid uid, CultistComponent component, MobStateChangedEvent ev)
{
@@ -422,8 +426,6 @@ public sealed class CultRuleSystem : GameRuleSystem<CultRuleComponent>
_factionSystem.RemoveFaction(cultist, "NanoTrasen", false);
_factionSystem.AddFaction(cultist, "Cultist");
RaiseLocalEvent(cultist, new MoodEffectEvent("CultFocused"));
if (_inventorySystem.TryGetSlotEntity(cultist, "back", out var backPack))
{
foreach (var itemPrototype in rule.StartingItems)
@@ -442,6 +444,20 @@ public sealed class CultRuleSystem : GameRuleSystem<CultRuleComponent>
return true;
}
private void RemoveAllCultistItems(EntityUid uid)
{
if (!_inventorySystem.TryGetContainerSlotEnumerator(uid, out var enumerator))
return;
while (enumerator.MoveNext(out var container))
{
if (container.ContainedEntity != null && HasComp<CultItemComponent>(container.ContainedEntity.Value))
{
_container.Remove(container.ContainedEntity.Value, container, true, true);
}
}
}
public void TransferRole(EntityUid transferFrom, EntityUid transferTo)
{
if (HasComp<PentagramComponent>(transferFrom))

View File

@@ -1,18 +1,11 @@
using System.Threading;
using Content.Server._White.Cult.GameRule;
using Content.Server.Objectives.Components;
using Content.Server.Popups;
using Content.Server.Roles;
using Content.Server.Stunnable;
using Content.Shared.Chemistry.Reagent;
using Content.Shared.IdentityManagement;
using Content.Shared.Inventory;
using Content.Shared._White.Cult.Components;
using Content.Shared._White.Mood;
using Content.Shared.Jittering;
using Content.Shared.Mind;
using JetBrains.Annotations;
using Robust.Server.Containers;
using Robust.Shared.Prototypes;
using CultistComponent = Content.Shared._White.Cult.Components.CultistComponent;
using Timer = Robust.Shared.Timing.Timer;
@@ -60,26 +53,10 @@ public sealed partial class DeconvertCultist : ReagentEffect
cultist.HolyConvertToken = null;
var inventory = entityManager.System<InventorySystem>();
var containerSystem = entityManager.System<ContainerSystem>();
if (!inventory.TryGetContainerSlotEnumerator(uid, out var enumerator))
return;
while (enumerator.MoveNext(out var container))
{
if (container.ContainedEntity != null &&
entityManager.HasComponent<CultItemComponent>(container.ContainedEntity.Value))
{
containerSystem.Remove(container.ContainedEntity.Value, container, true, true);
}
}
entityManager.RemoveComponent<CultistComponent>(uid);
entityManager.RemoveComponent<PentagramComponent>(uid);
var cultRuleSystem = entityManager.System<CultRuleSystem>();
cultRuleSystem.RemoveObjectiveAndRole(uid);
entityManager.EventBus.RaiseLocalEvent(uid, new MoodRemoveEffectEvent("CultFocused"));
}
}

View File

@@ -10,4 +10,7 @@ public sealed partial class CultRobeModifierComponent : Component
public string DamageModifierSetId = "CultRobe";
public string? StoredDamageSetId { get; set; }
[ViewVariables]
public bool Active;
}

View File

@@ -29,18 +29,22 @@ public sealed class CultRobeModifierSystem : EntitySystem
if (args.Slot != "outerClothing")
return;
component.Active = true;
ModifySpeed(args.Equipee, component, true);
ModifyDamage(args.Equipee, component, true);
}
private void OnUnequip(EntityUid uid, CultRobeModifierComponent component, GotUnequippedEvent args)
{
if (!HasComp<CultistComponent>(args.Equipee))
if (!component.Active)
return;
if (args.Slot != "outerClothing")
return;
component.Active = false;
ModifySpeed(args.Equipee, component, false);
ModifyDamage(args.Equipee, component, false);
}

View File

@@ -0,0 +1,24 @@
using Content.Server.Power.Components;
using Content.Shared._White.Lighting;
using Content.Shared._White.Lighting.PointLight.Airlock;
using Content.Shared.Doors.Components;
namespace Content.Server._White.Lighting.Pointlight.Airlock;
public sealed class PointLightAirlockSystem : EntitySystem
{
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<PointLightAirlockComponent, PowerChangedEvent>(OnPowerChanged);
}
private void OnPowerChanged(EntityUid uid, PointLightAirlockComponent component, PowerChangedEvent args)
{
if (!TryComp<DoorComponent>(uid, out var door))
return;
RaiseLocalEvent(uid, new DoorlightsChangedEvent(args.Powered ? door.State : null, args.Powered), true);
}
}

View File

@@ -1,4 +1,4 @@
namespace Content.Server._White.Lighting;
namespace Content.Server._White.Lighting.Pointlight.Battery;
[RegisterComponent]
public sealed partial class PointLightBatteryComponent : Component

View File

@@ -1,8 +1,10 @@
using Content.Shared.Lightning;
using Content.Server.Power.Components;
using Content.Shared.Lightning;
using Content.Shared.PowerCell;
using Content.Shared.PowerCell.Components;
using Content.Shared.Weapons.Ranged.Components;
namespace Content.Server._White.Lighting;
namespace Content.Server._White.Lighting.Pointlight.Battery;
public sealed class PointLightBatterySystem : SharedLightningSystem
{
@@ -12,6 +14,7 @@ public sealed class PointLightBatterySystem : SharedLightningSystem
{
base.Initialize();
SubscribeLocalEvent<PointLightBatteryComponent, PowerCellChangedEvent>(OnBatteryLoose);
SubscribeLocalEvent<PointLightBatteryComponent, ChargeChangedEvent>(OnBatteryChargeChanged);
}
private void OnBatteryLoose(EntityUid uid, PointLightBatteryComponent component, PowerCellChangedEvent args)
@@ -27,4 +30,18 @@ public sealed class PointLightBatterySystem : SharedLightningSystem
RaiseLocalEvent(uid, new PointLightToggleEvent(isBatteryCharged && !args.Ejected), true);
}
private void OnBatteryChargeChanged(EntityUid uid, PointLightBatteryComponent component, ChargeChangedEvent args)
{
if (!component.RequireBattery)
return;
if (!_pointLightSystem.TryGetLight(uid, out var pointLightComponent))
return;
var isBatteryCharged = TryComp<ProjectileBatteryAmmoProviderComponent>(uid, out var projectileBattery) && projectileBattery.Shots > 0;
_pointLightSystem.SetEnabled(uid, isBatteryCharged, pointLightComponent);
RaiseLocalEvent(uid, new PointLightToggleEvent(isBatteryCharged), true);
}
}

View File

@@ -0,0 +1,63 @@
using Content.Server.Power.Components;
using Content.Shared.PowerCell;
using Content.Shared.Rounding;
namespace Content.Server._White.Lighting.PointLight.RealBattery;
public sealed class PointLightRealBatterySystem : EntitySystem
{
[Dependency] private readonly SharedPointLightSystem _pointLightSystem = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<PointLightRealBatteryComponent, ChargeChangedEvent>(OnChargeChanged);
SubscribeLocalEvent<PointLightRealBatteryComponent, ComponentInit>(OnComponentInit);
}
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, PointLightRealBatteryComponent component, ComponentInit args)
{
if (!TryComp<BatteryComponent>(uid, out var battery))
return;
var ev = new ChargeChangedEvent(battery.CurrentCharge, battery.MaxCharge);
RaiseLocalEvent(uid, ref ev);
}
public void OnChargeChanged(EntityUid uid, PointLightRealBatteryComponent component, ChargeChangedEvent args)
{
var frac = args.Charge / args.MaxCharge;
var level = (byte) ContentHelpers.RoundToNearestLevels(frac, 1, PowerCellComponent.PowerCellVisualsLevels);
switch (level)
{
case 2:
ToggleLight(uid, component.GreenColor);
break;
case 1:
ToggleLight(uid, component.YellowColor);
break;
case 0:
ToggleLight(uid, string.Empty, false);
break;
}
}
}

View File

@@ -0,0 +1,15 @@
namespace Content.Server._White.Lighting.PointLight.RealBattery;
[RegisterComponent]
public sealed partial class PointLightRealBatteryComponent : Component
{
[DataField, ViewVariables]
public string RedColor = "#D56C6C";
[DataField, ViewVariables]
public string GreenColor = "#7FC080";
[DataField, ViewVariables]
public string YellowColor = "#BDC07F";
}

View File

@@ -1,4 +1,5 @@
using System.Diagnostics.CodeAnalysis;
using Content.Shared._White.Telescope;
using Content.Shared._White.WeaponModules;
using Content.Shared.Weapons.Ranged.Components;
using Content.Shared.Weapons.Ranged.Systems;
@@ -11,7 +12,7 @@ public sealed class WeaponModulesSystem : EntitySystem
{
protected static readonly Dictionary<string, Enum> Slots = new()
{
{ "handguard_module", ModuleVisualState.HandGuardModule }, { "barrel_module", ModuleVisualState.BarrelModule }
{ "handguard_module", ModuleVisualState.HandGuardModule }, { "barrel_module", ModuleVisualState.BarrelModule }, { "aim_module", ModuleVisualState.AimModule }
};
[Dependency] private readonly PointLightSystem _lightSystem = default!;
@@ -36,6 +37,9 @@ public sealed class WeaponModulesSystem : EntitySystem
SubscribeLocalEvent<AcceleratorModuleComponent, EntGotInsertedIntoContainerMessage>(AcceleratorModuleOnInsert);
SubscribeLocalEvent<AcceleratorModuleComponent, EntGotRemovedFromContainerMessage>(AcceleratorModuleOnEject);
SubscribeLocalEvent<AimModuleComponent, EntGotInsertedIntoContainerMessage>(EightAimModuleOnInsert);
SubscribeLocalEvent<AimModuleComponent, EntGotRemovedFromContainerMessage>(EightAimModuleOnEject);
}
private bool TryInsertModule(EntityUid module, EntityUid weapon, BaseModuleComponent component,
@@ -154,6 +158,18 @@ public sealed class WeaponModulesSystem : EntitySystem
_gunSystem.SetFireRate(weapon, component.OldFireRate + component.FireRateAdd);
}
private void EightAimModuleOnInsert(EntityUid module, AimModuleComponent component, EntGotInsertedIntoContainerMessage args)
{
EntityUid weapon = args.Container.Owner;
if (!TryComp<GunComponent>(weapon, out var gunComp)) return;
if(!TryInsertModule(module, weapon, component, args.Container.ID, out var weaponModulesComponent))
return;
EnsureComp<TelescopeComponent>(weapon).Divisor = component.Divisor;
}
#endregion
#region EjectModules
@@ -213,5 +229,15 @@ public sealed class WeaponModulesSystem : EntitySystem
_gunSystem.SetFireRate(weapon, component.OldFireRate);
}
private void EightAimModuleOnEject(EntityUid module, AimModuleComponent component, EntGotRemovedFromContainerMessage args)
{
EntityUid weapon = args.Container.Owner;
if(!TryEjectModule(module, weapon, args.Container.ID, out var weaponModulesComponent))
return;
RemComp<TelescopeComponent>(weapon);
}
#endregion
}

View File

@@ -1,5 +1,6 @@
using System.Linq;
using System.Numerics;
using Content.Server._White.Cult;
using Content.Server._White.IncorporealSystem;
using Content.Server._White.Wizard.Magic.Amaterasu;
using Content.Server._White.Wizard.Magic.Other;
@@ -24,7 +25,6 @@ using Content.Shared._White.Wizard;
using Content.Shared._White.Wizard.Magic;
using Content.Shared.Actions;
using Content.Shared.Borer;
using Content.Shared.Changeling;
using Content.Shared.Cluwne;
using Content.Shared.Coordinates.Helpers;
using Content.Shared.Hands.Components;
@@ -36,6 +36,7 @@ using Content.Shared.Inventory.VirtualItem;
using Content.Shared.Item;
using Content.Shared.Magic;
using Content.Shared.Maps;
using Content.Shared.Mobs;
using Content.Shared.Mobs.Components;
using Content.Shared.Physics;
using Content.Shared.Popups;
@@ -85,6 +86,7 @@ public sealed class WizardSpellsSystem : EntitySystem
{
base.Initialize();
SubscribeLocalEvent<StopTimeSpellEvent>(OnTimeStop);
SubscribeLocalEvent<MindswapSpellEvent>(OnMindswapSpell);
SubscribeLocalEvent<TeleportSpellEvent>(OnTeleportSpell);
SubscribeLocalEvent<InstantRecallSpellEvent>(OnInstantRecallSpell);
@@ -103,6 +105,25 @@ public sealed class WizardSpellsSystem : EntitySystem
SubscribeLocalEvent<MagicComponent, BeforeCastSpellEvent>(OnBeforeCastSpell);
}
#region Timestop
private void OnTimeStop(StopTimeSpellEvent msg)
{
if (!CanCast(msg))
return;
var ent = Spawn(msg.Prototype, Transform(msg.Performer).Coordinates);
_transformSystem.AttachToGridOrMap(ent);
var comp = EnsureComp<PreventCollideComponent>(ent);
comp.Uid = msg.Performer;
msg.Handled = true;
Speak(msg);
}
#endregion
#region Mindswap
private void OnMindswapSpell(MindswapSpellEvent msg)
@@ -113,17 +134,12 @@ public sealed class WizardSpellsSystem : EntitySystem
var target = msg.Target;
var uid = msg.Performer;
if (HasComp<ChangelingComponent>(target) || HasComp<RevolutionaryComponent>(target) ||
HasComp<CultistComponent>(target))
{
_popupSystem.PopupEntity("Не работает на культистов, генокрадов и революционеров.", uid, uid,
PopupType.MediumCaution);
if (!TryComp(target, out MobStateComponent? mobState) || mobState.CurrentState != MobState.Alive)
return;
}
if (TryComp(target, out InfestedBorerComponent? borer) && borer.ControllingBrain)
{
_popupSystem.PopupEntity("Им уже кто-то управляет.", uid, uid, PopupType.MediumCaution);
_popupSystem.PopupEntity(Loc.GetString("mindswap-borer-failed"), uid, uid, PopupType.MediumCaution);
return;
}
@@ -138,7 +154,7 @@ public sealed class WizardSpellsSystem : EntitySystem
if (targetHasMind)
{
_mindSystem.TransferTo(targetMindId, uid, mind: targetMind);
_popupSystem.PopupEntity(Loc.GetString("Ваш разум подменили!"), uid, uid, PopupType.LargeCaution);
_popupSystem.PopupEntity(Loc.GetString("mindswap-success"), uid, uid, PopupType.LargeCaution);
}
TransferAllMagicActions(uid, target);
@@ -149,23 +165,11 @@ public sealed class WizardSpellsSystem : EntitySystem
msg.Handled = true;
Speak(msg);
var hasWiz = HasComp<WizardComponent>(uid);
var targetHasWiz = HasComp<WizardComponent>(target);
if (hasWiz == targetHasWiz)
return;
if (hasWiz)
{
RemComp<WizardComponent>(uid);
EnsureComp<WizardComponent>(target);
}
if (targetHasWiz)
{
RemComp<WizardComponent>(target);
EnsureComp<WizardComponent>(uid);
}
SwapComponent<WizardComponent>(uid, target);
SwapComponent<RevolutionaryComponent>(uid, target);
SwapComponent<HeadRevolutionaryComponent>(uid, target);
SwapComponent<PentagramComponent>(uid, target);
SwapComponent<CultistComponent>(uid, target);
}
#endregion
@@ -919,5 +923,26 @@ public sealed class WizardSpellsSystem : EntitySystem
}
}
private void SwapComponent<T>(EntityUid uid1, EntityUid uid2) where T : Component, new()
{
var hasComp = HasComp<T>(uid1);
var targetHasComp = HasComp<T>(uid2);
if (hasComp == targetHasComp)
return;
if (hasComp)
{
EnsureComp<T>(uid2);
RemComp<T>(uid1);
}
if (targetHasComp)
{
EnsureComp<T>(uid1);
RemComp<T>(uid2);
}
}
#endregion
}

View File

@@ -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
{

View File

@@ -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
{
}

View File

@@ -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;
}

View 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);

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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";

View File

@@ -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)

View 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;
}
}

View File

@@ -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";
}

View File

@@ -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;
}
}
}

View File

@@ -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;
}

View File

@@ -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);
}
}

View File

@@ -0,0 +1,9 @@
using Robust.Shared.Serialization;
namespace Content.Shared._White.NiceIdCards;
[Serializable, NetSerializable]
public enum IdVisuals : byte
{
State
}

View File

@@ -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;
}

View File

@@ -2,7 +2,6 @@
namespace Content.Shared._White.WeaponModules;
[RegisterComponent, NetworkedComponent]
public partial class BaseModuleComponent : Component
{

View File

@@ -1,8 +1,5 @@
namespace Content.Shared._White.WeaponModules;
/// <summary>
/// This is used for...
/// </summary>
[RegisterComponent]
public sealed partial class FlameHiderModuleComponent : BaseModuleComponent
{

View File

@@ -20,7 +20,8 @@ public partial class WeaponModulesComponent : Component
public enum ModuleVisualState : byte
{
BarrelModule,
HandGuardModule
HandGuardModule,
AimModule
}
[Serializable, NetSerializable]

View File

@@ -0,0 +1,8 @@
using Robust.Shared.GameStates;
namespace Content.Shared._White.Wizard.Timestop;
[RegisterComponent, NetworkedComponent]
public sealed partial class FreezeContactsComponent : Component
{
}

View 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>);
}
}

View 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;
}

View File

@@ -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

Binary file not shown.

View File

@@ -4601,3 +4601,187 @@
id: 313
time: '2024-06-19T15:59:59.0000000+00:00'
url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/367
- author: Aviu
changes:
- message: "\u0422\u0435\u043F\u0435\u0440\u044C \u043C\u044B\u0448\u044C \u0432\
\ \u043A\u043E\u043B\u043F\u0430\u043A\u0435 \u043C\u043E\u0436\u0435\u0442\
\ \u0443\u043F\u0440\u0430\u0432\u043B\u044F\u0442\u044C \u043D\u043E\u0441\u0438\
\u0442\u0435\u043B\u0435\u043C."
type: Add
- message: "\u041A\u043E\u0440\u043E\u043B\u044C \u043A\u0440\u044B\u0441 \u0442\
\u0435\u043F\u0435\u0440\u044C \u043B\u0435\u0447\u0438\u0442 \u043A\u0440\u043E\
\u0432\u043E\u043F\u043E\u0442\u0435\u0440\u044E \u043E\u0442 \u043C\u0438\u0430\
\u0437\u043C\u044B."
type: Add
- message: "\u0421\u044A\u0435\u0434\u0435\u043D\u043D\u044B\u0435 \u0434\u0440\u0430\
\u043A\u043E\u043D\u043E\u043C \u0442\u0440\u0443\u043F\u044B \u0432\u044B\u043F\
\u0430\u0434\u0430\u044E\u0442 \u043F\u0440\u0438 \u0440\u0430\u0437\u0434\u0435\
\u043B\u043A\u0435."
type: Fix
- message: "\u0411\u043E\u043B\u044C\u0448\u0435 \u043D\u0435\u043B\u044C\u0437\u044F\
\ \u0441\u0442\u0430\u0432\u0438\u0442\u044C \u043F\u043E\u0440\u0442\u0430\u043B\
\ \u043D\u0430 \u0440\u0430\u0437\u043D\u044B\u0445 \u0433\u0440\u0438\u0434\
\u0430\u0445."
type: Fix
id: 314
time: '2024-06-20T16:24:36.0000000+00:00'
url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/371
- author: Aviu
changes:
- message: "\u0417\u0430\u043A\u043B\u0438\u043D\u0430\u043D\u0438\u0435 \u043E\u0441\
\u0442\u0430\u043D\u043E\u0432\u043A\u0438 \u0432\u0440\u0435\u043C\u0435\u043D\
\u0438."
type: Add
- message: "\u0422\u0435\u043F\u0435\u0440\u044C \u0437\u0430\u043A\u043B\u0438\u043D\
\u0430\u043D\u0438\u0435 \u043F\u0435\u0440\u0435\u043D\u043E\u0441\u0430 \u0441\
\u043E\u0437\u043D\u0430\u043D\u0438\u044F \u0440\u0430\u0431\u043E\u0442\u0430\
\u0435\u0442 \u043D\u0430 \u043A\u0443\u043B\u044C\u0442\u0438\u0441\u0442\u043E\
\u0432, \u0433\u0435\u043D\u043E\u043A\u0440\u0430\u0434\u043E\u0432 \u0438\
\ \u0440\u0435\u0432\u043E\u043B\u044E\u0446\u0438\u043E\u043D\u0435\u0440\u043E\
\u0432."
type: Tweak
id: 315
time: '2024-06-20T16:24:10.0000000+00:00'
url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/370
- author: RinKeeper
changes:
- message: "\u0418\u0437\u043C\u0435\u043D\u0435\u043D \u0440\u0435\u0446\u0435\u043F\
\u0442 \u0441\u0438\u043D\u0442\u0435\u043F\u043B\u043E\u0442\u0438, \u0430\
\ \u0442\u0430\u043A\u0436\u0435 \u0440\u0435\u0430\u0433\u0435\u043D\u0442\u044B\
\ \u0442\u0435\u043F\u0435\u0440\u044C \u043D\u0443\u0436\u043D\u043E \u0440\
\u0430\u0437\u043E\u0433\u0440\u0435\u0432\u0430\u0442\u044C"
type: Fix
- message: "\u0422\u0435\u043F\u0435\u0440\u044C \u0432 \u043F\u0440\u0438\u043D\
\u0442\u0435\u0440\u0435 \u0443\u043D\u0438\u0444\u043E\u0440\u043C\u044B \u0435\
\u0441\u0442\u044C \u043D\u0435\u0431\u0435\u0441\u043D\u043E-\u0433\u043E\u043B\
\u0443\u0431\u043E\u0439 \u043A\u043E\u0432\u0451\u0440"
type: Fix
- message: "\u041E\u0433\u043D\u0435\u0442\u0443\u0448\u0438\u0442\u0435\u043B\u044C\
\ \u0438 \u043F\u043E\u0434\u043E\u0431\u043D\u044B\u0435 \u0435\u043C\u0443\
\ \u0442\u0435\u043F\u0435\u0440\u044C \u043D\u0435 \u043C\u043E\u0433\u0443\
\u0442 \u0437\u0430 1 \u043F\u0440\u044B\u0441\u043A \u043F\u0440\u0438\u043C\
\u0435\u043D\u0438\u0442\u044C \u044D\u0444\u0444\u0435\u043A\u0442 \u0434\u0432\
\u0430\u0436\u0434\u044B \u0438\u043B\u0438 \u0442\u0440\u0438\u0436\u0434\u044B"
type: Fix
- message: "\u0422\u0435\u043F\u0435\u0440\u044C \u043F\u0440\u0435\u0434\u043C\u0435\
\u0442\u044B \u0432 \u043F\u043E\u043B\u0435\u0442\u0435 \u043D\u0435 \u0441\
\u0440\u0430\u0431\u0430\u0442\u044B\u0432\u0430\u044E\u0442 \u0431\u043E\u043B\
\u044C\u0448\u0435 1 \u0440\u0430\u0437\u0430"
type: Fix
- message: "\u0441 \u043F\u043E\u043C\u043E\u0449\u044C\u044E \u043A\u043E\u043C\
\u0430\u043D\u0434\u044B showmanifest \u0442\u0435\u043F\u0435\u0440\u044C \u043C\
\u043E\u0436\u043D\u043E \u043F\u043E\u0441\u043C\u043E\u0442\u0440\u0435\u0442\
\u044C \u043C\u0430\u043D\u0438\u0444\u0435\u0441\u0442 \u043F\u043E\u0441\u043B\
\u0435 \u0440\u0430\u0443\u043D\u0434\u0430 \u0434\u0430\u0436\u0435 \u0435\u0441\
\u043B\u0438 \u0432\u044B \u0435\u0433\u043E \u0437\u0430\u043A\u0440\u044B\u043B\
\u0438"
type: Add
id: 316
time: '2024-06-20T19:29:43.0000000+00:00'
url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/343
- author: ThereDrD
changes:
- message: "\u0423\u043B\u0443\u0447\u0448\u0435\u043D \u0438\u043D\u0442\u0435\u0440\
\u0444\u0435\u0439\u0441 \u043A\u043E\u043D\u0441\u043E\u043B\u0438 \u0425\u043E\
\u041F\u0430, \u0442\u0435\u043F\u0435\u0440\u044C \u0434\u043E\u0441\u0442\u0443\
\u043F\u044B \u0438 \u0438\u043A\u043E\u043D\u043A\u0438 \u043E\u0442\u0441\u043E\
\u0440\u0442\u0438\u0440\u043E\u0432\u0430\u043D\u044B \u043F\u043E \u043E\u0442\
\u0434\u0435\u043B\u0430\u043C \u0438 \u043F\u043E \u0432\u0430\u0436\u043D\u043E\
\u0441\u0442\u0438, \u0433\u0434\u0435 \u044D\u0442\u043E \u0432\u043E\u0437\
\u043C\u043E\u0436\u043D\u043E"
type: Add
- message: "\u0422\u0435\u043F\u0435\u0440\u044C \u043A\u043E\u043D\u0441\u043E\u043B\
\u044C \u0425\u043E\u041F\u0430 \u043C\u0435\u043D\u044F\u0435\u0442 \u0438\u043A\
\u043E\u043D\u043A\u0443 \u043D\u0430 \u0441\u043F\u0440\u0430\u0439\u0442\u0435\
\ \u043A\u0430\u0440\u0442\u043E\u0447\u043A\u0438, \u0435\u0441\u043B\u0438\
\ \u043F\u043E\u0441\u0442\u0430\u0432\u0438\u0442\u044C \u0441\u043E\u043E\u0442\
\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044E\u0449\u0438\u0439 \u043F\u0440\
\u0435\u0441\u0435\u0442."
type: Add
- message: "\u0422\u0435\u043F\u0435\u0440\u044C \u043F\u0440\u0435\u0441\u0435\u0442\
\u044B \u0432 \u043A\u043E\u043D\u0441\u043E\u043B\u0438 \u0425\u043E\u041F\u0430\
\ \u0432\u044B\u0441\u0442\u0430\u0432\u043B\u044F\u044E\u0442\u0441\u044F \u043F\
\u043E \u043D\u0430\u0436\u0430\u0442\u0438\u044E \u0438\u043A\u043E\u043D\u043A\
\u0438, \u0430 \u043D\u0435 \u043A\u043D\u043E\u043F\u043A\u0438 \u0438\u0437\
\ \u0432\u044B\u043F\u0430\u0434\u0430\u044E\u0449\u0435\u0433\u043E \u0441\u043F\
\u0438\u0441\u043A\u0430"
type: Tweak
- message: "\u0412\u044B\u043F\u0430\u0434\u0430\u044E\u0449\u0438\u0439 \u0441\u043F\
\u0438\u0441\u043E\u043A \u0432 \u043A\u043E\u043D\u0441\u043E\u043B\u0438 \u0425\
\u043E\u041F\u0430. \u041E\u043D \u043E\u0442\u0432\u0440\u0430\u0442\u0438\u0442\
\u0435\u043B\u0435\u043D."
type: Remove
id: 317
time: '2024-06-20T19:29:26.0000000+00:00'
url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/369
- author: ThereDrD
changes:
- message: "\u0414\u043E\u0441\u0442\u0443\u043F \u043A\u0432\u0430\u0440\u0442\u0438\
\u0440\u043C\u0430\u0441\u0442\u0435\u0440\u0430 \u0441\u043D\u043E\u0432\u0430\
\ \u0435\u0441\u0442\u044C \u0432 \u043A\u043E\u043D\u0441\u043E\u043B\u0438\
\ \u0445\u043E\u043F\u0430"
type: Fix
id: 318
time: '2024-06-20T21:18:50.0000000+00:00'
url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/372
- author: ThereDrD
changes:
- message: "\u0428\u043B\u044E\u0437\u044B \u0442\u0435\u043F\u0435\u0440\u044C\
\ \u0438\u043C\u0435\u044E\u0442 \u0441\u0432\u0435\u0447\u0435\u043D\u0438\u0435\
, \u0437\u0430\u0432\u0438\u0441\u0438\u043C\u043E\u0435 \u043E\u0442 \u0435\
\u0433\u043E \u0441\u043E\u0441\u0442\u043E\u044F\u043D\u0438\u044F"
type: Add
- message: "\u041E\u0440\u0443\u0436\u0438\u0435 \u0442\u0435\u043F\u0435\u0440\u044C\
\ \u0438\u043C\u0435\u0435\u0442 \u0441\u0432\u0435\u0447\u0435\u043D\u0438\u0435\
, \u0437\u0430\u0432\u0438\u0441\u0438\u043C\u043E\u0435 \u043E\u0442 \u043F\
\u043E\u0434\u0441\u0432\u0435\u0442\u043A\u0438 \u043D\u0430 \u0442\u0435\u043A\
\u0441\u0442\u0443\u0440\u0435 \u0438 \u0441\u0442\u0435\u043F\u0435\u043D\u0438\
\ \u0437\u0430\u0440\u044F\u0434\u043A\u0438"
type: Add
- message: "\u0428\u043A\u0430\u0444\u0447\u0438\u043A\u0438 \u0442\u0435\u043F\u0435\
\u0440\u044C \u0438\u043C\u0435\u044E\u0442 \u0441\u0432\u0435\u0447\u0435\u043D\
\u0438\u0435, \u0437\u0430\u0432\u0438\u0441\u0438\u043C\u043E\u0435 \u043E\u0442\
\ \u043F\u043E\u0434\u0441\u0432\u0435\u0442\u043A\u0438 \u043D\u0430 \u0442\
\u0435\u043A\u0441\u0442\u0443\u0440\u0435"
type: Add
- message: "\u0411\u0430\u0442\u0430\u0440\u0435\u0439\u043A\u0438 \u0438 \u043C\
\u0443\u043B\u044C\u0442\u0438\u0442\u0443\u043B \u0442\u0435\u043F\u0435\u0440\
\u044C \u0442\u043E\u0436\u0435 \u0441\u0432\u0435\u0442\u044F\u0442\u0441\u044F"
type: Add
- message: "\u041F\u0440\u043E\u0436\u0435\u043A\u0442\u0430\u0439\u043B\u044B \u043B\
\u0430\u0437\u0435\u0440\u043E\u0432, \u043A\u043E\u043D\u0441\u043E\u043B\u0438\
, \u0442\u043E\u0440\u0433\u043E\u0432\u044B\u0435 \u0430\u0432\u0442\u043E\u043C\
\u0430\u0442\u044B, \u044D\u043D\u0435\u0440\u0433\u043E\u043C\u0435\u0447\u0438\
, \u044D\u043D\u0435\u0440\u0433\u043E\u0449\u0438\u0442 \u0438 \u0441\u0432\
\u0435\u0442 \u043E\u0442 \u0432\u044B\u0441\u0442\u0440\u0435\u043B\u0430 \u0438\
\u0437 \u043E\u0440\u0443\u0436\u0438\u044F \u0442\u0435\u043F\u0435\u0440\u044C\
\ \u0438\u043C\u0435\u044E\u0442 \u043C\u0435\u043D\u0435\u0435 \u044F\u0434\
\u0440\u0435\u043D\u043E\u0435 \u0441\u0432\u0435\u0447\u0435\u043D\u0438\u0435\
."
type: Add
id: 319
time: '2024-06-21T03:15:55.0000000+00:00'
url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/316
- author: CaypenNow
changes:
- message: "\u0414\u043E\u0431\u0430\u0432\u043B\u0435\u043D \u043C\u043E\u0434\u0443\
\u043B\u044C\u043D\u044B\u0439 \u043F\u0440\u0438\u0446\u0435\u043B."
type: Add
- message: "\u0418\u0441\u043F\u0440\u0430\u0432\u043B\u0435\u043D\u0430 \u043E\u0448\
\u0438\u0431\u043A\u0430, \u0441\u0432\u044F\u0437\u0430\u043D\u043D\u0430\u044F\
\ \u0441 \u043C\u043E\u0434\u0443\u043B\u044F\u043C\u0438 \u0443 M-90gl."
type: Fix
id: 320
time: '2024-06-21T10:24:13.0000000+00:00'
url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/365
- author: ThereDrD
changes:
- message: "\u041A\u043E\u043D\u0441\u043E\u043B\u044C \u0425\u043E\u041F\u0430\
\ \u0441\u043D\u043E\u0432\u0430 \u043C\u043E\u0436\u0435\u0442 \u0432\u044B\
\u0434\u0430\u0442\u044C \u0434\u043E\u0441\u0442\u0443\u043F \u043F\u043E \u043D\
\u0430\u0436\u0430\u0442\u0438\u044E \u043A\u043D\u043E\u043F\u043A\u0438 \u0441\
\ \u0434\u043E\u0441\u0442\u0443\u043F\u043E\u043C"
type: Fix
id: 321
time: '2024-06-21T10:44:40.0000000+00:00'
url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/373

View File

@@ -5,7 +5,6 @@ id-card-console-window-save-button = Save
id-card-console-window-job-title-label = Job title:
id-card-console-window-eject-button = Eject
id-card-console-window-insert-button = Insert
id-card-console-window-job-selection-label = Job presets (sets department and job icon):
access-id-card-console-component-no-hands-error = You have no hands.
id-card-console-privileged-id = Privileged ID

View File

@@ -0,0 +1 @@
handheld-teleporter-instability-fizzle = The portal fizzles as you try to place it, destroying both ends!

View File

@@ -17,6 +17,7 @@ scroll-component-recall = призыв
scroll-component-teleport = телепортацию
scroll-component-smite = кару
scroll-component-mindswap = подмену сознания
scroll-component-timestop = остановку времени
ent-BaseScroll = магический свиток
.desc = Этот древний пергамент, ставший реликвией в арканных преданиях, хранит в себе бесчисленные мистические заклятия и забытые заклинания.
@@ -50,3 +51,7 @@ ent-ScrollTeleport = свиток телепортации
.desc = { ent-BaseScroll.desc }
ent-ScrollSmite = свиток кары
.desc = { ent-BaseScroll.desc }
ent-ScrollMindswap = свиток подмены сознания
.desc = { ent-BaseScroll.desc }
ent-ScrollTimestop = свиток остановки времени
.desc = { ent-BaseScroll.desc }

View File

@@ -43,6 +43,9 @@ spellbook-smite-desc = { ent-ActionSmite.desc }
spellbook-mindswap-name = { ent-ActionMindswapSpell }
spellbook-mindswap-desc = { ent-ActionMindswapSpell.desc }
spellbook-timestop-name = { ent-ActionTimestopSpell }
spellbook-timestop-desc = { ent-ActionTimestopSpell.desc }
spellbook-hardsuit-name = Скафандр волшебника
spellbook-hardsuit-desc = Украшенный магическими драгоценными камнями скафандр, функционирующий так же, как и обычная мантия волшебника, но в то же время является пригодным для использования в космосе и бронированным. Небольшое замедление. Теперь вы можете произносить заклинания в космосе и местах с низкой температурой! Имеет функцию энергетического щита,который защищает от всех снарядов. Щит разряжается при получении урона и автоматически заряжается.

View File

@@ -44,4 +44,7 @@ ent-ActionSmite = Кара
.desc = Заряжает вашу руку мерзкой энергией, которую можно использовать для взрыва жертв. Заклинание требует, чтобы вы коснулись своей цели, поэтому вы не сможете использовать его в наручниках или будучи оглушённым. Не работает без волшебной мантии и шляпы.
ent-ActionMindswapSpell = Подмена сознания
.desc = Позволяет заклинателю переключаться между телами с целью. Вы должны быть рядом с целью, в которую хотите перейти, после чего вы оба будете нокаутированы. Не работает на культистов, генокрадов и революционеров.
.desc = Позволяет заклинателю переключаться между телами с целью. Вы должны быть рядом с целью, в которую хотите перейти, после чего вы оба будете нокаутированы.
ent-ActionTimestopSpell = Остановка времени
.desc = Останавливает время в радиусе вокруг вас. Находящиеся под воздействием существа не смогут двигаться, а пролетающие мимо снаряды будут остановлены до окончания остановки времени. Не работает без волшебной мантии и шляпы.

View File

@@ -36,6 +36,9 @@ ent-ClothingOuterRealWizardFancy = мантия волшебника
ent-ClothingHeadHelmetWizardHelmArmored = шлем мага
.desc = Странный головной убор, который наверняка принадлежит настоящему магу. Не обладает свойствами волшебной шляпы.
mindswap-success = Ваш разум подменили!
mindswap-borer-failed = Его разумом кто-то управляет.
store-currency-display-spell-point = Очки заклинаний
store-category-spells-attack = Атакующие заклинания

View File

@@ -5,7 +5,6 @@ id-card-console-window-save-button = Сохранить
id-card-console-window-job-title-label = Должность:
id-card-console-window-eject-button = Извлечь
id-card-console-window-insert-button = Вставить
id-card-console-window-job-selection-label = Предустановки должностей (задает иконку отдела и должности):
access-id-card-console-component-no-hands-error = У вас нет рук.
id-card-console-privileged-id = Основной ID
id-card-console-target-id = Целевой ID

View File

@@ -285,6 +285,7 @@
- id: MagazinePistol
- id: BoxMindshield
- id: TagillaHammer
- id: EightAimModule
- type: entity
id: LockerFreezerVaultFilled
suffix: Vault, Locked

View File

@@ -250,6 +250,10 @@
- type: ContainerContainer
containers:
storagebase: !type:Container
- type: PilotedClothing
pilotWhitelist:
tags:
- ChefPilot
- type: Tag
tags:
- ClothMade

View File

@@ -1584,6 +1584,7 @@
tags:
- Trash
- VimPilot
- ChefPilot
- Mouse
- Meat
- type: Respirator
@@ -3065,6 +3066,7 @@
- type: Tag
tags:
- VimPilot
- ChefPilot
- Trash
- Hamster
- Meat

View File

@@ -594,6 +594,7 @@
- CannotSuicide
- Hamster
- VimPilot
- ChefPilot
- type: entity
name: Shiva

View File

@@ -24,6 +24,60 @@
- WhitelistChameleon
- type: StealTarget
stealGroup: IDCard
- type: Appearance
- type: GenericVisualizer
visuals:
enum.IdVisuals.State:
base:
Captain: { state: idcaptain }
HeadOfPersonnel: { state: idheadofpersonnel }
HeadOfSecurity: { state: idheadofsecurity }
ChiefMedicalOfficer: { state: idchiefmedicalofficer }
ChiefEngineer: { state: idchiefengineer }
ResearchDirector: { state: idresearchdirector }
QuarterMaster: { state: idquartermaster }
Lawyer: { state: idlawyer }
Clown: { state: idclown }
Bartender: { state: idbartender }
Reporter: { state: idreporter }
Chef: { state: idcook }
Botanist: { state: idbotanist }
ServiceWorker: { state: idintern-service }
Zookeeper: { state: idzookeeper }
Musician: { state: idmusician }
Librarian: { state: idcurator }
Janitor: { state: idjanitor }
Chaplain: { state: idchaplain }
Mime: { state: idmime }
Boxer: { state: idboxer }
Passenger: { state: idpassenger }
Visitor: { state: idpassenger }
Borg: { state: idunknown }
CustomId: { state: idunknown }
Warden: { state: idwarden }
SeniorOfficer: { state: idseniorofficer }
SecurityOfficer: { state: idsecurityofficer }
Detective: { state: iddetective }
SecurityCadet: { state: idintern-cadet }
Brigmedic: { state: idbrigmedic }
SeniorPhysician: { state: idseniorphysician }
Paramedic: { state: idparamedic }
Chemist: { state: idchemist }
MedicalDoctor: { state: idmedicaldoctor }
Virologist: { state: idvirologist }
Geneticist: { state: idgeneticist }
MedicalIntern: { state: idintern-med }
Psychologist: { state: idpsychologist }
SeniorEngineer: { state: idseniorengineer }
AtmosphericTechnician: { state: idatmospherictechnician }
StationEngineer: { state: idstationengineer }
TechnicalAssistant: { state: idintern-tech }
SeniorResearcher: { state: idseniorresearcher }
Scientist: { state: idscientist }
Roboticist: { state: idroboticist }
ResearchAssistant: { state: idintern-sci }
ShaftMiner: { state: idshaftminer }
CargoTechnician: { state: idcargotechnician }
#IDs with layers

View File

@@ -37,6 +37,12 @@
- type: ProjectileBatteryAmmoProvider
proto: BulletTrailLaserLight
fireCost: 50
- type: PointLight
enabled: false
color: "#7FC080"
radius: 1.05
energy: 0.3
- type: PointLightRealBattery
- type: entity
name: potato battery
@@ -57,6 +63,10 @@
- type: Construction
graph: PowerCellPotato
node: potatobattery
- type: PointLight
enabled: false
radius: 1 # Костыльный путь отрубить свет
energy: 1
- type: entity
name: small-capacity power cell
@@ -122,6 +132,7 @@
part: PowerCell
rating: 2
- type: entity
id: PowerCellMediumPrinted
suffix: Empty
@@ -301,6 +312,11 @@
walkModifier: 0.8
sprintModifier: 0.8
- type: HeldSpeedModifier
- type: PointLight
enabled: false
color: "#7FC080"
radius: 1.2
energy: 0.5
- type: entity
id: PowerCageSmall

View File

@@ -455,8 +455,8 @@
netsync: false
enabled: false
radius: 1.5
energy: 2
color: blue
energy: 0.7
color: "#678AD9"
- type: Reflect
enabled: false
reflectProb: 1

View File

@@ -272,6 +272,10 @@
Plastic: 100
- type: StaticPrice
price: 56
- type: PointLight
color: "#7FC080"
radius: 1.05
energy: 0.3
- type: entity
name: network configurator

View File

@@ -99,8 +99,11 @@
- type: Welder
- type: PointLight
enabled: false
radius: 1.5
radius: 1.4
energy: 0.5
color: orange
mask: /Textures/Effects/LightMasks/cone.png
autoRot: true
netsync: false
- type: Appearance
- type: RequiresEyeProtection
@@ -181,7 +184,11 @@
- type: PointLight
enabled: false
radius: 1.5
energy: 0.7
color: lightblue
mask: /Textures/Effects/LightMasks/cone.png
autoRot: true
netsync: false
- type: SolutionRegeneration
solution: Welder
generated:
@@ -213,5 +220,9 @@
speed: 0.7
- type: PointLight
enabled: false
radius: 1.0
radius: 0.9
energy: 0.5
color: orange
mask: /Textures/Effects/LightMasks/cone.png
autoRot: true
netsync: false

View File

@@ -1,3 +1,9 @@
# Colors for pointlight
# BDC07F - yellow
# 7FC080 - green
# C07F7F - red
# 7F93C0 - blue
- type: entity
id: BaseWeaponBattery
parent: BaseItem
@@ -132,6 +138,11 @@
magState: mag
steps: 5
zeroVisible: true
- type: PointLightBattery
- type: PointLight
radius: 1.3
energy: 0.15
color: "#BDC07F"
- type: entity
name: retro laser blaster
@@ -155,6 +166,11 @@
steps: 5
zeroVisible: true
- type: Appearance
- type: PointLightBattery
- type: PointLight
radius: 1.3
energy: 0.15
color: "#C07F7F"
- type: entity
name: makeshift laser pistol
@@ -175,6 +191,11 @@
- type: ProjectileBatteryAmmoProvider
proto: BulletTrailLaser
fireCost: 125
- type: PointLightBattery
- type: PointLight
radius: 1.3
energy: 0.15
color: "#7FC080"
- type: entity
name: tesla gun
@@ -230,6 +251,11 @@
- type: ProjectileBatteryAmmoProvider
proto: BulletTrailLaser
fireCost: 62.5
- type: PointLightBattery
- type: PointLight
radius: 1.3
energy: 0.15
color: "#7FC080"
- type: entity
name: practice laser rifle
@@ -265,6 +291,11 @@
- SemiAuto
soundGunshot:
path: /Audio/Weapons/Guns/Gunshots/laser_cannon.ogg
- type: PointLightBattery
- type: PointLight
radius: 1.3
energy: 0.15
color: "#7F93C0"
- type: ProjectileBatteryAmmoProvider
proto: PulseBoltProjectile
fireCost: 100
@@ -302,6 +333,11 @@
- FullAuto
soundGunshot:
path: /Audio/Weapons/Guns/Gunshots/laser_cannon.ogg
- type: PointLightBattery
- type: PointLight
radius: 1.3
energy: 0.15
color: "#7F93C0"
- type: ProjectileBatteryAmmoProvider
proto: PulseBoltProjectile
fireCost: 40
@@ -335,6 +371,11 @@
fireRate: 1.5
soundGunshot:
path: /Audio/Weapons/Guns/Gunshots/laser3.ogg
- type: PointLightBattery
- type: PointLight
radius: 1.3
energy: 0.15
color: "#7F93C0"
- type: ProjectileBatteryAmmoProvider
proto: PulseBoltProjectile
fireCost: 2.5
@@ -371,6 +412,11 @@
- type: ProjectileBatteryAmmoProvider
proto: BulletTrailLaserHeavy
fireCost: 100
- type: PointLightBattery
- type: PointLight
radius: 1.3
energy: 0.15
color: "#C07F7F"
- type: entity
name: portable particle decelerator
@@ -607,6 +653,11 @@
price: 750
- type: StealTarget
stealGroup: WeaponAntiqueLaser
- type: PointLightBattery
- type: PointLight
radius: 1.3
energy: 0.15
color: "#C07F7F"
- type: entity
name: advanced laser pistol
@@ -642,6 +693,11 @@
- type: Appearance
- type: StaticPrice
price: 63
- type: PointLightBattery
- type: PointLight
radius: 1.3
energy: 0.15
color: "#C07F7F"
- type: entity
name: C.H.I.M.P. handcannon

View File

@@ -798,7 +798,7 @@
muzzleFlash: null
- type: PointLight
radius: 3.5
color: blue
color: "#164CAC"
energy: 0.5
- type: entity
@@ -1090,9 +1090,9 @@
- 1, 0, 0, 1
- 1, 0, 0, 0
- type: PointLight
radius: 3.5
radius: 1.4
color: red
energy: 1
energy: 0.7
- type: Reflective
reflective:
- Energy
@@ -1166,9 +1166,9 @@
- 1, 0, 0, 1
- 1, 0, 0, 0
- type: PointLight
radius: 3.5
radius: 1.4
color: red
energy: 1
energy: 0.7
- type: Reflective
reflective:
- Energy
@@ -1217,9 +1217,9 @@
- 0, 0, 1, 1
- 0, 0, 1, 0
- type: PointLight
radius: 3.5
color: blue
energy: 1
radius: 1.7
color: "#164CAC"
energy: 0.7
- type: Reflective
reflective:
- Energy
@@ -1267,9 +1267,9 @@
- 1, 0, 0, 1
- 1, 0, 0, 0
- type: PointLight
radius: 3.5
radius: 1.9
color: red
energy: 1
energy: 0.7
- type: Reflective
reflective:
- Energy
@@ -1317,9 +1317,9 @@
- 0, 1, 0, 1
- 0, 1, 0, 0
- type: PointLight
radius: 3.5
radius: 1.7
color: green
energy: 1
energy: 0.7
- type: Reflective
reflective:
- Energy
@@ -1367,9 +1367,9 @@
- 1, 0, 0, 1
- 1, 0, 0, 0
- type: PointLight
radius: 3.5
radius: 1.7
color: red
energy: 1
energy: 0.7
- type: Reflective
reflective:
- Energy

View File

@@ -15,7 +15,6 @@
- Back
- suitStorage
- type: AmmoCounter
- type: WeaponModules
- type: Gun
fireRate: 5
selectedMode: FullAuto
@@ -81,10 +80,15 @@
visible: false
sprite: White/Objects/Weapons/modulesOnWeapon.rsi
map: [ "enum.ModuleVisualState.HandGuardModule" ]
- state: aim_module
visible: false
sprite: White/Objects/Weapons/modulesOnWeapon.rsi
map: [ "enum.ModuleVisualState.AimModule" ]
- type: Gun
fireRate: 5
soundGunshot:
path: /Audio/Weapons/Guns/Gunshots/ak.ogg
- type: WeaponModules
- type: ChamberMagazineAmmoProvider
soundRack:
path: /Audio/Weapons/Guns/Cock/ltrifle_cock.ogg
@@ -122,12 +126,21 @@
whitelist:
tags:
- BaseBarrelModule
aim_module:
name: Aim Module
insertSound: /Audio/White/Gun/Modules/insertmodule.ogg
ejectSound: /Audio/White/Gun/Modules/ejectmodule.ogg
priority: 3
whitelist:
tags:
- BaseAimModule
- type: ContainerContainer
containers:
gun_magazine: !type:ContainerSlot
gun_chamber: !type:ContainerSlot
handguard_module: !type:ContainerSlot
barrel_module: !type:ContainerSlot
aim_module: !type:ContainerSlot
- type: MagazineVisuals
magState: mag
steps: 1
@@ -201,11 +214,16 @@
visible: false
sprite: White/Objects/Weapons/modulesOnWeapon.rsi
map: [ "enum.ModuleVisualState.HandGuardModule" ]
- state: aim_module
visible: false
sprite: White/Objects/Weapons/modulesOnWeapon.rsi
map: [ "enum.ModuleVisualState.AimModule" ]
- type: Clothing
sprite: Objects/Weapons/Guns/Rifles/lecter.rsi
- type: Gun
soundGunshot:
path: /Audio/Weapons/Guns/Gunshots/ltrifle.ogg
- type: WeaponModules
- type: ItemSlots
slots:
gun_magazine:
@@ -240,12 +258,21 @@
whitelist:
tags:
- BaseBarrelModule
aim_module:
name: Aim Module
insertSound: /Audio/White/Gun/Modules/insertmodule.ogg
ejectSound: /Audio/White/Gun/Modules/ejectmodule.ogg
priority: 3
whitelist:
tags:
- BaseAimModule
- type: ContainerContainer
containers:
gun_magazine: !type:ContainerSlot
gun_chamber: !type:ContainerSlot
handguard_module: !type:ContainerSlot
barrel_module: !type:ContainerSlot
aim_module: !type:ContainerSlot
- type: MagazineVisuals
magState: mag
steps: 1
@@ -261,6 +288,7 @@
id: WeaponRifleLecterRubber
suffix: Non-lethal
components:
- type: WeaponModules
- type: ItemSlots
slots:
gun_magazine:
@@ -295,3 +323,11 @@
whitelist:
tags:
- BaseBarrelModule
aim_module:
name: Aim Module
insertSound: /Audio/White/Gun/Modules/insertmodule.ogg
ejectSound: /Audio/White/Gun/Modules/ejectmodule.ogg
priority: 3
whitelist:
tags:
- BaseAimModule

View File

@@ -108,6 +108,10 @@
visible: false
sprite: White/Objects/Weapons/modulesOnSMGs.rsi
map: [ "enum.ModuleVisualState.HandGuardModule" ]
- state: aim_module
visible: false
sprite: White/Objects/Weapons/modulesOnSMGs.rsi
map: [ "enum.ModuleVisualState.AimModule" ]
- type: Clothing
sprite: Objects/Weapons/Guns/SMGs/c20r.rsi
- type: Gun
@@ -150,12 +154,21 @@
whitelist:
tags:
- BaseHandGuardModule
aim_module:
name: Aim Module
insertSound: /Audio/White/Gun/Modules/insertmodule.ogg
ejectSound: /Audio/White/Gun/Modules/ejectmodule.ogg
priority: 3
whitelist:
tags:
- BaseAimModule
- type: ContainerContainer
containers:
gun_magazine: !type:ContainerSlot
gun_chamber: !type:ContainerSlot
handguard_module: !type:ContainerSlot
barrel_module: !type:ContainerSlot
aim_module: !type:ContainerSlot
- type: MagazineVisuals
magState: mag
steps: 6
@@ -186,6 +199,10 @@
visible: false
sprite: White/Objects/Weapons/modulesOnWeapon.rsi
map: [ "enum.ModuleVisualState.HandGuardModule" ]
- state: aim_module
visible: false
sprite: White/Objects/Weapons/modulesOnWeapon.rsi
map: [ "enum.ModuleVisualState.AimModule" ]
- type: Clothing
sprite: Objects/Weapons/Guns/SMGs/drozd.rsi
- type: Gun
@@ -230,12 +247,21 @@
whitelist:
tags:
- BaseHandGuardModule
aim_module:
name: Aim Module
insertSound: /Audio/White/Gun/Modules/insertmodule.ogg
ejectSound: /Audio/White/Gun/Modules/ejectmodule.ogg
priority: 3
whitelist:
tags:
- BaseAimModule
- type: ContainerContainer
containers:
gun_magazine: !type:ContainerSlot
gun_chamber: !type:ContainerSlot
handguard_module: !type:ContainerSlot
barrel_module: !type:ContainerSlot
aim_module: !type:ContainerSlot
- type: MagazineVisuals
magState: mag
steps: 1
@@ -319,6 +345,10 @@
visible: false
sprite: White/Objects/Weapons/modulesOnWeapon.rsi
map: [ "enum.ModuleVisualState.HandGuardModule" ]
- state: aim_module
visible: false
sprite: White/Objects/Weapons/modulesOnWeapon.rsi
map: [ "enum.ModuleVisualState.AimModule" ]
- type: Clothing
sprite: Objects/Weapons/Guns/SMGs/wt550.rsi
- type: ChamberMagazineAmmoProvider
@@ -363,12 +393,21 @@
whitelist:
tags:
- BaseHandGuardModule
aim_module:
name: Aim Module
insertSound: /Audio/White/Gun/Modules/insertmodule.ogg
ejectSound: /Audio/White/Gun/Modules/ejectmodule.ogg
priority: 2
whitelist:
tags:
- BaseAimModule
- type: ContainerContainer
containers:
gun_magazine: !type:ContainerSlot
gun_chamber: !type:ContainerSlot
handguard_module: !type:ContainerSlot
barrel_module: !type:ContainerSlot
aim_module: !type:ContainerSlot
- type: MagazineVisuals
magState: mag
steps: 6
@@ -419,6 +458,14 @@
whitelist:
tags:
- BaseHandGuardModule
aim_module:
name: Aim Module
insertSound: /Audio/White/Gun/Modules/insertmodule.ogg
ejectSound: /Audio/White/Gun/Modules/ejectmodule.ogg
priority: 3
whitelist:
tags:
- BaseAimModule
- type: entity
name: Vector

View File

@@ -62,7 +62,7 @@
- type: PointLight
enabled: false
radius: 2
energy: 2
energy: 0.6
color: white
netsync: false
- type: Appearance

View File

@@ -149,9 +149,15 @@
# This tag is used to nagivate the Airlock construction graph. It's needed because the construction graph is shared between Airlock, AirlockGlass, and HighSecDoor
- type: PryUnpowered
- type: BlockWeather
- type: PointLight
enabled: false
radius: 1.5
energy: 0.7
- type: PointLightAirlock
placement:
mode: SnapgridCenter
- type: entity
id: AirlockRCDResistant
parent: Airlock

View File

@@ -42,8 +42,8 @@
False: { visible: true, shader: shaded }
- type: LitOnPowered
- type: PointLight
radius: 1.5
energy: 1.6
radius: 1.6
energy: 0.7
enabled: false
mask: /Textures/Effects/LightMasks/cone.png
autoRot: true

View File

@@ -1090,6 +1090,7 @@
- CarpetBlack
- CarpetPink
- CarpetBlue
- CarpetSBlue
- CarpetGreen
- CarpetOrange
- CarpetPurple

View File

@@ -88,8 +88,8 @@
usesApcPower: true
- type: PointLight
enabled: false
castShadows: false
radius: 1.5
radius: 1.3
energy: 0.7
- type: LitOnPowered
- type: ApcPowerReceiver
powerLoad: 200
@@ -221,8 +221,8 @@
- state: panel
map: ["enum.WiresVisualLayers.MaintenancePanel"]
- type: PointLight
radius: 1
energy: 1.3
radius: 1.3
energy: 0.7
color: "#ffb0b0"
- type: AccessReader
access: [["HeadOfPersonnel"]]
@@ -256,8 +256,8 @@
- type: AccessReader
access: [["Service"]]
- type: PointLight
radius: 1.5
energy: 1.6
radius: 1.3
energy: 0.7
color: "#4b93ad"
- type: entity
@@ -324,8 +324,8 @@
- state: panel
map: ["enum.WiresVisualLayers.MaintenancePanel"]
- type: PointLight
radius: 1.8
energy: 1.6
radius: 1.3
energy: 0.7
color: "#3db83b"
- type: CargoSellBlacklist
@@ -361,8 +361,8 @@
- state: panel
map: [ "enum.WiresVisualLayers.MaintenancePanel" ]
- type: PointLight
radius: 1.8
energy: 1.6
radius: 1.3
energy: 0.7
color: "#3db83b"
- type: entity
@@ -403,8 +403,8 @@
- state: panel
map: ["enum.WiresVisualLayers.MaintenancePanel"]
- type: PointLight
radius: 1.5
energy: 1.3
radius: 1.3
energy: 0.7
color: "#ad7c4b"
- type: entity
@@ -440,8 +440,8 @@
- state: panel
map: ["enum.WiresVisualLayers.MaintenancePanel"]
- type: PointLight
radius: 1.5
energy: 1.6
radius: 1.3
energy: 0.7
color: "#3c5eb5"
- type: entity
@@ -460,8 +460,8 @@
- state: panel
map: ["enum.WiresVisualLayers.MaintenancePanel"]
- type: PointLight
radius: 1.5
energy: 1.6
radius: 1.3
energy: 0.7
color: "#423438"
- type: entity
@@ -481,8 +481,8 @@
- state: panel
map: ["enum.WiresVisualLayers.MaintenancePanel"]
- type: PointLight
radius: 1.5
energy: 1.6
radius: 1.3
energy: 0.7
color: "#A50824"
- type: entity
@@ -505,8 +505,8 @@
- state: panel
map: ["enum.WiresVisualLayers.MaintenancePanel"]
- type: PointLight
radius: 1.5
energy: 1.6
radius: 1.3
energy: 0.7
color: "#44964A"
- type: entity
@@ -528,8 +528,8 @@
- state: panel
map: ["enum.WiresVisualLayers.MaintenancePanel"]
- type: PointLight
radius: 1.5
energy: 1.6
radius: 1.3
energy: 0.7
color: "#CBC6BE"
- type: entity
@@ -552,8 +552,8 @@
- state: panel
map: ["enum.WiresVisualLayers.MaintenancePanel"]
- type: PointLight
radius: 1.5
energy: 1.6
radius: 1.3
energy: 0.7
color: "#D3A44D"
- type: entity
@@ -587,8 +587,8 @@
- state: panel
map: ["enum.WiresVisualLayers.MaintenancePanel"]
- type: PointLight
radius: 1.5
energy: 1.6
radius: 1.3
energy: 0.7
color: "#66538F"
- type: entity
@@ -624,8 +624,8 @@
- state: panel
map: ["enum.WiresVisualLayers.MaintenancePanel"]
- type: PointLight
radius: 1.5
energy: 1.6
radius: 1.3
energy: 0.7
color: "#6927C5"
- type: entity
@@ -660,8 +660,8 @@
- state: panel
map: ["enum.WiresVisualLayers.MaintenancePanel"]
- type: PointLight
radius: 1.5
energy: 1.6
radius: 1.3
energy: 0.7
color: "#D82929"
- type: entity
@@ -693,8 +693,8 @@
- type: AccessReader
access: [["Service"]]
- type: PointLight
radius: 1.5
energy: 1.6
radius: 1.3
energy: 0.7
color: "#4b93ad"
- type: entity
@@ -723,8 +723,8 @@
- state: panel
map: ["enum.WiresVisualLayers.MaintenancePanel"]
- type: PointLight
radius: 1.5
energy: 1.6
radius: 1.3
energy: 0.7
color: "#9a18d6"
- type: entity
@@ -757,8 +757,8 @@
- texture: Structures/Machines/VendingMachines/maintenance_panel.png
map: ["enum.WiresVisualLayers.MaintenancePanel"]
- type: PointLight
radius: 1.5
energy: 1.6
radius: 1.3
energy: 0.7
color: "#6148c7"
- type: entity
@@ -787,8 +787,8 @@
- type: AccessReader
access: [["Engineering"]]
- type: PointLight
radius: 1.5
energy: 1.6
radius: 1.3
energy: 0.7
color: "#b89e2a"
- type: entity
@@ -822,8 +822,8 @@
- type: AccessReader
access: [["Medical"]]
- type: PointLight
radius: 1.5
energy: 1.6
radius: 1.3
energy: 0.7
color: "#9dc5c9"
- type: GuideHelp
guides:
@@ -859,8 +859,8 @@
- type: AccessReader
access: [["Hydroponics"]]
- type: PointLight
radius: 1.5
energy: 1.6
radius: 1.3
energy: 0.7
color: "#326e3f"
- type: entity
@@ -929,8 +929,8 @@
- state: panel
map: ["enum.WiresVisualLayers.MaintenancePanel"]
- type: PointLight
radius: 1.5
energy: 1.6
radius: 1.3
energy: 0.7
color: "#326e3f"
- type: entity
@@ -973,8 +973,8 @@
- state: panel
map: ["enum.WiresVisualLayers.MaintenancePanel"]
- type: PointLight
radius: 1.5
energy: 1.6
radius: 1.3
energy: 0.7
color: "#c73434"
- type: entity
@@ -1004,8 +1004,8 @@
- state: panel
map: ["enum.WiresVisualLayers.MaintenancePanel"]
- type: PointLight
radius: 1.5
energy: 1.6
radius: 1.3
energy: 0.7
color: "#737785"
- type: entity
@@ -1024,8 +1024,8 @@
- state: panel
map: ["enum.WiresVisualLayers.MaintenancePanel"]
- type: PointLight
radius: 1.5
energy: 1.6
radius: 1.3
energy: 0.7
color: "#3c5eb5"
- type: entity
@@ -1044,8 +1044,8 @@
- state: panel
map: ["enum.WiresVisualLayers.MaintenancePanel"]
- type: PointLight
radius: 1.5
energy: 1.6
radius: 1.3
energy: 0.7
color: "#CE3401"
- type: entity
@@ -1064,8 +1064,8 @@
- state: panel
map: ["enum.WiresVisualLayers.MaintenancePanel"]
- type: PointLight
radius: 1.5
energy: 1.6
radius: 1.3
energy: 0.7
color: "#5F6A1C"
- type: entity
@@ -1084,8 +1084,8 @@
- state: panel
map: ["enum.WiresVisualLayers.MaintenancePanel"]
- type: PointLight
radius: 1.5
energy: 1.6
radius: 1.3
energy: 0.7
color: "#207E79"
- type: entity
@@ -1120,8 +1120,8 @@
- state: panel
map: ["enum.WiresVisualLayers.MaintenancePanel"]
- type: PointLight
radius: 1.5
energy: 1.6
radius: 1.3
energy: 0.7
color: "#389690"
- type: entity
@@ -1158,8 +1158,8 @@
map: ["enum.VendingMachineVisualLayers.Screen"]
shader: unshaded
- type: PointLight
radius: 1.5
energy: 1.6
radius: 1.3
energy: 0.7
color: "#c73434"
- type: Tag
tags:
@@ -1194,8 +1194,8 @@
- state: panel
map: ["enum.WiresVisualLayers.MaintenancePanel"]
- type: PointLight
radius: 1.5
energy: 1.6
radius: 1.3
energy: 0.7
color: "#9dc5c9"
- type: entity
@@ -1229,8 +1229,8 @@
- type: AccessReader
access: [["Research"]]
- type: PointLight
radius: 1.5
energy: 1.6
radius: 1.3
energy: 0.7
color: "#B0ADA9"
- type: GuideHelp
guides:
@@ -1260,8 +1260,8 @@
- state: panel
map: ["enum.WiresVisualLayers.MaintenancePanel"]
- type: PointLight
radius: 1.5
energy: 1.6
radius: 1.3
energy: 0.7
color: "#d4ab33"
- type: Tag
tags:
@@ -1295,8 +1295,8 @@
- state: panel
map: ["enum.WiresVisualLayers.MaintenancePanel"]
- type: PointLight
radius: 1.5
energy: 1.6
radius: 1.3
energy: 0.7
color: "#326e3f"
- type: entity
@@ -1329,8 +1329,8 @@
- state: panel
map: ["enum.WiresVisualLayers.MaintenancePanel"]
- type: PointLight
radius: 1.5
energy: 1.6
radius: 1.3
energy: 0.7
color: "#ffe599"
- type: entity
@@ -1356,8 +1356,8 @@
- state: panel
map: ["enum.WiresVisualLayers.MaintenancePanel"]
- type: PointLight
radius: 1.5
energy: 1.6
radius: 1.3
energy: 0.7
color: "#9dc5c9"
- type: AccessReader
access: [["Salvage"]]
@@ -1395,8 +1395,8 @@
- state: panel
map: ["enum.WiresVisualLayers.MaintenancePanel"]
- type: PointLight
radius: 1.5
energy: 1.6
radius: 1.3
energy: 0.7
color: "#d4ab33"
# wallmounted machines
@@ -1591,8 +1591,8 @@
- type: AccessReader
access: [["Chapel"]]
- type: PointLight
radius: 1.5
energy: 1.6
radius: 1.3
energy: 0.7
color: "#CCCCCC" #The holy C
- type: entity
@@ -2022,8 +2022,8 @@
- state: panel
map: ["enum.WiresVisualLayers.MaintenancePanel"]
- type: PointLight
radius: 1.5
energy: 1.6
radius: 1.3
energy: 0.7
color: "#48CF48"
- type: AccessReader
access: [["CentralCommand"]]
@@ -2056,8 +2056,8 @@
- state: panel
map: ["enum.WiresVisualLayers.MaintenancePanel"]
- type: PointLight
radius: 1.5
energy: 1.6
radius: 1.3
energy: 0.7
color: "#3c5eb5"
- type: Advertise
pack: HappyHonkAds

View File

@@ -13,10 +13,9 @@
sound:
path: /Audio/Ambience/Objects/hdd_buzz.ogg
- type: PointLight
radius: 1.5
energy: 1.6
radius: 1.4
energy: 0.7
color: "#3db83b"
castShadows: false
netsync: false
- type: Clickable
- type: AccessReader

View File

@@ -49,6 +49,11 @@
node: done
containers:
- entity_storage
- type: PointLight
enabled: false
radius: 1.15
energy: 0.45
- type: PointLightLocker
- type: entity
id: LockerBaseSecure

View File

@@ -330,6 +330,7 @@
components:
- MindContainer
- ActionContainer
- MobState
canTargetSelf: false
checkCanInteract: false
useDelay: 60
@@ -339,3 +340,24 @@
state: mindswap
event: !type:MindswapSpellEvent
speech: "GIN'YU CAPAN!"
- type: entity
id: ActionTimestopSpell
name: Stop time
noSpawn: true
components:
- type: Magic
requiresClothes: true
- type: InstantAction
alwaysPlaySound: false
sound: !type:SoundPathSpecifier
path: /Audio/White/Magic/timeparadox2.ogg
useDelay: 50
itemIconStyle: BigAction
checkCanInteract: false
icon:
sprite: Objects/Magic/magicactions.rsi
state: time
event: !type:StopTimeSpellEvent
prototype: Timestop
speech: "TOKI YO TOMARE!"

View File

@@ -247,6 +247,8 @@
groups:
Brute: -5
Burn: -5
types:
Bloodloss: -5
- type: reagent

View File

@@ -1248,6 +1248,13 @@
materials:
Cloth: 100
- type: latheRecipe
id: CarpetSBlue
result: FloorCarpetItemSkyBlue
completetime: 1
materials:
Cloth: 100
- type: latheRecipe
id: CarpetGreen
result: FloorCarpetItemGreen

View File

@@ -701,3 +701,12 @@
Plastic: 1000
Glass: 500
Gold: 1000
- type: latheRecipe
id: EightAimRecipe
result: EightAimModule
completetime: 15
materials:
Steel: 500
Plastic: 700
Glass: 300

View File

@@ -577,9 +577,12 @@
- type: reaction
id: Synthflesh
minTemp: 370
reactants:
Blood:
amount: 1
amount: 2
WeldingFuel:
amount: 2
Carbon:
amount: 1
Bicaridine:

View File

@@ -0,0 +1,31 @@
- type: entity
id: Timestop
name: "chronofield"
description: "ZA WARUDO"
components:
- type: Sprite
drawdepth: FloorObjects
sprite: White/Effects/timestop.rsi
state: icon
- type: Fixtures
fixtures:
fix1:
shape:
!type:PhysShapeCircle
radius: 2.5
density: 0
hard: false
mask:
- None
layer:
- Impassable
- HighImpassable
- MidImpassable
- LowImpassable
- Opaque
- BulletImpassable
- type: Physics
bodyType: Static
- type: TimedDespawn
lifetime: 10
- type: FreezeContacts

View File

@@ -32,6 +32,23 @@
- 0,0,0,0
- type: Appearance
- type: entity
id: BaseAimModule
parent: BaseItem
abstract: true
components:
- type: Sprite
sprite: White/Objects/Weapons/modules.rsi
- type: Tag
tags:
- BaseAimModule
- type: Item
sprite: White/Objects/Weapons/modules.rsi
size: Small
shape:
- 0,0,0,0
- type: Appearance
# modules
- type: entity
id: LightModule
@@ -97,3 +114,16 @@
- type: Sprite
state: accelerator
- type: Appearance
- type: entity
id: EightAimModule
description: 8X Aim Module for rifles.
name: "aim module"
parent: BaseAimModule
components:
- type: AimModule
value: "eightaim"
module_type: "aim_module"
- type: Sprite
state: eightaim
- type: Appearance

View File

@@ -160,3 +160,12 @@
- type: Scroll
actionId: ActionMindswapSpell
learnPopup: scroll-component-mindswap
- type: entity
id: ScrollTimestop
parent: BaseScroll
name: "Stop time scroll"
components:
- type: Scroll
actionId: ActionTimestopSpell
learnPopup: scroll-component-timestop

View File

@@ -30,6 +30,22 @@
- !type:ListingLimitedStockCondition
stock: 1
- type: listing
id: SpellBookTimestop
name: spellbook-timestop-name
description: spellbook-timestop-desc
productEntity: ScrollTimestop
icon:
sprite: Objects/Magic/magicactions.rsi
state: time
cost:
SpellPoint: 2
categories:
- DefenceSpells
conditions:
- !type:ListingLimitedStockCondition
stock: 1
- type: listing
id: SpellBookKnock
name: spellbook-knock-name

View File

@@ -75,3 +75,6 @@
- type: Tag
id: BaseHandGuardModule
- type: Tag
id: BaseAimModule

View File

@@ -361,6 +361,10 @@
- type: Tag
id: Chicken
# Allowed to control someone wearing a Chef's hat if inside their hat.
- type: Tag
id: ChefPilot
- type: Tag
id: ChemDispensable # container that can go into the chem dispenser

View File

@@ -60,6 +60,9 @@
},
{
"name": "mindswap"
},
{
"name": "time"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 568 KiB

View File

@@ -0,0 +1,37 @@
{
"version": 1,
"license": "CC-BY-SA-3.0",
"copyright": "Taken from tgstation at https://github.com/tgstation/tgstation/pull/49264/commits/d0dffe7ca643db2624424fdcebf45863f85c0448",
"size": {
"x": 160,
"y": 160
},
"states": [
{
"name": "icon",
"delays": [
[
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1
]
]
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@@ -22,11 +22,17 @@
{
"name": "accelerator"
},
{
"name": "eightaim"
},
{
"name": "barrel_module"
},
{
"name": "handguard_module"
},
{
"name": "aim_module"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 B

View File

@@ -22,11 +22,17 @@
{
"name": "accelerator"
},
{
"name": "eightaim"
},
{
"name": "handguard_module"
},
{
"name": "barrel_module"
},
{
"name": "aim_module"
}
]
}

Some files were not shown because too many files have changed in this diff Show More