Use conditions to store progress for Ninja objectives (#20254)
* TryGetObjectiveComp * helper function to get objective * store N of jacked doors in condition * store called in threat bool in condition * store techs in steal research condition * fix access * remove unused transform system * use popup from shared system * fix formatting * condition => obj everywhere * i fogror to remove downloaded nodes from role * change signature * use query * View Variables * spider charge detonated => condition
This commit is contained in:
@@ -1,16 +1,10 @@
|
||||
using Content.Server.Communications;
|
||||
using Content.Server.DoAfter;
|
||||
using Content.Server.Mind;
|
||||
using Content.Server.Ninja.Events;
|
||||
using Content.Server.Power.Components;
|
||||
using Content.Server.Roles;
|
||||
using Content.Server.Objectives.Components;
|
||||
using Content.Shared.Communications;
|
||||
using Content.Shared.DoAfter;
|
||||
using Content.Shared.Interaction.Components;
|
||||
using Content.Shared.Interaction.Events;
|
||||
using Content.Shared.Ninja.Components;
|
||||
using Content.Shared.Ninja.Systems;
|
||||
using Content.Shared.Popups;
|
||||
using Content.Shared.Research.Components;
|
||||
using Content.Shared.Toggleable;
|
||||
|
||||
@@ -94,7 +88,7 @@ public sealed class NinjaGlovesSystem : SharedNinjaGlovesSystem
|
||||
|
||||
EnsureComp<ResearchStealerComponent>(user);
|
||||
// prevent calling in multiple threats by toggling gloves after
|
||||
if (_mind.TryGetRole<NinjaRoleComponent>(user, out var role) && !role.CalledInThreat)
|
||||
if (_mind.TryGetObjectiveComp<TerrorConditionComponent>(user, out var obj) && !obj.CalledInThreat)
|
||||
{
|
||||
var hacker = EnsureComp<CommsHackerComponent>(user);
|
||||
var rule = _ninja.NinjaRule(user);
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
using Content.Server.Administration.Commands;
|
||||
using Content.Server.Communications;
|
||||
using Content.Server.Chat.Managers;
|
||||
using Content.Server.StationEvents.Components;
|
||||
using Content.Server.GameTicking;
|
||||
using Content.Server.GameTicking.Rules;
|
||||
using Content.Server.GameTicking.Rules.Components;
|
||||
using Content.Server.Ghost.Roles.Events;
|
||||
using Content.Server.Objectives;
|
||||
using Content.Server.Power.Components;
|
||||
using Content.Server.Power.EntitySystems;
|
||||
using Content.Server.PowerCell;
|
||||
@@ -23,16 +19,12 @@ using Content.Shared.Mind.Components;
|
||||
using Content.Shared.Ninja.Components;
|
||||
using Content.Shared.Ninja.Systems;
|
||||
using Content.Shared.Popups;
|
||||
using Content.Shared.Roles;
|
||||
using Content.Shared.PowerCell.Components;
|
||||
using Content.Shared.Rounding;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Physics.Components;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Random;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using Content.Server.Objectives.Components;
|
||||
|
||||
namespace Content.Server.Ninja.Systems;
|
||||
|
||||
@@ -57,8 +49,6 @@ public sealed class SpaceNinjaSystem : SharedSpaceNinjaSystem
|
||||
[Dependency] private readonly RoleSystem _role = default!;
|
||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||
[Dependency] private readonly SharedMindSystem _mind = default!;
|
||||
[Dependency] private readonly SharedPopupSystem _popup = default!;
|
||||
[Dependency] private readonly SharedTransformSystem _transform = default!;
|
||||
[Dependency] private readonly StealthClothingSystem _stealthClothing = default!;
|
||||
|
||||
public override void Initialize()
|
||||
@@ -85,12 +75,12 @@ public sealed class SpaceNinjaSystem : SharedSpaceNinjaSystem
|
||||
/// </summary>
|
||||
private int Download(EntityUid uid, List<string> ids)
|
||||
{
|
||||
if (!_mind.TryGetRole<NinjaRoleComponent>(uid, out var role))
|
||||
if (!_mind.TryGetObjectiveComp<StealResearchConditionComponent>(uid, out var obj))
|
||||
return 0;
|
||||
|
||||
var oldCount = role.DownloadedNodes.Count;
|
||||
role.DownloadedNodes.UnionWith(ids);
|
||||
var newCount = role.DownloadedNodes.Count;
|
||||
var oldCount = obj.DownloadedNodes.Count;
|
||||
obj.DownloadedNodes.UnionWith(ids);
|
||||
var newCount = obj.DownloadedNodes.Count;
|
||||
return newCount - oldCount;
|
||||
}
|
||||
|
||||
@@ -205,7 +195,7 @@ public sealed class SpaceNinjaSystem : SharedSpaceNinjaSystem
|
||||
if (ninja.Suit == null)
|
||||
return;
|
||||
|
||||
float wattage = _suit.SuitWattage(ninja.Suit.Value);
|
||||
float wattage = Suit.SuitWattage(ninja.Suit.Value);
|
||||
|
||||
SetSuitPowerAlert(uid, ninja);
|
||||
if (!TryUseCharge(uid, wattage * frameTime))
|
||||
@@ -225,11 +215,11 @@ public sealed class SpaceNinjaSystem : SharedSpaceNinjaSystem
|
||||
return;
|
||||
|
||||
// this popup is serverside since door emag logic is serverside (power funnies)
|
||||
_popup.PopupEntity(Loc.GetString("ninja-doorjack-success", ("target", Identity.Entity(args.Target, EntityManager))), uid, uid, PopupType.Medium);
|
||||
Popup.PopupEntity(Loc.GetString("ninja-doorjack-success", ("target", Identity.Entity(args.Target, EntityManager))), uid, uid, PopupType.Medium);
|
||||
|
||||
// handle greentext
|
||||
if (_mind.TryGetRole<NinjaRoleComponent>(uid, out var role))
|
||||
role.DoorsJacked++;
|
||||
if (_mind.TryGetObjectiveComp<DoorjackConditionComponent>(uid, out var obj))
|
||||
obj.DoorsJacked++;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -242,14 +232,14 @@ public sealed class SpaceNinjaSystem : SharedSpaceNinjaSystem
|
||||
? Loc.GetString("ninja-research-steal-fail")
|
||||
: Loc.GetString("ninja-research-steal-success", ("count", gained), ("server", args.Target));
|
||||
|
||||
_popup.PopupEntity(str, uid, uid, PopupType.Medium);
|
||||
Popup.PopupEntity(str, uid, uid, PopupType.Medium);
|
||||
}
|
||||
|
||||
private void OnThreatCalledIn(EntityUid uid, SpaceNinjaComponent comp, ref ThreatCalledInEvent args)
|
||||
{
|
||||
if (_mind.TryGetRole<NinjaRoleComponent>(uid, out var role))
|
||||
if (_mind.TryGetObjectiveComp<TerrorConditionComponent>(uid, out var obj))
|
||||
{
|
||||
role.CalledInThreat = true;
|
||||
obj.CalledInThreat = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Content.Server.Explosion.EntitySystems;
|
||||
using Content.Server.Mind;
|
||||
using Content.Server.Objectives.Components;
|
||||
using Content.Server.Popups;
|
||||
using Content.Server.Roles;
|
||||
using Content.Server.Sticky.Events;
|
||||
@@ -69,10 +70,10 @@ public sealed class SpiderChargeSystem : EntitySystem
|
||||
/// </summary>
|
||||
private void OnExplode(EntityUid uid, SpiderChargeComponent comp, TriggerEvent args)
|
||||
{
|
||||
if (comp.Planter == null || !_mind.TryGetRole<NinjaRoleComponent>(comp.Planter.Value, out var role))
|
||||
if (comp.Planter == null || !_mind.TryGetObjectiveComp<SpiderChargeConditionComponent>(comp.Planter.Value, out var obj))
|
||||
return;
|
||||
|
||||
// assumes the target was destroyed, that the charge wasn't moved somehow
|
||||
role.SpiderChargeDetonated = true;
|
||||
obj.SpiderChargeDetonated = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Content.Server.Objectives.Systems;
|
||||
using Content.Shared.Ninja.Systems;
|
||||
|
||||
namespace Content.Server.Objectives.Components;
|
||||
|
||||
@@ -6,7 +7,9 @@ namespace Content.Server.Objectives.Components;
|
||||
/// Objective condition that requires the player to be a ninja and have doorjacked at least a random number of airlocks.
|
||||
/// Requires <see cref="NumberObjectiveComponent"/> to function.
|
||||
/// </summary>
|
||||
[RegisterComponent, Access(typeof(NinjaConditionsSystem))]
|
||||
[RegisterComponent, Access(typeof(NinjaConditionsSystem), typeof(SharedSpaceNinjaSystem))]
|
||||
public sealed partial class DoorjackConditionComponent : Component
|
||||
{
|
||||
[DataField("doorsJacked"), ViewVariables(VVAccess.ReadWrite)]
|
||||
public int DoorsJacked;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using Content.Server.Ninja.Systems;
|
||||
using Content.Server.Objectives.Systems;
|
||||
|
||||
namespace Content.Server.Objectives.Components;
|
||||
@@ -5,7 +6,9 @@ namespace Content.Server.Objectives.Components;
|
||||
/// <summary>
|
||||
/// Requires that the player is a ninja and blew up their spider charge at its target location.
|
||||
/// </summary>
|
||||
[RegisterComponent, Access(typeof(NinjaConditionsSystem))]
|
||||
[RegisterComponent, Access(typeof(NinjaConditionsSystem), typeof(SpiderChargeSystem))]
|
||||
public sealed partial class SpiderChargeConditionComponent : Component
|
||||
{
|
||||
[DataField("spiderChargeDetonated"), ViewVariables(VVAccess.ReadWrite)]
|
||||
public bool SpiderChargeDetonated;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Content.Server.Objectives.Systems;
|
||||
using Content.Shared.Ninja.Systems;
|
||||
|
||||
namespace Content.Server.Objectives.Components;
|
||||
|
||||
@@ -6,7 +7,9 @@ namespace Content.Server.Objectives.Components;
|
||||
/// Objective condition that requires the player to be a ninja and have stolen at least a random number of technologies.
|
||||
/// Requires <see cref="NumberObjectiveComponent"/> to function.
|
||||
/// </summary>
|
||||
[RegisterComponent, Access(typeof(NinjaConditionsSystem))]
|
||||
[RegisterComponent, Access(typeof(NinjaConditionsSystem), typeof(SharedSpaceNinjaSystem))]
|
||||
public sealed partial class StealResearchConditionComponent : Component
|
||||
{
|
||||
[DataField("downloadedNodes"), ViewVariables(VVAccess.ReadWrite)]
|
||||
public HashSet<string> DownloadedNodes = new();
|
||||
}
|
||||
|
||||
@@ -1,11 +1,17 @@
|
||||
using Content.Server.Objectives.Systems;
|
||||
using Content.Shared.Ninja.Systems;
|
||||
|
||||
namespace Content.Server.Objectives.Components;
|
||||
|
||||
/// <summary>
|
||||
/// Requires that the player is a ninja and has called in a threat.
|
||||
/// </summary>
|
||||
[RegisterComponent, Access(typeof(NinjaConditionsSystem))]
|
||||
[RegisterComponent, Access(typeof(NinjaConditionsSystem), typeof(SharedSpaceNinjaSystem))]
|
||||
public sealed partial class TerrorConditionComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// Whether the comms console has been hacked
|
||||
/// </summary>
|
||||
[DataField("calledInThreat"), ViewVariables(VVAccess.ReadWrite)]
|
||||
public bool CalledInThreat;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ using Content.Server.Roles;
|
||||
using Content.Server.Objectives.Components;
|
||||
using Content.Server.Warps;
|
||||
using Content.Shared.Objectives.Components;
|
||||
using Robust.Shared.GameObjects;
|
||||
|
||||
namespace Content.Server.Objectives.Systems;
|
||||
|
||||
@@ -31,22 +30,16 @@ public sealed class NinjaConditionsSystem : EntitySystem
|
||||
|
||||
private void OnDoorjackGetProgress(EntityUid uid, DoorjackConditionComponent comp, ref ObjectiveGetProgressEvent args)
|
||||
{
|
||||
args.Progress = DoorjackProgress(args.MindId, _number.GetTarget(uid));
|
||||
args.Progress = DoorjackProgress(comp, _number.GetTarget(uid));
|
||||
}
|
||||
|
||||
private float DoorjackProgress(EntityUid mindId, int target)
|
||||
private float DoorjackProgress(DoorjackConditionComponent comp, int target)
|
||||
{
|
||||
// prevent divide-by-zero
|
||||
if (target == 0)
|
||||
return 1f;
|
||||
|
||||
if (!TryComp<NinjaRoleComponent>(mindId, out var role))
|
||||
return 0f;
|
||||
|
||||
if (role.DoorsJacked >= target)
|
||||
return 1f;
|
||||
|
||||
return (float) role.DoorsJacked / (float) target;
|
||||
return MathF.Min(comp.DoorsJacked / (float) target, 1f);
|
||||
}
|
||||
|
||||
// spider charge
|
||||
@@ -58,7 +51,7 @@ public sealed class NinjaConditionsSystem : EntitySystem
|
||||
|
||||
private void OnSpiderChargeGetProgress(EntityUid uid, SpiderChargeConditionComponent comp, ref ObjectiveGetProgressEvent args)
|
||||
{
|
||||
args.Progress = TryComp<NinjaRoleComponent>(args.MindId, out var role) && role.SpiderChargeDetonated ? 1f : 0f;
|
||||
args.Progress = comp.SpiderChargeDetonated ? 1f : 0f;
|
||||
}
|
||||
|
||||
private string SpiderChargeTitle(EntityUid mindId)
|
||||
@@ -79,28 +72,20 @@ public sealed class NinjaConditionsSystem : EntitySystem
|
||||
|
||||
private void OnStealResearchGetProgress(EntityUid uid, StealResearchConditionComponent comp, ref ObjectiveGetProgressEvent args)
|
||||
{
|
||||
args.Progress = StealResearchProgress(args.MindId, _number.GetTarget(uid));
|
||||
args.Progress = StealResearchProgress(comp, _number.GetTarget(uid));
|
||||
}
|
||||
|
||||
private float StealResearchProgress(EntityUid mindId, int target)
|
||||
private float StealResearchProgress(StealResearchConditionComponent comp, int target)
|
||||
{
|
||||
// prevent divide-by-zero
|
||||
if (target == 0)
|
||||
return 1f;
|
||||
|
||||
if (!TryComp<NinjaRoleComponent>(mindId, out var role))
|
||||
return 0f;
|
||||
|
||||
if (role.DownloadedNodes.Count >= target)
|
||||
return 1f;
|
||||
|
||||
return (float) role.DownloadedNodes.Count / (float) target;
|
||||
return MathF.Min(comp.DownloadedNodes.Count / (float) target, 1f);
|
||||
}
|
||||
|
||||
// terror
|
||||
|
||||
private void OnTerrorGetProgress(EntityUid uid, TerrorConditionComponent comp, ref ObjectiveGetProgressEvent args)
|
||||
{
|
||||
args.Progress = TryComp<NinjaRoleComponent>(args.MindId, out var role) && role.CalledInThreat ? 1f : 0f;
|
||||
args.Progress = comp.CalledInThreat ? 1f : 0f;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,33 +8,9 @@ namespace Content.Server.Roles;
|
||||
[RegisterComponent]
|
||||
public sealed partial class NinjaRoleComponent : AntagonistRoleComponent
|
||||
{
|
||||
/// <summary>
|
||||
/// Number of doors that have been doorjacked, used for objective
|
||||
/// </summary>
|
||||
[DataField("doorsJacked")]
|
||||
public int DoorsJacked;
|
||||
|
||||
/// <summary>
|
||||
/// Research nodes that have been downloaded, used for objective
|
||||
/// </summary>
|
||||
[DataField("downloadedNodes")]
|
||||
public HashSet<string> DownloadedNodes = new();
|
||||
|
||||
/// <summary>
|
||||
/// Warp point that the spider charge has to target
|
||||
/// </summary>
|
||||
[DataField("spiderChargeTarget")]
|
||||
public EntityUid? SpiderChargeTarget;
|
||||
|
||||
/// <summary>
|
||||
/// Whether the spider charge has been detonated on the target, used for objective
|
||||
/// </summary>
|
||||
[DataField("spiderChargeDetonated")]
|
||||
public bool SpiderChargeDetonated;
|
||||
|
||||
/// <summary>
|
||||
/// Whether the comms console has been hacked, used for objective
|
||||
/// </summary>
|
||||
[DataField("calledInThreat")]
|
||||
public bool CalledInThreat;
|
||||
}
|
||||
|
||||
@@ -292,6 +292,33 @@ public abstract class SharedMindSystem : EntitySystem
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool TryGetObjectiveComp<T>(EntityUid uid, [NotNullWhen(true)] out T? objective) where T : Component
|
||||
{
|
||||
if (TryGetMind(uid, out var mindId, out var mind) && TryGetObjectiveComp(mindId, out objective, mind))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
objective = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool TryGetObjectiveComp<T>(EntityUid mindId, [NotNullWhen(true)] out T? objective, MindComponent? mind = null) where T : Component
|
||||
{
|
||||
if (Resolve(mindId, ref mind))
|
||||
{
|
||||
var query = GetEntityQuery<T>();
|
||||
foreach (var uid in mind.AllObjectives)
|
||||
{
|
||||
if (query.TryGetComponent(uid, out objective))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
objective = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool TryGetSession(EntityUid? mindId, [NotNullWhen(true)] out ICommonSession? session)
|
||||
{
|
||||
session = null;
|
||||
|
||||
@@ -11,8 +11,8 @@ namespace Content.Shared.Ninja.Systems;
|
||||
/// </summary>
|
||||
public abstract class SharedSpaceNinjaSystem : EntitySystem
|
||||
{
|
||||
[Dependency] protected readonly SharedNinjaSuitSystem _suit = default!;
|
||||
[Dependency] protected readonly SharedPopupSystem _popup = default!;
|
||||
[Dependency] protected readonly SharedNinjaSuitSystem Suit = default!;
|
||||
[Dependency] protected readonly SharedPopupSystem Popup = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -74,7 +74,7 @@ public abstract class SharedSpaceNinjaSystem : EntitySystem
|
||||
{
|
||||
if (comp.Suit != null && TryComp<StealthClothingComponent>(comp.Suit, out var stealthClothing) && stealthClothing.Enabled)
|
||||
{
|
||||
_suit.RevealNinja(comp.Suit.Value, uid, null, stealthClothing);
|
||||
Suit.RevealNinja(comp.Suit.Value, uid, null, stealthClothing);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ public abstract class SharedSpaceNinjaSystem : EntitySystem
|
||||
/// </summary>
|
||||
private void OnShotAttempted(EntityUid uid, SpaceNinjaComponent comp, ref ShotAttemptedEvent args)
|
||||
{
|
||||
_popup.PopupClient(Loc.GetString("gun-disabled"), uid, uid);
|
||||
Popup.PopupClient(Loc.GetString("gun-disabled"), uid, uid);
|
||||
args.Cancel();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user