Cleanup ExecutionSystem (#24382)

* Creat Execution Component and add to sharp items

* Kill Server ExecutionSystem. Create ExecutionSystem in shared. Create ActiveExecution Component.
Transferred the Execution system into shared. Heavily re-wrote the system in order to reduce duplication,
and remove gun code from the system.
The melee weapon modifier which was dependant on swing rate was removed.

The ActiveExecutionComponent was created in order to apply the damage modifier to the shot from a gun execution.
It is added just before the gun fires and removed after an attempt is made.

* Fix bugs

The execution completed text will now only show up if the gun fires.

The client also no longer crashes because I forgot to network the component.

* Remove clumsy text

* Make BaseSword abstract

* Add ExecutionComponent to every weapon

* Fix bug

* Remove execution comp from battery weapons

Currently the gun system does not have a way to alter hitscan damage like it does with projectiles.

* Cleanup

* Revert "Remove clumsy text"

This reverts commit a46da6448d5d179a4e936f9213d5622bedb58a16.

* Actually fix the ExecutionSystem

Everything about the shot goes through the gun system now.
The Damage multiplier is only applied when a projectile impacts the target so people that get in the way don't get hit
with 9 times damage for no reason.

In order to make suicides work I needed to create fake EntityCoordinates because the gun system and the projectile
system do not play well with a projectile that has the same start and end position.

* Make launchers able to execute

* Fix prediction bug

The OnAmmoShotEvent is only raised on the server.

* Readd ability for clowns to accidentally shoot themselves while executing

* Cleanup

* Reset melee cooldown to initial value

* Address reviews fix bug

Addressed reviews on overriding messages.
Now I actually mark doafters as handled.
Return normal cooldown to some meleeweapons I forgot on the previous commit.

* Address Reviews

Remove duplication

* Exorcise codebase

Remove evil null coercion that I was sure I removed a while ago

* Address reviews again

* Remove melee weapon attack logic and rely on the system. Remove gun and
melee checks.

* Make system functional again and cleanup

* Remove code I forgot to remove

* Cleanup

* stalled

* Selectively revert gun penetration

The collision layer check doesn't work and I don't have time to fix it.

* Fixes

---------

Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com>
This commit is contained in:
nikthechampiongr
2024-02-25 13:07:10 +02:00
committed by GitHub
parent ec5edc3626
commit bcbe2ec1af
27 changed files with 566 additions and 478 deletions

View File

@@ -21,6 +21,7 @@ using Content.Shared.Weapons.Melee;
using Content.Shared.Weapons.Melee.Events;
using Content.Shared.Weapons.Ranged.Components;
using Content.Shared.Weapons.Ranged.Events;
using JetBrains.Annotations;
using Robust.Shared.Audio;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Containers;
@@ -143,7 +144,7 @@ public abstract partial class SharedGunSystem : EntitySystem
gun.ShootCoordinates = GetCoordinates(msg.Coordinates);
Log.Debug($"Set shoot coordinates to {gun.ShootCoordinates}");
AttemptShoot(user.Value, ent, gun);
AttemptShootInternal(user.Value, ent, gun);
}
private void OnStopShootRequest(RequestStopShootEvent ev, EntitySessionEventArgs args)
@@ -207,13 +208,38 @@ public abstract partial class SharedGunSystem : EntitySystem
Dirty(uid, gun);
}
/// <summary>
/// Attempts to shoot the specified target directly.
/// This may bypass projectiles firing etc.
/// </summary>
public bool AttemptDirectShoot(EntityUid user, EntityUid gunUid, EntityUid target, GunComponent gun)
{
// Unique name so people don't think it's "shoot towards" and not "I will teleport a bullet into them".
gun.ShootCoordinates = Transform(target).Coordinates;
if (!TryTakeAmmo(user, gunUid, gun, out _, out _, out var args))
{
gun.ShootCoordinates = null;
return false;
}
var result = ShootDirect(gunUid, gun, target, args.Ammo, user: user);
gun.ShootCoordinates = null;
return result;
}
protected virtual bool ShootDirect(EntityUid gunUid, GunComponent gun, EntityUid target, List<(EntityUid? Entity, IShootable Shootable)> ammo, EntityUid user)
{
return false;
}
/// <summary>
/// Attempts to shoot at the target coordinates. Resets the shot counter after every shot.
/// </summary>
public void AttemptShoot(EntityUid user, EntityUid gunUid, GunComponent gun, EntityCoordinates toCoordinates)
{
gun.ShootCoordinates = toCoordinates;
AttemptShoot(user, gunUid, gun);
AttemptShootInternal(user, gunUid, gun);
gun.ShotCounter = 0;
}
@@ -224,20 +250,35 @@ public abstract partial class SharedGunSystem : EntitySystem
{
var coordinates = new EntityCoordinates(gunUid, new Vector2(0, -1));
gun.ShootCoordinates = coordinates;
AttemptShoot(gunUid, gunUid, gun);
AttemptShootInternal(gunUid, gunUid, gun);
gun.ShotCounter = 0;
}
private void AttemptShoot(EntityUid user, EntityUid gunUid, GunComponent gun)
private void AttemptShootInternal(EntityUid user, EntityUid gunUid, GunComponent gun)
{
if (!TryTakeAmmo(user, gunUid, gun, out var fromCoordinates, out var toCoordinates, out var args))
return;
Shoot(gunUid, gun, args.Ammo, fromCoordinates, toCoordinates, out var userImpulse, user: user);
if (userImpulse && TryComp<PhysicsComponent>(user, out var userPhysics))
{
if (_gravity.IsWeightless(user, userPhysics))
CauseImpulse(fromCoordinates, toCoordinates, user, userPhysics);
}
}
/// <summary>
/// Validates if a gun can currently shoot.
/// </summary>
[Pure]
private bool CanShoot(EntityUid user, EntityUid gunUid, GunComponent gun)
{
if (gun.FireRateModified <= 0f ||
!_actionBlockerSystem.CanAttack(user))
return;
var toCoordinates = gun.ShootCoordinates;
if (toCoordinates == null)
return;
{
return false;
}
var curTime = Timing.CurTime;
@@ -249,17 +290,42 @@ public abstract partial class SharedGunSystem : EntitySystem
};
RaiseLocalEvent(gunUid, ref prevention);
if (prevention.Cancelled)
return;
return false;
RaiseLocalEvent(user, ref prevention);
if (prevention.Cancelled)
return;
return false;
// Need to do this to play the clicking sound for empty automatic weapons
// but not play anything for burst fire.
if (gun.NextFire > curTime)
return;
return false;
return true;
}
/// <summary>
/// Tries to return ammo prepped for shooting if a gun is available to shoot.
/// </summary>
private bool TryTakeAmmo(
EntityUid user,
EntityUid gunUid, GunComponent gun,
out EntityCoordinates fromCoordinates,
out EntityCoordinates toCoordinates,
[NotNullWhen(true)] out TakeAmmoEvent? args)
{
toCoordinates = EntityCoordinates.Invalid;
fromCoordinates = EntityCoordinates.Invalid;
args = null;
if (!CanShoot(user, gunUid, gun))
return false;
if (gun.ShootCoordinates == null)
return false;
toCoordinates = gun.ShootCoordinates.Value;
var curTime = Timing.CurTime;
var fireRate = TimeSpan.FromSeconds(1f / gun.FireRateModified);
// First shot
@@ -307,10 +373,11 @@ public abstract partial class SharedGunSystem : EntitySystem
}
gun.NextFire = TimeSpan.FromSeconds(Math.Max(lastFire.TotalSeconds + SafetyNextFire, gun.NextFire.TotalSeconds));
return;
return false;
}
var fromCoordinates = Transform(user).Coordinates;
fromCoordinates = Transform(user).Coordinates;
// Remove ammo
var ev = new TakeAmmoEvent(shots, new List<(EntityUid? Entity, IShootable Shootable)>(), fromCoordinates, user);
@@ -345,24 +412,18 @@ public abstract partial class SharedGunSystem : EntitySystem
// May cause prediction issues? Needs more tweaking
gun.NextFire = TimeSpan.FromSeconds(Math.Max(lastFire.TotalSeconds + SafetyNextFire, gun.NextFire.TotalSeconds));
Audio.PlayPredicted(gun.SoundEmpty, gunUid, user);
return;
return false;
}
return;
return false;
}
// Shoot confirmed - sounds also played here in case it's invalid (e.g. cartridge already spent).
Shoot(gunUid, gun, ev.Ammo, fromCoordinates, toCoordinates.Value, out var userImpulse, user, throwItems: attemptEv.ThrowItems);
var shotEv = new GunShotEvent(user, ev.Ammo);
RaiseLocalEvent(gunUid, ref shotEv);
if (userImpulse && TryComp<PhysicsComponent>(user, out var userPhysics))
{
if (_gravity.IsWeightless(user, userPhysics))
CauseImpulse(fromCoordinates, toCoordinates.Value, user, userPhysics);
}
Dirty(gunUid, gun);
args = ev;
return true;
}
public void Shoot(