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

Jester Role #49

Merged
merged 8 commits into from
Dec 22, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
5 changes: 5 additions & 0 deletions Content.Client/_SSS/UserInterface/SSSStatusUIController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,11 @@ public void UpdateRoleDisplay(SuspicionRuleUpdateRole ev, EntitySessionEventArgs
SuspicionRole.Traitor => "roles-antag-suspicion-traitor-name",
SuspicionRole.Detective => "roles-antag-suspicion-detective-name",
SuspicionRole.Innocent => "roles-antag-suspicion-innocent-name",
SuspicionRole.Wildcard => ev.NewSubRole switch
{
SuspicionSubRole.Jester => "roles-antag-suspicion-jester-name",
_ => "roles-antag-suspicion-wildcard-unknown",
},
_ => "roles-antag-suspicion-unknown",
});
SetRoleUI(roleName, Color.FromName(ev.NewRole.GetRoleColor()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ private void InitializeCVars()
{
Subs.CVar(_cfg, CCVars.SSSTraitorPercentage, f => _traitorPercentage = f, true);
Subs.CVar(_cfg, CCVars.SSSDetectivePercentage, f => _detectivePercentage = f, true);
Subs.CVar(_cfg, CCVars.SSSWildcardPercentage, f => _wildcardPercentage = f, true);
Subs.CVar(_cfg, CCVars.SSSWildcardChance, f => _wildcardChance = f, true);
Subs.CVar(_cfg, CCVars.SSSPreparingDuration, i => _preparingDuration = i, true);
Subs.CVar(_cfg, CCVars.SSSRoundDuration, i => _roundDuration = i, true);
Subs.CVar(_cfg, CCVars.SSSTimeAddedPerKill, i => _timeAddedPerKill = i, true);
Expand All @@ -16,6 +18,8 @@ private void InitializeCVars()

private float _traitorPercentage = 0.25f;
private float _detectivePercentage = 0.25f;
private float _wildcardPercentage = 0.15f;
private float _wildcardChance = 0.3f;
private int _preparingDuration = 30;
private int _roundDuration = 480;
private int _timeAddedPerKill = 30;
Expand Down
19 changes: 16 additions & 3 deletions Content.Server/_SSS/SuspicionGameRule/SuspicionRuleSystem.Rules.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ private void OnMobStateChanged(EntityUid uid, SuspicionPlayerComponent component

var allInnocents = FindAllOfType(SuspicionRole.Innocent);
var allDetectives = FindAllOfType(SuspicionRole.Detective);
var allJestersAlive = FindAllOfType(SuspicionSubRole.Jester);
var allJesters = FindAllOfType(SuspicionSubRole.Jester, false);

if (allInnocents.Count == 0 && allDetectives.Count == 0)
{
Expand All @@ -92,6 +94,15 @@ private void OnMobStateChanged(EntityUid uid, SuspicionPlayerComponent component
_roundEndSystem.EndRound(TimeSpan.FromSeconds(sus.PostRoundDuration));
return;
}

if (allJesters != allJestersAlive)
{
_chatManager.DispatchServerAnnouncement("The jesters have won the round.");
sus.GameState = SuspicionGameState.PostRound;
_roundEndSystem.EndRound(TimeSpan.FromSeconds(sus.PostRoundDuration));
return;
}

break;
}
}
Expand Down Expand Up @@ -166,7 +177,7 @@ private void OnExamine(EntityUid uid, SuspicionPlayerComponent component, ref Ex
EntityUid.Invalid,
false,
client: session.Channel,
recordReplay:true
recordReplay: true
);
}
}
Expand All @@ -176,11 +187,13 @@ private void OnExamine(EntityUid uid, SuspicionPlayerComponent component, ref Ex
}
}

var victimRole = role.Value.Comp2.SubRole?.ToString() ?? role.Value.Comp2.Role.ToString();

args.PushMarkup(Loc.GetString(
"suspicion-examination",
("ent", args.Examined),
("col", role.Value.Comp2.Role.GetRoleColor()),
("role", role.Value.Comp2.Role.ToString())),
("role", victimRole)),
-10);

