Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cyborg Loadouts #30406

Open
wants to merge 17 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
35 changes: 32 additions & 3 deletions Content.Client/Lobby/LobbyUIController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -454,22 +454,51 @@ public void GiveDummyJobClothes(EntityUid dummy, HumanoidCharacterProfile profil
public EntityUid LoadProfileEntity(HumanoidCharacterProfile? humanoid, JobPrototype? job, bool jobClothes)
{
EntityUid dummyEnt;
bool isDummy = false;

if (humanoid is not null)
{
job ??= GetPreferredJob(humanoid);
var jobLoadout = LoadoutSystem.GetJobPrototype(job.ID);
humanoid.Loadouts.TryGetValue(jobLoadout, out var loadoutValue);

var dummy = _prototypeManager.Index<SpeciesPrototype>(humanoid.Species).DollPrototype;

if (loadoutValue != null)
{
foreach (var group in loadoutValue.SelectedLoadouts)
{
foreach (var items in group.Value)
{
if (!_prototypeManager.TryIndex(items.Prototype, out var loadoutProto))
{
continue;
}

if (loadoutProto.EntityDummy != String.Empty && loadoutProto.EntityDummy != null)
{
isDummy = true;
dummy = loadoutProto.EntityDummy;
break;
}
}
}
}

dummyEnt = EntityManager.SpawnEntity(dummy, MapCoordinates.Nullspace);
}
else
{
dummyEnt = EntityManager.SpawnEntity(_prototypeManager.Index<SpeciesPrototype>(SharedHumanoidAppearanceSystem.DefaultSpecies).DollPrototype, MapCoordinates.Nullspace);
}

_humanoid.LoadProfile(dummyEnt, humanoid);
if (!isDummy)
{
_humanoid.LoadProfile(dummyEnt, humanoid);
}

if (humanoid != null && jobClothes)
if (humanoid != null && jobClothes && job != null)
{
job ??= GetPreferredJob(humanoid);
GiveDummyJobClothes(dummyEnt, humanoid, job);

if (_prototypeManager.HasIndex<RoleLoadoutPrototype>(LoadoutSystem.GetJobPrototype(job.ID)))
Expand Down
28 changes: 16 additions & 12 deletions Content.Client/Lobby/UI/Loadouts/LoadoutContainer.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public sealed partial class LoadoutContainer : BoxContainer

public Button Select => SelectButton;

public LoadoutContainer(ProtoId<LoadoutPrototype> proto, bool disabled, FormattedMessage? reason)
public LoadoutContainer(ProtoId<LoadoutPrototype> proto, bool disabled, FormattedMessage? reason, string? dummy)
{
RobustXamlLoader.Load(this);
IoCManager.InjectDependencies(this);
Expand All @@ -34,20 +34,24 @@ public LoadoutContainer(ProtoId<LoadoutPrototype> proto, bool disabled, Formatte
SelectButton.TooltipSupplier = _ => tooltip;
}

if (_protoManager.TryIndex(proto, out var loadProto))
if (dummy != String.Empty)
{
var ent = _entManager.System<LoadoutSystem>().GetFirstOrNull(loadProto);
LoadoutSprite(dummy, _entity);
}
else if (_protoManager.TryIndex(proto, out var loadProto))
{
LoadoutSprite(_entManager.System<LoadoutSystem>().GetFirstOrNull(loadProto), _entity);
}

if (ent != null)
{
_entity = _entManager.SpawnEntity(ent, MapCoordinates.Nullspace);
Sprite.SetEntity(_entity);
}

var spriteTooltip = new Tooltip();
spriteTooltip.SetMessage(FormattedMessage.FromUnformatted(_entManager.GetComponent<MetaDataComponent>(_entity.Value).EntityDescription));
TooltipSupplier = _ => spriteTooltip;
}
}
private void LoadoutSprite(EntProtoId? proto, EntityUid? ent)
{
ent = _entManager.SpawnEntity(proto, MapCoordinates.Nullspace);
Sprite.SetEntity(ent);
var spriteTooltip = new Tooltip();
spriteTooltip.SetMessage(FormattedMessage.FromUnformatted(_entManager.GetComponent<MetaDataComponent>(ent.Value).EntityDescription));
TooltipSupplier = _ => spriteTooltip;
}

protected override void Dispose(bool disposing)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,14 +69,21 @@ public void RefreshLoadouts(HumanoidCharacterProfile profile, RoleLoadout loadou

foreach (var loadoutProto in _groupProto.Loadouts)
{
string loadoutDummy = String.Empty;

if (!protoMan.TryIndex(loadoutProto, out var loadProto))
continue;

if (loadProto.EntityDummy != null)
{
loadoutDummy = loadProto.EntityDummy;
}

var matchingLoadout = selected.FirstOrDefault(e => e.Prototype == loadoutProto);
var pressed = matchingLoadout != null;

var enabled = loadout.IsValid(profile, session, loadoutProto, collection, out var reason);
var loadoutContainer = new LoadoutContainer(loadoutProto, !enabled, reason);
var loadoutContainer = new LoadoutContainer(loadoutProto, !enabled, reason, loadoutDummy);
loadoutContainer.Select.Pressed = pressed;
loadoutContainer.Text = loadoutSystem.GetName(loadProto);

Expand Down
74 changes: 58 additions & 16 deletions Content.Server/Station/Systems/StationSpawningSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -128,20 +128,41 @@ public EntityUid SpawnPlayerMob(
if (prototype?.JobEntity != null)
{
DebugTools.Assert(entity is null);
var jobEntity = EntityManager.SpawnEntity(prototype.JobEntity, coordinates);
MakeSentientCommand.MakeSentient(jobEntity, EntityManager);
var jobEntity = SpawnEntity(prototype.JobEntity, coordinates, job);

// Make sure custom names get handled, what is gameticker control flow whoopy.
if (loadout != null)
{
EquipRoleName(jobEntity, loadout, roleProto!);
}

DoJobSpecials(job, jobEntity);
_identity.QueueIdentityUpdate(jobEntity);
return jobEntity;
}

profile?.Loadouts.TryGetValue(jobLoadout, out loadout);

if (loadout != null && roleProto != null)
{
foreach (var group in loadout.SelectedLoadouts.OrderBy(x => roleProto.Groups.FindIndex(e => e == x.Key)))
{
foreach (var items in group.Value)
{
if (!_prototypeManager.TryIndex(items.Prototype, out var loadoutProto))
{
continue;
}

if (loadoutProto.Entity != null)
{
var newEntity = SpawnEntity(loadoutProto.Entity, coordinates, job);
EquipLoadout(newEntity, jobLoadout, loadout, roleProto, prototype, profile);
EntityManager.DeleteEntity(entity);
return newEntity;
}
}
}
}

string speciesId;
if (_randomizeCharacters)
{
Expand All @@ -161,27 +182,25 @@ public EntityUid SpawnPlayerMob(
if (!_prototypeManager.TryIndex<SpeciesPrototype>(speciesId, out var species))
throw new ArgumentException($"Invalid species prototype was used: {speciesId}");

entity ??= Spawn(species.Prototype, coordinates);
entity ??= SpawnEntity(species.Prototype, coordinates, job);

if (_randomizeCharacters)
{
profile = HumanoidCharacterProfile.RandomWithSpecies(speciesId);
}

if (loadout != null)
if (roleProto != null)
{
EquipRoleLoadout(entity.Value, loadout, roleProto!);
}
// Set to default if not present
if (loadout == null)
{
loadout = new RoleLoadout(jobLoadout);
loadout.SetDefault(profile, _actors.GetSession(entity), _prototypeManager);
}

if (prototype?.StartingGear != null)
{
var startingGear = _prototypeManager.Index<StartingGearPrototype>(prototype.StartingGear);
EquipStartingGear(entity.Value, startingGear, raiseEvent: false);
EquipLoadout(entity.Value, jobLoadout, loadout, roleProto, prototype, profile);
}

var gearEquippedEv = new StartingGearEquippedEvent(entity.Value);
RaiseLocalEvent(entity.Value, ref gearEquippedEv);

if (profile != null)
{
if (prototype != null)
Expand All @@ -195,11 +214,34 @@ public EntityUid SpawnPlayerMob(
}
}

DoJobSpecials(job, entity.Value);
_identity.QueueIdentityUpdate(entity.Value);
return entity.Value;
}

private EntityUid SpawnEntity(string prototype, EntityCoordinates coordinates, JobComponent? job)
{
var entity = EntityManager.SpawnEntity(prototype, coordinates);
MakeSentientCommand.MakeSentient(entity, EntityManager);
DoJobSpecials(job, entity);
_identity.QueueIdentityUpdate(entity);
return entity;
}

private void EquipLoadout(EntityUid entity, string jobLoadout, RoleLoadout loadout, RoleLoadoutPrototype roleProto, JobPrototype? prototype, HumanoidCharacterProfile? profile)
{
EquipRoleLoadout(entity, loadout, roleProto);

if (prototype?.StartingGear != null)
{
var startingGear = _prototypeManager.Index<StartingGearPrototype>(prototype.StartingGear);
EquipStartingGear(entity, startingGear, raiseEvent: false);
}

var gearEquippedEv = new StartingGearEquippedEvent(entity);
RaiseLocalEvent(entity, ref gearEquippedEv);

}

private void DoJobSpecials(JobComponent? job, EntityUid entity)
{
if (!_prototypeManager.TryIndex(job?.Prototype ?? string.Empty, out JobPrototype? prototype))
Expand Down
15 changes: 11 additions & 4 deletions Content.Shared/Clothing/LoadoutSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -92,25 +92,32 @@ public string GetName(LoadoutPrototype loadout)
{
if (_protoMan.TryIndex(loadout.StartingGear, out var gear))
{
return GetName(gear);
return GetName(gear, loadout);
}

return GetName((IEquipmentLoadout) loadout);
return GetName((IEquipmentLoadout) loadout, loadout);
}

/// <summary>
/// Tries to get the name of a loadout.
/// </summary>
public string GetName(IEquipmentLoadout? gear)
public string GetName(IEquipmentLoadout? gear, LoadoutPrototype? loadout)
{
if (gear == null)
return string.Empty;

if (loadout != null
&& loadout.EntityDummy != null
&& _protoMan.TryIndex<EntityPrototype>(loadout.EntityDummy, out var proto))
{
return proto.Name;
}

var count = gear.Equipment.Count + gear.Storage.Values.Sum(o => o.Count) + gear.Inhand.Count;

if (count == 1)
{
if (gear.Equipment.Count == 1 && _protoMan.TryIndex<EntityPrototype>(gear.Equipment.Values.First(), out var proto))
if (gear.Equipment.Count == 1 && _protoMan.TryIndex<EntityPrototype>(gear.Equipment.Values.First(), out proto))
{
return proto.Name;
}
Expand Down
13 changes: 13 additions & 0 deletions Content.Shared/Preferences/Loadouts/LoadoutPrototype.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,19 @@ public sealed partial class LoadoutPrototype : IPrototype, IEquipmentLoadout
[DataField]
public List<LoadoutEffect> Effects = new();

/// <summary>
/// Overides the players entity
/// </summary>
[DataField]
public string? Entity { get; set; }

/// <summary>
/// Meant to be used in conjunction with Entity
/// Entity to show as the players dummy in the lobby
/// </summary>
[DataField]
public string? EntityDummy { get; set; }

/// <inheritdoc />
[DataField]
public Dictionary<string, EntProtoId> Equipment { get; set; } = new();
Expand Down
2 changes: 2 additions & 0 deletions Resources/Locale/en-US/preferences/loadout-groups.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -203,3 +203,5 @@ loadout-group-psychologist-jumpsuit = Psychologist jumpsuit

loadout-group-boxer-jumpsuit = Boxer jumpsuit
loadout-group-boxer-gloves = Boxer gloves

loadout-group-borg-chassis = Cyborg chassis
Loading
Loading