mirror of
https://github.com/WWhiteDreamProject/wwdpublic.git
synced 2026-04-17 21:48:58 +03:00
# Description Prevents entities who are Pacified (through the Pacifist trait or being a thief) from throwing items that deal damage on hit or embed. ## Technical Details Two components will prevent throwing if they deal any damage: `DamageOtherOnHitComponent` and `EmbedPassiveComponent`. The pacifist check on `EmbeddableProjectileComponent` has been removed, because just because an item is embeddable does not mean they deal damage. ## Media **Throw attempt with the Pacifist trait**  # Changelog 🆑 Skubman - fix: Pacified characters (Pacifist trait and thieves) can no longer throw items that deal throwing damage. --------- Signed-off-by: VMSolidus <evilexecutive@gmail.com> Co-authored-by: VMSolidus <evilexecutive@gmail.com> (cherry picked from commit 71e3c031750db523f8fcccc4a36a61200b1028f2)
128 lines
5.2 KiB
C#
128 lines
5.2 KiB
C#
using Content.Shared.CombatMode.Pacification;
|
|
using Content.Shared.Damage;
|
|
using Content.Shared.Damage.Components;
|
|
using Content.Shared.Damage.Events;
|
|
using Content.Shared.Item.ItemToggle.Components;
|
|
using Content.Shared.Mobs;
|
|
using Content.Shared.Mobs.Systems;
|
|
using Content.Shared.Mobs.Components;
|
|
using Content.Shared.FixedPoint;
|
|
using Robust.Shared.Timing;
|
|
|
|
namespace Content.Shared.Projectiles;
|
|
|
|
public sealed class EmbedPassiveDamageSystem : EntitySystem
|
|
{
|
|
[Dependency] private readonly DamageableSystem _damageable = default!;
|
|
[Dependency] private readonly IGameTiming _timing = default!;
|
|
|
|
public override void Initialize()
|
|
{
|
|
base.Initialize();
|
|
|
|
SubscribeLocalEvent<EmbedPassiveDamageComponent, DamageOtherOnHitStartupEvent>(OnDamageOtherOnHitStartup);
|
|
SubscribeLocalEvent<ItemToggleEmbedPassiveDamageComponent, ItemToggleDamageOtherOnHitStartupEvent>(OnItemToggleStartup);
|
|
SubscribeLocalEvent<EmbedPassiveDamageComponent, EmbedEvent>(OnEmbed);
|
|
SubscribeLocalEvent<EmbedPassiveDamageComponent, RemoveEmbedEvent>(OnRemoveEmbed);
|
|
SubscribeLocalEvent<EmbedPassiveDamageComponent, ItemToggledEvent>(OnItemToggle);
|
|
SubscribeLocalEvent<EmbedPassiveDamageComponent, AttemptPacifiedThrowEvent>(OnAttemptPacifiedThrow);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Inherit stats from DamageOtherOnHit.
|
|
/// </summary>
|
|
private void OnDamageOtherOnHitStartup(EntityUid uid, EmbedPassiveDamageComponent component, DamageOtherOnHitStartupEvent args)
|
|
{
|
|
if (component.Damage.Empty)
|
|
component.Damage = args.Weapon.Comp.Damage * component.ThrowingDamageMultiplier;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Inherit stats from ItemToggleDamageOtherOnHit.
|
|
/// </summary>
|
|
private void OnItemToggleStartup(EntityUid uid, ItemToggleEmbedPassiveDamageComponent component, ItemToggleDamageOtherOnHitStartupEvent args)
|
|
{
|
|
if (!TryComp<EmbedPassiveDamageComponent>(uid, out var embedPassiveDamage) ||
|
|
component.ActivatedDamage != null ||
|
|
!(args.Weapon.Comp.ActivatedDamage is {} activatedDamage))
|
|
return;
|
|
|
|
component.ActivatedDamage = activatedDamage * embedPassiveDamage.ThrowingDamageMultiplier;
|
|
}
|
|
|
|
private void OnEmbed(EntityUid uid, EmbedPassiveDamageComponent component, EmbedEvent args)
|
|
{
|
|
if (component.Damage.Empty || component.Damage.GetTotal() == 0 ||
|
|
!TryComp<MobStateComponent>(args.Embedded, out var mobState) ||
|
|
!TryComp<DamageableComponent>(args.Embedded, out var damageable))
|
|
return;
|
|
|
|
component.Embedded = args.Embedded;
|
|
component.EmbeddedDamageable = damageable;
|
|
component.EmbeddedMobState = mobState;
|
|
component.EmbeddedBodyPart = args.BodyPart;
|
|
component.NextDamage = _timing.CurTime + TimeSpan.FromSeconds(1f);
|
|
|
|
Dirty(uid, component);
|
|
}
|
|
|
|
private void OnRemoveEmbed(EntityUid uid, EmbedPassiveDamageComponent component, RemoveEmbedEvent args)
|
|
{
|
|
component.Embedded = null;
|
|
component.EmbeddedDamageable = null;
|
|
component.EmbeddedMobState = null;
|
|
component.EmbeddedBodyPart = null;
|
|
component.NextDamage = TimeSpan.Zero;
|
|
|
|
Dirty(uid, component);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Used to update the EmbedPassiveDamageComponent component on item toggle.
|
|
/// </summary>
|
|
private void OnItemToggle(EntityUid uid, EmbedPassiveDamageComponent component, ItemToggledEvent args)
|
|
{
|
|
if (!TryComp<ItemToggleEmbedPassiveDamageComponent>(uid, out var itemTogglePassiveDamage))
|
|
return;
|
|
|
|
if (args.Activated && itemTogglePassiveDamage.ActivatedDamage is {} activatedDamage)
|
|
{
|
|
itemTogglePassiveDamage.DeactivatedDamage ??= component.Damage;
|
|
component.Damage = activatedDamage;
|
|
}
|
|
else if (itemTogglePassiveDamage.DeactivatedDamage is {} deactivatedDamage)
|
|
component.Damage = deactivatedDamage;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Prevent Pacified entities from throwing items that deal passive damage when embedded.
|
|
/// </summary>
|
|
private void OnAttemptPacifiedThrow(EntityUid uid, EmbedPassiveDamageComponent comp, ref AttemptPacifiedThrowEvent args)
|
|
{
|
|
// Allow healing projectiles, forbid any that do damage
|
|
if (comp.Damage.AnyPositive())
|
|
args.Cancel("pacified-cannot-throw");
|
|
}
|
|
|
|
public override void Update(float frameTime)
|
|
{
|
|
base.Update(frameTime);
|
|
var curTime = _timing.CurTime;
|
|
|
|
var query = EntityQueryEnumerator<EmbedPassiveDamageComponent>();
|
|
while (query.MoveNext(out var uid, out var comp))
|
|
{
|
|
if (comp.Embedded is null ||
|
|
comp.EmbeddedDamageable is null ||
|
|
comp.NextDamage > curTime || // Make sure they're up for a damage tick
|
|
comp.EmbeddedMobState is null ||
|
|
comp.EmbeddedMobState.CurrentState == MobState.Dead) // Don't damage dead mobs, they've already gone through too much
|
|
continue;
|
|
|
|
comp.NextDamage = curTime + TimeSpan.FromSeconds(1f);
|
|
|
|
_damageable.TryChangeDamage(comp.Embedded, comp.Damage, false, false, comp.EmbeddedDamageable, targetPart: comp.EmbeddedBodyPart);
|
|
}
|
|
}
|
|
}
|