Add the NT-3 (#4622)
* Add Bipod System * Add the NT-3 * Small fixes * Small fixes * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Fix Test Fails * Small oversight * Robust the Code * Fix Action Name Co-authored-by: Tobias Berger <toby@tobot.dev> Signed-off-by: Sir Warock <67167466+SirWarock@users.noreply.github.com> * Fix Action Description Co-authored-by: Tobias Berger <toby@tobot.dev> Signed-off-by: Sir Warock <67167466+SirWarock@users.noreply.github.com> * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Add WallPierce + Changes * Small fix * Cleanup * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Fix Testfail + Add Descriptions --------- Signed-off-by: Sir Warock <67167466+SirWarock@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Tobias Berger <toby@tobot.dev> Co-authored-by: Vanessa <908648+ShepardToTheStars@users.noreply.github.com>
|
|
@ -1,3 +1,4 @@
|
|||
using Content.Server._DV.Projectiles.Events; // DeltaV - Addition of the NT-3
|
||||
using Content.Server.Administration.Logs;
|
||||
using Content.Server.Destructible;
|
||||
using Content.Server.Effects;
|
||||
|
|
@ -88,6 +89,9 @@ public sealed class ProjectileSystem : SharedProjectileSystem
|
|||
component.ProjectileSpent = true;
|
||||
}
|
||||
|
||||
var pierceEv = new ProjectilePierceEvent(target, damageRequired); // DeltaV - Addition of the NT-3
|
||||
RaiseLocalEvent(uid, ref pierceEv);
|
||||
|
||||
// If the object won't be destroyed, it "tanks" the penetration hit.
|
||||
if (modifiedDamage.GetTotal() < damageRequired)
|
||||
{
|
||||
|
|
@ -103,6 +107,9 @@ public sealed class ProjectileSystem : SharedProjectileSystem
|
|||
component.ProjectileSpent = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (component.ProjectileSpent && pierceEv.Pierced) // DeltaV - Addition of the NT-3
|
||||
component.ProjectileSpent = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,53 @@
|
|||
using Content.Shared.Tag;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server._DV.Projectiles.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class PiercingProjectileComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// The health threshold that a target has to supersede to block the projectile.
|
||||
/// A normal wall has 200.
|
||||
/// </summary>
|
||||
[DataField(required: true)]
|
||||
public float HealthThreshold;
|
||||
|
||||
/// <summary>
|
||||
/// The number of entities it pierced.
|
||||
/// It'll only count the entities with the <see cref="PierceBlockTag"/>.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public float PierceCounter;
|
||||
|
||||
/// <summary>
|
||||
/// The tag that will cause the piercing bullet to increment it's <see cref="PierceCounter"/>.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public List<ProtoId<TagPrototype>> PierceBlockTag = ["Wall", "Window"];
|
||||
|
||||
/// <summary>
|
||||
/// The number of entities it is allowed to pierce before being deleted.
|
||||
/// When <see cref="PierceCounter"/> is higher than this number, it'll be deleted.
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// A bullet with a MaxPierceNumberThreshold of 3 will pierce 3 entities with the <see cref="PierceBlockTag"/> and be deleted when hitting the fourth.
|
||||
/// </example>
|
||||
[DataField]
|
||||
public float MaxPierceNumberThreshold = 1f;
|
||||
|
||||
/// <summary>
|
||||
/// The cardinal direction that the bullet is flying toward.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public Direction? Direction;
|
||||
|
||||
/// <summary>
|
||||
/// The vertical/horizontal coordinate that will be ignored for <see cref="PierceCounter"/>.
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// A bullet going positive Y hitting a wall at X 3 and Y 5 will not increment the <see cref="PierceCounter"/> when hitting other walls at Y 5.
|
||||
/// </example>
|
||||
[DataField]
|
||||
public float? IgnoreRowCoordinate;
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
using Content.Shared.FixedPoint;
|
||||
|
||||
namespace Content.Server._DV.Projectiles.Events;
|
||||
|
||||
/// <summary>
|
||||
/// Raised when a piercing projectile hits an entity that doesn't follow upstream piercing rules.
|
||||
/// </summary>
|
||||
[ByRefEvent]
|
||||
public record struct ProjectilePierceEvent(EntityUid Target, FixedPoint2 RequiredDamage, bool Pierced = false);
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
using Content.Server._DV.Projectiles.Components;
|
||||
using Content.Server._DV.Projectiles.Events;
|
||||
using Content.Shared.Tag;
|
||||
|
||||
namespace Content.Server._DV.Projectiles.Systems;
|
||||
|
||||
public sealed class PiercingProjectileSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly TagSystem _tagSystem = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<PiercingProjectileComponent, ProjectilePierceEvent>(OnPierce);
|
||||
}
|
||||
|
||||
private void OnPierce(Entity<PiercingProjectileComponent> bullet, ref ProjectilePierceEvent args)
|
||||
{
|
||||
// If the target doesn't have any tags to stop the bullet from piercing, it's automatically true.
|
||||
if (!_tagSystem.HasAnyTag(args.Target, bullet.Comp.PierceBlockTag))
|
||||
{
|
||||
args.Pierced = true;
|
||||
return;
|
||||
}
|
||||
// If it does have the tag to stop it and enough health to count as "strongly armored", it'll block the bullet.
|
||||
if (bullet.Comp.HealthThreshold < args.RequiredDamage)
|
||||
return;
|
||||
|
||||
if (bullet.Comp.Direction == null) // Get the direction of the bullet to determine which walls count.
|
||||
bullet.Comp.Direction = Transform(bullet).LocalRotation.GetCardinalDir();
|
||||
|
||||
var xTarget = Transform(args.Target);
|
||||
|
||||
var targetPosition = bullet.Comp.Direction is Direction.East or Direction.West
|
||||
? xTarget.Coordinates.X // If the bullet is going horizontal, wall rows are vertical.
|
||||
: xTarget.Coordinates.Y; // And when vertical, the wall rows are horizontal
|
||||
|
||||
// If the wall is part of a wall-row that the bullet already pierced, pierce it too and ignore it for the counter.
|
||||
if (bullet.Comp.IgnoreRowCoordinate != null
|
||||
&& Math.Abs(targetPosition - bullet.Comp.IgnoreRowCoordinate.Value) < 0.25)
|
||||
{
|
||||
args.Pierced = true;
|
||||
return;
|
||||
}
|
||||
|
||||
bullet.Comp.PierceCounter++;
|
||||
|
||||
if (bullet.Comp.PierceCounter > bullet.Comp.MaxPierceNumberThreshold)
|
||||
return;
|
||||
|
||||
// Save the row-position of the last wall it pierced, so we can ignore any other wall part of the same row.
|
||||
bullet.Comp.IgnoreRowCoordinate = targetPosition;
|
||||
args.Pierced = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -99,6 +99,7 @@ public abstract partial class SharedGunSystem : EntitySystem
|
|||
SubscribeLocalEvent<GunComponent, MapInitEvent>(OnMapInit);
|
||||
|
||||
InitializeHolders(); // DeltaV
|
||||
InitializeBipods(); // DeltaV
|
||||
}
|
||||
|
||||
private void OnMapInit(Entity<GunComponent> gun, ref MapInitEvent args)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,65 @@
|
|||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared._DV.Weapons.Ranged.Components;
|
||||
|
||||
/// <summary>
|
||||
/// Alters the accuracy and firerate of the gun after a DoAfter, immoblizing the wielder.
|
||||
/// </summary>
|
||||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
|
||||
public sealed partial class GunBipodComponent : Component
|
||||
{
|
||||
[DataField, AutoNetworkedField]
|
||||
public Angle MinAngle = Angle.FromDegrees(-43);
|
||||
|
||||
/// <summary>
|
||||
/// Angle bonus applied upon the bipod being used.
|
||||
/// </summary>
|
||||
[DataField, AutoNetworkedField]
|
||||
public Angle MaxAngle = Angle.FromDegrees(-43);
|
||||
|
||||
/// <summary>
|
||||
/// Recoil bonuses applied upon the bipod being used.
|
||||
/// Higher angle decay bonus, quicker recovery.
|
||||
/// </summary>
|
||||
[DataField, AutoNetworkedField]
|
||||
public Angle AngleDecay = Angle.FromDegrees(0);
|
||||
|
||||
/// <summary>
|
||||
/// Recoil bonuses applied upon the bipod being used.
|
||||
/// Lower angle increase bonus (negative numbers), slower buildup.
|
||||
/// </summary>
|
||||
[DataField, AutoNetworkedField]
|
||||
public Angle AngleIncrease = Angle.FromDegrees(0);
|
||||
|
||||
/// <summary>
|
||||
/// Firerate bonus applied upon the bipod being used.
|
||||
/// </summary>
|
||||
[DataField, AutoNetworkedField]
|
||||
public float FireRateIncrease = 3f;
|
||||
|
||||
/// <summary>
|
||||
/// Time to set up the bipod.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public TimeSpan SetupDelay = TimeSpan.FromSeconds(2);
|
||||
|
||||
/// <summary>
|
||||
/// Is the bipod set up?
|
||||
/// </summary>
|
||||
[DataField, AutoNetworkedField]
|
||||
public bool IsSetup;
|
||||
|
||||
[DataField]
|
||||
public EntProtoId BipodToggleAction = "ActionToggleBipod";
|
||||
|
||||
[DataField, AutoNetworkedField]
|
||||
public EntityUid? BipodToggleActionEntity;
|
||||
|
||||
/// <summary>
|
||||
/// The time when the Bipod has begun being set up.
|
||||
/// Used to stop it from firing while the bipod is being set up.
|
||||
/// </summary>
|
||||
[AutoNetworkedField]
|
||||
public TimeSpan BipodSetupTime = TimeSpan.Zero;
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
using Robust.Shared.GameStates;
|
||||
|
||||
namespace Content.Shared._DV.Weapons.Ranged.Components;
|
||||
|
||||
/// <summary>
|
||||
/// An entity currently using a bipod weapon has this component.
|
||||
/// </summary>
|
||||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
|
||||
public sealed partial class IsUsingBipodComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// A list of BipodComponents, so we can shut them down on movement.
|
||||
/// </summary>
|
||||
[AutoNetworkedField]
|
||||
public List<EntityUid> BipodOwnerUids = [];
|
||||
}
|
||||
|
|
@ -0,0 +1,200 @@
|
|||
using Content.Shared._DV.Weapons.Ranged.Components;
|
||||
using Content.Shared.Actions;
|
||||
using Content.Shared.DoAfter;
|
||||
using Content.Shared.Hands;
|
||||
using Content.Shared.IdentityManagement;
|
||||
using Content.Shared.Interaction.Events;
|
||||
using Content.Shared.Toggleable;
|
||||
using Content.Shared.Weapons.Ranged.Events;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared.Weapons.Ranged.Systems;
|
||||
|
||||
public abstract partial class SharedGunSystem
|
||||
{
|
||||
[Dependency] private readonly ActionContainerSystem _actionContainerSystem = default!;
|
||||
|
||||
private void InitializeBipods()
|
||||
{
|
||||
SubscribeLocalEvent<GunBipodComponent, GotUnequippedHandEvent>(OnUnequip);
|
||||
SubscribeLocalEvent<GunBipodComponent, DroppedEvent>(OnDrop);
|
||||
|
||||
SubscribeLocalEvent<GunBipodComponent, GetItemActionsEvent>(OnGetActions);
|
||||
SubscribeLocalEvent<GunBipodComponent, ToggleActionEvent>(OnToggleAction);
|
||||
|
||||
SubscribeLocalEvent<GunBipodComponent, MapInitEvent>(OnMapInit);
|
||||
|
||||
SubscribeLocalEvent<GunBipodComponent, GunRefreshModifiersEvent>(OnGunRefreshModifiers);
|
||||
SubscribeLocalEvent<GunBipodComponent, BipodSetupFinishedEvent>(SetupBipod);
|
||||
SubscribeLocalEvent<GunBipodComponent, ShotAttemptedEvent>(OnShotAttempted);
|
||||
SubscribeLocalEvent<IsUsingBipodComponent, MoveEvent>(OnMove);
|
||||
}
|
||||
|
||||
private void OnMapInit(Entity<GunBipodComponent> weapon, ref MapInitEvent args)
|
||||
{
|
||||
_actionContainerSystem.EnsureAction(weapon.Owner, ref weapon.Comp.BipodToggleActionEntity, weapon.Comp.BipodToggleAction);
|
||||
Dirty(weapon);
|
||||
}
|
||||
|
||||
private void OnGetActions(Entity<GunBipodComponent> ent, ref GetItemActionsEvent args)
|
||||
{
|
||||
args.AddAction(ref ent.Comp.BipodToggleActionEntity, ent.Comp.BipodToggleAction);
|
||||
}
|
||||
|
||||
private void OnUnequip(Entity<GunBipodComponent> weapon, ref GotUnequippedHandEvent args)
|
||||
{
|
||||
if (weapon.Comp.IsSetup)
|
||||
PackUpBipod(weapon, args.User, null);
|
||||
}
|
||||
|
||||
private void OnDrop(Entity<GunBipodComponent> weapon, ref DroppedEvent args)
|
||||
{
|
||||
if (weapon.Comp.IsSetup)
|
||||
PackUpBipod(weapon, args.User, null);
|
||||
}
|
||||
|
||||
private void OnMove(Entity<IsUsingBipodComponent> bipodUser, ref MoveEvent args)
|
||||
{
|
||||
// This fires when the entity rotates. If the position didn't change, do not undo the bipod.
|
||||
if (args.OldPosition.Equals(args.NewPosition))
|
||||
return;
|
||||
// Undo the Bipod of every gun currently used.
|
||||
foreach (var weaponUid in bipodUser.Comp.BipodOwnerUids.ToArray())
|
||||
{
|
||||
if (!TryComp<GunBipodComponent>(weaponUid, out var bipod))
|
||||
continue;
|
||||
|
||||
PackUpBipod((weaponUid, bipod), bipodUser.Owner, bipodUser.Comp);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnToggleAction(Entity<GunBipodComponent> ent, ref ToggleActionEvent args)
|
||||
{
|
||||
if (args.Handled)
|
||||
return;
|
||||
|
||||
if (ent.Comp.IsSetup)
|
||||
PackUpBipod(ent, args.Performer, null);
|
||||
else
|
||||
TrySetupBipod(ent, args.Performer);
|
||||
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
private void TrySetupBipod(Entity<GunBipodComponent> ent, EntityUid user)
|
||||
{
|
||||
var xform = Transform(user);
|
||||
|
||||
//Don't allow someone to set up the bipod if they're not parented to a grid
|
||||
if (xform.GridUid != xform.ParentUid)
|
||||
{
|
||||
CantSetupError(user, Loc.GetString("action-popup-bipod-user-cant-setup"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't allow someone to set up the bipod if they're not holding the weapon
|
||||
if (!_hands.IsHolding(user, ent.Owner, out _))
|
||||
{
|
||||
CantSetupError(user, Loc.GetString("action-popup-bipod-user-not-holding"));
|
||||
return;
|
||||
}
|
||||
|
||||
var gunName = Name(ent.Owner);
|
||||
var bipodUser = Identity.Entity(user, EntityManager);
|
||||
// Show a popup for everyone to show them setting up their bipod.
|
||||
var msgUser = Loc.GetString("action-popup-bipod-user", ("gunName", gunName));
|
||||
var msgOther = Loc.GetString("action-popup-bipod-other", ("bipodUser", bipodUser), ("gunName", gunName));
|
||||
|
||||
PopupSystem.PopupPredicted(msgUser, msgOther, user, user);
|
||||
|
||||
var doAfterArgs = new DoAfterArgs(EntityManager, user, ent.Comp.SetupDelay, new BipodSetupFinishedEvent(), ent.Owner, target: ent.Owner, used: ent.Owner)
|
||||
{
|
||||
BreakOnDamage = false,
|
||||
BreakOnMove = true,
|
||||
};
|
||||
// This is used to prevent the gun from shooting while setting up the bipod.
|
||||
ent.Comp.BipodSetupTime = Timing.CurTime;
|
||||
_doAfter.TryStartDoAfter(doAfterArgs);
|
||||
}
|
||||
|
||||
private void SetupBipod(Entity<GunBipodComponent> ent, ref BipodSetupFinishedEvent bipodEvent)
|
||||
{
|
||||
if (bipodEvent.Cancelled) // This method is called whether the DoAfter was successful - Hence the catch.
|
||||
{
|
||||
ent.Comp.BipodSetupTime = TimeSpan.Zero; // This allows them to shoot again when they cancel putting down the bipod.
|
||||
return;
|
||||
}
|
||||
|
||||
var bipodUseComp = EnsureComp<IsUsingBipodComponent>(bipodEvent.User); // Set a component on the user so we can track it for movement.
|
||||
bipodUseComp.BipodOwnerUids.Add(ent.Owner); // Add it to the used Bipods.
|
||||
|
||||
var gunName = Name(ent.Owner);
|
||||
var bipodUser = Identity.Entity(bipodEvent.User, EntityManager);
|
||||
// Send another popup that the bipod is successfully set up.
|
||||
var msgUser = Loc.GetString("action-popup-bipod-finished-user", ("gunName", gunName));
|
||||
var msgOther = Loc.GetString("action-popup-bipod-finished-other", ("bipodUser", bipodUser), ("gunName", gunName));
|
||||
|
||||
Actions.SetToggled(ent.Comp.BipodToggleActionEntity, true);
|
||||
PopupSystem.PopupPredicted(msgUser, msgOther, bipodEvent.User, bipodEvent.User);
|
||||
|
||||
ent.Comp.IsSetup = true; // Activate the Bipod.
|
||||
|
||||
RefreshModifiers(ent.Owner); // This will update the modifiers of the weapon, so the bipod is in effect.
|
||||
Dirty(ent);
|
||||
}
|
||||
|
||||
private void PackUpBipod(Entity<GunBipodComponent> weapon, EntityUid user, IsUsingBipodComponent? userComp)
|
||||
{
|
||||
if (Timing.ApplyingState
|
||||
|| !Resolve(user, ref userComp)) // Component can be nullable, so we resolve. Less expensive than TryComp.
|
||||
return;
|
||||
|
||||
userComp.BipodOwnerUids.Remove(weapon); // Remove the bipod component from the list of used bipods.
|
||||
if (userComp.BipodOwnerUids.Count == 0) // Remove the Component if no bipod is in use anymore.
|
||||
RemComp<IsUsingBipodComponent>(user);
|
||||
|
||||
var gunName = Name(weapon);
|
||||
var bipodUser = Identity.Entity(user, EntityManager);
|
||||
// Show a popup that the bipod has been removed.
|
||||
var msgUser = Loc.GetString("action-popup-bipod-disabling-user", ("gunName", gunName));
|
||||
var msgOther = Loc.GetString("action-popup-bipod-disabling-other", ("bipodUser", bipodUser), ("gunName", gunName));
|
||||
|
||||
Actions.SetToggled(weapon.Comp.BipodToggleActionEntity, false); // Set the action icon to red.
|
||||
PopupSystem.PopupPredicted(msgUser, msgOther, user, user);
|
||||
|
||||
weapon.Comp.IsSetup = false; // Deactivate the Bipod.
|
||||
|
||||
RefreshModifiers(weapon.Owner); // This will update the modifiers of the weapon, so the bipod bonus is lost.
|
||||
Dirty(weapon);
|
||||
}
|
||||
|
||||
private void CantSetupError(EntityUid user, string errorMessage)
|
||||
{
|
||||
PopupSystem.PopupClient(errorMessage, user, user);
|
||||
}
|
||||
|
||||
private void OnGunRefreshModifiers(Entity<GunBipodComponent> bonus, ref GunRefreshModifiersEvent args)
|
||||
{
|
||||
if (bonus.Comp.IsSetup)
|
||||
{
|
||||
args.MinAngle += bonus.Comp.MinAngle;
|
||||
args.MaxAngle += bonus.Comp.MaxAngle;
|
||||
args.AngleDecay += bonus.Comp.AngleDecay;
|
||||
args.AngleIncrease += bonus.Comp.AngleIncrease;
|
||||
args.FireRate += bonus.Comp.FireRateIncrease;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnShotAttempted(Entity<GunBipodComponent> ent, ref ShotAttemptedEvent args)
|
||||
{
|
||||
// This is true when the bipod is being set up - Preventing the gun from shooting.
|
||||
if (Timing.CurTime < ent.Comp.BipodSetupTime + ent.Comp.SetupDelay)
|
||||
args.Cancel();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This event gets called when the Setup Doafter is done.
|
||||
/// </summary>
|
||||
[Serializable, NetSerializable]
|
||||
public sealed partial class BipodSetupFinishedEvent : SimpleDoAfterEvent;
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
action-popup-bipod-user = You're setting up the bipod of your {$gunName}!
|
||||
action-popup-bipod-disabling-user = You pack up the bipod of your {$gunName}!
|
||||
action-popup-bipod-finished-user = You've set up the bipod of your {$gunName}!
|
||||
|
||||
action-popup-bipod-other = {CAPITALIZE(THE($bipodUser))} is setting up the bipod of {POSS-ADJ($bipodUser)} {$gunName}!
|
||||
action-popup-bipod-disabling-other = {CAPITALIZE(THE($bipodUser))} packed up the bipod of {POSS-ADJ($bipodUser)} {$gunName}!
|
||||
action-popup-bipod-finished-other = {CAPITALIZE(THE($bipodUser))} has set up the bipod of {POSS-ADJ($bipodUser)} {$gunName}!
|
||||
|
||||
action-popup-bipod-user-cant-setup = You tried to set up your bipod, but there was nothing to set up on.
|
||||
action-popup-bipod-user-not-holding = You aren't holding the weapon with the bipod.
|
||||
|
|
@ -465,6 +465,18 @@
|
|||
- Sheet
|
||||
- RawMaterial
|
||||
- Ingot
|
||||
# End DeltaV Additions
|
||||
- type: BlueprintReceiver
|
||||
whitelist:
|
||||
tags:
|
||||
- BlueprintAutolathe
|
||||
- BlueprintSecurityTechfab
|
||||
- type: ContainerContainer
|
||||
containers:
|
||||
machine_board: !type:Container
|
||||
machine_parts: !type:Container
|
||||
blueprint: !type:Container
|
||||
# End DeltaV Additions
|
||||
- type: OreSiloClient
|
||||
- type: LatheAnnouncing
|
||||
channels: [Security]
|
||||
|
|
@ -497,6 +509,17 @@
|
|||
unlitRunningState: unlit-building # DeltaV - added animation sprite layers
|
||||
staticPacks:
|
||||
- SecurityAmmoStatic
|
||||
# End DeltaV Additions
|
||||
- type: BlueprintReceiver
|
||||
whitelist:
|
||||
tags:
|
||||
- BlueprintAmmoTechfab
|
||||
- type: ContainerContainer
|
||||
containers:
|
||||
machine_board: !type:Container
|
||||
machine_parts: !type:Container
|
||||
blueprint: !type:Container
|
||||
# End DeltaV Additions
|
||||
- type: MaterialStorage
|
||||
whitelist:
|
||||
tags:
|
||||
|
|
|
|||
|
|
@ -66,3 +66,13 @@
|
|||
useDelay: 30
|
||||
- type: InstantAction
|
||||
event: !type:CoughItemActionEvent
|
||||
|
||||
- type: entity
|
||||
parent: BaseToggleAction
|
||||
id: ActionToggleBipod
|
||||
name: Set up your bipod
|
||||
description: Increase the accuracy and fire rate of your firearm.
|
||||
components:
|
||||
- type: Action
|
||||
icon: { sprite: _DV/Objects/Weapons/Guns/LMGs/NT-3.rsi, state: bipod-off }
|
||||
iconOn: { sprite: _DV/Objects/Weapons/Guns/LMGs/NT-3.rsi, state: bipod-on }
|
||||
|
|
|
|||
|
|
@ -69,3 +69,13 @@
|
|||
cost: 18000
|
||||
category: Armory
|
||||
group: market
|
||||
|
||||
- type: cargoProduct
|
||||
id: ArmoryNT3
|
||||
icon:
|
||||
sprite: _DV/Objects/Weapons/Guns/LMGs/NT-3.rsi
|
||||
state: icon
|
||||
product: CrateNT3
|
||||
cost: 13000
|
||||
category: Armory
|
||||
group: market
|
||||
|
|
|
|||
|
|
@ -68,3 +68,14 @@
|
|||
contents:
|
||||
- id: WatchdogImplanter
|
||||
amount: 3
|
||||
|
||||
- type: entity
|
||||
id: CrateNT3
|
||||
parent: CrateWeaponSecure
|
||||
name: NT-3 crate
|
||||
description: Contains the refurbished NT-3, along with two magazine boxes filled with .40 anti-material ammunition and a blueprint for the ammunition.
|
||||
components:
|
||||
- type: EntityTableContainerFill
|
||||
containers:
|
||||
entity_storage: !type:NestedSelector
|
||||
tableId: NT3Table
|
||||
|
|
|
|||
|
|
@ -39,3 +39,13 @@
|
|||
- id: GamblagatorCapacitor
|
||||
amount: !type:ConstantNumberSelector
|
||||
value: 4
|
||||
|
||||
- type: entityTable
|
||||
id: NT3Table
|
||||
table: !type:AllSelector
|
||||
children:
|
||||
- id: WeaponLightMachinegGunNT3
|
||||
- id: BlueprintMagazineBoxLMGAntiMateriel
|
||||
- id: MagazineLMGAntiMaterielBox
|
||||
amount: !type:ConstantNumberSelector
|
||||
value: 2
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
- type: entity
|
||||
parent: BaseBlueprint
|
||||
id: BlueprintMagazineBoxLMGAntiMateriel
|
||||
name: ammuntion box blueprint (.40 anti-materiel)
|
||||
description: A blueprint with a schematic of for .40 anti-materiel cartridges, used by the NT-3. It can be inserted into a Security Techfab.
|
||||
components:
|
||||
- type: Blueprint
|
||||
providedRecipes:
|
||||
- MagazineBoxLMGAntiMateriel
|
||||
- type: Tag
|
||||
tags:
|
||||
- BlueprintSecurityTechfab
|
||||
- BlueprintAmmoTechfab
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
- type: entity
|
||||
parent: MagazineBoxAntiMateriel
|
||||
id: MagazineBoxLMGAntiMateriel
|
||||
name: ammunition box (.40 anti-materiel)
|
||||
description: A rigid steel box of .40 anti-materiel rounds. Intended to hold structure-piercing kinetic ammunition.
|
||||
components:
|
||||
- type: BallisticAmmoProvider
|
||||
mayTransfer: true
|
||||
whitelist:
|
||||
tags:
|
||||
- CartridgeLMGAntiMateriel
|
||||
proto: CartridgeLMGAntiMateriel
|
||||
capacity: 30
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
- type: entity
|
||||
parent: [ BaseCartridge, BaseSecurityContraband ]
|
||||
id: CartridgeLMGAntiMateriel
|
||||
name: cartridge (.40 anti-materiel)
|
||||
description: A expensive, heavy cartridge used by special LMGs. Structural-piercing kinetic ammunition is useful for when you don't care about what's between you and your target.
|
||||
components:
|
||||
- type: Tag
|
||||
tags:
|
||||
- Cartridge
|
||||
- CartridgeLMGAntiMateriel
|
||||
- type: CartridgeAmmo
|
||||
proto: BulletLMGAntiMateriel
|
||||
- type: Sprite
|
||||
sprite: Objects/Weapons/Guns/Ammunition/Casings/ammo_casing.rsi
|
||||
layers:
|
||||
- state: base
|
||||
map: ["enum.AmmoVisualLayers.Base"]
|
||||
- type: Appearance
|
||||
- type: SpentAmmoVisuals
|
||||
- type: StaticPrice
|
||||
price: 20
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
- type: entity
|
||||
parent: [ BaseItem, BaseSecurityContraband ]
|
||||
id: MagazineLMGAntiMaterielBox
|
||||
name: "NT-3 magazine box (.40 anti-materiel)"
|
||||
description: An ancient design of a box containing containing a 60-round belt of linked .40 anti-materiel rounds, used by refurbished light machine guns such as the NT-3. Intended to hold structure-piercing kinetic ammunition.
|
||||
components:
|
||||
- type: Tag
|
||||
tags:
|
||||
- MagazineLMGAntiMaterielBox
|
||||
- type: BallisticAmmoProvider
|
||||
mayTransfer: true
|
||||
whitelist:
|
||||
tags:
|
||||
- CartridgeLMGAntiMateriel
|
||||
proto: CartridgeLMGAntiMateriel
|
||||
capacity: 60
|
||||
- type: Item
|
||||
size: Small
|
||||
- type: ContainerContainer
|
||||
containers:
|
||||
ballistic-ammo: !type:Container
|
||||
- type: Sprite
|
||||
sprite: _DV/Objects/Weapons/Guns/Ammunition/Magazine/LightRifle/light_rifle_small_box.rsi
|
||||
layers:
|
||||
- state: base
|
||||
map: ["enum.GunVisualLayers.Base"]
|
||||
- state: mag-1
|
||||
map: ["enum.GunVisualLayers.Mag"]
|
||||
- type: MagazineVisuals
|
||||
magState: mag
|
||||
steps: 6
|
||||
zeroVisible: false
|
||||
- type: Appearance
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
- type: entity
|
||||
categories: [ HideSpawnMenu ]
|
||||
parent: BaseBullet
|
||||
id: BulletLMGAntiMateriel
|
||||
name: bullet (.40 anti-materiel)
|
||||
components:
|
||||
- type: Projectile
|
||||
damage:
|
||||
types:
|
||||
Piercing: 20
|
||||
Structural: 20
|
||||
penetrationThreshold: 200 # This is irrelevant - As long as it's above 0.
|
||||
- type: PiercingProjectile
|
||||
healthThreshold: 200 # Normal walls have a threshold of 200.
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
- type: entity
|
||||
name: NT-3
|
||||
parent: BaseItem # The base LightMachineGun had unwanted components.
|
||||
id: WeaponLightMachinegGunNT3
|
||||
description: An ancient weapon from the old wars, refurbished and rebranded for NT's strongest stations.
|
||||
components:
|
||||
- type: Sprite
|
||||
sprite: _DV/Objects/Weapons/Guns/LMGs/NT-3.rsi
|
||||
layers:
|
||||
- state: base
|
||||
map: ["enum.GunVisualLayers.Base"]
|
||||
- state: mag-3
|
||||
map: [ "enum.GunVisualLayers.Mag" ]
|
||||
- type: MagazineVisuals
|
||||
magState: mag
|
||||
steps: 4
|
||||
zeroVisible: true
|
||||
- type: Item
|
||||
size: Ginormous
|
||||
shape:
|
||||
- 0,0,4,3
|
||||
- type: Clothing
|
||||
sprite: _DV/Objects/Weapons/Guns/LMGs/NT-3.rsi
|
||||
quickEquip: false
|
||||
slots:
|
||||
- Back
|
||||
- type: ClothingSpeedModifier
|
||||
sprintModifier: 0.9
|
||||
- type: Appearance
|
||||
- type: Wieldable
|
||||
unwieldOnUse: false
|
||||
- type: GunRequiresWield
|
||||
- type: Gun
|
||||
minAngle: 12
|
||||
maxAngle: 30
|
||||
angleIncrease: 4
|
||||
angleDecay: 16
|
||||
fireRate: 4
|
||||
selectedMode: FullAuto
|
||||
availableModes:
|
||||
- FullAuto
|
||||
soundGunshot:
|
||||
path: /Audio/Weapons/Guns/Gunshots/lmg.ogg
|
||||
soundEmpty:
|
||||
path: /Audio/Weapons/Guns/Empty/lmg_empty.ogg
|
||||
- type: GunBipod
|
||||
minAngle: -12
|
||||
maxAngle: -20
|
||||
angleDecay: 4
|
||||
fireRateIncrease: 3
|
||||
- type: ChamberMagazineAmmoProvider
|
||||
soundRack:
|
||||
path: /Audio/Weapons/Guns/Cock/lmg_cock.ogg
|
||||
- type: AmmoCounter
|
||||
- type: ItemSlots
|
||||
slots:
|
||||
gun_magazine:
|
||||
name: Magazine
|
||||
startingItem: MagazineLMGAntiMaterielBox
|
||||
insertSound: /Audio/Weapons/Guns/MagIn/batrifle_magin.ogg
|
||||
ejectSound: /Audio/Weapons/Guns/MagOut/batrifle_magout.ogg
|
||||
priority: 2
|
||||
whitelist:
|
||||
tags:
|
||||
- MagazineLMGAntiMaterielBox
|
||||
gun_chamber:
|
||||
name: Chamber
|
||||
startingItem: CartridgeLMGAntiMateriel
|
||||
priority: 1
|
||||
whitelist:
|
||||
tags:
|
||||
- CartridgeLMGAntiMateriel
|
||||
- type: ContainerContainer
|
||||
containers:
|
||||
gun_magazine: !type:ContainerSlot
|
||||
gun_chamber: !type:ContainerSlot
|
||||
- type: StaticPrice
|
||||
price: 500
|
||||
- type: UseDelay
|
||||
delay: 1
|
||||
|
|
@ -353,6 +353,16 @@
|
|||
Gold: 500
|
||||
Wood: 300
|
||||
|
||||
# .40 Anti-materiel Ammo for the NT-3
|
||||
|
||||
- type: latheRecipe
|
||||
id: MagazineBoxLMGAntiMateriel
|
||||
result: MagazineBoxLMGAntiMateriel
|
||||
completetime: 4
|
||||
materials:
|
||||
Steel: 1000
|
||||
Uranium: 250
|
||||
|
||||
- type: latheRecipe
|
||||
id: PyroLeftArm
|
||||
result: PyroLeftArm
|
||||
|
|
|
|||
|
|
@ -36,6 +36,12 @@
|
|||
- type: Tag
|
||||
id: BeltSlotNotBelt #not a 'belt'
|
||||
|
||||
- type: Tag
|
||||
id: BlueprintAmmoTechfab
|
||||
|
||||
- type: Tag
|
||||
id: BlueprintSecurityTechfab
|
||||
|
||||
- type: Tag
|
||||
id: BluespaceCrystal
|
||||
|
||||
|
|
@ -57,6 +63,9 @@
|
|||
- type: Tag
|
||||
id: CartridgeLaser
|
||||
|
||||
- type: Tag
|
||||
id: CartridgeLMGAntiMateriel
|
||||
|
||||
- type: Tag
|
||||
id: CartridgeSpecial # For the .38 special ammo and revolver
|
||||
|
||||
|
|
@ -114,6 +123,9 @@
|
|||
- type: Tag
|
||||
id: MagazineLaser
|
||||
|
||||
- type: Tag
|
||||
id: MagazineLMGAntiMaterielBox # For the NT-3
|
||||
|
||||
- type: Tag
|
||||
id: MagazinePistolSpecial # For the .38 special ammo and pistol
|
||||
|
||||
|
|
|
|||
|
After Width: | Height: | Size: 269 B |
|
After Width: | Height: | Size: 296 B |
|
After Width: | Height: | Size: 301 B |
|
After Width: | Height: | Size: 125 B |
|
After Width: | Height: | Size: 149 B |
|
After Width: | Height: | Size: 163 B |
|
After Width: | Height: | Size: 177 B |
|
After Width: | Height: | Size: 180 B |
|
|
@ -0,0 +1,37 @@
|
|||
{
|
||||
"version": 1,
|
||||
"size": {
|
||||
"x": 32,
|
||||
"y": 32
|
||||
},
|
||||
"license": "CC-BY-SA-3.0",
|
||||
"copyright": "Sprites made by SirWarock on Github",
|
||||
"states": [
|
||||
{
|
||||
"name": "base"
|
||||
},
|
||||
{
|
||||
"name": "mag-1"
|
||||
},
|
||||
{
|
||||
"name": "mag-2"
|
||||
},
|
||||
{
|
||||
"name": "mag-3"
|
||||
},
|
||||
{
|
||||
"name": "mag-4"
|
||||
},
|
||||
{
|
||||
"name": "mag-5"
|
||||
},
|
||||
{
|
||||
"name": "inhand-left",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "inhand-right",
|
||||
"directions": 4
|
||||
}
|
||||
]
|
||||
}
|
||||
|
After Width: | Height: | Size: 469 B |
|
After Width: | Height: | Size: 397 B |
|
After Width: | Height: | Size: 389 B |
|
After Width: | Height: | Size: 493 B |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 583 B |
|
After Width: | Height: | Size: 349 B |
|
After Width: | Height: | Size: 342 B |
|
After Width: | Height: | Size: 198 B |
|
After Width: | Height: | Size: 223 B |
|
After Width: | Height: | Size: 229 B |
|
After Width: | Height: | Size: 235 B |
|
|
@ -0,0 +1,58 @@
|
|||
{
|
||||
"version": 1,
|
||||
"license": "CC-BY-SA-3.0",
|
||||
"copyright": "Sprites made by SirWarock on Github.",
|
||||
"size": {
|
||||
"x": 32,
|
||||
"y": 32
|
||||
},
|
||||
"states": [
|
||||
{
|
||||
"name": "icon"
|
||||
},
|
||||
{
|
||||
"name": "base"
|
||||
},
|
||||
{
|
||||
"name": "bolt-open"
|
||||
},
|
||||
{
|
||||
"name": "mag-0"
|
||||
},
|
||||
{
|
||||
"name": "mag-1"
|
||||
},
|
||||
{
|
||||
"name": "mag-2"
|
||||
},
|
||||
{
|
||||
"name": "mag-3"
|
||||
},
|
||||
{
|
||||
"name": "inhand-left",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "inhand-right",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "wielded-inhand-left",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "wielded-inhand-right",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "equipped-BACKPACK",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "bipod-off"
|
||||
},
|
||||
{
|
||||
"name": "bipod-on"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 1003 B |