Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Port] Crossbow / Арбалет #76

Merged
merged 14 commits into from
Oct 26, 2024
24 changes: 24 additions & 0 deletions Content.Client/_White/Guns/Stretched/StretchedVisualizerSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using Content.Shared._White.Guns.Stretched;
using Content.Shared.Weapons.Ranged.Systems;
using Robust.Client.GameObjects;

namespace Content.Client._White.Guns.Stretched;

public sealed class StretchedVisualizerSystem : VisualizerSystem<StretchedVisualsComponent>
{
[Dependency] private readonly AppearanceSystem _appearance = default!;

protected override void OnAppearanceChange(EntityUid uid, StretchedVisualsComponent component, ref AppearanceChangeEvent args)
{
if (args.Sprite == null)
return;

_appearance.TryGetData<bool>(uid, StretchedVisuals.Stretched, out var stretched, args.Component);
_appearance.TryGetData<bool>(uid, AmmoVisuals.HasAmmo, out var hasAmmo, args.Component);

// StretchedState: Weapon is stretched and ready to fire
// LoadedState: Weapon is loaded but not stretched
// UnstrungState: Weapon is neither stretched nor loaded
args.Sprite.LayerSetState(StretchedVisuals.Layer, stretched ? component.StretchedState : hasAmmo ? component.LoadedState : component.UnstrungState);
}
}
14 changes: 14 additions & 0 deletions Content.Client/_White/Guns/Stretched/StretchedVisualsComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
namespace Content.Client._White.Guns.Stretched;

[RegisterComponent, Access(typeof(StretchedVisualizerSystem))]
public sealed partial class StretchedVisualsComponent : Component
{
[DataField(required: true)]
public string LoadedState = string.Empty;

[DataField(required: true)]
public string StretchedState = string.Empty;

[DataField(required: true)]
public string UnstrungState = string.Empty;
}
32 changes: 32 additions & 0 deletions Content.Server/Power/EntitySystems/BatterySystem.cs
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
using System.Diagnostics.CodeAnalysis;
using Content.Server.Cargo.Systems;
using Content.Server.Emp;
using Content.Shared.Emp;
using Content.Server.Power.Components;
using Content.Shared.Examine;
using Content.Shared.Rejuvenate;
using JetBrains.Annotations;
using Robust.Shared.Containers;
using Robust.Shared.Utility;

namespace Content.Server.Power.EntitySystems
{
[UsedImplicitly]
public sealed class BatterySystem : EntitySystem
{
[Dependency] private readonly SharedContainerSystem _containers = default!; // WD EDIT

public override void Initialize()
{
base.Initialize();
Expand Down Expand Up @@ -181,5 +185,33 @@ public bool IsFull(EntityUid uid, BatteryComponent? battery = null)

return battery.CurrentCharge / battery.MaxCharge >= 0.99f;
}

// WD EDIT START
public bool TryGetBatteryComponent(EntityUid uid, [NotNullWhen(true)] out BatteryComponent? battery,
[NotNullWhen(true)] out EntityUid? batteryUid)
{
if (TryComp(uid, out battery))
{
batteryUid = uid;
return true;
}

if (!_containers.TryGetContainer(uid, "cell_slot", out var container)
|| container is not ContainerSlot slot)
{
battery = null;
batteryUid = null;
return false;
}

batteryUid = slot.ContainedEntity;

if (batteryUid != null)
return TryComp(batteryUid, out battery);

battery = null;
return false;
}
// WD EDIT END
}
}
79 changes: 79 additions & 0 deletions Content.Server/Projectiles/ProjectileSystem.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
using Content.Server.Administration.Logs;
using Content.Server.Effects;
using Content.Server.Hands.Systems;
using Content.Server.Weapons.Ranged.Systems;
using Content.Shared._White.Penetrated;
using Content.Shared._White.Projectile;
using Content.Shared.Camera;
using Content.Shared.Damage;
using Content.Shared.Database;
using Content.Shared.DoAfter;
using Content.Shared.Projectiles;
using Content.Shared.Throwing;
using Robust.Server.GameObjects;
using Robust.Shared.Physics;
using Robust.Shared.Physics.Components;
using Robust.Shared.Physics.Events;
using Robust.Shared.Player;

