fix antag bugs (#27319)

* fix antag bugs

* Update NukeopsRuleComponent.cs
This commit is contained in:
Nemanja
2024-04-25 20:25:57 -04:00
committed by GitHub
parent 281e5fa448
commit a0b3a6b679
8 changed files with 86 additions and 29 deletions

View File

@@ -5,15 +5,13 @@ using Robust.Shared.Random;
namespace Content.Server.Antag; namespace Content.Server.Antag;
public sealed class AntagSelectionPlayerPool(params List<ICommonSession>[] sessions) public sealed class AntagSelectionPlayerPool (List<List<ICommonSession>> orderedPools)
{ {
private readonly List<List<ICommonSession>> _orderedPools = sessions.ToList();
public bool TryPickAndTake(IRobustRandom random, [NotNullWhen(true)] out ICommonSession? session) public bool TryPickAndTake(IRobustRandom random, [NotNullWhen(true)] out ICommonSession? session)
{ {
session = null; session = null;
foreach (var pool in _orderedPools) foreach (var pool in orderedPools)
{ {
if (pool.Count == 0) if (pool.Count == 0)
continue; continue;
@@ -25,5 +23,5 @@ public sealed class AntagSelectionPlayerPool(params List<ICommonSession>[] sessi
return session != null; return session != null;
} }
public int Count => _orderedPools.Sum(p => p.Count); public int Count => orderedPools.Sum(p => p.Count);
} }

View File

@@ -35,7 +35,6 @@ public sealed partial class AntagSelectionSystem : GameRuleSystem<AntagSelection
[Dependency] private readonly AudioSystem _audio = default!; [Dependency] private readonly AudioSystem _audio = default!;
[Dependency] private readonly GhostRoleSystem _ghostRole = default!; [Dependency] private readonly GhostRoleSystem _ghostRole = default!;
[Dependency] private readonly JobSystem _jobs = default!; [Dependency] private readonly JobSystem _jobs = default!;
[Dependency] private readonly MapSystem _map = default!;
[Dependency] private readonly MindSystem _mind = default!; [Dependency] private readonly MindSystem _mind = default!;
[Dependency] private readonly RoleSystem _role = default!; [Dependency] private readonly RoleSystem _role = default!;
[Dependency] private readonly StationSpawningSystem _stationSpawning = default!; [Dependency] private readonly StationSpawningSystem _stationSpawning = default!;
@@ -133,7 +132,8 @@ public sealed partial class AntagSelectionSystem : GameRuleSystem<AntagSelection
if (!TryGetNextAvailableDefinition((uid, antag), out var def)) if (!TryGetNextAvailableDefinition((uid, antag), out var def))
continue; continue;
MakeAntag((uid, antag), args.Player, def.Value); if (TryMakeAntag((uid, antag), args.Player, def.Value))
break;
} }
} }
@@ -218,6 +218,21 @@ public sealed partial class AntagSelectionSystem : GameRuleSystem<AntagSelection
} }
} }
/// <summary>
/// Tries to makes a given player into the specified antagonist.
/// </summary>
public bool TryMakeAntag(Entity<AntagSelectionComponent> ent, ICommonSession? session, AntagSelectionDefinition def, bool ignoreSpawner = false)
{
if (!IsSessionValid(ent, session, def) ||
!IsEntityValid(session?.AttachedEntity, def))
{
return false;
}
MakeAntag(ent, session, def, ignoreSpawner);
return true;
}
/// <summary> /// <summary>
/// Makes a given player into the specified antagonist. /// Makes a given player into the specified antagonist.
/// </summary> /// </summary>
@@ -262,7 +277,6 @@ public sealed partial class AntagSelectionSystem : GameRuleSystem<AntagSelection
{ {
var playerXform = Transform(player); var playerXform = Transform(player);
var pos = RobustRandom.Pick(getPosEv.Coordinates); var pos = RobustRandom.Pick(getPosEv.Coordinates);
var mapEnt = _map.GetMap(pos.MapId);
_transform.SetMapCoordinates((player, playerXform), pos); _transform.SetMapCoordinates((player, playerXform), pos);
} }
@@ -291,8 +305,8 @@ public sealed partial class AntagSelectionSystem : GameRuleSystem<AntagSelection
_mind.SetUserId(curMind.Value, session.UserId); _mind.SetUserId(curMind.Value, session.UserId);
} }
EntityManager.AddComponents(curMind.Value, def.MindComponents);
_mind.TransferTo(curMind.Value, antagEnt, ghostCheckOverride: true); _mind.TransferTo(curMind.Value, antagEnt, ghostCheckOverride: true);
_role.MindAddRoles(curMind.Value, def.MindComponents);
ent.Comp.SelectedMinds.Add((curMind.Value, Name(player))); ent.Comp.SelectedMinds.Add((curMind.Value, Name(player)));
} }
@@ -310,42 +324,45 @@ public sealed partial class AntagSelectionSystem : GameRuleSystem<AntagSelection
/// </summary> /// </summary>
public AntagSelectionPlayerPool GetPlayerPool(Entity<AntagSelectionComponent> ent, List<ICommonSession> sessions, AntagSelectionDefinition def) public AntagSelectionPlayerPool GetPlayerPool(Entity<AntagSelectionComponent> ent, List<ICommonSession> sessions, AntagSelectionDefinition def)
{ {
var primaryList = new List<ICommonSession>(); var preferredList = new List<ICommonSession>();
var secondaryList = new List<ICommonSession>(); var secondBestList = new List<ICommonSession>();
var fallbackList = new List<ICommonSession>(); var unwantedList = new List<ICommonSession>();
var rawList = new List<ICommonSession>(); var invalidList = new List<ICommonSession>();
foreach (var session in sessions) foreach (var session in sessions)
{ {
if (!IsSessionValid(ent, session, def) || if (!IsSessionValid(ent, session, def) ||
!IsEntityValid(session.AttachedEntity, def)) !IsEntityValid(session.AttachedEntity, def))
{ {
rawList.Add(session); invalidList.Add(session);
continue; continue;
} }
var pref = (HumanoidCharacterProfile) _pref.GetPreferences(session.UserId).SelectedCharacter; var pref = (HumanoidCharacterProfile) _pref.GetPreferences(session.UserId).SelectedCharacter;
if (def.PrefRoles.Count == 0 || pref.AntagPreferences.Any(p => def.PrefRoles.Contains(p))) if (def.PrefRoles.Count != 0 && pref.AntagPreferences.Any(p => def.PrefRoles.Contains(p)))
{ {
primaryList.Add(session); preferredList.Add(session);
} }
else if (def.PrefRoles.Count == 0 || pref.AntagPreferences.Any(p => def.FallbackRoles.Contains(p))) else if (def.FallbackRoles.Count != 0 && pref.AntagPreferences.Any(p => def.FallbackRoles.Contains(p)))
{ {
secondaryList.Add(session); secondBestList.Add(session);
} }
else else
{ {
fallbackList.Add(session); unwantedList.Add(session);
} }
} }
return new AntagSelectionPlayerPool(primaryList, secondaryList, fallbackList, rawList); return new AntagSelectionPlayerPool(new() { preferredList, secondBestList, unwantedList, invalidList });
} }
/// <summary> /// <summary>
/// Checks if a given session is valid for an antagonist. /// Checks if a given session is valid for an antagonist.
/// </summary> /// </summary>
public bool IsSessionValid(Entity<AntagSelectionComponent> ent, ICommonSession session, AntagSelectionDefinition def, EntityUid? mind = null) public bool IsSessionValid(Entity<AntagSelectionComponent> ent, ICommonSession? session, AntagSelectionDefinition def, EntityUid? mind = null)
{ {
if (session == null)
return true;
mind ??= session.GetMind(); mind ??= session.GetMind();
if (session.Status is SessionStatus.Disconnected or SessionStatus.Zombie) if (session.Status is SessionStatus.Disconnected or SessionStatus.Zombie)

View File

@@ -71,5 +71,5 @@ public sealed partial class TraitorRuleComponent : Component
public int StartingBalance = 20; public int StartingBalance = 20;
[DataField] [DataField]
public int MaxDifficulty = 20; public int MaxDifficulty = 5;
} }

