Flavor text (#8070)

This commit is contained in:
Veritius
2022-05-14 08:58:45 +10:00
committed by GitHub
parent 83da49e1be
commit 3b7e202044
23 changed files with 2705 additions and 14 deletions

View File

@@ -0,0 +1,5 @@
<Control Name="CFlavorText" xmlns="https://spacestation14.io">
<BoxContainer Orientation="Vertical" HorizontalExpand="True">
<LineEdit Name="CFlavorTextInput" Access="Public" MinSize="220 0" HorizontalExpand="True" />
</BoxContainer>
</Control>

View File

@@ -0,0 +1,25 @@
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.XAML;
namespace Content.Client.FlavorText
{
[GenerateTypedNameReferences]
public sealed partial class FlavorText : Control
{
public Action<string>? OnFlavorTextChanged;
public FlavorText()
{
RobustXamlLoader.Load(this);
IoCManager.InjectDependencies(this);
CFlavorTextInput.OnTextChanged += _ => FlavorTextChanged();
}
public void FlavorTextChanged()
{
OnFlavorTextChanged?.Invoke(CFlavorTextInput.Text);
}
}
}

View File

@@ -18,6 +18,7 @@ using Robust.Client.Player;
using Robust.Client.ResourceManagement;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Shared.Configuration;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
@@ -42,6 +43,7 @@ namespace Content.Client.Lobby
[Dependency] private readonly IClientPreferencesManager _preferencesManager = default!;
[Dependency] private readonly IGameTiming _gameTiming = default!;
[Dependency] private readonly IVoteManager _voteManager = default!;
[Dependency] private readonly IConfigurationManager _configurationManager = default!;
[ViewVariables] private CharacterSetupGui? _characterSetup;
[ViewVariables] private LobbyGui? _lobby;
@@ -52,7 +54,7 @@ namespace Content.Client.Lobby
{
_gameTicker = EntitySystem.Get<ClientGameTicker>();
_characterSetup = new CharacterSetupGui(_entityManager, _resourceCache, _preferencesManager,
_prototypeManager);
_prototypeManager, _configurationManager);
LayoutContainer.SetAnchorPreset(_characterSetup, LayoutContainer.LayoutPreset.Wide);
_lobby = new LobbyGui(_entityManager, _preferencesManager);

View File

@@ -13,6 +13,7 @@ using Robust.Client.ResourceManagement;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Configuration;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
@@ -29,6 +30,7 @@ namespace Content.Client.Preferences.UI
private readonly IClientPreferencesManager _preferencesManager;
private readonly IEntityManager _entityManager;
private readonly IPrototypeManager _prototypeManager;
private readonly IConfigurationManager _configurationManager;
private readonly Button _createNewCharacterButton;
private readonly HumanoidProfileEditor _humanoidProfileEditor;
@@ -36,12 +38,14 @@ namespace Content.Client.Preferences.UI
IEntityManager entityManager,
IResourceCache resourceCache,
IClientPreferencesManager preferencesManager,
IPrototypeManager prototypeManager)
IPrototypeManager prototypeManager,
IConfigurationManager configurationManager)
{
RobustXamlLoader.Load(this);
_entityManager = entityManager;
_prototypeManager = prototypeManager;
_preferencesManager = preferencesManager;
_configurationManager = configurationManager;
var panelTex = resourceCache.GetTexture("/Textures/Interface/Nano/button.svg.96dpi.png");
var back = new StyleBoxTexture
@@ -64,7 +68,7 @@ namespace Content.Client.Preferences.UI
args.Event.Handle();
};
_humanoidProfileEditor = new HumanoidProfileEditor(preferencesManager, prototypeManager, entityManager);
_humanoidProfileEditor = new HumanoidProfileEditor(preferencesManager, prototypeManager, entityManager, configurationManager);
_humanoidProfileEditor.OnProfileChanged += ProfileChanged;
CharEditor.AddChild(_humanoidProfileEditor);

View File

