Fix/Addition - Wizard Survivor Antag Status (#35226)
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
namespace Content.Server.GameTicking.Rules.Components;
|
||||
|
||||
/// <summary>
|
||||
/// Component for the SurvivorRuleSystem. Game rule that turns everyone into a survivor and gives them the objective to escape centcom alive.
|
||||
/// Started by Wizard Summon Guns/Magic spells.
|
||||
/// </summary>
|
||||
[RegisterComponent, Access(typeof(SurvivorRuleSystem))]
|
||||
public sealed partial class SurvivorRuleComponent : Component;
|
||||
108
Content.Server/GameTicking/Rules/SurvivorRuleSystem.cs
Normal file
108
Content.Server/GameTicking/Rules/SurvivorRuleSystem.cs
Normal file
@@ -0,0 +1,108 @@
|
||||
using Content.Server.Antag;
|
||||
using Content.Server.GameTicking.Rules.Components;
|
||||
using Content.Server.Mind;
|
||||
using Content.Server.Roles;
|
||||
using Content.Server.Shuttles.Systems;
|
||||
using Content.Shared.GameTicking.Components;
|
||||
using Content.Shared.Mind;
|
||||
using Content.Shared.Mobs.Systems;
|
||||
using Content.Shared.Survivor.Components;
|
||||
using Content.Shared.Tag;
|
||||
using Robust.Server.GameObjects;
|
||||
|
||||
namespace Content.Server.GameTicking.Rules;
|
||||
|
||||
public sealed class SurvivorRuleSystem : GameRuleSystem<SurvivorRuleComponent>
|
||||
{
|
||||
[Dependency] private readonly RoleSystem _role = default!;
|
||||
[Dependency] private readonly MindSystem _mind = default!;
|
||||
[Dependency] private readonly AntagSelectionSystem _antag = default!;
|
||||
[Dependency] private readonly TransformSystem _xform = default!;
|
||||
[Dependency] private readonly EmergencyShuttleSystem _eShuttle = default!;
|
||||
[Dependency] private readonly TagSystem _tag = default!;
|
||||
[Dependency] private readonly MobStateSystem _mobState = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<SurvivorRoleComponent, GetBriefingEvent>(OnGetBriefing);
|
||||
}
|
||||
|
||||
// TODO: Planned rework post wizard release when RandomGlobalSpawnSpell becomes a gamerule
|
||||
protected override void Started(EntityUid uid, SurvivorRuleComponent component, GameRuleComponent gameRule, GameRuleStartedEvent args)
|
||||
{
|
||||
base.Started(uid, component, gameRule, args);
|
||||
|
||||
var allAliveHumanMinds = _mind.GetAliveHumans();
|
||||
|
||||
foreach (var humanMind in allAliveHumanMinds)
|
||||
{
|
||||
if (!humanMind.Comp.OwnedEntity.HasValue)
|
||||
continue;
|
||||
|
||||
var mind = humanMind.Owner;
|
||||
var ent = humanMind.Comp.OwnedEntity.Value;
|
||||
|
||||
if (HasComp<SurvivorComponent>(mind) || _tag.HasTag(mind, "InvalidForSurvivorAntag"))
|
||||
continue;
|
||||
|
||||
EnsureComp<SurvivorComponent>(mind);
|
||||
_role.MindAddRole(mind, "MindRoleSurvivor");
|
||||
_antag.SendBriefing(ent, Loc.GetString("survivor-role-greeting"), Color.Olive, null);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnGetBriefing(Entity<SurvivorRoleComponent> ent, ref GetBriefingEvent args)
|
||||
{
|
||||
args.Append(Loc.GetString("survivor-role-greeting"));
|
||||
}
|
||||
|
||||
protected override void AppendRoundEndText(EntityUid uid,
|
||||
SurvivorRuleComponent component,
|
||||
GameRuleComponent gameRule,
|
||||
ref RoundEndTextAppendEvent args)
|
||||
{
|
||||
base.AppendRoundEndText(uid, component, gameRule, ref args);
|
||||
|
||||
// Using this instead of alive antagonists to make checking for shuttle & if the ent is alive easier
|
||||
var existingSurvivors = AllEntityQuery<SurvivorComponent, MindComponent>();
|
||||
|
||||
var deadSurvivors = 0;
|
||||
var aliveMarooned = 0;
|
||||
var aliveOnShuttle = 0;
|
||||
var eShuttle = _eShuttle.GetShuttle();
|
||||
|
||||
while (existingSurvivors.MoveNext(out _, out _, out var mindComp))
|
||||
{
|
||||
// If their brain is gone or they respawned/became a ghost role
|
||||
if (mindComp.CurrentEntity is null)
|
||||
{
|
||||
deadSurvivors++;
|
||||
continue;
|
||||
}
|
||||
|
||||
var survivor = mindComp.CurrentEntity.Value;
|
||||
|
||||
if (!_mobState.IsAlive(survivor))
|
||||
{
|
||||
deadSurvivors++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (eShuttle != null && eShuttle.Value.IsValid() && (Transform(eShuttle.Value).MapID == _xform.GetMapCoordinates(survivor).MapId))
|
||||
{
|
||||
aliveOnShuttle++;
|
||||
continue;
|
||||
}
|
||||
|
||||
aliveMarooned++;
|
||||
}
|
||||
|
||||
args.AddLine(Loc.GetString("survivor-round-end-dead-count", ("deadCount", deadSurvivors)));
|
||||
args.AddLine(Loc.GetString("survivor-round-end-alive-count", ("aliveCount", aliveMarooned)));
|
||||
args.AddLine(Loc.GetString("survivor-round-end-alive-on-shuttle-count", ("aliveCount", aliveOnShuttle)));
|
||||
|
||||
// Player manifest at EOR shows who's a survivor so no need for extra info here.
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,20 @@
|
||||
using Content.Server.Chat.Systems;
|
||||
using Content.Server.GameTicking;
|
||||
using Content.Server.GameTicking.Rules.Components;
|
||||
using Content.Shared.Magic;
|
||||
using Content.Shared.Magic.Events;
|
||||
using Content.Shared.Mind;
|
||||
using Content.Shared.Tag;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.Magic;
|
||||
|
||||
public sealed class MagicSystem : SharedMagicSystem
|
||||
{
|
||||
[Dependency] private readonly ChatSystem _chat = default!;
|
||||
[Dependency] private readonly GameTicker _gameTicker = default!;
|
||||
[Dependency] private readonly TagSystem _tag = default!;
|
||||
[Dependency] private readonly SharedMindSystem _mind = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -32,4 +40,20 @@ public sealed class MagicSystem : SharedMagicSystem
|
||||
Spawn(ev.Effect, perfXForm.Coordinates);
|
||||
Spawn(ev.Effect, targetXForm.Coordinates);
|
||||
}
|
||||
|
||||
protected override void OnRandomGlobalSpawnSpell(RandomGlobalSpawnSpellEvent ev)
|
||||
{
|
||||
base.OnRandomGlobalSpawnSpell(ev);
|
||||
|
||||
if (!ev.MakeSurvivorAntagonist)
|
||||
return;
|
||||
|
||||
if (_mind.TryGetMind(ev.Performer, out var mind, out _) && !_tag.HasTag(mind, "InvalidForSurvivorAntag"))
|
||||
_tag.AddTag(mind, "InvalidForSurvivorAntag");
|
||||
|
||||
EntProtoId survivorRule = "Survivor";
|
||||
|
||||
if (!_gameTicker.IsGameRuleActive<SurvivorRuleComponent>())
|
||||
_gameTicker.StartGameRule(survivorRule);
|
||||
}
|
||||
}
|
||||
|
||||
9
Content.Server/Roles/SurvivorRoleComponent.cs
Normal file
9
Content.Server/Roles/SurvivorRoleComponent.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
using Content.Shared.Roles;
|
||||
|
||||
namespace Content.Server.Roles;
|
||||
|
||||
/// <summary>
|
||||
/// Adds to a mind role ent to tag they're a Survivor
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
public sealed partial class SurvivorRoleComponent : BaseMindRoleComponent;
|
||||
@@ -35,6 +35,7 @@ using Content.Shared.Prying.Components;
|
||||
using Content.Shared.Traits.Assorted;
|
||||
using Robust.Shared.Audio.Systems;
|
||||
using Content.Shared.Ghost.Roles.Components;
|
||||
using Content.Shared.Tag;
|
||||
|
||||
namespace Content.Server.Zombies;
|
||||
|
||||
@@ -58,6 +59,7 @@ public sealed partial class ZombieSystem
|
||||
[Dependency] private readonly MovementSpeedModifierSystem _movementSpeedModifier = default!;
|
||||
[Dependency] private readonly NPCSystem _npc = default!;
|
||||
[Dependency] private readonly SharedRoleSystem _roles = default!;
|
||||
[Dependency] private readonly TagSystem _tag = default!;
|
||||
|
||||
/// <summary>
|
||||
/// Handles an entity turning into a zombie when they die or go into crit
|
||||
@@ -275,5 +277,9 @@ public sealed partial class ZombieSystem
|
||||
RaiseLocalEvent(target, ref ev, true);
|
||||
//zombies get slowdown once they convert
|
||||
_movementSpeedModifier.RefreshMovementSpeedModifiers(target);
|
||||
|
||||
//Need to prevent them from getting an item, they have no hands.
|
||||
// Also prevents them from becoming a Survivor. They're undead.
|
||||
_tag.AddTag(target, "InvalidForGlobalSpawnSpell");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,4 +20,11 @@ public sealed partial class RandomGlobalSpawnSpellEvent : InstantActionEvent, IS
|
||||
|
||||
[DataField]
|
||||
public string? Speech { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Should this Global spawn spell turn its targets into a Survivor Antagonist?
|
||||
/// Ignores the caster for this.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public bool MakeSurvivorAntagonist = false;
|
||||
}
|
||||
|
||||
@@ -469,7 +469,8 @@ public abstract class SharedMagicSystem : EntitySystem
|
||||
#endregion
|
||||
#region Global Spells
|
||||
|
||||
private void OnRandomGlobalSpawnSpell(RandomGlobalSpawnSpellEvent ev)
|
||||
// TODO: Change this into a "StartRuleAction" when actions with multiple events are supported
|
||||
protected virtual void OnRandomGlobalSpawnSpell(RandomGlobalSpawnSpellEvent ev)
|
||||
{
|
||||
if (!_net.IsServer || ev.Handled || !PassesSpellPrerequisites(ev.Action, ev.Performer) || ev.Spawns is not { } spawns)
|
||||
return;
|
||||
@@ -486,6 +487,9 @@ public abstract class SharedMagicSystem : EntitySystem
|
||||
|
||||
var ent = human.Comp.OwnedEntity.Value;
|
||||
|
||||
if (_tag.HasTag(ent, "InvalidForGlobalSpawnSpell"))
|
||||
continue;
|
||||
|
||||
var mapCoords = _transform.GetMapCoordinates(ent);
|
||||
foreach (var spawn in EntitySpawnCollection.GetSpawns(spawns, _random))
|
||||
{
|
||||
|
||||
9
Content.Shared/Survivor/Components/SurvivorComponent.cs
Normal file
9
Content.Shared/Survivor/Components/SurvivorComponent.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
using Robust.Shared.GameStates;
|
||||
|
||||
namespace Content.Shared.Survivor.Components;
|
||||
|
||||
/// <summary>
|
||||
/// Component to keep track of which entities are a Survivor antag.
|
||||
/// </summary>
|
||||
[RegisterComponent, NetworkedComponent]
|
||||
public sealed partial class SurvivorComponent : Component;
|
||||
@@ -0,0 +1,36 @@
|
||||
## Survivor
|
||||
|
||||
roles-antag-survivor-name = Survivor
|
||||
# It's a Halo reference
|
||||
roles-antag-survivor-objective = Current Objective: Survive
|
||||
|
||||
survivor-role-greeting =
|
||||
You are a Survivor.
|
||||
Above all you need to make it back to CentComm alive.
|
||||
Collect as much firepower as needed to guarantee your survival.
|
||||
Trust no one.
|
||||
|
||||
survivor-round-end-dead-count =
|
||||
{
|
||||
$deadCount ->
|
||||
[one] [color=red]{$deadCount}[/color] survivor died.
|
||||
*[other] [color=red]{$deadCount}[/color] survivors died.
|
||||
}
|
||||
|
||||
survivor-round-end-alive-count =
|
||||
{
|
||||
$aliveCount ->
|
||||
[one] [color=yellow]{$aliveCount}[/color] survivor was marooned on the station.
|
||||
*[other] [color=yellow]{$aliveCount}[/color] survivors were marooned on the station.
|
||||
}
|
||||
|
||||
survivor-round-end-alive-on-shuttle-count =
|
||||
{
|
||||
$aliveCount ->
|
||||
[one] [color=green]{$aliveCount}[/color] survivor made it out alive.
|
||||
*[other] [color=green]{$aliveCount}[/color] survivors made it out alive.
|
||||
}
|
||||
|
||||
## TODO: Wizard
|
||||
|
||||
## TODO: Wizard Apprentice (Coming sometime post-wizard release)
|
||||
5
Resources/Prototypes/GameRules/survivor.yml
Normal file
5
Resources/Prototypes/GameRules/survivor.yml
Normal file
@@ -0,0 +1,5 @@
|
||||
- type: entity
|
||||
id: Survivor
|
||||
parent: BaseGameRule
|
||||
components:
|
||||
- type: SurvivorRule
|
||||
@@ -26,6 +26,7 @@
|
||||
sprite: Objects/Weapons/Guns/Rifles/ak.rsi
|
||||
state: base
|
||||
event: !type:RandomGlobalSpawnSpellEvent
|
||||
makeSurvivorAntagonist: true
|
||||
spawns:
|
||||
- id: WeaponPistolViper
|
||||
orGroup: Guns
|
||||
@@ -158,7 +159,7 @@
|
||||
- id: RevolverCapGunFake
|
||||
orGroup: Guns
|
||||
speech: action-speech-spell-summon-guns
|
||||
|
||||
|
||||
- type: entity
|
||||
id: ActionSummonMagic
|
||||
name: Summon Magic
|
||||
@@ -172,6 +173,7 @@
|
||||
sprite: Objects/Magic/magicactions.rsi
|
||||
state: magicmissile
|
||||
event: !type:RandomGlobalSpawnSpellEvent
|
||||
makeSurvivorAntagonist: true
|
||||
spawns:
|
||||
- id: SpawnSpellbook
|
||||
orGroup: Magics
|
||||
|
||||
8
Resources/Prototypes/Roles/Antags/wizard.yml
Normal file
8
Resources/Prototypes/Roles/Antags/wizard.yml
Normal file
@@ -0,0 +1,8 @@
|
||||
# TODO: Actual wizard coming later, this is just for the survival antags
|
||||
|
||||
- type: antag
|
||||
id: Survivor
|
||||
name: roles-antag-survivor-name
|
||||
antagonist: true
|
||||
objective: roles-antag-survivor-objective
|
||||
# guides: [ ]
|
||||
@@ -196,6 +196,17 @@
|
||||
- type: MindRole
|
||||
antagPrototype: Rev
|
||||
|
||||
# Survivors (Wizard)
|
||||
- type: entity
|
||||
parent: BaseMindRoleAntag
|
||||
id: MindRoleSurvivor
|
||||
name: Survivor Role
|
||||
components:
|
||||
- type: MindRole
|
||||
antagPrototype: Survivor
|
||||
roleType: FreeAgent
|
||||
- type: SurvivorRole
|
||||
|
||||
# Thief
|
||||
- type: entity
|
||||
parent: BaseMindRoleAntag
|
||||
|
||||
@@ -35,3 +35,4 @@
|
||||
id: SiliconAntagonist
|
||||
name: role-type-silicon-antagonist-name
|
||||
color: '#c832e6'
|
||||
|
||||
|
||||
@@ -752,6 +752,12 @@
|
||||
- type: Tag
|
||||
id: IntercomElectronics
|
||||
|
||||
- type: Tag
|
||||
id: InvalidForGlobalSpawnSpell
|
||||
|
||||
- type: Tag
|
||||
id: InvalidForSurvivorAntag
|
||||
|
||||
- type: Tag
|
||||
id: JawsOfLife
|
||||
|
||||
|
||||
Reference in New Issue
Block a user