Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
c2419a7
basic auditions
Just-a-Unity-Dev Jun 13, 2025
c91d4cf
Add producer singleton
Just-a-Unity-Dev Jun 14, 2025
9b7ea00
view variables
Just-a-Unity-Dev Jun 14, 2025
7fb4ed9
server auditions system
Just-a-Unity-Dev Jun 14, 2025
f76b05d
relationship prototype
Just-a-Unity-Dev Jun 14, 2025
188fe46
Merge branch 'master' of github.com:EphemeralSpace/ephemeral-space in…
Just-a-Unity-Dev Jun 14, 2025
1ce5015
basic relationships
Just-a-Unity-Dev Jun 14, 2025
cefef47
doccomment
Just-a-Unity-Dev Jun 14, 2025
0747606
integrate relationships
Just-a-Unity-Dev Jun 14, 2025
6b42858
Integrate relationships
Just-a-Unity-Dev Jun 14, 2025
0f3e3bc
cast generation
Just-a-Unity-Dev Jun 14, 2025
501cc9b
make producer an argument
Just-a-Unity-Dev Jun 14, 2025
d306263
cast generation
Just-a-Unity-Dev Jun 14, 2025
eaab942
documentation
Just-a-Unity-Dev Jun 14, 2025
4e0b962
doc comments
Just-a-Unity-Dev Jun 14, 2025
a8af9b3
unified -> mutual refactor
Just-a-Unity-Dev Jun 14, 2025
2b51c39
datafield+networked comp
Just-a-Unity-Dev Jun 14, 2025
4a269a5
[ForbidLiteral] these prototypes
Just-a-Unity-Dev Jun 14, 2025
ca011db
oops lol
Just-a-Unity-Dev Jun 14, 2025
9251998
protoyptpye
Just-a-Unity-Dev Jun 14, 2025
82a715d
remove stupid params
Just-a-Unity-Dev Jun 14, 2025
fc76ad2
datafielded
Just-a-Unity-Dev Jun 14, 2025
3899640
PARTING THE RED SEA
Just-a-Unity-Dev Jun 14, 2025
03eacee
datadef
Just-a-Unity-Dev Jun 14, 2025
b3ee772
dirty clean
Just-a-Unity-Dev Jun 14, 2025
c8065a1
make the api better
Just-a-Unity-Dev Jun 14, 2025
2929547
events for systems to integrate with
Just-a-Unity-Dev Jun 14, 2025
35e3896
sosyal groups
Just-a-Unity-Dev Jun 14, 2025
d7c3476
decrewization
Just-a-Unity-Dev Jun 15, 2025
b3de2c5
clean up events
Just-a-Unity-Dev Jun 15, 2025
e5bce22
doc comments
Just-a-Unity-Dev Jun 15, 2025
b20f08c
randomized date of birtghs
Just-a-Unity-Dev Jun 15, 2025
3e4f83e
force mutual oopsies!
Just-a-Unity-Dev Jun 15, 2025
c7f3db8
fix date time test fail
Just-a-Unity-Dev Jun 15, 2025
c69fe8a
tidy
Just-a-Unity-Dev Jun 15, 2025
045176c
fix test fail
Just-a-Unity-Dev Jun 15, 2025
b966c99
backgrounds
Just-a-Unity-Dev Jun 15, 2025
6b14668
command for casting
Just-a-Unity-Dev Jun 15, 2025
4adf9bf
default command argunebnts
Just-a-Unity-Dev Jun 15, 2025
f58f3ff
toolshed descriptior
Just-a-Unity-Dev Jun 15, 2025
6c9306f
dont integrate groups that have already been integrated
Just-a-Unity-Dev Jun 15, 2025
e1aef29
oops integration
Just-a-Unity-Dev Jun 15, 2025
740f0ea
it8jdhbiuksfxhrs
Just-a-Unity-Dev Jun 15, 2025
f2c597e
make exes rarer
Just-a-Unity-Dev Jun 15, 2025
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
158 changes: 158 additions & 0 deletions Content.Server/_ES/Auditions/AuditionsSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
using System.Diagnostics;
using System.Linq;
using Content.Server.Administration;
using Content.Shared._ES.Auditions;
using Content.Shared.Administration;
using Robust.Shared.Random;
using Robust.Shared.Toolshed;

namespace Content.Server._ES.Auditions;

