Goida revert (#600)

* Revert "- fix: YAML linter fixes. (#598)"

This reverts commit 012bf3c357.

* Revert "Automatic changelog update"

This reverts commit cf1c3a9af5.

* Revert "[Fix] Base Layer Prototype (#597)"

This reverts commit b000423999.

* Revert "Modules update (#596)"

This reverts commit 00fbdead77.

* Revert "Automatic changelog update"

This reverts commit 0d7a12b2a2.

* Revert "Fixes (#593)"

This reverts commit 943c77031c.

* Revert "minor loadout fixes (#594)"

This reverts commit 143c010a89.

* Revert "Update DryDock.yml (#595)"

This reverts commit 4cd0100ac7.

* Revert "Automatic changelog update"

This reverts commit 08eadc690f.

* Revert "fix: Maximum message size (#591)"

This reverts commit 343f3612eb.

* Revert "Черри пики 7 (#592)"

This reverts commit 3f97bdce2f.

* Revert "Automatic changelog update"

This reverts commit 0678eca250.

* Revert "Рандомфиксы (#590)"

This reverts commit 2b9e5e2437.

* Revert "Нижнее бельё в лодауты (#580)"

This reverts commit e01a47b089.

* Revert "add lathe sounds (#588)"

This reverts commit c80a2985f2.

* Revert "Добавил параметр группы для некоторых реагентов (#585)"

This reverts commit 713b16bb98.

* Revert "add hrp ++++ aspect (#587)"

This reverts commit a6a69cc60f.

* Revert "Новые амбиенты и пару песен (#586)"

This reverts commit 48c86bd846.

* Revert "Сообщения в ПДА 2 (#583)"

This reverts commit cced3cc98b.

* Revert "Automatic changelog update"

This reverts commit abf435b11d.

* Revert "Chem stuff and more (#584)"

This reverts commit 3608960f5c.

* Revert "JobRequiremet refactor (#579)"

This reverts commit 9a9c9598e0.

* Revert "Revert "Reapply "Нижнее бельё в лодауты"""

This reverts commit 44447d573f.

* Revert "Reapply "Нижнее бельё в лодауты""

This reverts commit 0c4d082ad3.

* Revert "Revert "Нижнее бельё в лодауты""

This reverts commit 56473c5492.

* Revert "Нижнее бельё в лодауты"

This reverts commit d1cb0cb364.

* Revert "DryDock and WhiteMoose update (#578)"

This reverts commit 14755808af.

* Revert "Automatic changelog update"

This reverts commit 0133f82722.

* Revert "Fixes (#576)"

This reverts commit b7cc49896c.

* Revert "порт системы регенерации солюшена цинки (#574)"

This reverts commit a22cf3d50b.

* Revert "Воровские перчатки (#573)"

This reverts commit bb7140f3d4.

* Revert "mood resprite (#572)"

This reverts commit 4db96dc569.

* Revert "fix missing letter (#571)"

This reverts commit 94ea756794.

* Revert "Сообщения в ПДА (#564)"

This reverts commit d023d29e54.

* Revert "- fix: No visible aghost."

This reverts commit 27e7f25f7e.

* Revert "- tweak: Nerf cult shield."

This reverts commit 6a384246b8.
This commit is contained in:
MJSailor
2024-08-09 16:09:22 +00:00
committed by GitHub
parent 012bf3c357
commit a95fe13180
408 changed files with 33683 additions and 40901 deletions

View File

@@ -42,7 +42,7 @@ public sealed partial class RoleBanWindow : DefaultWindow
var prototypeManager = IoCManager.Resolve<IPrototypeManager>();
foreach (var proto in prototypeManager.EnumeratePrototypes<DepartmentPrototype>())
{
CreateRoleGroup(proto.ID, proto.Roles.Select(x => x.Id), proto.Color);
CreateRoleGroup(proto.ID, proto.Roles, proto.Color);
}
CreateRoleGroup("Antagonist", prototypeManager.EnumeratePrototypes<AntagPrototype>().Select(p => p.ID),

View File

@@ -54,7 +54,7 @@ public sealed class AudioUIController : UIController
{
if (!string.IsNullOrEmpty(value))
{
var resource = GetSoundOrFallback(value, CCVars.UIClickSound.DefaultValue);
var resource = _cache.GetResource<AudioResource>(value);
var source =
_audioManager.CreateAudioSource(resource);
@@ -77,7 +77,7 @@ public sealed class AudioUIController : UIController
{
if (!string.IsNullOrEmpty(value))
{
var hoverResource = GetSoundOrFallback(value, CCVars.UIHoverSound.DefaultValue);
var hoverResource = _cache.GetResource<AudioResource>(value);
var hoverSource =
_audioManager.CreateAudioSource(hoverResource);
@@ -95,12 +95,4 @@ public sealed class AudioUIController : UIController
UIManager.SetHoverSound(null);
}
}
private AudioResource GetSoundOrFallback(string path, string fallback)
{
if (!_cache.TryGetResource(path, out AudioResource? resource))
return _cache.GetResource<AudioResource>(fallback);
return resource;
}
}

View File

@@ -31,8 +31,8 @@ public sealed partial class ContentAudioSystem
[Dependency] private readonly RulesSystem _rules = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
private readonly TimeSpan _minAmbienceTime = TimeSpan.FromSeconds(5);
private readonly TimeSpan _maxAmbienceTime = TimeSpan.FromSeconds(10);
private readonly TimeSpan _minAmbienceTime = TimeSpan.FromSeconds(30);
private readonly TimeSpan _maxAmbienceTime = TimeSpan.FromSeconds(60);
private const float AmbientMusicFadeTime = 10f;
private static float _volumeSlider;

View File

@@ -82,7 +82,6 @@ namespace Content.Client.Input
human.AddFunction(ContentKeyFunctions.Arcade3);
human.AddFunction(ContentKeyFunctions.LieDown); // WD EDIT
human.AddFunction(ContentKeyFunctions.OfferItem); // WD EDIT
human.AddFunction(ContentKeyFunctions.LookUp); // WD EDIT
// actions should be common (for ghosts, mobs, etc)
common.AddFunction(ContentKeyFunctions.OpenActionsMenu);

View File

@@ -4,9 +4,7 @@ using Content.Client.CrewManifest;
using Content.Client.GameTicking.Managers;
using Content.Client.UserInterface.Controls;
using Content.Client.Players.PlayTimeTracking;
using Content.Client.Preferences;
using Content.Shared.CCVar;
using Content.Shared.Preferences;
using Content.Shared.Roles;
using Content.Shared.StatusIcon;
using Robust.Client.Console;
@@ -28,7 +26,6 @@ namespace Content.Client.LateJoin
[Dependency] private readonly IConfigurationManager _configManager = default!;
[Dependency] private readonly IEntitySystemManager _entitySystem = default!;
[Dependency] private readonly JobRequirementsManager _jobRequirements = default!;
[Dependency] private readonly IClientPreferencesManager _preferencesManager = default!;
public event Action<(NetEntity, string)> SelectedId;
@@ -257,7 +254,7 @@ namespace Content.Client.LateJoin
jobButton.OnPressed += _ => SelectedId.Invoke((id, jobButton.JobId));
if (!_jobRequirements.IsAllowed(prototype, (HumanoidCharacterProfile?)_preferencesManager.Preferences?.SelectedCharacter, out var reason))
if (!_jobRequirements.IsAllowed(prototype, out var reason))
{
jobButton.Disabled = true;

View File

@@ -193,7 +193,6 @@ namespace Content.Client.Options.UI.Tabs
AddButton(ContentKeyFunctions.SaveItemLocation);
AddButton(ContentKeyFunctions.OfferItem); // WD EDIT
AddButton(ContentKeyFunctions.LieDown); // WD EDIT
AddButton(ContentKeyFunctions.LookUp); // WD EDIT
AddCheckBox("ui-options-function-auto-get-up", _cfg.GetCVar(WhiteCVars.AutoGetUp), HandleToggleAutoGetUp); // WD EDIT
AddHeader("ui-options-header-interaction-adv");

View File

@@ -26,13 +26,13 @@ namespace Content.Client.PDA
public const int ProgramContentView = 3;
private string _pdaOwnerName = Loc.GetString("comp-pda-ui-unknown");
private string _pdaOwner = Loc.GetString("comp-pda-ui-unknown");
private string _owner = Loc.GetString("comp-pda-ui-unknown");
private string _jobTitle = Loc.GetString("comp-pda-ui-unassigned");
private string _stationName = Loc.GetString("comp-pda-ui-unknown");
private string _alertLevel = Loc.GetString("comp-pda-ui-unknown");
private string _instructions = Loc.GetString("comp-pda-ui-unknown");
private int _currentView;
@@ -96,7 +96,7 @@ namespace Content.Client.PDA
PdaOwnerButton.OnPressed += _ =>
{
_clipboard.SetText(_pdaOwnerName);
_clipboard.SetText(_pdaOwner);
};
IdInfoButton.OnPressed += _ =>
@@ -125,7 +125,7 @@ namespace Content.Client.PDA
_clipboard.SetText(_instructions);
};
HideAllViews();
@@ -138,9 +138,9 @@ namespace Content.Client.PDA
if (state.PdaOwnerInfo.ActualOwnerName != null)
{
_pdaOwnerName = state.PdaOwnerInfo.ActualOwnerName;
_pdaOwner = state.PdaOwnerInfo.ActualOwnerName;
PdaOwnerLabel.SetMarkup(Loc.GetString("comp-pda-ui-owner",
("actualOwnerName", _pdaOwnerName)));
("actualOwnerName", _pdaOwner)));
}
@@ -160,7 +160,7 @@ namespace Content.Client.PDA
_stationName = state.StationName ?? Loc.GetString("comp-pda-ui-unknown");
StationNameLabel.SetMarkup(Loc.GetString("comp-pda-ui-station",
("station", _stationName)));
var stationTime = _gameTiming.CurTime.Subtract(_gameTicker.RoundStartTimeSpan);

View File

@@ -1,10 +1,8 @@
using System.Diagnostics.CodeAnalysis;
using Content.Client.Administration.Managers;
using Content.Client.Lobby;
using Content.Shared.CCVar;
using Content.Shared.Players;
using Content.Shared.Players.PlayTimeTracking;
using Content.Shared.Preferences;
using Content.Shared.Roles;
using Robust.Client;
using Robust.Client.Player;
@@ -24,7 +22,7 @@ public sealed class JobRequirementsManager : ISharedPlaytimeManager
[Dependency] private readonly IEntityManager _entManager = default!;
[Dependency] private readonly IPlayerManager _playerManager = default!;
[Dependency] private readonly IPrototypeManager _prototypes = default!;
[Dependency] private readonly IClientAdminManager _adminManager = default!;
[Dependency] private readonly IClientAdminManager _adminManager = default!; // WD
private readonly Dictionary<string, TimeSpan> _roles = new();
private readonly List<string> _roleBans = new();
@@ -42,6 +40,7 @@ public sealed class JobRequirementsManager : ISharedPlaytimeManager
_net.RegisterNetMessage<MsgPlayTime>(RxPlayTime);
_client.RunLevelChanged += ClientOnRunLevelChanged;
_adminManager.AdminStatusUpdated += () => Updated?.Invoke(); // WD
}
private void ClientOnRunLevelChanged(object? sender, RunLevelChangedEventArgs e)
@@ -83,8 +82,7 @@ public sealed class JobRequirementsManager : ISharedPlaytimeManager
Updated?.Invoke();
}
public bool IsAllowed(JobPrototype job, HumanoidCharacterProfile? profile, [NotNullWhen(false)] out FormattedMessage? reason)
public bool IsAllowed(JobPrototype job, [NotNullWhen(false)] out FormattedMessage? reason)
{
reason = null;
@@ -98,16 +96,11 @@ public sealed class JobRequirementsManager : ISharedPlaytimeManager
if (player == null)
return true;
return CheckRoleRequirements(job, profile, out reason);
return _adminManager.IsActive() || // WD
CheckRoleTime(job.Requirements, out reason);
}
public bool CheckRoleRequirements(JobPrototype job, HumanoidCharacterProfile? profile, [NotNullWhen(false)] out FormattedMessage? reason)
{
var reqs = _entManager.System<SharedRoleSystem>().GetJobRequirement(job);
return CheckRoleRequirements(reqs, profile, out reason);
}
public bool CheckRoleRequirements(HashSet<JobRequirement>? requirements, HumanoidCharacterProfile? profile, [NotNullWhen(false)] out FormattedMessage? reason)
public bool CheckRoleTime(HashSet<JobRequirement>? requirements, [NotNullWhen(false)] out FormattedMessage? reason)
{
reason = null;
@@ -115,13 +108,9 @@ public sealed class JobRequirementsManager : ISharedPlaytimeManager
return true;
var reasons = new List<string>();
var isAdmin = _adminManager.IsAdmin(true); // WD
foreach (var requirement in requirements)
{
if (requirement.IgnoreIfAdmin && isAdmin) // WD
continue;
if (requirement.Check(_entManager, _prototypes, profile, _roles, out var jobReason))
if (JobRequirements.TryRequirementMet(requirement, _roles, out var jobReason, _entManager, _prototypes))
continue;
reasons.Add(jobReason.ToMarkup());

View File

@@ -1,5 +1,4 @@
using Content.Client.Players.PlayTimeTracking;
using Content.Shared.Preferences;
using Content.Shared.Roles;
using Robust.Client.UserInterface.Controls;
@@ -16,7 +15,7 @@ public sealed class AntagPreferenceSelector : RequirementsSelector<AntagPrototyp
public event Action<bool>? PreferenceChanged;
public AntagPreferenceSelector(AntagPrototype proto, ButtonGroup btnGroup, HumanoidCharacterProfile profile)
public AntagPreferenceSelector(AntagPrototype proto, ButtonGroup btnGroup)
: base(proto, btnGroup)
{
Options.OnItemSelected += args => PreferenceChanged?.Invoke(Preference);
@@ -29,12 +28,12 @@ public sealed class AntagPreferenceSelector : RequirementsSelector<AntagPrototyp
var title = Loc.GetString(proto.Name);
var description = Loc.GetString(proto.Objective);
// Not supported yet get fucked.
Setup(null, profile, items, title, 250, description);
Setup(null, items, title, 250, description);
// immediately lock requirements if they arent met.
// another function checks Disabled after creating the selector so this has to be done now
var requirements = IoCManager.Resolve<JobRequirementsManager>();
if (!requirements.CheckRoleRequirements(proto.Requirements, profile, out var reason))
if (proto.Requirements != null && !requirements.CheckRoleTime(proto.Requirements, out var reason))
{
LockRequirements(reason);
}

View File

@@ -557,16 +557,12 @@ namespace Content.Client.Preferences.UI
_antagPreferences.Clear();
var btnGroup = new ButtonGroup();
var character = (HumanoidCharacterProfile?) _preferencesManager.Preferences?.SelectedCharacter;
if (character == null)
return;
foreach (var antag in _prototypeManager.EnumeratePrototypes<AntagPrototype>().OrderBy(a => Loc.GetString(a.Name)))
{
if (!antag.SetPreference)
continue;
var selector = new AntagPreferenceSelector(antag, btnGroup, character)
var selector = new AntagPreferenceSelector(antag, btnGroup)
{
Margin = new Thickness(3f, 3f, 3f, 0f),
};
@@ -594,10 +590,6 @@ namespace Content.Client.Preferences.UI
_jobCategories.Clear();
var firstCategory = true;
var character = (HumanoidCharacterProfile?) _preferencesManager.Preferences?.SelectedCharacter;
if (character == null)
return;
var departments = _prototypeManager.EnumeratePrototypes<DepartmentPrototype>().ToArray();
Array.Sort(departments, DepartmentUIComparer.Instance);
@@ -658,12 +650,12 @@ namespace Content.Client.Preferences.UI
// Clone so we don't modify the underlying loadout.
Profile?.Loadouts.TryGetValue(LoadoutSystem.GetJobPrototype(job.ID), out loadout);
loadout = loadout?.Clone();
var selector = new JobPrioritySelector(loadout, job, jobLoadoutGroup, _prototypeManager, character)
var selector = new JobPrioritySelector(loadout, job, jobLoadoutGroup, _prototypeManager)
{
Margin = new Thickness(3f, 3f, 3f, 0f),
};
if (!_requirements.IsAllowed(job, (HumanoidCharacterProfile?)_preferencesManager.Preferences?.SelectedCharacter, out var reason))
if (!_requirements.IsAllowed(job, out var reason))
{
selector.LockRequirements(reason);
}

View File

@@ -20,7 +20,7 @@ public sealed class JobPrioritySelector : RequirementsSelector<JobPrototype>
public event Action<JobPriority>? PriorityChanged;
public JobPrioritySelector(RoleLoadout? loadout, JobPrototype proto, ButtonGroup btnGroup, IPrototypeManager protoMan, HumanoidCharacterProfile profile)
public JobPrioritySelector(RoleLoadout? loadout, JobPrototype proto, ButtonGroup btnGroup, IPrototypeManager protoMan)
: base(proto, btnGroup)
{
Options.OnItemSelected += args => PriorityChanged?.Invoke(Priority);
@@ -41,6 +41,6 @@ public sealed class JobPrioritySelector : RequirementsSelector<JobPrototype>
var jobIcon = protoMan.Index<StatusIconPrototype>(proto.Icon);
icon.Texture = jobIcon.Icon.Frame0();
Setup(loadout, profile, items, proto.LocalizedName, 200, proto.LocalizedDescription, icon);
Setup(loadout, items, proto.LocalizedName, 200, proto.LocalizedDescription, icon);
}
}

View File

@@ -1,6 +1,5 @@
using System.Linq;
using Content.Shared.Clothing;
using Content.Shared.Preferences;
using Content.Shared.Preferences.Loadouts;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.Controls;
@@ -18,18 +17,18 @@ public sealed partial class LoadoutGroupContainer : BoxContainer
public event Action<ProtoId<ItemLoadoutPrototype>>? OnLoadoutPressed;
public event Action<ProtoId<ItemLoadoutPrototype>>? OnLoadoutUnpressed;
public LoadoutGroupContainer(HumanoidCharacterProfile profile, RoleLoadout loadout, LoadoutGroupPrototype groupProto, ICommonSession session, IDependencyCollection collection)
public LoadoutGroupContainer(RoleLoadout loadout, LoadoutGroupPrototype groupProto, ICommonSession session, IDependencyCollection collection)
{
RobustXamlLoader.Load(this);
_groupProto = groupProto;
RefreshLoadouts(profile, loadout, session, collection);
RefreshLoadouts(loadout, session, collection);
}
/// <summary>
/// Updates button availabilities and buttons.
/// </summary>
public void RefreshLoadouts(HumanoidCharacterProfile profile, RoleLoadout loadout, ICommonSession session, IDependencyCollection collection)
public void RefreshLoadouts(RoleLoadout loadout, ICommonSession session, IDependencyCollection collection)
{
var protoMan = collection.Resolve<IPrototypeManager>();
var loadoutSystem = collection.Resolve<IEntityManager>().System<LoadoutSystem>();
@@ -75,7 +74,7 @@ public sealed partial class LoadoutGroupContainer : BoxContainer
var matchingLoadout = selected.FirstOrDefault(e => e.Prototype == loadoutProto);
var pressed = matchingLoadout != null;
var enabled = loadout.IsValid(profile, session, loadoutProto, collection, out var reason);
var enabled = loadout.IsValid(session, loadoutProto, collection, out var reason);
var loadoutContainer = new LoadoutContainer(loadoutProto, !enabled, reason);
loadoutContainer.Select.Pressed = pressed;
loadoutContainer.Text = loadoutSystem.GetName(loadProto);

View File

@@ -1,6 +1,5 @@
using Content.Client.Lobby;
using Content.Client.UserInterface.Controls;
using Content.Shared.Preferences;
using Content.Shared.Preferences.Loadouts;
using Content.Shared.Preferences.Loadouts.Effects;
using Robust.Client.AutoGenerated;
@@ -18,12 +17,9 @@ public sealed partial class LoadoutWindow : FancyWindow
private List<LoadoutGroupContainer> _groups = new();
public HumanoidCharacterProfile Profile;
public LoadoutWindow(HumanoidCharacterProfile profile, RoleLoadout loadout, RoleLoadoutPrototype proto, ICommonSession session, IDependencyCollection collection)
public LoadoutWindow(RoleLoadout loadout, RoleLoadoutPrototype proto, ICommonSession session, IDependencyCollection collection)
{
RobustXamlLoader.Load(this);
Profile = profile;
var protoManager = collection.Resolve<IPrototypeManager>();
foreach (var group in proto.Groups)
@@ -31,7 +27,7 @@ public sealed partial class LoadoutWindow : FancyWindow
if (!protoManager.TryIndex(group, out var groupProto))
continue;
var container = new LoadoutGroupContainer(profile, loadout, protoManager.Index(group), session, collection);
var container = new LoadoutGroupContainer(loadout, protoManager.Index(group), session, collection);
LoadoutGroupsContainer.AddTab(container, Loc.GetString(groupProto.Name));
_groups.Add(container);
@@ -58,7 +54,7 @@ public sealed partial class LoadoutWindow : FancyWindow
{
foreach (var group in _groups)
{
group.RefreshLoadouts(Profile, loadout, session, collection);
group.RefreshLoadouts(loadout, session, collection);
}
}
}

View File

@@ -3,7 +3,6 @@ using Content.Client.Lobby;
using Content.Client.Stylesheets;
using Content.Client.UserInterface.Controls;
using Content.Shared.Clothing;
using Content.Shared.Preferences;
using Content.Shared.Preferences.Loadouts;
using Content.Shared.Preferences.Loadouts.Effects;
using Content.Shared.Roles;
@@ -76,7 +75,7 @@ public abstract class RequirementsSelector<T> : BoxContainer where T : IPrototyp
/// <summary>
/// Actually adds the controls, must be called in the inheriting class' constructor.
/// </summary>
protected void Setup(RoleLoadout? loadout, HumanoidCharacterProfile profile, (string, int)[] items, string title, int titleSize, string? description, TextureRect? icon = null)
protected void Setup(RoleLoadout? loadout, (string, int)[] items, string title, int titleSize, string? description, TextureRect? icon = null)
{
_loadout = loadout;
@@ -132,7 +131,7 @@ public abstract class RequirementsSelector<T> : BoxContainer where T : IPrototyp
_loadout ??= new RoleLoadout(LoadoutSystem.GetJobPrototype(Proto.ID));
_loadout.SetDefault(protoManager);
_loadoutWindow = new LoadoutWindow(profile, _loadout, protoManager.Index(_loadout.Role), session, collection)
_loadoutWindow = new LoadoutWindow(_loadout, protoManager.Index(_loadout.Role), session, collection)
{
Title = Loc.GetString(Proto.ID + "-loadout"),
};
@@ -151,7 +150,7 @@ public abstract class RequirementsSelector<T> : BoxContainer where T : IPrototyp
if (!_loadout.RemoveLoadout(selectedGroup, selectedLoadout, protoManager))
return;
_loadout.EnsureValid(profile, session, collection);
_loadout.EnsureValid(session, collection);
_loadoutWindow.RefreshLoadouts(_loadout, session, collection);
var controller = UserInterfaceManager.GetUIController<LobbyUIController>();
controller.ReloadProfile();
@@ -163,7 +162,7 @@ public abstract class RequirementsSelector<T> : BoxContainer where T : IPrototyp
if (!_loadout.AddLoadout(selectedGroup, selectedLoadout, protoManager))
return;
_loadout.EnsureValid(profile, session, collection);
_loadout.EnsureValid(session, collection);
_loadoutWindow.RefreshLoadouts(_loadout, session, collection);
var controller = UserInterfaceManager.GetUIController<LobbyUIController>();
controller.ReloadProfile();

View File

@@ -23,7 +23,6 @@ using Content.Shared._White;
using Content.Shared._White.Cult.Components;
using Content.Shared._White.Utils;
using Content.Shared._White.Cult.Systems;
using Content.Shared._White.Radio;
using Robust.Client.Graphics;
using Robust.Client.Input;
using Robust.Client.Player;
@@ -576,12 +575,6 @@ public sealed class ChatUIController : UIController
FilterableChannels |= ChatChannel.Changeling;
CanSendChannels |= ChatSelectChannel.Changeling;
}
if (_entities.HasComponent<NetworkChatComponent>(localEnt))
{
FilterableChannels |= ChatChannel.Network;
CanSendChannels |= ChatSelectChannel.Network;
}
// WD EDIT END
SelectableChannels = CanSendChannels;

View File

@@ -24,11 +24,8 @@ public sealed partial class ChannelFilterPopup : Popup
ChatChannel.AdminAlert,
ChatChannel.AdminChat,
ChatChannel.Server,
// WD EDIT START
ChatChannel.Changeling,
ChatChannel.Cult,
ChatChannel.Network
// WD EDIT END
ChatChannel.Cult // WD EDIT
};
private readonly Dictionary<ChatChannel, ChannelFilterCheckbox> _filterStates = new();

View File

@@ -93,7 +93,7 @@ namespace Content.Client.UserInterface.Systems.Ghost.Controls.Roles
bool hasAccess = true;
FormattedMessage? reason;
if (!requirementsManager.CheckRoleRequirements(group.Key.Requirements, null, out reason))
if (!requirementsManager.CheckRoleTime(group.Key.Requirements, out reason))
{
hasAccess = false;
}

View File

@@ -1,38 +0,0 @@
using Content.Client.UserInterface.Fragments;
using Content.Shared._White.CartridgeLoader.Cartridges;
using Content.Shared.CartridgeLoader;
using Robust.Client.UserInterface;
namespace Content.Client._White.CartridgeLoader.Cartridges;
public sealed partial class MessagesUi : UIFragment
{
private MessagesUiFragment _fragment;
public override Control GetUIFragmentRoot()
{
return _fragment;
}
public override void Setup(BoundUserInterface userInterface, EntityUid? fragmentOwner)
{
_fragment = new MessagesUiFragment();
_fragment.OnMessageSent += note => SendMessagesMessage(MessagesUiAction.Send, note, null, userInterface);
_fragment.OnButtonPressed += userUid => SendMessagesMessage(MessagesUiAction.ChangeChat, null, userUid, userInterface);
}
public override void UpdateState(BoundUserInterfaceState state)
{
if (state is not MessagesUiState messagesState)
return;
_fragment.UpdateState(messagesState.Mode, messagesState.Users, messagesState.Messages, messagesState.Name);
}
private void SendMessagesMessage(MessagesUiAction action, string? stringInput, int? uidInput, BoundUserInterface userInterface)
{
var messagesMessage = new MessagesUiMessageEvent(action, stringInput, uidInput);
var message = new CartridgeUiMessage(messagesMessage);
userInterface.SendMessage(message);
}
}

View File

@@ -1,125 +0,0 @@
using System.Numerics;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using Content.Shared._White.CartridgeLoader.Cartridges;
using Content.Shared.Roles;
using Robust.Shared.Prototypes;
namespace Content.Client._White.CartridgeLoader.Cartridges;
[GenerateTypedNameReferences]
public sealed partial class MessagesUiFragment : BoxContainer
{
public event Action<string>? OnMessageSent;
public event Action<int?>? OnButtonPressed;
private string _searchText = string.Empty;
public MessagesUiFragment()
{
RobustXamlLoader.Load(this);
Input.OnTextEntered += _ =>
{
if (!string.IsNullOrEmpty(Input.Text))
OnMessageSent?.Invoke(Input.Text);
Input.Clear();
};
BackButton.OnPressed += _ => OnButtonPressed?.Invoke(null);
SearchBar.OnTextChanged += OnSearchTextChanged;
UpdateState(MessagesUiStateMode.UserList, [], [], null);
}
public void UpdateState(MessagesUiStateMode mode, List<(MessagesUserData, int?)>? users, List<(string, int?)>? messages, string? name)
{
MessageContainer.DisposeAllChildren();
Input.Orphan();
BackButton.Orphan();
SearchBar.Visible = false;
if (mode == MessagesUiStateMode.Chat && messages != null)
{
HeaderLabel.Text = name;
foreach (var (senderName, message) in messages)
{
AddNote($"{senderName} {message}");
}
OverContainer.AddChild(Input);
HeaderBox.AddChild(BackButton);
BackButton.SetPositionInParent(0);
}
else if (mode == MessagesUiStateMode.Error)
{
HeaderLabel.Text = Loc.GetString("messages-pda-error-header");
AddNote(Loc.GetString("messages-pda-error-message"));
}
else if (mode == MessagesUiStateMode.UserList && users != null)
{
SearchBar.Visible = true;
HeaderLabel.Text = Loc.GetString("messages-pda-chat-choice");
foreach (var (messagesUser, userUid) in users)
{
AddButton(userUid, messagesUser.Name + ", " + messagesUser.Job, messagesUser.Department);
}
}
}
///<summary>
/// Adding a button for selecting a chat
///</summary>
private void AddButton(int? userUid, string userName, string departmentId)
{
var styleClass = IoCManager.Resolve<IPrototypeManager>().Index<DepartmentPrototype>(departmentId).ButtonStyle;
var button = new Button
{
Text = userName,
HorizontalExpand = true,
ClipText = true,
StyleClasses = { styleClass },
MinWidth = 60
};
button.OnPressed += _ => OnButtonPressed?.Invoke(userUid);
MessageContainer.AddChild(button);
}
///<summary>
/// Adding a text label to the message container
///</summary>
private void AddNote(string note)
{
MessageContainer.AddChild(new Label
{
Text = note,
HorizontalExpand = true,
ClipText = false
});
}
private bool ButtonIsVisible(Button button)
{
return string.IsNullOrEmpty(_searchText) || button.Text == null || button.Text.Contains(_searchText, StringComparison.OrdinalIgnoreCase);
}
private void UpdateVisibleButtons()
{
foreach (var child in MessageContainer.Children)
{
if (child is Button button)
button.Visible = ButtonIsVisible(button);
}
}
private void OnSearchTextChanged(LineEdit.LineEditEventArgs args)
{
_searchText = args.Text;
UpdateVisibleButtons();
MessagesScroll.SetScrollValue(Vector2.Zero);
}
}

View File

@@ -1,17 +0,0 @@
<cartridges1:MessagesUiFragment
xmlns="https://spacestation14.io"
xmlns:cartridges1="clr-namespace:Content.Client._White.CartridgeLoader.Cartridges"
Margin="1 0 2 0" Orientation="Vertical" HorizontalExpand="True" VerticalExpand="True">
<PanelContainer StyleClasses="BackgroundDark"/>
<BoxContainer Name="OverContainer" Orientation="Vertical" HorizontalExpand="True" VerticalExpand="True">
<BoxContainer Name="HeaderBox">
<Button Name="BackButton" Text="{Loc 'messages-pda-ui-back'}" HorizontalExpand="False"/>
<Label Name="HeaderLabel"/>
</BoxContainer>
<LineEdit Name="SearchBar" PlaceHolder="Search" HorizontalExpand="True" Margin="0 4" />
<ScrollContainer Name="MessagesScroll" HorizontalExpand="True" VerticalExpand="True" HScrollEnabled="True">
<BoxContainer Orientation="Vertical" Name="MessageContainer" HorizontalExpand="True" VerticalExpand="True"/>
</ScrollContainer>
<LineEdit Name="Input" HorizontalExpand="True" SetHeight="32"/>
</BoxContainer>
</cartridges1:MessagesUiFragment>

View File

@@ -2,7 +2,6 @@ using System.Numerics;
using Content.Client.Viewport;
using Content.Shared._White.Telescope;
using Content.Shared.Hands.Components;
using Content.Shared.Input;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Client.Input;
@@ -24,7 +23,6 @@ public sealed class TelescopeSystem : SharedTelescopeSystem
private ScalingViewport? _viewport;
public override void FrameUpdate(float frameTime)
{
base.FrameUpdate(frameTime);
@@ -34,25 +32,19 @@ public sealed class TelescopeSystem : SharedTelescopeSystem
var player = _player.LocalEntity;
var entity = GetRightEntity(player);
if (entity == EntityUid.Invalid)
return;
var telescope = Comp<TelescopeComponent>(entity);
if (!TryComp<EyeComponent>(player, out var eye))
if (!TryComp<HandsComponent>(player, out var hands) ||
!TryComp<TelescopeComponent>(hands.ActiveHandEntity, out var telescope) ||
!TryComp<EyeComponent>(player.Value, out var eye))
return;
var offset = Vector2.Zero;
if (_inputSystem.CmdStates.GetState(ContentKeyFunctions.LookUp) != BoundKeyState.Down)
if (_inputSystem.CmdStates.GetState(EngineKeyFunctions.UseSecondary) != BoundKeyState.Down)
{
RaisePredictiveEvent(new EyeOffsetChangedEvent
{
Offset = offset
});
return;
}

View File

@@ -392,8 +392,7 @@ namespace Content.Server.Administration.Managers
// я ебался в зад, поймите
if (!data.HasFlag(AdminFlags.Permissions) && !data.HasFlag(AdminFlags.Host) &&
dbData.AdminServer != null && dbData.AdminServer != "unknown" && currentServerName != "unknown"
&& currentServerName != dbData.AdminServer
&& _cfg.GetCVar(CCVars.AdminUseCustomNamesAdminRank))
&& currentServerName != dbData.AdminServer)
{
return null;
}

View File

@@ -405,21 +405,14 @@ namespace Content.Server.Administration.Systems
var escapedText = FormattedMessage.EscapeText(message.Text);
string bwoinkText;
string adminPrefix = "";
//Getting an administrator position
if (_config.GetCVar(CCVars.AhelpAdminPrefix) && senderAdmin is not null && senderAdmin.Title is not null)
{
adminPrefix = $"[bold]\\[{senderAdmin.Title}\\][/bold] ";
}
if (senderAdmin is not null && senderAdmin.Flags == AdminFlags.Adminhelp) // Mentor. Not full admin. That's why it's colored differently.
{
bwoinkText = $"[color=purple]{adminPrefix}{senderSession.Name}[/color]";
bwoinkText = $"[color=purple]{senderSession.Name}[/color]";
}
else if (senderAdmin is not null && senderAdmin.HasFlag(AdminFlags.Adminhelp))
{
bwoinkText = $"[color=red]{adminPrefix}{senderSession.Name}[/color]";
bwoinkText = $"[color=red]{senderSession.Name}[/color]";
}
else
{
@@ -442,13 +435,6 @@ namespace Content.Server.Administration.Systems
RaiseNetworkEvent(msg, channel);
}
string adminPrefixWebhook = "";
if (_config.GetCVar(CCVars.AhelpAdminPrefixWebhook) && senderAdmin is not null && senderAdmin.Title is not null)
{
adminPrefixWebhook = $"[bold]\\[{senderAdmin.Title}\\][/bold] ";
}
// Notify player
if (_playerManager.TryGetSessionById(message.UserId, out var session))
{
@@ -461,11 +447,11 @@ namespace Content.Server.Administration.Systems
// Doing the same thing as above, but with the override name. Theres probably a better way to do this.
if (senderAdmin is not null && senderAdmin.Flags == AdminFlags.Adminhelp) // Mentor. Not full admin. That's why it's colored differently.
{
overrideMsgText = $"[color=purple]{adminPrefixWebhook}{_overrideClientName}[/color]";
overrideMsgText = $"[color=purple]{_overrideClientName}[/color]";
}
else if (senderAdmin is not null && senderAdmin.HasFlag(AdminFlags.Adminhelp))
{
overrideMsgText = $"[color=red]{adminPrefixWebhook}{_overrideClientName}[/color]";
overrideMsgText = $"[color=red]{_overrideClientName}[/color]";
}
else
{

View File

@@ -386,4 +386,4 @@ public sealed class AntagSelectionSystem : GameRuleSystem<GameRuleComponent>
}
#endregion
}
}

View File

@@ -104,7 +104,7 @@ namespace Content.Server.Body.Components
/// The sound to be played when a weapon instantly deals blood loss damage.
/// </summary>
[DataField]
public SoundSpecifier InstantBloodSound = new SoundCollectionSpecifier("BloodLossRun");
public SoundSpecifier InstantBloodSound = new SoundCollectionSpecifier("blood");
/// <summary>
/// The sound to be played when some damage actually heals bleeding rather than starting it.
@@ -181,12 +181,6 @@ namespace Content.Server.Body.Components
/// </summary>
public bool IsBleeding => BleedAmount > 0;
public readonly AudioParams DefaultParams = AudioParams.Default.WithVolume(-1f);
public SoundSpecifier? BloodLossSound = new SoundCollectionSpecifier("BloodLoss");
//public SoundSpecifier? BloodLossRunSound = new SoundCollectionSpecifier("");
//WD-EDIT
}
}

