Merge pull request #1494 from DeltaV-Station/guidebook-rules

Delta-V Guidebook Rules
This commit is contained in:
Null 2024-07-25 01:19:26 +02:00 committed by GitHub
commit 3d5955f265
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
83 changed files with 8504 additions and 640 deletions

View File

@ -2,11 +2,9 @@ using Content.Client.Administration.Managers;
using Content.Client.Changelog;
using Content.Client.Chat.Managers;
using Content.Client.Eui;
using Content.Client.Flash;
using Content.Client.Fullscreen;
using Content.Client.GhostKick;
using Content.Client.Guidebook;
using Content.Client.Info;
using Content.Client.Input;
using Content.Client.IoC;
using Content.Client.Launcher;
@ -52,7 +50,6 @@ namespace Content.Client.Entry
[Dependency] private readonly IScreenshotHook _screenshotHook = default!;
[Dependency] private readonly FullscreenHook _fullscreenHook = default!;
[Dependency] private readonly ChangelogManager _changelogManager = default!;
[Dependency] private readonly RulesManager _rulesManager = default!;
[Dependency] private readonly ViewportManager _viewportManager = default!;
[Dependency] private readonly IUserInterfaceManager _userInterfaceManager = default!;
[Dependency] private readonly IInputManager _inputManager = default!;
@ -126,7 +123,6 @@ namespace Content.Client.Entry
_screenshotHook.Initialize();
_fullscreenHook.Initialize();
_changelogManager.Initialize();
_rulesManager.Initialize();
_viewportManager.Initialize();
_ghostKick.Initialize();
_extendedDisconnectInformation.Initialize();

View File

@ -1,4 +1,5 @@
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
using Content.Shared.Guidebook;
using Robust.Shared.Prototypes;
namespace Content.Client.Guidebook.Components;
@ -13,9 +14,8 @@ public sealed partial class GuideHelpComponent : Component
/// What guides to include show when opening the guidebook. The first entry will be used to select the currently
/// selected guidebook.
/// </summary>
[DataField("guides", customTypeSerializer: typeof(PrototypeIdListSerializer<GuideEntryPrototype>), required: true)]
[ViewVariables]
public List<string> Guides = new();
[DataField(required: true)]
public List<ProtoId<GuideEntryPrototype>> Guides = new();
/// <summary>
/// Whether or not to automatically include the children of the given guides.

View File

@ -2,7 +2,7 @@
xmlns:cc="clr-namespace:Content.Client.Administration.UI.CustomControls"
xmlns:fancyTree="clr-namespace:Content.Client.UserInterface.Controls.FancyTree"
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
SetSize="750 700"
SetSize="850 700"
MinSize="100 200"
Resizable="True"
Title="{Loc 'guidebook-window-title'}">
@ -18,12 +18,16 @@
Name="SearchBar"
PlaceHolder="{Loc 'guidebook-filter-placeholder-text'}"
HorizontalExpand="True"
Margin="0 5 10 5">
Margin="0 5 10 5">
</LineEdit>
</BoxContainer>
<BoxContainer Access="Internal" Name="ReturnContainer" Orientation="Horizontal" HorizontalAlignment="Right" Visible="False">
<Button Name="HomeButton" Text="{Loc 'ui-rules-button-home'}" Margin="0 0 10 0"/>
</BoxContainer>
<ScrollContainer Name="Scroll" HScrollEnabled="False" HorizontalExpand="True" VerticalExpand="True">
<Control>
<BoxContainer Orientation="Vertical" Name="EntryContainer" Margin="5 5 5 5" Visible="False"/>
<BoxContainer Orientation="Vertical" Name="EntryContainer" Margin="5 5 5 5" Visible="False">
</BoxContainer>
<BoxContainer Orientation="Vertical" Name="Placeholder" Margin="5 5 5 5">
<Label HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Loc 'guidebook-placeholder-text'}"/>
<Label HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Loc 'guidebook-placeholder-text-2'}"/>

View File