View File

@@ -16,6 +16,14 @@ public abstract partial class GameRuleSystem<T> where T: IComponent
return EntityQueryEnumerator<ActiveGameRuleComponent, T, GameRuleComponent>(); return EntityQueryEnumerator<ActiveGameRuleComponent, T, GameRuleComponent>();
} }
/// <summary>
/// Queries all gamerules, regardless of if they're active or not.
/// </summary>
protected EntityQueryEnumerator<T, GameRuleComponent> QueryAllRules()
{
return EntityQueryEnumerator<T, GameRuleComponent>();
}
/// <summary> /// <summary>
/// Utility function for finding a random event-eligible station entity /// Utility function for finding a random event-eligible station entity
/// </summary> /// </summary>

View File

@@ -34,8 +34,8 @@ public abstract partial class GameRuleSystem<T> : EntitySystem where T : ICompon
if (args.Forced || args.Cancelled) if (args.Forced || args.Cancelled)
return; return;
var query = QueryActiveRules(); var query = QueryAllRules();
while (query.MoveNext(out var uid, out _, out _, out var gameRule)) while (query.MoveNext(out var uid, out _, out var gameRule))
{ {
var minPlayers = gameRule.MinPlayers; var minPlayers = gameRule.MinPlayers;
if (args.Players.Length >= minPlayers) if (args.Players.Length >= minPlayers)

View File

@@ -344,7 +344,7 @@ public sealed class NukeopsRuleSystem : GameRuleSystem<NukeopsRuleComponent>
var timeRemain = nukeops.WarNukieArriveDelay + Timing.CurTime; var timeRemain = nukeops.WarNukieArriveDelay + Timing.CurTime;
ev.DeclaratorEntity.Comp.ShuttleDisabledTime = timeRemain; ev.DeclaratorEntity.Comp.ShuttleDisabledTime = timeRemain;
DistributeExtraTc(nukeops); DistributeExtraTc((uid, nukeops));
} }
} }
} }
@@ -371,7 +371,7 @@ public sealed class NukeopsRuleSystem : GameRuleSystem<NukeopsRuleComponent>
return WarConditionStatus.YesWar; return WarConditionStatus.YesWar;
} }
private void DistributeExtraTc(NukeopsRuleComponent nukieRule) private void DistributeExtraTc(Entity<NukeopsRuleComponent> nukieRule)
{ {
var enumerator = EntityQueryEnumerator<StoreComponent>(); var enumerator = EntityQueryEnumerator<StoreComponent>();
while (enumerator.MoveNext(out var uid, out var component)) while (enumerator.MoveNext(out var uid, out var component))
@@ -379,13 +379,13 @@ public sealed class NukeopsRuleSystem : GameRuleSystem<NukeopsRuleComponent>
if (!_tag.HasTag(uid, NukeOpsUplinkTagPrototype)) if (!_tag.HasTag(uid, NukeOpsUplinkTagPrototype))
continue; continue;
if (GetOutpost(uid) is not {} outpost) if (GetOutpost(nukieRule.Owner) is not { } outpost)
continue; continue;
if (Transform(uid).MapID != Transform(outpost).MapID) // Will receive bonus TC only on their start outpost if (Transform(uid).MapID != Transform(outpost).MapID) // Will receive bonus TC only on their start outpost
continue; continue;
_store.TryAddCurrency(new () { { TelecrystalCurrencyPrototype, nukieRule.WarTcAmountPerNukie } }, uid, component); _store.TryAddCurrency(new () { { TelecrystalCurrencyPrototype, nukieRule.Comp.WarTcAmountPerNukie } }, uid, component);
var msg = Loc.GetString("store-currency-war-boost-given", ("target", uid)); var msg = Loc.GetString("store-currency-war-boost-given", ("target", uid));
_popupSystem.PopupEntity(msg, uid); _popupSystem.PopupEntity(msg, uid);
@@ -510,7 +510,7 @@ public sealed class NukeopsRuleSystem : GameRuleSystem<NukeopsRuleComponent>
if (!Resolve(ent, ref ent.Comp, false)) if (!Resolve(ent, ref ent.Comp, false))
return null; return null;
return ent.Comp.MapGrids.FirstOrNull(); return ent.Comp.MapGrids.Where(e => HasComp<StationMemberComponent>(e) && !HasComp<NukeOpsShuttleComponent>(e)).FirstOrNull();
} }
/// <remarks> /// <remarks>