View File

@@ -1,7 +1,5 @@
using Content.Server.Body.Systems;
using Content.Shared.Chat.Prototypes;
using Content.Shared.Damage;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
using Robust.Shared.Audio; // WD
@@ -53,16 +51,10 @@ namespace Content.Server.Body.Components
public DamageSpecifier DamageRecovery = default!;
[DataField]
public TimeSpan GaspEmoteCooldown = TimeSpan.FromSeconds(8);
public TimeSpan GaspPopupCooldown = TimeSpan.FromSeconds(8);
[ViewVariables]
public TimeSpan LastGaspEmoteTime;
/// <summary>
/// The emote when gasps
/// </summary>
[DataField]
public ProtoId<EmotePrototype> GaspEmote = "Gasp";
public TimeSpan LastGaspPopupTime;
/// <summary>
/// How many cycles in a row has the mob been under-saturated?

View File

@@ -13,12 +13,9 @@ using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.Chemistry.Reaction;
using Content.Shared.Damage;
using Content.Shared.Damage.Components;
using Content.Shared.Damage.Prototypes;
using Content.Shared.Drunk;
using Content.Shared.FixedPoint;
using Content.Shared.Mobs;
using Content.Shared.Mobs.Components;
using Content.Shared.Mobs.Systems;
using Content.Shared.Movement.Systems;
using Content.Shared.Popups;
@@ -47,7 +44,7 @@ public sealed class BloodstreamSystem : EntitySystem
[Dependency] private readonly AlertsSystem _alertsSystem = default!;
[Dependency] private readonly ForensicsSystem _forensicsSystem = default!;
[Dependency] private readonly MovementSpeedModifierSystem _speed = default!; // WD
[Dependency] private readonly BloodLossAccent _bloodLossAccent = default!; // WD
[Dependency] private readonly BloodLossAccent _bloodLossAccent = default!;
public override void Initialize()
{
@@ -386,13 +383,6 @@ public sealed class BloodstreamSystem : EntitySystem
}
tempSolution.RemoveAllSolution();
// WD edit start
if (TryComp<MobStateComponent>(uid, out var mobState) && TryComp<StaminaComponent>(uid, out var stamina))
if (mobState.CurrentState != MobState.Critical && !stamina.Critical)
_audio.PlayPvs(component.BloodLossSound, uid, component.DefaultParams);
// WD edit end
}
_solutionContainerSystem.UpdateChemicals(component.TemporarySolution.Value);