if (!HasComp<HandsComponent>(args.Examiner))
Expand Down Expand Up @@ -211,7 +224,7 @@ private void OnExamine(EntityUid uid, SuspicionPlayerComponent component, ref Ex
("found", args.Examined),
("where", _navMapSystem.GetNearestBeaconString(loc)),
("col", role.Value.Comp2.Role.GetRoleColor()),
("role", role.Value.Comp2.Role.ToString()));
("role", victimRole));
SendAnnouncement(
msg
);
Expand Down
125 changes: 115 additions & 10 deletions Content.Server/_SSS/SuspicionGameRule/SuspicionRuleSystem.Spawning.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
using Content.Shared.Players;
using Content.Shared.Security.Components;
using Robust.Shared.Prototypes;
using Content.Shared.CombatMode.Pacification;

namespace Content.Server._SSS.SuspicionGameRule;

Expand All @@ -39,6 +40,11 @@ private void OnGetBriefing(Entity<SuspicionRoleComponent> role, ref GetBriefingE
SuspicionRole.Traitor => Loc.GetString("roles-antag-suspicion-traitor-objective"),
SuspicionRole.Detective => Loc.GetString("roles-antag-suspicion-detective-objective"),
SuspicionRole.Innocent => Loc.GetString("roles-antag-suspicion-innocent-objective"),
SuspicionRole.Wildcard => role.Comp.SubRole switch
{
SuspicionSubRole.Jester => Loc.GetString("roles-antag-suspicion-jester-objective"),
_ => "roles-antag-suspicion-pending-objective",
},
_ => Loc.GetString("roles-antag-suspicion-pending-objective")
};
}
Expand Down Expand Up @@ -79,29 +85,79 @@ private void StartRound(EntityUid uid, SuspicionRuleComponent component, GameRul
_rejuvenate.PerformRejuvenate(ent.Value);
}

var traitorCount = MathHelper.Clamp((int) (participatingPlayers.Count * _traitorPercentage), 1, allPlayerData.Count);
var detectiveCount = MathHelper.Clamp((int) (participatingPlayers.Count * _detectivePercentage), 1, allPlayerData.Count);
var traitorCount = MathHelper.Clamp((int)(participatingPlayers.Count * _traitorPercentage), 1, allPlayerData.Count);
var detectiveCount = MathHelper.Clamp((int)(participatingPlayers.Count * _detectivePercentage), 1, allPlayerData.Count);
var wildcardCount = 0; // Zero by default, we roll to see if wildcards will be in the next round in the next line.
if (RobustRandom.NextFloat() <= _wildcardChance)
wildcardCount = MathHelper.Clamp((int)(participatingPlayers.Count * _wildcardPercentage), 1, allPlayerData.Count);

if (traitorCount + detectiveCount > participatingPlayers.Count)
if (traitorCount + detectiveCount + wildcardCount > participatingPlayers.Count)
{
// we somehow have more picked players than valid

// what the fuck

traitorCount = participatingPlayers.Count;
detectiveCount = 0;
wildcardCount = 0;
}

/* Simyon, I think the issue is you didnt make it random enough, so I made it more random for you!
RobustRandom.Shuffle(participatingPlayers); // Shuffle the list so we can just take the first N players
RobustRandom.Shuffle(participatingPlayers);
RobustRandom.Shuffle(participatingPlayers); // I don't trust the shuffle.
RobustRandom.Shuffle(participatingPlayers);
RobustRandom.Shuffle(participatingPlayers); // I really don't trust the shuffle.
*/

int seed1 = (int)(Math.Sin(RobustRandom.Next()) * 10000);
int seed2 = (int)(Math.Cos(RobustRandom.Next()) * 10000);
Aidenkrz marked this conversation as resolved.
Show resolved Hide resolved
int combinedSeed = seed1 ^ seed2;

RobustRandom.SetSeed(combinedSeed);