@@ -2,7 +2,8 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:magicmirror="clr-namespace:Content.Client.CharacterAppearance"
xmlns:prefUi="clr-namespace:Content.Client.Preferences.UI"
xmlns:markings="clr-namespace:Content.Client.Markings">
xmlns:markings="clr-namespace:Content.Client.Markings"
xmlns:flavorText="clr-namespace:Content.Client.FlavorText">
<BoxContainer Orientation="Horizontal">
<!-- Left side -->
<BoxContainer Orientation="Vertical" Margin="10 10 10 10">

View File

@@ -5,6 +5,7 @@ using Content.Client.CharacterAppearance;
using Content.Client.Lobby.UI;
using Content.Client.Message;
using Content.Client.Stylesheets;
using Content.Shared.CCVar;
using Content.Shared.CharacterAppearance;
using Content.Shared.CharacterAppearance.Systems;
using Content.Shared.GameTicking;
@@ -19,6 +20,7 @@ using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using Robust.Client.Utility;
using Robust.Shared.Configuration;
using Robust.Shared.Enums;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
@@ -52,13 +54,16 @@ namespace Content.Client.Preferences.UI
[GenerateTypedNameReferences]
public sealed partial class HumanoidProfileEditor : Control
{
private readonly IClientPreferencesManager _preferencesManager;
private readonly IEntityManager _entMan;
private readonly IConfigurationManager _configurationManager;
private LineEdit _ageEdit => CAgeEdit;
private LineEdit _nameEdit => CNameEdit;
private LineEdit _flavorTextEdit = null!;
private Button _nameRandomButton => CNameRandomize;
private Button _randomizeEverythingButton => CRandomizeEverything;
private RichTextLabel _warningLabel => CWarningLabel;
private readonly IClientPreferencesManager _preferencesManager;
private readonly IEntityManager _entMan;
private Button _saveButton => CSaveButton;
private Button _sexFemaleButton => CSexFemale;
private Button _sexMaleButton => CSexMale;
@@ -104,13 +109,14 @@ namespace Content.Client.Preferences.UI
public event Action<HumanoidCharacterProfile, int>? OnProfileChanged;
public HumanoidProfileEditor(IClientPreferencesManager preferencesManager, IPrototypeManager prototypeManager,
IEntityManager entityManager)
IEntityManager entityManager, IConfigurationManager configurationManager)
{
RobustXamlLoader.Load(this);
_random = IoCManager.Resolve<IRobustRandom>();
_prototypeManager = prototypeManager;
_entMan = entityManager;
_preferencesManager = preferencesManager;
_configurationManager = configurationManager;
#region Left
@@ -458,6 +464,20 @@ namespace Content.Client.Preferences.UI
#endregion Markings
#region FlavorText
if (_configurationManager.GetCVar(CCVars.FlavorText))
{
var flavorText = new FlavorText.FlavorText();
_tabContainer.AddChild(flavorText);
_tabContainer.SetTabTitle(_tabContainer.ChildCount-1, Loc.GetString("humanoid-profile-editor-flavortext-tab"));
_flavorTextEdit = flavorText.CFlavorTextInput;
flavorText.OnFlavorTextChanged += OnFlavorTextChange;
}
#endregion FlavorText
#endregion Left
if (preferencesManager.ServerDataLoaded)
@@ -471,6 +491,15 @@ namespace Content.Client.Preferences.UI
IsDirty = false;
}
private void OnFlavorTextChange(string content)
{
if (Profile is null)
return;
Profile = Profile.WithFlavorText(content);
IsDirty = true;
}
private void OnMarkingChange(MarkingsSet markings)
{
if (Profile is null)
@@ -561,7 +590,7 @@ namespace Content.Client.Preferences.UI
}
IsDirty = true;
NeedsDummyRebuild = true; // ugh - fix this asap
NeedsDummyRebuild = true; // TODO: ugh - fix this asap
}
protected override void Dispose(bool disposing)
@@ -716,6 +745,14 @@ namespace Content.Client.Preferences.UI
_nameEdit.Text = Profile?.Name ?? "";
}
private void UpdateFlavorTextEdit()
{
if(_flavorTextEdit != null)
{
_flavorTextEdit.Text = Profile?.FlavorText ?? "";
}
}
private void UpdateAgeEdit()
{
_ageEdit.Text = Profile?.Age.ToString() ?? "";
@@ -893,6 +930,7 @@ namespace Content.Client.Preferences.UI
{
if (Profile is null) return;
UpdateNameEdit();
UpdateFlavorTextEdit();
UpdateSexControls();
UpdateGenderControls();
UpdateSkinColor();

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,26 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Content.Server.Database.Migrations.Postgres
{
public partial class FlavorText : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "flavor_text",
table: "profile",
type: "text",
nullable: false,
defaultValue: "");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "flavor_text",
table: "profile");
}
}
}