View File

@@ -2,7 +2,6 @@ using Content.Server.Administration.Logs;
using Content.Server.Atmos;
using Content.Server.Atmos.EntitySystems;
using Content.Server.Body.Components;
using Content.Server.Chat.Systems;
using Content.Server.Chemistry.Containers.EntitySystems;
using Content.Server.DoAfter;
using Content.Server.Nutrition.Components; // WD
@@ -43,16 +42,14 @@ public sealed class RespiratorSystem : EntitySystem
[Dependency] private readonly BodySystem _bodySystem = default!;
[Dependency] private readonly DamageableSystem _damageableSys = default!;
[Dependency] private readonly LungSystem _lungSystem = default!;
[Dependency] private readonly PopupSystem _popupSystem = default!;
[Dependency] private readonly MobStateSystem _mobState = default!;
[Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!;
[Dependency] private readonly ChatSystem _chat = default!;
[Dependency] private readonly InventorySystem _inventorySystem = default!; // WD
[Dependency] private readonly ActionBlockerSystem _blocker = default!; // WD
[Dependency] private readonly AudioSystem _audio = default!; // WD
[Dependency] private readonly DoAfterSystem _doAfter = default!; // WD
[Dependency] private readonly DamageableSystem _damageable = default!; // WD
[Dependency] private readonly SharedPopupSystem _popupSystem = default!; // WD
public override void Initialize()
{
@@ -119,10 +116,10 @@ public sealed class RespiratorSystem : EntitySystem
continue;
}
if (_gameTiming.CurTime >= respirator.LastGaspEmoteTime + respirator.GaspEmoteCooldown)
if (_gameTiming.CurTime >= respirator.LastGaspPopupTime + respirator.GaspPopupCooldown)
{
respirator.LastGaspEmoteTime = _gameTiming.CurTime;
_chat.TryEmoteWithChat(uid, respirator.GaspEmote, ignoreActionBlocker: true);
respirator.LastGaspPopupTime = _gameTiming.CurTime;
_popupSystem.PopupEntity($"{Name(Identity.Entity(uid, EntityManager))} задыхается!", uid);
}
TakeSuffocationDamage((uid, respirator));

View File

@@ -24,7 +24,6 @@ using Content.Server.Popups;
using Content.Server.Store.Components;
using Content.Server.Temperature.Components;
using Content.Server.Temperature.Systems;
using Content.Shared._White.Item.PseudoItem;
using Content.Shared._White.Overlays;
using Content.Shared.Actions;
using Content.Shared.Borer;
@@ -1012,7 +1011,7 @@ public sealed partial class ChangelingSystem
if (!TryComp(polymorphEntity.Value, out FelinidComponent? felinid))
return polymorphEntity;
_action.SetCharges(felinid.HairballAction, 0);
_action.SetEnabled(felinid.HairballAction, false);
@@ -1021,9 +1020,6 @@ public sealed partial class ChangelingSystem
private void BeforeTransform(EntityUid target)
{
if (TryComp(target, out PseudoItemComponent? pseudoItem) && pseudoItem.Active)
_transform.AttachToGridOrMap(target);
if (TryComp(target, out BorerHostComponent? host) && host.BorerContainer.Count > 0)
_borer.GetOut(host.BorerContainer.ContainedEntities[0]);

View File

@@ -27,7 +27,6 @@ using Content.Shared._White;
using Content.Shared._White.Cult.Components;
using Content.Shared.Speech;
using Content.Shared._White.Cult.Systems;
using Content.Shared._White.Radio;
using Robust.Server.Player;
using Robust.Shared.Audio;
using Robust.Shared.Audio.Systems;
@@ -774,7 +773,7 @@ public sealed partial class ChatSystem : SharedChatSystem
.Select(p => p.Channel);
}
// WD EDIT START
// WD EDIT
private void SendCultChat(EntityUid source, ICommonSession player, string message, bool hideChat)
{
var clients = GetCultChatClients();
@@ -803,28 +802,6 @@ public sealed partial class ChatSystem : SharedChatSystem
.Select(p => p.Channel);
}
public void SendNetworkChat(EntityUid source, string message, bool hideChat)
{
var clients = GetNetworkChatClients();
var wrappedMessage = Loc.GetString("chat-manager-send-message-chat-wrap-message",
("channelName", Loc.GetString("chat-manager-message-channel-name")),
("message", FormattedMessage.EscapeText(message)));
_chatManager.ChatMessageToMany(ChatChannel.Network, message, wrappedMessage, source, hideChat, false,
clients.ToList());
}
private IEnumerable<INetChannel> GetNetworkChatClients()
{
return Filter.Empty()
.AddWhereAttachedEntity(HasComp<GhostComponent>)
.AddWhereAttachedEntity(HasComp<NetworkChatComponent>)
.Recipients
.Union(_adminManager.ActiveAdmins)
.Select(p => p.Channel);
}
// WD EDIT END
private void SendDeadChat(EntityUid source, ICommonSession player, string message, bool hideChat)
{
var clients = GetDeadChatClients();

View File

@@ -205,7 +205,7 @@ public sealed class InjectorSystem : SharedInjectorSystem
DoAfter.TryStartDoAfter(new DoAfterArgs(EntityManager, user, actualDelay, new InjectorDoAfterEvent(), injector.Owner, target: target, used: injector.Owner)
{
BreakOnMove = isTarget, // WD EDIT
BreakOnMove = true,
BreakOnWeightlessMove = false,
BreakOnDamage = true,
NeedHand = true,

View File

@@ -56,7 +56,7 @@ public sealed class SingletonDeviceNetServerSystem : EntitySystem
if (!server.Available)
{
DisconnectServer(uid, server, device);
DisconnectServer(uid,server, device);
continue;
}

View File

@@ -149,10 +149,8 @@ public sealed partial class EnergyDomeSystem : EntitySystem
private void OnGetActions(Entity<EnergyDomeGeneratorComponent> generator, ref GetItemActionsEvent args)
{
if (args.SlotFlags != SlotFlags.OUTERCLOTHING)
return;
args.AddAction(ref generator.Comp.ToggleActionEntity, generator.Comp.ToggleAction);
if (generator.Comp.CanInteractUse)
args.AddAction(ref generator.Comp.ToggleActionEntity, generator.Comp.ToggleAction);
}
private void OnToggleAction(Entity<EnergyDomeGeneratorComponent> generator, ref ToggleActionEvent args)

View File

@@ -14,10 +14,6 @@ namespace Content.Server.Ghost.Roles.Components
[DataField("rules")] private string _roleRules = "ghost-role-component-default-rules";
// TODO ROLE TIMERS
// Actually make use of / enforce this requirement?
// Why is this even here.
// Move to ghost role prototype & respect CCvars.GameRoleTimerOverride
[DataField("requirements")]
public HashSet<JobRequirement>? Requirements;

View File

@@ -20,7 +20,6 @@ using Content.Server.Station.Systems;
using Content.Shared.Popups;
using Content.Shared.StationRecords;
using Robust.Shared.Audio.Systems;
using Content.Server.Chat.Managers;
namespace Content.Server.MassMedia.Systems;
@@ -36,7 +35,6 @@ public sealed class NewsSystem : SharedNewsSystem
[Dependency] private readonly GameTicker _ticker = default!;
[Dependency] private readonly AccessReaderSystem _accessReader = default!;
[Dependency] private readonly IdCardSystem _idCardSystem = default!;
[Dependency] private readonly IChatManager _chatManager = default!;
public override void Initialize()
{
@@ -169,12 +167,6 @@ public sealed class NewsSystem : SharedNewsSystem
$"{ToPrettyString(author):actor} created news article {article.Title} by {article.Author}: {article.Content}"
);
_chatManager.SendAdminAnnouncement(Loc.GetString("news-publish-admin-announcement",
("actor", msg.Session.AttachedEntity),
("title", article.Title),
("author", article.Author ?? Loc.GetString("news-read-ui-no-author"))
));
articles.Add(article);
var args = new NewsArticlePublishedEvent(article);

View File

@@ -1,4 +1,4 @@
using Content.Server.DeviceNetwork;
using Content.Server.DeviceNetwork;
using Content.Server.DeviceNetwork.Components;
using Content.Server.DeviceNetwork.Systems;
using Content.Server.Medical.SuitSensors;

View File

@@ -7,9 +7,12 @@ using Content.Server.Ghost;
using Content.Server.Popups;
using Content.Server.PowerCell;
using Content.Server.Traits.Assorted;
using Content.Shared._White.Item.DelayedKnockdown;
using Content.Shared.Damage;
using Content.Shared.Damage.Components;
using Content.Shared.Damage.Events;
using Content.Shared.DoAfter;
using Content.Shared.Emag.Systems;
using Content.Shared.Interaction;
using Content.Shared.Interaction.Components;
using Content.Shared.Interaction.Events;
@@ -21,6 +24,8 @@ using Content.Shared.Mobs.Systems;
using Content.Shared.PowerCell;
using Content.Shared.Timing;
using Content.Shared.Toggleable;
using Content.Shared.Weapons.Melee;
using Robust.Shared.Audio;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Player;
using Robust.Shared.Timing;
@@ -67,8 +72,6 @@ public sealed class DefibrillatorSystem : EntitySystem
{
if (!_powerCell.HasActivatableCharge(uid))
TryDisable(uid, comp);
comp.NextZapTime = _timing.CurTime + TimeSpan.FromSeconds(3);
_appearance.SetData(uid, DefibrillatorVisuals.Ready, false);
return;
}
@@ -198,7 +201,6 @@ public sealed class DefibrillatorSystem : EntitySystem
uid, target, uid)
{
BreakOnMove = user == target, // WD EDIT
DuplicateCondition = DuplicateConditions.None, // WD EDIT
BlockDuplicate = true,
BreakOnHandChange = true,
NeedHand = true

View File

@@ -88,7 +88,7 @@ public sealed class RenameCommand : IConsoleCommand
{
if (pda.OwnerName == oldName)
{
pdaSystem.SetOwnerName(uid, pda, name);
pdaSystem.SetOwner(uid, pda, name);
}
}
}

View File

@@ -14,7 +14,6 @@ using Content.Shared.CartridgeLoader;
using Content.Shared.Chat;
using Content.Shared.Light.Components;
using Content.Shared.PDA;
using Content.Shared.Roles;
using Robust.Server.Containers;
using Robust.Server.GameObjects;
using Robust.Shared.Containers;
@@ -91,24 +90,12 @@ namespace Content.Server.PDA
UpdatePdaUi(uid, pda);
}
public void SetOwnerName(EntityUid uid, PdaComponent pda, string ownerName)
public void SetOwner(EntityUid uid, PdaComponent pda, string ownerName)
{
pda.OwnerName = ownerName;
UpdatePdaUi(uid, pda);
}
public void SetOwnerJob(EntityUid uid, PdaComponent pda, string ownerJob)
{
pda.OwnerJob = ownerJob;
UpdatePdaUi(uid, pda);
}
public void SetOwnerDepartment(EntityUid uid, PdaComponent pda, string ownerDepartment)
{
pda.OwnerDepartment = ownerDepartment;
UpdatePdaUi(uid, pda);
}
private void OnStationRenamed(StationRenamedEvent ev)
{
UpdateAllPdaUisOnStation();
@@ -185,7 +172,6 @@ namespace Content.Server.PDA
new PdaIdInfoText
{
ActualOwnerName = pda.OwnerName,
ActualOwnerJob = pda.OwnerJob, // WD EDIT
IdOwner = id?.FullName,
JobTitle = id?.JobTitle,
StationAlertLevel = pda.StationAlertLevel,

View File

@@ -4,15 +4,12 @@ using Content.Server.Afk;
using Content.Server.Afk.Events;
using Content.Server.GameTicking;
using Content.Server.Mind;
using Content.Server.Preferences.Managers;
using Content.Server.Station.Events;
using Content.Shared.CCVar;
using Content.Shared.GameTicking;
using Content.Shared.Mobs;
using Content.Shared.Mobs.Components;
using Content.Shared.Players;
using Content.Shared.Players.PlayTimeTracking;
using Content.Shared.Preferences;
using Content.Shared.Roles;
using Robust.Server.GameObjects;
using Robust.Server.Player;
@@ -36,8 +33,6 @@ public sealed class PlayTimeTrackingSystem : EntitySystem
[Dependency] private readonly MindSystem _minds = default!;
[Dependency] private readonly IPlayTimeTrackingManager _tracking = default!;
[Dependency] private readonly IAdminManager _adminManager = default!;
[Dependency] private readonly IServerPreferencesManager _preferencesManager = default!;
[Dependency] private readonly SharedRoleSystem _role = default!;
public override void Initialize()
{
@@ -164,9 +159,18 @@ public sealed class PlayTimeTrackingSystem : EntitySystem
_tracking.QueueSendTimers(ev.PlayerSession);
}
private bool IsBypassingChecks(ICommonSession player)
{
return _adminManager.IsAdmin(player, true);
}
public bool IsAllowed(ICommonSession player, string role)
{
if (IsBypassingChecks(player))
return true;
if (!_prototypes.TryIndex<JobPrototype>(role, out var job) ||
job.Requirements == null ||
!_cfg.GetCVar(CCVars.GameRoleTimers))
return true;
@@ -176,15 +180,16 @@ public sealed class PlayTimeTrackingSystem : EntitySystem
playTimes = new Dictionary<string, TimeSpan>();
}
var isAdmin = _adminManager.IsAdmin(player, true); // WD
return JobRequirements.TryRequirementsMet(job, playTimes, out _, EntityManager, _prototypes, (HumanoidCharacterProfile?) _preferencesManager.GetPreferences(player.UserId).SelectedCharacter, isAdmin); // WD EDIT
return JobRequirements.TryRequirementsMet(job, playTimes, out _, EntityManager, _prototypes);
}
public HashSet<string> GetDisallowedJobs(ICommonSession player)
{
var roles = new HashSet<string>();
if (IsBypassingChecks(player))
return roles;
if (!_cfg.GetCVar(CCVars.GameRoleTimers))
return roles;
@@ -194,24 +199,36 @@ public sealed class PlayTimeTrackingSystem : EntitySystem
playTimes = new Dictionary<string, TimeSpan>();
}
var isAdmin = _adminManager.IsAdmin(player, true); // WD
foreach (var job in _prototypes.EnumeratePrototypes<JobPrototype>())
{
if (JobRequirements.TryRequirementsMet(job, playTimes, out _, EntityManager, _prototypes, (HumanoidCharacterProfile?) _preferencesManager.GetPreferences(player.UserId).SelectedCharacter, isAdmin)) // WD EDIT
roles.Add(job.ID);
if (job.Requirements != null)
{
foreach (var requirement in job.Requirements)
{
if (JobRequirements.TryRequirementMet(requirement, playTimes, out _, EntityManager, _prototypes))
continue;
goto NoRole;
}
}
roles.Add(job.ID);
NoRole:;
}
return roles;
}
public void RemoveDisallowedJobs(NetUserId userId, List<ProtoId<JobPrototype>> jobs)
public void RemoveDisallowedJobs(NetUserId userId, ref List<string> jobs)
{
if (!_cfg.GetCVar(CCVars.GameRoleTimers))
return;
var player = _playerManager.GetSessionById(userId);
if (IsBypassingChecks(player))
return;
if (!_tracking.TryGetTrackerTimes(player, out var playTimes))
{
// Sorry mate but your playtimes haven't loaded.
@@ -219,18 +236,24 @@ public sealed class PlayTimeTrackingSystem : EntitySystem
playTimes ??= new Dictionary<string, TimeSpan>();
}
var isAdmin = _adminManager.IsAdmin(player, true); // WD
for (var i = 0; i < jobs.Count; i++)
{
if (_prototypes.TryIndex(jobs[i], out var job)
&& JobRequirements.TryRequirementsMet(job, playTimes, out _, EntityManager, _prototypes, (HumanoidCharacterProfile?) _preferencesManager.GetPreferences(userId).SelectedCharacter, isAdmin)) // WD EDIT
{
continue;
}
var job = jobs[i];
jobs.RemoveSwap(i);
i--;
if (!_prototypes.TryIndex<JobPrototype>(job, out var jobber) ||
jobber.Requirements == null ||
jobber.Requirements.Count == 0)
continue;
foreach (var requirement in jobber.Requirements)
{
if (JobRequirements.TryRequirementMet(requirement, playTimes, out _, EntityManager, _prototypes))
continue;
jobs.RemoveSwap(i);
i--;
break;
}
}
}

View File

@@ -1,4 +1,4 @@
using Content.Server.Lightning;
using Content.Server.Beam;
using Content.Shared.Revenant.Components;
using Content.Shared.Revenant.EntitySystems;
@@ -9,7 +9,7 @@ namespace Content.Server.Revenant.EntitySystems;
/// </summary>
public sealed class RevenantOverloadedLightsSystem : SharedRevenantOverloadedLightsSystem
{
[Dependency] private readonly LightningSystem _lightning = default!; // WD EDIT
[Dependency] private readonly BeamSystem _beam = default!;
protected override void OnZap(Entity<RevenantOverloadedLightsComponent> lights)
{
@@ -25,6 +25,6 @@ public sealed class RevenantOverloadedLightsSystem : SharedRevenantOverloadedLig
if (distance > component.ZapRange)
return;
_lightning.ShootLightning(lights, component.Target.Value, component.ZapBeamEntityId, false); // WD EDIT
_beam.TryCreateBeam(lights, component.Target.Value, component.ZapBeamEntityId);
}
}

View File

@@ -5,10 +5,20 @@ namespace Content.Server.Speech.EntitySystems
{
public sealed class OwOAccentSystem : EntitySystem
{
[Dependency] private readonly IRobustRandom _random = default!;
private static readonly IReadOnlyList<string> Faces = new List<string>{
//WD-EDIT
" (`ω´)", " ;;w;;", " owo", " UwU", " >w<", " ^w^"
//WD-EDIT
}.AsReadOnly();
private static readonly IReadOnlyDictionary<string, string> SpecialWords = new Dictionary<string, string>()
{
{ "you", "wu" },
{ "ты", "ти" } // WD
//WD-EDIT
{ "ты", "ти" }
//WD-EDIT
};
public override void Initialize()
@@ -23,7 +33,8 @@ namespace Content.Server.Speech.EntitySystems
message = message.Replace(word, repl);
}
return message.Replace("r", "w").Replace("R", "W")
return message.Replace("!", _random.Pick(Faces))
.Replace("r", "w").Replace("R", "W")
.Replace("l", "w").Replace("L", "W")
//WD-EDIT

View File

@@ -345,8 +345,8 @@ public sealed partial class StationJobsSystem
foreach (var (player, profile) in profiles)
{
var roleBans = _banManager.GetJobBans(player);
var profileJobs = profile.JobPriorities.Keys.Select(k => new ProtoId<JobPrototype>(k)).ToList();
_playTime.RemoveDisallowedJobs(player, profileJobs);
var profileJobs = profile.JobPriorities.Keys.ToList();
_playTime.RemoveDisallowedJobs(player, ref profileJobs);
List<string>? availableJobs = null;

View File

@@ -12,7 +12,6 @@ using Content.Shared.Access.Systems;
using Content.Shared.CCVar;
using Content.Shared.Clothing;
using Content.Shared.Humanoid;
using Content.Server.Roles.Jobs;
using Content.Shared.Humanoid.Prototypes;
using Content.Shared.PDA;
using Content.Shared.Preferences;
@@ -50,7 +49,6 @@ public sealed class StationSpawningSystem : SharedStationSpawningSystem
[Dependency] private readonly SharedAccessSystem _accessSystem = default!;
[Dependency] private readonly IdentitySystem _identity = default!;
[Dependency] private readonly MetaDataSystem _metaSystem = default!;
[Dependency] private readonly JobSystem _jobs = default!; // WD EDIT
[Dependency] private readonly ArrivalsSystem _arrivalsSystem = default!;
[Dependency] private readonly ContainerSpawnPointSystem _containerSpawnPointSystem = default!;
@@ -339,14 +337,7 @@ public sealed class StationSpawningSystem : SharedStationSpawningSystem
_accessSystem.SetAccessToJob(cardId, jobPrototype, extendedAccess);
if (pdaComponent != null)
{
_pdaSystem.SetOwnerName(idUid.Value, pdaComponent, characterName);
//WD EDIT START
_pdaSystem.SetOwnerJob(idUid.Value, pdaComponent, jobPrototype.LocalizedName);
_jobs.TryGetDepartment(jobPrototype.ID, out var department);
_pdaSystem.SetOwnerDepartment(idUid.Value, pdaComponent, department?.ID ?? "Specific");
//WD EDIT END
}
_pdaSystem.SetOwner(idUid.Value, pdaComponent, characterName);
}

View File

@@ -43,7 +43,7 @@ public sealed partial class BuyerDepartmentCondition : ListingCondition
{
foreach (var department in prototypeManager.EnumeratePrototypes<DepartmentPrototype>())
{
if (department.Roles.Contains(job.Prototype.Value) && Blacklist.Contains(department.ID))
if (department.Roles.Contains(job.Prototype) && Blacklist.Contains(department.ID))
return false;
}
}
@@ -56,7 +56,7 @@ public sealed partial class BuyerDepartmentCondition : ListingCondition
{
foreach (var department in prototypeManager.EnumeratePrototypes<DepartmentPrototype>())
{
if (department.Roles.Contains(job.Prototype.Value) && Whitelist.Contains(department.ID))
if (department.Roles.Contains(job.Prototype) && Whitelist.Contains(department.ID))
{
found = true;
break;

View File

@@ -257,7 +257,7 @@ namespace Content.Server.VendingMachines
private void OnWithdrawMessage(EntityUid uid, VendingMachineComponent component, VendingMachineWithdrawMessage args)
{
_stackSystem.Spawn(component.Credits, PrototypeManager.Index(component.CreditStackPrototype),
_stackSystem.Spawn(component.Credits, PrototypeManager.Index(component.CreditStackPrototype),
Transform(uid).Coordinates);
component.Credits = 0;
Audio.PlayPvs(component.SoundWithdrawCurrency, uid);
@@ -583,7 +583,7 @@ namespace Content.Server.VendingMachines
if (!Resolve(uid, ref vendComponent))
return;
RestockInventoryFromPrototype(uid, vendComponent, false);
RestockInventoryFromPrototype(uid, vendComponent);
UpdateVendingMachineInterfaceState(uid, vendComponent);
TryUpdateVisualState(uid, vendComponent);

View File

@@ -1,7 +0,0 @@
namespace Content.Server._White.AspectsSystem.Aspects.Components;
[RegisterComponent]
public sealed partial class ImmersiveAspectComponent : Component
{
}

View File

@@ -1,100 +0,0 @@
using System.Numerics;
using Content.Server.GameTicking.Rules.Components;
using Content.Server._White.AspectsSystem.Aspects.Components;
using Content.Server._White.AspectsSystem.Base;
using Content.Server.GameTicking;
using Content.Shared._White.Telescope;
using Content.Shared.Humanoid;
using Content.Shared.Movement.Components;
using Content.Shared.Movement.Systems;
namespace Content.Server._White.AspectsSystem.Aspects;
public sealed class ImmersiveAspect : AspectSystem<ImmersiveAspectComponent>
{
[Dependency] private readonly SharedContentEyeSystem _eye = default!;
[Dependency] private readonly SharedTelescopeSystem _telescope = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<PlayerSpawnCompleteEvent>(HandleLateJoin);
}
protected override void Started(EntityUid uid, ImmersiveAspectComponent component, GameRuleComponent gameRule,
GameRuleStartedEvent args)
{
base.Started(uid, component, gameRule, args);
WayToHRPPlusPlus();
}
private void WayToHRPPlusPlus()
{
var humans = EntityQuery<HumanoidAppearanceComponent>();
foreach (var human in humans)
{
var entity = human.Owner;
if (!HasComp<ContentEyeComponent>(entity))
continue;
FuckUpEye(entity, 0.6f);
AddTelescope(entity);
}
}
private void FuckUpEye(EntityUid human, float modifier)
{
_eye.SetMaxZoom(human, new Vector2(modifier));
_eye.SetZoom(human, new Vector2(modifier));
}
private void AddTelescope(EntityUid human)
{
var telescope = EnsureComp<TelescopeComponent>(human);
_telescope.SetParameters((human, telescope), 0.15f, 0.07f);
}
private void HandleLateJoin(PlayerSpawnCompleteEvent ev)
{
if (!ev.LateJoin)
return;
if (!HasComp<ContentEyeComponent>(ev.Mob))
return;
var query = EntityQueryEnumerator<ImmersiveAspectComponent, GameRuleComponent>();
while (query.MoveNext(out var ruleEntity, out _, out var gameRule))
{
if (!GameTicker.IsGameRuleAdded(ruleEntity, gameRule))
continue;
FuckUpEye(ev.Mob, 0.6f);
AddTelescope(ev.Mob);
}
}
protected override void Ended(EntityUid uid, ImmersiveAspectComponent component, GameRuleComponent gameRule, GameRuleEndedEvent args)
{
base.Ended(uid, component, gameRule, args);
var humans = EntityQuery<HumanoidAppearanceComponent>();
foreach (var human in humans)
{
var entity = human.Owner;
if (!HasComp<ContentEyeComponent>(entity))
continue;
FuckUpEye(entity, 1f);
RemComp<TelescopeComponent>(entity);
}
}
}

View File

@@ -1,33 +0,0 @@
using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.Reagent;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
namespace Content.Server._White.AutoRegenReagent
{
[RegisterComponent]
public sealed partial class AutoRegenReagentComponent : Component
{
[DataField("solution", required: true)]
public string? SolutionName = null; // we'll fail during tests otherwise
[DataField("reagents", required: true)]
public List<string> Reagents = default!;
[DataField]
public string CurrentReagent = "";
[DataField]
public int CurrentIndex = 0;
public Entity<SolutionComponent>? Solution = default!;
[DataField("interval")]
public TimeSpan Interval = TimeSpan.FromSeconds(10);
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer))]
public TimeSpan NextUpdate;
[DataField("unitsPerInterval")]
public float UnitsPerInterval = 1f;
}
}

View File

@@ -1,127 +0,0 @@
using Content.Server.Chemistry.Containers.EntitySystems;
using Content.Server.Chemistry.EntitySystems;
using Content.Server.Popups;
using Content.Shared.Examine;
using Content.Shared.Interaction.Events;
using Content.Shared.Verbs;
using Robust.Shared.Timing;
namespace Content.Server._White.AutoRegenReagent
{
/// <summary>
/// So we have a solution name in AutoRegenReagent comp. We will try to get it and start generating reagents. When we switch reagents we clear the solution and start generating different reagent.
/// </summary>
public sealed class AutoRegenReagentSystem : EntitySystem
{
[Dependency] private readonly SolutionContainerSystem _solutionSystem = default!;
[Dependency] private readonly PopupSystem _popups = default!;
[Dependency] private readonly IGameTiming _timing = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<AutoRegenReagentComponent, ComponentInit>(OnCompInit);
SubscribeLocalEvent<AutoRegenReagentComponent, GetVerbsEvent<AlternativeVerb>>(AddSwitchVerb);
SubscribeLocalEvent<AutoRegenReagentComponent, ExaminedEvent>(OnExamined);
SubscribeLocalEvent<AutoRegenReagentComponent, UseInHandEvent>(OnUseInHand,
before: new[] { typeof(ChemistrySystem) });
}
public override void Update(float frameTime)
{
base.Update(frameTime);
var query = EntityQueryEnumerator<AutoRegenReagentComponent>();
while (query.MoveNext(out var uid, out var autoComp))
{
if (_timing.CurTime < autoComp.NextUpdate)
return;
autoComp.NextUpdate += autoComp.Interval;
if (autoComp.Solution == null)
TryGetSolution(uid, autoComp);
if (autoComp.Solution == null)
return;
_solutionSystem.TryAddReagent(autoComp.Solution.Value, autoComp.CurrentReagent, autoComp.UnitsPerInterval);
}
}
private void OnCompInit(EntityUid uid, AutoRegenReagentComponent component, ComponentInit args)
{
component.NextUpdate = _timing.CurTime + component.Interval;
SwitchReagent(component);
}
private void OnUseInHand(EntityUid uid, AutoRegenReagentComponent component, UseInHandEvent args)
{
if (args.Handled)
return;
if (component.Reagents.Count <= 1)
return;
SwitchReagent(component, args.User);
args.Handled = true;
}
private void OnExamined(EntityUid uid, AutoRegenReagentComponent component, ExaminedEvent args)
{
args.PushMarkup(Loc.GetString("reagent-name", ("reagent", component.CurrentReagent)));
}
private void AddSwitchVerb(EntityUid uid, AutoRegenReagentComponent component,
GetVerbsEvent<AlternativeVerb> args)
{
if (!args.CanInteract || !args.CanAccess)
return;
if (component.Reagents.Count <= 1)
return;
AlternativeVerb verb = new()
{
Act = () =>
{
SwitchReagent(component, args.User);
},
Text = Loc.GetString("autoreagent-switch"),
Priority = 2
};
args.Verbs.Add(verb);
}
private void TryGetSolution(EntityUid uid, AutoRegenReagentComponent component)
{
if (component.SolutionName == null)
return;
if (!_solutionSystem.TryGetSolution(uid, component.SolutionName, out var solution))
return;
component.Solution = solution;
component.CurrentReagent = component.Reagents[component.CurrentIndex];
}
private string SwitchReagent(AutoRegenReagentComponent component, EntityUid? user = null)
{
if (component.CurrentIndex + 1 == component.Reagents.Count)
component.CurrentIndex = 0;
else
component.CurrentIndex++;
if (component.Solution != null)
_solutionSystem.RemoveAllSolution(component.Solution.Value);
component.CurrentReagent = component.Reagents[component.CurrentIndex];
if (user != null)
_popups.PopupEntity(Loc.GetString("autoregen-switched", ("reagent", component.CurrentReagent)), user.Value, user.Value);
return component.CurrentReagent;
}
}
}

View File

@@ -1,20 +0,0 @@
namespace Content.Server._White.CartridgeLoader.Cartridges;
[RegisterComponent]
public sealed partial class MessagesCartridgeComponent : Component
{
/// <summary>
/// The component of the last contacted server
/// </summary>
[DataField]
public EntityUid? LastServer;
/// <summary>
/// The message system user id of the crew the user is chatting with
/// </summary>
[DataField]
public int? ChatUid;
[DataField]
public int? UserUid;
}

View File

@@ -1,288 +0,0 @@
using System.Linq;
using Content.Server._White.Radio.Components;
using Content.Server._White.Radio.EntitySystems;
using Content.Server.CartridgeLoader;
using Content.Shared.CartridgeLoader;
using Content.Shared.PDA;
using Content.Server.GameTicking;
using Robust.Shared.Timing;
using Content.Server.DeviceNetwork.Systems;
using Content.Shared.DeviceNetwork;
using Content.Server.Station.Systems;
using Content.Shared._White.CartridgeLoader.Cartridges;
namespace Content.Server._White.CartridgeLoader.Cartridges;
public sealed class MessagesCartridgeSystem : EntitySystem
{
[Dependency] private readonly CartridgeLoaderSystem _cartridgeLoaderSystem = default!;
[Dependency] private readonly IGameTiming _gameTiming = default!;
[Dependency] private readonly GameTicker _gameTicker = default!;
[Dependency] private readonly MessagesServerSystem _messagesServerSystem = default!;
[Dependency] private readonly DeviceNetworkSystem _deviceNetworkSystem = default!;
[Dependency] private readonly SingletonDeviceNetServerSystem _singletonServerSystem = default!;
[Dependency] private readonly StationSystem _stationSystem = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<MessagesCartridgeComponent, CartridgeMessageEvent>(OnUiMessage);
SubscribeLocalEvent<MessagesCartridgeComponent, CartridgeUiReadyEvent>(OnUiReady);
SubscribeLocalEvent<MessagesCartridgeComponent, DeviceNetworkPacketEvent>(OnPacketReceived);
SubscribeLocalEvent<MessagesCartridgeComponent, CartridgeActivatedEvent>(OnCartActivation);
SubscribeLocalEvent<MessagesCartridgeComponent, CartridgeDeactivatedEvent>(OnCartDeactivation);
SubscribeLocalEvent<MessagesCartridgeComponent, CartridgeAddedEvent>(OnCartInsertion);
SubscribeLocalEvent<MessagesCartridgeComponent, ComponentInit>(OnInit);
SubscribeLocalEvent<MessagesCartridgeComponent, ComponentRemove>(OnRemove);
}
private void OnInit(EntityUid uid, MessagesCartridgeComponent component, ComponentInit args)
{
var stationId = _stationSystem.GetOwningStation(uid);
if (!stationId.HasValue ||
!_singletonServerSystem.TryGetActiveServerAddress<MessagesServerComponent>(stationId.Value,
out var address) || !TryComp(uid, out CartridgeComponent? cartComponent))
return;
SendName(uid, component, cartComponent, address);
component.UserUid = cartComponent.LoaderUid?.Id;
}
private void OnRemove(EntityUid uid, MessagesCartridgeComponent component, ComponentRemove args)
{
if (component.LastServer == null || !TryComp<MessagesServerComponent>(component.LastServer, out var messagesServerComponent) || component.UserUid == null)
return;
messagesServerComponent.Dictionary.Remove(component.UserUid.Value);
}
/// <summary>
/// This gets called when the ui fragment needs to be updated for the first time after activating
/// </summary>
private void OnUiReady(EntityUid uid, MessagesCartridgeComponent component, CartridgeUiReadyEvent args)
{
var stationId = _stationSystem.GetOwningStation(uid);
if (stationId.HasValue && _singletonServerSystem.TryGetActiveServerAddress<MessagesServerComponent>(stationId.Value, out var address) && TryComp(uid, out CartridgeComponent? cartComponent))
SendName(uid, component, cartComponent, address);
UpdateUiState(uid, component);
}
/// <summary>
/// The ui messages received here get wrapped by a CartridgeMessageEvent and are relayed from the <see cref="CartridgeLoaderSystem"/>
/// </summary>
/// <remarks>
/// The cartridge specific ui message event needs to inherit from the CartridgeMessageEvent
/// </remarks>
private void OnUiMessage(EntityUid uid, MessagesCartridgeComponent component, CartridgeMessageEvent args)
{
if (args is not MessagesUiMessageEvent messageEvent)
return;
if (messageEvent.Action == MessagesUiAction.Send && HasComp<CartridgeComponent>(uid) && component.UserUid is { } userId && component.ChatUid != null && messageEvent.StringInput != null)
{
var stationId = _stationSystem.GetOwningStation(uid);
if (!stationId.HasValue)
return;
var content = messageEvent.StringInput;
if (content.Length > 1000)
content = content.Substring(0, 997) + "...";
MessagesMessageData messageData = new()
{
SenderId = userId,
ReceiverId = component.ChatUid.Value,
Content = content,
Time = _gameTiming.CurTime.Subtract(_gameTicker.RoundStartTimeSpan)
};
var packet = new NetworkPayload()
{
[MessagesNetworkKeys.Message] = messageData
};
_singletonServerSystem.TryGetActiveServerAddress<MessagesServerComponent>(stationId.Value, out var address);
_deviceNetworkSystem.QueuePacket(uid, address, packet);
}
else
{
if (messageEvent.Action == MessagesUiAction.ChangeChat)
component.ChatUid = messageEvent.TargetChatUid;
}
UpdateUiState(uid, component);
}
/// <summary>
/// On cart insertion, register as background process.
/// </summary>
private void OnCartInsertion(EntityUid uid, MessagesCartridgeComponent component, CartridgeAddedEvent args)
{
_cartridgeLoaderSystem.RegisterBackgroundProgram(args.Loader, uid);
component.UserUid = args.Loader.Id;
}
/// <summary>
/// On cartridge activation, connect to messages network.
/// </summary>
private void OnCartActivation(EntityUid uid, MessagesCartridgeComponent component, CartridgeActivatedEvent args)
{
_deviceNetworkSystem.ConnectDevice(uid);
var stationId = _stationSystem.GetOwningStation(uid);
if (stationId.HasValue && _singletonServerSystem.TryGetActiveServerAddress<MessagesServerComponent>(stationId.Value, out var address) && TryComp(uid, out CartridgeComponent? cartComponent))
SendName(uid, component, cartComponent, address);
}
/// <summary>
/// On cartridge deactivation, disconnect from messages network.
/// </summary>
private void OnCartDeactivation(EntityUid uid, MessagesCartridgeComponent component, CartridgeDeactivatedEvent args)
{
_deviceNetworkSystem.DisconnectDevice(uid, null);
}
/// <summary>
/// React and respond to packets from the server
/// </summary>
private void OnPacketReceived(EntityUid uid, MessagesCartridgeComponent component, DeviceNetworkPacketEvent args)
{
if (!TryComp(uid, out CartridgeComponent? cartComponent))
return;
component.LastServer = args.Sender;
if (args.Data.TryGetValue<MessagesMessageData>(MessagesNetworkKeys.Message, out var message) && cartComponent.LoaderUid != null)
{
if (message.ReceiverId == cartComponent.LoaderUid.Value.Id)
{
TryGetName(message.SenderId, component, out var name);
var subtitleString = Loc.GetString("messages-pda-notification-header", ("name", name));
_cartridgeLoaderSystem.SendNotification(
cartComponent.LoaderUid.Value,
subtitleString,
message.Content);
}
}
UpdateUiState(uid, component);
}
/// <summary>
/// Updates the user's name in the storage component.
/// </summary>
private void SendName(EntityUid uid, MessagesCartridgeComponent component, CartridgeComponent cartComponent, string? address)
{
TryGetMessagesUser(component, cartComponent, out var messagesUser);
var packet = new NetworkPayload()
{
[MessagesNetworkKeys.UserId] = component.UserUid,
[MessagesNetworkKeys.NewUser] = messagesUser
};
_deviceNetworkSystem.QueuePacket(uid, address, packet);
}
/// <summary>
/// Retrieves the name of the given user from the last contacted server
/// </summary>
private void TryGetName(int key, MessagesCartridgeComponent component, out string name)
{
if (component.LastServer != null && _messagesServerSystem.TryGetUserFromDict(component.LastServer, key, out var messagesUser))
{
name = messagesUser.Name;
return;
}
name = Loc.GetString("messages-pda-connection-error");
}
/// <summary>
/// Returns the user's name, job title and job department
/// </summary>
public bool TryGetMessagesUser(MessagesCartridgeComponent component, CartridgeComponent cartridgeComponent, out MessagesUserData messagesUserData)
{
messagesUserData = new MessagesUserData();
if (component.LastServer != null &&
TryComp<MessagesServerComponent>(component.LastServer, out var messagesServerComponent) &&
component.UserUid != null)
messagesUserData = messagesServerComponent.Dictionary[component.UserUid.Value];
var pda = cartridgeComponent.LoaderUid;
if (pda == null)
return false;
var pdaComponent = CompOrNull<PdaComponent>(pda);
if (pdaComponent?.OwnerName == null)
return false;
messagesUserData.SetMessagesUser(pdaComponent.OwnerName, pdaComponent.OwnerJob, pdaComponent.OwnerDepartment);
return true;
}
private void UpdateUiState(EntityUid uid, MessagesCartridgeComponent? component = null)
{
if (!Resolve(uid, ref component))
return;
if (!TryComp(uid, out CartridgeComponent? cartComponent))
return;
if (cartComponent.LoaderUid == null)
return;
var loaderUid = cartComponent.LoaderUid.Value;
MessagesUiState state;
var currentUserId = component.UserUid;
if (currentUserId == null || component.LastServer == null)
{
state = new MessagesUiState(MessagesUiStateMode.Error);
_cartridgeLoaderSystem.UpdateCartridgeUiState(loaderUid, state);
return;
}
if (component.ChatUid == null) //if no chat is loaded, list users
{
List<(MessagesUserData, int?)> userList = [];
var dictionary = _messagesServerSystem.GetNameDict(component.LastServer);
foreach (var nameEntry in dictionary.Keys)
{
if (nameEntry == currentUserId)
continue;
userList.Add((dictionary[nameEntry], nameEntry));
}
userList.Sort((a, b) => TimeSpan.Compare(b.Item1.Messages.LastOrDefault().Time, a.Item1.Messages.LastOrDefault().Time));
state = new MessagesUiState(MessagesUiStateMode.UserList, userList);
}
else
{
List<MessagesMessageData> messageList = []; //Else, list messages from the current chat
foreach (var message in _messagesServerSystem.GetMessages(component.LastServer, component.ChatUid.Value, currentUserId.Value))
{
if (message.SenderId == component.ChatUid && message.ReceiverId == currentUserId || message.ReceiverId == component.ChatUid && message.SenderId == currentUserId)
messageList.Add(message);
}
messageList.Sort((a, b) => TimeSpan.Compare(a.Time, b.Time));
List<(string, int?)> formattedMessageList = [];
foreach (var message in messageList)
{
TryGetName(message.SenderId, component, out var name);
var stationTime = message.Time.Subtract(_gameTicker.RoundStartTimeSpan);
var content = $"{stationTime:\\[hh\\:mm\\:ss\\]} {name}: {message.Content}";
formattedMessageList.Add((content, null));
}
TryGetName(component.ChatUid.Value, component, out var user);
state = new MessagesUiState(MessagesUiStateMode.Chat, null, formattedMessageList, user);
}
_cartridgeLoaderSystem.UpdateCartridgeUiState(loaderUid, state);
}
}

View File

@@ -58,7 +58,7 @@ public sealed class RandomHumanSystem : EntitySystem
var cardId = pdaComponent.ContainedId.Value;
_card.TryChangeFullName(cardId, newProfile.Name, card);
_pda.SetOwnerName(idUid.Value, pdaComponent, newProfile.Name);
_pda.SetOwner(idUid.Value, pdaComponent, newProfile.Name);
if (EntityManager.TryGetComponent(cardId, out StationRecordKeyStorageComponent? keyStorage)
&& keyStorage.Key is { } key)

View File

@@ -1,20 +0,0 @@
using Content.Server.Power.Components;
using Content.Shared._White.CartridgeLoader.Cartridges;
namespace Content.Server._White.Radio.Components;
/// <summary>
/// Entities with <see cref="MessagesServerComponent"/> are needed to transmit messages using PDAs.
/// They also need to be powered by <see cref="ApcPowerReceiverComponent"/>
/// in order for them to work on the same map as server.
/// </summary>
[RegisterComponent]
public sealed partial class MessagesServerComponent : Component
{
/// <summary>
/// Dictionary translating IDs to MessagesUser
/// </summary>
[DataField]
public Dictionary<int, MessagesUserData> Dictionary = new();
}

View File

@@ -1,134 +0,0 @@
using System.Linq;
using Content.Server._White.CartridgeLoader.Cartridges;
using Content.Server._White.Radio.Components;
using Content.Server.Administration.Logs;
using Content.Server.Chat.Systems;
using Content.Server.DeviceNetwork.Systems;
using Content.Shared._White.CartridgeLoader.Cartridges;
using Content.Shared.CartridgeLoader;
using Content.Shared.Database;
using Content.Shared.DeviceNetwork;
namespace Content.Server._White.Radio.EntitySystems;
public sealed class MessagesServerSystem : EntitySystem
{
[Dependency] private readonly DeviceNetworkSystem _deviceNetworkSystem = default!;
[Dependency] private readonly SingletonDeviceNetServerSystem _singletonServerSystem = default!;
[Dependency] private readonly MessagesCartridgeSystem _messagesSystem = default!;
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
[Dependency] private readonly ChatSystem _chat = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<MessagesServerComponent, DeviceNetworkPacketEvent>(OnPacketReceived);
SubscribeLocalEvent<MessagesServerComponent, ComponentInit>(OnInit);
}
private void OnInit(EntityUid uid, MessagesServerComponent component, ComponentInit args)
{
var query = EntityQueryEnumerator<MessagesCartridgeComponent>();
while (query.MoveNext(out var entityUid, out var cartridge))
{
if (!TryComp(entityUid, out CartridgeComponent? cartComponent))
continue;
_messagesSystem.TryGetMessagesUser(cartridge, cartComponent, out var messagesUser);
if (cartridge.UserUid == null || messagesUser.Name == Loc.GetString("messages-pda-unknown-name"))
continue;
component.Dictionary[cartridge.UserUid.Value] = messagesUser;
cartridge.LastServer = uid;
}
}
/// <summary>
/// Reacts to packets received from clients
/// </summary>
private void OnPacketReceived(EntityUid uid, MessagesServerComponent component, DeviceNetworkPacketEvent args)
{
if (!_singletonServerSystem.IsActiveServer(uid))
return;
if (args.Data.TryGetValue<MessagesUserData>(MessagesNetworkKeys.NewUser, out var messagesUser) && args.Data.TryGetValue<int>(MessagesNetworkKeys.UserId, out var userId))
{
component.Dictionary[userId] = messagesUser;
var packet = new NetworkPayload();
_deviceNetworkSystem.QueuePacket(uid, args.SenderAddress, packet);
}
if (args.Data.TryGetValue<MessagesMessageData>(MessagesNetworkKeys.Message, out var message))
SendMessage(uid, component, message);
}
/// <summary>
/// Broadcasts a message into the network
/// </summary>
private void SendMessage(EntityUid uid, MessagesServerComponent component, MessagesMessageData message)
{
component.Dictionary[message.ReceiverId].Messages.Add(message);
component.Dictionary[message.SenderId].Messages.Add(message);
_adminLogger.Add(LogType.DeviceNetwork, $"{Loc.GetString("chat-manager-send-message", ("sender", component.Dictionary[message.SenderId].Name + $" ({message.SenderId})"), ("receiver", component.Dictionary[message.ReceiverId].Name + $" ({message.ReceiverId})"), ("message", message.Content))}");
_chat.SendNetworkChat(uid, Loc.GetString("chat-manager-send-message", ("sender", component.Dictionary[message.SenderId].Name), ("receiver", component.Dictionary[message.ReceiverId].Name), ("message", message.Content)), false);
var packet = new NetworkPayload()
{
[MessagesNetworkKeys.Message] = message
};
_deviceNetworkSystem.QueuePacket(uid, null, packet);
}
/// <summary>
/// Returns user
/// </summary>
public bool TryGetUserFromDict(EntityUid? uid, int key, out MessagesUserData messagesUserData)
{
messagesUserData = new MessagesUserData();
if (!TryComp(uid, out MessagesServerComponent? component) || !component.Dictionary.TryGetValue(key, out var keyValue))
return false;
messagesUserData = keyValue;
return true;
}
/// <summary>
/// Returns the user dictionary cache
/// </summary>
public Dictionary<int, MessagesUserData> GetNameDict(EntityUid? uid)
{
return !TryComp(uid, out MessagesServerComponent? component) ? new Dictionary<int, MessagesUserData>() : component.Dictionary;
}
/// <summary>
/// Returns list of messages between the two users
/// </summary>
public List<MessagesMessageData> GetMessages(EntityUid? uid, int id1, int id2)
{
if (!TryComp(uid, out MessagesServerComponent? component))
return [];
return
[
..component.Dictionary[id1]
.Messages.Where(message =>
message.SenderId == id1 && message.ReceiverId == id2 ||
message.SenderId == id2 && message.ReceiverId == id1)
];
}
}
public static class MessagesNetworkKeys
{
public const string NewUser = "new_user";
public const string UserId = "user_id";
public const string Message = "message";
}

View File

@@ -1,4 +1,4 @@
using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.CodeAnalysis;
using Content.Shared._White.Telescope;
using Content.Shared._White.WeaponModules;
using Content.Shared.Weapons.Ranged.Components;
@@ -128,7 +128,7 @@ public sealed class WeaponModulesSystem : EntitySystem
return;
weaponModulesComponent.WeaponFireEffect = true;
Dirty(weapon, weaponModulesComponent);
Dirty(module, weaponModulesComponent);
}
private void SilencerModuleOnInsert(EntityUid module, SilencerModuleComponent component, EntGotInsertedIntoContainerMessage args)
@@ -145,7 +145,7 @@ public sealed class WeaponModulesSystem : EntitySystem
weaponModulesComponent.WeaponFireEffect = true;
_gunSystem.SetSound(weapon, component.NewSoundGunshot);
Dirty(weapon, weaponModulesComponent);
Dirty(module, weaponModulesComponent);
}
private void AcceleratorModuleOnInsert(EntityUid module, AcceleratorModuleComponent component, EntGotInsertedIntoContainerMessage args)
@@ -224,7 +224,7 @@ public sealed class WeaponModulesSystem : EntitySystem
return;
weaponModulesComponent.WeaponFireEffect = false;
Dirty(weapon, weaponModulesComponent);
Dirty(module, weaponModulesComponent);
}
private void SilencerModuleOnEject(EntityUid module, SilencerModuleComponent component, EntGotRemovedFromContainerMessage args)
@@ -236,7 +236,7 @@ public sealed class WeaponModulesSystem : EntitySystem
weaponModulesComponent.WeaponFireEffect = false;
_gunSystem.SetSound(weapon, component.OldSoundGunshot!);
Dirty(weapon, weaponModulesComponent);
Dirty(module, weaponModulesComponent);
}
private void AcceleratorModuleOnEject(EntityUid module, AcceleratorModuleComponent component, EntGotRemovedFromContainerMessage args)