int depth = 5;
while (depth > 0)
{
int chaoticSeed = (int)Math.Pow(RobustRandom.Next(), 3) ^ (RobustRandom.Next() % 10000);
RobustRandom.SetSeed(chaoticSeed);

int halfCount = participatingPlayers.Count / 2;
var shuffledSubset = participatingPlayers.Take(halfCount).ToList();
RobustRandom.Shuffle(shuffledSubset);
participatingPlayers.RemoveRange(0, halfCount);
participatingPlayers.AddRange(shuffledSubset);

depth--;
}

RobustRandom.SetSeed(RobustRandom.Next());
RobustRandom.Shuffle(participatingPlayers);

RobustRandom.SetSeed(RobustRandom.Next());
RobustRandom.Shuffle(participatingPlayers);

var shuffledIndices = participatingPlayers
.Select((_, i) => (Index: i, Value: RobustRandom.Next()))
.OrderBy(tuple => tuple.Value)
.Select(tuple => tuple.Index)
.ToList();

var reorderedPlayers = shuffledIndices.Select(i => participatingPlayers[i]).ToList();
participatingPlayers.Clear();
participatingPlayers.AddRange(reorderedPlayers);

for (int i = 0; i < 3; i++)
{
RobustRandom.SetSeed(RobustRandom.Next());
RobustRandom.Shuffle(participatingPlayers);
}

// I hope thats random enough!