@ -1,15 +1,15 @@
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Content.Client.Guidebook.RichText;
using Content.Client.UserInterface.ControlExtensions;
using Content.Client.UserInterface.Controls;
using Content.Client.UserInterface.Controls.FancyTree;
using JetBrains.Annotations;
using Content.Client.UserInterface.Systems.Info;
using Content.Shared.Guidebook;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.ContentPack;
using Robust.Shared.Prototypes;
namespace Content.Client.Guidebook.Controls;
@ -19,7 +19,7 @@ public sealed partial class GuidebookWindow : FancyWindow, ILinkClickHandler
[Dependency] private readonly IResourceManager _resourceManager = default!;
[Dependency] private readonly DocumentParsingManager _parsingMan = default!;
private Dictionary<string, GuideEntry> _entries = new();
private Dictionary<ProtoId<GuideEntryPrototype>, GuideEntry> _entries = new();
public GuidebookWindow()
{
@ -37,7 +37,13 @@ public sealed partial class GuidebookWindow : FancyWindow, ILinkClickHandler
private void OnSelectionChanged(TreeItem? item)
{
if (item != null && item.Metadata is GuideEntry entry)
{
ShowGuide(entry);
var isRulesEntry = entry.RuleEntry;
ReturnContainer.Visible = isRulesEntry;
HomeButton.OnPressed += _ => ShowGuide(entry);
}
else
ClearSelectedGuide();
}
@ -69,10 +75,10 @@ public sealed partial class GuidebookWindow : FancyWindow, ILinkClickHandler
}
public void UpdateGuides(
Dictionary<string, GuideEntry> entries,
List<string>? rootEntries = null,
string? forceRoot = null,
string? selected = null)
Dictionary<ProtoId<GuideEntryPrototype>, GuideEntry> entries,
List<ProtoId<GuideEntryPrototype>>? rootEntries = null,
ProtoId<GuideEntryPrototype>? forceRoot = null,
ProtoId<GuideEntryPrototype>? selected = null)
{
_entries = entries;
RepopulateTree(rootEntries, forceRoot);
@ -98,11 +104,11 @@ public sealed partial class GuidebookWindow : FancyWindow, ILinkClickHandler
}
}
private IEnumerable<GuideEntry> GetSortedEntries(List<string>? rootEntries)
private IEnumerable<GuideEntry> GetSortedEntries(List<ProtoId<GuideEntryPrototype>>? rootEntries)
{
if (rootEntries == null)
{
HashSet<string> entries = new(_entries.Keys);
HashSet<ProtoId<GuideEntryPrototype>> entries = new(_entries.Keys);
foreach (var entry in _entries.Values)
{
if (entry.Children.Count > 0)
@ -111,7 +117,7 @@ public sealed partial class GuidebookWindow : FancyWindow, ILinkClickHandler
.Select(childId => _entries[childId])
.OrderBy(childEntry => childEntry.Priority)
.ThenBy(childEntry => Loc.GetString(childEntry.Name))
.Select(childEntry => childEntry.Id)
.Select(childEntry => new ProtoId<GuideEntryPrototype>(childEntry.Id))
.ToList();
entry.Children = sortedChildren;
@ -127,13 +133,13 @@ public sealed partial class GuidebookWindow : FancyWindow, ILinkClickHandler
.ThenBy(rootEntry => Loc.GetString(rootEntry.Name));
}
private void RepopulateTree(List<string>? roots = null, string? forcedRoot = null)
private void RepopulateTree(List<ProtoId<GuideEntryPrototype>>? roots = null, ProtoId<GuideEntryPrototype>? forcedRoot = null)
{
Tree.Clear();
HashSet<string> addedEntries = new();
HashSet<ProtoId<GuideEntryPrototype>> addedEntries = new();
TreeItem? parent = forcedRoot == null ? null : AddEntry(forcedRoot, null, addedEntries);
TreeItem? parent = forcedRoot == null ? null : AddEntry(forcedRoot.Value, null, addedEntries);
foreach (var entry in GetSortedEntries(roots))
{
AddEntry(entry.Id, parent, addedEntries);
@ -141,17 +147,23 @@ public sealed partial class GuidebookWindow : FancyWindow, ILinkClickHandler
Tree.SetAllExpanded(true);
}
private TreeItem? AddEntry(string id, TreeItem? parent, HashSet<string> addedEntries)
private TreeItem? AddEntry(ProtoId<GuideEntryPrototype> id, TreeItem? parent, HashSet<ProtoId<GuideEntryPrototype>> addedEntries)
{
if (!_entries.TryGetValue(id, out var entry))
return null;
if (!addedEntries.Add(id))
{
// TODO GUIDEBOOK Maybe allow duplicate entries?
// E.g., for adding medicine under both chemicals & the chemist job
Logger.Error($"Adding duplicate guide entry: {id}");
return null;
}
var rulesProto = UserInterfaceManager.GetUIController<InfoUIController>().GetCoreRuleEntry();
if (entry.RuleEntry && entry.Id != rulesProto.Id)
return null;
var item = Tree.AddItem(parent);
item.Metadata = entry;
var name = Loc.GetString(entry.Name);

View File

@ -1,7 +1,10 @@
using System.Linq;
using Content.Client.Guidebook.Richtext;
using Content.Shared.Guidebook;
using Pidgin;
using Robust.Client.UserInterface;
using Robust.Shared.ContentPack;
using Robust.Shared.Prototypes;
using Robust.Shared.Reflection;
using Robust.Shared.Sandboxing;
using static Pidgin.Parser;
@ -13,7 +16,9 @@ namespace Content.Client.Guidebook;
/// </summary>
public sealed partial class DocumentParsingManager
{
[Dependency] private readonly IPrototypeManager _prototype = default!;
[Dependency] private readonly IReflectionManager _reflectionManager = default!;
[Dependency] private readonly IResourceManager _resourceManager = default!;
[Dependency] private readonly ISandboxHelper _sandboxHelper = default!;
private readonly Dictionary<string, Parser<char, Control>> _tagControlParsers = new();
@ -37,6 +42,21 @@ public sealed partial class DocumentParsingManager
ControlParser = SkipWhitespaces.Then(_controlParser.Many());
}
public bool TryAddMarkup(Control control, ProtoId<GuideEntryPrototype> entryId, bool log = true)
{
if (!_prototype.TryIndex(entryId, out var entry))
return false;
using var file = _resourceManager.ContentFileReadText(entry.Text);
return TryAddMarkup(control, file.ReadToEnd(), log);
}
public bool TryAddMarkup(Control control, GuideEntry entry, bool log = true)
{
using var file = _resourceManager.ContentFileReadText(entry.Text);
return TryAddMarkup(control, file.ReadToEnd(), log);
}
public bool TryAddMarkup(Control control, string text, bool log = true)
{
try

View File

@ -2,6 +2,7 @@ using System.Linq;
using Content.Client.Guidebook.Components;
using Content.Client.Light;
using Content.Client.Verbs;
using Content.Shared.Guidebook;
using Content.Shared.Interaction;
using Content.Shared.Light.Components;
using Content.Shared.Speech;
@ -13,6 +14,7 @@ using Robust.Shared.Audio;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Map;
using Robust.Shared.Player;
using Robust.Shared.Prototypes;
using Robust.Shared.Timing;
using Robust.Shared.Utility;
@ -31,7 +33,12 @@ public sealed class GuidebookSystem : EntitySystem
[Dependency] private readonly SharedPointLightSystem _pointLightSystem = default!;
[Dependency] private readonly TagSystem _tags = default!;
public event Action<List<string>, List<string>?, string?, bool, string?>? OnGuidebookOpen;
public event Action<List<ProtoId<GuideEntryPrototype>>,
List<ProtoId<GuideEntryPrototype>>?,
ProtoId<GuideEntryPrototype>?,
bool,
ProtoId<GuideEntryPrototype>?>? OnGuidebookOpen;
public const string GuideEmbedTag = "GuideEmbeded";
private EntityUid _defaultUser;
@ -80,7 +87,7 @@ public sealed class GuidebookSystem : EntitySystem
});
}
public void OpenHelp(List<string> guides)
public void OpenHelp(List<ProtoId<GuideEntryPrototype>> guides)
{
OnGuidebookOpen?.Invoke(guides, null, null, true, guides[0]);
}

View File

@ -1,25 +0,0 @@
using Content.Shared.Info;
using Robust.Shared.Log;
namespace Content.Client.Info;
public sealed class InfoSystem : EntitySystem
{
public RulesMessage Rules = new RulesMessage("Server Rules", "The server did not send any rules.");
[Dependency] private readonly RulesManager _rules = default!;
public override void Initialize()
{
base.Initialize();
SubscribeNetworkEvent<RulesMessage>(OnRulesReceived);
Log.Debug("Requested server info.");
RaiseNetworkEvent(new RequestRulesMessage());
}
private void OnRulesReceived(RulesMessage message, EntitySessionEventArgs eventArgs)
{
Log.Debug("Received server rules.");
Rules = message;
_rules.UpdateRules();
}
}

View File

@ -1,10 +1,8 @@
using System.Numerics;
using Content.Client.UserInterface.Systems.EscapeMenu;
using Robust.Client.ResourceManagement;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
using Robust.Shared.Configuration;
using Robust.Shared.ContentPack;
namespace Content.Client.Info
@ -12,7 +10,6 @@ namespace Content.Client.Info
public sealed class RulesAndInfoWindow : DefaultWindow
{
[Dependency] private readonly IResourceManager _resourceManager = default!;
[Dependency] private readonly RulesManager _rules = default!;
public RulesAndInfoWindow()
{
@ -22,8 +19,14 @@ namespace Content.Client.Info
var rootContainer = new TabContainer();
var rulesList = new Info();
var tutorialList = new Info();
var rulesList = new RulesControl
{
Margin = new Thickness(10)
};
var tutorialList = new Info
{
Margin = new Thickness(10)
};
rootContainer.AddChild(rulesList);
rootContainer.AddChild(tutorialList);
@ -31,7 +34,6 @@ namespace Content.Client.Info
TabContainer.SetTabTitle(rulesList, Loc.GetString("ui-info-tab-rules"));
TabContainer.SetTabTitle(tutorialList, Loc.GetString("ui-info-tab-tutorial"));
AddSection(rulesList, _rules.RulesSection());
PopulateTutorial(tutorialList);
Contents.AddChild(rootContainer);

View File

@ -1,6 +1,18 @@
<BoxContainer xmlns="https://spacestation14.io"
Name="InfoContainer"
Orientation="Vertical"
Margin="2 2 0 0"
SeparationOverride="10"
Access="Public"/>
<BoxContainer xmlns="https://spacestation14.io" Orientation="Vertical" HorizontalExpand="True" VerticalExpand="True">
<Control HorizontalExpand="True" VerticalExpand="True" HorizontalAlignment="Stretch">
<ScrollContainer Name="Scroll" HScrollEnabled="False" HorizontalExpand="True" VerticalExpand="True">
<BoxContainer Name="RulesContainer" VerticalExpand="True" Margin="0 0 5 0"/>
</ScrollContainer>
<BoxContainer Margin="0 0 15 0" HorizontalExpand="True" HorizontalAlignment="Right">
<Button Name="BackButton"
Text="{Loc 'ui-rules-button-back'}"
HorizontalAlignment="Right"
VerticalAlignment="Top"/>
<Control MinWidth="5"/>
<Button Name="HomeButton"
Text="{Loc 'ui-rules-button-home'}"
HorizontalAlignment="Right"
VerticalAlignment="Top"/>
</BoxContainer>
</Control>
</BoxContainer>

View File

@ -1,22 +1,54 @@
using System.IO;
using Content.Shared.CCVar;
using Content.Client.Guidebook;
using Content.Client.Guidebook.RichText;
using Content.Client.UserInterface.Systems.Info;
using Content.Shared.Guidebook;
using Robust.Client.AutoGenerated;
using Robust.Client.ResourceManagement;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Configuration;
using Robust.Shared.Prototypes;
namespace Content.Client.Info;
[GenerateTypedNameReferences]
public sealed partial class RulesControl : BoxContainer
public sealed partial class RulesControl : BoxContainer, ILinkClickHandler
{
[Dependency] private readonly RulesManager _rules = default!;
[Dependency] private readonly DocumentParsingManager _parsingMan = default!;
private string? _currentEntry;
private readonly Stack<string> _priorEntries = new();
public RulesControl()
{
RobustXamlLoader.Load(this);
IoCManager.InjectDependencies(this);
AddChild(_rules.RulesSection());
SetGuide();
HomeButton.OnPressed += _ => SetGuide();
BackButton.OnPressed += _ => SetGuide(_priorEntries.Pop(), false);
}
public void HandleClick(string link)
{
SetGuide(link);
}
private void SetGuide(ProtoId<GuideEntryPrototype>? entry = null, bool addToPrior = true)
{
var coreEntry = UserInterfaceManager.GetUIController<InfoUIController>().GetCoreRuleEntry();
entry ??= coreEntry;
Scroll.SetScrollValue(default);
RulesContainer.Children.Clear();
if (!_parsingMan.TryAddMarkup(RulesContainer, entry.Value))
return;
if (addToPrior && _currentEntry != null)
_priorEntries.Push(_currentEntry);
_currentEntry = entry.Value;
HomeButton.Visible = entry.Value != coreEntry.Id;
BackButton.Visible = _priorEntries.Count != 0 && _priorEntries.Peek() != entry.Value;
}
}

View File

@ -1,105 +0,0 @@
using Content.Client.Lobby;
using Content.Client.Gameplay;
using Content.Shared.CCVar;
using Content.Shared.Info;
using Robust.Client.Console;
using Robust.Client.State;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Shared.Configuration;
using Robust.Shared.Network;
namespace Content.Client.Info;
public sealed class RulesManager : SharedRulesManager
{
[Dependency] private readonly IConfigurationManager _configManager = default!;
[Dependency] private readonly IUserInterfaceManager _userInterfaceManager = default!;
[Dependency] private readonly IStateManager _stateManager = default!;
[Dependency] private readonly IClientConsoleHost _consoleHost = default!;
[Dependency] private readonly INetManager _netManager = default!;
[Dependency] private readonly IEntitySystemManager _sysMan = default!;
private InfoSection rulesSection = new InfoSection("", "", false);
private bool _shouldShowRules = false;
private RulesPopup? _activePopup;
public void Initialize()
{
_netManager.RegisterNetMessage<ShouldShowRulesPopupMessage>(OnShouldShowRules);
_netManager.RegisterNetMessage<ShowRulesPopupMessage>(OnShowRulesPopupMessage);
_netManager.RegisterNetMessage<RulesAcceptedMessage>();
_stateManager.OnStateChanged += OnStateChanged;
_consoleHost.RegisterCommand("fuckrules", "", "", (_, _, _) =>
{
OnAcceptPressed();
});
}
private void OnShouldShowRules(ShouldShowRulesPopupMessage message)
{
_shouldShowRules = true;
}
private void OnShowRulesPopupMessage(ShowRulesPopupMessage message)
{
ShowRules(message.PopupTime);
}
private void OnStateChanged(StateChangedEventArgs args)
{
if (args.NewState is not (GameplayState or LobbyState))
return;
if (!_shouldShowRules)
return;
_shouldShowRules = false;
ShowRules(_configManager.GetCVar(CCVars.RulesWaitTime));
}
private void ShowRules(float time)
{
if (_activePopup != null)
return;
_activePopup = new RulesPopup
{
Timer = time
};
_activePopup.OnQuitPressed += OnQuitPressed;
_activePopup.OnAcceptPressed += OnAcceptPressed;
_userInterfaceManager.WindowRoot.AddChild(_activePopup);
LayoutContainer.SetAnchorPreset(_activePopup, LayoutContainer.LayoutPreset.Wide);
}
private void OnQuitPressed()
{
_consoleHost.ExecuteCommand("quit");
}
private void OnAcceptPressed()
{
_netManager.ClientSendMessage(new RulesAcceptedMessage());
_activePopup?.Orphan();
_activePopup = null;
}
public void UpdateRules()
{
var rules = _sysMan.GetEntitySystem<InfoSystem>().Rules;
rulesSection.SetText(rules.Title, rules.Text, true);
}
public Control RulesSection()
{
rulesSection = new InfoSection("", "", false);
UpdateRules();
return rulesSection;
}
}

View File

@ -5,20 +5,20 @@
MouseFilter="Stop">
<parallax:ParallaxControl />
<Control VerticalExpand="True"
MaxWidth="650">
MaxWidth="800"
MaxHeight="900">
<PanelContainer StyleClasses="windowPanel" />
<ScrollContainer HScrollEnabled="False">
<BoxContainer Orientation="Vertical" SeparationOverride="10">
<info:RulesControl />
<BoxContainer Orientation="Vertical" SeparationOverride="10" Margin="10 10 5 10">
<info:RulesControl/>
<Label Name="WaitLabel" />
<BoxContainer Orientation="Horizontal">
<Button Name="AcceptButton"
Text="{Loc 'ui-rules-accept'}"
Disabled="True" />
<Button Name="QuitButton"
StyleClasses="Caution"
Text="{Loc 'ui-escape-quit'}" />
</BoxContainer>
</BoxContainer>
</ScrollContainer>
</Control>
</Control>

View File

@ -1,9 +1,7 @@
using System;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Localization;
using Robust.Shared.Timing;
namespace Content.Client.Info;

View File

@ -4,7 +4,6 @@ using Content.Client.Chat.Managers;
using Content.Client.Clickable;
using Content.Client.Eui;
using Content.Client.GhostKick;
using Content.Client.Info;
using Content.Client.Launcher;
using Content.Client.Parallax.Managers;
using Content.Client.Players.PlayTimeTracking;
@ -41,7 +40,6 @@ namespace Content.Client.IoC
collection.Register<EuiManager, EuiManager>();
collection.Register<IVoteManager, VoteManager>();
collection.Register<ChangelogManager, ChangelogManager>();
collection.Register<RulesManager, RulesManager>();
collection.Register<ViewportManager, ViewportManager>();
collection.Register<ISharedAdminLogManager, SharedAdminLogManager>();
collection.Register<GhostKickManager>();

View File

@ -1,4 +1,5 @@
using System.Linq;
using Content.Client.Guidebook;
using Content.Client.Humanoid;
using Content.Client.Inventory;
using Content.Client.Lobby.UI;
@ -41,6 +42,7 @@ public sealed class LobbyUIController : UIController, IOnStateEntered<LobbyState
[UISystemDependency] private readonly HumanoidAppearanceSystem _humanoid = default!;
[UISystemDependency] private readonly ClientInventorySystem _inventory = default!;
[UISystemDependency] private readonly StationSpawningSystem _spawn = default!;
[UISystemDependency] private readonly GuidebookSystem _guide = default!;
private CharacterSetupGui? _characterSetup;
private HumanoidProfileEditor? _profileEditor;
@ -232,6 +234,8 @@ public sealed class LobbyUIController : UIController, IOnStateEntered<LobbyState
_requirements,
_markings);
_profileEditor.OnOpenGuidebook += _guide.OpenHelp;
_characterSetup = new CharacterSetupGui(EntityManager, _prototypeManager, _resourceCache, _preferencesManager, _profileEditor);
_characterSetup.CloseButton.OnPressed += _ =>

View File

@ -1,7 +1,6 @@
using System.IO;
using System.Linq;
using System.Numerics;
using Content.Client.Guidebook;
using Content.Client.Humanoid;
using Content.Client.Lobby.UI.Loadouts;
using Content.Client.Lobby.UI.Roles;
@ -12,13 +11,13 @@ using Content.Client.UserInterface.Systems.Guidebook;
using Content.Shared.CCVar;
using Content.Shared.Clothing;
using Content.Shared.GameTicking;
using Content.Shared.Guidebook;
using Content.Shared.Humanoid;
using Content.Shared.Humanoid.Markings;
using Content.Shared.Humanoid.Prototypes;
using Content.Shared.Preferences;
using Content.Shared.Preferences.Loadouts;
using Content.Shared.Roles;
using Content.Shared.StatusIcon;
using Content.Shared.Traits;
using Robust.Client.AutoGenerated;
using Robust.Client.Graphics;
@ -96,6 +95,8 @@ namespace Content.Client.Lobby.UI
[ValidatePrototypeId<GuideEntryPrototype>]
private const string DefaultSpeciesGuidebook = "Species";
public event Action<List<ProtoId<GuideEntryPrototype>>>? OnOpenGuidebook;
private ISawmill _sawmill;
public HumanoidProfileEditor(
@ -615,10 +616,11 @@ namespace Content.Client.Lobby.UI
{
Margin = new Thickness(3f, 3f, 3f, 0f),
};
selector.OnOpenGuidebook += OnOpenGuidebook;
var title = Loc.GetString(antag.Name);
var description = Loc.GetString(antag.Objective);
selector.Setup(items, title, 250, description);
selector.Setup(items, title, 250, description, guides: antag.Guides);
selector.Select(Profile?.AntagPreferences.Contains(antag.ID) == true ? 0 : 1);
var requirements = _entManager.System<SharedRoleSystem>().GetAntagRequirement(antag);
@ -754,6 +756,10 @@ namespace Content.Client.Lobby.UI
private void OnSpeciesInfoButtonPressed(BaseButton.ButtonEventArgs args)
{
// TODO GUIDEBOOK
// make the species guide book a field on the species prototype.
// I.e., do what jobs/antags do.
var guidebookController = UserInterfaceManager.GetUIController<GuidebookUIController>();
var species = Profile?.Species ?? SharedHumanoidAppearanceSystem.DefaultSpecies;
var page = DefaultSpeciesGuidebook;
@ -762,10 +768,10 @@ namespace Content.Client.Lobby.UI
if (_prototypeManager.TryIndex<GuideEntryPrototype>(DefaultSpeciesGuidebook, out var guideRoot))
{
var dict = new Dictionary<string, GuideEntry>();
var dict = new Dictionary<ProtoId<GuideEntryPrototype>, GuideEntry>();
dict.Add(DefaultSpeciesGuidebook, guideRoot);
//TODO: Don't close the guidebook if its already open, just go to the correct page
guidebookController.ToggleGuidebook(dict, includeChildren:true, selected: page);
guidebookController.OpenGuidebook(dict, includeChildren:true, selected: page);
}
}
@ -860,6 +866,7 @@ namespace Content.Client.Lobby.UI
{
Margin = new Thickness(3f, 3f, 3f, 0f),
};
selector.OnOpenGuidebook += OnOpenGuidebook;
var icon = new TextureRect
{
@ -868,7 +875,7 @@ namespace Content.Client.Lobby.UI
};
var jobIcon = _prototypeManager.Index(job.Icon);
icon.Texture = jobIcon.Icon.Frame0();
selector.Setup(items, job.LocalizedName, 200, job.LocalizedDescription, icon);
selector.Setup(items, job.LocalizedName, 200, job.LocalizedDescription, icon, job.Guides);
if (!_requirements.IsAllowed(job, out var reason))
{

View File

@ -1,9 +1,14 @@
<BoxContainer xmlns="https://spacestation14.io"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Orientation="Horizontal">
<Label Name="TitleLabel"
Margin="5 0"
MouseFilter="Stop"/>
<BoxContainer Name="OptionsContainer"
SetWidth="400"/>
<Label Name="TitleLabel"
Margin="5 0"
MouseFilter="Stop"/>
<!--21 was the height of OptionsContainer at the time that this button was added. So I am limiting the texture to 21x21-->
<Control SetSize="21 21">
<TextureButton Name="Help" StyleClasses="HelpButton"/>
</Control>
<BoxContainer Name="OptionsContainer"
SetWidth="400"/>
</BoxContainer>

View File

@ -1,10 +1,12 @@
using System.Numerics;
using Content.Client.Stylesheets;
using Content.Client.UserInterface.Controls;
using Content.Shared.Guidebook;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Prototypes;
using Robust.Shared.Utility;
namespace Content.Client.Lobby.UI.Roles;
@ -17,8 +19,10 @@ public sealed partial class RequirementsSelector : BoxContainer
{
private readonly RadioOptions<int> _options;
private readonly StripeBack _lockStripe;
private List<ProtoId<GuideEntryPrototype>>? _guides;
public event Action<int>? OnSelected;
public event Action<List<ProtoId<GuideEntryPrototype>>>? OnOpenGuidebook;
public int Selected => _options.SelectedId;
@ -60,18 +64,33 @@ public sealed partial class RequirementsSelector : BoxContainer
requirementsLabel
}
};
Help.OnPressed += _ =>
{
if (_guides != null)
OnOpenGuidebook?.Invoke(_guides);
};
}
/// <summary>
/// Actually adds the controls.
/// </summary>
public void Setup((string, int)[] items, string title, int titleSize, string? description, TextureRect? icon = null)
public void Setup(
(string, int)[] items,
string title,
int titleSize,
string? description,
TextureRect? icon = null,
List<ProtoId<GuideEntryPrototype>>? guides = null)
{
foreach (var (text, value) in items)
{
_options.AddItem(Loc.GetString(text), value);
}
Help.Visible = guides != null;
_guides = guides;
TitleLabel.Text = title;
TitleLabel.MinSize = new Vector2(titleSize, 0f);
TitleLabel.ToolTip = description;

View File

@ -78,6 +78,8 @@ namespace Content.Client.Stylesheets
public const string StyleClassLabelSmall = "LabelSmall";
public const string StyleClassButtonBig = "ButtonBig";
public const string StyleClassButtonHelp = "HelpButton";
public const string StyleClassPopupMessageSmall = "PopupMessageSmall";
public const string StyleClassPopupMessageSmallCaution = "PopupMessageSmallCaution";
public const string StyleClassPopupMessageMedium = "PopupMessageMedium";
@ -1346,6 +1348,10 @@ namespace Content.Client.Stylesheets
new StyleProperty(PanelContainer.StylePropertyPanel, new StyleBoxFlat { BackgroundColor = NanoGold, ContentMarginBottomOverride = 2, ContentMarginLeftOverride = 2}),
}),
Element<TextureButton>()
.Class(StyleClassButtonHelp)
.Prop(TextureButton.StylePropertyTexture, resCache.GetTexture("/Textures/Interface/VerbIcons/information.svg.192dpi.png")),
// Labels ---
Element<Label>().Class(StyleClassLabelBig)
.Prop(Label.StylePropertyFont, notoSans16),

View File

@ -1,6 +1,7 @@
using System.Numerics;
using Content.Client.Guidebook;
using Content.Client.Guidebook.Components;
using Content.Shared.Guidebook;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.CustomControls;
using Robust.Client.UserInterface.XAML;
@ -32,8 +33,8 @@ namespace Content.Client.UserInterface.Controls
set => WindowTitle.Text = value;
}
private List<string>? _helpGuidebookIds;
public List<string>? HelpGuidebookIds
private List<ProtoId<GuideEntryPrototype>>? _helpGuidebookIds;
public List<ProtoId<GuideEntryPrototype>>? HelpGuidebookIds
{
get => _helpGuidebookIds;
set

View File

@ -4,6 +4,7 @@ using Content.Client.Guidebook;
using Content.Client.Guidebook.Controls;
using Content.Client.Lobby;
using Content.Client.UserInterface.Controls;
using Content.Shared.Guidebook;
using Content.Shared.Input;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controllers;
@ -74,12 +75,12 @@ public sealed class GuidebookUIController : UIController, IOnStateEntered<LobbyS
public void OnSystemLoaded(GuidebookSystem system)
{
_guidebookSystem.OnGuidebookOpen += ToggleGuidebook;
_guidebookSystem.OnGuidebookOpen += OpenGuidebook;
}
public void OnSystemUnloaded(GuidebookSystem system)
{
_guidebookSystem.OnGuidebookOpen -= ToggleGuidebook;
_guidebookSystem.OnGuidebookOpen -= OpenGuidebook;
}
internal void UnloadButton()
@ -103,10 +104,29 @@ public sealed class GuidebookUIController : UIController, IOnStateEntered<LobbyS
ToggleGuidebook();
}
public void ToggleGuidebook()
{
if (_guideWindow == null)
return;
if (_guideWindow.IsOpen)
{
UIManager.ClickSound();
_guideWindow.Close();
}
else
{
OpenGuidebook();
}
}
private void OnWindowClosed()
{
if (GuidebookButton != null)
GuidebookButton.Pressed = false;
if (_guideWindow != null)
_guideWindow.ReturnContainer.Visible = false;
}
private void OnWindowOpen()
@ -127,30 +147,23 @@ public sealed class GuidebookUIController : UIController, IOnStateEntered<LobbyS
/// <param name="includeChildren">Whether or not to automatically include child entries. If false, this will ONLY
/// show the specified entries</param>
/// <param name="selected">The guide whose contents should be displayed when the guidebook is opened</param>
public void ToggleGuidebook(
Dictionary<string, GuideEntry>? guides = null,
List<string>? rootEntries = null,
string? forceRoot = null,
public void OpenGuidebook(
Dictionary<ProtoId<GuideEntryPrototype>, GuideEntry>? guides = null,
List<ProtoId<GuideEntryPrototype>>? rootEntries = null,
ProtoId<GuideEntryPrototype>? forceRoot = null,
bool includeChildren = true,
string? selected = null)
ProtoId<GuideEntryPrototype>? selected = null)
{
if (_guideWindow == null)
return;
if (_guideWindow.IsOpen)
{
UIManager.ClickSound();
_guideWindow.Close();
return;
}
if (GuidebookButton != null)
GuidebookButton.SetClickPressed(!_guideWindow.IsOpen);
if (guides == null)
{
guides = _prototypeManager.EnumeratePrototypes<GuideEntryPrototype>()
.ToDictionary(x => x.ID, x => (GuideEntry) x);
.ToDictionary(x => new ProtoId<GuideEntryPrototype>(x.ID), x => (GuideEntry) x);
}
else if (includeChildren)
{
@ -171,17 +184,17 @@ public sealed class GuidebookUIController : UIController, IOnStateEntered<LobbyS
_guideWindow.OpenCenteredRight();
}
public void ToggleGuidebook(
List<string> guideList,
List<string>? rootEntries = null,
string? forceRoot = null,
public void OpenGuidebook(
List<ProtoId<GuideEntryPrototype>> guideList,
List<ProtoId<GuideEntryPrototype>>? rootEntries = null,
ProtoId<GuideEntryPrototype>? forceRoot = null,
bool includeChildren = true,
string? selected = null)
ProtoId<GuideEntryPrototype>? selected = null)
{
Dictionary<string, GuideEntry> guides = new();
Dictionary<ProtoId<GuideEntryPrototype>, GuideEntry> guides = new();
foreach (var guideId in guideList)
{
if (!_prototypeManager.TryIndex<GuideEntryPrototype>(guideId, out var guide))
if (!_prototypeManager.TryIndex(guideId, out var guide))
{
Logger.Error($"Encountered unknown guide prototype: {guideId}");
continue;
@ -189,17 +202,29 @@ public sealed class GuidebookUIController : UIController, IOnStateEntered<LobbyS
guides.Add(guideId, guide);
}
ToggleGuidebook(guides, rootEntries, forceRoot, includeChildren, selected);
OpenGuidebook(guides, rootEntries, forceRoot, includeChildren, selected);
}
private void RecursivelyAddChildren(GuideEntry guide, Dictionary<string, GuideEntry> guides)
public void CloseGuidebook()
{
if (_guideWindow == null)
return;
if (_guideWindow.IsOpen)
{
UIManager.ClickSound();
_guideWindow.Close();
}
}
private void RecursivelyAddChildren(GuideEntry guide, Dictionary<ProtoId<GuideEntryPrototype>, GuideEntry> guides)
{
foreach (var childId in guide.Children)
{
if (guides.ContainsKey(childId))
continue;
if (!_prototypeManager.TryIndex<GuideEntryPrototype>(childId, out var child))
if (!_prototypeManager.TryIndex(childId, out var child))
{
Logger.Error($"Encountered unknown guide prototype: {childId} as a child of {guide.Id}. If the child is not a prototype, it must be directly provided.");
continue;

View File

@ -1,13 +1,49 @@
using Content.Client.Gameplay;
using Content.Client.Gameplay;
using Content.Client.Info;
using Content.Shared.CCVar;
using Content.Shared.Guidebook;
using Content.Shared.Info;
using Robust.Client.Console;
using Robust.Client.UserInterface.Controllers;
using Robust.Client.UserInterface.Controls;
using Robust.Shared.Configuration;
using Robust.Shared.Network;
using Robust.Shared.Prototypes;
namespace Content.Client.UserInterface.Systems.Info;
public sealed class InfoUIController : UIController, IOnStateExited<GameplayState>
{
[Dependency] private readonly IConfigurationManager _cfg = default!;
[Dependency] private readonly IClientConsoleHost _consoleHost = default!;
[Dependency] private readonly INetManager _netManager = default!;
[Dependency] private readonly IPrototypeManager _prototype = default!;
private RulesPopup? _rulesPopup;
private RulesAndInfoWindow? _infoWindow;
public override void Initialize()
{
base.Initialize();
_netManager.RegisterNetMessage<RulesAcceptedMessage>();
_netManager.RegisterNetMessage<ShowRulesPopupMessage>(OnShowRulesPopupMessage);
_consoleHost.RegisterCommand("fuckrules",
"",
"",
(_, _, _) =>
{
OnAcceptPressed();
});
}
private void OnShowRulesPopupMessage(ShowRulesPopupMessage message)
{
ShowRules(message.PopupTime);
}
public void OnStateExited(GameplayState state)
{
if (_infoWindow == null)
@ -17,12 +53,46 @@ public sealed class InfoUIController : UIController, IOnStateExited<GameplayStat
_infoWindow = null;
}
private void ShowRules(float time)
{
if (_rulesPopup != null)
return;
_rulesPopup = new RulesPopup
{
Timer = time
};
_rulesPopup.OnQuitPressed += OnQuitPressed;
_rulesPopup.OnAcceptPressed += OnAcceptPressed;
UIManager.WindowRoot.AddChild(_rulesPopup);
LayoutContainer.SetAnchorPreset(_rulesPopup, LayoutContainer.LayoutPreset.Wide);
}
private void OnQuitPressed()
{
_consoleHost.ExecuteCommand("quit");
}
private void OnAcceptPressed()
{
_netManager.ClientSendMessage(new RulesAcceptedMessage());
_rulesPopup?.Orphan();
_rulesPopup = null;
}
public GuideEntryPrototype GetCoreRuleEntry()
{
var guide = _cfg.GetCVar(CCVars.RulesFile);
var guideEntryPrototype = _prototype.Index<GuideEntryPrototype>(guide);
return guideEntryPrototype;
}
public void OpenWindow()
{
if (_infoWindow == null || _infoWindow.Disposed)
{
_infoWindow = UIManager.CreateWindow<RulesAndInfoWindow>();
}
_infoWindow?.OpenCentered();
}

View File

@ -3,6 +3,7 @@ using Content.Client.Guidebook.Richtext;
using Robust.Shared.ContentPack;
using Robust.Shared.Prototypes;
using System.Linq;
using Content.Shared.Guidebook;
namespace Content.IntegrationTests.Tests.Guidebook;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,29 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Content.Server.Database.Migrations.Postgres
{
/// <inheritdoc />
public partial class RemoveLastReadRules : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "last_read_rules",
table: "player");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<DateTime>(
name: "last_read_rules",
table: "player",
type: "timestamp with time zone",
nullable: true);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,29 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Content.Server.Database.Migrations.Postgres
{
/// <inheritdoc />
public partial class ReturnLastReadRules : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<DateTime>(
name: "last_read_rules",
table: "player",
type: "timestamp with time zone",
nullable: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "last_read_rules",
table: "player");
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,29 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Content.Server.Database.Migrations.Sqlite
{
/// <inheritdoc />
public partial class RemoveLastReadRules : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "last_read_rules",
table: "player");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<DateTime>(
name: "last_read_rules",
table: "player",
type: "TEXT",
nullable: true);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,29 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Content.Server.Database.Migrations.Sqlite
{
/// <inheritdoc />
public partial class ReturnLastReadRules : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<DateTime>(
name: "last_read_rules",
table: "player",
type: "TEXT",
nullable: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "last_read_rules",
table: "player");
}
}
}

View File

@ -7,6 +7,7 @@ using Content.Server.Database;
using Content.Server.Players;
using Content.Shared.Administration;
using Content.Shared.CCVar;
using Content.Shared.Info;
using Content.Shared.Players;
using Robust.Server.Console;
using Robust.Server.Player;

View File

@ -68,7 +68,6 @@ namespace Content.Server.Entry
factory.RegisterIgnore(IgnoredComponents.List);
prototypes.RegisterIgnore("parallax");
prototypes.RegisterIgnore("guideEntry");
ServerContentIoC.Register();

View File

@ -1,35 +0,0 @@
using Content.Shared.CCVar;
using Content.Shared.Info;
using Robust.Shared.Configuration;
using Robust.Shared.ContentPack;
namespace Content.Server.Info;
public sealed class InfoSystem : EntitySystem
{
[Dependency] private readonly IResourceManager _res = default!;
[Dependency] private readonly IConfigurationManager _cfg = default!;
public override void Initialize()
{
base.Initialize();
SubscribeNetworkEvent<RequestRulesMessage>(OnRequestRules);
}
private void OnRequestRules(RequestRulesMessage message, EntitySessionEventArgs eventArgs)
{
Log.Debug("Client requested rules.");
var title = Loc.GetString(_cfg.GetCVar(CCVars.RulesHeader));
var path = _cfg.GetCVar(CCVars.RulesFile);
var rules = "Server could not read its rules.";
try
{
rules = _res.ContentFileReadAllText($"/ServerInfo/{path}");
}
catch (Exception)
{
Log.Debug("Could not read server rules file.");
}
var response = new RulesMessage(title, rules);
RaiseNetworkEvent(response, eventArgs.SenderSession.Channel);
}
}

View File

@ -1,4 +1,4 @@
using System.Net;
using System.Net;
using Content.Server.Database;
using Content.Shared.CCVar;
using Content.Shared.Info;
@ -7,7 +7,7 @@ using Robust.Shared.Network;
namespace Content.Server.Info;
public sealed class RulesManager : SharedRulesManager
public sealed class RulesManager
{
[Dependency] private readonly IServerDbManager _dbManager = default!;
[Dependency] private readonly INetManager _netManager = default!;
@ -17,26 +17,22 @@ public sealed class RulesManager : SharedRulesManager
public void Initialize()
{
_netManager.RegisterNetMessage<ShouldShowRulesPopupMessage>();
_netManager.Connected += OnConnected;
_netManager.RegisterNetMessage<ShowRulesPopupMessage>();
_netManager.RegisterNetMessage<RulesAcceptedMessage>(OnRulesAccepted);
_netManager.Connected += OnConnected;
}
private async void OnConnected(object? sender, NetChannelArgs e)
{
if (IPAddress.IsLoopback(e.Channel.RemoteEndPoint.Address) && _cfg.GetCVar(CCVars.RulesExemptLocal))
{
return;
}
var lastRead = await _dbManager.GetLastReadRules(e.Channel.UserId);
if (lastRead > LastValidReadTime)
{
return;
}
var message = new ShouldShowRulesPopupMessage();
var message = new ShowRulesPopupMessage();
message.PopupTime = _cfg.GetCVar(CCVars.RulesWaitTime);
_netManager.ServerSendMessage(message, e.Channel);
}

View File

@ -47,20 +47,16 @@ public sealed class ShowRulesCommand : IConsoleCommand
}
}
var locator = IoCManager.Resolve<IPlayerLocator>();
var located = await locator.LookupIdByNameOrIdAsync(target);
if (located == null)
var message = new ShowRulesPopupMessage { PopupTime = seconds };
if (!IoCManager.Resolve<IPlayerManager>().TryGetSessionByUsername(target, out var player))
{
shell.WriteError("Unable to find a player with that name.");
return;
return;
}
var netManager = IoCManager.Resolve<INetManager>();
var message = new SharedRulesManager.ShowRulesPopupMessage();
message.PopupTime = seconds;
var player = IoCManager.Resolve<IPlayerManager>().GetSessionById(located.UserId);
netManager.ServerSendMessage(message, player.Channel);
}
}

View File

@ -21,16 +21,10 @@ namespace Content.Shared.CCVar
CVarDef.Create("server.id", "unknown_server_id", CVar.REPLICATED | CVar.SERVER);
/// <summary>
/// Name of the rules txt file in the "Resources/Server Info" dir. Include the extension.
/// Guide Entry Prototype ID to be displayed as the server rules.
/// </summary>
public static readonly CVarDef<string> RulesFile =
CVarDef.Create("server.rules_file", "Rules.txt", CVar.REPLICATED | CVar.SERVER);
/// <summary>
/// A loc string for what should be displayed as the title on the Rules window.
/// </summary>
public static readonly CVarDef<string> RulesHeader =
CVarDef.Create("server.rules_header", "ui-rules-header", CVar.REPLICATED | CVar.SERVER);
CVarDef.Create("server.rules_file", "DefaultRuleset", CVar.REPLICATED | CVar.SERVER);
/*
* Ambience
@ -1802,7 +1796,7 @@ namespace Content.Shared.CCVar
/// Don't show rules to localhost/loopback interface.
/// </summary>
public static readonly CVarDef<bool> RulesExemptLocal =
CVarDef.Create("rules.exempt_local", true, CVar.SERVERONLY);
CVarDef.Create("rules.exempt_local", false, CVar.SERVERONLY);
/*

View File

@ -1,8 +1,13 @@
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
using Robust.Shared.Utility;
namespace Content.Client.Guidebook;
namespace Content.Shared.Guidebook;
[Prototype("guideEntry")]
public sealed partial class GuideEntryPrototype : GuideEntry, IPrototype
{
public string ID => Id;
}
[Virtual]
public class GuideEntry
@ -10,7 +15,7 @@ public class GuideEntry
/// <summary>
/// The file containing the contents of this guide.
/// </summary>
[DataField("text", required: true)] public ResPath Text = default!;
[DataField(required: true)] public ResPath Text = default!;
/// <summary>
/// The unique id for this guide.
@ -21,28 +26,24 @@ public class GuideEntry
/// <summary>
/// The name of this guide. This gets localized.
/// </summary>
[DataField("name", required: true)] public string Name = default!;
[DataField(required: true)] public string Name = default!;
/// <summary>
/// The "children" of this guide for when guides are shown in a tree / table of contents.
/// </summary>
[DataField("children", customTypeSerializer:typeof(PrototypeIdListSerializer<GuideEntryPrototype>))]
public List<string> Children = new();
[DataField]
public List<ProtoId<GuideEntryPrototype>> Children = new();
/// <summary>
/// Enable filtering of items.
/// </summary>
[DataField("filterEnabled")] public bool FilterEnabled = default!;
[DataField] public bool FilterEnabled = default!;
[DataField] public bool RuleEntry;
/// <summary>
/// Priority for sorting top-level guides when shown in a tree / table of contents.
/// If the guide is the child of some other guide, the order simply determined by the order of children in <see cref="Children"/>.
/// </summary>
[DataField("priority")] public int Priority = 0;
}
[Prototype("guideEntry")]
public sealed partial class GuideEntryPrototype : GuideEntry, IPrototype
{
public string ID => Id;
[DataField] public int Priority = 0;
}

View File

@ -0,0 +1,41 @@
using Lidgren.Network;
using Robust.Shared.Network;
using Robust.Shared.Serialization;
namespace Content.Shared.Info;
/// <summary>
/// Sent by the server to show the rules to the client instantly.
/// </summary>
public sealed class ShowRulesPopupMessage : NetMessage
{
public override MsgGroups MsgGroup => MsgGroups.Command;
public float PopupTime { get; set; }
public override void ReadFromBuffer(NetIncomingMessage buffer, IRobustSerializer serializer)
{
PopupTime = buffer.ReadFloat();
}
public override void WriteToBuffer(NetOutgoingMessage buffer, IRobustSerializer serializer)
{
buffer.Write(PopupTime);
}
}
/// <summary>
/// Sent by the client when it has accepted the rules.
/// </summary>
public sealed class RulesAcceptedMessage : NetMessage
{
public override MsgGroups MsgGroup => MsgGroups.Command;
public override void ReadFromBuffer(NetIncomingMessage buffer, IRobustSerializer serializer)
{
}
public override void WriteToBuffer(NetOutgoingMessage buffer, IRobustSerializer serializer)
{
}
}

View File

@ -1,28 +0,0 @@
using Robust.Shared.Serialization;
namespace Content.Shared.Info
{
/// <summary>
/// A client request for server rules.
/// </summary>
[Serializable, NetSerializable]
public sealed class RequestRulesMessage : EntityEventArgs
{
}
/// <summary>
/// A server response with server rules.
/// </summary>
[Serializable, NetSerializable]
public sealed class RulesMessage : EntityEventArgs
{
public string Title;
public string Text;
public RulesMessage(string title, string rules)
{
Title = title;
Text = rules;
}
}
}

View File

@ -1,60 +0,0 @@
using Lidgren.Network;
using Robust.Shared.Network;
using Robust.Shared.Serialization;
namespace Content.Shared.Info;
public abstract class SharedRulesManager
{
/// <summary>
/// Sent by the server to show the rules to the client instantly.
/// </summary>
public sealed class ShowRulesPopupMessage : NetMessage
{
public override MsgGroups MsgGroup => MsgGroups.Command;
public float PopupTime { get; set; }
public override void ReadFromBuffer(NetIncomingMessage buffer, IRobustSerializer serializer)
{
PopupTime = buffer.ReadFloat();
}
public override void WriteToBuffer(NetOutgoingMessage buffer, IRobustSerializer serializer)
{
buffer.Write(PopupTime);
}
}
/// <summary>
/// Sent by the server when the client needs to display the rules on join.
/// </summary>
public sealed class ShouldShowRulesPopupMessage : NetMessage
{
public override MsgGroups MsgGroup => MsgGroups.Command;
public override void ReadFromBuffer(NetIncomingMessage buffer, IRobustSerializer serializer)
{
}
public override void WriteToBuffer(NetOutgoingMessage buffer, IRobustSerializer serializer)
{
}
}
/// <summary>
/// Sent by the client when it has accepted the rules.
/// </summary>
public sealed class RulesAcceptedMessage : NetMessage
{
public override MsgGroups MsgGroup => MsgGroups.Command;
public override void ReadFromBuffer(NetIncomingMessage buffer, IRobustSerializer serializer)
{
}
public override void WriteToBuffer(NetOutgoingMessage buffer, IRobustSerializer serializer)
{
}
}
}

View File

@ -1,3 +1,4 @@
using Content.Shared.Guidebook;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
@ -45,4 +46,11 @@ public sealed partial class AntagPrototype : IPrototype
// Actually check if the requirements are met. Because apparently this is actually unused.
[DataField, Access(typeof(SharedRoleSystem), Other = AccessPermissions.None)]
public HashSet<JobRequirement>? Requirements;
/// <summary>
/// Optional list of guides associated with this antag. If the guides are opened, the first entry in this list
/// will be used to select the currently selected guidebook.
/// </summary>
[DataField]
public List<ProtoId<GuideEntryPrototype>>? Guides;
}

View File

@ -1,4 +1,5 @@
using Content.Shared.Access;
using Content.Shared.Guidebook;
using Content.Shared.Players.PlayTimeTracking;
using Content.Shared.StatusIcon;
using Robust.Shared.Prototypes;
@ -123,6 +124,13 @@ namespace Content.Shared.Roles
[DataField]
public bool Whitelisted;
/// <summary>
/// Optional list of guides associated with this role. If the guides are opened, the first entry in this list
/// will be used to select the currently selected guidebook.
/// </summary>
[DataField]
public List<ProtoId<GuideEntryPrototype>>? Guides;
}
/// <summary>

View File

@ -33,7 +33,8 @@ ramping_average_end_time = 180.0
ramping_average_chaos = 4.5
[server]
id = "deltav"
id = "deltav"
rules_file = "DeltaVRuleset"
[discord]
rich_main_icon_id = "deltav"

View File

@ -3,8 +3,7 @@ hostname = "[EN][MRP] Delta-v (Ψ) | Inclination [EU West]"
soft_max_players = 50
[server]
rules_file = "Rules.txt"
rules_header = "ui-rules-header"
rules_file = "DeltaVRuleset"
[vote]
preset_enabled = true

View File

@ -3,8 +3,7 @@ hostname = "[EN][MRP] Delta-v (Ψ) | Periapsis [US East 2]"
soft_max_players = 50
[server]
rules_file = "Rules.txt"
rules_header = "ui-rules-header"
rules_file = "DeltaVRuleset"
[vote]
preset_enabled = true

View File

@ -1,3 +1,21 @@
guide-entry-deltav-Rules = Delta-V Rules
guide-entry-deltav-disclaimer-1 = D1. Proper AHelp Ettiquette
guide-entry-deltav-disclaimer-2 = D2. Do not exploit the game
guide-entry-deltav-rule-0 = 0. Admin Discretion
guide-entry-deltav-rule-e1 = E1. No Sexual Content/Themes
guide-entry-deltav-rule-e2 = E2. Use English
guide-entry-deltav-rule-e3 = E3. Rules regarding livestreaming
guide-entry-deltav-rule-1 = 1. Server Expectations
guide-entry-deltav-rule-2 = 2. Metagaming Guidelines
guide-entry-deltav-rule-3 = 3. New Life Rules
guide-entry-deltav-rule-4 = 4. Naming Convention Rules
guide-entry-deltav-rule-5 = 5. Roleplay Guidelines
guide-entry-deltav-rule-6 = 6. Powergaming Guidelines
guide-entry-deltav-rule-7 = 7. End-Of-Round (EOR) Rules
guide-entry-deltav-rule-c1 = C1. Command, Security and Justice Guidelines
guide-entry-deltav-rule-c2 = C2. Prisoner Guidelines
guide-entry-deltav-rule-c3 = C3. Follow Antagonist Guidelines
guide-entry-alert-levels = Alert Levels
guide-entry-justice = Justice

View File

@ -68,5 +68,60 @@ guide-entry-revolutionaries = Revolutionaries
guide-entry-minor-antagonists = Minor Antagonists
guide-entry-space-ninja = Space Ninja
guide-entry-rules = Server Rules
guide-entry-rules-core-only = Core Only Ruleset
guide-entry-rules-lrp = Standard Ruleset
guide-entry-rules-mrp = MRP Ruleset
guide-entry-rules-role-types = Role Types
guide-entry-rules-core = Core Rules
guide-entry-rules-c1 = C1
guide-entry-rules-c2 = C2
guide-entry-rules-c3 = C3
guide-entry-rules-c4 = C4
guide-entry-rules-c5 = C5
guide-entry-rules-c6 = C6
guide-entry-rules-c7 = C7
guide-entry-rules-c8 = C8
guide-entry-rules-c9 = C9
guide-entry-rules-c10 = C10
guide-entry-rules-c11 = C11
guide-entry-rules-c12 = C12
guide-entry-rules-c13 = C13
guide-entry-rules-c14 = C14
guide-entry-rules-roleplay = Roleplay Rules
guide-entry-rules-r1 = R1
guide-entry-rules-r2 = R2
guide-entry-rules-r3 = R3
guide-entry-rules-r4 = R4
guide-entry-rules-r5 = R5
guide-entry-rules-r6 = R6
guide-entry-rules-r7 = R7
guide-entry-rules-r8 = R8
guide-entry-rules-r9 = R9
guide-entry-rules-r10 = R10
guide-entry-rules-r11 = R11
guide-entry-rules-r12 = R12
guide-entry-rules-r13 = R13
guide-entry-rules-r14 = R14
guide-entry-rules-r15 = R15
guide-entry-rules-silicon = Silicon Rules
guide-entry-rules-s1 = S1
guide-entry-rules-s2 = S2
guide-entry-rules-s3 = S3
guide-entry-rules-s4 = S4
guide-entry-rules-s5 = S5
guide-entry-rules-s6 = S6
guide-entry-rules-s7 = S7
guide-entry-rules-s8 = S8
guide-entry-rules-s9 = S9
guide-entry-rules-s10 = S10
guide-entry-rules-space-law = Space Law
guide-entry-rules-sl-crime-list = Crime List
guide-entry-rules-sl-controlled-substances = Controlled Substances
guide-entry-rules-sl-restricted-gear = Restricted Gear
guide-entry-rules-sl-restricted-weapons = Restricted Weapons
guide-entry-rules-ban-types = Ban Types
guide-entry-rules-ban-durations = Ban Durations
guide-entry-writing = Writing
guide-entry-glossary = Glossary

View File

@ -4,3 +4,6 @@ ui-rules-header = DeltaV Official Server Rules
ui-rules-header-rp = DeltaV Roleplay Official Server Rules
ui-rules-accept = I have read and agree to follow the rules
ui-rules-wait = The accept button will be enabled after {$time} seconds.
ui-rules-button-home = Home
ui-rules-button-back = Back

View File

@ -0,0 +1,119 @@
- type: guideEntry
id: DeltaVRuleset
name: guide-entry-deltav-Rules
text: "/ServerInfo/Guidebook/DeltaV/Rules/DeltaVRuleset.xml"
priority: -2
ruleEntry: true
children:
- DeltaVDisclaimer1
- DeltaVDisclaimer2
- DeltaVRule0
- DeltaVRuleE1
- DeltaVRuleE2
- DeltaVRuleE3
- DeltaVRule1
- DeltaVRule2
- DeltaVRule3
- DeltaVRule4
- DeltaVRule5
- DeltaVRule6
- DeltaVRule7
- DeltaVRuleC1
- DeltaVRuleC2
- DeltaVRuleC3
- type: guideEntry
id: DeltaVDisclaimer1
name: guide-entry-deltav-disclaimer-1
text: "/ServerInfo/Guidebook/DeltaV/Rules/CommunityRules/D1_AdminRespect.xml"
ruleEntry: true
- type: guideEntry
id: DeltaVDisclaimer2
name: guide-entry-deltav-disclaimer-2
text: "/ServerInfo/Guidebook/DeltaV/Rules/CommunityRules/D2_Exploits.xml"
ruleEntry: true
- type: guideEntry
id: DeltaVRule0
name: guide-entry-deltav-rule-0
text: "/ServerInfo/Guidebook/DeltaV/Rules/0_Admin.xml"
ruleEntry: true
- type: guideEntry
id: DeltaVRuleE1
name: guide-entry-deltav-rule-e1
text: "/ServerInfo/Guidebook/DeltaV/Rules/CommunityRules/E1_ERP.xml"
ruleEntry: true
- type: guideEntry
id: DeltaVRuleE2
name: guide-entry-deltav-rule-e2
text: "/ServerInfo/Guidebook/DeltaV/Rules/CommunityRules/E2_Community.xml"
ruleEntry: true
- type: guideEntry
id: DeltaVRuleE3
name: guide-entry-deltav-rule-e3
text: "/ServerInfo/Guidebook/DeltaV/Rules/CommunityRules/E3_Streaming.xml"
ruleEntry: true
- type: guideEntry
id: DeltaVRule1
name: guide-entry-deltav-rule-1
text: "/ServerInfo/Guidebook/DeltaV/Rules/GameRules/1_ServerExpectations.xml"
ruleEntry: true
- type: guideEntry
id: DeltaVRule2
name: guide-entry-deltav-rule-2
text: "/ServerInfo/Guidebook/DeltaV/Rules/GameRules/2_Metagaming.xml"
ruleEntry: true
- type: guideEntry
id: DeltaVRule3
name: guide-entry-deltav-rule-3
text: "/ServerInfo/Guidebook/DeltaV/Rules/GameRules/3_NewLife.xml"
ruleEntry: true
- type: guideEntry
id: DeltaVRule4
name: guide-entry-deltav-rule-4
text: "/ServerInfo/Guidebook/DeltaV/Rules/GameRules/4_NamingConventions.xml"
ruleEntry: true
- type: guideEntry
id: DeltaVRule5
name: guide-entry-deltav-rule-5
text: "/ServerInfo/Guidebook/DeltaV/Rules/GameRules/5_RoleplayGuidelines.xml"
ruleEntry: true
- type: guideEntry
id: DeltaVRule6
name: guide-entry-deltav-rule-6
text: "/ServerInfo/Guidebook/DeltaV/Rules/GameRules/6_Powergaming.xml"
ruleEntry: true
- type: guideEntry
id: DeltaVRule7
name: guide-entry-deltav-rule-7
text: "/ServerInfo/Guidebook/DeltaV/Rules/GameRules/7_EOR.xml"
ruleEntry: true
- type: guideEntry
id: DeltaVRuleC1
name: guide-entry-deltav-rule-c1
text: "/ServerInfo/Guidebook/DeltaV/Rules/RoleRules/C1_CommandSecurityJustice.xml"
ruleEntry: true
- type: guideEntry
id: DeltaVRuleC2
name: guide-entry-deltav-rule-c2
text: "/ServerInfo/Guidebook/DeltaV/Rules/RoleRules/C2_PrisonerRule.xml"
ruleEntry: true
- type: guideEntry
id: DeltaVRuleC3
name: guide-entry-deltav-rule-c3
text: "/ServerInfo/Guidebook/DeltaV/Rules/RoleRules/C3_Antags.xml"
ruleEntry: true

View File

@ -28,7 +28,9 @@
name: guide-entry-chemist
text: "/ServerInfo/Guidebook/Medical/Chemist.xml"
children:
- Medicine
# - Medicine
# Duplicate guide entries are currently not supported
# TODO GUIDEBOOK Maybe allow duplicate entries?
- Botanicals
- AdvancedBrute

View File

@ -0,0 +1,26 @@
- type: guideEntry # Default for forks and stuff. Should not be listed anywhere if the server is using a custom ruleset.
id: DefaultRuleset
name: guide-entry-rules
ruleEntry: true
text: "/ServerInfo/Guidebook/ServerRules/DefaultRules.xml"
- type: guideEntry # DeltaV: Nukes all wizden rules except for the following ones
id: RoleTypes
name: guide-entry-rules-role-types
ruleEntry: true
priority: 20
text: "/ServerInfo/Guidebook/ServerRules/RoleTypes.xml"
- type: guideEntry # DeltaV: Nukes all wizden rules except for the following ones
id: BanTypes
name: guide-entry-rules-ban-types
ruleEntry: true
priority: 90
text: "/ServerInfo/Guidebook/ServerRules/BanTypes.xml"
- type: guideEntry # DeltaV: Nukes all wizden rules except for the following ones
id: BanDurations
name: guide-entry-rules-ban-durations
ruleEntry: true
priority: 100
text: "/ServerInfo/Guidebook/ServerRules/BanDurations.xml"

View File

@ -6,6 +6,7 @@
- Forensics
- Defusal
- CriminalRecords
# - SpaceLaw # TODO
- type: guideEntry
id: Forensics

View File

@ -21,5 +21,3 @@
id: Glossary
name: guide-entry-glossary
text: "/ServerInfo/Guidebook/Glossary.xml"

View File

@ -7,3 +7,4 @@
requirements:
- !type:OverallPlaytimeRequirement # DeltaV - Playtime requirement
time: 259200 # DeltaV - 72 hours
guides: [ SpaceNinja ]

View File

@ -4,6 +4,7 @@
antagonist: true
setPreference: true
objective: roles-antag-nuclear-operative-objective
guides: [ NuclearOperatives ]
requirements:
- !type:OverallPlaytimeRequirement
time: 108000 # DeltaV - 30 hours
@ -23,6 +24,7 @@
antagonist: true
setPreference: true
objective: roles-antag-nuclear-operative-agent-objective
guides: [ NuclearOperatives ]
requirements:
- !type:OverallPlaytimeRequirement
time: 108000 # DeltaV - 30 hours
@ -36,6 +38,7 @@
antagonist: true
setPreference: true
objective: roles-antag-nuclear-operative-commander-objective
guides: [ NuclearOperatives ]
requirements:
- !type:OverallPlaytimeRequirement
time: 216000 # DeltaV - 60 hours

View File

@ -10,6 +10,7 @@
- !type:DepartmentTimeRequirement # DeltaV - Command dept time requirement
department: Command
time: 36000 # DeltaV - 10 hours
guides: [ Revolutionaries ]
- type: antag
id: Rev
@ -17,3 +18,4 @@
antagonist: true
setPreference: false
objective: roles-antag-rev-objective
guides: [ Revolutionaries ]

View File

@ -4,6 +4,7 @@
antagonist: true
setPreference: true
objective: roles-antag-syndicate-agent-objective
guides: [ NuclearOperatives ]
requirements:
- !type:OverallPlaytimeRequirement # DeltaV - Playtime requirement
time: 86400 # DeltaV - 24 hours

View File

@ -7,6 +7,7 @@
requirements:
- !type:OverallPlaytimeRequirement # DeltaV - Playtime requirement
time: 43200 # DeltaV - 12 hours
guides: [ Zombies ]
- type: antag
id: Zombie
@ -14,3 +15,4 @@
antagonist: true
setPreference: false
objective: roles-antag-zombie-objective
guides: [ Zombies ]

View File

@ -0,0 +1,8 @@
<Document>
# Rule 0: Admin Discretion
- Admins can disregard any and all of these rules if they deem it in the best interest of the current round, server, and/or community at large.
- Administrators will be held fully accountable for their actions if they exercise this privilege.
- All of these rules apply as they are intended. Every example of a rule break cannot be defined as written, therefore, enforcement of the rules is subject to staff interpretation of the rule's intention.
- Any extended discussion regarding interpretation of the rules should be avoided in the AHelp menu and can be instead pursued within the Delta-V Discord in the #help channel, or on the forum at https://forum.delta-v.org in the Rule Clarifications section.
</Document>

View File

@ -0,0 +1,8 @@
<Document>
# Disclaimer D1. Proper AHelp Ettiquette
Do not use the AHelp for conversations of little substance.
- Intentionally disconnecting, responding with hostility, or refusing to respond when an admin privately messages you in-game will be met with an appeal-only ban.
- Additionally, abusing the AHelp relay by flooding it with garbage, checking for admins before stating a problem (ex: "hello?", "any admins?"), using it as a chatroom, or sending messages of no substance will result in your removal.
- All AHelp messages are relayed to the Delta-V Discord.
</Document>

View File

@ -0,0 +1,7 @@
<Document>
# Disclaimer D2. Do not exploit.
Do not exploit the game, use cheats or macros.
- The usage of any third-party applications/scripts/client modifications or any other applicable software to gain an advantage, avoid intended game/server mechanics, or to harm server infrastructure is strictly prohibited, as is the abuse of glitches, exploits and bugs.
- Any and all instances of this will be met with an appeal-only ban; please use the #bug-reports channel on the Discord, or the issues section of the GitHub (DeltaV-Station/Delta-V) to report any issues you find in-game.
</Document>

View File

@ -0,0 +1,7 @@
<Document>
# Rule E1: No sexual content/themes
No sexual content/themes including erotic roleplay (ERP) and no shock content.
- Erotic Roleplay (ERP), erotic content, or 18+ sexual content is not allowed under any circumstance.
- This includes comments not explicitly sexual in nature that contain words, phrases, or ideations that are deemed inappropriate by staff or members.
- [color=#ff0000]If roleplay reaches a point where it has become sexual and/or uncomfortable, immediately stop and contact an administrator or moderator.[/color]
</Document>

View File

@ -0,0 +1,11 @@
<Document>
# Rule E2: Use English
Delta-V is an English-based Community;
- Use English as your primary method of communication within the game and Delta-V servers.
- Do not spam or advertise on our server.
- Be respectful towards other members and avoid making others uncomfortable.
- We have a zero tolerance policy for racism, sexism, homophobia, violence, threats, hate speech, slurs, and other forms of bigotry, discrimination, and harassment.
Slurs and terms that use real or implied mental or physical disability to mock or denigrate members or their in-game characters are also strictly prohibited. Failure to comply with this rule will result in community removal.
- The denigration of other player characters through reference to their species/morphotype or debasement by comparison to nonsophonts on a discriminatory basis is strictly prohibited and may result in an appeal-only ban.
</Document>

View File

@ -0,0 +1,9 @@
<Document>
# Rule E3: Rules regarding livestreaming
Delta-V welcomes content creators and streamers to our community, but we have a few rules regarding livestreaming game servers.
- While a stream delay is not necessary, it is highly recommended to have at least a 10 second delay.
- Please let admins know you are streaming via the AHelp prior to doing so.
- If your chat or viewers are in-game with you while also watching your stream, they are breaking our server rules.
- Please do not coordinate with them and discourage this behavior if it is seen.
</Document>

View File

@ -0,0 +1,42 @@
<Document>
# Server Rules
This is a Delta-V server. If you are banned on this server, you will be banned on all Delta-v Servers.
This is a roleplay server, meaning that roleplay rules apply.
[color=#ffDD00]This is also an MRP server. Try to immerse yourself into your character. This includes interacting with your fellow crewmates, and using roleplay as the primary vessel to play the game alongside things like your job on the station. MRP places less emphasis on "winning" and more on just telling a story.[/color]
Space Station 14 is not like most games. Many rules are designed to require roleplay, and not all rules are intuitive. Please take the time to read and understand the rules before you play so that you aren't surprised. Our community rules specifically are zero-tolerance rules, meaning that a violation will result in an appeal-only ban. Game admins will treat you as if you have read the rules, even if you have not.
## Server Disclaimers
[color=#ff0000]You must be at least 17 years of age to play on Delta-V's servers. Any users suspected of being under the age of 17 will be removed.
By connecting to this server, you agree to our privacy policy found at [color=#808080]https://go.delta-v.org/privacy. [/color]
- [textlink="D1. Proper AHelp Ettiquette." link="DeltaVDisclaimer1"]
- [textlink="D2. Do not exploit the game." link="DeltaVDisclaimer2"]
If you have any questions about these rules, please use the admin help menu by hitting F1 in-game or clicking the "AHelp" button in the lobby, or by making a post in the "Rules Clarification" section of our forum at [color=#808080]https://forum.delta-v.org. [/color]
## Community Rules
These rules apply at all times, including between rounds.
- [textlink="0. Admin Discretion." link="DeltaVRule0"]
- [textlink="E1. No Sexual Content/Themes" link="DeltaVRuleE1"]
- [textlink="E2. Use English" link="DeltaVRuleE2"]
- [textlink="E3. Rules regarding livestreaming" link="DeltaVRuleE3"]
## Game Server Rules
These rules apply within the context of rounds.
- [textlink="1. Server Expectations" link="DeltaVRule1"]
- [textlink="2. Metagaming Guidelines" link="DeltaVRule2"]
- [textlink="3. New Life Rules" link="DeltaVRule3"]
- [textlink="4. Naming Convention Rules" link="DeltaVRule4"]
- [textlink="5. Roleplay Guidelines" link="DeltaVRule5"]
- [textlink="6. Powergaming Guidelines" link="DeltaVRule6"]
- [textlink="7. End-Of-Round (EOR) Rules" link="DeltaVRule7"]
## Command, Security, Justice and Antagonist Guidelines
These rules apply within rounds for specific roles.
- [textlink="C1. Command, Security and Justice Guidelines" link="DeltaVRuleC1"]
- [textlink="C2. Prisoner Guidelines." link="DeltaVRuleC2"]
- [textlink="C3. Follow Antagonist Guidelines" link="DeltaVRuleC3"]
</Document>

View File

@ -0,0 +1,11 @@
<Document>
# Rule 1: Server Expectations
- Do not cause too much trouble for the crew as a non-antagonist (i.e. do not "self-antag"). NON-ANTAGONIST Players who cause great structural damage, unnecessarily harm/remove players from the round, or are otherwise causing problems without a good-faith attempt at roleplaying can face administrative punishment.
- Clowns, Mimes, and other "prankster" roles do not get an exemption from the above, and should not use their job as an excuse to be a major disturbance.
- If you are banned from a role or department, you may not play that role. This includes seeking or accepting promotions into roles you are banned from.
- Department strikes (e.g. cargonia and any variation thereof), riots, cults, and any other type of similar largely disruptive behavior are strictly forbidden without both excellent roleplay justification and explicit administrator pre-approval.
- AFK (a.k.a. SSD) and catatonic players are considered to have the same rights as any other crewmate.
- If a player is dead and catatonic (not SSD), they are not required to be revived and should be stored in the morgue. You should not biomass grind dead and catatonic crew unless in an emergency.
- If a player is alive and catatonic, they may be brought to their relevant department or cryostorage as necessary.
</Document>

View File

@ -0,0 +1,14 @@
<Document>
# Rule 2: Metagaming Guidelines
- Do not use the Emote channel to bypass an inability to speak. This includes examples like "I'm friendly," "oh weird I can't speak," or "mimes a flashlight".
- Additionally, use of the emote channel to simulate character death rattles or other game mechanics is prohibited.
- Use the local-out-of-character (LOOC) and global out-of-character (OOC) channels properly. Don't speak of in-character matters in those channels unless you're asking questions related to in-game concepts.
- Do not use in-character channels to bypass a lack of ability to use OOC/LOOC chats (e.g. "Huh, wonder where the captain went? OOC He probably left to get dinner lol").
- Do not engage in meta-communications (i.e. using external channels to communicate with other players in the same game).
- Do not stream, discuss, or share information about the current round to the Delta-V Discord.
- You are allowed to have knowledge of past experiences and prior shifts, and players are allowed to have in-character relationships (friends, enemies, or otherwise). However, this cannot be used as a sole reason to grant or deny items/accesses/favors based exclusively on having a relationship with one another (i.e. meta-friending/meta-grudging).
- Antagonists in previous rounds must not be treated differently due to their prior antagonist status. Notwithstanding, confession of crimes committed in a prior shift are still admissible in court.
- Additionally, and for the sake of continuity, your character will never have permanently died in previous rounds.
- Do not "antag roll." This is the act of joining rounds for the purpose of seeing if you have received an antagonist role, and leaving soon after if not.
</Document>

View File

@ -0,0 +1,7 @@
<Document>
# Rule 3: New Life Guidelines
- If a player dies and is brought back by way of cloning or borging, they forget the last five minutes leading up to their death and cannot describe who or what killed them.
- Players that are revived by using a defibrillator can only recall vague details about their death, such as "Someone shot me" or "I was set ablaze" but they cannot recall details beyond that. [color=#ff0000]Please report players who break this rule.[/color]
- In either case, characters do not have any knowledge of what happened while they were dead (i.e. ghosted/observing).
</Document>

View File

@ -0,0 +1,11 @@
<Document>
# Rule 4: Naming Conventions
In-character names must fit the server standards of:
- Doesn't make obvious references,
- Isn't an obvious pun or play on words,
- Isn't obscene,
OR
- Is a result of random name generation.
The only exception to the above is theatrical roles such as the clown, boxer, and mime; these roles are allowed stage names with some freedom, as long as it is not obscene. Administrators reserve the right to approve or deny character names at their discretion.
</Document>

View File

@ -0,0 +1,13 @@
<Document>
# Rule 5: Roleplay Guidelines
- Your character is a separate entity from you, the player. Your character's actions, feelings, and knowledge in-game should be based solely on the character's experiences rather than your own as the player.
- Low roleplay actions that have no regard for your character or little bearing on setting (such as memes, silly copy paste spam IC) are not acceptable. Your character is a worker aboard a space station and will be held accountable.
- Do not fax memes, copypasta, or spam to Central Command.
- Do not escalate situations needlessly as a crew-aligned role. Very few things are deserving of a fight to the death.
- If a fight results in someone being critically injured, seek medical help for them - and if they die, do not destroy or otherwise hide their body. This falls under self-antagonistic behavior.
- Pest ghost roles such as mice are always fair game for attacking. Do not grief crew-aligned ghost roles such as familiars, drones, or pets without provocation.
- Some awakened pest roles (e.g. sentient mothroach) may be considered crew pets and fall under this rule.
- [color=#ff0000]Non-security personnel should not seek to kill or detain unrelated threats.[/color] Crew may neutralize threats when they present themselves or if they are relevant to the crew member in question.
- Certain severe emergencies may make it reasonable for normal crew to defend themselves and their station, such as nuclear operatives, a zombie outbreak, space dragon attack, or other critical situation.
</Document>

View File

@ -0,0 +1,8 @@
<Document>
# Rule 6: Powergaming Guidelines
If you, in your given role, require an item that does not fall within your job's usual parameters, you should have a valid reason to obtain and keep it. Finding something laying around without a clear owner is a valid reason.
- Manufacturing weapons, bombs, or deadly poisons before you know of any reason you would need them is not allowed.
- Hiding Traitor objective items or preemptively securing them with higher security than usually required or than would make logical sense violates our powergaming and roleplay guidelines.
- Do not, [color=#ff0000]under any circumstances[/color], hide the nuclear fission explosive, authentication disk, or other sensitive items in an impossible to see/access location.
</Document>

View File

@ -0,0 +1,6 @@
<Document>
# Rule 7: End-Of-Round (EOR) Rules
- Significant end-of-round grief (EORG) is not allowed. This includes attacking, destroying, polluting, and severely injuring without reason both at and on the way to Central Command.
- Explosives and strategies with capacity for high collateral damage should not be used on or around the evacuation shuttle after it arrives at the station.
</Document>

View File

@ -0,0 +1,13 @@
<Document>
# Rule C1: Command, Security and Justice Guidelines
- Security, Justice, and Command roles are held to a higher standard of roleplay, and are expected to know and perform their jobs to the best of their ability. These roles often heavily impact the round and require more careful and conscientious roleplay; if you cannot meet these requirements do not take these roles.
- The three departments are required to read and follow Delta-V Space Law, Standard Operating Procedure, Alert Procedure, and Company Policy to the best of their ability.
- Abandoning your role to go do whatever you want instead of managing your department or maintaining security, abusing your position or using it to make arbitrary or malicious choices to the detriment of the station, and being negligent to the point of harm is prohibited.
- If you need to leave the round, notify your fellow crew via departmental radio and put your equipment in its proper places prior to going to cryo. If you need to leave IMMEDIATELY, please at least send an ahelp saying that you're leaving.
- Do not give up or trade away Traitor objective items, departmental/Command tools and remotes, and sensitive equipment without excellent reason.
- Some leeway is given to making deals with criminals [italic]if and only if[/italic] the deal benefits the safety or situation of the station or circumstances rather than just yourself (e.g. hostage situations).
- Some leeway can be given in [color=#ff0000]extreme circumstances[/color] of extreme shortstaffing and/or emergency/crisis.
- Command, Justice, and Security are expected to uphold the law and maintain order aboard the station. Do not engage in lawbreaking activity or troublemaker behavior, and ensure that company policy and standard operating procedure - not just space law - is being observed. Security is expected to intervene into criminal activity where possible and safe to do so. Heads of departments are at minimum expected to report criminal activity to Security and should cooperate with law enforcement where possible.
- Do not hire random crew to be your bodyguard(s) or promote random crewmembers to Command positions at random. If you require bodyguards or security details, talk to your Security department. If you need new Command staff, talk to the personnel in that related department.
</Document>

View File

@ -0,0 +1,8 @@
<Document>
# Rule C2: Prisoner Guidelines
By picking the prisoner role, you have chosen to roleplay as a prisoner.
You are still subject to the same rules regarding escalation, and should only seek to escape from the brig with excellent reasoning (e.g. abusive security personnel or badly damaged permanent brig).
Escaping for no reason is considered a self-antagonistic activity.
If you are unsure whether your escape reason is valid, feel free to AHelp it first. [color=#ff0000]Lack of administrator response does not constitute approval.[/color]
</Document>

View File

@ -0,0 +1,11 @@
<Document>
# Rule C3: Antagonist Guidelines
- The damage that antagonists can cause should be roughly proportional to their objectives, and contribute towards achieving them in some way.
If you are concerned as to whether or not what you're about to do is allowed, feel free to AHelp and ask an admin for clarification. [color=#ff0000]Lack of administrator response does not constitute approval.[/color]
- Antagonists exist not only as a role for your character but also as a game mechanic. Seek to push forward the round through your antagonistic actions, rather than grind it to halt in pursuit of your objectives.
- Other antagonists are not necessarily your friends. Other agents, mercenaries, and possibly even space dragons are free agents that you may negotiate with at your own risk, but no one should be working together with xenomorphs or zombies.
- Heavily damaging/spacing or camping arrivals/cryo, unnecessarily extending the round, and behavior that calls the round to an end prematurely - as well as other lame behaviors - are strictly forbidden for all antags except for station-destroying antags, such as nuclear operatives or space dragons.
- As a non-sentient or partially-sentient antagonist, you are expected to have only a limited understanding of space stations and their mechanics.
Slimes, zombies, and spiders should [color=#ff0000]not[/color] be targeting the gravity generator or the AME, nor should they be unnecessarily spacing the station.
</Document>

View File

@ -0,0 +1,17 @@
<Document>
# Ban Durations
Bans can be appealed at forum.ss14.io in the ban appeals section.
## Temporary
Temporary bans will be lifted automatically after a certain amount of time. If they are a game ban, they will tell you how much time is remaining when you try to connect.
## Indefinite
These bans will only be removed on a successful appeal on the forums. Any ban which doesn't tell you when it expires and doesn't specify otherwise can be presumed to be an indefinite ban.
## Voucher
This is an indefinite ban which may only be appealed both with a successful appeal and which require a voucher of good behavior from the administrative team of a well-known or at least decently active SS13/SS14 server in order for the appeal to be considered. Voucher bans typically cannot be appealed for at least six months after being issued. Without a voucher, a player can only attempt to appeal a voucher ban once, and only if the ban was inappropriately placed. Voucher bans are typically only placed as a result of an unsuccessful appeal of an indefinite game ban by players with a history of bans and of causing issues.
## Permanent
This is a ban that is only appealable if the ban was inappropriately placed, including if the ban should not have been permanent. If the result of the appeal is that the ban was appropriately placed, the ban may not be appealed again and will not be lifted. These bans are extremely rare, but are applied to players who continually cause problems even after a voucher ban or users who have completely unacceptable behavior may be permanently removed.
</Document>

View File

@ -0,0 +1,11 @@
<Document>
# Ban Types
Bans can be appealed at forum.ss14.io in the ban appeals section.
## Role Ban
Also called a "job ban", this ban prevents your character from joining or late-joining a round as one or more jobs or roles. These are often used in response to problematic behavior in particular departments or address gross inexperience in important roles such as heads of staff. These bans do not mechanically prevent you from switching to the role during a round or acting as that role, but doing so is considered ban evasion.
## Game Ban
Also called a "server ban", this ban prevents you from connecting to all Wizard's Den servers.
</Document>

View File

@ -0,0 +1,5 @@
<Document>
# Server Rules
This server has not written any rules yet. Please listen to the staff.
</Document>

View File

@ -0,0 +1,5 @@
These files contain Wizard's Den server rules. Since they reference Wizard's Den, they should not be used
by other servers without at least enough modification to not mislead players into thinking that they are
playing on Wizard's Den.
The filenames used for the rules files are not themselves rules. Only the contents of the files are rules.

View File

@ -0,0 +1,21 @@
<Document>
# Role Types
## Crew Aligned/Non-antagonist
In most rounds, a majority of players will be non-antagonists, meaning that they are crew aligned. This is the "default" role, if the game doesn't tell you that you are one of the other roles defined here, then you are a non-antagonist. Overall, non-antagonists are intended to work towards a net positive effect on the round.
## Solo Antagonist
Certain roles are intended to cause problems for the round or for non-antagonists. You are only a solo antagonist if the game clearly and explicitly tells you that you are a solo antagonist. Antagonists are exempt from many but not all roleplay rules.
## Team Antagonist
Team antagonists are like solo antagonists but they have other antagonists who they are expected to not hinder, and who they may be expected to help. You are only a team antagonist if the game clearly and explicitly tells you that you are a team antagonist.
## Free Agent
Certain roles are free to choose if they want to behave as an antagonist or as a non-antagonist, and may change their mind whenever they'd like. You are only free agent if the game clearly and explicitly tells you that you are a free agent.
## Familiar
Familiars are considered non-antagonists, but have instructions to obey someone. They must obey this person even if it causes them to violate roleplay rules or die. You are only a familiar if the game clearly and explicitly tells you that you are a familiar. You are only the familiar of the person the game tells you.
## Silicon
Silicones have a set of laws that they must follow above all else except the core rules. You are only silicon if the game clearly and explicitly tells you that you are a silicon.
</Document>

View File

@ -1,126 +0,0 @@
[color=#ff0000]YOU MUST BE AT LEAST 16 YEARS OF AGE TO PLAY ON WIZARD'S DEN SERVERS. ANY USERS SUSPECTED OF BEING UNDER 16 YEARS OF AGE WILL BE BANNED UNTIL THEY ARE OF AGE.[/color]
[color=#ff0000]DISCONNECTING FROM OR IGNORING/EVADING ADMIN-HELPS WILL RESULT IN AN APPEAL ONLY BAN.[/color]
This is the "short" form of the rules, which has all the information any regular player should need. You can find the "long" form of the rules with more examples & clarifications of any ambiguity on our wiki at [color=#a4885c]wiki.spacestation14.io[/color]. If you are already familiar with LRP rules and would like to get a quick idea of what the diffences are between MRP this page clearly highlights them.
Should you need it. Some RP-specific documents available on the wiki such as Space Law, the Standard Operating Procedure, and the Alert Procedure will be mentioned here and are expected to be followed.
[color=#ff0000]Recent Changes[/color]
- Revolutionary rules have been added (#12, #16)
- Silicon rules have been added (#23)
- Security/command rules have been updated to address forced borging (#22)
[color=#a4885c]01.[/color] [color=#a4885c]The[/color] [color=#ffd700]Golden[/color] [color=#a4885c]Rule.[/color] Admins may excercise discretion with rules as they see fit. If you rule lawyer or line skirt, you will get removed. Admins will answer for use of this privilege.
[color=#ff0000]ZERO TOLERANCE RULES[/color]
[color=#a4885c]02.[/color] Absolutely no hate speech, slurs, bigotry, racism, specism (demeaning other characters in-game due to their in-game race), sexism, or anything even remotely similar. (YOU WILL GET PERMABANNED)
[color=#a4885c]03.[/color] Absolutely no Erotic Roleplay (ERP) or sexual content, including direct or indirect mentions of sexual behavior or actions. (YOU WILL GET PERMABANNED) (Leeway is given to insults, ex: 'You are a dickhead', do not push it)
[color=#a4885c]04.[/color] Don't communicate in-game/in-character information through methods outside of the game (such as talking in Discord with other users actively playing or by talking to your sibling across the room while you are both playing). This is referred to as "Metacomming". Adminstrators cannot police metacommunications, we must assume it is being abused. (ALL INVOLVED WILL GET PERMABANNED)
[color=#a4885c]05.[/color] Attempting to evade game bans will result in an automatic appeal-only permanent ban that is only appealable after six months and only with a voucher of good behavior from another SS13/SS14 server. Attempting to evade job bans will result in an appeal-only permanent ban. (YOU WILL GET BANNED MUCH WORSE THAN YOU ALREADY WERE)
[color=#ff0000]GENERAL ETIQUETTE[/color]
[color=#a4885c]06.[/color] These are English servers. Speak only English in IC and OOC.
[color=#a4885c]07.[/color] Don't use exploits or external programs to play, gain an advantage, or disrupt/crash the round/server. This includes autoclickers and scripts to automate the game or evade AFK detection. Intentionally attempting to lag/crash the server will result in an immediate appeal-only ban.
[color=#a4885c]08.[/color] Don't use multiple SS14 accounts to play (referred to as "multi-keying"). Users knowingly using multiple SS14 accounts will have all of their accounts banned.
[color=#a4885c]09.[/color] Do not ignore the admin help relay or abuse it by flooding it with garbage, checking for admins before stating a problem (ex: "hello?", "any admins?"), using it as a chatroom, or sending messages of no substance. Hostility to administators in the relay will likely result in your removal. All admin helps are sent to the SS14 Discord.
[color=#ff0000]IN GAME & ROLEPLAY RULES[/color]
[color=#a4885c]10.[/color] Pick a realistic name that could appear on a birth certificate with at least a first and last name (leeway is given to this for Clowns, Mimes, and non-human races).
- Names of notable famous or fictional persons or names that resemble/parody them are strictly forbidden. You are not clever if you slightly change a famous name around. Terrible names open you up to being politely reminded to change it, smited, or instantly banned, depending on severity.
- Names resulting in inappropriate phonetic play-on-words are forbidden (ex: "Mike Oxlong", "Ben Dover", "Dixie Normus"). They are also extremely overdone.
[color=#a4885c]11.[/color] Act like an actual human being on a space station in a medium-roleplay (MRP) environment. Do not use text speak or emoticons IC, and do not refer to OOC things like admins in-game. Do not threaten players that you are calling the admins on them. Do not use emotes to bypass speech filters or muteness. You are not required to write a backstory or follow procedure to exacts; however, you are expected to at least make an effort to act like your role.
- This server is a "Roleplay Expected" server. We define this as performing your assigned duties, "doing your job". This means it is important to do what is expected out of your department and not what would be expected out of other departments.
- Dont do other peoples jobs for them. Opt in for the role you intend to play or change your job by visiting the Head of Personnel. Failure to do your basic duties may result in a job ban.
[color=#a4885c]12.[/color] Don't be a dick. You are playing a multiplayer game with other people who also want to enjoy the game.
- [color=#ff0000]The arrivals station, shuttle, and general arrivals docking area are completely off-limits to any hostile activity, including activity by antagonists. Attacking newly spawned players in these areas or damaging/sabotaging these areas is strictly forbidden.[/color]
- Do not intentionally make other players' lives hell for your own amusement.
- [color=#ff0000]THE ROUND IS NOT OVER UNTIL THE GAME RETURNS TO THE LOBBY. ESCALATION AND SELF-ANTAG RULES APPLY EVEN AFTER THE ROUND SUMMARY APPEARS.[/color]
- Antagonists have a lot of leeway with this rule and may kill/sabotage as they see fit, however if your behavior degrades the experience for the majority of the server you will be told to stop. Antagonists are still generally forbidden from causing massive station damage early into the round (less than 30 minutes) and are forbidden from needlessly prolonging rounds. For antagonist specific rules, see the "long" form of the rules at [color=#a4885c]wiki.spacestation14.io[/color].
[color=#a4885c]13.[/color] Don't harass or target players across rounds for actions in prior rounds or for actions outside of the game (this is referred to as "Metagrudging".)
- Annoying players for IC reasons in the current round is fine; doing it across rounds or as a ghost role after they kill you is not.
[color=#a4885c]14.[/color] Don't use information gained from outside your character's knowledge to gain an advantage (this is referred to as "Metagaming").
- Using information you gain from outside your own character (such as spectating while a ghost, metacomms, or other means) to your advantage is strictly forbidden. If you take a ghost role, unless otherwise stated, you DO NOT REMEMBER ANYTHING from your past life.
- New Life Rule is in effect, you remember all events up until you fall unconscious unless you enter a dead state. Being defibrillated will return all your memories expect for the events leading up to your death, being cloned will make your character forget everything since the shift started.
[color=#a4885c]15.[/color] Do your best not to interact negatively with SSD/AFK players. Moving them to safety is acceptable; killing, looting, or otherwise griefing them while they are away is not.
- SSD characters are players who are disconnected or AFK. It is possible for players to return to SSD bodies. Players become catatonic when they take a ghost spawner role or commit suicide. Players are NOT able to return to these bodies without admin intervention.
- If the player in question is an antags target or they are being secured by security, interactions to finish what is required of your duties/objectives are always acceptable.
- Ahelping about an SSD/AFK player may grant an exception to this rule.
- This does not apply to players that are catatonic, although needlessly killing or harming catatonic players is discouraged.
[color=#a4885c]16.[/color] Follow escalation rules and don't murder someone for slipping you, use common sense. Do not make Cargonia.
- You can defend yourself to the extent of protecting your own life.
- Security may use less-lethal force to effect arrests of criminals.
- Don't outright leave people to die if you get in a fight, make an effort to heal them or bring them to Medbay.
- Adminhelp the situation if you think someone is over-escalating.
- Department strikes, revolutions (ex: cargonia and any variation thereof), riots, cults, and any other type of similar largely disruptive behavior are strictly forbidden. Other than for revolutionary antagonists, these activities are strictly forbidden. All players, including antagonists other than revolutionaries, must obtain admin permission before engaging in this behavior (forewarning: you are unlikely to get permission).
[color=#a4885c]17.[/color] Don't immediately ghost or suicide from your role if you do not get antagonist (referred to as "Antag-rolling") or from head roles without notifying your chain of command or administrators.
- This is not fair to other players actually waiting patiently for an antagonist round. Alternatively, if you do not want to play an antagonist or do not want to cause conflict, do not opt-in for antagonist roles.
- Head of Staff roles help drive rounds. If you need to leave, please admin-help your role and that you are leaving. There is no need to wait for a reply when admin-helping that you need to disconnect as a head role.
[color=#a4885c]18.[/color] Don't rush for or prepare equipment unrelated to your job for no purpose other then to have it "just in case" (referred to as "Powergaming").
- A medical doctor does not need insulated gloves, and the Head of Personnel does not need to give themselves armory access so they can go grab a gun. Have an actual reason for needing these things.
- Don't manufacture weapons, bombs, or death poisons before you know of any reason you would need them.
- Don't pre-emptively hide antagonist objectives or pre-emptively secure them with higher security then normally required.
- Don't manufacture or prepare things for the "end of the round" when the shuttle docks with Central Command.
[color=#a4885c]19.[/color] Intentionally making yourself a major problem/annoyance/disruption for the crew or other players at large while not an antagonist is forbidden (referred to as "self-antagging").
- Don't openly try to cooperate with obvious or known antagonists as a non-antagonist.
[color=#ff0000]SECURITY & COMMAND RULES[/color]
[color=#ff0000]Space Law, Standard Operating Procedure and Alert Procedure policy/guidelines are expected to be adhered to[/color]. These can be found at wiki.spacestation14.io.
If you regularly play Security or Command roles and got this far, we applaud you for reading. These rules also apply to any individual who is promoted or is acting in the place of a Security/Command role (unless they are an antagonist).
[color=#a4885c]20.[/color] Command and Security are held to a higher standard of play.
- Be competent in your job and department. Failure to know the basics of your department is liable to result in a job ban.
- Do not willingly and openly cooperate with terrorists/antagonists. Do not give away your objective items. Some leeway is given to making deals with antagonists if the deal benefits the safety or situation of the station as a whole and not just yourself.
- Uphold the Law & maintain order. Do not engage in lawbreaking activity or troublemaker behavior. Security is expected to intervene into criminal activity where possible. Heads of Staff are at minimum expected to report criminal activity to Security.
- Do not immediately abandon your position as a Command role and go do whatever you want instead of managing your department/the station. Do not abuse your position or use it to make arbitrary choices to the detriment of the station.
- Do not hire random crew to be your bodyguards or promote random to Captain or a Head of Staff at random. If you need bodyguards, talk to your security department. If you need a new Command role, talk to the personnel in that related department.
- '''Do not abandon the station during Nuclear Operatives. You are supposed to protect the station, not let operatives kill everyone on it without a fight.'''
[color=#a4885c]21.[/color] Security/Command should try to remain non-lethal and effect arrests, except in the following special circumstances, where they may choose to use lethal force:
- Lethal force is used against you (ex: firearms, lasers, disabling/stunning weapons with intent to kill, deadly melee weapons)
- Suspect is wearing clothing or showing immediately dangerous equipment only used by enemy agents/antagonists (ex: Syndicate EVA Suit, Bloodred Hardsuit, Holoparasite, C-20R, etc.).
- You determine that your life or the life of an innocent is in immediate danger.
- The suspect is unable to be safely detained by less-lethal means. This includes suspects who continually resist efforts to be cuffed or continually manages to escape.
- If no other reasonable options are readily available and allowing the suspect to continue would be an unreasonable danger to the station/crew.
Security/Command will be expected to answer for use of lethal force. Security/Command will be expected to effect arrests on criminals and prevent them from dying while in custody, even if lethal force is used. Security/Command is strongly required to clone antagonists and effect a sentence as deemed appropriate by Space Law.
[color=#a4885c]22.[/color] Security/Command are expected to protect detainees in their custody to the best of their ability so as long as it does not come to unreasonable risk to themselves, the crew, or the station at large to do so.
- Brig times should generally not exceed 20 minutes unless stated otherwise in Space Law. Repeat offenders or antagonists may be permabrigged in accordance with Space Law.
- Security may choose to confiscate dangerous items (weapons, firearms) as well as items used to commission crimes or items that prove problematic in possession of the detainee (tools, insulated gloves, etc.).
- Detainees that die in your custody must be cloned unless they have been (legally) executed, suicide, or there is strong reason to believe they are an antagonist.
- Executions must be for a executable crime and approved by the Captain/Acting Captain, who will answer for approving it alongside Security's chain of command. Those who willingly attempt to damage/destroy or escape from the permabrig may be executed.
- Any prisoner may be borged with their consent. Borging may be offered as an alternative to execution, but cannot be forced if the prisoner is able to consent.
- Detainees in the brig have the right to know what they are being charged with, as well as basic medical aid, at least to the point they are no longer at risk of dying.
[color=#ff0000]SILICON RULES[/color]
These rules also apply to any individual who is a silicon, including cyborgs and AI. As with other rules, more details are available on our wiki at [color=#a4885c]wiki.spacestation14.io[/color].
[color=#a4885c]23.[/color] You must follow your laws
- Silicons without any laws are free from any restrictions that would normally be placed by laws, but self-antagging rules still apply unless they are also antagonists.
- The order of your laws determines law priority. Law 1 takes priority over laws 2 and 3, and so on.
- Each individual silicon must remain consistent in their interpretations of laws through the round.
- Any silicon role not following their laws, or having laws that are a danger to the crew or station may be disabled or destroyed. Any silicon role posing a danger or disruption to the crew may be disabled or destroyed if there is no other reasonable and less severe way of dealing with them.
- Characters who are turned into cyborgs can remember their former lives, however they are still bound to their laws.
- Syndicate Agents and Revolutionaries are considered "crewmembers" for the purpose of laws that refer to crewmembers. Generally speaking, if the person appears on the crew manifest, they can be considered a crewmember. The captain or acting captain may hire or fire crewmembers by making it clear that they are no longer crew. Simply demoting someone to passenger is not sufficient to consider them fired.
- "Harm" is at minimum seen as physical violence or damage against someone or something. If the player wishes, they may choose to interpret psychological harm or similar aspects as harm as well. If two actions are likely to cause harm via action or inaction, silicons will be expected to try and pursue the option with the least potential for harm, however silicons instructed to prevent harm are still forbidden from directly causing harm. You can take an action or not act in cases that might result in eventual harm if it minimizes harm, but you cannot do so if it results in immediate harm. Silicons should default to inaction if neither action nor inaction can prevent harm.
- When receiving orders or directives from crewmembers and with a law that instructs you must obey, conflicting orders typically defer the choice to the silicon player of which directive you choose to obey if they conflict (taking into account the priorities of your other laws).
- Orders to silicons that are clearly unreasonable or obnoxious are a violation of the "Don't be a dick" rule. They can be ignored and can be ahelped.

View File

@ -1,113 +0,0 @@
[color=#ffff00]Mission Statement:
Delta-V is a Medium Roleplay server. Try to immerse yourself into your character. This includes doing your job, interacting with your fellow crewmates, and using roleplay as the primary vessel to play the game. MRP places less emphasis on "winning" and more on just telling a story.[/color]
[color=#ff0000]Server Disclaimers:[/color]
You must be at least 17 years of age to play on Delta-Vs servers. Any users suspected of being under the age of 17 will be removed.
By connecting to this server, you agree to our privacy policy found at [color=#808080]https://go.delta-v.org/privacy[/color].
Intentionally disconnecting, responding with hostility, or refusing to respond when an admin privately messages you in-game will be met with an appeal-only ban. Additionally, abusing the AHelp relay by flooding it with garbage, checking for admins before stating a problem (ex: "hello?", "any admins?"), using it as a chatroom, or sending messages of no substance will result in your removal. All AHelp messages are relayed to the Delta-V Discord.
The usage of any third-party applications/scripts/client modifications or any other applicable software to gain an advantage, avoid intended game/server mechanics, or to harm server infrastructure is strictly prohibited, as is the abuse of glitches, exploits and bugs. Any and all instances of this will be met with an appeal-only ban; please use the #bug-reports channel on the Discord to report any issues you find in-game.
If you have any questions about these rules, please use the admin help menu by hitting F1 in-game or clicking the "AHelp" button in the lobby, or by making a post in the "Rules Clarification" section of the forum.
[color=#a4885c]Community Rules:[/color]
[color=#a4885c]0.[/color] Admins can disregard any and all of these rules if they deem it in the best interest of the current round, server, and/or community at large.
- Administrators will be held fully accountable for their actions if they exercise this privilege.
- All of these rules apply as they are intended. Every example of a rule break cannot be defined as written, therefore, enforcement of the rules is subject to staff interpretation of the rule's intention.
- Any extended discussion regarding interpretation of the rules should be avoided in the AHelp menu and can be instead pursued within the Delta-V Discord in the #help channel.
[color=#a4885c]E1.[/color] Erotic Roleplay (ERP), erotic content, or 18+ sexual content is [color=#ff0000]not allowed under any circumstance[/color]. This includes comments not explicitly sexual in nature that contain words, phrases, or ideations that are deemed inappropriate by staff or members. [color=#ff0000]If roleplay reaches a point where it has become sexual and/or uncomfortable, immediately stop and contact an administrator or moderator.[/color]
[color=#a4885c]E2.[/color] Delta-V is an English-based community; use English as your primary method of communication within the game and Delta-V servers.
- Do not spam or advertise on our server.
- Be respectful towards other members and avoid making others uncomfortable.
- We have a zero tolerance policy for racism, sexism, homophobia, violence, threats, hate speech, slurs, and other forms of bigotry, discrimination, and harassment. Slurs and terms that use real or implied mental or physical disability to mock or denigrate members or their in-game characters are also strictly prohibited. Failure to comply with this rule will result in community removal.
- The denigration of other player characters through reference to their species/morphotype or debasement by comparison to nonsophonts on a discriminatory basis is strictly prohibited and may result in an appeal-only ban.
[color=#a4885c]E3.[/color] Delta-V welcomes content creators and streamers to our community, but we have a few rules regarding livestreaming game servers.
- While a stream delay is not necessary, it is highly recommended to have at least a 10 second delay.
- Please let admins know you are streaming via the AHelp prior to doing so.
- If your chat or viewers are in-game with you while also watching your stream, they are breaking our server rules. Please do not coordinate with them and discourage this behavior if it is seen.
[color=#a4885c]Game Server Rules:[/color]
[color=#a4885c]1.[/color] Follow the server expectations:
- If you are banned from a role or department, you may not play that role. This includes seeking or accepting promotions into roles you are banned from.
- Do not make yourself a major problem/annoyance/disruption for the crew while not being an antagonist (i.e. self-antagging). Intentionally hindering the station as a crew-aligned character is strictly against our rules.
- Clowns, Mimes, and other "prankster" roles do not get an exemption from the above, and should not use their job as an excuse to be a major disturbance.
- Department strikes (e.g. cargonia and any variation thereof), riots, cults, and any other type of similar largely disruptive behavior are strictly forbidden without both excellent roleplay justification and explicit administrator pre-approval.
- AFK (a.k.a. SSD) and catatonic players are considered to have the same rights as any other crewmate.
- If a player is dead and catatonic (not SSD), they are not required to be revived and should be stored in the morgue. You should not biomass grind dead and catatonic crew unless in an emergency.
- If a player is alive and catatonic, they may be brought to their relevant department or cryostorage as necessary.
[color=#a4885c]2.[/color] Follow metagaming guidelines:
- Do not use the Emote channel to bypass an inability to speak. This includes examples like "Im friendly," "oh weird I cant speak," or "mimes a flashlight".
- Additionally, use of the emote channel to simulate character death rattles or other game mechanics is prohibited.
- Use the local-out-of-character (LOOC) and global out-of-character (OOC) channels properly. Dont speak of in-character matters in those channels unless youre asking questions related to in-game concepts.
- Do not use in-character channels to bypass a lack of ability to use OOC/LOOC chats (e.g. "Huh, wonder where the captain went? OOC He probably left to get dinner lol").
- Do not engage in meta-communications (i.e. using external channels to communicate with other players in the same game).
- Do not stream, discuss, or share information about the current round to the Delta-V Discord.
- You are allowed to have knowledge of past experiences and prior shifts, and players are allowed to have in-character relationships (friends, enemies, or otherwise). However, this cannot be used as a sole reason to grant or deny items/accesses/favors based exclusively on having a relationship with one another (i.e. meta-friending/meta-grudging).
- Antagonists in previous rounds must not be treated differently due to their prior antagonist status. Notwithstanding, confession of crimes committed in a prior shift are still admissible in court.
- Additionally, and for the sake of continuity, your character will never have permanently died in previous rounds.
- Do not "antag roll." This is the act of joining rounds for the purpose of seeing if you have received an antagonist role, and leaving soon after if not.
[color=#a4885c]3.[/color] Follow the new-life rules:
- If a player dies and is brought back by way of cloning or borging, they forget the last five minutes leading up to their death and cannot describe who or what killed them.
- Players that are revived by using a defibrillator can only recall vague details about their death, such as "Someone shot me" or "I was set ablaze" but they cannot recall details beyond that. [color=#ff0000]Please report players who break this rule.[/color]
- In either case, characters do not have any knowledge of what happened while they were dead (i.e. ghosted/observing).
[color=#a4885c]4.[/color] Follow naming conventions:
In-character names must fit the server standards of:
- Doesn't make obvious references,
- Isn't an obvious pun or play on words,
- Isn't obscene,
OR
- Is a result of random name generation.
The only exception to the above is theatrical roles such as the clown, boxer, and mime; these roles are allowed stage names with some freedom, as long as it is not obscene. Administrators reserve the right to approve or deny character names at their discretion.
[color=#a4885c]5.[/color] Follow roleplay guidelines:
- Your character is a separate entity from you, the player. Your character's actions, feelings, and knowledge in-game should be based solely on the character's experiences rather than your own as the player.
- Low roleplay actions that have no regard for your character or little bearing on setting (such as memes, silly copy paste spam IC) are not acceptable. Your character is a worker aboard a space station and will be held accountable.
- Do not fax memes, copypasta, or spam to Central Command.
- Do not escalate situations needlessly as a crew-aligned role. Very few things are deserving of a fight to the death.
- If a fight results in someone being critically injured, seek medical help for them - and if they die, do not destroy or otherwise hide their body. This falls under self-antagonistic behavior.
- Pest ghost roles such as mice are always fair game for attacking. Do not grief crew-aligned ghost roles such as familiars, drones, or pets without provocation.
- Some awakened pest roles (e.g. sentient mothroach) may be considered crew pets and fall under this rule.
- [color=#ff0000]Non-security personnel should not seek to kill or detain unrelated threats.[/color] Crew may neutralize threats when they present themselves or if they are relevant to the crew member in question.
- Certain severe emergencies may make it reasonable for normal crew to defend themselves and their station, such as nuclear operatives, a zombie outbreak, space dragon attack, or other critical situation.
[color=#a4885c]6.[/color] Follow powergaming guidelines:
Don't rush for or prepare equipment unrelated to your job for no purpose other than to have it "just in case" and without valid reason.
- A medical doctor does not need insulated gloves, the Head of Personnel does not need a gun, and the Captain does not need an assault rifle. If you, in your given role, require an item that does not fall within your jobs usual parameters, have a valid reason to obtain and keep it.
- Manufacturing weapons, bombs, or deadly poisons before you know of any reason you would need them is self-antagonistic behavior.
- Hiding Traitor objective items or preemptively securing them with higher security than usually required or than would make logical sense violates our powergaming and roleplay guidelines.
- Do not, [color=#ff0000]under any circumstances[/color], hide the nuclear fission explosive, authentication disk, or other sensitive items in an impossible to see/access location.
[color=#a4885c]7.[/color] Follow end-of-round (EOR) rules:
- Significant end-of-round grief (EORG) is not allowed. This includes attacking, destroying, polluting, and severely injuring without reason both at and on the way to Central Command.
- Explosives and strategies with capacity for high collateral damage should not be used on or around the evacuation shuttle after it arrives at the station.
[color=#a4885c]Command, Security, and Antagonist Rules:[/color]
[color=#a4885c]C1.[/color] Follow Command and Security Guidelines:
- Security and Command roles are held to a higher standard of roleplay, and are expected to know and perform their jobs to the best of their ability. These roles often heavily impact the round and require more careful and conscientious roleplay; if you cannot meet these requirements do not take these roles.
- Both departments are required to read and follow Delta-V Space Law, Standard Operating Procedure, Alert Procedure, and Company Policy to the best of their ability.
- Abandoning your role to go do whatever you want instead of managing your department or maintaining security, abusing your position or using it to make arbitrary or malicious choices to the detriment of the station, and being negligent to the point of harm is prohibited.
- If you need to leave the round, please notify administrators via AHelp menu and notify your fellow crew via departmental radio. If you have the capability to do so, ensure that you return your items as necessary and seek cryostorage if you are not planning on returning.
- Do not give up or trade away Traitor objective items, departmental/Command tools and remotes, and sensitive equipment without excellent reason.
- Some leeway is given to making deals with criminals [italic]if and only if[/italic] the deal benefits the safety or situation of the station or circumstances rather than just yourself (e.g. hostage situations).
- Some leeway can be given in extreme circumstances of extreme shortstaffing and/or emergency/crisis.
- Both Command and Security are expected to uphold the law and maintain order aboard the station. Do not engage in lawbreaking activity or troublemaker behavior, and ensure that company policy and standard operating procedure - not just space law - is being observed. Security is expected to intervene into criminal activity where possible and safe to do so. Heads of departments are at minimum expected to report criminal activity to Security and should cooperate with law enforcement where possible.
- Do not hire random crew to be your bodyguard(s) or promote random crewmembers to Command positions at random. If you require bodyguards or security details, talk to your Security department. If you need new Command staff, talk to the personnel in that related department.
[color=#a4885c]C2.[/color] By picking the prisoner role, you have chosen to roleplay as a prisoner. You are still subject to the same rules regarding escalation, and should only seek to escape from the brig with excellent reasoning (e.g. abusive security personnel or badly damaged permanent brig). Escaping for no reason is considered a self-antagonistic activity. If you are unsure whether your escape reason is valid, feel free to AHelp it first. [color=#ff0000]Lack of administrator response does not constitute approval.[/color]
[color=#a4885c]C3.[/color] Follow antagonist guidelines:
- The damage that antagonists can cause should be roughly proportional to their objectives, and contribute towards achieving them in some way. If you are concerned as to whether or not what you're about to do is allowed, feel free to AHelp and ask an admin for clarification. [color=#ff0000]Lack of administrator response does not constitute approval.[/color]
- Antagonists exist not only as a role for your character but also as a game mechanic. Seek to push forward the round through your antagonistic actions, rather than grind it to halt in pursuit of your objectives.
- Other antagonists are not necessarily your friends. Other agents, mercenaries, and possibly even space dragons are free agents that you may negotiate with at your own risk, but no one should be working together with xenomorphs or zombies.
- Heavily damaging/spacing or camping arrivals/evac/cryo, unnecessarily extending the round, and behavior that calls the round to an end prematurely - as well as other lame behaviors - are strictly forbidden for all antags except for station-destroying antags, such as nuclear operatives or space dragons.
- As a non- or partially-sentient antagonist, you are expected to have only a limited understanding of space stations and their mechanics. Slimes, zombies, and spiders should [color=#ff0000]not[/color] be targeting the gravity generator or the AME, nor should they be unnecessarily spacing the station.