Added a component that lets ranged weapons make melee attacks. (#29484)
This commit is contained in:
@@ -6,6 +6,7 @@ using Content.Shared.Hands.Components;
|
||||
using Content.Shared.Mobs.Components;
|
||||
using Content.Shared.StatusEffect;
|
||||
using Content.Shared.Weapons.Melee;
|
||||
using Content.Shared.Weapons.Melee.Components;
|
||||
using Content.Shared.Weapons.Melee.Events;
|
||||
using Content.Shared.Weapons.Ranged.Components;
|
||||
using Robust.Client.GameObjects;
|
||||
@@ -89,16 +90,6 @@ public sealed partial class MeleeWeaponSystem : SharedMeleeWeaponSystem
|
||||
|
||||
// TODO using targeted actions while combat mode is enabled should NOT trigger attacks.
|
||||
|
||||
// TODO: Need to make alt-fire melee its own component I guess?
|
||||
// Melee and guns share a lot in the middle but share virtually nothing at the start and end so
|
||||
// it's kinda tricky.
|
||||
// I think as long as we make secondaries their own component it's probably fine
|
||||
// as long as guncomp has an alt-use key then it shouldn't be too much of a PITA to deal with.
|
||||
if (TryComp<GunComponent>(weaponUid, out var gun) && gun.UseKey)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var mousePos = _eyeManager.PixelToMap(_inputManager.MouseScreenPosition);
|
||||
|
||||
if (mousePos.MapId == MapId.Nullspace)
|
||||
@@ -116,6 +107,30 @@ public sealed partial class MeleeWeaponSystem : SharedMeleeWeaponSystem
|
||||
{
|
||||
coordinates = TransformSystem.ToCoordinates(_map.GetMap(mousePos.MapId), mousePos);
|
||||
}
|
||||
|
||||
// If the gun has AltFireComponent, it can be used to attack.
|
||||
if (TryComp<GunComponent>(weaponUid, out var gun) && gun.UseKey)
|
||||
{
|
||||
if (!TryComp<AltFireMeleeComponent>(weaponUid, out var altFireComponent) || altDown != BoundKeyState.Down)
|
||||
return;
|
||||
|
||||
switch(altFireComponent.AttackType)
|
||||
{
|
||||
case AltFireAttackType.Light:
|
||||
ClientLightAttack(entity, mousePos, coordinates, weaponUid, weapon);
|
||||
break;
|
||||
|
||||
case AltFireAttackType.Heavy:
|
||||
ClientHeavyAttack(entity, coordinates, weaponUid, weapon);
|
||||
break;
|
||||
|
||||
case AltFireAttackType.Disarm:
|
||||
ClientDisarm(entity, mousePos, coordinates);
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Heavy attack.
|
||||
if (altDown == BoundKeyState.Down)
|
||||
@@ -123,14 +138,7 @@ public sealed partial class MeleeWeaponSystem : SharedMeleeWeaponSystem
|
||||
// If it's an unarmed attack then do a disarm
|
||||
if (weapon.AltDisarm && weaponUid == entity)
|
||||
{
|
||||
EntityUid? target = null;
|
||||
|
||||
if (_stateManager.CurrentState is GameplayStateBase screen)
|
||||
{
|
||||
target = screen.GetClickedEntity(mousePos);
|
||||
}
|
||||
|
||||
EntityManager.RaisePredictiveEvent(new DisarmAttackEvent(GetNetEntity(target), GetNetCoordinates(coordinates)));
|
||||
ClientDisarm(entity, mousePos, coordinates);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -140,28 +148,7 @@ public sealed partial class MeleeWeaponSystem : SharedMeleeWeaponSystem
|
||||
|
||||
// Light attack
|
||||
if (useDown == BoundKeyState.Down)
|
||||
{
|
||||
var attackerPos = TransformSystem.GetMapCoordinates(entity);
|
||||
|
||||
if (mousePos.MapId != attackerPos.MapId ||
|
||||
(attackerPos.Position - mousePos.Position).Length() > weapon.Range)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
EntityUid? target = null;
|
||||
|
||||
if (_stateManager.CurrentState is GameplayStateBase screen)
|
||||
{
|
||||
target = screen.GetClickedEntity(mousePos);
|
||||
}
|
||||
|
||||
// Don't light-attack if interaction will be handling this instead
|
||||
if (Interaction.CombatModeCanHandInteract(entity, target))
|
||||
return;
|
||||
|
||||
RaisePredictiveEvent(new LightAttackEvent(GetNetEntity(target), GetNetEntity(weaponUid), GetNetCoordinates(coordinates)));
|
||||
}
|
||||
ClientLightAttack(entity, mousePos, coordinates, weaponUid, weapon);
|
||||
}
|
||||
|
||||
protected override bool InRange(EntityUid user, EntityUid target, float range, ICommonSession? session)
|
||||
@@ -235,6 +222,35 @@ public sealed partial class MeleeWeaponSystem : SharedMeleeWeaponSystem
|
||||
var entities = GetNetEntityList(ArcRayCast(userPos, direction.ToWorldAngle(), component.Angle, distance, userXform.MapID, user).ToList());
|
||||
RaisePredictiveEvent(new HeavyAttackEvent(GetNetEntity(meleeUid), entities.GetRange(0, Math.Min(MaxTargets, entities.Count)), GetNetCoordinates(coordinates)));
|
||||
}
|
||||
|
||||
private void ClientDisarm(EntityUid attacker, MapCoordinates mousePos, EntityCoordinates coordinates)
|
||||
{
|
||||
EntityUid? target = null;
|
||||
|
||||
if (_stateManager.CurrentState is GameplayStateBase screen)
|
||||
target = screen.GetClickedEntity(mousePos);
|
||||
|
||||
RaisePredictiveEvent(new DisarmAttackEvent(GetNetEntity(target), GetNetCoordinates(coordinates)));
|
||||
}
|
||||
|
||||
private void ClientLightAttack(EntityUid attacker, MapCoordinates mousePos, EntityCoordinates coordinates, EntityUid weaponUid, MeleeWeaponComponent meleeComponent)
|
||||
{
|
||||
var attackerPos = TransformSystem.GetMapCoordinates(attacker);
|
||||
|
||||
if (mousePos.MapId != attackerPos.MapId || (attackerPos.Position - mousePos.Position).Length() > meleeComponent.Range)
|
||||
return;
|
||||
|
||||
EntityUid? target = null;
|
||||
|
||||
if (_stateManager.CurrentState is GameplayStateBase screen)
|
||||
target = screen.GetClickedEntity(mousePos);
|
||||
|
||||
// Don't light-attack if interaction will be handling this instead
|
||||
if (Interaction.CombatModeCanHandInteract(attacker, target))
|
||||
return;
|
||||
|
||||
RaisePredictiveEvent(new LightAttackEvent(GetNetEntity(target), GetNetEntity(weaponUid), GetNetCoordinates(coordinates)));
|
||||
}
|
||||
|
||||
private void OnMeleeLunge(MeleeLungeEvent ev)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
using Robust.Shared.GameStates;
|
||||
|
||||
namespace Content.Shared.Weapons.Melee.Components;
|
||||
|
||||
/// <summary>
|
||||
/// This is used to allow ranged weapons to make melee attacks by right-clicking.
|
||||
/// </summary>
|
||||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState, Access(typeof(SharedMeleeWeaponSystem))]
|
||||
public sealed partial class AltFireMeleeComponent : Component
|
||||
{
|
||||
[DataField, AutoNetworkedField]
|
||||
public AltFireAttackType AttackType = AltFireAttackType.Light;
|
||||
}
|
||||
|
||||
|
||||
[Flags]
|
||||
public enum AltFireAttackType : byte
|
||||
{
|
||||
Light = 0, // Standard single-target attack.
|
||||
Heavy = 1 << 0, // Wide swing.
|
||||
Disarm = 1 << 1
|
||||
}
|
||||
Reference in New Issue
Block a user