diff --git a/Content.Server/Explosion/Components/ExplosiveComponent.cs b/Content.Server/Explosion/Components/ExplosiveComponent.cs
index 04a08955a35..2b27a89d9db 100644
--- a/Content.Server/Explosion/Components/ExplosiveComponent.cs
+++ b/Content.Server/Explosion/Components/ExplosiveComponent.cs
@@ -81,6 +81,13 @@ public sealed partial class ExplosiveComponent : Component
[DataField("deleteAfterExplosion")]
public bool? DeleteAfterExplosion;
+ ///
+ /// Whether to not set to true, allowing it to explode multiple times.
+ /// This should never be used if it is damageable.
+ ///
+ [DataField]
+ public bool Repeatable;
+
///
/// Avoid somehow double-triggering this explosion (e.g. by damaging this entity from its own explosion.
///
diff --git a/Content.Server/Explosion/Components/RepeatingTriggerComponent.cs b/Content.Server/Explosion/Components/RepeatingTriggerComponent.cs
new file mode 100644
index 00000000000..cc08de53f90
--- /dev/null
+++ b/Content.Server/Explosion/Components/RepeatingTriggerComponent.cs
@@ -0,0 +1,25 @@
+using Content.Server.Explosion.EntitySystems;
+using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
+
+namespace Content.Server.Explosion.Components;
+
+///
+/// Constantly triggers after being added to an entity.
+///
+[RegisterComponent, Access(typeof(TriggerSystem))]
+[AutoGenerateComponentPause]
+public sealed partial class RepeatingTriggerComponent : Component
+{
+ ///
+ /// How long to wait between triggers.
+ /// The first trigger starts this long after the component is added.
+ ///
+ [DataField]
+ public TimeSpan Delay = TimeSpan.FromSeconds(1);
+
+ ///
+ /// When the next trigger will be.
+ ///
+ [DataField(customTypeSerializer: typeof(TimeOffsetSerializer)), AutoPausedField]
+ public TimeSpan NextTrigger;
+}
diff --git a/Content.Server/Explosion/EntitySystems/ExplosionSystem.cs b/Content.Server/Explosion/EntitySystems/ExplosionSystem.cs
index 1f91b28ec2b..eb2cf9b6548 100644
--- a/Content.Server/Explosion/EntitySystems/ExplosionSystem.cs
+++ b/Content.Server/Explosion/EntitySystems/ExplosionSystem.cs
@@ -165,7 +165,7 @@ public void TriggerExplosive(EntityUid uid, ExplosiveComponent? explosive = null
if (explosive.Exploded)
return;
- explosive.Exploded = true;
+ explosive.Exploded = !explosive.Repeatable;
// Override the explosion intensity if optional arguments were provided.
if (radius != null)
diff --git a/Content.Server/Explosion/EntitySystems/TriggerSystem.cs b/Content.Server/Explosion/EntitySystems/TriggerSystem.cs
index eb5aeec8158..37c63438152 100644
--- a/Content.Server/Explosion/EntitySystems/TriggerSystem.cs
+++ b/Content.Server/Explosion/EntitySystems/TriggerSystem.cs
@@ -98,6 +98,7 @@ public override void Initialize()
SubscribeLocalEvent(OnStepTriggered);
SubscribeLocalEvent(OnSlipTriggered);
SubscribeLocalEvent(OnEmptyTriggered);
+ SubscribeLocalEvent(OnRepeatInit);
SubscribeLocalEvent(OnSpawnTrigger);
SubscribeLocalEvent(HandleDeleteTrigger);
@@ -278,6 +279,11 @@ private void OnEmptyTriggered(EntityUid uid, TriggerWhenEmptyComponent component
Trigger(uid, args.EmptyGun);
}
+ private void OnRepeatInit(Entity ent, ref MapInitEvent args)
+ {
+ ent.Comp.NextTrigger = _timing.CurTime + ent.Comp.Delay;
+ }
+
public bool Trigger(EntityUid trigger, EntityUid? user = null)
{
var triggerEvent = new TriggerEvent(trigger, user);
@@ -360,6 +366,7 @@ public override void Update(float frameTime)
UpdateProximity();
UpdateTimer(frameTime);
UpdateTimedCollide(frameTime);
+ UpdateRepeat();
}
private void UpdateTimer(float frameTime)
@@ -394,5 +401,19 @@ private void UpdateTimer(float frameTime)
_appearance.SetData(uid, TriggerVisuals.VisualState, TriggerVisualState.Unprimed, appearance);
}
}
+
+ private void UpdateRepeat()
+ {
+ var now = _timing.CurTime;
+ var query = EntityQueryEnumerator();
+ while (query.MoveNext(out var uid, out var comp))
+ {
+ if (comp.NextTrigger > now)
+ continue;
+
+ comp.NextTrigger = now + comp.Delay;
+ Trigger(uid);
+ }
+ }
}
}
diff --git a/Content.Shared/Access/Components/IdCardConsoleComponent.cs b/Content.Shared/Access/Components/IdCardConsoleComponent.cs
index 5fe5fe1024b..16aaae9b45b 100644
--- a/Content.Shared/Access/Components/IdCardConsoleComponent.cs
+++ b/Content.Shared/Access/Components/IdCardConsoleComponent.cs
@@ -72,7 +72,6 @@ public WriteToTargetIdMessage(string fullName, string jobTitle, List
public static int CountFreeHands(this HandsComponent component) => component.Hands.Values.Count(hand => hand.IsEmpty);
+ ///
+ /// Get the number of hands that are not currently holding anything. This is a LinQ method, not a property, so
+ /// cache it instead of accessing this multiple times.
+ ///
+ public static int CountFreeableHands(this Entity component, SharedHandsSystem system)
+ {
+ return system.CountFreeableHands(component);
+ }
+
///
/// Get a list of hands that are currently holding nothing. This is a LinQ method, not a property, so cache
/// it instead of accessing this multiple times.
diff --git a/Content.Shared/Hands/EntitySystems/SharedHandsSystem.cs b/Content.Shared/Hands/EntitySystems/SharedHandsSystem.cs
index fd732009e9a..e48aafeab52 100644
--- a/Content.Shared/Hands/EntitySystems/SharedHandsSystem.cs
+++ b/Content.Shared/Hands/EntitySystems/SharedHandsSystem.cs
@@ -5,7 +5,6 @@
using Content.Shared.Hands.Components;
using Content.Shared.Interaction;
using Content.Shared.Inventory.VirtualItem;
-using Content.Shared.Item;
using Content.Shared.Storage.EntitySystems;
using Robust.Shared.Containers;
using Robust.Shared.Input.Binding;
@@ -299,4 +298,16 @@ public bool TryGetHand(EntityUid handsUid, string handId, [NotNullWhen(true)] ou
return hands.Hands.TryGetValue(handId, out hand);
}
+
+ public int CountFreeableHands(Entity hands)
+ {
+ var freeable = 0;
+ foreach (var hand in hands.Comp.Hands.Values)
+ {
+ if (hand.IsEmpty || CanDropHeld(hands, hand))
+ freeable++;
+ }
+
+ return freeable;
+ }
}
diff --git a/Content.Shared/Inventory/VirtualItem/SharedVirtualItemSystem.cs b/Content.Shared/Inventory/VirtualItem/SharedVirtualItemSystem.cs
index e45530e4582..b31cc755763 100644
--- a/Content.Shared/Inventory/VirtualItem/SharedVirtualItemSystem.cs
+++ b/Content.Shared/Inventory/VirtualItem/SharedVirtualItemSystem.cs
@@ -4,6 +4,7 @@
using Content.Shared.Interaction;
using Content.Shared.Inventory.Events;
using Content.Shared.Item;
+using Content.Shared.Popups;
using Robust.Shared.Containers;
using Robust.Shared.Network;
using Robust.Shared.Prototypes;
@@ -29,6 +30,7 @@ public abstract class SharedVirtualItemSystem : EntitySystem
[Dependency] private readonly SharedItemSystem _itemSystem = default!;
[Dependency] private readonly InventorySystem _inventorySystem = default!;
[Dependency] private readonly SharedHandsSystem _handsSystem = default!;
+ [Dependency] private readonly SharedPopupSystem _popup = default!;
[ValidatePrototypeId]
private const string VirtualItem = "VirtualItem";
@@ -71,23 +73,53 @@ private void OnBeforeRangedInteract(Entity ent, ref Before
}
#region Hands
+
///
/// Spawns a virtual item in a empty hand
///
/// The entity we will make a virtual entity copy of
/// The entity that we want to insert the virtual entity
- public bool TrySpawnVirtualItemInHand(EntityUid blockingEnt, EntityUid user)
+ /// Whether or not to try and drop other items to make space
+ public bool TrySpawnVirtualItemInHand(EntityUid blockingEnt, EntityUid user, bool dropOthers = false)
{
- return TrySpawnVirtualItemInHand(blockingEnt, user, out _);
+ return TrySpawnVirtualItemInHand(blockingEnt, user, out _, dropOthers);
}
- ///
- public bool TrySpawnVirtualItemInHand(EntityUid blockingEnt, EntityUid user, [NotNullWhen(true)] out EntityUid? virtualItem)
+ ///
+ public bool TrySpawnVirtualItemInHand(EntityUid blockingEnt, EntityUid user, [NotNullWhen(true)] out EntityUid? virtualItem, bool dropOthers = false)
{
- if (!TrySpawnVirtualItem(blockingEnt, user, out virtualItem) || !_handsSystem.TryGetEmptyHand(user, out var hand))
+ virtualItem = null;
+ if (!_handsSystem.TryGetEmptyHand(user, out var empty))
+ {
+ if (!dropOthers)
+ return false;
+
+ foreach (var hand in _handsSystem.EnumerateHands(user))
+ {
+ if (hand.HeldEntity is not { } held)
+ continue;
+
+ if (held == blockingEnt || HasComp(held))
+ continue;
+
+ if (!_handsSystem.TryDrop(user, hand))
+ continue;
+
+ if (!TerminatingOrDeleted(held))
+ _popup.PopupClient(Loc.GetString("virtual-item-dropped-other", ("dropped", held)), user, user);
+
+ empty = hand;
+ break;
+ }
+ }
+
+ if (empty == null)
+ return false;
+
+ if (!TrySpawnVirtualItem(blockingEnt, user, out virtualItem))
return false;
- _handsSystem.DoPickup(user, hand, virtualItem.Value);
+ _handsSystem.DoPickup(user, empty, virtualItem.Value);
return true;
}
@@ -120,6 +152,7 @@ public void DeleteInHandsMatching(EntityUid user, EntityUid matching)
/// The entity we will make a virtual entity copy of
/// The entity that we want to insert the virtual entity
/// The slot to which we will insert the virtual entity (could be the "shoes" slot, for example)
+ /// Whether or not to force an equip
public bool TrySpawnVirtualItemInInventory(EntityUid blockingEnt, EntityUid user, string slot, bool force = false)
{
return TrySpawnVirtualItemInInventory(blockingEnt, user, slot, force, out _);
@@ -140,6 +173,8 @@ public bool TrySpawnVirtualItemInInventory(EntityUid blockingEnt, EntityUid user
/// that's done check if the found virtual entity is a copy of our matching entity,
/// if it is, delete it
///
+ /// The entity that we want to delete the virtual entity from
+ /// The entity that made the virtual entity
/// Set this param if you have the name of the slot, it avoids unnecessary queries
public void DeleteInSlotMatching(EntityUid user, EntityUid matching, string? slotName = null)
{
@@ -178,6 +213,7 @@ public void DeleteInSlotMatching(EntityUid user, EntityUid matching, string? slo
///
/// The entity we will make a virtual entity copy of
/// The entity that we want to insert the virtual entity
+ /// The virtual item, if spawned
public bool TrySpawnVirtualItem(EntityUid blockingEnt, EntityUid user, [NotNullWhen(true)] out EntityUid? virtualItem)
{
if (_netManager.IsClient)
diff --git a/Content.Shared/Preferences/Loadouts/RoleLoadout.cs b/Content.Shared/Preferences/Loadouts/RoleLoadout.cs
index e1c6f8395d0..ff3db32fd6f 100644
--- a/Content.Shared/Preferences/Loadouts/RoleLoadout.cs
+++ b/Content.Shared/Preferences/Loadouts/RoleLoadout.cs
@@ -74,12 +74,20 @@ public void EnsureValid(ICommonSession session, IDependencyCollection collection
{
var loadout = loadouts[i];
+ // Old prototype or otherwise invalid.
if (!protoManager.TryIndex(loadout.Prototype, out var loadoutProto))
{
loadouts.RemoveAt(i);
continue;
}
+ // Malicious client maybe, check the group even has it.
+ if (!groupProto.Loadouts.Contains(loadout.Prototype))
+ {
+ loadouts.RemoveAt(i);
+ continue;
+ }
+
// Validate the loadout can be applied (e.g. points).
if (!IsValid(session, loadout.Prototype, collection, out _))
{
diff --git a/Content.Shared/Weapons/Ranged/Components/ActionGunComponent.cs b/Content.Shared/Weapons/Ranged/Components/ActionGunComponent.cs
new file mode 100644
index 00000000000..112339efd74
--- /dev/null
+++ b/Content.Shared/Weapons/Ranged/Components/ActionGunComponent.cs
@@ -0,0 +1,37 @@
+using Content.Shared.Actions;
+using Content.Shared.Weapons.Ranged.Systems;
+using Robust.Shared.GameStates;
+using Robust.Shared.Prototypes;
+
+namespace Content.Shared.Weapons.Ranged.Components;
+
+///
+/// Lets you shoot a gun using an action.
+///
+[RegisterComponent, NetworkedComponent, Access(typeof(ActionGunSystem))]
+public sealed partial class ActionGunComponent : Component
+{
+ ///
+ /// Action to create, must use .
+ ///
+ [DataField(required: true)]
+ public EntProtoId Action = string.Empty;
+
+ [DataField]
+ public EntityUid? ActionEntity;
+
+ ///
+ /// Prototype of gun entity to spawn.
+ /// Deleted when this component is removed.
+ ///
+ [DataField(required: true)]
+ public EntProtoId GunProto = string.Empty;
+
+ [DataField]
+ public EntityUid? Gun;
+}
+
+///
+/// Action event for to shoot at a position.
+///
+public sealed partial class ActionGunShootEvent : WorldTargetActionEvent;
diff --git a/Content.Shared/Weapons/Ranged/Components/GunRequiresWieldComponent.cs b/Content.Shared/Weapons/Ranged/Components/GunRequiresWieldComponent.cs
index 2ae71334b47..fa3732209f5 100644
--- a/Content.Shared/Weapons/Ranged/Components/GunRequiresWieldComponent.cs
+++ b/Content.Shared/Weapons/Ranged/Components/GunRequiresWieldComponent.cs
@@ -6,8 +6,13 @@ namespace Content.Shared.Weapons.Ranged.Components;
///
/// Indicates that this gun requires wielding to be useable.
///
-[RegisterComponent, NetworkedComponent, Access(typeof(WieldableSystem))]
+[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
+[Access(typeof(WieldableSystem))]
public sealed partial class GunRequiresWieldComponent : Component
{
+ [DataField, AutoNetworkedField]
+ public TimeSpan LastPopup;
+ [DataField, AutoNetworkedField]
+ public TimeSpan PopupCooldown = TimeSpan.FromSeconds(1);
}
diff --git a/Content.Shared/Weapons/Ranged/Components/GunWieldBonusComponent.cs b/Content.Shared/Weapons/Ranged/Components/GunWieldBonusComponent.cs
index ce96639e3c4..522319ccbd3 100644
--- a/Content.Shared/Weapons/Ranged/Components/GunWieldBonusComponent.cs
+++ b/Content.Shared/Weapons/Ranged/Components/GunWieldBonusComponent.cs
@@ -33,4 +33,7 @@ public sealed partial class GunWieldBonusComponent : Component
///
[DataField, AutoNetworkedField]
public Angle AngleIncrease = Angle.FromDegrees(0);
+
+ [DataField]
+ public LocId? WieldBonusExamineMessage = "gunwieldbonus-component-examine";
}
diff --git a/Content.Shared/Weapons/Ranged/Events/ShotAttemptedEvent.cs b/Content.Shared/Weapons/Ranged/Events/ShotAttemptedEvent.cs
index 40925ad614c..d61862bf1a0 100644
--- a/Content.Shared/Weapons/Ranged/Events/ShotAttemptedEvent.cs
+++ b/Content.Shared/Weapons/Ranged/Events/ShotAttemptedEvent.cs
@@ -1,3 +1,5 @@
+using Content.Shared.Weapons.Ranged.Components;
+
namespace Content.Shared.Weapons.Ranged.Events;
///
@@ -15,7 +17,7 @@ public record struct ShotAttemptedEvent
///
/// The gun being shot.
///
- public EntityUid Used;
+ public Entity Used;
public bool Cancelled { get; private set; }
diff --git a/Content.Shared/Weapons/Ranged/Systems/ActionGunSystem.cs b/Content.Shared/Weapons/Ranged/Systems/ActionGunSystem.cs
new file mode 100644
index 00000000000..f3dfe8a2a03
--- /dev/null
+++ b/Content.Shared/Weapons/Ranged/Systems/ActionGunSystem.cs
@@ -0,0 +1,41 @@
+using Content.Shared.Actions;
+using Content.Shared.Weapons.Ranged.Components;
+
+namespace Content.Shared.Weapons.Ranged.Systems;
+
+public sealed class ActionGunSystem : EntitySystem
+{
+ [Dependency] private readonly SharedActionsSystem _actions = default!;
+ [Dependency] private readonly SharedGunSystem _gun = default!;
+
+ public override void Initialize()
+ {
+ base.Initialize();
+
+ SubscribeLocalEvent(OnMapInit);
+ SubscribeLocalEvent(OnShutdown);
+ SubscribeLocalEvent(OnShoot);
+ }
+
+ private void OnMapInit(Entity ent, ref MapInitEvent args)
+ {
+ if (string.IsNullOrEmpty(ent.Comp.Action))
+ return;
+
+ _actions.AddAction(ent, ref ent.Comp.ActionEntity, ent.Comp.Action);
+ ent.Comp.Gun = Spawn(ent.Comp.GunProto);
+ }
+
+ private void OnShutdown(Entity ent, ref ComponentShutdown args)
+ {
+ if (ent.Comp.Gun is {} gun)
+ QueueDel(gun);
+ }
+
+ private void OnShoot(Entity ent, ref ActionGunShootEvent args)
+ {
+ if (TryComp(ent.Comp.Gun, out var gun))
+ _gun.AttemptShoot(ent, ent.Comp.Gun.Value, gun, args.Target);
+ }
+}
+
diff --git a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs
index c592a241419..eb597467fdc 100644
--- a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs
+++ b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs
@@ -239,7 +239,7 @@ private void AttemptShoot(EntityUid user, EntityUid gunUid, GunComponent gun)
var prevention = new ShotAttemptedEvent
{
User = user,
- Used = gunUid
+ Used = (gunUid, gun)
};
RaiseLocalEvent(gunUid, ref prevention);
if (prevention.Cancelled)
diff --git a/Content.Shared/Wieldable/WieldableSystem.cs b/Content.Shared/Wieldable/WieldableSystem.cs
index ba3f787a4bb..c09044f84b4 100644
--- a/Content.Shared/Wieldable/WieldableSystem.cs
+++ b/Content.Shared/Wieldable/WieldableSystem.cs
@@ -1,3 +1,4 @@
+using Content.Shared.Examine;
using Content.Shared.Hands;
using Content.Shared.Hands.Components;
using Content.Shared.Hands.EntitySystems;
@@ -15,7 +16,7 @@
using Content.Shared.Weapons.Ranged.Systems;
using Content.Shared.Wieldable.Components;
using Robust.Shared.Audio.Systems;
-using Robust.Shared.Player;
+using Robust.Shared.Timing;
namespace Content.Shared.Wieldable;
@@ -29,6 +30,7 @@ public sealed class WieldableSystem : EntitySystem
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly UseDelaySystem _delay = default!;
[Dependency] private readonly SharedGunSystem _gun = default!;
+ [Dependency] private readonly IGameTiming _timing = default!;
public override void Initialize()
{
@@ -39,12 +41,14 @@ public override void Initialize()
SubscribeLocalEvent(OnItemLeaveHand);
SubscribeLocalEvent(OnVirtualItemDeleted);
SubscribeLocalEvent>(AddToggleWieldVerb);
+ SubscribeLocalEvent(OnDeselectWieldable);
SubscribeLocalEvent(OnMeleeAttempt);
- SubscribeLocalEvent(OnShootAttempt);
+ SubscribeLocalEvent(OnShootAttempt);
SubscribeLocalEvent(OnGunWielded);
SubscribeLocalEvent(OnGunUnwielded);
SubscribeLocalEvent(OnGunRefreshModifiers);
+ SubscribeLocalEvent(OnExamine);
SubscribeLocalEvent(OnGetMeleeDamage);
}
@@ -59,16 +63,21 @@ private void OnMeleeAttempt(EntityUid uid, MeleeRequiresWieldComponent component
}
}
- private void OnShootAttempt(EntityUid uid, GunRequiresWieldComponent component, ref AttemptShootEvent args)
+ private void OnShootAttempt(EntityUid uid, GunRequiresWieldComponent component, ref ShotAttemptedEvent args)
{
if (TryComp(uid, out var wieldable) &&
!wieldable.Wielded)
{
- args.Cancelled = true;
+ args.Cancel();
- if (!HasComp(uid) && !HasComp(uid))
+ var time = _timing.CurTime;
+ if (time > component.LastPopup + component.PopupCooldown &&
+ !HasComp(uid) &&
+ !HasComp(uid))
{
- args.Message = Loc.GetString("wieldable-component-requires", ("item", uid));
+ component.LastPopup = time;
+ var message = Loc.GetString("wieldable-component-requires", ("item", uid));
+ _popupSystem.PopupClient(message, args.Used, args.User);
}
}
}
@@ -83,6 +92,14 @@ private void OnGunWielded(EntityUid uid, GunWieldBonusComponent component, ref I
_gun.RefreshModifiers(uid);
}
+ private void OnDeselectWieldable(EntityUid uid, WieldableComponent component, HandDeselectedEvent args)
+ {
+ if (!component.Wielded)
+ return;
+
+ TryUnwield(uid, component, args.User);
+ }
+
private void OnGunRefreshModifiers(Entity bonus, ref GunRefreshModifiersEvent args)
{
if (TryComp(bonus, out WieldableComponent? wield) &&
@@ -95,6 +112,12 @@ private void OnGunRefreshModifiers(Entity bonus, ref Gun
}
}
+ private void OnExamine(EntityUid uid, GunWieldBonusComponent component, ref ExaminedEvent args)
+ {
+ if (component.WieldBonusExamineMessage != null)
+ args.PushText(Loc.GetString(component.WieldBonusExamineMessage));
+ }
+
private void AddToggleWieldVerb(EntityUid uid, WieldableComponent component, GetVerbsEvent args)
{
if (args.Hands == null || !args.CanAccess || !args.CanInteract)
@@ -147,7 +170,7 @@ public bool CanWield(EntityUid uid, WieldableComponent component, EntityUid user
return false;
}
- if (hands.CountFreeHands() < component.FreeHandsRequired)
+ if (_handsSystem.CountFreeableHands((user, hands)) < component.FreeHandsRequired)
{
if (!quiet)
{
@@ -188,9 +211,21 @@ public bool TryWield(EntityUid used, WieldableComponent component, EntityUid use
if (component.WieldSound != null)
_audioSystem.PlayPredicted(component.WieldSound, used, user);
+ var virtuals = new List();
for (var i = 0; i < component.FreeHandsRequired; i++)
{
- _virtualItemSystem.TrySpawnVirtualItemInHand(used, user);
+ if (_virtualItemSystem.TrySpawnVirtualItemInHand(used, user, out var virtualItem, true))
+ {
+ virtuals.Add(virtualItem.Value);
+ continue;
+ }
+
+ foreach (var existingVirtual in virtuals)
+ {
+ QueueDel(existingVirtual);
+ }
+
+ return false;
}
if (TryComp(used, out UseDelayComponent? useDelay)
diff --git a/Resources/Audio/_NF/Jukebox/attributions.yml b/Resources/Audio/_NF/Jukebox/attributions.yml
new file mode 100644
index 00000000000..92e453f3ef3
--- /dev/null
+++ b/Resources/Audio/_NF/Jukebox/attributions.yml
@@ -0,0 +1,4 @@
+- files: ["lateraligator.ogg"]
+ license: "CC-BY-3.0"
+ copyright: "Later Alligator By Silverman Sound Studios. Converted to mono ogg"
+ source: "https://soundcloud.com/silvermansound/later-alligator"
diff --git a/Resources/Audio/_NF/Jukebox/lateraligator.ogg b/Resources/Audio/_NF/Jukebox/lateraligator.ogg
new file mode 100644
index 00000000000..e4186cccdf9
Binary files /dev/null and b/Resources/Audio/_NF/Jukebox/lateraligator.ogg differ
diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml
index f6548202538..8489a3c74a0 100644
--- a/Resources/Changelog/Changelog.yml
+++ b/Resources/Changelog/Changelog.yml
@@ -4710,3 +4710,44 @@ Entries:
Frontier.
id: 4997
time: '2024-05-31T11:11:02.0000000+00:00'
+- author: dvir01
+ changes:
+ - type: Tweak
+ message: Added more selections to loadouts options! make sure to pick new items!
+ id: 4998
+ time: '2024-06-01T12:46:43.0000000+00:00'
+- author: Katarn1933
+ changes:
+ - type: Add
+ message: New swampy tune for jukebox
+ id: 4999
+ time: '2024-06-01T13:03:59.0000000+00:00'
+- author: erhardsteinhauer
+ changes:
+ - type: Add
+ message: >-
+ Added new messenger bags: arcadia, chaplain, chief engineer, contractor,
+ SR, security, black, blue, green, orange, red, purple, brown, light
+ brown, white. Most of new messenger bags available through loadouts.
+ - type: Tweak
+ message: >-
+ Resprited some messenger bags a bit (engineering, janitor, cultist, both
+ NFSD).
+ id: 5000
+ time: '2024-06-01T14:44:45.0000000+00:00'
+- author: erhardsteinhauer
+ changes:
+ - type: Fix
+ message: >-
+ Mail RPDS, N2554 Pattern Repeater and BB gun no longer turn invisible if
+ wielded or put in suit storage slot.
+ id: 5001
+ time: '2024-06-01T15:17:54.0000000+00:00'
+- author: Leander
+ changes:
+ - type: Tweak
+ message: >-
+ Silver Industries has released the argenti 2.0 with improved chamber and
+ shooting speed.
+ id: 5002
+ time: '2024-06-01T16:30:25.0000000+00:00'
diff --git a/Resources/Locale/en-US/_NF/preferences/loadout-groups.ftl b/Resources/Locale/en-US/_NF/preferences/loadout-groups.ftl
index b2e2b077145..79a9a45c33a 100644
--- a/Resources/Locale/en-US/_NF/preferences/loadout-groups.ftl
+++ b/Resources/Locale/en-US/_NF/preferences/loadout-groups.ftl
@@ -14,12 +14,6 @@ loadout-group-contractor-face = mask
loadout-group-contractor-utility = tools
loadout-group-contractor-fun = fun
loadout-group-contractor-trinkets = trinkets
-# Security
-
-loadout-group-security-guard-jumpsuit = head
-loadout-group-security-guard-jumpsuit = jumpsuit
-loadout-group-security-guard-gloves = gloves
-loadout-group-security-guard-head = head
-loadout-group-security-guard-outerclothing = outer clothing
-loadout-group-security-guard-shoes = shoes
-loadout-group-security-guard-id = ID
+loadout-group-contractor-survival-box = survival box
+loadout-group-contractor-encryption-key = encryption keys
+loadout-group-contractor-implanter = implanters
\ No newline at end of file
diff --git a/Resources/Locale/en-US/virtual/virtual-item.ftl b/Resources/Locale/en-US/virtual/virtual-item.ftl
new file mode 100644
index 00000000000..cb91f24cf7c
--- /dev/null
+++ b/Resources/Locale/en-US/virtual/virtual-item.ftl
@@ -0,0 +1 @@
+virtual-item-dropped-other = You dropped {THE($dropped)}!
diff --git a/Resources/Locale/en-US/wieldable/wieldable-component.ftl b/Resources/Locale/en-US/wieldable/wieldable-component.ftl
index 91eee8c2eaf..84b58224a77 100644
--- a/Resources/Locale/en-US/wieldable/wieldable-component.ftl
+++ b/Resources/Locale/en-US/wieldable/wieldable-component.ftl
@@ -1,4 +1,4 @@
-### Locale for wielding items; i.e. two-handing them
+### Locale for wielding items; i.e. two-handing them
wieldable-verb-text-wield = Wield
wieldable-verb-text-unwield = Unwield
@@ -17,3 +17,4 @@ wieldable-component-not-in-hands = { CAPITALIZE(THE($item)) } isn't in your hand
wieldable-component-requires = { CAPITALIZE(THE($item))} must be wielded!
+gunwieldbonus-component-examine = This weapon has improved accuracy when wielded.
diff --git a/Resources/Prototypes/Access/misc.yml b/Resources/Prototypes/Access/misc.yml
index dd47e1f015d..db359351e79 100644
--- a/Resources/Prototypes/Access/misc.yml
+++ b/Resources/Prototypes/Access/misc.yml
@@ -20,7 +20,6 @@
- Mail # Frontier
- Medical
- Mercenary # Frontier
- - Pilot # Frontier
- Quartermaster
- Salvage
- Cargo
diff --git a/Resources/Prototypes/Catalog/Jukebox/Standard.yml b/Resources/Prototypes/Catalog/Jukebox/Standard.yml
index 7440428bd49..1cc80ff6e2f 100644
--- a/Resources/Prototypes/Catalog/Jukebox/Standard.yml
+++ b/Resources/Prototypes/Catalog/Jukebox/Standard.yml
@@ -38,4 +38,4 @@
id: sunset
name: PigeonBeans - Sunset
path:
- path: /Audio/Jukebox/sunset.ogg
+ path: /Audio/Jukebox/sunset.ogg
\ No newline at end of file
diff --git a/Resources/Prototypes/Catalog/VendingMachines/Inventories/ammo.yml b/Resources/Prototypes/Catalog/VendingMachines/Inventories/ammo.yml
index 447e2037996..26f71911eb7 100644
--- a/Resources/Prototypes/Catalog/VendingMachines/Inventories/ammo.yml
+++ b/Resources/Prototypes/Catalog/VendingMachines/Inventories/ammo.yml
@@ -7,16 +7,17 @@
WeaponSniperRepeater: 10
MagazineBoxLightRifle: 10
MagazineBoxLightRiflePractice: 10
-# MagazineBoxLightRifleRubber: 15 # Frontier - TODO: Restore Rubber
+ MagazineBoxLightRifleRubber: 15
WeaponShotgunDoubleBarreled: 10
+ WeaponRevolverArgenti: 10
BoxShotgunSlug: 10
BoxLethalshot: 10
BoxBeanbag: 10
BoxShotgunPractice: 10
- WeaponRevolverArgenti: 10
MagazineBoxRifle: 10
-# MagazineBoxRifleRubber: 15 # Frontier - TODO: Restore Rubber
- MagazineBoxRiflePractice: 10
+ MagazineBoxRifleRubber: 15
MagazineBoxMagnum: 10
+ SpeedLoaderRifleHeavy: 10
+ SpeedLoaderRifleHeavyRubber: 10
emaggedInventory:
WeaponPistolViper: 1
diff --git a/Resources/Prototypes/DeltaV/Entities/Objects/Fun/toy_guns.yml b/Resources/Prototypes/DeltaV/Entities/Objects/Fun/toy_guns.yml
index 9acf9740191..cbe7fea8475 100644
--- a/Resources/Prototypes/DeltaV/Entities/Objects/Fun/toy_guns.yml
+++ b/Resources/Prototypes/DeltaV/Entities/Objects/Fun/toy_guns.yml
@@ -1,6 +1,6 @@
- type: entity
name: BB Gun
- parent: BaseItem
+ parent: [BaseItem, BaseGunWieldable] # Frontier
id: WeaponRifleBB
description: The classic Red Ryder BB gun. Don't shoot your eye out.
components:
@@ -39,4 +39,4 @@
ents: []
- type: Appearance
- type: StaticPrice
- price: 2750
+ price: 500
diff --git a/Resources/Prototypes/Entities/Mobs/Player/dragon.yml b/Resources/Prototypes/Entities/Mobs/Player/dragon.yml
index c58577722c2..76260bb9e83 100644
--- a/Resources/Prototypes/Entities/Mobs/Player/dragon.yml
+++ b/Resources/Prototypes/Entities/Mobs/Player/dragon.yml
@@ -89,6 +89,12 @@
speedModifierThresholds:
250: 0.7
400: 0.5
+ # disable taking damage from fire, since its a fire breathing dragon
+ - type: Flammable
+ damage:
+ types: {}
+ - type: Temperature
+ heatDamageThreshold: 800
- type: Metabolizer
solutionOnBody: false
updateInterval: 0.25
@@ -134,15 +140,37 @@
- type: entity
parent: BaseMobDragon
id: MobDragon
+ suffix: No role or objectives
components:
- type: Dragon
spawnRiftAction: ActionSpawnRift
- # - type: GenericAntag
- # rule: Dragon
+ - type: ActionGun
+ action: ActionDragonsBreath
+ gunProto: DragonsBreathGun
- type: GuideHelp
guides:
- MinorAntagonists
+- type: entity
+ noSpawn: true
+ id: DragonsBreathGun
+ name: dragon's lung
+ description: For dragon's breathing
+ components:
+ - type: RechargeBasicEntityAmmo
+ rechargeCooldown: 5
+ rechargeSound:
+ path: /Audio/Animals/space_dragon_roar.ogg
+ - type: BasicEntityAmmoProvider
+ proto: ProjectileDragonsBreath
+ capacity: 1
+ count: 1
+ - type: Gun
+ soundGunshot:
+ path: /Audio/Animals/space_dragon_roar.ogg
+ soundEmpty: null
+ projectileSpeed: 5
+
- type: entity
parent: BaseMobDragon
id: MobDragonDungeon
@@ -181,6 +209,7 @@
state: icon
event: !type:DragonSpawnRiftActionEvent
useDelay: 1
+ priority: 3
- type: entity
id: ActionDevour
@@ -192,3 +221,18 @@
icon: { sprite : Interface/Actions/devour.rsi, state: icon }
iconOn: { sprite : Interface/Actions/devour.rsi, state: icon-on }
event: !type:DevourActionEvent
+ priority: 1
+
+- type: entity
+ noSpawn: true
+ id: ActionDragonsBreath
+ name: "[color=orange]Dragon's Breath[/color]"
+ description: Spew out flames at anyone foolish enough to attack you!
+ components:
+ - type: WorldTargetAction
+ # TODO: actual sprite
+ icon: { sprite : Objects/Weapons/Guns/Projectiles/magic.rsi, state: fireball }
+ event: !type:ActionGunShootEvent
+ priority: 2
+ checkCanAccess: false
+ range: 0
diff --git a/Resources/Prototypes/Entities/Objects/Tools/access_configurator.yml b/Resources/Prototypes/Entities/Objects/Tools/access_configurator.yml
index 65c958c16af..0c06c4d6e3d 100644
--- a/Resources/Prototypes/Entities/Objects/Tools/access_configurator.yml
+++ b/Resources/Prototypes/Entities/Objects/Tools/access_configurator.yml
@@ -44,7 +44,6 @@
- Maintenance
- Medical
- Mercenary # Frontier
- - Pilot # Frontier
- Quartermaster
- Research
- ResearchDirector
diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Boxes/light_rifle.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Boxes/light_rifle.yml
index d5fb4360a82..3241a892262 100644
--- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Boxes/light_rifle.yml
+++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Boxes/light_rifle.yml
@@ -102,4 +102,4 @@
map: ["enum.GunVisualLayers.Base"]
- state: mag-1
map: ["enum.GunVisualLayers.Mag"]
- - state: uranium
+ - state: uranium
\ No newline at end of file
diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Cartridges/caseless_rifle.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Cartridges/caseless_rifle.yml
index a35a42d8c2a..73f29189864 100644
--- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Cartridges/caseless_rifle.yml
+++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Cartridges/caseless_rifle.yml
@@ -43,3 +43,4 @@
- state: tip
map: [ "enum.AmmoVisualLayers.Tip" ]
color: "#dbdbdb"
+
diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Projectiles/caseless_rifle.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Projectiles/caseless_rifle.yml
index 741f0a4e1a0..5ce0bf82fe9 100644
--- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Projectiles/caseless_rifle.yml
+++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Projectiles/caseless_rifle.yml
@@ -19,3 +19,14 @@
damage:
types:
Blunt: 2
+
+- type: entity
+ id: BulletCaselessRifleRubber
+ name: bullet (.25 caseless rubber)
+ parent: BaseBulletRubber
+ noSpawn: true
+ components:
+ - type: Projectile
+ damage:
+ types:
+ Blunt: 3
diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Projectiles/light_rifle.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Projectiles/light_rifle.yml
index c6a4808b77b..3a0df2ac6c7 100644
--- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Projectiles/light_rifle.yml
+++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Projectiles/light_rifle.yml
@@ -20,6 +20,17 @@
types:
Blunt: 2
+- type: entity
+ id: BulletLightRifleRubber
+ name: bullet (.20 rifle rubber)
+ parent: BaseBulletRubber
+ noSpawn: true
+ components:
+ - type: Projectile
+ damage:
+ types:
+ Blunt: 3
+
- type: entity
id: BulletLightRifleIncendiary
parent: BaseBulletIncendiary
diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Projectiles/magnum.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Projectiles/magnum.yml
index 798de9fa853..1b5cf7890ba 100644
--- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Projectiles/magnum.yml
+++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Projectiles/magnum.yml
@@ -20,6 +20,19 @@
types:
Blunt: 1
+- type: entity
+ id: BulletMagnumRubber
+ name: bullet (.45 magnum rubber)
+ parent: BaseBulletRubber
+ noSpawn: true
+ components:
+ - type: Projectile
+ damage:
+ types:
+ Blunt: 3
+ - type: StaminaDamageOnCollide
+ damage: 35 # 3 hits to stun cuz revolver
+
- type: entity
id: BulletMagnumIncendiary
parent: BaseBulletIncendiary
@@ -31,7 +44,7 @@
types:
Blunt: 3
Heat: 32
-
+
- type: entity
id: BulletMagnumAP
name: bullet (.45 magnum armor-piercing)
diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Projectiles/pistol.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Projectiles/pistol.yml
index 3cfcc0cf206..086a8dc914f 100644
--- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Projectiles/pistol.yml
+++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Projectiles/pistol.yml
@@ -20,6 +20,17 @@
types:
Blunt: 2
+- type: entity
+ id: BulletPistolRubber
+ name: bullet (.35 auto rubber)
+ parent: BaseBulletRubber
+ noSpawn: true
+ components:
+ - type: Projectile
+ damage:
+ types:
+ Blunt: 3
+
- type: entity
id: BulletPistolIncendiary
parent: BaseBulletIncendiary
diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Projectiles/rifle.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Projectiles/rifle.yml
index 6f6fa0f9077..2113916cf52 100644
--- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Projectiles/rifle.yml
+++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Projectiles/rifle.yml
@@ -20,6 +20,17 @@
types:
Blunt: 2
+- type: entity
+ id: BulletRifleRubber
+ name: bullet (0.20 rifle rubber)
+ parent: BaseBulletRubber
+ noSpawn: true
+ components:
+ - type: Projectile
+ damage:
+ types:
+ Blunt: 3
+
- type: entity
id: BulletRifleIncendiary
parent: BaseBulletIncendiary
@@ -31,7 +42,7 @@
types:
Blunt: 2
Heat: 15
-
+
- type: entity
id: BulletRifleUranium
parent: BaseBulletUranium
@@ -43,4 +54,4 @@
types:
Radiation: 7
Piercing: 8
-
+
diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Basic/base_wieldable.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Basic/base_wieldable.yml
new file mode 100644
index 00000000000..cf858e17374
--- /dev/null
+++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Basic/base_wieldable.yml
@@ -0,0 +1,12 @@
+# A basic inheritable template for a gun that is wieldable and has the standard inaccuracy.
+- type: entity
+ id: BaseGunWieldable
+ abstract: true
+ components:
+ - type: Wieldable
+ - type: GunWieldBonus
+ minAngle: -20
+ maxAngle: -30
+ - type: Gun
+ minAngle: 21
+ maxAngle: 32
diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Battery/battery_guns.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Battery/battery_guns.yml
index 576545f8e86..642447b49e5 100644
--- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Battery/battery_guns.yml
+++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Battery/battery_guns.yml
@@ -204,7 +204,7 @@
- type: entity
name: laser rifle
- parent: BaseWeaponBattery
+ parent: [BaseWeaponBattery, BaseGunWieldable]
id: WeaponLaserCarbine
description: A simple civilian grade laser carbine, the workhorse of many private security organizations.
components:
@@ -271,7 +271,7 @@
- type: entity
name: pulse carbine
- parent: BaseWeaponBattery
+ parent: [BaseWeaponBattery, BaseGunWieldable]
id: WeaponPulseCarbine
description: A high tech energy carbine favoured by the NT-ERT operatives. On the handle is a label that says 'for authorized use only.'
components:
@@ -302,7 +302,7 @@
- type: entity
name: pulse rifle
- parent: BaseWeaponBattery
+ parent: [BaseWeaponBattery, BaseGunWieldable]
id: WeaponPulseRifle
description: A weapon that is almost as infamous as its users. On the handle is a label that says 'for authorized use only.'
components:
@@ -329,7 +329,7 @@
- type: entity
name: laser cannon
- parent: BaseWeaponBattery
+ parent: [BaseWeaponBattery, BaseGunWieldable]
id: WeaponLaserCannon
description: A heavy duty, high powered laser weapon. On the handle is a label that says 'for authorized use only.'
components:
@@ -388,7 +388,7 @@
- type: entity
name: x-ray cannon
- parent: BaseWeaponBattery
+ parent: [BaseWeaponBattery, BaseGunWieldable]
id: WeaponXrayCannon
description: An illegal and experimental weapon that uses concentrated x-ray energy against its target.
components:
diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Launchers/launchers.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Launchers/launchers.yml
index 9f94ed2c52b..82a36357455 100644
--- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Launchers/launchers.yml
+++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Launchers/launchers.yml
@@ -22,7 +22,7 @@
- type: entity
name: china lake
- parent: BaseWeaponLauncher
+ parent: [BaseWeaponLauncher, BaseGunWieldable]
id: WeaponLauncherChinaLake
description: PLOOP
components:
diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/magic.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/magic.yml
index 3556d1c8f8b..d6adcd614e3 100644
--- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/magic.yml
+++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/magic.yml
@@ -30,6 +30,39 @@
- type: IgniteOnCollide
fireStacks: 0.35
+- type: entity
+ noSpawn: true
+ parent: BaseBulletTrigger
+ id: ProjectileDragonsBreath
+ name: dragon's breath
+ description: Try not to get toasted.
+ components:
+ - type: PointLight
+ color: "#E25822"
+ radius: 3.0
+ energy: 5.0
+ - type: Sprite
+ sprite: Objects/Weapons/Guns/Projectiles/magic.rsi
+ layers:
+ - state: fireball
+ shader: unshaded
+ - type: IgnitionSource
+ temperature: 1000
+ ignited: true
+ - type: RepeatingTrigger
+ delay: 0.5 # line of fire as well as if it hits something
+ - type: ExplodeOnTrigger
+ - type: Explosive
+ explosionType: FireBomb
+ totalIntensity: 5 # low intensity, the point is to burn attackers not to break open walls, dragons can just eat them
+ intensitySlope: 1
+ maxIntensity: 3
+ canCreateVacuum: false
+ deleteAfterExplosion: false
+ repeatable: true
+ - type: TimedDespawn
+ lifetime: 5
+
- type: entity
id: ProjectileAnomalyFireball
name: fireball
diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/projectiles.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/projectiles.yml
index 60121fde792..7f9ce36f2bd 100644
--- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/projectiles.yml
+++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/projectiles.yml
@@ -104,6 +104,25 @@
types:
Blunt: 1
+- type: entity
+ id: BaseBulletRubber
+ name: base bullet rubber
+ parent: BaseBullet
+ noSpawn: true
+ components:
+ - type: Sprite
+ sprite: Objects/Weapons/Guns/Projectiles/projectiles2.rsi
+ layers:
+ - state: rubber
+ - type: Projectile
+ damage:
+ types:
+ Blunt: 3
+ soundHit:
+ path: /Audio/Weapons/Guns/Hits/snap.ogg
+ - type: StaminaDamageOnCollide
+ damage: 22 # 5 hits to stun sounds reasonable
+
- type: entity
id: BaseBulletIncendiary
name: base bullet incendiary
diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Rifles/rifles.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Rifles/rifles.yml
index ef83e6c5722..50d8ca7c597 100644
--- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Rifles/rifles.yml
+++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Rifles/rifles.yml
@@ -1,6 +1,6 @@
- type: entity
name: BaseWeaponRifle
- parent: BaseItem
+ parent: [BaseItem, BaseGunWieldable]
id: BaseWeaponRifle
description: A rooty tooty point and shooty.
abstract: true
@@ -186,3 +186,4 @@
steps: 1
zeroVisible: true
- type: Appearance
+
diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/SMGs/smgs.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/SMGs/smgs.yml
index 45be47f79c0..852aaa7c8b8 100644
--- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/SMGs/smgs.yml
+++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/SMGs/smgs.yml
@@ -20,7 +20,7 @@
maxAngle: 16
fireRate: 8
angleIncrease: 3
- angleDecay: 16
+ angleDecay: 16
selectedMode: FullAuto
availableModes:
- SemiAuto
@@ -80,7 +80,7 @@
- type: entity
name: C-20r sub machine gun
- parent: BaseWeaponSubMachineGun
+ parent: [BaseWeaponSubMachineGun, BaseGunWieldable]
id: WeaponSubMachineGunC20r
description: An illegal firearm that is often used by the infamous nuclear operatives. Uses .35 auto ammo.
components:
@@ -94,6 +94,8 @@
- type: Clothing
sprite: Objects/Weapons/Guns/SMGs/c20r.rsi
- type: Gun
+ minAngle: 21
+ maxAngle: 32
shotsPerBurst: 5
availableModes:
- SemiAuto
@@ -112,7 +114,7 @@
- type: entity
name: Drozd
- parent: BaseWeaponSubMachineGun
+ parent: [BaseWeaponSubMachineGun, BaseGunWieldable]
id: WeaponSubMachineGunDrozd
description: An excellent fully automatic Heavy SMG. An illegal firearm often used by Syndicate agents.
components:
@@ -126,6 +128,8 @@
- type: Clothing
sprite: Objects/Weapons/Guns/SMGs/drozd.rsi
- type: Gun
+ minAngle: 21
+ maxAngle: 32
fireRate: 6
selectedMode: FullAuto
soundGunshot:
@@ -231,7 +235,7 @@
minAngle: 1
maxAngle: 6
angleIncrease: 1.5
- angleDecay: 6
+ angleDecay: 6
selectedMode: FullAuto
shotsPerBurst: 5
availableModes:
diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Shotguns/shotguns.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Shotguns/shotguns.yml
index bce85aac322..a8ab8a8e41c 100644
--- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Shotguns/shotguns.yml
+++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Shotguns/shotguns.yml
@@ -46,7 +46,7 @@
- type: entity
name: Bulldog
# Don't parent to BaseWeaponShotgun because it differs significantly
- parent: BaseItem
+ parent: [BaseItem, BaseGunWieldable]
id: WeaponShotgunBulldog
description: It's a magazine-fed shotgun designed for close quarters combat. Uses .50 shotgun shells. An illegal firearm often used by Syndicate agents.
components:
@@ -66,6 +66,7 @@
- Back
- suitStorage
- type: AmmoCounter
+ - type: GunRequiresWield #remove when inaccuracy on spreads is fixed
- type: Gun
fireRate: 2
selectedMode: FullAuto
@@ -102,7 +103,7 @@
- type: entity
name: double-barreled shotgun
- parent: BaseWeaponShotgun
+ parent: [BaseWeaponShotgun, BaseGunWieldable]
id: WeaponShotgunDoubleBarreled
description: An immortal classic. A civilian grade shotgun. Uses .50 shotgun shells.
components:
@@ -112,8 +113,8 @@
size: Normal
shape:
- 0,0,4,0
- sprite: Objects/Weapons/Guns/Shotguns/inhands_64x.rsi
- heldPrefix: db
+ sprite: Objects/Weapons/Guns/Shotguns/db_shotgun_inhands_64x.rsi
+ - type: GunRequiresWield #remove when inaccuracy on spreads is fixed
- type: Gun
fireRate: 2
- type: BallisticAmmoProvider
@@ -137,7 +138,7 @@
- type: entity
name: Enforcer
- parent: BaseWeaponShotgun
+ parent: [BaseWeaponShotgun, BaseGunWieldable]
id: WeaponShotgunEnforcer
description: A premium combat shotgun based on the Kammerer design, featuring an upgraded clip capacity. .50 shotgun shells. On the receiver is a label that says 'for authorized use only.'
components:
@@ -146,9 +147,9 @@
- type: Clothing
sprite: Objects/Weapons/Guns/Shotguns/enforcer.rsi
- type: Item
- sprite: Objects/Weapons/Guns/Shotguns/inhands_64x.rsi
- heldPrefix: enforcer
+ sprite: Objects/Weapons/Guns/Shotguns/enforcer_inhands_64x.rsi
- type: BallisticAmmoProvider
+ - type: GunRequiresWield #remove when inaccuracy on spreads is fixed
- type: entity
parent: WeaponShotgunEnforcer
@@ -160,7 +161,7 @@
- type: entity
name: Kammerer
- parent: BaseWeaponShotgun
+ parent: [BaseWeaponShotgun, BaseGunWieldable]
id: WeaponShotgunKammerer
description: When an old Remington design meets modern materials, this is the result. A civilian grade shotgun, favored by militia forces throughout many worlds. Uses .50 shotgun shells.
components:
@@ -168,12 +169,12 @@
size: Normal
shape:
- 0,0,4,0
- sprite: Objects/Weapons/Guns/Shotguns/inhands_64x.rsi
- heldPrefix: pump
+ sprite: Objects/Weapons/Guns/Shotguns/pump_inhands_64x.rsi
- type: Sprite
sprite: Objects/Weapons/Guns/Shotguns/pump.rsi
- type: Clothing
sprite: Objects/Weapons/Guns/Shotguns/pump.rsi
+ - type: GunRequiresWield #remove when inaccuracy on spreads is fixed
- type: BallisticAmmoProvider
capacity: 4
- type: Tag
@@ -192,8 +193,7 @@
sprite: Objects/Weapons/Guns/Shotguns/sawn.rsi
- type: Item
size: Small
- sprite: Objects/Weapons/Guns/Shotguns/inhands_64x.rsi
- heldPrefix: sawn
+ sprite: Objects/Weapons/Guns/Shotguns/sawn_inhands_64x.rsi
- type: Gun
fireRate: 4
- type: BallisticAmmoProvider
@@ -241,7 +241,7 @@
- type: entity
name: blunderbuss
- parent: BaseWeaponShotgun
+ parent: [BaseWeaponShotgun, BaseGunWieldable]
id: WeaponShotgunBlunderbuss
suffix: Pirate
description: Deadly at close range, an illegal shotgun often found at the side of a pirate.
@@ -252,6 +252,7 @@
- 0,0,4,0
- type: Sprite
sprite: Objects/Weapons/Guns/Shotguns/blunderbuss.rsi
+ - type: GunRequiresWield #remove when inaccuracy on spreads is fixed
- type: Gun
fireRate: 2
- type: BallisticAmmoProvider
@@ -261,7 +262,7 @@
- type: entity
name: improvised shotgun
- parent: BaseWeaponShotgun
+ parent: [BaseWeaponShotgun, BaseGunWieldable]
id: WeaponShotgunImprovised
description: A shitty, but legal, hand-made shotgun that uses .50 shotgun shells. It can only hold one round in the chamber.
components:
@@ -273,8 +274,8 @@
size: Normal
shape:
- 0,0,4,0
- sprite: Objects/Weapons/Guns/Shotguns/inhands_64x.rsi
- heldPrefix: improvised
+ sprite: Objects/Weapons/Guns/Shotguns/improvised_shotgun_inhands_64x.rsi
+ - type: GunRequiresWield #remove when inaccuracy on spreads is fixed
- type: Gun
fireRate: 4 #No reason to stifle the firerate since you have to manually reload every time anyways.
- type: BallisticAmmoProvider
diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Snipers/snipers.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Snipers/snipers.yml
index a45924fd4c5..9c9a8c77e57 100644
--- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Snipers/snipers.yml
+++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Snipers/snipers.yml
@@ -40,7 +40,7 @@
- type: entity
name: Kardashev-Mosin
- parent: BaseWeaponSniper
+ parent: [BaseWeaponSniper, BaseGunWieldable]
id: WeaponSniperMosin
description: A civilian grade weapon for hunting, or endless trench warfare. Uses .30 rifle ammo.
components:
@@ -51,7 +51,7 @@
- type: entity
name: Hristov
- parent: BaseWeaponSniper
+ parent: [BaseWeaponSniper, BaseGunWieldable]
id: WeaponSniperHristov
description: A portable anti-materiel rifle. Fires armor piercing 14.5mm shells. Uses .60 anti-materiel ammo. On the receiver is a label that says 'for authorized use only.'
components:
diff --git a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml
index cd0ba89b3b5..ad0fa9702d1 100644
--- a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml
+++ b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml
@@ -191,6 +191,8 @@
- ShellTranquilizer
- SpeedLoaderMagnum
- SpeedLoaderMagnumEmpty
+ - SpeedLoaderRifleHeavy # Frontier
+ - SpeedLoaderRifleHeavyEmpty # Frontier
emagDynamicRecipes:
- BoxBeanbag
- BoxShotgunIncendiary
@@ -221,6 +223,8 @@
- PowerCageSmall
- SpeedLoaderMagnumIncendiary
- SpeedLoaderMagnumUranium
+ - SpeedLoaderRifleHeavyIncendiary # Frontier
+ - SpeedLoaderRifleHeavyUranium # Frontier
- type: entity
id: AutolatheHyperConvection
@@ -764,6 +768,8 @@
- RiotShield
- SpeedLoaderMagnum
- SpeedLoaderMagnumEmpty
+ - SpeedLoaderRifleHeavy # Frontier
+ - SpeedLoaderRifleHeavyEmpty # Frontier
- Stunbaton
- TargetClown
- TargetHuman
@@ -822,6 +828,8 @@
- SignalTrigger
- SpeedLoaderMagnumIncendiary
- SpeedLoaderMagnumUranium
+ - SpeedLoaderRifleHeavyIncendiary # Frontier
+ - SpeedLoaderRifleHeavyUranium # Frontier
- TelescopicShield
- TimerTrigger
- Truncheon
@@ -883,6 +891,8 @@
- ShellTranquilizer
- SpeedLoaderMagnum
- SpeedLoaderMagnumEmpty
+ - SpeedLoaderRifleHeavy # Frontier
+ - SpeedLoaderRifleHeavyEmpty # Frontier
- type: MaterialStorage
whitelist:
tags:
diff --git a/Resources/Prototypes/Loadouts/role_loadouts.yml b/Resources/Prototypes/Loadouts/role_loadouts.yml
index 316082562ba..7d9aedee1fd 100644
--- a/Resources/Prototypes/Loadouts/role_loadouts.yml
+++ b/Resources/Prototypes/Loadouts/role_loadouts.yml
@@ -75,8 +75,12 @@
groups:
- LawyerNeck
- LawyerJumpsuit
- - LawyerBackpack
+ - ContractorBackpack
- ContractorGlasses
+ - ContractorFace
+ - ContractorBoxSurvival
+ - ContractorEncryptionKey
+ - ContractorImplanter
- ContractorFun
- ContractorTrinkets
@@ -87,9 +91,12 @@
- ChaplainMask
- ChaplainNeck
- ChaplainJumpsuit
- - ChaplainBackpack
+ - ContractorBackpack
- ChaplainOuterClothing
- ContractorGlasses
+ - ContractorBoxSurvival
+ - ContractorEncryptionKey
+ - ContractorImplanter
- ContractorFun
- ContractorTrinkets
@@ -99,9 +106,13 @@
- JanitorHead
- JanitorJumpsuit
- JanitorGloves
- - CommonBackpack
+ - ContractorBackpack
- JanitorOuterClothing
+ - ContractorFace
- ContractorGlasses
+ - ContractorBoxSurvival
+ - ContractorEncryptionKey
+ - ContractorImplanter
- ContractorFun
- ContractorTrinkets
diff --git a/Resources/Prototypes/Nyanotrasen/Roles/Jobs/Wildcards/prisoner.yml b/Resources/Prototypes/Nyanotrasen/Roles/Jobs/Wildcards/prisoner.yml
index 34a0a75ee5d..b0d447b4d0c 100644
--- a/Resources/Prototypes/Nyanotrasen/Roles/Jobs/Wildcards/prisoner.yml
+++ b/Resources/Prototypes/Nyanotrasen/Roles/Jobs/Wildcards/prisoner.yml
@@ -18,7 +18,5 @@
- type: startingGear
id: PrisonerGear
equipment:
- jumpsuit: ClothingUniformJumpsuitPrisoner
shoes: ClothingShoesColorBlack
- id: PrisonerPDA
ears: ClothingHeadsetGrey
diff --git a/Resources/Prototypes/Research/arsenal.yml b/Resources/Prototypes/Research/arsenal.yml
index c8cee57de2b..5aed3aa6aaa 100644
--- a/Resources/Prototypes/Research/arsenal.yml
+++ b/Resources/Prototypes/Research/arsenal.yml
@@ -33,6 +33,7 @@
- MagazinePistolIncendiary
- MagazineLightRifleIncendiary
- SpeedLoaderMagnumIncendiary
+ - SpeedLoaderRifleHeavyIncendiary # Frontier
- MagazineShotgunIncendiary
- MagazineBoxPistolIncendiary
- MagazineBoxMagnumIncendiary
@@ -80,6 +81,7 @@
- MagazinePistolUranium
- MagazineLightRifleUranium
- SpeedLoaderMagnumUranium
+ - SpeedLoaderRifleHeavyUranium # Frontier
- MagazineBoxPistolUranium
- MagazineBoxMagnumUranium
- MagazineBoxLightRifleUranium
diff --git a/Resources/Prototypes/Roles/Jobs/Civilian/chaplain.yml b/Resources/Prototypes/Roles/Jobs/Civilian/chaplain.yml
index 677449cfac8..5395e9ed861 100644
--- a/Resources/Prototypes/Roles/Jobs/Civilian/chaplain.yml
+++ b/Resources/Prototypes/Roles/Jobs/Civilian/chaplain.yml
@@ -22,3 +22,5 @@
shoes: ClothingShoesColorBlack
id: ChaplainPDA
ears: ClothingHeadsetService
+ pocket1: Bible # Frontier
+ pocket2: RubberStampChaplain # Frontier
diff --git a/Resources/Prototypes/Roles/Jobs/Civilian/lawyer.yml b/Resources/Prototypes/Roles/Jobs/Civilian/lawyer.yml
index 347f4185df1..b2bf348ebde 100644
--- a/Resources/Prototypes/Roles/Jobs/Civilian/lawyer.yml
+++ b/Resources/Prototypes/Roles/Jobs/Civilian/lawyer.yml
@@ -16,10 +16,10 @@
- type: startingGear
id: LawyerGear
equipment:
- jumpsuit: ClothingUniformJumpsuitLawyerBlack # TODO change jumpsuit to randomiser of the 4 variants
- back: ClothingBackpackLawyerFilled # Frontier
shoes: ClothingShoesBootsLaceup
id: LawyerPDA
- ears: ClothingHeadsetSecurity
+ ears: ClothingHeadsetNfsdGreen # Frontier ClothingHeadsetSecurity