Expand All @@ -17,11 +25,22 @@ public sealed class ProjectileSystem : SharedProjectileSystem
[Dependency] private readonly DamageableSystem _damageableSystem = default!;
[Dependency] private readonly GunSystem _guns = default!;
[Dependency] private readonly SharedCameraRecoilSystem _sharedCameraRecoil = default!;
// WD EDIT START
[Dependency] private readonly DamageableSystem _damageable = default!;
Spatison marked this conversation as resolved.
Show resolved Hide resolved
[Dependency] private readonly HandsSystem _hands = default!;
[Dependency] private readonly PhysicsSystem _physics = default!;
[Dependency] private readonly SharedTransformSystem _transform = default!;
[Dependency] private readonly PenetratedSystem _penetrated = default!;
// WD EDIT END

public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<ProjectileComponent, StartCollideEvent>(OnStartCollide);
// WD EDIT START
SubscribeLocalEvent<EmbeddableProjectileComponent, EmbedEvent>(OnEmbed);
SubscribeLocalEvent<EmbeddableProjectileComponent, RemoveEmbeddedProjectileEvent>(OnEmbedRemove);
// WD EDIT END
}

private void OnStartCollide(EntityUid uid, ProjectileComponent component, ref StartCollideEvent args)
Expand Down Expand Up @@ -77,4 +96,64 @@ private void OnStartCollide(EntityUid uid, ProjectileComponent component, ref St
RaiseNetworkEvent(new ImpactEffectEvent(component.ImpactEffect, GetNetCoordinates(xform.Coordinates)), Filter.Pvs(xform.Coordinates, entityMan: EntityManager));
}
}

// WD EDIT START
private void OnEmbed(EntityUid uid, EmbeddableProjectileComponent component, ref EmbedEvent args)
{
var dmg = _damageable.TryChangeDamage(args.Embedded, component.Damage, origin: args.Shooter);
if (dmg is { Empty: false })
_color.RaiseEffect(Color.Red, new List<EntityUid>() { args.Embedded }, Filter.Pvs(args.Embedded, entityManager: EntityManager));
}
Spatison marked this conversation as resolved.
Show resolved Hide resolved

private void OnEmbedRemove(EntityUid uid, EmbeddableProjectileComponent component, RemoveEmbeddedProjectileEvent args)
{
// Whacky prediction issues.
if (args.Cancelled)
return;

if (component.DeleteOnRemove)
{
QueueDel(uid);
FreePenetrated(uid);
return;
}

if (!TryComp<PhysicsComponent>(uid, out var physics))
{
FreePenetrated(uid);
return;
}

var xform = Transform(uid);
_physics.SetBodyType(uid, BodyType.Dynamic, body: physics, xform: xform);
_transform.AttachToGridOrMap(uid, xform);

// Reset whether the projectile has damaged anything if it successfully was removed
if (TryComp<ProjectileComponent>(uid, out var projectile))
{
projectile.Shooter = null;
projectile.Weapon = null;
projectile.DamagedEntity = false;
}

FreePenetrated(uid);

// Land it just coz uhhh yeah
var landEv = new LandEvent(args.User, true);
RaiseLocalEvent(uid, ref landEv);
_physics.WakeBody(uid, body: physics);

// try place it in the user's hand
_hands.TryPickupAnyHand(args.User, uid);
}

private void FreePenetrated(EntityUid uid, PenetratedProjectileComponent? penetratedProjectile = null)
{
if (!Resolve(uid, ref penetratedProjectile)
|| !penetratedProjectile.PenetratedUid.HasValue)
Spatison marked this conversation as resolved.
Show resolved Hide resolved
return;

_penetrated.FreePenetrated(penetratedProjectile.PenetratedUid.Value);
}
// WD EDIT END
}
40 changes: 5 additions & 35 deletions Content.Server/Stunnable/Systems/StunbatonSystem.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using System.Diagnostics.CodeAnalysis;
using Content.Server.Power.Components;
using Content.Server.Power.EntitySystems;
using Content.Server.Power.Events;
Expand All @@ -12,7 +11,6 @@
using Content.Shared.Popups;
using Content.Shared.PowerCell.Components;
using Content.Shared.Stunnable;
using Robust.Shared.Containers;

