decelerator nerf and projectile penetration mini refactor (#24032)

* decelerator nerf and projectile fix

* datafield name difference

* forgot to add component

* missed datafield styling

* comment made summary

* CanPenetrateComponent and CollisionLayer check.

* Small comment changes
This commit is contained in:
Arendian
2024-01-15 00:39:09 +01:00
committed by GitHub
parent f9a57dc11e
commit 04a8761bb6
7 changed files with 154 additions and 38 deletions

View File

@@ -4,12 +4,14 @@ using Content.Shared.Damage;
using Content.Shared.DoAfter;
using Content.Shared.Hands.EntitySystems;
using Content.Shared.Interaction;
using Content.Shared.Mobs.Components;
using Content.Shared.Throwing;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Map;
using Robust.Shared.Network;
using Robust.Shared.Physics;
using Robust.Shared.Physics.Components;
using Robust.Shared.Physics.Dynamics;
using Robust.Shared.Physics.Events;
using Robust.Shared.Physics.Systems;
using Robust.Shared.Serialization;
@@ -32,6 +34,7 @@ public abstract partial class SharedProjectileSystem : EntitySystem
base.Initialize();
SubscribeLocalEvent<ProjectileComponent, PreventCollideEvent>(PreventCollision);
SubscribeLocalEvent<ProjectileComponent, AfterProjectileHitEvent>(AfterProjectileHit);
SubscribeLocalEvent<EmbeddableProjectileComponent, ProjectileHitEvent>(OnEmbedProjectileHit);
SubscribeLocalEvent<EmbeddableProjectileComponent, ThrowDoHitEvent>(OnEmbedThrowDoHit);
SubscribeLocalEvent<EmbeddableProjectileComponent, ActivateInWorldEvent>(OnEmbedActivate);
@@ -160,6 +163,45 @@ public abstract partial class SharedProjectileSystem : EntitySystem
{
args.Cancel("pacified-cannot-throw-embed");
}
/// <summary>
/// Checks if the projectile is allowed to penetrate the target it hit.
/// </summary>
private void AfterProjectileHit(EntityUid uid, ProjectileComponent component, ref AfterProjectileHitEvent args)
{
if (!TryComp<CanPenetrateComponent>(uid, out var damageAfterCollide))
return;
//Delete the projectile if it hits an entity with a CollisionLayer that has a higher value than it's PenetrationLayer.
//This allows a projectile to only penetrate a specific set of entities.
if (damageAfterCollide.PenetrationLayer != null)
{
if (args.Fixture.CollisionLayer > (int) damageAfterCollide.PenetrationLayer ||
damageAfterCollide.PenetrationPower == 0)
{
QueueDel(uid);
return;
}
}
//Allow the projectile to deal damage again.
if(damageAfterCollide.DamageAfterCollide)
component.DamagedEntity = false;
//If the projectile has a limit on the amount of penetrations, reduce it.
if (damageAfterCollide.PenetrationPower != null)
damageAfterCollide.PenetrationPower -= 1;
//Apply the penetration damage modifier if the projectile has one.
if (damageAfterCollide.DamageModifier != null)
component.Damage *= damageAfterCollide.DamageModifier.Value;
//Overrides the original DeleteOnCollide if the projectile passes all penetration checks.
//This is to prevent having to set DeleteOnCollide to false on every prototype
//you want to give the ability to penetrate entities.
if(component.DeleteOnCollide)
component.DeleteOnCollide = false;
}
}
[Serializable, NetSerializable]
@@ -186,3 +228,9 @@ public record struct ProjectileReflectAttemptEvent(EntityUid ProjUid, Projectile
/// </summary>
[ByRefEvent]
public record struct ProjectileHitEvent(DamageSpecifier Damage, EntityUid Target, EntityUid? Shooter = null);
/// <summary>
/// Raised after a projectile has dealt it's damage.
/// </summary>
[ByRefEvent]
public record struct AfterProjectileHitEvent(DamageSpecifier Damage, EntityUid Target, Fixture Fixture);