Skip to content
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions Content.Client/Guidebook/Controls/GhostRoleRulesEmbed.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<BoxContainer xmlns="https://spacestation14.io"
Orientation="Vertical"
HorizontalExpand="True">
<Collapsible HorizontalExpand="True">
<CollapsibleHeading Title="{Loc 'ghost-role-rules-embed-header'}"/>
<CollapsibleBody>
<BoxContainer Orientation="Vertical" HorizontalExpand="True" Margin="5 2 5 5">
<Label Text="{Loc 'ghost-role-rules-embed-allowed-header'}" HorizontalExpand="True"/>
<RichTextLabel Name="AllowedContent" HorizontalExpand="True" Margin="5 0 0 5"/>
<Label Text="{Loc 'ghost-role-rules-embed-not-allowed-header'}" HorizontalExpand="True"/>
<RichTextLabel Name="NotAllowedContent" HorizontalExpand="True" Margin="5 0 0 0"/>
</BoxContainer>
</CollapsibleBody>
</Collapsible>
</BoxContainer>
38 changes: 38 additions & 0 deletions Content.Client/Guidebook/Controls/GhostRoleRulesEmbed.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using System.Diagnostics.CodeAnalysis;
using Content.Client.Guidebook.Richtext;
using Content.Client.Message;
using JetBrains.Annotations;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Localization;

namespace Content.Client.Guidebook.Controls;