View File

@@ -1,5 +1,3 @@
using Content.Shared.Maps;
using Content.Shared.Roles;
using Robust.Shared;
using Robust.Shared.Configuration;
@@ -237,12 +235,6 @@ namespace Content.Shared.CCVar
public static readonly CVarDef<bool>
GameRoleTimers = CVarDef.Create("game.role_timers", true, CVar.SERVER | CVar.REPLICATED);
/// <summary>
/// Override default role requirements using a <see cref="JobRequirementOverridePrototype"/>
/// </summary>
public static readonly CVarDef<string>
GameRoleTimerOverride = CVarDef.Create("game.role_timer_override", "", CVar.SERVER | CVar.REPLICATED);
/// <summary>
/// Whether or not disconnecting inside of a cryopod should remove the character or just store them until they reconnect.
/// </summary>
@@ -874,52 +866,6 @@ namespace Content.Shared.CCVar
public static readonly CVarDef<bool> AdminBypassMaxPlayers =
CVarDef.Create("admin.bypass_max_players", true, CVar.SERVERONLY);
/// <summary>
/// Determine if custom rank names are used.
/// If it is false, it'd use the actual rank name regardless of the individual's title.
/// </summary>
/// <seealso cref="AhelpAdminPrefix"/>
/// <seealso cref="AhelpAdminPrefixWebhook"/>
public static readonly CVarDef<bool> AdminUseCustomNamesAdminRank =
CVarDef.Create("admin.use_custom_names_admin_rank", true, CVar.SERVERONLY);
/*
* AHELP
*/
/// <summary>
/// Ahelp rate limit values are accounted in periods of this size (seconds).
/// After the period has passed, the count resets.
/// </summary>
/// <seealso cref="AhelpRateLimitCount"/>
public static readonly CVarDef<int> AhelpRateLimitPeriod =
CVarDef.Create("ahelp.rate_limit_period", 2, CVar.SERVERONLY);
/// <summary>
/// How many ahelp messages are allowed in a single rate limit period.
/// </summary>
/// <seealso cref="AhelpRateLimitPeriod"/>
public static readonly CVarDef<int> AhelpRateLimitCount =
CVarDef.Create("ahelp.rate_limit_count", 10, CVar.SERVERONLY);
/// <summary>
/// Should the administrator's position be displayed in ahelp.
/// If it is is false, only the admin's ckey will be displayed in the ahelp.
/// </summary>
/// <seealso cref="AdminUseCustomNamesAdminRank"/>
/// <seealso cref="AhelpAdminPrefixWebhook"/>
public static readonly CVarDef<bool> AhelpAdminPrefix =
CVarDef.Create("ahelp.admin_prefix", true, CVar.SERVERONLY);
/// <summary>
/// Should the administrator's position be displayed in the webhook.
/// If it is is false, only the admin's ckey will be displayed in webhook.
/// </summary>
/// <seealso cref="AdminUseCustomNamesAdminRank"/>
/// <seealso cref="AhelpAdminPrefix"/>
public static readonly CVarDef<bool> AhelpAdminPrefixWebhook =
CVarDef.Create("ahelp.admin_prefix_webhook", true, CVar.SERVERONLY);
/*
* Explosions
*/