View File

@@ -580,6 +580,11 @@ namespace Content.Server.Database.Migrations.Postgres
.HasColumnType("text")
.HasColumnName("facial_hair_name");
b.Property<string>("FlavorText")
.IsRequired()
.HasColumnType("text")
.HasColumnName("flavor_text");
b.Property<string>("Gender")
.IsRequired()
.HasColumnType("text")

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,26 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Content.Server.Database.Migrations.Sqlite
{
public partial class FlavorText : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "flavor_text",
table: "profile",
type: "TEXT",
nullable: false,
defaultValue: "");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "flavor_text",
table: "profile");
}
}
}

View File

@@ -539,6 +539,11 @@ namespace Content.Server.Database.Migrations.Sqlite
.HasColumnType("TEXT")
.HasColumnName("facial_hair_name");
b.Property<string>("FlavorText")
.IsRequired()
.HasColumnType("TEXT")
.HasColumnName("flavor_text");
b.Property<string>("Gender")
.IsRequired()
.HasColumnType("TEXT")

View File

@@ -197,6 +197,7 @@ namespace Content.Server.Database
public int Id { get; set; }
public int Slot { get; set; }
[Column("char_name")] public string CharacterName { get; set; } = null!;
public string FlavorText { get; set; } = null!;
public int Age { get; set; }
public string Sex { get; set; } = null!;
public string Gender { get; set; } = null!;

View File

