diff --git a/Content.Server/Ninja/NinjaRole.cs b/Content.Server/Ninja/NinjaRole.cs
new file mode 100644
index 0000000000..80b0f47984
--- /dev/null
+++ b/Content.Server/Ninja/NinjaRole.cs
@@ -0,0 +1,43 @@
+using Content.Server.Traitor;
+using Content.Shared.Roles;
+
+namespace Content.Server.Ninja;
+
+///
+/// Stores the ninja's objectives in the mind so if they die the rest of the greentext persists.
+///
+public sealed class NinjaRole : TraitorRole
+{
+ public NinjaRole(Mind.Mind mind, AntagPrototype antagPrototype) : base(mind, antagPrototype) { }
+
+ ///
+ /// Number of doors that have been doorjacked, used for objective
+ ///
+ [ViewVariables]
+ public int DoorsJacked = 0;
+
+ ///
+ /// Research nodes that have been downloaded, used for objective
+ ///
+ // TODO: client doesn't need to know what nodes are downloaded, just how many
+ [ViewVariables]
+ public HashSet DownloadedNodes = new();
+
+ ///
+ /// Warp point that the spider charge has to target
+ ///
+ [ViewVariables]
+ public EntityUid? SpiderChargeTarget = null;
+
+ ///
+ /// Whether the spider charge has been detonated on the target, used for objective
+ ///
+ [ViewVariables]
+ public bool SpiderChargeDetonated;
+
+ ///
+ /// Whether the comms console has been hacked, used for objective
+ ///
+ [ViewVariables]
+ public bool CalledInThreat;
+}
diff --git a/Content.Server/Ninja/Systems/NinjaGlovesSystem.cs b/Content.Server/Ninja/Systems/NinjaGlovesSystem.cs
index 0a7fe722ec..57377da556 100644
--- a/Content.Server/Ninja/Systems/NinjaGlovesSystem.cs
+++ b/Content.Server/Ninja/Systems/NinjaGlovesSystem.cs
@@ -1,15 +1,20 @@
using Content.Server.Communications;
using Content.Server.DoAfter;
+using Content.Server.Ninja.Systems;
using Content.Server.Power.Components;
using Content.Shared.DoAfter;
using Content.Shared.Interaction.Events;
using Content.Shared.Ninja.Components;
using Content.Shared.Ninja.Systems;
+using Content.Shared.Popups;
+using Content.Shared.Research.Components;
namespace Content.Server.Ninja.Systems;
public sealed class NinjaGlovesSystem : SharedNinjaGlovesSystem
{
+ [Dependency] private readonly new NinjaSystem _ninja = default!;
+
protected override void OnDrain(EntityUid uid, NinjaDrainComponent comp, InteractionAttemptEvent args)
{
if (!GloveCheck(uid, args, out var gloves, out var user, out var target)
@@ -29,8 +34,59 @@ public sealed class NinjaGlovesSystem : SharedNinjaGlovesSystem
_doAfter.TryStartDoAfter(doAfterArgs);
}
- protected override bool IsCommsConsole(EntityUid uid)
+ protected override void OnDownloadDoAfter(EntityUid uid, NinjaDownloadComponent comp, DownloadDoAfterEvent args)
{
- return HasComp(uid);
+ if (args.Cancelled || args.Handled)
+ return;
+
+ var user = args.User;
+ var target = args.Target;
+
+ if (!TryComp(user, out var ninja)
+ || !TryComp(target, out var database))
+ return;
+
+ var gained = _ninja.Download(uid, database.TechnologyIds);
+ var str = gained == 0
+ ? Loc.GetString("ninja-download-fail")
+ : Loc.GetString("ninja-download-success", ("count", gained), ("server", target));
+
+ Popups.PopupEntity(str, user, user, PopupType.Medium);
+ }
+
+ protected override void OnTerror(EntityUid uid, NinjaTerrorComponent comp, InteractionAttemptEvent args)
+ {
+ if (!GloveCheck(uid, args, out var gloves, out var user, out var target)
+ || !_ninja.GetNinjaRole(user, out var role)
+ || !HasComp(target))
+ return;
+
+
+ // can only do it once
+ if (role.CalledInThreat)
+ {
+ Popups.PopupEntity(Loc.GetString("ninja-terror-already-called"), user, user);
+ return;
+ }
+
+ var doAfterArgs = new DoAfterArgs(user, comp.TerrorTime, new TerrorDoAfterEvent(), target: target, used: uid, eventTarget: uid)
+ {
+ BreakOnDamage = true,
+ BreakOnUserMove = true,
+ MovementThreshold = 0.5f,
+ CancelDuplicate = false
+ };
+
+ _doAfter.TryStartDoAfter(doAfterArgs);
+ // FIXME: doesnt work, don't show the console popup
+ args.Cancel();
+ }
+
+ protected override void OnTerrorDoAfter(EntityUid uid, NinjaTerrorComponent comp, TerrorDoAfterEvent args)
+ {
+ if (args.Cancelled || args.Handled)
+ return;
+
+ _ninja.CallInThreat(args.User);
}
}
diff --git a/Content.Server/Ninja/Systems/NinjaSystem.cs b/Content.Server/Ninja/Systems/NinjaSystem.cs
index 318d1115bd..b9812c5be4 100644
--- a/Content.Server/Ninja/Systems/NinjaSystem.cs
+++ b/Content.Server/Ninja/Systems/NinjaSystem.cs
@@ -8,12 +8,12 @@ using Content.Server.GameTicking.Rules;
using Content.Server.GameTicking.Rules.Configurations;
using Content.Server.Ghost.Roles.Events;
using Content.Server.Mind.Components;
+using Content.Server.Ninja;
using Content.Server.Ninja.Components;
using Content.Server.Objectives;
using Content.Server.Popups;
using Content.Server.Power.Components;
using Content.Server.PowerCell;
-using Content.Server.Traitor;
using Content.Server.Warps;
using Content.Shared.Alert;
using Content.Shared.Doors.Components;
@@ -32,6 +32,7 @@ using Robust.Shared.Player;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
using System.Diagnostics.CodeAnalysis;
+using System.Linq;
namespace Content.Server.Ninja.Systems;
@@ -89,6 +90,49 @@ public sealed class NinjaSystem : SharedNinjaSystem
GreetNinja(mind);
}
+ ///
+ /// Download the given set of nodes, returning how many new nodes were downloaded.'
+ ///
+ public int Download(EntityUid uid, List ids)
+ {
+ if (!GetNinjaRole(uid, out var role))
+ return 0;
+
+ var oldCount = role.DownloadedNodes.Count;
+ role.DownloadedNodes.UnionWith(ids);
+ var newCount = role.DownloadedNodes.Count;
+ return newCount - oldCount;
+ }
+
+ ///
+ /// Gets a ninja's role using the player's mind
+ ///
+ public static bool GetNinjaRole(Mind.Mind? mind, [NotNullWhen(true)] out NinjaRole? role)
+ {
+ if (mind == null)
+ {
+ role = null;
+ return false;
+ }
+
+ role = (NinjaRole?) mind.AllRoles
+ .Where(r => r is NinjaRole)
+ .FirstOrDefault();
+ return role != null;
+ }
+
+ ///
+ /// Gets a ninja's role using the player's entity id
+ ///
+ public bool GetNinjaRole(EntityUid uid, [NotNullWhen(true)] out NinjaRole? role)
+ {
+ role = null;
+ if (!TryComp(uid, out var mind))
+ return false;
+
+ return GetNinjaRole(mind.Mind, out role);
+ }
+
///
/// Returns the space ninja spawn gamerule's config
///
@@ -150,14 +194,17 @@ public sealed class NinjaSystem : SharedNinjaSystem
return GetNinjaBattery(user, out var battery) && battery.TryUseCharge(charge);
}
- public override void CallInThreat(NinjaComponent comp)
+ ///
+ /// Completes the objective, makes announcement and adds rule of a random threat.
+ ///
+ public void CallInThreat(EntityUid uid)
{
- base.CallInThreat(comp);
-
var config = RuleConfig();
- if (config.Threats.Count == 0)
+ if (config.Threats.Count == 0 || !GetNinjaRole(uid, out var role) || role.CalledInThreat)
return;
+ role.CalledInThreat = true;
+
var threat = _random.Pick(config.Threats);
if (_proto.TryIndex(threat.Rule, out var rule))
{
@@ -224,7 +271,38 @@ public sealed class NinjaSystem : SharedNinjaSystem
_implants.ForceImplant(uid, implant, implantComp);
}
+ }
+ private void OnNinjaSpawned(EntityUid uid, NinjaComponent comp, GhostRoleSpawnerUsedEvent args)
+ {
+ // inherit spawner's station grid
+ if (TryComp(args.Spawner, out var station))
+ SetNinjaStationGrid(uid, station.Grid);
+ }
+
+ private void OnNinjaMindAdded(EntityUid uid, NinjaComponent comp, MindAddedMessage args)
+ {
+ Logger.ErrorS("ninja_testing", "AMONG US 2 RELASED");
+ if (TryComp(uid, out var mind) && mind.Mind != null)
+ GreetNinja(mind.Mind);
+ }
+
+ private void GreetNinja(Mind.Mind mind)
+ {
+ Logger.ErrorS("ninja_testing", "GREETING");
+ if (!mind.TryGetSession(out var session))
+ return;
+
+ var config = RuleConfig();
+ var role = new NinjaRole(mind, _proto.Index("SpaceNinja"));
+ mind.AddRole(role);
+ _traitorRule.Traitors.Add(role);
+ foreach (var objective in config.Objectives)
+ {
+ AddObjective(mind, objective);
+ }
+
+ Logger.ErrorS("ninja_testing", "added role");
// choose spider charge detonation point
// currently based on warp points, something better could be done (but would likely require mapping work)
var warps = new List();
@@ -237,35 +315,7 @@ public sealed class NinjaSystem : SharedNinjaSystem
}
if (warps.Count > 0)
- comp.SpiderChargeTarget = _random.Pick(warps);
- }
-
- private void OnNinjaSpawned(EntityUid uid, NinjaComponent comp, GhostRoleSpawnerUsedEvent args)
- {
- // inherit spawner's station grid
- if (TryComp(args.Spawner, out var station))
- SetNinjaStationGrid(uid, station.Grid);
- }
-
- private void OnNinjaMindAdded(EntityUid uid, NinjaComponent comp, MindAddedMessage args)
- {
- if (TryComp(uid, out var mind) && mind.Mind != null)
- GreetNinja(mind.Mind);
- }
-
- private void GreetNinja(Mind.Mind mind)
- {
- if (!mind.TryGetSession(out var session))
- return;
-
- var config = RuleConfig();
- var role = new TraitorRole(mind, _proto.Index("SpaceNinja"));
- mind.AddRole(role);
- _traitorRule.Traitors.Add(role);
- foreach (var objective in config.Objectives)
- {
- AddObjective(mind, objective);
- }
+ role.SpiderChargeTarget = _random.Pick(warps);
_audio.PlayGlobal(config.GreetingSound, Filter.Empty().AddPlayer(session), false, AudioParams.Default);
_chatMan.DispatchServerMessage(session, Loc.GetString("ninja-role-greeting"));
@@ -285,8 +335,8 @@ public sealed class NinjaSystem : SharedNinjaSystem
private void OnDoorEmagged(EntityUid uid, DoorComponent door, ref DoorEmaggedEvent args)
{
// make sure it's a ninja doorjacking it
- if (TryComp(args.UserUid, out var ninja))
- ninja.DoorsJacked++;
+ if (GetNinjaRole(args.UserUid, out var role))
+ role.DoorsJacked++;
}
private void UpdateNinja(EntityUid uid, NinjaComponent ninja, float frameTime)
diff --git a/Content.Server/Ninja/Systems/SpiderChargeSystem.cs b/Content.Server/Ninja/Systems/SpiderChargeSystem.cs
index 94d3fb7911..35cad95335 100644
--- a/Content.Server/Ninja/Systems/SpiderChargeSystem.cs
+++ b/Content.Server/Ninja/Systems/SpiderChargeSystem.cs
@@ -26,7 +26,7 @@ public sealed class SpiderChargeSystem : EntitySystem
{
var user = args.User;
- if (!TryComp(user, out var ninja))
+ if (!_ninja.GetNinjaRole(user, out var role))
{
_popups.PopupEntity(Loc.GetString("spider-charge-not-ninja"), user, user);
args.Handled = true;
@@ -34,17 +34,16 @@ public sealed class SpiderChargeSystem : EntitySystem
}
// allow planting anywhere if there is no target, which should never happen
- if (ninja.SpiderChargeTarget != null)
+ if (role.SpiderChargeTarget == null)
+ return;
+
+ // assumes warp point still exists
+ var target = Transform(role.SpiderChargeTarget.Value).MapPosition;
+ var coords = args.ClickLocation.ToMap(EntityManager, _transform);
+ if (!coords.InRange(target, comp.Range))
{
- // assumes warp point still exists
- var target = Transform(ninja.SpiderChargeTarget.Value).MapPosition;
- var coords = args.ClickLocation.ToMap(EntityManager, _transform);
- if (!coords.InRange(target, comp.Range))
- {
- _popups.PopupEntity(Loc.GetString("spider-charge-too-far"), user, user);
- args.Handled = true;
- return;
- }
+ _popups.PopupEntity(Loc.GetString("spider-charge-too-far"), user, user);
+ args.Handled = true;
}
}
@@ -55,10 +54,10 @@ public sealed class SpiderChargeSystem : EntitySystem
private void OnExplode(EntityUid uid, SpiderChargeComponent comp, TriggerEvent args)
{
- if (comp.Planter == null || !TryComp(comp.Planter, out var ninja))
+ if (comp.Planter == null || !_ninja.GetNinjaRole(comp.Planter.Value, out var role))
return;
// assumes the target was destroyed, that the charge wasn't moved somehow
- _ninja.DetonateSpiderCharge(ninja);
+ role.SpiderChargeDetonated = true;
}
}
diff --git a/Content.Server/Objectives/Conditions/DoorjackCondition.cs b/Content.Server/Objectives/Conditions/DoorjackCondition.cs
index 335b18f198..fc46d03836 100644
--- a/Content.Server/Objectives/Conditions/DoorjackCondition.cs
+++ b/Content.Server/Objectives/Conditions/DoorjackCondition.cs
@@ -1,5 +1,5 @@
+using Content.Server.Ninja.Systems;
using Content.Server.Objectives.Interfaces;
-using Content.Shared.Ninja.Components;
using Robust.Shared.Random;
using Robust.Shared.Utility;
@@ -30,16 +30,14 @@ public sealed class DoorjackCondition : IObjectiveCondition
{
get
{
- var entMan = IoCManager.Resolve();
- if (_mind?.OwnedEntity == null
- || !entMan.TryGetComponent(_mind.OwnedEntity, out var ninja))
- return 0f;
-
// prevent divide-by-zero
if (_target == 0)
return 1f;
- return (float) ninja.DoorsJacked / (float) _target;
+ if (!NinjaSystem.GetNinjaRole(_mind, out var role))
+ return 0f;
+
+ return (float) role.DoorsJacked / (float) _target;
}
}
diff --git a/Content.Server/Objectives/Conditions/DownloadCondition.cs b/Content.Server/Objectives/Conditions/DownloadCondition.cs
index 18948b1955..fe71aa05da 100644
--- a/Content.Server/Objectives/Conditions/DownloadCondition.cs
+++ b/Content.Server/Objectives/Conditions/DownloadCondition.cs
@@ -1,5 +1,5 @@
+using Content.Server.Ninja.Systems;
using Content.Server.Objectives.Interfaces;
-using Content.Shared.Ninja.Components;
using Robust.Shared.Random;
using Robust.Shared.Utility;
@@ -34,12 +34,10 @@ public sealed class DownloadCondition : IObjectiveCondition
if (_target == 0)
return 1f;
- var entMan = IoCManager.Resolve();
- if (_mind?.OwnedEntity == null
- || !entMan.TryGetComponent(_mind.OwnedEntity, out var ninja))
+ if (!NinjaSystem.GetNinjaRole(_mind, out var role))
return 0f;
- return (float) ninja.DownloadedNodes.Count / (float) _target;
+ return (float) role.DownloadedNodes.Count / (float) _target;
}
}
diff --git a/Content.Server/Objectives/Conditions/SpiderChargeCondition.cs b/Content.Server/Objectives/Conditions/SpiderChargeCondition.cs
index c8ea4897df..5ae9cad3b1 100644
--- a/Content.Server/Objectives/Conditions/SpiderChargeCondition.cs
+++ b/Content.Server/Objectives/Conditions/SpiderChargeCondition.cs
@@ -1,6 +1,6 @@
+using Content.Server.Ninja.Systems;
using Content.Server.Objectives.Interfaces;
using Content.Server.Warps;
-using Content.Shared.Ninja.Components;
using Robust.Shared.Random;
using Robust.Shared.Utility;
@@ -23,12 +23,11 @@ public sealed class SpiderChargeCondition : IObjectiveCondition
get
{
var entMan = IoCManager.Resolve();
- if (_mind?.OwnedEntity == null
- || !entMan.TryGetComponent(_mind.OwnedEntity, out var ninja)
- || ninja.SpiderChargeTarget == null
- || !entMan.TryGetComponent(ninja.SpiderChargeTarget, out var warp)
+ if (!NinjaSystem.GetNinjaRole(_mind, out var role)
+ || role.SpiderChargeTarget == null
+ || !entMan.TryGetComponent(role.SpiderChargeTarget, out var warp)
|| warp.Location == null)
- // if you are funny and microbomb then press c, you get this
+ // this should never really happen but eh
return Loc.GetString("objective-condition-spider-charge-no-target");
return Loc.GetString("objective-condition-spider-charge-title", ("location", warp.Location));
@@ -43,12 +42,10 @@ public sealed class SpiderChargeCondition : IObjectiveCondition
{
get
{
- var entMan = IoCManager.Resolve();
- if (_mind?.OwnedEntity == null
- || !entMan.TryGetComponent(_mind.OwnedEntity, out var ninja))
+ if (!NinjaSystem.GetNinjaRole(_mind, out var role))
return 0f;
- return ninja.SpiderChargeDetonated ? 1f : 0f;
+ return role.SpiderChargeDetonated ? 1f : 0f;
}
}
diff --git a/Content.Server/Objectives/Conditions/SurviveCondition.cs b/Content.Server/Objectives/Conditions/SurviveCondition.cs
index b4bfe4426d..2641918238 100644
--- a/Content.Server/Objectives/Conditions/SurviveCondition.cs
+++ b/Content.Server/Objectives/Conditions/SurviveCondition.cs
@@ -1,46 +1,43 @@
using Content.Server.Objectives.Interfaces;
-using JetBrains.Annotations;
using Robust.Shared.Utility;
-namespace Content.Server.Objectives.Conditions
+namespace Content.Server.Objectives.Conditions;
+
+[DataDefinition]
+public sealed class SurviveCondition : IObjectiveCondition
{
- [UsedImplicitly]
- [DataDefinition]
- public sealed class SurviveCondition : IObjectiveCondition
+ private Mind.Mind? _mind;
+
+ public IObjectiveCondition GetAssigned(Mind.Mind mind)
{
- private Mind.Mind? _mind;
+ return new SurviveCondition {_mind = mind};
+ }
- public IObjectiveCondition GetAssigned(Mind.Mind mind)
- {
- return new SurviveCondition {_mind = mind};
- }
+ public string Title => Loc.GetString("objective-condition-survive-title");
- public string Title => Loc.GetString("objective-condition-survive-title");
+ public string Description => Loc.GetString("objective-condition-survive-description");
- public string Description => Loc.GetString("objective-condition-survive-description");
+ public SpriteSpecifier Icon => new SpriteSpecifier.Rsi(new ResourcePath("Clothing/Head/Helmets/spaceninja.rsi"), "icon");
- public SpriteSpecifier Icon => new SpriteSpecifier.Rsi(new ResourcePath("Clothing/Head/Helmets/spaceninja.rsi"), "icon");
+ public float Difficulty => 0.5f;
- public float Difficulty => 0.5f;
+ public float Progress => (_mind?.CharacterDeadIC ?? true) ? 0f : 1f;
- public float Progress => (_mind?.CharacterDeadIC ?? true) ? 0f : 1f;
+ public bool Equals(IObjectiveCondition? other)
+ {
+ return other is SurviveCondition condition && Equals(_mind, condition._mind);
+ }
- public bool Equals(IObjectiveCondition? other)
- {
- return other is SurviveCondition condition && Equals(_mind, condition._mind);
- }
+ public override bool Equals(object? obj)
+ {
+ if (ReferenceEquals(null, obj)) return false;
+ if (ReferenceEquals(this, obj)) return true;
+ if (obj.GetType() != GetType()) return false;
+ return Equals((SurviveCondition) obj);
+ }
- public override bool Equals(object? obj)
- {
- if (ReferenceEquals(null, obj)) return false;
- if (ReferenceEquals(this, obj)) return true;
- if (obj.GetType() != GetType()) return false;
- return Equals((SurviveCondition) obj);
- }
-
- public override int GetHashCode()
- {
- return (_mind != null ? _mind.GetHashCode() : 0);
- }
+ public override int GetHashCode()
+ {
+ return (_mind != null ? _mind.GetHashCode() : 0);
}
}
diff --git a/Content.Server/Objectives/Conditions/TerrorCondition.cs b/Content.Server/Objectives/Conditions/TerrorCondition.cs
index 10f76b6a6e..89d5f41263 100644
--- a/Content.Server/Objectives/Conditions/TerrorCondition.cs
+++ b/Content.Server/Objectives/Conditions/TerrorCondition.cs
@@ -1,5 +1,5 @@
+using Content.Server.Ninja.Systems;
using Content.Server.Objectives.Interfaces;
-using Content.Shared.Ninja.Components;
using Robust.Shared.Utility;
namespace Content.Server.Objectives.Conditions;
@@ -24,12 +24,10 @@ public sealed class TerrorCondition : IObjectiveCondition
{
get
{
- var entMan = IoCManager.Resolve();
- if (_mind?.OwnedEntity == null
- || !entMan.TryGetComponent(_mind.OwnedEntity, out var ninja))
+ if (!NinjaSystem.GetNinjaRole(_mind, out var role))
return 0f;
- return ninja.CalledInThreat ? 1f : 0f;
+ return role.CalledInThreat ? 1f : 0f;
}
}
diff --git a/Content.Server/Objectives/Requirements/NinjaRequirement.cs b/Content.Server/Objectives/Requirements/NinjaRequirement.cs
new file mode 100644
index 0000000000..e330a7f1e8
--- /dev/null
+++ b/Content.Server/Objectives/Requirements/NinjaRequirement.cs
@@ -0,0 +1,13 @@
+using Content.Server.Objectives.Interfaces;
+using Content.Server.Ninja;
+
+namespace Content.Server.Objectives.Requirements;
+
+[DataDefinition]
+public sealed class NinjaRequirement : IObjectiveRequirement
+{
+ public bool CanBeAssigned(Mind.Mind mind)
+ {
+ return mind.HasRole();
+ }
+}
diff --git a/Content.Server/Traitor/TraitorRole.cs b/Content.Server/Traitor/TraitorRole.cs
index 4e23122e7d..d7b4d39f30 100644
--- a/Content.Server/Traitor/TraitorRole.cs
+++ b/Content.Server/Traitor/TraitorRole.cs
@@ -4,7 +4,8 @@ using Content.Shared.Roles;
namespace Content.Server.Traitor
{
- public sealed class TraitorRole : Role
+ [Virtual]
+ public class TraitorRole : Role
{
public AntagPrototype Prototype { get; }
diff --git a/Content.Shared/Ninja/Components/NinjaComponent.cs b/Content.Shared/Ninja/Components/NinjaComponent.cs
index 851be9a5a9..3036e06b73 100644
--- a/Content.Shared/Ninja/Components/NinjaComponent.cs
+++ b/Content.Shared/Ninja/Components/NinjaComponent.cs
@@ -8,7 +8,6 @@ namespace Content.Shared.Ninja.Components;
/// Component placed on a mob to make it a space ninja, able to use suit and glove powers.
/// Contains ids of all ninja equipment.
///
-// TODO: Contains objective related stuff, might want to move it out somehow
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
[Access(typeof(SharedNinjaSystem))]
public sealed partial class NinjaComponent : Component
@@ -16,6 +15,7 @@ public sealed partial class NinjaComponent : Component
///
/// Grid entity of the station the ninja was spawned around. Set if spawned naturally by the event.
///
+ [ViewVariables, AutoNetworkedField]
public EntityUid? StationGrid;
///
@@ -35,35 +35,4 @@ public sealed partial class NinjaComponent : Component
///
[ViewVariables]
public EntityUid? Katana = null;
-
- ///
- /// Number of doors that have been doorjacked, used for objective
- ///
- [ViewVariables, AutoNetworkedField]
- public int DoorsJacked = 0;
-
- ///
- /// Research nodes that have been downloaded, used for objective
- ///
- // TODO: client doesn't need to know what nodes are downloaded, just how many
- [ViewVariables, AutoNetworkedField]
- public HashSet DownloadedNodes = new();
-
- ///
- /// Warp point that the spider charge has to target
- ///
- [ViewVariables, AutoNetworkedField]
- public EntityUid? SpiderChargeTarget = null;
-
- ///
- /// Whether the spider charge has been detonated on the target, used for objective
- ///
- [ViewVariables, AutoNetworkedField]
- public bool SpiderChargeDetonated;
-
- ///
- /// Whether the comms console has been hacked, used for objective
- ///
- [ViewVariables, AutoNetworkedField]
- public bool CalledInThreat;
}
diff --git a/Content.Shared/Ninja/Systems/NinjaGlovesSystem.cs b/Content.Shared/Ninja/Systems/NinjaGlovesSystem.cs
index bccb3d9521..b62feb188e 100644
--- a/Content.Shared/Ninja/Systems/NinjaGlovesSystem.cs
+++ b/Content.Shared/Ninja/Systems/NinjaGlovesSystem.cs
@@ -36,7 +36,7 @@ public abstract class SharedNinjaGlovesSystem : EntitySystem
[Dependency] private readonly SharedInteractionSystem _interaction = default!;
[Dependency] private readonly INetManager _net = default!;
[Dependency] private readonly SharedNinjaSystem _ninja = default!;
- [Dependency] private readonly SharedPopupSystem _popups = default!;
+ [Dependency] protected readonly SharedPopupSystem Popups = default!;
[Dependency] private readonly TagSystem _tags = default!;
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly UseDelaySystem _useDelay = default!;
@@ -72,7 +72,7 @@ public abstract class SharedNinjaGlovesSystem : EntitySystem
if (comp.User != null)
{
comp.User = null;
- _popups.PopupEntity(Loc.GetString("ninja-gloves-off"), user, user);
+ Popups.PopupEntity(Loc.GetString("ninja-gloves-off"), user, user);
}
}
@@ -191,7 +191,7 @@ public abstract class SharedNinjaGlovesSystem : EntitySystem
// take charge from battery
if (!_ninja.TryUseCharge(user, comp.StunCharge))
{
- _popups.PopupEntity(Loc.GetString("ninja-no-power"), user, user);
+ Popups.PopupEntity(Loc.GetString("ninja-no-power"), user, user);
return;
}
@@ -239,76 +239,18 @@ public abstract class SharedNinjaGlovesSystem : EntitySystem
args.Cancel();
}
- private void OnDownloadDoAfter(EntityUid uid, NinjaDownloadComponent comp, DownloadDoAfterEvent args)
- {
- if (args.Cancelled || args.Handled)
- return;
+ // can't predict roles so only done on server.
+ protected virtual void OnDownloadDoAfter(EntityUid uid, NinjaDownloadComponent comp, DownloadDoAfterEvent args) { }
- var user = args.User;
- var target = args.Target;
+ // cant predict roles for checking if already called
+ protected virtual void OnTerror(EntityUid uid, NinjaTerrorComponent comp, InteractionAttemptEvent args) { }
- if (!TryComp(user, out var ninja)
- || !TryComp(target, out var database))
- return;
-
- var gained = _ninja.Download(ninja, database.TechnologyIds);
- var str = gained == 0
- ? Loc.GetString("ninja-download-fail")
- : Loc.GetString("ninja-download-success", ("count", gained), ("server", target));
-
- _popups.PopupEntity(str, user, user, PopupType.Medium);
- }
-
- private void OnTerror(EntityUid uid, NinjaTerrorComponent comp, InteractionAttemptEvent args)
- {
- if (!GloveCheck(uid, args, out var gloves, out var user, out var target)
- || !TryComp(user, out var ninja))
- return;
-
- if (!IsCommsConsole(target))
- return;
-
- // can only do it once
- if (ninja.CalledInThreat)
- {
- _popups.PopupEntity(Loc.GetString("ninja-terror-already-called"), user, user);
- return;
- }
-
- var doAfterArgs = new DoAfterArgs(user, comp.TerrorTime, new TerrorDoAfterEvent(), target: target, used: uid, eventTarget: uid)
- {
- BreakOnDamage = true,
- BreakOnUserMove = true,
- MovementThreshold = 0.5f,
- CancelDuplicate = false
- };
-
- _doAfter.TryStartDoAfter(doAfterArgs);
- // FIXME: doesnt work, don't show the console popup
- args.Cancel();
- }
-
- //for some reason shared comms console component isn't a component, so this has to be done server-side
- protected virtual bool IsCommsConsole(EntityUid uid)
- {
- return false;
- }
-
- private void OnTerrorDoAfter(EntityUid uid, NinjaTerrorComponent comp, TerrorDoAfterEvent args)
- {
- if (args.Cancelled || args.Handled)
- return;
-
- var user = args.User;
- if (!TryComp(user, out var ninja) || ninja.CalledInThreat)
- return;
-
- _ninja.CallInThreat(ninja);
- }
+ // can't predict roles or anything announcements related so only done on server.
+ protected virtual void OnTerrorDoAfter(EntityUid uid, NinjaTerrorComponent comp, TerrorDoAfterEvent args) { }
private void ClientPopup(string msg, EntityUid user, PopupType type = PopupType.Small)
{
if (_net.IsClient)
- _popups.PopupEntity(msg, user, user, type);
+ Popups.PopupEntity(msg, user, user, type);
}
}
diff --git a/Content.Shared/Ninja/Systems/NinjaSystem.cs b/Content.Shared/Ninja/Systems/NinjaSystem.cs
index d1b51ad77c..1097db7f67 100644
--- a/Content.Shared/Ninja/Systems/NinjaSystem.cs
+++ b/Content.Shared/Ninja/Systems/NinjaSystem.cs
@@ -48,21 +48,6 @@ public abstract class SharedNinjaSystem : EntitySystem
comp.Katana = katana;
}
- // TODO: remove when objective stuff moved into objectives somehow
- public void DetonateSpiderCharge(NinjaComponent comp)
- {
- comp.SpiderChargeDetonated = true;
- }
-
- ///
- /// Marks the objective as complete.
- /// On server, makes announcement and adds rule of random threat.
- ///
- public virtual void CallInThreat(NinjaComponent comp)
- {
- comp.CalledInThreat = true;
- }
-
///
/// Drain power from a target battery into the ninja's suit battery.
/// Serverside only.
@@ -71,17 +56,6 @@ public abstract class SharedNinjaSystem : EntitySystem
{
}
- ///
- /// Download the given set of nodes, returning how many new nodes were downloaded.'
- ///
- public int Download(NinjaComponent ninja, List ids)
- {
- var oldCount = ninja.DownloadedNodes.Count;
- ninja.DownloadedNodes.UnionWith(ids);
- var newCount = ninja.DownloadedNodes.Count;
- return newCount - oldCount;
- }
-
///
/// Gets the user's battery and tries to use some charge from it, returning true if successful.
/// Serverside only.
diff --git a/Resources/Prototypes/Objectives/ninjaObjectives.yml b/Resources/Prototypes/Objectives/ninjaObjectives.yml
index d2e1fa4068..8b8208cffa 100644
--- a/Resources/Prototypes/Objectives/ninjaObjectives.yml
+++ b/Resources/Prototypes/Objectives/ninjaObjectives.yml
@@ -2,7 +2,7 @@
id: DownloadObjective
issuer: spiderclan
requirements:
- - !type:TraitorRequirement {}
+ - !type:NinjaRequirement {}
conditions:
- !type:DownloadCondition {}
@@ -10,7 +10,7 @@
id: DoorjackObjective
issuer: spiderclan
requirements:
- - !type:TraitorRequirement {}
+ - !type:NinjaRequirement {}
conditions:
- !type:DoorjackCondition {}
@@ -18,7 +18,7 @@
id: SpiderChargeObjective
issuer: spiderclan
requirements:
- - !type:TraitorRequirement {}
+ - !type:NinjaRequirement {}
conditions:
- !type:SpiderChargeCondition {}
@@ -26,7 +26,7 @@
id: TerrorObjective
issuer: spiderclan
requirements:
- - !type:TraitorRequirement {}
+ - !type:NinjaRequirement {}
conditions:
- !type:TerrorCondition {}
@@ -34,6 +34,6 @@
id: SurviveObjective
issuer: spiderclan
requirements:
- - !type:TraitorRequirement {}
+ - !type:NinjaRequirement {}
conditions:
- !type:SurviveCondition {}