View File

@@ -33,7 +33,7 @@ public sealed partial class CartridgeLoaderComponent : Component
/// The maximum amount of programs that can be installed on the cartridge loader entity
/// </summary>
[DataField]
public int DiskSpace = 7; // WD EDIT
public int DiskSpace = 5;
/// <summary>
/// Controls whether the cartridge loader will play notifications if it supports it at all

View File

@@ -80,26 +80,23 @@ public enum ChatChannel : uint
/// </summary>
AdminChat = 1 << 13,
//WD EDIT START
/// <summary>
/// Changeling
/// </summary>
Changeling = 1 << 14,
//WD EDIT
Cult = 1 << 15,
Network = 1 << 16,
//WD EDIT END
/// <summary>
/// Unspecified.
/// </summary>
Unspecified = 1 << 17,
Unspecified = 1 << 16,
/// <summary>
/// Channels considered to be IC.
/// </summary>
IC = Local | Whisper | Radio | Dead | Emotes | Damage | Visual | Notifications | Cult | Changeling | Network,
IC = Local | Whisper | Radio | Dead | Emotes | Damage | Visual | Notifications | Cult | Changeling,
AdminRelated = Admin | AdminAlert | AdminChat,
}
}

View File

@@ -15,11 +15,8 @@ public static class ChatChannelExtensions
ChatChannel.AdminAlert => Color.Red,
ChatChannel.AdminChat => Color.HotPink,
ChatChannel.Whisper => Color.DarkGray,
// WD EDIT START
ChatChannel.Cult => Color.DarkRed,
ChatChannel.Changeling => Color.Purple,
ChatChannel.Network => Color.White,
// WD EDIT END
ChatChannel.Cult => Color.DarkRed, // WD EDIT
_ => Color.LightGray
};
}