/// <summary>
/// This handles the server-side of auditioning!
/// </summary>
public sealed class AuditionsSystem : SharedAuditionsSystem
{
[Dependency] private readonly IRobustRandom _random = default!;

/// <summary>
/// Hires a cast, and integrates relationships between all of the characters.
/// </summary>
public void GenerateCast(
int captainCount = 26,
int crewCount = 10,
ProducerComponent? producer = null
)
{
if (!TryGetProducer(ref producer))
throw new Exception("Could not get ProducerComponent!");

var preEvt = new PreCastGenerateEvent(producer);
RaiseLocalEvent(ref preEvt);

var captains = GenerateEmptySocialGroup();
captains.Comp.RelativeContext = producer.CaptainContext;

var newCharacters = new List<EntityUid>();

for (var i = 0; i < captainCount; i++)
{
var newCrew = GenerateRandomCrew(crewCount);
captains.Comp.Members.Add(newCrew.Comp.Members[0]);
newCharacters.AddRange(newCrew.Comp.Members);
}

var psgEvt = new PostShipGenerateEvent(producer);
RaiseLocalEvent(ref psgEvt);

foreach (var group in producer.SocialGroups)
{
var comp = EnsureComp<SocialGroupComponent>(group);
if (comp.Integrated)
continue;

var ent = (group, comp);

var pre = new SocialGroupPreIntegrationEvent(ent);
RaiseLocalEvent(ref pre);

IntegrateRelationshipGroup(comp.RelativeContext, comp.Members);
comp.Integrated = true;

var post = new SocialGroupPostIntegrationEvent(ent);
RaiseLocalEvent(ref post);
}

IntegrateRelationshipGroup(producer.IntercrewContext, newCharacters);
producer.Characters.AddRange(newCharacters);

var postEvt = new PostCastGenerateEvent(producer);
RaiseLocalEvent(ref postEvt);
}

public void GenerateCast(
int captainCount = 26,
int minimumCrew = 5,
int maximumCrew = 12,
ProducerComponent? producer = null
)
{
GenerateCast(captainCount, _random.Next(minimumCrew, maximumCrew), producer);
}
}

[ToolshedCommand, AdminCommand(AdminFlags.Round)]
public sealed class CastCommand : ToolshedCommand
{
private AuditionsSystem? _auditions;

[CommandImplementation("generate")]
public IEnumerable<string> Generate(int captainCount = 26, int crewSize = 10)
{
_auditions ??= GetSys<AuditionsSystem>();

var stopwatch = new Stopwatch();
stopwatch.Start();

_auditions.GenerateCast(captainCount, crewSize, null);

yield return $"Generated cast in {stopwatch.Elapsed.TotalMilliseconds} ms.";
}

[CommandImplementation("view")]
public IEnumerable<string> View([PipedArgument] EntityUid castMember)
{
_auditions ??= GetSys<AuditionsSystem>();
if (!EntityManager.TryGetComponent<CharacterComponent>(castMember, out var character))
{
yield return "Invalid cast member object (did not have CharacterComponent)!";
}
else
{
yield return $"{character.Name}, {character.Age} years old ({character.DateOfBirth.ToShortDateString()})\nBackground: {character.Background}\nRelationships\n";
Dictionary<string, List<string>> relationships = new();
foreach (var relationship in character.Relationships)
{
if (relationships.ContainsKey(relationship.Value))
relationships[relationship.Value].Add(relationship.Key);
else
relationships[relationship.Value] = [relationship.Key];
}

foreach (var relationship in relationships)
{
yield return $"{relationship.Key} ({relationship.Value.Count}): {string.Join(", ", relationship.Value.ToArray())}";
}
}
}
}

/// <summary>
/// Fires prior to this social group's relationships being integrated.
/// </summary>
[ByRefEvent]
public readonly record struct SocialGroupPreIntegrationEvent(Entity<SocialGroupComponent> Group);

/// <summary>
/// Fires after this social group's relationships have been integrated.
/// </summary>
[ByRefEvent]
public readonly record struct SocialGroupPostIntegrationEvent(Entity<SocialGroupComponent> Group);

/// <summary>
/// Fires prior to any generation events (captain group, crew groups, etc).
/// </summary>
[ByRefEvent]
public readonly record struct PreCastGenerateEvent(ProducerComponent Producer);

/// <summary>
/// Fires after the primary generation events (captain group, crew group, etc) but before integration of relationships.
/// </summary>
[ByRefEvent]
public readonly record struct PostShipGenerateEvent(ProducerComponent Producer);

/// <summary>
/// Fires after all relationships have been integrated.
/// </summary>
[ByRefEvent]
public readonly record struct PostCastGenerateEvent(ProducerComponent Producer);
26 changes: 26 additions & 0 deletions Content.Shared/_ES/Auditions/BackgroundPrototype.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using Robust.Shared.Prototypes;

namespace Content.Shared._ES.Auditions;