@@ -192,6 +192,7 @@ namespace Content.Server.Database
return new HumanoidCharacterProfile(
profile.CharacterName,
profile.FlavorText,
profile.Species,
profile.Age,
sex,
@@ -227,6 +228,7 @@ namespace Content.Server.Database
var entity = new Profile
{
CharacterName = humanoid.Name,
FlavorText = humanoid.FlavorText,
Species = humanoid.Species,
Age = humanoid.Age,
Sex = humanoid.Sex.ToString(),

View File

@@ -0,0 +1,9 @@
namespace Content.Server.DetailExaminable
{
[RegisterComponent]
public sealed class DetailExaminableComponent : Component
{
[DataField("content", required: true)] [ViewVariables(VVAccess.ReadWrite)]
public string Content = "";
}
}

View File

@@ -0,0 +1,41 @@
using Content.Shared.Examine;
using Content.Shared.Verbs;
using Robust.Shared.Utility;
namespace Content.Server.DetailExaminable
{
public sealed class DetailExaminableSystem : EntitySystem
{
[Dependency] private readonly ExamineSystemShared _examineSystem = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<DetailExaminableComponent, GetVerbsEvent<ExamineVerb>>(OnGetExamineVerbs);
}
private void OnGetExamineVerbs(EntityUid uid, DetailExaminableComponent component, GetVerbsEvent<ExamineVerb> args)
{
// TODO: Hide if identity isn't visible (when identity is merged)
var detailsRange = _examineSystem.IsInDetailsRange(args.User, uid);
var verb = new ExamineVerb()
{
Act = () =>
{
var markup = new FormattedMessage();
markup.AddMarkup(component.Content);
_examineSystem.SendExamineTooltip(args.User, uid, markup, false, false);
},
Text = Loc.GetString("detail-examinable-verb-text"),
Category = VerbCategory.Examine,
Disabled = !detailsRange,
Message = Loc.GetString("detail-examinable-verb-disabled"),
IconTexture = "/Textures/Interface/VerbIcons/examine.svg.192dpi.png"
};
args.Verbs.Add(verb);
}
}
}

View File

@@ -1,17 +1,20 @@
using Content.Server.Access.Systems;
using Content.Server.Access.Systems;
using Content.Server.CharacterAppearance.Systems;
using Content.Server.DetailExaminable;
using Content.Server.Hands.Components;
using Content.Server.Hands.Systems;
using Content.Server.PDA;
using Content.Server.Roles;
using Content.Server.Station.Components;
using Content.Shared.Access.Components;
using Content.Shared.CCVar;
using Content.Shared.Inventory;
using Content.Shared.PDA;
using Content.Shared.Preferences;
using Content.Shared.Roles;
using Content.Shared.Species;
using JetBrains.Annotations;
using Robust.Shared.Configuration;
using Robust.Shared.Map;
using Robust.Shared.Prototypes;
using Robust.Shared.Utility;
@@ -26,6 +29,7 @@ namespace Content.Server.Station.Systems;
public sealed class StationSpawningSystem : EntitySystem
{
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IConfigurationManager _configurationManager = default!;
[Dependency] private readonly HandsSystem _handsSystem = default!;
[Dependency] private readonly HumanoidAppearanceSystem _humanoidAppearanceSystem = default!;
[Dependency] private readonly IdCardSystem _cardSystem = default!;
@@ -97,6 +101,10 @@ public sealed class StationSpawningSystem : EntitySystem
{
_humanoidAppearanceSystem.UpdateFromProfile(entity, profile);
EntityManager.GetComponent<MetaDataComponent>(entity).EntityName = profile.Name;
if (profile.FlavorText != "" && _configurationManager.GetCVar(CCVars.FlavorText))
{
EntityManager.AddComponent<DetailExaminableComponent>(entity).Content = profile.FlavorText;
}
}
foreach (var jobSpecial in job?.Prototype.Special ?? Array.Empty<JobSpecial>())

View File

@@ -840,6 +840,12 @@ namespace Content.Shared.CCVar
public static readonly CVarDef<bool> RestrictedNames =
CVarDef.Create("ic.restricted_names", true, CVar.SERVER | CVar.REPLICATED);
/// <summary>
/// Allows flavor text (character descriptions)
/// </summary>
public static readonly CVarDef<bool> FlavorText =
CVarDef.Create("ic.flavor_text", false, CVar.SERVER | CVar.REPLICATED);
/*
* Salvage
*/

View File

@@ -11,6 +11,7 @@ using Robust.Shared.Enums;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
using Robust.Shared.Serialization;
using Robust.Shared.Utility;
namespace Content.Shared.Preferences
{
@@ -23,12 +24,14 @@ namespace Content.Shared.Preferences
public const int MinimumAge = 18;
public const int MaximumAge = 120;
public const int MaxNameLength = 32;
public const int MaxDescLength = 512;
private readonly Dictionary<string, JobPriority> _jobPriorities;
private readonly List<string> _antagPreferences;
private HumanoidCharacterProfile(
string name,
string flavortext,
string species,
int age,
Sex sex,
@@ -41,6 +44,7 @@ namespace Content.Shared.Preferences
List<string> antagPreferences)
{
Name = name;
FlavorText = flavortext;
Species = species;
Age = age;
Sex = sex;
@@ -58,7 +62,7 @@ namespace Content.Shared.Preferences
HumanoidCharacterProfile other,
Dictionary<string, JobPriority> jobPriorities,
List<string> antagPreferences)
: this(other.Name, other.Species, other.Age, other.Sex, other.Gender, other.Appearance, other.Clothing, other.Backpack,
: this(other.Name, other.FlavorText, other.Species, other.Age, other.Sex, other.Gender, other.Appearance, other.Clothing, other.Backpack,
jobPriorities, other.PreferenceUnavailable, antagPreferences)
{
}
@@ -71,6 +75,7 @@ namespace Content.Shared.Preferences
public HumanoidCharacterProfile(
string name,
string flavortext,
string species,
int age,
Sex sex,
@@ -81,7 +86,7 @@ namespace Content.Shared.Preferences
IReadOnlyDictionary<string, JobPriority> jobPriorities,
PreferenceUnavailableMode preferenceUnavailable,
IReadOnlyList<string> antagPreferences)
: this(name, species, age, sex, gender, appearance, clothing, backpack, new Dictionary<string, JobPriority>(jobPriorities),
: this(name, flavortext, species, age, sex, gender, appearance, clothing, backpack, new Dictionary<string, JobPriority>(jobPriorities),
preferenceUnavailable, new List<string>(antagPreferences))
{
}
@@ -90,6 +95,7 @@ namespace Content.Shared.Preferences
{
return new(
"John Doe",
"",
SpeciesManager.DefaultSpecies,
MinimumAge,
Sex.Male,
@@ -118,7 +124,7 @@ namespace Content.Shared.Preferences
var name = sex.GetName(species, prototypeManager, random);
var age = random.Next(MinimumAge, MaximumAge);
return new HumanoidCharacterProfile(name, species, age, sex, gender, HumanoidCharacterAppearance.Random(sex), ClothingPreference.Jumpsuit, BackpackPreference.Backpack,
return new HumanoidCharacterProfile(name, "", species, age, sex, gender, HumanoidCharacterAppearance.Random(sex), ClothingPreference.Jumpsuit, BackpackPreference.Backpack,
new Dictionary<string, JobPriority>
{
{SharedGameTicker.FallbackOverflowJob, JobPriority.High}
@@ -126,6 +132,7 @@ namespace Content.Shared.Preferences
}
public string Name { get; private set; }
public string FlavorText { get; private set; }
public string Species { get; private set; }
public int Age { get; private set; }
public Sex Sex { get; private set; }
@@ -143,6 +150,11 @@ namespace Content.Shared.Preferences
return new(this) { Name = name };
}
public HumanoidCharacterProfile WithFlavorText(string flavorText)
{
return new(this) { FlavorText = flavorText };
}
public HumanoidCharacterProfile WithAge(int age)
{
return new(this) { Age = age };
@@ -295,6 +307,16 @@ namespace Content.Shared.Preferences
name = Sex.GetName(Species);
}
string flavortext;
if (FlavorText.Length > MaxDescLength)
{
flavortext = FormattedMessage.RemoveMarkup(FlavorText)[..MaxDescLength];
}
else
{
flavortext = FormattedMessage.RemoveMarkup(FlavorText);
}
var appearance = HumanoidCharacterAppearance.EnsureValid(Appearance, Species);
var prefsUnavailableMode = PreferenceUnavailable switch
@@ -336,6 +358,7 @@ namespace Content.Shared.Preferences
.ToList();
Name = name;
FlavorText = flavortext;
Age = age;
Sex = sex;
Gender = gender;

View File

@@ -43,6 +43,7 @@ namespace Content.Tests.Server.Preferences
{
return new(
"Charlie Charlieson",
"The biggest boy around.",
"Human",
21,
Sex.Male,

View File

@@ -0,0 +1,2 @@
detail-examinable-verb-text = Detail
detail-examinable-verb-disabled = View the object in greater detail.

View File

@@ -34,5 +34,6 @@ humanoid-profile-editor-job-priority-high-button = High
humanoid-profile-editor-job-priority-medium-button = Medium
humanoid-profile-editor-job-priority-low-button = Low
humanoid-profile-editor-job-priority-never-button = Never
humanoid-profile-editor-naming-rules-warning = Warning: Offensive or LRP IC names will lead to admin intervention on this server. Read our \[Rules\] for more.
humanoid-profile-editor-naming-rules-warning = Warning: Offensive or LRP IC names and descriptions will lead to admin intervention on this server. Read our \[Rules\] for more.
humanoid-profile-editor-markings-tab = Markings
humanoid-profile-editor-flavortext-tab = Description

View File

@@ -23,7 +23,7 @@
- Intentionally seeking to demean others due to their actual or perceived race, sex, gender, orientation or the like is not tolerated.
- Words that are closely tied to real life slurs are [color=#ff0000]not allowed[/color].
[color=#a4885c]8.[/color] Offensive/bad/out-of-character character names put you at the mercy of administrators, from receiving brain damage to becoming valid to straight up getting banned on the spot depending on how bad they are. Character names should be something a real person might have for a name.
[color=#a4885c]8.[/color] Offensive/bad/out-of-character character names and descriptions put you at the mercy of administrators, from receiving brain damage to becoming valid to straight up getting banned on the spot depending on how bad they are. Character names should be something a real person might have for a name.
[color=#a4885c]9.[/color] Knowingly using exploits, external programs, or other unintended game mechanics to powergame, slow down, or crash the server is [color=#ff0000]not allowed[/color].