View File

@@ -46,19 +46,15 @@
/// </summary>
Dead = ChatChannel.Dead,
// WD EDIT START
Cult = ChatChannel.Cult,
Changeling = ChatChannel.Changeling,
Network = ChatChannel.Network,
// WD EDIT END
/// <summary>
/// Admin chat
/// </summary>
Admin = ChatChannel.AdminChat,
Changeling = ChatChannel.Changeling,
Console = ChatChannel.Unspecified
}
}

View File

@@ -1,17 +1,13 @@
using Robust.Shared.Audio;
using Robust.Shared.GameStates;
namespace Content.Shared.Damage.Components;
[RegisterComponent]
[NetworkedComponent, AutoGenerateComponentState] // WD
public sealed partial class StaminaDamageOnHitComponent : Component
{
[ViewVariables(VVAccess.ReadWrite), DataField("damage")]
[AutoNetworkedField] // WD
public float Damage = 30f;
[DataField("sound")]
[AutoNetworkedField] // WD
public SoundSpecifier? Sound;
}

View File

@@ -1,38 +0,0 @@
using Robust.Shared.Prototypes;
namespace Content.Shared.Ghost.Roles;
/// <summary>
/// For selectable ghostrole prototypes in ghostrole spawners.
/// </summary>
[Prototype]
public sealed partial class GhostRolePrototype : IPrototype
{
[ViewVariables]
[IdDataField]
public string ID { get; private set; } = default!;
/// <summary>
/// The name of the ghostrole.
/// </summary>
[DataField(required: true)]
public string Name { get; set; } = default!;
/// <summary>
/// The description of the ghostrole.
/// </summary>
[DataField(required: true)]
public string Description { get; set; } = default!;
/// <summary>
/// The entity prototype of the ghostrole
/// </summary>
[DataField(required: true)]
public EntProtoId EntityPrototype;
/// <summary>
/// Rules of the ghostrole
/// </summary>
[DataField(required: true)]
public string Rules = default!;
}

View File

@@ -11,11 +11,6 @@ namespace Content.Shared.Ghost.Roles
public string Name { get; set; }
public string Description { get; set; }
public string Rules { get; set; }
// TODO ROLE TIMERS
// Actually make use of / enforce this requirement?
// Why is this even here.
// Move to ghost role prototype & respect CCvars.GameRoleTimerOverride
public HashSet<JobRequirement>? Requirements { get; set; }
/// <inheritdoc cref="GhostRoleKind"/>

View File

@@ -59,7 +59,6 @@ namespace Content.Shared.Input
public static readonly BoundKeyFunction ResetZoom = "ResetZoom";
public static readonly BoundKeyFunction LieDown = "LieDown"; // WD EDIT
public static readonly BoundKeyFunction OfferItem = "OfferItem"; // WD EDIT
public static readonly BoundKeyFunction LookUp = "LookUp"; // WD EDIT
public static readonly BoundKeyFunction ArcadeUp = "ArcadeUp";
public static readonly BoundKeyFunction ArcadeDown = "ArcadeDown";

View File

@@ -13,12 +13,12 @@ public sealed partial class ContentEyeComponent : Component
/// <summary>
/// Zoom we're lerping to.
/// </summary>
[DataField, AutoNetworkedField]
[DataField("targetZoom"), AutoNetworkedField]
public Vector2 TargetZoom = Vector2.One;
/// <summary>
/// How far we're allowed to zoom out.
/// </summary>
[ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField]
[ViewVariables(VVAccess.ReadWrite), DataField("maxZoom"), AutoNetworkedField]
public Vector2 MaxZoom = Vector2.One;
}

View File

@@ -2,7 +2,6 @@ using Robust.Shared.Prototypes;
using Robust.Shared.GameStates;
using Content.Shared.Access.Components;
using Content.Shared.Containers.ItemSlots;
using Content.Shared.Roles;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
namespace Content.Shared.PDA
@@ -38,8 +37,6 @@ namespace Content.Shared.PDA
[ViewVariables] public bool FlashlightOn;
[ViewVariables(VVAccess.ReadWrite)] public string? OwnerName;
[ViewVariables(VVAccess.ReadWrite)] public string? OwnerJob; // WD EDIT
[ViewVariables(VVAccess.ReadWrite)] public string? OwnerDepartment; // WD EDIT
[ViewVariables] public string? StationName;
[ViewVariables] public string? StationAlertLevel;
[ViewVariables] public Color StationAlertColor = Color.White;

View File

@@ -45,7 +45,6 @@ namespace Content.Shared.PDA
public struct PdaIdInfoText
{
public string? ActualOwnerName;
public string? ActualOwnerJob; // WD EDIT
public string? IdOwner;
public string? JobTitle;
public string? StationAlertLevel;

View File

@@ -707,7 +707,7 @@ namespace Content.Shared.Preferences
continue;
}
loadouts.EnsureValid(this, session, collection);
loadouts.EnsureValid(session, collection);
}
foreach (var value in toRemove)

View File

@@ -13,13 +13,13 @@ public sealed partial class GroupLoadoutEffect : LoadoutEffect
[DataField(required: true)]
public ProtoId<LoadoutEffectGroupPrototype> Proto;
public override bool Validate(HumanoidCharacterProfile profile, RoleLoadout loadout, ICommonSession session, IDependencyCollection collection, [NotNullWhen(false)] out FormattedMessage? reason)
public override bool Validate(RoleLoadout loadout, ICommonSession session, IDependencyCollection collection, [NotNullWhen(false)] out FormattedMessage? reason)
{
var effectsProto = collection.Resolve<IPrototypeManager>().Index(Proto);
foreach (var effect in effectsProto.Effects)
{
if (!effect.Validate(profile, loadout, session, collection, out reason))
if (!effect.Validate(loadout, session, collection, out reason))
return false;
}

View File

@@ -15,14 +15,12 @@ public sealed partial class JobRequirementLoadoutEffect : LoadoutEffect
[DataField(required: true)]
public JobRequirement Requirement = default!;
public override bool Validate(HumanoidCharacterProfile profile, RoleLoadout loadout, ICommonSession session, IDependencyCollection collection, [NotNullWhen(false)] out FormattedMessage? reason)
public override bool Validate(RoleLoadout loadout, ICommonSession session, IDependencyCollection collection, [NotNullWhen(false)] out FormattedMessage? reason)
{
var manager = collection.Resolve<ISharedPlaytimeManager>();
var playtimes = manager.GetPlayTimes(session);
return Requirement.Check(collection.Resolve<IEntityManager>(),
collection.Resolve<IPrototypeManager>(),
profile,
playtimes,
out reason);
return JobRequirements.TryRequirementMet(Requirement, playtimes, out reason,
collection.Resolve<IEntityManager>(),
collection.Resolve<IPrototypeManager>());
}
}

View File