/// <summary>
/// This is a prototype for marking backgrounds
/// </summary>
[Prototype]
public sealed partial class BackgroundPrototype : IPrototype
{
/// <inheritdoc/>
[IdDataField]
public string ID { get; } = default!;

/// <summary>
/// Name of this relationship.
/// </summary>
[DataField, ViewVariables]
public LocId Name;

/// <summary>
/// Description of this relationship.
/// </summary>
[DataField, ViewVariables]
public LocId Description;
}
38 changes: 38 additions & 0 deletions Content.Shared/_ES/Auditions/CharacterComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using Content.Shared.Humanoid;
using Robust.Shared.Enums;
using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;

namespace Content.Shared._ES.Auditions;

/// <summary>
/// This is used for marking the character of components.
/// </summary>
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
public sealed partial class CharacterComponent : Component
{
[DataField, AutoNetworkedField]
public string Name = "Rain Miskovitch";

[DataField, AutoNetworkedField]
public int Age = 25;

[DataField, AutoNetworkedField]
public Gender Gender = Gender.Neuter;

[DataField, AutoNetworkedField]
public HumanoidCharacterAppearance Appearance = default!;

[DataField, AutoNetworkedField]
public DateTime DateOfBirth = new(2025, 1, 1);

[DataField, AutoNetworkedField]
public Dictionary<string, ProtoId<RelationshipPrototype>> Relationships = new ();

[DataField, AutoNetworkedField]
public ProtoId<BackgroundPrototype> Background = "Colonist";

[DataField, AutoNetworkedField]
public List<EntityUid> Memories = new ();
}
84 changes: 84 additions & 0 deletions Content.Shared/_ES/Auditions/ProducerComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
using Content.Shared.Random;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;

namespace Content.Shared._ES.Auditions;

/// <summary>
/// This is the cast component placed onto the producer entity.
/// </summary>
[RegisterComponent]
public sealed partial class ProducerComponent : Component
{
/// <summary>
/// All the characters in the cast.
/// </summary>
[DataField]
public List<EntityUid> Characters = new ();

/// <summary>
/// List of all active social groups.
/// </summary>
[DataField]
public List<EntityUid> SocialGroups = new ();

[DataField]
public RelationshipContext CrewContext = new ("RelationshipPoolCrew", 0.75f);

[DataField]
public RelationshipContext CaptainContext = new ("RelationshipPoolCaptains", 0.5f);

[DataField]
public RelationshipContext IntercrewContext = new ("RelationshipPoolIntercrew", 0.1f);
}

/// <summary>
/// Configuration for integrating relationships.
/// </summary>
[Serializable, NetSerializable, DataDefinition]
public partial struct RelationshipContext
{
/// <summary>
/// List of possible relationships.
/// </summary>
[DataField]
public ProtoId<WeightedRandomPrototype> PoolPrototype;

/// <summary>
/// How likely is a relationship to spark in this context?
/// </summary>
[DataField]
public float RelationshipProbability = 0.5f;

/// <summary>
/// How likely is a relationship to be mutual (both sides have the same relationship)?
/// </summary>
[DataField]
public float UnificationProbability = 1f;

/// <summary>
/// If the relationship isnt mutual, what are other possible relationships to give? If null, no relationship is assigned.
/// </summary>
[DataField]
public ProtoId<WeightedRandomPrototype>? SeperatePoolPrototype;

public RelationshipContext()
{
}

public RelationshipContext(string prototype, float probability)
{
RelationshipProbability = probability;
PoolPrototype = prototype;
UnificationProbability = 1f;
SeperatePoolPrototype = null;
}

public RelationshipContext(string prototype, float probability, float unificationProbability, string? seperatePrototype)
{
RelationshipProbability = probability;
PoolPrototype = prototype;
UnificationProbability = unificationProbability;
SeperatePoolPrototype = seperatePrototype;
}
}
32 changes: 32 additions & 0 deletions Content.Shared/_ES/Auditions/RelationshipPrototype.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using Robust.Shared.Prototypes;

namespace Content.Shared._ES.Auditions;

/// <summary>
/// This is a prototype for marking relationships
/// </summary>
[Prototype]
public sealed partial class RelationshipPrototype : IPrototype
{
/// <inheritdoc/>
[IdDataField]
public string ID { get; } = default!;

/// <summary>
/// Name of this relationship.
/// </summary>
[DataField, ViewVariables]
public LocId Name;

/// <summary>
/// Color of this relationship.
/// </summary>
[DataField, ViewVariables]
public Color Color;

/// <summary>
/// Whether or not this relationship must be mutual. Family members, ex-lovers, etc, all fall under this.
/// </summary>
[DataField, ViewVariables]
public bool ForceMutual;
}
Loading
Loading