using Content.Shared.Actions;
using Content.Shared.Alert;
using Content.Shared.IdentityManagement;
using Content.Shared.Interaction.Events;
using Content.Shared.Popups;
using Content.Shared.Throwing;
namespace Content.Shared.CombatMode.Pacification;
///
/// Raised when a Pacified entity attempts to throw something.
/// The throw is only permitted if this event is not cancelled.
///
[ByRefEvent]
public struct AttemptPacifiedThrowEvent
{
public EntityUid ItemUid;
public EntityUid PlayerUid;
public AttemptPacifiedThrowEvent(EntityUid itemUid, EntityUid playerUid)
{
ItemUid = itemUid;
PlayerUid = playerUid;
}
public bool Cancelled { get; private set; } = false;
public string? CancelReasonMessageId { get; private set; }
///
/// Localization string ID for the reason this event has been cancelled.
/// If null, a generic message will be shown to the player.
/// Note that any supplied localization string MUST accept a '$projectile'
/// parameter specifying the name of the thrown entity.
///
public void Cancel(string? reasonMessageId = null)
{
Cancelled = true;
CancelReasonMessageId = reasonMessageId;
}
}
public sealed class PacificationSystem : EntitySystem
{
[Dependency] private readonly AlertsSystem _alertsSystem = default!;
[Dependency] private readonly SharedActionsSystem _actionsSystem = default!;
[Dependency] private readonly SharedCombatModeSystem _combatSystem = default!;
[Dependency] private readonly SharedPopupSystem _popup = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent(OnStartup);
SubscribeLocalEvent(OnShutdown);
SubscribeLocalEvent(OnBeforeThrow);
SubscribeLocalEvent(OnAttackAttempt);
}
private void OnAttackAttempt(EntityUid uid, PacifiedComponent component, AttackAttemptEvent args)
{
args.Cancel();
}
private void OnStartup(EntityUid uid, PacifiedComponent component, ComponentStartup args)
{
if (!TryComp(uid, out var combatMode))
return;
if (combatMode.CanDisarm != null)
_combatSystem.SetCanDisarm(uid, false, combatMode);
_combatSystem.SetInCombatMode(uid, false, combatMode);
_actionsSystem.SetEnabled(combatMode.CombatToggleActionEntity, false);
_alertsSystem.ShowAlert(uid, AlertType.Pacified);
}
private void OnShutdown(EntityUid uid, PacifiedComponent component, ComponentShutdown args)
{
if (!TryComp(uid, out var combatMode))
return;
if (combatMode.CanDisarm != null)
_combatSystem.SetCanDisarm(uid, true, combatMode);
_actionsSystem.SetEnabled(combatMode.CombatToggleActionEntity, true);
_alertsSystem.ClearAlert(uid, AlertType.Pacified);
}
private void OnBeforeThrow(Entity ent, ref BeforeThrowEvent args)
{
var thrownItem = args.ItemUid;
var itemName = Identity.Entity(thrownItem, EntityManager);
// Raise an AttemptPacifiedThrow event and rely on other systems to check
// whether the candidate item is OK to throw:
var ev = new AttemptPacifiedThrowEvent(thrownItem, ent);
RaiseLocalEvent(thrownItem, ref ev);
if (!ev.Cancelled)
return;
args.Cancelled = true;
// Tell the player why they can’t throw stuff:
var cannotThrowMessage = ev.CancelReasonMessageId ?? "pacified-cannot-throw";
_popup.PopupEntity(Loc.GetString(cannotThrowMessage, ("projectile", itemName)), ent, ent);
}
}