@@ -11,7 +11,6 @@ public abstract partial class LoadoutEffect
/// Tries to validate the effect.
/// </summary>
public abstract bool Validate(
HumanoidCharacterProfile profile,
RoleLoadout loadout,
ICommonSession session,
IDependencyCollection collection,

View File

@@ -11,7 +11,6 @@ public sealed partial class PointsCostLoadoutEffect : LoadoutEffect
public int Cost = 1;
public override bool Validate(
HumanoidCharacterProfile profile,
RoleLoadout loadout,
ICommonSession session,
IDependencyCollection collection,

View File

@@ -44,7 +44,7 @@ public sealed class RoleLoadout
/// <summary>
/// Ensures all prototypes exist and effects can be applied.
/// </summary>
public void EnsureValid(HumanoidCharacterProfile profile, ICommonSession session, IDependencyCollection collection)
public void EnsureValid(ICommonSession session, IDependencyCollection collection)
{
var groupRemove = new ValueList<string>();
var protoManager = collection.Resolve<IPrototypeManager>();
@@ -81,7 +81,7 @@ public sealed class RoleLoadout
}
// Validate the loadout can be applied (e.g. points).
if (!IsValid(profile, session, loadout.Prototype, collection, out _))
if (!IsValid(session, loadout.Prototype, collection, out _))
{
loadouts.RemoveAt(i);
continue;
@@ -167,7 +167,7 @@ public sealed class RoleLoadout
/// <summary>
/// Returns whether a loadout is valid or not.
/// </summary>
public bool IsValid(HumanoidCharacterProfile profile, ICommonSession session, ProtoId<ItemLoadoutPrototype> loadout, IDependencyCollection collection, [NotNullWhen(false)] out FormattedMessage? reason)
public bool IsValid(ICommonSession session, ProtoId<ItemLoadoutPrototype> loadout, IDependencyCollection collection, [NotNullWhen(false)] out FormattedMessage? reason)
{
reason = null;
@@ -190,7 +190,7 @@ public sealed class RoleLoadout
foreach (var effect in loadoutProto.Effects)
{
valid = valid && effect.Validate(profile, this, session, collection, out reason);
valid = valid && effect.Validate(this, session, collection, out reason);
}
return valid;

View File

@@ -41,8 +41,6 @@ public sealed partial class AntagPrototype : IPrototype
/// <summary>
/// Requirements that must be met to opt in to this antag role.
/// </summary>
// TODO ROLE TIMERS
// Actually check if the requirements are met. Because apparently this is actually unused.
[DataField]
[DataField("requirements")]
public HashSet<JobRequirement>? Requirements;
}

View File

@@ -9,16 +9,16 @@ public sealed partial class DepartmentPrototype : IPrototype
[IdDataField] public string ID { get; } = default!;
/// <summary>
/// The name LocId of the department that will be displayed in the various menus.
/// A name string.
/// </summary>
[DataField(required: true)]
public LocId Name = string.Empty;
public string Name = default!;
/// <summary>
/// A description LocId to display in the character menu as an explanation of the department's function.
/// A description string to display in the character menu as an explanation of the department's function.
/// </summary>
[DataField(required: true)]
public LocId Description = string.Empty;
[DataField (required: true)]
public string Description = default!;
/// <summary>
/// A color representing this department to use for text.
@@ -26,8 +26,8 @@ public sealed partial class DepartmentPrototype : IPrototype
[DataField(required: true)]
public Color Color = default!;
[DataField, ViewVariables(VVAccess.ReadWrite)]
public List<ProtoId<JobPrototype>> Roles = new();
[ViewVariables(VVAccess.ReadWrite), DataField(customTypeSerializer: typeof(PrototypeIdListSerializer<JobPrototype>))]
public List<string> Roles = new();
/// <summary>
/// Whether this is a primary department or not.

View File

@@ -1,50 +0,0 @@
using System.Diagnostics.CodeAnalysis;
using Content.Shared.Preferences;
using JetBrains.Annotations;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.Utility;
namespace Content.Shared.Roles;
/// <summary>
/// Requires the character to be older or younger than a certain age (inclusive)
/// </summary>
[UsedImplicitly]
[Serializable, NetSerializable]
public sealed partial class AgeRequirement : JobRequirement
{
[DataField(required: true)]
public int RequiredAge;
public override bool Check(IEntityManager entManager,
IPrototypeManager protoManager,
HumanoidCharacterProfile? profile,
IReadOnlyDictionary<string, TimeSpan> playTimes,
[NotNullWhen(false)] out FormattedMessage? reason)
{
reason = new FormattedMessage();
if (profile is null) //the profile could be null if the player is a ghost. In this case we don't need to block the role selection for ghostrole
return true;
if (!Inverted)
{
reason = FormattedMessage.FromMarkupPermissive(Loc.GetString("role-timer-age-to-young",
("age", RequiredAge)));
if (profile.Age <= RequiredAge)
return false;
}
else
{
reason = FormattedMessage.FromMarkupPermissive(Loc.GetString("role-timer-age-to-old",
("age", RequiredAge)));
if (profile.Age >= RequiredAge)
return false;
}
return true;
}
}

View File

@@ -1,85 +0,0 @@
using System.Diagnostics.CodeAnalysis;
using Content.Shared.Preferences;
using JetBrains.Annotations;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.Utility;
namespace Content.Shared.Roles;
[UsedImplicitly]
[Serializable, NetSerializable]
public sealed partial class DepartmentTimeRequirement : JobRequirement
{
public override bool IgnoreIfAdmin => true; // WD
/// <summary>
/// Which department needs the required amount of time.
/// </summary>
[DataField(required: true)]
public ProtoId<DepartmentPrototype> Department = default!;
/// <summary>
/// How long (in seconds) this requirement is.
/// </summary>
[DataField(required: true)]
public TimeSpan Time;
public override bool Check(IEntityManager entManager,
IPrototypeManager protoManager,
HumanoidCharacterProfile? profile,
IReadOnlyDictionary<string, TimeSpan> playTimes,
[NotNullWhen(false)] out FormattedMessage? reason)
{
reason = new FormattedMessage();
var playtime = TimeSpan.Zero;
// Check all jobs' departments
var department = protoManager.Index(Department);
var jobs = department.Roles;
string proto;
// Check all jobs' playtime
foreach (var other in jobs)
{
// The schema is stored on the Job role but we want to explode if the timer isn't found anyway.
proto = protoManager.Index(other).PlayTimeTracker;
playTimes.TryGetValue(proto, out var otherTime);
playtime += otherTime;
}
var deptDiff = Time.TotalMinutes - playtime.TotalMinutes;
var nameDepartment = "role-timer-department-unknown";
if (protoManager.TryIndex(Department, out var departmentIndexed))
{
nameDepartment = departmentIndexed.Name;
}
if (!Inverted)
{
if (deptDiff <= 0)
return true;
reason = FormattedMessage.FromMarkupPermissive(Loc.GetString(
"role-timer-department-insufficient",
("time", Math.Ceiling(deptDiff)),
("department", Loc.GetString(nameDepartment)),
("departmentColor", department.Color.ToHex())));
return false;
}
if (deptDiff <= 0)
{
reason = FormattedMessage.FromMarkupPermissive(Loc.GetString(
"role-timer-department-too-high",
("time", -deptDiff),
("department", Loc.GetString(nameDepartment)),
("departmentColor", department.Color.ToHex())));
return false;
}
return true;
}
}

View File

@@ -1,52 +0,0 @@
using System.Diagnostics.CodeAnalysis;
using Content.Shared.Players.PlayTimeTracking;
using Content.Shared.Preferences;
using JetBrains.Annotations;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.Utility;
namespace Content.Shared.Roles;
[UsedImplicitly]
[Serializable, NetSerializable]
public sealed partial class OverallPlaytimeRequirement : JobRequirement
{
public override bool IgnoreIfAdmin => true; // WD
/// <inheritdoc cref="DepartmentTimeRequirement.Time"/>
[DataField(required: true)]
public TimeSpan Time;
public override bool Check(IEntityManager entManager,
IPrototypeManager protoManager,
HumanoidCharacterProfile? profile,
IReadOnlyDictionary<string, TimeSpan> playTimes,
[NotNullWhen(false)] out FormattedMessage? reason)
{
reason = new FormattedMessage();
var overallTime = playTimes.GetValueOrDefault(PlayTimeTrackingShared.TrackerOverall);
var overallDiff = Time.TotalMinutes - overallTime.TotalMinutes;
if (!Inverted)
{
if (overallDiff <= 0 || overallTime >= Time)
return true;
reason = FormattedMessage.FromMarkupPermissive(Loc.GetString(
"role-timer-overall-insufficient",
("time", Math.Ceiling(overallDiff))));
return false;
}
if (overallDiff <= 0 || overallTime >= Time)
{
reason = FormattedMessage.FromMarkupPermissive(Loc.GetString("role-timer-overall-too-high",
("time", -overallDiff)));
return false;
}
return true;
}
}

View File

@@ -1,75 +0,0 @@
using System.Diagnostics.CodeAnalysis;
using Content.Shared.Players.PlayTimeTracking;
using Content.Shared.Preferences;
using Content.Shared.Roles.Jobs;
using JetBrains.Annotations;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.Utility;
namespace Content.Shared.Roles;
[UsedImplicitly]
[Serializable, NetSerializable]
public sealed partial class RoleTimeRequirement : JobRequirement
{
public override bool IgnoreIfAdmin => true; // WD
/// <summary>
/// What particular role they need the time requirement with.
/// </summary>
[DataField(required: true)]
public ProtoId<PlayTimeTrackerPrototype> Role = default!;
/// <inheritdoc cref="DepartmentTimeRequirement.Time"/>
[DataField(required: true)]
public TimeSpan Time;
public override bool Check(IEntityManager entManager,
IPrototypeManager protoManager,
HumanoidCharacterProfile? profile,
IReadOnlyDictionary<string, TimeSpan> playTimes,
[NotNullWhen(false)] out FormattedMessage? reason)
{
reason = new FormattedMessage();
string proto = Role;
playTimes.TryGetValue(proto, out var roleTime);
var roleDiff = Time.TotalMinutes - roleTime.TotalMinutes;
var departmentColor = Color.Yellow;
if (entManager.EntitySysManager.TryGetEntitySystem(out SharedJobSystem? jobSystem))
{
var jobProto = jobSystem.GetJobPrototype(proto);
if (jobSystem.TryGetDepartment(jobProto, out var departmentProto))
departmentColor = departmentProto.Color;
}
if (!Inverted)
{
if (roleDiff <= 0)
return true;
reason = FormattedMessage.FromMarkupPermissive(Loc.GetString(
"role-timer-role-insufficient",
("time", Math.Ceiling(roleDiff)),
("job", Loc.GetString(proto)),
("departmentColor", departmentColor.ToHex())));
return false;
}
if (roleDiff <= 0)
{
reason = FormattedMessage.FromMarkupPermissive(Loc.GetString(
"role-timer-role-too-high",
("time", -roleDiff),
("job", Loc.GetString(proto)),
("departmentColor", departmentColor.ToHex())));
return false;
}
return true;
}
}

View File

@@ -1,59 +0,0 @@
using System.Diagnostics.CodeAnalysis;
using System.Text;
using Content.Shared.Humanoid.Prototypes;
using Content.Shared.Preferences;
using JetBrains.Annotations;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.Utility;
namespace Content.Shared.Roles;
/// <summary>
/// Requires the character to be or not be on the list of specified species
/// </summary>
[UsedImplicitly]
[Serializable, NetSerializable]
public sealed partial class SpeciesRequirement : JobRequirement
{
[DataField(required: true)]
public HashSet<ProtoId<SpeciesPrototype>> Species = new();
public override bool Check(IEntityManager entManager,
IPrototypeManager protoManager,
HumanoidCharacterProfile? profile,
IReadOnlyDictionary<string, TimeSpan> playTimes,
[NotNullWhen(false)] out FormattedMessage? reason)
{
reason = new FormattedMessage();
if (profile is null) //the profile could be null if the player is a ghost. In this case we don't need to block the role selection for ghostrole
return true;
var sb = new StringBuilder();
sb.Append("[color=yellow]");
foreach (var s in Species)
{
sb.Append(Loc.GetString(protoManager.Index(s).Name) + " ");
}
sb.Append("[/color]");
if (!Inverted)
{
reason = FormattedMessage.FromMarkupPermissive($"{Loc.GetString("role-timer-whitelisted-species")}\n{sb}");
if (!Species.Contains(profile.Species))
return false;
}
else
{
reason = FormattedMessage.FromMarkupPermissive($"{Loc.GetString("role-timer-blacklisted-species")}\n{sb}");
if (Species.Contains(profile.Species))
return false;
}
return true;
}
}

View File

@@ -1,20 +0,0 @@
using Robust.Shared.Prototypes;
namespace Content.Shared.Roles;
/// <summary>
/// Collection of job, antag, and ghost-role job requirements for per-server requirement overrides.
/// </summary>
[Prototype]
public sealed partial class JobRequirementOverridePrototype : IPrototype
{
[ViewVariables]
[IdDataField]
public string ID { get; private set; } = default!;
[DataField]
public Dictionary<ProtoId<JobPrototype>, HashSet<JobRequirement>> Jobs = new ();
[DataField]
public Dictionary<ProtoId<AntagPrototype>, HashSet<JobRequirement>> Antags = new ();
}

View File

@@ -1,57 +1,226 @@
using System.Diagnostics.CodeAnalysis;
using Content.Shared.Preferences;
using Content.Shared.Players.PlayTimeTracking;
using Content.Shared.Roles.Jobs;
using JetBrains.Annotations;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
using Robust.Shared.Utility;
namespace Content.Shared.Roles;
public static class JobRequirements
namespace Content.Shared.Roles
{
public static bool TryRequirementsMet(
JobPrototype job,
IReadOnlyDictionary<string, TimeSpan> playTimes,
[NotNullWhen(false)] out FormattedMessage? reason,
IEntityManager entManager,
IPrototypeManager protoManager,
HumanoidCharacterProfile? profile,
bool isAdmin)
/// <summary>
/// Abstract class for playtime and other requirements for role gates.
/// </summary>
[ImplicitDataDefinitionForInheritors]
[Serializable, NetSerializable]
public abstract partial class JobRequirement{}
[UsedImplicitly]
[Serializable, NetSerializable]
public sealed partial class DepartmentTimeRequirement : JobRequirement
{
var sys = entManager.System<SharedRoleSystem>();
var requirements = sys.GetJobRequirement(job);
reason = null;
if (requirements == null)
return true;
/// <summary>
/// Which department needs the required amount of time.
/// </summary>
[DataField("department", customTypeSerializer: typeof(PrototypeIdSerializer<DepartmentPrototype>))]
public string Department = default!;
foreach (var requirement in requirements)
/// <summary>
/// How long (in seconds) this requirement is.
/// </summary>
[DataField("time")] public TimeSpan Time;
/// <summary>
/// If true, requirement will return false if playtime above the specified time.
/// </summary>
/// <value>
/// <c>False</c> by default.<br />
/// <c>True</c> for invert general requirement
/// </value>
[DataField("inverted")] public bool Inverted;
}
[UsedImplicitly]
[Serializable, NetSerializable]
public sealed partial class RoleTimeRequirement : JobRequirement
{
/// <summary>
/// What particular role they need the time requirement with.
/// </summary>
[DataField("role", customTypeSerializer: typeof(PrototypeIdSerializer<PlayTimeTrackerPrototype>))]
public string Role = default!;
/// <inheritdoc cref="DepartmentTimeRequirement.Time"/>
[DataField("time")] public TimeSpan Time;
/// <inheritdoc cref="DepartmentTimeRequirement.Inverted"/>
[DataField("inverted")] public bool Inverted;
}
[UsedImplicitly]
[Serializable, NetSerializable]
public sealed partial class OverallPlaytimeRequirement : JobRequirement
{
/// <inheritdoc cref="DepartmentTimeRequirement.Time"/>
[DataField("time")] public TimeSpan Time;
/// <inheritdoc cref="DepartmentTimeRequirement.Inverted"/>
[DataField("inverted")] public bool Inverted;
}
public static class JobRequirements
{
public static bool TryRequirementsMet(
JobPrototype job,
Dictionary<string, TimeSpan> playTimes,
[NotNullWhen(false)] out FormattedMessage? reason,
IEntityManager entManager,
IPrototypeManager prototypes)
{
if (isAdmin && requirement.IgnoreIfAdmin)
continue;
reason = null;
if (job.Requirements == null)
return true;
if (!requirement.Check(entManager, protoManager, profile, playTimes, out reason))
return false;
foreach (var requirement in job.Requirements)
{
if (!TryRequirementMet(requirement, playTimes, out reason, entManager, prototypes))
return false;
}
return true;
}
return true;
/// <summary>
/// Returns a string with the reason why a particular requirement may not be met.
/// </summary>
public static bool TryRequirementMet(
JobRequirement requirement,
IReadOnlyDictionary<string, TimeSpan> playTimes,
[NotNullWhen(false)] out FormattedMessage? reason,
IEntityManager entManager,
IPrototypeManager prototypes)
{
reason = null;
switch (requirement)
{
case DepartmentTimeRequirement deptRequirement:
var playtime = TimeSpan.Zero;
// Check all jobs' departments
var department = prototypes.Index<DepartmentPrototype>(deptRequirement.Department);
var jobs = department.Roles;
string proto;
// Check all jobs' playtime
foreach (var other in jobs)
{
// The schema is stored on the Job role but we want to explode if the timer isn't found anyway.
proto = prototypes.Index<JobPrototype>(other).PlayTimeTracker;
playTimes.TryGetValue(proto, out var otherTime);
playtime += otherTime;
}
var deptDiff = deptRequirement.Time.TotalMinutes - playtime.TotalMinutes;
if (!deptRequirement.Inverted)
{
if (deptDiff <= 0)
return true;
reason = FormattedMessage.FromMarkup(Loc.GetString(
"role-timer-department-insufficient",
("time", Math.Ceiling(deptDiff)),
("department", Loc.GetString(deptRequirement.Department)),
("departmentColor", department.Color.ToHex())));
return false;
}
else
{
if (deptDiff <= 0)
{
reason = FormattedMessage.FromMarkup(Loc.GetString(
"role-timer-department-too-high",
("time", -deptDiff),
("department", Loc.GetString(deptRequirement.Department)),
("departmentColor", department.Color.ToHex())));
return false;
}
return true;
}
case OverallPlaytimeRequirement overallRequirement:
var overallTime = playTimes.GetValueOrDefault(PlayTimeTrackingShared.TrackerOverall);
var overallDiff = overallRequirement.Time.TotalMinutes - overallTime.TotalMinutes;
if (!overallRequirement.Inverted)
{
if (overallDiff <= 0 || overallTime >= overallRequirement.Time)
return true;
reason = FormattedMessage.FromMarkup(Loc.GetString(
"role-timer-overall-insufficient",
("time", Math.Ceiling(overallDiff))));
return false;
}
else
{
if (overallDiff <= 0 || overallTime >= overallRequirement.Time)
{
reason = FormattedMessage.FromMarkup(Loc.GetString("role-timer-overall-too-high", ("time", -overallDiff)));
return false;
}
return true;
}
case RoleTimeRequirement roleRequirement:
proto = roleRequirement.Role;
playTimes.TryGetValue(proto, out var roleTime);
var roleDiff = roleRequirement.Time.TotalMinutes - roleTime.TotalMinutes;
var departmentColor = Color.Yellow;
if (entManager.EntitySysManager.TryGetEntitySystem(out SharedJobSystem? jobSystem))
{
var jobProto = jobSystem.GetJobPrototype(proto);
if (jobSystem.TryGetDepartment(jobProto, out var departmentProto))
departmentColor = departmentProto.Color;
}
if (!roleRequirement.Inverted)
{
if (roleDiff <= 0)
return true;
reason = FormattedMessage.FromMarkup(Loc.GetString(
"role-timer-role-insufficient",
("time", Math.Ceiling(roleDiff)),
("job", Loc.GetString(proto)),
("departmentColor", departmentColor.ToHex())));
return false;
}
else
{
if (roleDiff <= 0)
{
reason = FormattedMessage.FromMarkup(Loc.GetString(
"role-timer-role-too-high",
("time", -roleDiff),
("job", Loc.GetString(proto)),
("departmentColor", departmentColor.ToHex())));
return false;
}
return true;
}
default:
throw new NotImplementedException();
}
}
}
}
/// <summary>
/// Abstract class for playtime and other requirements for role gates.
/// </summary>
[ImplicitDataDefinitionForInheritors]
[Serializable, NetSerializable]
public abstract partial class JobRequirement
{
[DataField]
public bool Inverted;
public virtual bool IgnoreIfAdmin => false; // WD
public abstract bool Check(
IEntityManager entManager,
IPrototypeManager protoManager,
HumanoidCharacterProfile? profile,
IReadOnlyDictionary<string, TimeSpan> playTimes,
[NotNullWhen(false)] out FormattedMessage? reason);
}

View File

@@ -1,12 +1,9 @@
using Content.Shared.Administration.Logs;
using Content.Shared.CCVar;
using Content.Shared.Database;
using Content.Shared.Ghost.Roles;
using Content.Shared.Mind;
using Content.Shared.Roles.Jobs;
using Robust.Shared.Audio;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Configuration;
using Robust.Shared.Prototypes;
using Robust.Shared.Utility;
@@ -18,30 +15,14 @@ public abstract class SharedRoleSystem : EntitySystem
[Dependency] private readonly IPrototypeManager _prototypes = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly SharedMindSystem _minds = default!;
[Dependency] private readonly IConfigurationManager _cfg = default!;
// TODO please lord make role entities
private readonly HashSet<Type> _antagTypes = new();
private JobRequirementOverridePrototype? _requirementOverride;
public override void Initialize()
{
// TODO make roles entities
SubscribeLocalEvent<JobComponent, MindGetAllRolesEvent>(OnJobGetAllRoles);
Subs.CVar(_cfg, CCVars.GameRoleTimerOverride, SetRequirementOverride, true);
}
private void SetRequirementOverride(string value)
{
if (string.IsNullOrEmpty(value))
{
_requirementOverride = null;
return;
}
if (!_prototypes.TryIndex(value, out _requirementOverride ))
Log.Error($"Unknown JobRequirementOverridePrototype: {value}");
}
private void OnJobGetAllRoles(EntityUid uid, JobComponent component, ref MindGetAllRolesEvent args)
@@ -205,36 +186,4 @@ public abstract class SharedRoleSystem : EntitySystem
if (Resolve(mindId, ref mind) && mind.Session != null)
_audio.PlayGlobal(sound, mind.Session);
}
public HashSet<JobRequirement>? GetJobRequirement(JobPrototype job)
{
if (_requirementOverride != null && _requirementOverride.Jobs.TryGetValue(job.ID, out var req))
return req;
return job.Requirements;
}
public HashSet<JobRequirement>? GetJobRequirement(ProtoId<JobPrototype> job)
{
if (_requirementOverride != null && _requirementOverride.Jobs.TryGetValue(job, out var req))
return req;
return _prototypes.Index(job).Requirements;
}
public HashSet<JobRequirement>? GetAntagRequirement(ProtoId<AntagPrototype> antag)
{
if (_requirementOverride != null && _requirementOverride.Antags.TryGetValue(antag, out var req))
return req;
return _prototypes.Index(antag).Requirements;
}
public HashSet<JobRequirement>? GetAntagRequirement(AntagPrototype antag)
{
if (_requirementOverride != null && _requirementOverride.Antags.TryGetValue(antag.ID, out var req))
return req;
return antag.Requirements;
}
}

View File

@@ -85,10 +85,8 @@ public abstract partial class SharedToolSystem
if (!InteractionSystem.InRangeUnobstructed(user, coordinates, popup: false))
return false;
var delay = tileDef.IsSubFloor ? TimeSpan.FromSeconds(4) : comp.Delay; // WD
var args = new TileToolDoAfterEvent(GetNetCoordinates(coordinates));
UseTool(ent, user, ent, delay, tool.Qualities, args, out _, toolComponent: tool); // WD EDIT
UseTool(ent, user, ent, comp.Delay, tool.Qualities, args, out _, toolComponent: tool);
return true;
}