namespace Content.Server.Stunnable.Systems
{
Expand All @@ -23,8 +21,6 @@ public sealed class StunbatonSystem : SharedStunbatonSystem
[Dependency] private readonly SharedPopupSystem _popup = default!;
[Dependency] private readonly BatterySystem _battery = default!;
[Dependency] private readonly SharedItemToggleSystem _itemToggle = default!;
[Dependency] private readonly SharedContainerSystem _containers = default!; // WD EDIT

public override void Initialize()
{
base.Initialize();
Expand All @@ -42,7 +38,7 @@ private void OnStaminaHitAttempt(Entity<StunbatonComponent> entity, ref StaminaD
{
// WD EDIT START
if (!_itemToggle.IsActivated(entity.Owner)
|| !TryGetBatteryComponent(entity, out var battery, out var batteryUid)
|| !_battery.TryGetBatteryComponent(entity, out var battery, out var batteryUid)
|| !_battery.TryUseCharge(batteryUid.Value, entity.Comp.EnergyPerUse, battery))
args.Cancelled = true;
// WD EDIT END
Expand All @@ -55,7 +51,7 @@ private void OnExamined(Entity<StunbatonComponent> entity, ref ExaminedEvent arg
: Loc.GetString("comp-stunbaton-examined-off");
args.PushMarkup(onMsg);

if (TryGetBatteryComponent(entity, out var battery, out _)) // WD EDIT
if (_battery.TryGetBatteryComponent(entity, out var battery, out _)) // WD EDIT
{
var count = (int) (battery.CurrentCharge / entity.Comp.EnergyPerUse);
args.PushMarkup(Loc.GetString("melee-battery-examine", ("color", "yellow"), ("count", count)));
Expand All @@ -70,7 +66,7 @@ private void ToggleDone(Entity<StunbatonComponent> entity, ref ItemToggledEvent
private void TryTurnOn(Entity<StunbatonComponent> entity, ref ItemToggleActivateAttemptEvent args)
{
// WD EDIT START
if (!TryGetBatteryComponent(entity, out var battery, out _)
if (!_battery.TryGetBatteryComponent(entity, out var battery, out _)
|| battery.CurrentCharge < entity.Comp.EnergyPerUse)
{

Expand All @@ -81,7 +77,7 @@ private void TryTurnOn(Entity<StunbatonComponent> entity, ref ItemToggleActivate
_popup.PopupEntity(Loc.GetString("stunbaton-component-low-charge"), (EntityUid) args.User,
(EntityUid) args.User);
}

return;
}
// WD EDIT END
Expand Down Expand Up @@ -126,36 +122,10 @@ private void OnPowerCellChanged(Entity<StunbatonComponent> entity, ref PowerCell

private void CheckCharge(Entity<StunbatonComponent> entity)
{
if (!TryGetBatteryComponent(entity, out var battery, out _)
if (!_battery.TryGetBatteryComponent(entity, out var battery, out _)
|| battery.CurrentCharge < entity.Comp.EnergyPerUse)
_itemToggle.TryDeactivate(entity.Owner, predicted: false);
}

private bool TryGetBatteryComponent(EntityUid uid, [NotNullWhen(true)] out BatteryComponent? battery,
[NotNullWhen(true)] out EntityUid? batteryUid)
{
if (TryComp(uid, out battery))
{
batteryUid = uid;
return true;
}

if (!_containers.TryGetContainer(uid, "cell_slot", out var container)
|| container is not ContainerSlot slot)
{
battery = null;
batteryUid = null;
return false;
}

batteryUid = slot.ContainedEntity;

if (batteryUid != null)
return TryComp(batteryUid, out battery);

battery = null;
return false;
}
// WD EDIT END
}
}
11 changes: 11 additions & 0 deletions Content.Server/Weapons/Ranged/Systems/GunSystem.Ballistic.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using Content.Server.Stack;
using Content.Shared.Stacks;
using Content.Shared.Weapons.Ranged.Components;
using Content.Shared.Weapons.Ranged.Events;
using Robust.Shared.Map;
Expand All @@ -6,6 +8,8 @@ namespace Content.Server.Weapons.Ranged.Systems;

public sealed partial class GunSystem
{
[Dependency] private readonly StackSystem _stack = default!; // WD EDIT

protected override void Cycle(EntityUid uid, BallisticAmmoProviderComponent component, MapCoordinates coordinates)
{
EntityUid? ent = null;
Expand All @@ -32,4 +36,11 @@ protected override void Cycle(EntityUid uid, BallisticAmmoProviderComponent comp
var cycledEvent = new GunCycledEvent();
RaiseLocalEvent(uid, ref cycledEvent);
}

// WD EDIT START
protected override EntityUid GetStackEntity(EntityUid uid, StackComponent stack)
{
return _stack.Split(uid, 1, Transform(uid).Coordinates, stack) ?? uid;
}
// WD EDIT END
}
6 changes: 6 additions & 0 deletions Content.Server/Weapons/Ranged/Systems/GunSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
using Content.Shared.Effects;
using Content.Shared.Interaction.Components;
using Content.Shared.Projectiles;
using Content.Shared.Throwing;
using Content.Shared.Weapons.Melee;
using Content.Shared.Weapons.Ranged;
using Content.Shared.Weapons.Ranged.Components;
Expand Down Expand Up @@ -293,7 +294,12 @@ private void ShootOrThrow(EntityUid uid, Vector2 mapDirection, Vector2 gunVeloci
{
RemoveShootable(uid);
// TODO: Someone can probably yeet this a billion miles so need to pre-validate input somewhere up the call stack.
// WD EDIT START
if (gun.ThrowAngle.HasValue)
EnsureComp<ThrowingAngleComponent>(uid).Angle = gun.ThrowAngle.Value;
// WD EDIT END
ThrowingSystem.TryThrow(uid, mapDirection, gun.ProjectileSpeedModified, user);
RemComp<ThrowingAngleComponent>(uid); // WD EDIT
return;
}

Expand Down
14 changes: 14 additions & 0 deletions Content.Server/_White/Guns/PoweredComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
namespace Content.Server._White.Guns;

[RegisterComponent]
public sealed partial class PoweredComponent : Component
{
[DataField]
public float EnergyPerUse = 180f;

/// <summary>
/// Modifies the speed of projectiles fired from this powered weapon.
/// </summary>
[DataField]
public float ProjectileSpeedModified = 15f;
Spatison marked this conversation as resolved.
Show resolved Hide resolved
}
32 changes: 32 additions & 0 deletions Content.Server/_White/Guns/PoweredSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using Content.Server.Power.EntitySystems;
using Content.Server.Weapons.Ranged.Systems;
using Content.Shared.Weapons.Ranged.Events;
using Content.Shared.Weapons.Ranged.Systems;

namespace Content.Server._White.Guns;

public sealed class PoweredSystem : EntitySystem
{
[Dependency] private readonly BatterySystem _battery = default!;
[Dependency] private readonly GunSystem _gun = default!;

public override void Initialize()
{
SubscribeLocalEvent<PoweredComponent, AttemptShootEvent>(OnShoot);
SubscribeLocalEvent<PoweredComponent, GunRefreshModifiersEvent>(OnGunRefreshModifiers);
}

private void OnShoot(EntityUid uid, PoweredComponent component, AttemptShootEvent args)
{
_gun.RefreshModifiers(uid);
}

private void OnGunRefreshModifiers(EntityUid uid, PoweredComponent component, ref GunRefreshModifiersEvent args)
{
if (!_battery.TryGetBatteryComponent(uid, out var battery, out var batteryUid)
|| !_battery.TryUseCharge(batteryUid.Value, component.EnergyPerUse, battery))
return;

args.ProjectileSpeed += component.ProjectileSpeedModified;
}
}
Loading
Loading