View File

@@ -34,6 +34,7 @@ public sealed class ThiefRuleSystem : GameRuleSystem<ThiefRuleComponent>
//Generate objectives //Generate objectives
GenerateObjectives(mindId, mind, ent); GenerateObjectives(mindId, mind, ent);
_antag.SendBriefing(args.EntityUid, MakeBriefing(args.EntityUid), null, null);
} }
private void GenerateObjectives(EntityUid mindId, MindComponent mind, ThiefRuleComponent thiefRule) private void GenerateObjectives(EntityUid mindId, MindComponent mind, ThiefRuleComponent thiefRule)

View File

@@ -1,3 +1,4 @@
using System.Linq;
using Content.Shared.Administration.Logs; using Content.Shared.Administration.Logs;
using Content.Shared.Database; using Content.Shared.Database;
using Content.Shared.Mind; using Content.Shared.Mind;
@@ -62,6 +63,38 @@ public abstract class SharedRoleSystem : EntitySystem
_antagTypes.Add(typeof(T)); _antagTypes.Add(typeof(T));
} }
public void MindAddRoles(EntityUid mindId, ComponentRegistry components, MindComponent? mind = null, bool silent = false)
{
if (!Resolve(mindId, ref mind))
return;
EntityManager.AddComponents(mindId, components);
var antagonist = false;
foreach (var compReg in components.Values)
{
var compType = compReg.Component.GetType();
var comp = EntityManager.ComponentFactory.GetComponent(compType);
if (IsAntagonistRole(comp.GetType()))
{
antagonist = true;
break;
}
}
var mindEv = new MindRoleAddedEvent(silent);
RaiseLocalEvent(mindId, ref mindEv);
var message = new RoleAddedEvent(mindId, mind, antagonist, silent);
if (mind.OwnedEntity != null)
{
RaiseLocalEvent(mind.OwnedEntity.Value, message, true);
}
_adminLogger.Add(LogType.Mind, LogImpact.Low,
$"Role components {string.Join(components.Keys.ToString(), ", ")} added to mind of {_minds.MindOwnerLoggingString(mind)}");
}
public void MindAddRole(EntityUid mindId, Component component, MindComponent? mind = null, bool silent = false) public void MindAddRole(EntityUid mindId, Component component, MindComponent? mind = null, bool silent = false)
{ {
if (!Resolve(mindId, ref mind)) if (!Resolve(mindId, ref mind))