View File

@@ -29,7 +29,7 @@ public abstract partial class SharedVendingMachineSystem : EntitySystem
RestockInventoryFromPrototype(uid, component);
}
public void RestockInventoryFromPrototype(EntityUid uid, VendingMachineComponent? component = null, bool restockEverything = true) // WD EDIT
public void RestockInventoryFromPrototype(EntityUid uid, VendingMachineComponent? component = null)
{
if (!Resolve(uid, ref component))
{
@@ -40,8 +40,6 @@ public abstract partial class SharedVendingMachineSystem : EntitySystem
return;
AddInventoryFromPrototype(uid, packPrototype.StartingInventory, InventoryType.Regular, component);
if (!restockEverything) // WD
return;
AddInventoryFromPrototype(uid, packPrototype.EmaggedInventory, InventoryType.Emagged, component);
AddInventoryFromPrototype(uid, packPrototype.ContrabandInventory, InventoryType.Contraband, component);
}

View File

@@ -1,35 +0,0 @@
using Robust.Shared.Serialization;
namespace Content.Shared._White.CartridgeLoader.Cartridges;
///<summary>
/// Data of a single message in the system, containing the ids of the sender and recipient, the text content and the time it was sent.
///</summary>
[Serializable, NetSerializable]
public struct MessagesMessageData
{
public int SenderId;
public int ReceiverId;
public string Content;
public TimeSpan Time;
}
[Serializable, NetSerializable]
public sealed class MessagesUserData
{
public string Name = Loc.GetString("messages-pda-unknown-name");
public string Job = Loc.GetString("messages-pda-unknown-job");
public string Department = "Specific";
public List<MessagesMessageData> Messages = [];
public void SetMessagesUser(string? name, string? job, string? department)
{
Name = name ?? Loc.GetString("messages-pda-unknown-name");
Job = job ?? Loc.GetString("messages-pda-unknown-job");
Department = department ?? "Specific";
}
}

View File

@@ -1,21 +0,0 @@
using Content.Shared.CartridgeLoader;
using Robust.Shared.Serialization;
namespace Content.Shared._White.CartridgeLoader.Cartridges;
[Serializable, NetSerializable]
public sealed class MessagesUiMessageEvent(MessagesUiAction action, string? stringInput, int? targetChatUid) : CartridgeMessageEvent
{
public readonly MessagesUiAction Action = action;
public readonly int? TargetChatUid = targetChatUid;
public readonly string? StringInput = stringInput;
}
[Serializable, NetSerializable]
public enum MessagesUiAction : byte
{
Send,
ChangeChat
}

View File

@@ -1,28 +0,0 @@
using Robust.Shared.Serialization;
namespace Content.Shared._White.CartridgeLoader.Cartridges;
///<summary>
/// The state of the messages app interface.
/// Mode switches whether the UI should display a list of other users or a particular chat.
/// Contents contains either the names of users and their ids in the messages system or simply a list of message strings.
///</summary>
[Serializable, NetSerializable]
public sealed class MessagesUiState(MessagesUiStateMode mode, List<(MessagesUserData, int?)>? users = null, List<(string, int?)>? messages = null, string? name = null) : BoundUserInterfaceState
{
public List<(MessagesUserData, int?)>? Users = users;
public List<(string, int?)>? Messages = messages;
public MessagesUiStateMode Mode = mode;
public string? Name = name;
}
///<summary>
/// Enum representing the modes the program's UI can be in
///</summary>
[Serializable, NetSerializable]
public enum MessagesUiStateMode : byte
{
UserList,
Chat,
Error
}

View File

@@ -47,6 +47,7 @@ public sealed class NarcoticEffect : EntitySystem
TryComp<StatusEffectsComponent>(uid, out var statusEffectsComp);
RaiseLocalEvent(uid, new MoodEffectEvent("Stimulator"));
CancellationToken token = movespeedModifierComponent.CancelTokenSource.Token;
int timer = component.TimerInterval[_robustRandom.Next(0, component.TimerInterval.Count)];

View File

@@ -1,20 +0,0 @@
using Content.Shared._White.Mood;
using Content.Shared.Chemistry.Reagent;
using JetBrains.Annotations;
using Robust.Shared.Prototypes;
namespace Content.Shared._White.Chemistry;
[UsedImplicitly]
public sealed partial class NarcoticMoodEffect : ReagentEffect
{
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
{
return null;
}
public override void Effect(ReagentEffectArgs args)
{
args.EntityManager.EventBus.RaiseLocalEvent(args.SolutionEntity, new MoodEffectEvent("Stimulator"));
}
}

View File

@@ -1,19 +1,17 @@
using Robust.Shared.GameStates;
namespace Content.Shared._White.Item.DelayedKnockdown;
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
[RegisterComponent]
public sealed partial class DelayedKnockdownOnHitComponent : Component
{
[DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField]
[DataField, ViewVariables(VVAccess.ReadWrite)]
public TimeSpan Delay = TimeSpan.FromSeconds(2);
[DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField]
[DataField, ViewVariables(VVAccess.ReadWrite)]
public TimeSpan KnockdownTime = TimeSpan.FromSeconds(5);
[DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField]
[DataField, ViewVariables(VVAccess.ReadWrite)]
public TimeSpan StutterTime = TimeSpan.FromSeconds(16);
[DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField]
[DataField, ViewVariables(VVAccess.ReadWrite)]
public TimeSpan JitterTime = TimeSpan.FromSeconds(40);
}

View File

@@ -1,68 +0,0 @@
using System.Diagnostics.CodeAnalysis;
using System.Text;
using Content.Shared.Preferences;
using Content.Shared.Roles;
using JetBrains.Annotations;
using Robust.Shared.Enums;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.Utility;
namespace Content.Shared._White.JobRequirements;
[UsedImplicitly]
[Serializable, NetSerializable]
public sealed partial class GenderRequirement : JobRequirement
{
[DataField(required: true)]
public HashSet<Gender> RequiredGenders;
public override bool Check(IEntityManager entManager,
IPrototypeManager protoManager,
HumanoidCharacterProfile? profile,
IReadOnlyDictionary<string, TimeSpan> playTimes,
[NotNullWhen(false)] out FormattedMessage? reason)
{
reason = new FormattedMessage();
if (profile is null)
return true;
var sb = new StringBuilder();
sb.Append("[color=yellow]");
foreach (var g in RequiredGenders)
{
sb.Append(GenderToString(g) + " ");
}
sb.Append("[/color]");
if (!Inverted)
{
reason = FormattedMessage.FromMarkupPermissive($"{Loc.GetString("role-timer-gender-whitelisted")}\n{sb}");
if (!RequiredGenders.Contains(profile.Gender))
return false;
}
else
{
reason = FormattedMessage.FromMarkupPermissive($"{Loc.GetString("role-timer-gender-blacklisted")}\n{sb}");
if (RequiredGenders.Contains(profile.Gender))
return false;
}
return true;
}
private string GenderToString(Gender gender)
{
return gender switch
{
Gender.Male => Loc.GetString("humanoid-profile-editor-pronouns-male-text"),
Gender.Female => Loc.GetString("humanoid-profile-editor-pronouns-female-text"),
Gender.Epicene => Loc.GetString("humanoid-profile-editor-pronouns-epicene-text"),
_ => Loc.GetString("humanoid-profile-editor-pronouns-neuter-text")
};
}
}

View File

@@ -1,59 +0,0 @@
using System.Diagnostics.CodeAnalysis;
using Content.Shared.Humanoid;
using Content.Shared.Preferences;
using Content.Shared.Roles;
using JetBrains.Annotations;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.Utility;
namespace Content.Shared._White.JobRequirements;
[UsedImplicitly]
[Serializable, NetSerializable]
public sealed partial class SexRequirement : JobRequirement
{
[DataField(required: true)]
public Sex RequiredSex;
public override bool Check(IEntityManager entManager,
IPrototypeManager protoManager,
HumanoidCharacterProfile? profile,
IReadOnlyDictionary<string, TimeSpan> playTimes,
[NotNullWhen(false)] out FormattedMessage? reason)
{
reason = new FormattedMessage();
if (profile is null)
return true;
if (!Inverted)
{
reason = FormattedMessage.FromMarkupPermissive(Loc.GetString("role-timer-sex-whitelisted",
("sex", SexToString())));
if (profile.Sex != RequiredSex)
return false;
}
else
{
reason = FormattedMessage.FromMarkupPermissive(Loc.GetString("role-timer-sex-blacklisted",
("sex", SexToString())));
if (profile.Sex == RequiredSex)
return false;
}
return true;
}
private string SexToString()
{
return RequiredSex switch
{
Sex.Male => Loc.GetString("role-timer-sex-male"),
Sex.Female => Loc.GetString("role-timer-sex-female"),
_ => Loc.GetString("role-timer-sex-unsexed")
};
}
}

View File

@@ -1,7 +0,0 @@
namespace Content.Shared._White.Radio;
[RegisterComponent]
public sealed partial class NetworkChatComponent : Component
{
}

View File

@@ -2,7 +2,6 @@ using System.Numerics;
using Content.Shared.Camera;
using Content.Shared.Hands;
using Content.Shared.Hands.Components;
using Content.Shared.Item;
using Robust.Shared.Serialization;
namespace Content.Shared._White.Telescope;
@@ -42,45 +41,19 @@ public abstract class SharedTelescopeSystem : EntitySystem
if (!TryComp(args.User, out EyeComponent? eye))
return;
if (!HasComp<ItemComponent>(ent.Owner))
return;
SetOffset((args.User, eye), Vector2.Zero, ent);
}
public EntityUid GetRightEntity(EntityUid? ent)
{
var entity = EntityUid.Invalid;
if (TryComp<HandsComponent>(ent, out var hands) &&
HasComp<TelescopeComponent>(hands.ActiveHandEntity) &&
hands.ActiveHandEntity.HasValue)
{
entity = hands.ActiveHandEntity.Value;
}
else if (HasComp<TelescopeComponent>(ent))
{
entity = ent.Value;
}
return entity;
}
private void OnEyeOffsetChanged(EyeOffsetChangedEvent msg, EntitySessionEventArgs args)
{
if (args.SenderSession.AttachedEntity is not { } ent)
return;
if (!TryComp(ent, out EyeComponent? eye))
if (!TryComp<HandsComponent>(ent, out var hands) ||
!TryComp<TelescopeComponent>(hands.ActiveHandEntity, out var telescope) ||
!TryComp(ent, out EyeComponent? eye))
return;
var entity = GetRightEntity(ent);
if (entity == EntityUid.Invalid)
return;
var telescope = Comp<TelescopeComponent>(entity);
var offset = Vector2.Lerp(eye.Offset, msg.Offset, telescope.LerpAmount);
SetOffset((ent, eye), offset, telescope);
@@ -98,19 +71,6 @@ public abstract class SharedTelescopeSystem : EntitySystem
else
_eye.SetOffset(ent, offset, ent);
}
public void SetParameters(Entity<TelescopeComponent> ent, float? divisor = null, float? lerpAmount = null)
{
var telescope = ent.Comp;
divisor ??= telescope.Divisor;
lerpAmount ??= telescope.LerpAmount;
telescope.Divisor = divisor.Value;
telescope.LerpAmount = lerpAmount.Value;
Dirty(ent.Owner, telescope);
}
}
[Serializable, NetSerializable]

View File

@@ -164,7 +164,7 @@ public sealed class WhiteCVars
*/
public static readonly CVarDef<bool> FanaticXenophobiaEnabled =
CVarDef.Create("white.fanatic_xenophobia", false, CVar.SERVERONLY | CVar.ARCHIVE);
CVarDef.Create("white.fanatic_xenophobia", true, CVar.SERVERONLY | CVar.ARCHIVE);
/*
* MeatyOre

View File

@@ -7,7 +7,7 @@
license: "CC-BY-3.0"
copyright: "Modified from 'Meow 4.wav' by freesound user 'TRNGLE. The original audio was trimmed, split to mono, and converted from WAV to OGG format"
source: "https://freesound.org/people/TRNGLE/sounds/368006/"
- files: ["cat_meow2.ogg"]
license: "CC-BY-3.0"
copyright: "Created by freesound user 'TRNGLE. The original audio split to mono, and converted from WAV to OGG format"
@@ -117,42 +117,24 @@
license: "CC-BY-4.0"
copyright: "Audio is recorded/created by Pfranzen 'FreeSound.org'. The original audio was trimmed and renamed"
source: "https://freesound.org/people/pfranzen/sounds/322744/"
- files: ["dog_bark1.ogg"]
license: "CC0-1.0"
copyright: "Audio is recorded/created by KFerentchak 'FreeSound.org'. The original audio was trimmed and renamed"
source: "https://freesound.org/people/KFerentchak/sounds/235912/"
source: "https://freesound.org/people/KFerentchak/sounds/235912/"
- files: ["dog_bark2.ogg"]
license: "CC0-1.0"
copyright: "Audio is recorded/created by KFerentchak 'FreeSound.org'. The original audio was trimmed and renamed"
source: "https://freesound.org/people/KFerentchak/sounds/235912/"
source: "https://freesound.org/people/KFerentchak/sounds/235912/"
- files: ["dog_bark3.ogg"]
license: "CC0-1.0"
copyright: "Audio is recorded/created by KFerentchak 'FreeSound.org'. The original audio was trimmed and renamed"
source: "https://freesound.org/people/KFerentchak/sounds/235912/"
- files: ["nymph_chirp.ogg"]
license: "CC-BY-SA-3.0"
copyright: "Taken from ParadiseSS13"
source: "https://github.com/ParadiseSS13/Paradise/commit/a34f1054cef5a44a67fdac3b67b811137c6071dd"
- files:
- fox1.ogg
- fox2.ogg
- fox3.ogg
- fox4.ogg
- fox5.ogg
- fox6.ogg
- fox7.ogg
- fox8.ogg
- fox9.ogg
- fox10.ogg
- fox11.ogg
- fox12.ogg
- fox13.ogg
- fox14.ogg
copyright: "Created by fujiwaranao"
license: "CC-BY-NC-SA-4.0"
source: "https://github.com/space-wizards/space-station-14/pull/27578"

Binary file not shown.

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