Files
tbd-station-14/Content.Server/Objectives/Systems/StealConditionSystem.cs
deltanedas f7711edbe3 Objectives ecs rework (#19967)
Co-authored-by: deltanedas <@deltanedas:kde.org>
2023-09-16 16:18:10 +10:00

94 lines
3.7 KiB
C#

using Content.Server.Objectives.Components;
using Content.Shared.Mind;
using Content.Shared.Objectives.Components;
using Content.Shared.Objectives.Systems;
using Robust.Shared.Containers;
using Robust.Shared.Prototypes;
using Robust.Shared.Utility;
namespace Content.Server.Objectives.Systems;
public sealed class StealConditionSystem : EntitySystem
{
[Dependency] private readonly IPrototypeManager _proto = default!;
[Dependency] private readonly MetaDataSystem _metaData = default!;
[Dependency] private readonly SharedObjectivesSystem _objectives = default!;
private EntityQuery<ContainerManagerComponent> containerQuery;
private EntityQuery<MetaDataComponent> metaQuery;
public override void Initialize()
{
base.Initialize();
containerQuery = GetEntityQuery<ContainerManagerComponent>();
metaQuery = GetEntityQuery<MetaDataComponent>();
SubscribeLocalEvent<StealConditionComponent, ObjectiveAssignedEvent>(OnAssigned);
SubscribeLocalEvent<StealConditionComponent, ObjectiveAfterAssignEvent>(OnAfterAssign);
SubscribeLocalEvent<StealConditionComponent, ObjectiveGetProgressEvent>(OnGetProgress);
}
private void OnAssigned(EntityUid uid, StealConditionComponent comp, ref ObjectiveAssignedEvent args)
{
// cancel if the item to steal doesn't exist
args.Cancelled |= !_proto.HasIndex<EntityPrototype>(comp.Prototype);
}
private void OnAfterAssign(EntityUid uid, StealConditionComponent comp, ref ObjectiveAfterAssignEvent args)
{
var proto = _proto.Index<EntityPrototype>(comp.Prototype);
var title = comp.OwnerText == null
? Loc.GetString("objective-condition-steal-title-no-owner", ("itemName", proto.Name))
: Loc.GetString("objective-condition-steal-title", ("owner", Loc.GetString(comp.OwnerText)), ("itemName", proto.Name));
var description = Loc.GetString("objective-condition-steal-description", ("itemName", proto.Name));
_metaData.SetEntityName(uid, title, args.Meta);
_metaData.SetEntityDescription(uid, description, args.Meta);
_objectives.SetIcon(uid, new SpriteSpecifier.EntityPrototype(comp.Prototype), args.Objective);
}
private void OnGetProgress(EntityUid uid, StealConditionComponent comp, ref ObjectiveGetProgressEvent args)
{
args.Progress = GetProgress(args.Mind, comp.Prototype);
}
private float GetProgress(MindComponent mind, string prototype)
{
// TODO make this a container system function
// or: just iterate through transform children, instead of containers?
if (!metaQuery.TryGetComponent(mind.OwnedEntity, out var meta))
return 0;
// who added this check bruh
if (meta.EntityPrototype?.ID == prototype)
return 1;
if (!containerQuery.TryGetComponent(mind.OwnedEntity, out var currentManager))
return 0;
// recursively check each container for the item
// checks inventory, bag, implants, etc.
var stack = new Stack<ContainerManagerComponent>();
do
{
foreach (var container in currentManager.Containers.Values)
{
foreach (var entity in container.ContainedEntities)
{
// check if this is the item
if (metaQuery.GetComponent(entity).EntityPrototype?.ID == prototype)
return 1;
// if it is a container check its contents
if (containerQuery.TryGetComponent(entity, out var containerManager))
stack.Push(containerManager);
}
}
} while (stack.TryPop(out currentManager));
return 0;
}
}