for (var i = 0; i < traitorCount; i++)
{
var role = participatingPlayers[i];
var role = participatingPlayers[RobustRandom.Next(participatingPlayers.Count)];
role.comp.Role = SuspicionRole.Traitor;
var ownedEntity = Comp<MindComponent>(role.mind).OwnedEntity;
if (!ownedEntity.HasValue)
Expand All @@ -118,7 +174,7 @@ private void StartRound(EntityUid uid, SuspicionRuleComponent component, GameRul

_npcFactionSystem.AddFaction(ownedEntity.Value, component.TraitorFaction);

_subdermalImplant.AddImplants(ownedEntity.Value, new List<string> {component.UplinkImplant}); // Why does this method only take in a list???
_subdermalImplant.AddImplants(ownedEntity.Value, new List<string> { component.UplinkImplant }); // Why does this method only take in a list???

_antagSelectionSystem.SendBriefing(
ownedEntity.Value,
Expand All @@ -127,11 +183,12 @@ private void StartRound(EntityUid uid, SuspicionRuleComponent component, GameRul
_traitorStartSound);

RaiseNetworkEvent(new SuspicionRuleUpdateRole(SuspicionRole.Traitor), ownedEntity.Value);
participatingPlayers.Remove(role);
}

for (var i = traitorCount; i < traitorCount + detectiveCount; i++)
for (var i = 0; i < detectiveCount; i++)
{
var role = participatingPlayers[i];
var role = participatingPlayers[RobustRandom.Next(participatingPlayers.Count)];
role.comp.Role = SuspicionRole.Detective;
var ownedEntity = Comp<MindComponent>(role.mind).OwnedEntity;
if (!ownedEntity.HasValue)
Expand All @@ -144,14 +201,62 @@ private void StartRound(EntityUid uid, SuspicionRuleComponent component, GameRul

AddKeyToRadio(ownedEntity.Value, component.DetectiveRadio);

_subdermalImplant.AddImplants(ownedEntity.Value, new List<string> {component.DetectiveImplant});
_subdermalImplant.AddImplants(ownedEntity.Value, new List<string> { component.DetectiveImplant });

_antagSelectionSystem.SendBriefing(
ownedEntity.Value,
Loc.GetString("detective-briefing"),
Color.LightBlue,
briefingSound:null);
briefingSound: null);
RaiseNetworkEvent(new SuspicionRuleUpdateRole(SuspicionRole.Detective), ownedEntity.Value);
participatingPlayers.Remove(role);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like we should probably pull out some of the systems here (such as the briefing and shit) so we don't duplicated code like crazy.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We really should, but like I said, I'm not trying to refactor everything with this PR.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah thats fine

}

var wildcardRoles = new List<SuspicionSubRole>
{
SuspicionSubRole.Jester
};

for (var i = 0; i < wildcardCount; i++)
{
var role = participatingPlayers[RobustRandom.Next(participatingPlayers.Count)];

var selectedSubRole = wildcardRoles[RobustRandom.Next(wildcardRoles.Count)];

role.comp.Role = SuspicionRole.Wildcard;
role.comp.SubRole = selectedSubRole;

string briefingText = selectedSubRole switch
{
SuspicionSubRole.Jester => Loc.GetString("jester-briefing"),
_ => Loc.GetString("wildcard-briefing")
};

var ownedEntity = Comp<MindComponent>(role.mind).OwnedEntity;
if (!ownedEntity.HasValue)
{
Log.Error("Player mind has no entity.");
continue;
}

switch (selectedSubRole)
{
case SuspicionSubRole.Jester:
{
EnsureComp<PacifiedComponent>(ownedEntity.Value);
break;
}
}

_antagSelectionSystem.SendBriefing(
ownedEntity.Value,
briefingText,
Color.LightPink,
briefingSound: null);

RaiseNetworkEvent(new SuspicionRuleUpdateRole(SuspicionRole.Wildcard, selectedSubRole), ownedEntity.Value);

participatingPlayers.Remove(role);
}

// Anyone who isn't a traitor will get the innocent role.
Expand All @@ -169,7 +274,7 @@ private void StartRound(EntityUid uid, SuspicionRuleComponent component, GameRul
ownedEntity.Value,
Loc.GetString("innocent-briefing"),
briefingColor: Color.Green,
briefingSound:null);
briefingSound: null);

RaiseNetworkEvent(new SuspicionRuleUpdateRole(SuspicionRole.Innocent), ownedEntity.Value);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ private void AddTcToPlayer(EntityUid player, int amount, bool displayMessage = t
/// </summary>
private List<(EntityUid body, Entity<MindRoleComponent, SuspicionRoleComponent> sus)> FindAllOfType(SuspicionRole role, bool filterDead = true)
{
var allMinds = new HashSet<Entity<MindComponent>>();
var allMinds = new HashSet<Entity<MindComponent>>();
if (filterDead)
{
allMinds = _mindSystem.GetAliveHumans();
Expand Down Expand Up @@ -123,6 +123,49 @@ private void AddTcToPlayer(EntityUid player, int amount, bool displayMessage = t
return result;
}

/// <summary>
/// Finds all players with a specific sub-role.
/// </summary>
private List<(EntityUid body, Entity<MindRoleComponent, SuspicionRoleComponent> sus)> FindAllOfType(SuspicionSubRole subRole, bool filterDead = true)
{
var allMinds = new HashSet<Entity<MindComponent>>();
if (filterDead)
{
allMinds = _mindSystem.GetAliveHumans();
}
else
{
var query = EntityQueryEnumerator<HumanoidAppearanceComponent>();
while (query.MoveNext(out var uid, out _))
{
if (!_mindSystem.TryGetMind(uid, out var mind, out var mindComp))
continue;

allMinds.Add(new Entity<MindComponent>(mind, mindComp));
}
}

var result = new List<(EntityUid body, Entity<MindRoleComponent, SuspicionRoleComponent>)>();
foreach (var mind in allMinds)
{
var nullableMind = new Entity<MindComponent?>(mind.Owner, mind.Comp); // Following the pattern from the original method.
Aidenkrz marked this conversation as resolved.
Show resolved Hide resolved

if (!_roleSystem.MindHasRole<SuspicionRoleComponent>(nullableMind, out var roleComp))
continue;

if (roleComp.Value.Comp2.SubRole != subRole)
continue;

var entity = Comp<MindComponent>(mind).OwnedEntity;
if (!entity.HasValue)
continue;

result.Add((entity.Value, roleComp.Value));
}

return result;
}

public void DropAllItemsOnEntity(EntityUid entity)
{
if (!TryComp(entity, out InventoryComponent? inventory))
Expand Down
Loading
Loading