mirror of
https://github.com/WWhiteDreamProject/wwdpublic.git
synced 2026-04-18 05:59:03 +03:00
# Description Adds two negative traits, foreigner and its light version. Both of them make you unable to speak galactic common and give you a translator that lets you speak/understand GC, and also requires you to know one of the non-GC languages your entity normally speaks in order to work. The translator starts with a high-capacity power cell to compensate for the usual scarcity of publicly accessible chargers on most stations. The light version of the trait only makes you unable to speak GC. The heavy version also makes you unable to understand others when they speak it. This PR also makes you able to wear translator in the neck slot for convenience and transparency, and rewamps the examination menu of translators to provide more useful info. One little known issue (as seen in the screenshots below) is that, since the system chooses the first language in the list of languages your entity can speak, it can sometimes pick wrong if your species speaks more than two language, but it won't prevent you from using the translator normally. Also, the name of the light version of the trait is subject to change. I just couldn't think of anything more creative for it. # Why Although supposedly trystan or others have a language menu in mind, it's still not even being worked on yet. At the same time, I've already seen some people roleplay as though their characters do not speak galactic common. <details><summary><h1>Media</h1></summary> <p>      </p> </details> --- # Changelog 🆑 - add: Added two new foreigner traits that make your character unable to speak Galactic Common and give you a translator instead. - tweak: Translators can now be equipped in the neck slot and display useful info when examined.
106 lines
4.4 KiB
C#
106 lines
4.4 KiB
C#
using System.Linq;
|
|
using Content.Server.Hands.Systems;
|
|
using Content.Server.Language;
|
|
using Content.Server.Storage.EntitySystems;
|
|
using Content.Shared.Clothing.Components;
|
|
using Content.Shared.Inventory;
|
|
using Content.Shared.Language;
|
|
using Content.Shared.Language.Components;
|
|
using Content.Shared.Language.Components.Translators;
|
|
using Content.Shared.Storage;
|
|
using Robust.Shared.Prototypes;
|
|
|
|
namespace Content.Server.Traits.Assorted;
|
|
|
|
|
|
public sealed partial class ForeignerTraitSystem : EntitySystem
|
|
{
|
|
[Dependency] private readonly EntityManager _entMan = default!;
|
|
[Dependency] private readonly HandsSystem _hands = default!;
|
|
[Dependency] private readonly InventorySystem _inventory = default!;
|
|
[Dependency] private readonly LanguageSystem _languages = default!;
|
|
[Dependency] private readonly StorageSystem _storage = default!;
|
|
|
|
public override void Initialize()
|
|
{
|
|
SubscribeLocalEvent<ForeignerTraitComponent, ComponentInit>(OnSpawn); // TraitSystem adds it after PlayerSpawnCompleteEvent so it's fine
|
|
}
|
|
|
|
private void OnSpawn(Entity<ForeignerTraitComponent> entity, ref ComponentInit args)
|
|
{
|
|
if (entity.Comp.CantUnderstand && !entity.Comp.CantSpeak)
|
|
Log.Warning($"Allowing entity {entity.Owner} to speak a language but not understand it leads to undefined behavior.");
|
|
|
|
if (!TryComp<LanguageKnowledgeComponent>(entity, out var knowledge))
|
|
{
|
|
Log.Warning($"Entity {entity.Owner} does not have a LanguageKnowledge but has a ForeignerTrait!");
|
|
return;
|
|
}
|
|
|
|
var alternateLanguage = knowledge.SpokenLanguages.Find(it => it != entity.Comp.BaseLanguage);
|
|
if (alternateLanguage == null)
|
|
{
|
|
Log.Warning($"Entity {entity.Owner} does not have an alternative language to choose from (must have at least one non-GC for ForeignerTrait)!");
|
|
return;
|
|
}
|
|
|
|
if (TryGiveTranslator(entity.Owner, entity.Comp.BaseTranslator, entity.Comp.BaseLanguage, alternateLanguage, out var translator))
|
|
{
|
|
_languages.RemoveLanguage(entity, entity.Comp.BaseLanguage, entity.Comp.CantSpeak, entity.Comp.CantUnderstand, knowledge);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Tries to create and give the entity a translator to translator that translates speech between the two specified languages.
|
|
/// </summary>
|
|
public bool TryGiveTranslator(
|
|
EntityUid uid,
|
|
string baseTranslatorPrototype,
|
|
ProtoId<LanguagePrototype> translatorLanguage,
|
|
ProtoId<LanguagePrototype> entityLanguage,
|
|
out EntityUid result)
|
|
{
|
|
result = EntityUid.Invalid;
|
|
if (translatorLanguage == entityLanguage)
|
|
return false;
|
|
|
|
var translator = _entMan.SpawnNextToOrDrop(baseTranslatorPrototype, uid);
|
|
result = translator;
|
|
|
|
if (!TryComp<HandheldTranslatorComponent>(translator, out var handheld))
|
|
{
|
|
handheld = AddComp<HandheldTranslatorComponent>(translator);
|
|
handheld.ToggleOnInteract = true;
|
|
handheld.SetLanguageOnInteract = true;
|
|
}
|
|
|
|
// Allows to speak the specified language and requires entities language.
|
|
handheld.SpokenLanguages = [translatorLanguage];
|
|
handheld.UnderstoodLanguages = [translatorLanguage];
|
|
handheld.RequiredLanguages = [entityLanguage];
|
|
|
|
// Try to put it in entities hand
|
|
if (_hands.TryPickupAnyHand(uid, translator, false, false, false))
|
|
return true;
|
|
|
|
// Try to find a valid clothing slot on the entity and equip the translator there
|
|
if (TryComp<ClothingComponent>(translator, out var clothing)
|
|
&& clothing.Slots != SlotFlags.NONE
|
|
&& _inventory.TryGetSlots(uid, out var slots)
|
|
&& slots.Any(it => _inventory.TryEquip(uid, translator, it.Name, true, false)))
|
|
return true;
|
|
|
|
// Try to put the translator into entities bag, if it has one
|
|
if (_inventory.TryGetSlotEntity(uid, "back", out var bag)
|
|
&& TryComp<StorageComponent>(bag, out var storage)
|
|
&& _storage.Insert(bag.Value, translator, out _, null, storage, false, false))
|
|
return true;
|
|
|
|
// If all of the above has failed, just drop it at the same location as the entity
|
|
// This should ideally never happen, but who knows.
|
|
Transform(translator).Coordinates = Transform(uid).Coordinates;
|
|
|
|
return true;
|
|
}
|
|
}
|