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>
This commit is contained in:
Sir Warock 2025-11-25 19:03:33 +01:00 committed by GitHub
parent e9c914ba59
commit 09cbcd71cb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
46 changed files with 771 additions and 0 deletions

View File

@ -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
{

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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)

View File

@ -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;
}

View File

@ -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 = [];
}

View File

@ -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;

View File

@ -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.

View File

@ -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:

View File

@ -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 }

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 269 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 163 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 177 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 B

View File

@ -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
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 469 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 397 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 389 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 493 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 583 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 349 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 342 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 198 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 223 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 229 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 235 B

View File

@ -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"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1003 B