mirror of
https://github.com/WWhiteDreamProject/wwdpublic.git
synced 2026-04-20 23:17:43 +03:00
<!-- This is a semi-strict format, you can add/remove sections as needed but the order/format should be kept the same Remove these comments before submitting --> # Description <!-- Explain this PR in as much detail as applicable Some example prompts to consider: How might this affect the game? The codebase? What might be some alternatives to this? How/Who does this benefit/hurt [the game/codebase]? --> Adds an admin command to spawn a passport --- <!-- This is default collapsed, readers click to expand it and see all your media The PR media section can get very large at times, so this is a good way to keep it clean The title is written using HTML tags The title must be within the <summary> tags or you won't see it --> <details><summary><h1>Media</h1></summary> <p>  </p> </details> --- # Changelog <!-- You can add an author after the `🆑` to change the name that appears in the changelog (ex: `🆑 Death`) Leaving it blank will default to your GitHub display name This includes all available types for the changelog --> 🆑 - add: Added admin command to spawn a passport for a player --------- Signed-off-by: Timfa <timfalken@hotmail.com> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> (cherry picked from commit e7497abdadc017ff2f4494f505c253059d688e83)
164 lines
6.4 KiB
C#
164 lines
6.4 KiB
C#
using Content.Shared._EE.Contractors.Components;
|
|
using Content.Shared._EE.Contractors.Prototypes;
|
|
using Content.Shared.Administration.Logs;
|
|
using Content.Shared.Clothing.Loadouts.Systems;
|
|
using Content.Shared.Database;
|
|
using Content.Shared.Examine;
|
|
using Content.Shared.Humanoid.Prototypes;
|
|
using Content.Shared.Interaction.Events;
|
|
using Content.Shared.Inventory;
|
|
using Content.Shared.Item;
|
|
using Content.Shared.Preferences;
|
|
using Content.Shared.Storage;
|
|
using Content.Shared.Storage.EntitySystems;
|
|
using Robust.Shared;
|
|
using Content.Shared.CCVar;
|
|
using Content.Shared.Roles;
|
|
using Robust.Shared.Configuration;
|
|
using Robust.Shared.Prototypes;
|
|
using Robust.Shared.Timing;
|
|
|
|
|
|
namespace Content.Shared._EE.Contractors.Systems;
|
|
|
|
public class SharedPassportSystem : EntitySystem
|
|
{
|
|
public const int CurrentYear = 2450;
|
|
const string PIDChars = "ABCDEFGHJKLMNPQRSTUVWXYZ0123456789";
|
|
|
|
[Dependency] private readonly IGameTiming _timing = default!;
|
|
[Dependency] private readonly IEntityManager _entityManager = default!;
|
|
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
|
[Dependency] private readonly InventorySystem _inventory = default!;
|
|
[Dependency] private readonly SharedStorageSystem _storage = default!;
|
|
[Dependency] private readonly SharedTransformSystem _sharedTransformSystem = default!;
|
|
[Dependency] private readonly IConfigurationManager _configManager = default!;
|
|
[Dependency] private readonly ISharedAdminLogManager _adminLogManager = default!;
|
|
|
|
public override void Initialize()
|
|
{
|
|
base.Initialize();
|
|
|
|
SubscribeLocalEvent<PassportComponent, UseInHandEvent>(OnUseInHand);
|
|
SubscribeLocalEvent<PlayerLoadoutAppliedEvent>(OnPlayerLoadoutApplied);
|
|
SubscribeLocalEvent<PassportComponent, ExaminedEvent>(OnExamined);
|
|
}
|
|
|
|
private void OnExamined(EntityUid uid, PassportComponent component, ExaminedEvent args)
|
|
{
|
|
if (!args.IsInDetailsRange
|
|
|| component.IsClosed
|
|
|| component.OwnerProfile == null)
|
|
return;
|
|
|
|
var species = _prototypeManager.Index<SpeciesPrototype>(component.OwnerProfile.Species);
|
|
|
|
args.PushMarkup($"Registered to: {component.OwnerProfile.Name}", 50);
|
|
args.PushMarkup($"Species: {Loc.GetString(species.Name)}", 49);
|
|
args.PushMarkup($"Sex: {component.OwnerProfile.Gender}", 48);
|
|
args.PushMarkup($"Height: {MathF.Round(component.OwnerProfile.Height * species.AverageHeight)} cm", 47);
|
|
args.PushMarkup($"Year of Birth: {CurrentYear - component.OwnerProfile.Age}", 46);
|
|
|
|
args.PushMarkup(
|
|
$"PID: {GenerateIdentityString(component.OwnerProfile.Name
|
|
+ component.OwnerProfile.Height
|
|
+ component.OwnerProfile.Age
|
|
+ component.OwnerProfile.Height
|
|
+ component.OwnerProfile.FlavorText)}",
|
|
45);
|
|
}
|
|
|
|
private void OnPlayerLoadoutApplied(PlayerLoadoutAppliedEvent ev) =>
|
|
SpawnPassportForPlayer(ev.Mob, ev.Profile, ev.JobId);
|
|
|
|
public void SpawnPassportForPlayer(EntityUid mob, HumanoidCharacterProfile profile, string? jobId)
|
|
{
|
|
if (jobId == null || !_prototypeManager.TryIndex(
|
|
jobId,
|
|
out JobPrototype? jobPrototype)
|
|
|| !jobPrototype.CanHavePassport
|
|
|| Deleted(mob)
|
|
|| !Exists(mob)
|
|
|| !ShouldSpawnPassports)
|
|
return;
|
|
|
|
if (!_prototypeManager.TryIndex(
|
|
profile.Nationality,
|
|
out NationalityPrototype? nationalityPrototype) || !_prototypeManager.TryIndex(nationalityPrototype.PassportPrototype, out EntityPrototype? entityPrototype))
|
|
return;
|
|
|
|
var passportEntity = _entityManager.SpawnEntity(entityPrototype.ID, _sharedTransformSystem.GetMapCoordinates(mob));
|
|
var passportComponent = _entityManager.GetComponent<PassportComponent>(passportEntity);
|
|
|
|
UpdatePassportProfile(new(passportEntity, passportComponent), profile);
|
|
|
|
// Try to find back-mounted storage apparatus
|
|
if (_inventory.TryGetSlotEntity(mob, "back", out var item) &&
|
|
EntityManager.TryGetComponent<StorageComponent>(item, out var inventory))
|
|
// Try inserting the entity into the storage, if it can't, it leaves the loadout item on the ground
|
|
{
|
|
if (!EntityManager.TryGetComponent<ItemComponent>(passportEntity, out var itemComp)
|
|
|| !_storage.CanInsert(item.Value, passportEntity, out _, inventory, itemComp)
|
|
|| !_storage.Insert(item.Value, passportEntity, out _, playSound: false))
|
|
{
|
|
_adminLogManager.Add(
|
|
LogType.EntitySpawn,
|
|
LogImpact.Low,
|
|
$"Passport for {profile.Name} was spawned on the floor due to missing bag space");
|
|
}
|
|
}
|
|
}
|
|
|
|
private bool ShouldSpawnPassports =>
|
|
_configManager.GetCVar(CCVar.CCVars.ContractorsEnabled) &&
|
|
_configManager.GetCVar(CCVar.CCVars.ContractorsPassportEnabled);
|
|
|
|
public void UpdatePassportProfile(Entity<PassportComponent> passport, HumanoidCharacterProfile profile)
|
|
{
|
|
passport.Comp.OwnerProfile = profile;
|
|
var evt = new PassportProfileUpdatedEvent(profile);
|
|
RaiseLocalEvent(passport, ref evt);
|
|
}
|
|
|
|
private void OnUseInHand(Entity<PassportComponent> passport, ref UseInHandEvent evt)
|
|
{
|
|
if (evt.Handled || !_timing.IsFirstTimePredicted)
|
|
return;
|
|
|
|
evt.Handled = true;
|
|
passport.Comp.IsClosed = !passport.Comp.IsClosed;
|
|
|
|
var passportEvent = new PassportToggleEvent();
|
|
RaiseLocalEvent(passport, ref passportEvent);
|
|
}
|
|
|
|
private static string GenerateIdentityString(string seed)
|
|
{
|
|
var hashCode = seed.GetHashCode();
|
|
System.Random random = new System.Random(hashCode);
|
|
|
|
char[] result = new char[17]; // 15 characters + 2 dashes
|
|
|
|
int j = 0;
|
|
for (int i = 0; i < 15; i++)
|
|
{
|
|
if (i == 5 || i == 10)
|
|
{
|
|
result[j++] = '-';
|
|
}
|
|
result[j++] = PIDChars[random.Next(PIDChars.Length)];
|
|
}
|
|
|
|
return new string(result);
|
|
}
|
|
|
|
[ByRefEvent]
|
|
public sealed class PassportToggleEvent : HandledEntityEventArgs {}
|
|
|
|
[ByRefEvent]
|
|
public sealed class PassportProfileUpdatedEvent(HumanoidCharacterProfile profile) : HandledEntityEventArgs
|
|
{
|
|
public HumanoidCharacterProfile Profile { get; } = profile;
|
|
}
|
|
}
|