/// <summary>
/// Embed for displaying a collapsible "Specific Rules" section in ghost role guidebook entries.
/// Usage: &lt;GhostRoleRulesEmbed Id="free-agent-skeletons"/&gt;
/// </summary>
[UsedImplicitly, GenerateTypedNameReferences]
public sealed partial class GhostRoleRulesEmbed : BoxContainer, IDocumentTag
{
public GhostRoleRulesEmbed()
{
RobustXamlLoader.Load(this);
}

public bool TryParseTag(Dictionary<string, string> args, [NotNullWhen(true)] out Control? control)
{
control = null;

if (!args.TryGetValue("Id", out var id))
return false;

AllowedContent.SetMarkupPermissive(Loc.GetString($"ghost-role-rules-{id}-allowed"));
NotAllowedContent.SetMarkupPermissive(Loc.GetString($"ghost-role-rules-{id}-not-allowed"));

control = this;
return true;
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
<DefaultWindow xmlns="https://spacestation14.io"
Title="{Loc 'ghost-roles-window-title'}"
MinSize="500 300"
SetSize="500 300">
MinSize="600 500"
SetSize="600 500">
<BoxContainer Orientation="Vertical"
HorizontalExpand="True">
<RichTextLabel Name="TopBanner" VerticalExpand="True"/>
HorizontalExpand="True"
VerticalExpand="True">
<ScrollContainer HScrollEnabled="False"
HorizontalExpand="True"
VerticalExpand="True">
<BoxContainer Name="ContentBox"
Orientation="Vertical"
HorizontalExpand="True"
Margin="4 4"/>
</ScrollContainer>
<Button Name="RequestButton"
Text="{Loc 'ghost-roles-window-request-role-button'}"
Disabled="True"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
using Content.Client.Guidebook;
using Content.Shared.CCVar;
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.Configuration;
using Robust.Shared.Prototypes;
using Robust.Shared.Timing;
using Robust.Shared.Utility;

Expand All @@ -13,25 +16,49 @@ namespace Content.Client.UserInterface.Systems.Ghost.Controls.Roles
public sealed partial class GhostRoleRulesWindow : DefaultWindow
{
[Dependency] private readonly IConfigurationManager _cfg = IoCManager.Resolve<IConfigurationManager>();
[Dependency] private readonly DocumentParsingManager _docParsing = IoCManager.Resolve<DocumentParsingManager>();
private float _timer;

public GhostRoleRulesWindow(string rules, Action<BaseButton.ButtonEventArgs> requestAction)
public GhostRoleRulesWindow(string rules, ProtoId<GuideEntryPrototype>? guideEntry, Action<BaseButton.ButtonEventArgs> requestAction)
{
RobustXamlLoader.Load(this);
var ghostRoleTime = _cfg.GetCVar(CCVars.GhostRoleTime);
_timer = ghostRoleTime;

var usedGuide = false;

if (guideEntry != null)
{
usedGuide = _docParsing.TryAddMarkup(ContentBox, guideEntry.Value);
if (!usedGuide)
ContentBox.RemoveAllChildren();
}

if (!usedGuide)
{
var fallback = new RichTextLabel { HorizontalExpand = true };
var text = ghostRoleTime > 0f
? rules + "\n" + Loc.GetString("ghost-roles-window-rules-footer", ("time", ghostRoleTime))
: rules;
fallback.SetMessage(FormattedMessage.FromMarkupPermissive(text));
ContentBox.AddChild(fallback);
}
else if (ghostRoleTime > 0f)
{
var footer = new RichTextLabel { HorizontalExpand = true };
footer.SetMessage(FormattedMessage.FromMarkupPermissive(
Loc.GetString("ghost-roles-window-rules-footer", ("time", ghostRoleTime))));
ContentBox.AddChild(footer);
}

if (ghostRoleTime > 0f)
{
RequestButton.Text = Loc.GetString("ghost-roles-window-request-role-button-timer", ("time", $"{_timer:0.0}"));
TopBanner.SetMessage(FormattedMessage.FromMarkupPermissive(rules + "\n" + Loc.GetString("ghost-roles-window-rules-footer", ("time", ghostRoleTime))));
RequestButton.Disabled = true;
}

RequestButton.OnPressed += requestAction;
}


protected override void FrameUpdate(FrameEventArgs args)
{
base.FrameUpdate(args);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public GhostRolesEui()
return;
}

_windowRules = new GhostRoleRulesWindow(info.Rules, _ =>
_windowRules = new GhostRoleRulesWindow(info.Rules, info.GuideEntry, _ =>
{
SendMessage(new RequestGhostRoleMessage(info.Identifier));

Expand Down
7 changes: 7 additions & 0 deletions Content.Server/Ghost/Roles/Components/GhostRoleComponent.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Content.Server.Ghost.Roles.Raffles;
using Content.Server.Mind.Commands;
using Content.Shared.Guidebook;
using Content.Shared.Roles;
using Robust.Shared.Prototypes;

Expand Down Expand Up @@ -104,5 +105,11 @@ public string RoleRules
[DataField("job")]
[Access(typeof(GhostRoleSystem), Other = AccessPermissions.ReadWriteExecute)] // also FIXME Friends
public ProtoId<JobPrototype>? JobProto = null;

/// <summary>
/// If set, the ghost role rules window will render this guidebook entry inline instead of showing the raw rules text.
/// </summary>
[DataField]
public ProtoId<GuideEntryPrototype>? GuideEntry;
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using Content.Shared.Guidebook;
using Robust.Shared.GameObjects;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.Manager.Attributes;

namespace Content.Server.Ghost.Roles.Components;

/// <summary>
/// Added by conversion antagonist systems (zombies, etc.) to override the guidebook entry
/// shown in the ghost role popup, taking priority over <see cref="GhostRoleComponent.GuideEntry"/>.
/// Remove this component to restore the original guide entry. Future proofed for new conversion style antags.
/// </summary>
[RegisterComponent]
public sealed partial class GhostRoleConversionComponent : Component
{
[DataField]
public ProtoId<GuideEntryPrototype>? GuideEntry;
}
2 changes: 2 additions & 0 deletions Content.Server/Ghost/Roles/GhostRoleSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -673,6 +673,8 @@ public GhostRoleInfo[] GetGhostRolesInfo(ICommonSession? player)
Name = role.RoleName,
Description = role.RoleDescription,
Rules = role.RoleRules,
// Check if the ghost role has been converted - we need to show a different guidebook entry if so.
GuideEntry = CompOrNull<GhostRoleConversionComponent>(uid)?.GuideEntry ?? role.GuideEntry,
RolePrototypes = (jobs, antags),
Kind = kind,
RafflePlayerCount = rafflePlayerCount,
Expand Down
2 changes: 2 additions & 0 deletions Content.Server/Zombies/ZombieSystem.Transform.cs
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,8 @@ public void ZombifyEntity(EntityUid target, MobStateComponent? mobState = null)
//yet more hardcoding. Visit zombie.ftl for more information.
var ghostRole = EnsureComp<GhostRoleComponent>(target);
EnsureComp<GhostTakeoverAvailableComponent>(target);
// Override the ghost role information if the mob has been zombified
EnsureComp<GhostRoleConversionComponent>(target).GuideEntry = "Zombies";
ghostRole.RoleName = Loc.GetString("zombie-generic");
ghostRole.RoleDescription = Loc.GetString("zombie-role-desc");
ghostRole.RoleRules = Loc.GetString("zombie-role-rules");
Expand Down
6 changes: 6 additions & 0 deletions Content.Shared/Ghost/Roles/GhostRolesEuiMessages.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Content.Shared.Eui;
using Content.Shared.Guidebook;
using Content.Shared.Roles;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
Expand All @@ -18,6 +19,11 @@ public struct GhostRoleInfo
/// </summary>
public (List<ProtoId<JobPrototype>>?,List<ProtoId<AntagPrototype>>?) RolePrototypes;

/// <summary>
/// If set, the ghost role rules window renders this guidebook entry inline instead of the raw rules text.
/// </summary>
public ProtoId<GuideEntryPrototype>? GuideEntry { get; set; }

/// <inheritdoc cref="GhostRoleKind"/>
public GhostRoleKind Kind { get; set; }

Expand Down
2 changes: 1 addition & 1 deletion Resources/ConfigPresets/Build/development.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ role_loadout_timers = false
enabled = false

[ghost]
role_time = 0.5
role_time = 2
quick_lottery = true

[gateway]
Expand Down
64 changes: 64 additions & 0 deletions Resources/Locale/en-US/guidebook/ghost-roles/antagonists.ftl
Comment thread
JustinWinningham marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# Traitors
ghost-role-rules-traitors-allowed =
Comment thread
JustinWinningham marked this conversation as resolved.
- Team up with Nukies (they can still shoot you)
ghost-role-rules-traitors-not-allowed =
- Doing a prisoner exchange with a corpse that you are not allowed to RR (they tend to rot before being saved)
Comment thread
JustinWinningham marked this conversation as resolved.
Outdated

# Nuclear Operatives
ghost-role-rules-nuclear-operatives-allowed =
- Everything
ghost-role-rules-nuclear-operatives-not-allowed =
- N/A
Comment thread
JustinWinningham marked this conversation as resolved.

# Zombies
ghost-role-rules-zombies-allowed =
- Attack Borgs (They have brains/cyberbrains inside them)
- Show basic intelligence (take cover from gunfire, feign death, go prone, etc)
- Point at things as a method of communication
ghost-role-rules-zombies-not-allowed =
- Attack power sources
- Try to Loose
- Attack atmos

# Revolutionaries
ghost-role-rules-revolutionaries-allowed =
- Convert command / sec (instead of killing or gibbing)
- Order your minions to suicide bomb somewhere to progress your objectives
Comment thread
JustinWinningham marked this conversation as resolved.
Outdated
- Sacrifice a minion to keep your cover
- Team up with lesser threats (Xenoborgs, Ninja)
ghost-role-rules-revolutionaries-not-allowed =
- Order your minions to round remove themselves for no reason
- Loose, or order a loose
- Trit / Plasma flood without directive from Headrev
Comment thread
JustinWinningham marked this conversation as resolved.
- Team up with station destroying threats (Nukies, Dragon)

# Space Ninja
ghost-role-rules-space-ninja-allowed =
- Teaming with other threats
ghost-role-rules-space-ninja-not-allowed =
- Same limitations as traitor without DAGD

# Wizard
ghost-role-rules-wizard-allowed =
- Everything
ghost-role-rules-wizard-not-allowed =
- N/A

# Xenoborgs
ghost-role-rules-xenoborgs-allowed =
- Use cyberbrains instead of crew brains
ghost-role-rules-xenoborgs-not-allowed =
- Loose

# Space Dragon
ghost-role-rules-space-dragon-allowed =
- Teaming with other threats
ghost-role-rules-space-dragon-not-allowed =
- Loosing
- (As Fish) Attacking power sources without directive from Dragon

# Thieves
ghost-role-rules-thieves-allowed =
- Killing people (if you can figure out how)
ghost-role-rules-thieves-not-allowed =
- Same limitations as traitor without DAGD
7 changes: 7 additions & 0 deletions Resources/Locale/en-US/guidebook/ghost-roles/centcom.ftl
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Emergency Response Team
ghost-role-rules-centcom-allowed =
- Disobey or ignore orders from the Captain or other members of command
ghost-role-rules-centcom-not-allowed =
- Kill people outside your given objectives
- Gib anybody without direct instructions
- Station or power sabotage
63 changes: 63 additions & 0 deletions Resources/Locale/en-US/guidebook/ghost-roles/free-agents.ftl
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Shared embed UI strings
ghost-role-rules-embed-header = Role Specific Rule Interactions
ghost-role-rules-embed-allowed-header = Allowed
ghost-role-rules-embed-not-allowed-header = Not Allowed

# Skeletons
ghost-role-rules-free-agent-skeletons-allowed =
- Killing people who look at you funny
Comment thread
JustinWinningham marked this conversation as resolved.
Outdated
- Teaming with traitors, nukies, Dragon, etc.
ghost-role-rules-free-agent-skeletons-not-allowed =
- Round removing crew
Comment thread
JustinWinningham marked this conversation as resolved.
Outdated
- Sabotauging power sources (Loose, TEG, AME)
- Plasma/Trit flooding

# Mice
ghost-role-rules-free-agent-mice-allowed =
- Eat anything and everything not locked in a secure container
- Drinking drugs in chem
- Become a pet
- Taunt crew
ghost-role-rules-free-agent-mice-not-allowed =
- Miming to crew that you found something in maints (or similar)

# Mothroach
ghost-role-rules-free-agent-mothroach-allowed =
- Eat anything made of cloth
- Become a pet
- Taunt crew
ghost-role-rules-free-agent-mothroach-not-allowed =
- Miming to crew that you found something in maints (or similar)

# Snails
ghost-role-rules-free-agent-snails-allowed =
- Eat anything
- Become a pet
Comment thread
JustinWinningham marked this conversation as resolved.
ghost-role-rules-free-agent-snails-not-allowed =
- Miming to crew that you found something in maints (or similar)

# Bots
ghost-role-rules-free-agent-bots-allowed =
- Slip any one for any reason at any time
ghost-role-rules-free-agent-bots-not-allowed =
- N/A

# Visitors
ghost-role-rules-free-agent-visitors-allowed =
- Get hired (Visitors are not crew by default)
- Go adventuring in your ship
ghost-role-rules-free-agent-visitors-not-allowed =
- Act like a nukie or traitor

# Sentient Artifact
ghost-role-rules-free-agent-artifact-allowed =
- Kill or round remove crew with your powers
ghost-role-rules-free-agent-artifact-not-allowed =
- N/A

# Station Pets
ghost-role-rules-pets-allowed =
- N/A
Comment thread
JustinWinningham marked this conversation as resolved.
Outdated
- Attack crew in self defense or if threatened
ghost-role-rules-pets-not-allowed =
- Act like a free agent
24 changes: 24 additions & 0 deletions Resources/Locale/en-US/guidebook/ghost-roles/minorantagonists.ftl
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Paradox Clone
ghost-role-rules-paradox-clone-allowed =
- Act like a traitor without DAGD
ghost-role-rules-paradox-clone-not-allowed =
- Take up your clones objectives if they are a traitor
Comment thread
JustinWinningham marked this conversation as resolved.

# Revenant
ghost-role-rules-revenant-allowed =
- Spacing station/evac with your powers
ghost-role-rules-revenant-not-allowed =
- N/A

# Rat King
ghost-role-rules-rat-king-allowed =
- Making a deal with crew to aide them in exchange for food
ghost-role-rules-rat-king-not-allowed =
- Become a pet

# Slimes and Spiders
ghost-role-rules-angry-mobs-allowed =
- Pointing or gesturing to communicate with other Mobs
ghost-role-rules-angry-mobs-not-allowed =
- Pointing or gesturing to communicate with crew
- Become a pet
Loading
Loading