Merge branch 'master' into RefactorMouseFilterMode
@@ -55,9 +55,6 @@ namespace Content.Server.Administration
|
||||
return;
|
||||
}
|
||||
|
||||
if(mind.IsVisitingEntity)
|
||||
mind.UnVisit();
|
||||
|
||||
mindComponent.Mind?.TransferTo(null);
|
||||
mind.TransferTo(target);
|
||||
|
||||
|
||||
@@ -31,9 +31,10 @@ namespace Content.Server.GameObjects.Components.Construction
|
||||
|
||||
SpriteComponent Sprite;
|
||||
ITransformComponent Transform;
|
||||
#pragma warning disable 649
|
||||
#pragma warning disable 649
|
||||
[Dependency] private IRobustRandom _random;
|
||||
#pragma warning restore 649
|
||||
[Dependency] private readonly IEntitySystemManager _entitySystemManager;
|
||||
#pragma warning restore 649
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -46,6 +47,13 @@ namespace Content.Server.GameObjects.Components.Construction
|
||||
|
||||
public bool AttackBy(AttackByEventArgs eventArgs)
|
||||
{
|
||||
var playerEntity = eventArgs.User;
|
||||
var interactionSystem = _entitySystemManager.GetEntitySystem<InteractionSystem>();
|
||||
if (!interactionSystem.InRangeUnobstructed(playerEntity.Transform.MapPosition, Owner.Transform.WorldPosition, ignoredEnt: Owner, insideBlockerValid: true))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var stage = Prototype.Stages[Stage];
|
||||
|
||||
if (TryProcessStep(stage.Forward, eventArgs.AttackWith))
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using Content.Server.GameObjects.Components.Stack;
|
||||
using Content.Server.GameObjects.EntitySystems;
|
||||
using Content.Shared.Construction;
|
||||
@@ -29,7 +29,6 @@ namespace Content.Server.GameObjects.Components.Construction
|
||||
public override void HandleMessage(ComponentMessage message, INetChannel netChannel = null, IComponent component = null)
|
||||
{
|
||||
base.HandleMessage(message, netChannel, component);
|
||||
|
||||
switch (message)
|
||||
{
|
||||
case TryStartStructureConstructionMessage tryStart:
|
||||
@@ -43,7 +42,9 @@ namespace Content.Server.GameObjects.Components.Construction
|
||||
var prototype = _prototypeManager.Index<ConstructionPrototype>(prototypeName);
|
||||
|
||||
var transform = Owner.Transform;
|
||||
if (!loc.InRange(_mapManager, transform.GridPosition, InteractionSystem.InteractionRange))
|
||||
|
||||
var interactionSystem = _entitySystemManager.GetEntitySystem<InteractionSystem>();
|
||||
if (!interactionSystem.InRangeUnobstructed(loc.ToMap(_mapManager), Owner.Transform.WorldPosition, ignoredEnt: Owner, insideBlockerValid: true))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -78,11 +78,16 @@ namespace Content.Server.GameObjects
|
||||
|
||||
public bool CanPickup(IEntity user)
|
||||
{
|
||||
var coords = Owner.Transform.GridPosition;
|
||||
|
||||
if (!ActionBlockerSystem.CanPickup(user)) return false;
|
||||
|
||||
if (user.Transform.MapID != Owner.Transform.MapID)
|
||||
return false;
|
||||
|
||||
var userPos = user.Transform.MapPosition;
|
||||
var itemPos = Owner.Transform.WorldPosition;
|
||||
|
||||
return _entitySystemManager.GetEntitySystem<InteractionSystem>()
|
||||
.InRangeUnobstructed(coords, user.Transform.GridPosition, ignoredEnt:Owner);
|
||||
.InRangeUnobstructed(userPos, itemPos, ignoredEnt: Owner, insideBlockerValid:true);
|
||||
}
|
||||
|
||||
public bool AttackHand(AttackHandEventArgs eventArgs)
|
||||
|
||||
@@ -9,6 +9,7 @@ using Robust.Server.GameObjects.Components.UserInterface;
|
||||
using Robust.Server.Interfaces.GameObjects;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Interfaces.GameObjects;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Server.GameObjects.Components.Medical
|
||||
@@ -20,6 +21,7 @@ namespace Content.Server.GameObjects.Components.Medical
|
||||
private AppearanceComponent _appearance;
|
||||
private BoundUserInterface _userInterface;
|
||||
private ContainerSlot _bodyContainer;
|
||||
private readonly Vector2 _ejectOffset = new Vector2(-0.5f, 0f);
|
||||
public bool IsOccupied => _bodyContainer.ContainedEntity != null;
|
||||
|
||||
public override void Initialize()
|
||||
@@ -61,7 +63,7 @@ namespace Content.Server.GameObjects.Components.Medical
|
||||
|
||||
var dmgDict = new Dictionary<string, int>();
|
||||
|
||||
foreach (var dmgType in (DamageType[])Enum.GetValues(typeof(DamageType)))
|
||||
foreach (var dmgType in (DamageType[]) Enum.GetValues(typeof(DamageType)))
|
||||
{
|
||||
if (damageable.CurrentDamage.TryGetValue(dmgType, out var amount))
|
||||
{
|
||||
@@ -70,7 +72,7 @@ namespace Content.Server.GameObjects.Components.Medical
|
||||
}
|
||||
|
||||
return new MedicalScannerBoundUserInterfaceState(
|
||||
deathThresholdValue-currentHealth,
|
||||
deathThresholdValue - currentHealth,
|
||||
deathThresholdValue,
|
||||
dmgDict);
|
||||
}
|
||||
@@ -160,7 +162,9 @@ namespace Content.Server.GameObjects.Components.Medical
|
||||
|
||||
public void EjectBody()
|
||||
{
|
||||
_bodyContainer.Remove(_bodyContainer.ContainedEntity);
|
||||
var containedEntity = _bodyContainer.ContainedEntity;
|
||||
_bodyContainer.Remove(containedEntity);
|
||||
containedEntity.Transform.WorldPosition += _ejectOffset;
|
||||
UpdateUserInterface();
|
||||
UpdateAppearance();
|
||||
}
|
||||
|
||||
@@ -72,6 +72,11 @@ namespace Content.Server.GameObjects
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IActionBlocker.CanAttack()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -128,6 +133,11 @@ namespace Content.Server.GameObjects
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IActionBlocker.CanAttack()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -204,5 +214,10 @@ namespace Content.Server.GameObjects
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IActionBlocker.CanAttack()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,6 +117,11 @@ namespace Content.Server.GameObjects
|
||||
return CurrentDamageState.CanEmote();
|
||||
}
|
||||
|
||||
bool IActionBlocker.CanAttack()
|
||||
{
|
||||
return CurrentDamageState.CanAttack();
|
||||
}
|
||||
|
||||
List<DamageThreshold> IOnDamageBehavior.GetAllDamageThresholds()
|
||||
{
|
||||
var thresholdlist = DamageTemplate.DamageThresholds;
|
||||
|
||||
@@ -134,7 +134,7 @@ namespace Content.Server.GameObjects.Components.Weapon.Melee
|
||||
for (var i = 0; i < increments; i++)
|
||||
{
|
||||
var castAngle = new Angle(baseAngle + increment * i);
|
||||
var res = _physicsManager.IntersectRay(mapId, new CollisionRay(position, castAngle.ToVec(), 23), _range, ignore);
|
||||
var res = _physicsManager.IntersectRay(mapId, new CollisionRay(position, castAngle.ToVec(), 23), _range, ignore, ignoreNonHardCollidables: true);
|
||||
if (res.HitEntity != null)
|
||||
{
|
||||
resSet.Add(res.HitEntity);
|
||||
|
||||
@@ -90,7 +90,7 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Hitscan
|
||||
var angle = new Angle(clickLocation.Position - userPosition);
|
||||
|
||||
var ray = new CollisionRay(userPosition, angle.ToVec(), (int)(CollisionGroup.Impassable | CollisionGroup.MobImpassable));
|
||||
var rayCastResults = IoCManager.Resolve<IPhysicsManager>().IntersectRay(user.Transform.MapID, ray, MaxLength, user);
|
||||
var rayCastResults = IoCManager.Resolve<IPhysicsManager>().IntersectRay(user.Transform.MapID, ray, MaxLength, user, ignoreNonHardCollidables: true);
|
||||
|
||||
Hit(rayCastResults, energyModifier, user);
|
||||
AfterEffects(user, rayCastResults, angle, energyModifier);
|
||||
|
||||
@@ -1,32 +1,106 @@
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Content.Server.GameObjects.Components.Weapon.Ranged.Projectile
|
||||
{
|
||||
/// <summary>
|
||||
/// Passes information about the projectiles to be fired by AmmoWeapons
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
public class BallisticBulletComponent : Component
|
||||
{
|
||||
public override string Name => "BallisticBullet";
|
||||
|
||||
private BallisticCaliber _caliber;
|
||||
private string _projectileType;
|
||||
private bool _spent;
|
||||
/// <summary>
|
||||
/// Cartridge calibre, restricts what AmmoWeapons this ammo can be fired from.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public BallisticCaliber Caliber { get => _caliber; set => _caliber = value; }
|
||||
|
||||
public string ProjectileType => _projectileType;
|
||||
public BallisticCaliber Caliber => _caliber;
|
||||
public bool Spent
|
||||
{
|
||||
get => _spent;
|
||||
set => _spent = value;
|
||||
}
|
||||
private string _projectileID;
|
||||
/// <summary>
|
||||
/// YAML ID of the projectiles to be created when firing this ammo.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public string ProjectileID { get => _projectileID; set => _projectileID = value; }
|
||||
|
||||
private int _projectilesFired;
|
||||
/// <summary>
|
||||
/// How many copies of the projectile are shot.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public int ProjectilesFired { get => _projectilesFired; set => _projectilesFired = value; }
|
||||
|
||||
private float _spreadStdDev_Ammo;
|
||||
/// <summary>
|
||||
/// Weapons that fire projectiles from ammo types.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public float SpreadStdDev_Ammo { get => _spreadStdDev_Ammo; set => _spreadStdDev_Ammo = value; }
|
||||
|
||||
private float _evenSpreadAngle_Ammo;
|
||||
/// <summary>
|
||||
/// Arc angle of shotgun pellet spreads, only used if multiple projectiles are being fired.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public float EvenSpreadAngle_Ammo { get => _evenSpreadAngle_Ammo; set => _evenSpreadAngle_Ammo = value; }
|
||||
|
||||
private float _velocity_Ammo;
|
||||
/// <summary>
|
||||
/// Adds additional velocity to the projectile, on top of what it already has.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public float Velocity_Ammo { get => _velocity_Ammo; set => _velocity_Ammo = value; }
|
||||
|
||||
private bool _spent;
|
||||
/// <summary>
|
||||
/// If the ammo cartridge has been shot already.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public bool Spent { get => _spent; set => _spent = value; }
|
||||
|
||||
public override void ExposeData(ObjectSerializer serializer)
|
||||
{
|
||||
base.ExposeData(serializer);
|
||||
|
||||
serializer.DataField(ref _caliber, "caliber", BallisticCaliber.Unspecified);
|
||||
serializer.DataField(ref _projectileType, "projectile", null);
|
||||
serializer.DataField(ref _projectileID, "projectile", null);
|
||||
serializer.DataField(ref _spent, "spent", false);
|
||||
serializer.DataField(ref _projectilesFired, "projectilesfired", 1);
|
||||
serializer.DataField(ref _spreadStdDev_Ammo, "ammostddev", 0);
|
||||
serializer.DataField(ref _evenSpreadAngle_Ammo, "ammospread", 0);
|
||||
serializer.DataField(ref _velocity_Ammo, "ammovelocity", 0);
|
||||
}
|
||||
}
|
||||
public enum BallisticCaliber
|
||||
{
|
||||
Unspecified = 0,
|
||||
// .32
|
||||
A32,
|
||||
// .357
|
||||
A357,
|
||||
// .44
|
||||
A44,
|
||||
// .45mm
|
||||
A45mm,
|
||||
// .50 cal
|
||||
A50,
|
||||
// 5.56mm
|
||||
A556mm,
|
||||
// 6.5mm
|
||||
A65mm,
|
||||
// 7.62mm
|
||||
A762mm,
|
||||
// 9mm
|
||||
A9mm,
|
||||
// 10mm
|
||||
A10mm,
|
||||
// 20mm
|
||||
A20mm,
|
||||
// 24mm
|
||||
A24mm,
|
||||
// 12g
|
||||
A12g,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Projectile
|
||||
}
|
||||
}
|
||||
|
||||
_updateAppearance();
|
||||
UpdateAppearance();
|
||||
|
||||
OnAmmoCountChanged?.Invoke();
|
||||
_appearance.SetData(BallisticMagazineVisuals.AmmoCapacity, Capacity);
|
||||
@@ -99,7 +99,7 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Projectile
|
||||
|
||||
_bulletContainer.Insert(bullet);
|
||||
_loadedBullets.Push(bullet);
|
||||
_updateAppearance();
|
||||
UpdateAppearance();
|
||||
OnAmmoCountChanged?.Invoke();
|
||||
}
|
||||
|
||||
@@ -122,7 +122,7 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Projectile
|
||||
_bulletContainer.Remove(bullet);
|
||||
}
|
||||
|
||||
_updateAppearance();
|
||||
UpdateAppearance();
|
||||
OnAmmoCountChanged?.Invoke();
|
||||
return bullet;
|
||||
}
|
||||
@@ -224,7 +224,7 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Projectile
|
||||
return false;
|
||||
}
|
||||
|
||||
private void _updateAppearance()
|
||||
private void UpdateAppearance()
|
||||
{
|
||||
_appearance.SetData(BallisticMagazineVisuals.AmmoLeft, CountLoaded);
|
||||
}
|
||||
@@ -278,5 +278,8 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Projectile
|
||||
|
||||
// 24mm
|
||||
A24mm,
|
||||
|
||||
// 12g
|
||||
A12g,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,9 @@ using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Content.Server.GameObjects.Components.Weapon.Ranged.Projectile
|
||||
{
|
||||
/// <summary>
|
||||
/// Guns that have a magazine.
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
public class BallisticMagazineWeaponComponent : BallisticWeaponComponent, IUse, IAttackBy, IMapInit
|
||||
{
|
||||
@@ -46,7 +49,7 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Projectile
|
||||
[ViewVariables] private bool _autoEjectMagazine;
|
||||
[ViewVariables] private AppearanceComponent _appearance;
|
||||
|
||||
private static readonly Direction[] _randomBulletDirs =
|
||||
private static readonly Direction[] RandomBulletDirs =
|
||||
{
|
||||
Direction.North,
|
||||
Direction.East,
|
||||
@@ -54,12 +57,9 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Projectile
|
||||
Direction.West
|
||||
};
|
||||
|
||||
protected override int ChamberCount => 1;
|
||||
|
||||
public override void ExposeData(ObjectSerializer serializer)
|
||||
{
|
||||
base.ExposeData(serializer);
|
||||
|
||||
serializer.DataField(ref _magazineTypes, "magazines",
|
||||
new List<BallisticMagazineType> {BallisticMagazineType.Unspecified});
|
||||
serializer.DataField(ref _defaultMagazine, "default_magazine", null);
|
||||
@@ -72,7 +72,6 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Projectile
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
_appearance = Owner.GetComponent<AppearanceComponent>();
|
||||
}
|
||||
|
||||
@@ -80,57 +79,44 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Projectile
|
||||
protected override void Startup()
|
||||
{
|
||||
base.Startup();
|
||||
|
||||
_magazineSlot = ContainerManagerComponent.Ensure<ContainerSlot>("ballistic_gun_magazine", Owner);
|
||||
|
||||
if (Magazine != null)
|
||||
{
|
||||
// Already got magazine from loading a container.
|
||||
Magazine.GetComponent<BallisticMagazineComponent>().OnAmmoCountChanged += _magazineAmmoCountChanged;
|
||||
Magazine.GetComponent<BallisticMagazineComponent>().OnAmmoCountChanged += MagazineAmmoCountChanged;
|
||||
}
|
||||
|
||||
_updateAppearance();
|
||||
UpdateAppearance();
|
||||
}
|
||||
|
||||
public bool InsertMagazine(IEntity magazine, bool playSound = true)
|
||||
{
|
||||
if (!magazine.TryGetComponent(out BallisticMagazineComponent component))
|
||||
if (!magazine.TryGetComponent(out BallisticMagazineComponent magazinetype))
|
||||
{
|
||||
throw new ArgumentException("Not a magazine", nameof(magazine));
|
||||
}
|
||||
|
||||
if (!MagazineTypes.Contains(component.MagazineType))
|
||||
if (!MagazineTypes.Contains(magazinetype.MagazineType))
|
||||
{
|
||||
throw new ArgumentException("Wrong magazine type", nameof(magazine));
|
||||
}
|
||||
|
||||
if (component.Caliber != Caliber)
|
||||
{
|
||||
throw new ArgumentException("Wrong caliber", nameof(magazine));
|
||||
}
|
||||
|
||||
if (!_magazineSlot.Insert(magazine))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_magInSound != null)
|
||||
{
|
||||
Owner.GetComponent<SoundComponent>().Play(_magInSound);
|
||||
}
|
||||
|
||||
component.OnAmmoCountChanged += _magazineAmmoCountChanged;
|
||||
magazinetype.OnAmmoCountChanged += MagazineAmmoCountChanged;
|
||||
if (GetChambered(0) == null)
|
||||
{
|
||||
// No bullet in chamber, load one from magazine.
|
||||
var bullet = component.TakeBullet();
|
||||
var bullet = magazinetype.TakeBullet();
|
||||
if (bullet != null)
|
||||
{
|
||||
LoadIntoChamber(0, bullet);
|
||||
}
|
||||
}
|
||||
|
||||
_updateAppearance();
|
||||
UpdateAppearance();
|
||||
Dirty();
|
||||
return true;
|
||||
}
|
||||
@@ -142,7 +128,6 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Projectile
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_magazineSlot.Remove(entity))
|
||||
{
|
||||
entity.Transform.GridPosition = Owner.Transform.GridPosition;
|
||||
@@ -150,14 +135,12 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Projectile
|
||||
{
|
||||
Owner.GetComponent<SoundComponent>().Play(_magOutSound, AudioParams.Default.WithVolume(20));
|
||||
}
|
||||
|
||||
_updateAppearance();
|
||||
UpdateAppearance();
|
||||
Dirty();
|
||||
entity.GetComponent<BallisticMagazineComponent>().OnAmmoCountChanged -= _magazineAmmoCountChanged;
|
||||
entity.GetComponent<BallisticMagazineComponent>().OnAmmoCountChanged -= MagazineAmmoCountChanged;
|
||||
return true;
|
||||
}
|
||||
|
||||
_updateAppearance();
|
||||
UpdateAppearance();
|
||||
Dirty();
|
||||
return false;
|
||||
}
|
||||
@@ -168,9 +151,13 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Projectile
|
||||
|
||||
// Eject chambered bullet.
|
||||
var entity = RemoveFromChamber(chamber);
|
||||
if (entity == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var offsetPos = (CalcBulletOffset(), CalcBulletOffset());
|
||||
entity.Transform.GridPosition = Owner.Transform.GridPosition.Offset(offsetPos);
|
||||
entity.Transform.LocalRotation = _bulletDropRandom.Pick(_randomBulletDirs).ToAngle();
|
||||
entity.Transform.LocalRotation = _bulletDropRandom.Pick(RandomBulletDirs).ToAngle();
|
||||
var effect = $"/Audio/Guns/Casings/casingfall{_bulletDropRandom.Next(1, 4)}.ogg";
|
||||
Owner.GetComponent<SoundComponent>().Play(effect, AudioParams.Default.WithVolume(-3));
|
||||
|
||||
@@ -188,9 +175,8 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Projectile
|
||||
DoAutoEject();
|
||||
}
|
||||
}
|
||||
|
||||
Dirty();
|
||||
_updateAppearance();
|
||||
UpdateAppearance();
|
||||
}
|
||||
|
||||
private float CalcBulletOffset()
|
||||
@@ -206,7 +192,6 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Projectile
|
||||
{
|
||||
Owner.GetComponent<SoundComponent>().Play(_autoEjectSound, AudioParams.Default.WithVolume(-5));
|
||||
}
|
||||
|
||||
Dirty();
|
||||
}
|
||||
|
||||
@@ -221,7 +206,6 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Projectile
|
||||
{
|
||||
Owner.PopupMessage(eventArgs.User, "No magazine");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -231,29 +215,26 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Projectile
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Magazine != null)
|
||||
{
|
||||
Owner.PopupMessage(eventArgs.User, "Already got a magazine.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!MagazineTypes.Contains(component.MagazineType) || component.Caliber != Caliber)
|
||||
if (!MagazineTypes.Contains(component.MagazineType))
|
||||
{
|
||||
Owner.PopupMessage(eventArgs.User, "Magazine doesn't fit.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return InsertMagazine(eventArgs.AttackWith);
|
||||
}
|
||||
|
||||
private void _magazineAmmoCountChanged()
|
||||
private void MagazineAmmoCountChanged()
|
||||
{
|
||||
Dirty();
|
||||
_updateAppearance();
|
||||
UpdateAppearance();
|
||||
}
|
||||
|
||||
private void _updateAppearance()
|
||||
private void UpdateAppearance()
|
||||
{
|
||||
if (Magazine != null)
|
||||
{
|
||||
@@ -273,15 +254,12 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Projectile
|
||||
public override ComponentState GetComponentState()
|
||||
{
|
||||
var chambered = GetChambered(0) != null;
|
||||
|
||||
(int, int)? count = null;
|
||||
|
||||
if (Magazine != null)
|
||||
{
|
||||
var magComponent = Magazine.GetComponent<BallisticMagazineComponent>();
|
||||
count = (magComponent.CountLoaded, magComponent.Capacity);
|
||||
}
|
||||
|
||||
return new BallisticMagazineWeaponComponentState(chambered, count);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
using Content.Server.GameObjects.Components.Sound;
|
||||
using Robust.Server.GameObjects.Components.Container;
|
||||
using Robust.Shared.Interfaces.GameObjects;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.ViewVariables;
|
||||
using System;
|
||||
|
||||
namespace Content.Server.GameObjects.Components.Weapon.Ranged.Projectile
|
||||
{
|
||||
/// <summary>
|
||||
/// Handles firing projectiles from a contained <see cref="BallisticBulletComponent" />.
|
||||
/// </summary>
|
||||
public abstract class BallisticWeaponComponent : BaseProjectileWeaponComponent
|
||||
{
|
||||
private Chamber[] _chambers;
|
||||
|
||||
/// <summary>
|
||||
/// Number of chambers created during initialization.
|
||||
/// </summary>
|
||||
private int _chamberCount;
|
||||
|
||||
[ViewVariables]
|
||||
private BallisticCaliber _caliber ;
|
||||
/// <summary>
|
||||
/// What type of ammo this gun can fire.
|
||||
/// </summary>
|
||||
|
||||
private string _soundGunEmpty;
|
||||
/// <summary>
|
||||
/// Sound played when trying to shoot if there is no ammo available.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public string SoundGunEmpty { get => _soundGunEmpty; set => _soundGunEmpty = value; }
|
||||
|
||||
private float _spreadStdDevGun;
|
||||
/// <summary>
|
||||
/// Increases the standard deviation of the ammo being fired.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public float SpreadStdDevGun { get => _spreadStdDevGun; set => _spreadStdDevGun = value; }
|
||||
|
||||
private float _evenSpreadAngleGun;
|
||||
/// <summary>
|
||||
/// Increases the evenspread of the ammo being fired.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public float EvenSpreadAngleGun { get => _evenSpreadAngleGun; set => _evenSpreadAngleGun = value; }
|
||||
|
||||
private float _velocityGun;
|
||||
/// <summary>
|
||||
/// Increases the velocity of the ammo being fired.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public float VelocityGun { get => _velocityGun; set => _velocityGun = value; }
|
||||
|
||||
public override void ExposeData(ObjectSerializer serializer)
|
||||
{
|
||||
base.ExposeData(serializer);
|
||||
serializer.DataField(ref _soundGunEmpty, "sound_empty", "/Audio/Guns/Empty/empty.ogg");
|
||||
serializer.DataField(ref _spreadStdDevGun, "spreadstddev", 0);
|
||||
serializer.DataField(ref _evenSpreadAngleGun, "evenspread", 0);
|
||||
serializer.DataField(ref _velocityGun, "gunvelocity", 0);
|
||||
serializer.DataField(ref _caliber, "caliber", BallisticCaliber.Unspecified);
|
||||
serializer.DataField(ref _chamberCount, "chambers", 1);
|
||||
}
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
Owner.GetComponent<RangedWeaponComponent>().FireHandler = TryShoot;
|
||||
_chambers = new Chamber[_chamberCount];
|
||||
for (var i = 0; i < _chambers.Length; i++)
|
||||
{
|
||||
var container = ContainerManagerComponent.Ensure<ContainerSlot>($"ballistics_chamber_{i}", Owner);
|
||||
_chambers[i] = new Chamber(container);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fires projectiles based on loaded ammo from entity to a coordinate.
|
||||
/// </summary>
|
||||
protected void TryShoot(IEntity user, GridCoordinates clickLocation)
|
||||
{
|
||||
var ammo = GetChambered(FirstChamber)?.GetComponent<BallisticBulletComponent>();
|
||||
CycleChamberedBullet(FirstChamber);
|
||||
if (ammo == null || ammo?.Spent == true || ammo?.Caliber != _caliber)
|
||||
{
|
||||
PlayEmptySound();
|
||||
return;
|
||||
}
|
||||
ammo.Spent = true;
|
||||
var total_stdev = _spreadStdDevGun + ammo.SpreadStdDev_Ammo;
|
||||
var final_evenspread = _evenSpreadAngleGun + ammo.EvenSpreadAngle_Ammo;
|
||||
var final_velocity = _velocityGun + ammo.Velocity_Ammo;
|
||||
FireAtCoord(user, clickLocation, ammo.ProjectileID, total_stdev, ammo.ProjectilesFired, final_evenspread, final_velocity);
|
||||
}
|
||||
|
||||
protected IEntity GetChambered(int chamber) => _chambers[chamber].Slot.ContainedEntity;
|
||||
|
||||
/// <summary>
|
||||
/// Loads the next ammo casing into the chamber.
|
||||
/// </summary>
|
||||
protected virtual void CycleChamberedBullet(int chamber) { }
|
||||
|
||||
public IEntity RemoveFromChamber(int chamber)
|
||||
{
|
||||
var c = _chambers[chamber];
|
||||
var loaded = c.Slot.ContainedEntity;
|
||||
if (loaded != null)
|
||||
{
|
||||
c.Slot.Remove(loaded);
|
||||
}
|
||||
return loaded;
|
||||
}
|
||||
|
||||
protected bool LoadIntoChamber(int chamber, IEntity bullet)
|
||||
{
|
||||
if (!bullet.TryGetComponent(out BallisticBulletComponent component))
|
||||
{
|
||||
throw new ArgumentException("entity isn't a bullet.", nameof(bullet));
|
||||
}
|
||||
if (component.Caliber != _caliber)
|
||||
{
|
||||
throw new ArgumentException("entity is of the wrong caliber.", nameof(bullet));
|
||||
}
|
||||
if (GetChambered(chamber) != null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
_chambers[chamber].Slot.Insert(bullet);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void PlayEmptySound() => Owner.GetComponent<SoundComponent>().Play(_soundGunEmpty);
|
||||
|
||||
protected sealed class Chamber
|
||||
{
|
||||
public Chamber(ContainerSlot slot)
|
||||
{
|
||||
Slot = slot;
|
||||
}
|
||||
|
||||
public ContainerSlot Slot { get; }
|
||||
}
|
||||
|
||||
private const int FirstChamber = 0;
|
||||
}
|
||||
}
|
||||
@@ -1,121 +0,0 @@
|
||||
using System;
|
||||
using Content.Server.GameObjects.Components.Sound;
|
||||
using Robust.Server.GameObjects.Components.Container;
|
||||
using Robust.Shared.Interfaces.GameObjects;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Server.GameObjects.Components.Weapon.Ranged.Projectile
|
||||
{
|
||||
public abstract class BallisticWeaponComponent : ProjectileWeaponComponent
|
||||
{
|
||||
private BallisticCaliber _caliber;
|
||||
private Chamber[] _chambers;
|
||||
|
||||
public BallisticCaliber Caliber => _caliber;
|
||||
protected abstract int ChamberCount { get; }
|
||||
|
||||
private string _soundGunEmpty;
|
||||
|
||||
public override void ExposeData(ObjectSerializer serializer)
|
||||
{
|
||||
base.ExposeData(serializer);
|
||||
|
||||
serializer.DataField(ref _caliber, "caliber", BallisticCaliber.Unspecified);
|
||||
serializer.DataField(ref _soundGunEmpty, "sound_empty", null);
|
||||
}
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
_chambers = new Chamber[ChamberCount];
|
||||
for (var i = 0; i < _chambers.Length; i++)
|
||||
{
|
||||
var container = ContainerManagerComponent.Ensure<ContainerSlot>($"ballistics_chamber_{i}", Owner);
|
||||
_chambers[i] = new Chamber(container);
|
||||
}
|
||||
}
|
||||
|
||||
public IEntity GetChambered(int chamber) => _chambers[chamber].Slot.ContainedEntity;
|
||||
|
||||
public bool LoadIntoChamber(int chamber, IEntity bullet)
|
||||
{
|
||||
if (!bullet.TryGetComponent(out BallisticBulletComponent component))
|
||||
{
|
||||
throw new ArgumentException("entity isn't a bullet.", nameof(bullet));
|
||||
}
|
||||
|
||||
if (component.Caliber != Caliber)
|
||||
{
|
||||
throw new ArgumentException("entity is of the wrong caliber.", nameof(bullet));
|
||||
}
|
||||
|
||||
if (GetChambered(chamber) != null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
_chambers[chamber].Slot.Insert(bullet);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected sealed override IEntity GetFiredProjectile()
|
||||
{
|
||||
void PlayEmpty()
|
||||
{
|
||||
if (_soundGunEmpty != null)
|
||||
{
|
||||
Owner.GetComponent<SoundComponent>().Play(_soundGunEmpty);
|
||||
}
|
||||
}
|
||||
var chambered = GetChambered(0);
|
||||
if (chambered != null)
|
||||
{
|
||||
var bullet = chambered.GetComponent<BallisticBulletComponent>();
|
||||
if (bullet.Spent)
|
||||
{
|
||||
PlayEmpty();
|
||||
return null;
|
||||
}
|
||||
|
||||
var projectile = Owner.EntityManager.SpawnEntity(bullet.ProjectileType, Owner.Transform.GridPosition);
|
||||
bullet.Spent = true;
|
||||
|
||||
CycleChamberedBullet(0);
|
||||
|
||||
// Load a new bullet into the chamber from magazine.
|
||||
return projectile;
|
||||
}
|
||||
|
||||
PlayEmpty();
|
||||
return null;
|
||||
}
|
||||
|
||||
protected virtual void CycleChamberedBullet(int chamber)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public IEntity RemoveFromChamber(int chamber)
|
||||
{
|
||||
var c = _chambers[chamber];
|
||||
var loaded = c.Slot.ContainedEntity;
|
||||
if (loaded != null)
|
||||
{
|
||||
c.Slot.Remove(loaded);
|
||||
}
|
||||
return loaded;
|
||||
}
|
||||
|
||||
private sealed class Chamber
|
||||
{
|
||||
public Chamber(ContainerSlot slot)
|
||||
{
|
||||
Slot = slot;
|
||||
}
|
||||
|
||||
public ContainerSlot Slot { get; }
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
using Content.Server.GameObjects.Components.Mobs;
|
||||
using Content.Server.GameObjects.Components.Projectiles;
|
||||
using Content.Server.GameObjects.Components.Sound;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Interfaces.GameObjects;
|
||||
using Robust.Shared.Interfaces.Random;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Random;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.ViewVariables;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Content.Server.GameObjects.Components.Weapon.Ranged.Projectile
|
||||
{
|
||||
/// <summary>
|
||||
/// Methods to shoot projectiles.
|
||||
/// </summary>
|
||||
public abstract class BaseProjectileWeaponComponent : Component
|
||||
{
|
||||
private string _soundGunshot;
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public string SoundGunshot
|
||||
{ get => _soundGunshot; set => _soundGunshot = value; }
|
||||
|
||||
#pragma warning disable 649
|
||||
[Dependency] private IRobustRandom _spreadRandom;
|
||||
#pragma warning restore 649
|
||||
|
||||
public override void ExposeData(ObjectSerializer serializer)
|
||||
{
|
||||
base.ExposeData(serializer);
|
||||
serializer.DataField(ref _soundGunshot, "sound_gunshot", "/Audio/Guns/Gunshots/smg.ogg");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fires projectile from an entity at a coordinate.
|
||||
/// </summary>
|
||||
protected void FireAtCoord(IEntity source, GridCoordinates coord, string projectileType, double spreadStdDev, int projectilesFired = 1, double evenSpreadAngle = 0, float velocity = 0)
|
||||
{
|
||||
var angle = GetAngleFromClickLocation(source, coord);
|
||||
FireAtAngle(source, angle, projectileType, spreadStdDev, projectilesFired, evenSpreadAngle, velocity);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fires projectile in the direction of an angle.
|
||||
/// </summary>
|
||||
protected void FireAtAngle(IEntity source, Angle angle, string projectileType = null, double spreadStdDev = 0, int projectilesFired = 1, double evenSpreadAngle = 0, float velocity = 0)
|
||||
{
|
||||
List<Angle> sprayanglechange = null;
|
||||
if (evenSpreadAngle != 0 & projectilesFired > 1)
|
||||
{
|
||||
sprayanglechange = Linspace(-evenSpreadAngle/2, evenSpreadAngle/2, projectilesFired);
|
||||
}
|
||||
for (var i = 1; i <= projectilesFired; i++)
|
||||
{
|
||||
Angle finalangle = angle + Angle.FromDegrees(_spreadRandom.NextGaussian(0, spreadStdDev)) + (sprayanglechange != null ? sprayanglechange[i - 1] : 0);
|
||||
var projectile = Owner.EntityManager.SpawnEntity(projectileType, Owner.Transform.GridPosition);
|
||||
projectile.Transform.GridPosition = source.Transform.GridPosition; //move projectile to entity it is being fired from
|
||||
projectile.GetComponent<ProjectileComponent>().IgnoreEntity(source);//make sure it doesn't hit the source entity
|
||||
var finalvelocity = projectile.GetComponent<ProjectileComponent>().Velocity + velocity;//add velocity
|
||||
projectile.GetComponent<PhysicsComponent>().LinearVelocity = finalangle.ToVec() * finalvelocity;//Rotate the bullets sprite to the correct direction
|
||||
projectile.Transform.LocalRotation = finalangle.Theta;
|
||||
}
|
||||
PlayFireSound();
|
||||
if (source.TryGetComponent(out CameraRecoilComponent recoil))
|
||||
{
|
||||
var recoilVec = angle.ToVec() * -0.15f;
|
||||
recoil.Kick(recoilVec);
|
||||
}
|
||||
}
|
||||
|
||||
private void PlayFireSound() => Owner.GetComponent<SoundComponent>().Play(_soundGunshot);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the angle from an entity to a coordinate.
|
||||
/// </summary>
|
||||
protected Angle GetAngleFromClickLocation(IEntity source, GridCoordinates clickLocation) => new Angle(clickLocation.Position - source.Transform.GridPosition.Position);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a list of numbers that form a set of equal intervals between the start and end value. Used to calculate shotgun spread angles.
|
||||
/// </summary>
|
||||
protected List<Angle> Linspace(double start, double end, int intervals)
|
||||
{
|
||||
var linspace = new List<Angle> { };
|
||||
for (var i = 0; i <= intervals - 1; i++)
|
||||
{
|
||||
linspace.Add(Angle.FromDegrees(start + (end - start) * i / (intervals - 1)));
|
||||
}
|
||||
return linspace;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,130 +0,0 @@
|
||||
using Content.Server.GameObjects.Components.Mobs;
|
||||
using Content.Server.GameObjects.Components.Projectiles;
|
||||
using Content.Server.GameObjects.Components.Sound;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Interfaces.GameObjects;
|
||||
using Robust.Shared.Interfaces.Random;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Random;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Content.Server.GameObjects.Components.Weapon.Ranged.Projectile
|
||||
{
|
||||
public abstract class ProjectileWeaponComponent : Component
|
||||
{
|
||||
private float _spreadStdDev = 3;
|
||||
private bool _spread = true;
|
||||
private string _soundGunshot;
|
||||
|
||||
#pragma warning disable 649
|
||||
[Dependency] private IRobustRandom _spreadRandom;
|
||||
#pragma warning restore 649
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public bool Spread
|
||||
{
|
||||
get => _spread;
|
||||
set => _spread = value;
|
||||
}
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public float SpreadStdDev
|
||||
{
|
||||
get => _spreadStdDev;
|
||||
set => _spreadStdDev = value;
|
||||
}
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
var rangedWeapon = Owner.GetComponent<RangedWeaponComponent>();
|
||||
rangedWeapon.FireHandler = Fire;
|
||||
}
|
||||
|
||||
public override void ExposeData(ObjectSerializer serializer)
|
||||
{
|
||||
base.ExposeData(serializer);
|
||||
|
||||
serializer.DataField(ref _spread, "spread", true);
|
||||
serializer.DataField(ref _spreadStdDev, "spreadstddev", 3);
|
||||
serializer.DataField(ref _soundGunshot, "sound_gunshot", "/Audio/Guns/Gunshots/smg.ogg");
|
||||
}
|
||||
|
||||
private void Fire(IEntity user, GridCoordinates clickLocation)
|
||||
{
|
||||
var projectile = GetFiredProjectile();
|
||||
if (projectile == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var userPosition = user.Transform.GridPosition; //Remember world positions are ephemeral and can only be used instantaneously
|
||||
var angle = new Angle(clickLocation.Position - userPosition.Position);
|
||||
|
||||
if (user.TryGetComponent(out CameraRecoilComponent recoil))
|
||||
{
|
||||
var recoilVec = angle.ToVec() * -0.15f;
|
||||
recoil.Kick(recoilVec);
|
||||
}
|
||||
|
||||
if (Spread)
|
||||
{
|
||||
angle += Angle.FromDegrees(_spreadRandom.NextGaussian(0, SpreadStdDev));
|
||||
}
|
||||
|
||||
projectile.Transform.GridPosition = userPosition;
|
||||
|
||||
//Give it the velocity we fire from this weapon, and make sure it doesn't shoot our character
|
||||
projectile.GetComponent<ProjectileComponent>().IgnoreEntity(user);
|
||||
var velocity = projectile.GetComponent<ProjectileComponent>().Velocity;
|
||||
|
||||
//Give it the velocity this weapon gives to things it fires from itself
|
||||
projectile.GetComponent<PhysicsComponent>().LinearVelocity = angle.ToVec() * velocity;
|
||||
|
||||
//Rotate the bullets sprite to the correct direction, from north facing I guess
|
||||
projectile.Transform.LocalRotation = angle.Theta;
|
||||
|
||||
// Sound!
|
||||
Owner.GetComponent<SoundComponent>().Play(_soundGunshot);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Try to get a projectile for firing. If null, nothing will be fired.
|
||||
/// </summary>
|
||||
protected abstract IEntity GetFiredProjectile();
|
||||
}
|
||||
|
||||
public enum BallisticCaliber
|
||||
{
|
||||
Unspecified = 0,
|
||||
// .32
|
||||
A32,
|
||||
// .357
|
||||
A357,
|
||||
// .44
|
||||
A44,
|
||||
// .45mm
|
||||
A45mm,
|
||||
// .50 cal
|
||||
A50,
|
||||
// 5.56mm
|
||||
A556mm,
|
||||
// 6.5mm
|
||||
A65mm,
|
||||
// 7.62mm
|
||||
A762mm,
|
||||
// 9mm
|
||||
A9mm,
|
||||
// 10mm
|
||||
A10mm,
|
||||
// 20mm
|
||||
A20mm,
|
||||
// 24mm
|
||||
A24mm,
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using Content.Server.GameObjects.Components.Mobs;
|
||||
using Content.Server.GameObjects.EntitySystems;
|
||||
using Content.Shared.GameObjects.Components.Weapons.Ranged;
|
||||
using Robust.Server.Interfaces.Player;
|
||||
using Robust.Shared.GameObjects;
|
||||
@@ -30,7 +31,7 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged
|
||||
|
||||
private bool UserCanFire(IEntity user)
|
||||
{
|
||||
return UserCanFireHandler == null || UserCanFireHandler(user);
|
||||
return (UserCanFireHandler == null || UserCanFireHandler(user)) && ActionBlockerSystem.CanAttack(user);
|
||||
}
|
||||
|
||||
private void Fire(IEntity user, GridCoordinates clickLocation)
|
||||
|
||||
@@ -20,6 +20,8 @@ namespace Content.Server.GameObjects.EntitySystems
|
||||
bool CanPickup();
|
||||
|
||||
bool CanEmote();
|
||||
|
||||
bool CanAttack();
|
||||
}
|
||||
|
||||
public class ActionBlockerSystem : EntitySystem
|
||||
@@ -105,5 +107,17 @@ namespace Content.Server.GameObjects.EntitySystems
|
||||
|
||||
return canemote;
|
||||
}
|
||||
|
||||
public static bool CanAttack(IEntity entity)
|
||||
{
|
||||
bool canattack = true;
|
||||
|
||||
foreach (var actionblockercomponents in entity.GetAllComponents<IActionBlocker>())
|
||||
{
|
||||
canattack &= actionblockercomponents.CanAttack();
|
||||
}
|
||||
|
||||
return canattack;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -273,26 +273,31 @@ namespace Content.Server.GameObjects.EntitySystems
|
||||
/// If the <paramref name="range"/> is zero or negative,
|
||||
/// this method will only check if nothing obstructs the two sets of coordinates..
|
||||
/// </summary>
|
||||
/// <param name="mapManager">Map manager containing the two GridIds.</param>
|
||||
/// <param name="coords">Set of coordinates to use.</param>
|
||||
/// <param name="otherCoords">Other set of coordinates to use.</param>
|
||||
/// <param name="range">maximum distance between the two sets of coordinates.</param>
|
||||
/// <param name="collisionMask">the mask to check for collisions</param>
|
||||
/// <param name="ignoredEnt">the entity to be ignored when checking for collisions.</param>
|
||||
/// <param name="mapManager">Map manager containing the two GridIds.</param>
|
||||
/// <param name="insideBlockerValid">if coordinates inside obstructions count as obstructed or not</param>
|
||||
/// <returns>True if the two points are within a given range without being obstructed.</returns>
|
||||
public bool InRangeUnobstructed(GridCoordinates coords, GridCoordinates otherCoords, float range = InteractionRange, int collisionMask = (int)CollisionGroup.Impassable, IEntity ignoredEnt = null)
|
||||
public bool InRangeUnobstructed(MapCoordinates coords, Vector2 otherCoords, float range = InteractionRange,
|
||||
int collisionMask = (int) CollisionGroup.Impassable, IEntity ignoredEnt = null, bool insideBlockerValid = false)
|
||||
{
|
||||
if (range > 0f && !coords.InRange(_mapManager, otherCoords, range))
|
||||
{
|
||||
var dir = otherCoords - coords.Position;
|
||||
|
||||
if (dir.LengthSquared.Equals(0f))
|
||||
return true;
|
||||
|
||||
if (range > 0f && !(dir.LengthSquared <= range*range))
|
||||
return false;
|
||||
}
|
||||
|
||||
var dir = (otherCoords.Position - coords.Position);
|
||||
if (!(dir.Length > 0f)) return true;
|
||||
var ray = new CollisionRay(coords.Position, dir.Normalized, collisionMask);
|
||||
var rayResults = _physicsManager.IntersectRay(_mapManager.GetGrid(coords.GridID).ParentMapId, ray, dir.Length, ignoredEnt);
|
||||
var rayResults = _physicsManager.IntersectRay(coords.MapId, ray, dir.Length, ignoredEnt, true);
|
||||
|
||||
return !rayResults.DidHitObject;
|
||||
|
||||
|
||||
return !rayResults.DidHitObject || (insideBlockerValid && rayResults.DidHitObject && rayResults.Distance < 1f);
|
||||
}
|
||||
|
||||
private bool HandleActivateItemInWorld(ICommonSession session, GridCoordinates coords, EntityUid uid)
|
||||
@@ -848,7 +853,7 @@ namespace Content.Server.GameObjects.EntitySystems
|
||||
var item = hands.GetActiveHand?.Owner;
|
||||
|
||||
// TODO: If item is null we need some kinda unarmed combat.
|
||||
if (!ActionBlockerSystem.CanInteract(player) || item == null)
|
||||
if (!ActionBlockerSystem.CanAttack(player) || item == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -126,7 +126,7 @@ namespace Content.Server.GameObjects.EntitySystems
|
||||
|
||||
var interactionSystem = _entitySystemManager.GetEntitySystem<InteractionSystem>();
|
||||
|
||||
if(interactionSystem.InRangeUnobstructed(coords, ent.Transform.GridPosition, 0f, ignoredEnt:ent))
|
||||
if(interactionSystem.InRangeUnobstructed(coords.ToMap(_mapManager), ent.Transform.WorldPosition, 0f, ignoredEnt: ent))
|
||||
if (coords.InRange(_mapManager, ent.Transform.GridPosition, InteractionSystem.InteractionRange))
|
||||
{
|
||||
handsComp.Drop(handsComp.ActiveIndex, coords);
|
||||
|
||||
@@ -40,9 +40,6 @@ namespace Content.Server.GlobalVerbs
|
||||
var userMind = user.GetComponent<IActorComponent>().playerSession.ContentData().Mind;
|
||||
var targetMind = target.GetComponent<MindComponent>();
|
||||
|
||||
if(userMind.IsVisitingEntity)
|
||||
userMind.UnVisit();
|
||||
|
||||
targetMind.Mind?.TransferTo(null);
|
||||
userMind.TransferTo(target);
|
||||
}
|
||||
|
||||
BIN
Resources/Audio/items/skub.ogg
Normal file
@@ -70,7 +70,9 @@
|
||||
name: "Bike Horn"
|
||||
id: cargo.bikehorn
|
||||
description: HONK!
|
||||
icon: Objects/Fun/bikehorn.rsi
|
||||
icon:
|
||||
sprite: Objects/Fun/bikehorn.rsi
|
||||
state: icon
|
||||
product: crate_bikehorn
|
||||
cost: 300
|
||||
category: Other
|
||||
@@ -102,7 +104,9 @@
|
||||
name: "Medical Scanner"
|
||||
id: cargo.medscanner
|
||||
description: Scans patients. First we stick this probe...
|
||||
icon: Buildings/medical_scanner.rsi
|
||||
icon:
|
||||
sprite: Buildings/medical_scanner.rsi
|
||||
state: scanner_open
|
||||
product: crate_medscanner
|
||||
cost: 400
|
||||
category: Medical
|
||||
|
||||
12
Resources/Prototypes/Construction/misc.yml
Normal file
@@ -0,0 +1,12 @@
|
||||
- type: construction
|
||||
name: Skub
|
||||
id: skub
|
||||
category: Items/Misc
|
||||
keywords: [misc]
|
||||
description: In the end, there is only Skub.
|
||||
icon: Objects/Misc/skub.rsi/icon.png
|
||||
result: Skub
|
||||
objecttype: Item
|
||||
steps:
|
||||
- material: Metal
|
||||
amount: 1
|
||||
@@ -25,7 +25,7 @@
|
||||
name: Table
|
||||
id: table
|
||||
category: Structures
|
||||
icon:
|
||||
icon:
|
||||
sprite: Buildings/table_solid.rsi
|
||||
state: plain_preview
|
||||
result: table
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
id: bullet_10mm
|
||||
name: 10mm Bullet
|
||||
parent: bullet_base
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 20
|
||||
@@ -13,7 +13,7 @@
|
||||
id: bullet_10mmf
|
||||
name: 10mm Bullet (Flash)
|
||||
parent: bullet_base
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 20
|
||||
@@ -24,7 +24,7 @@
|
||||
id: bullet_10mmhv
|
||||
name: 10mm Bullet (High-Velocity)
|
||||
parent: bullet_base
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 30
|
||||
@@ -35,7 +35,7 @@
|
||||
id: bullet_10mml
|
||||
name: 10mm Bullet (L)
|
||||
parent: bullet_base
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 20
|
||||
@@ -46,7 +46,7 @@
|
||||
id: bullet_10mmp
|
||||
name: 10mm Bullet (Practice)
|
||||
parent: bullet_base
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 20
|
||||
@@ -57,7 +57,7 @@
|
||||
id: bullet_10mmr
|
||||
name: 10mm Bullet (Rubber)
|
||||
parent: bullet_base
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 20
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
# Empty mags
|
||||
- type: entity
|
||||
id: magazine_12g_empty
|
||||
name: "12g magazine - empty"
|
||||
parent: BaseItem
|
||||
abstract: true
|
||||
components:
|
||||
- type: BallisticMagazine
|
||||
caliber: A12g
|
||||
magazine: A12g
|
||||
capacity: 8
|
||||
- type: Sprite
|
||||
netsync: false
|
||||
|
||||
#Magazines
|
||||
- type: entity
|
||||
id: magazine_12g_shotgun
|
||||
name: "12g Magazine"
|
||||
parent: magazine_12g_empty
|
||||
components:
|
||||
- type: BallisticMagazine
|
||||
fill: ammo_casing_12g
|
||||
caliber: A12g
|
||||
magazine: A12g
|
||||
capacity: 20
|
||||
- type: Icon
|
||||
sprite: Objects/Guns/Ammunition/Magazine/10mm/12mml.rsi
|
||||
state: 12mml-1
|
||||
- type: Sprite
|
||||
sprite: Objects/Guns/Ammunition/Magazine/10mm/12mml.rsi
|
||||
state: 12mml-1
|
||||
- type: Appearance
|
||||
visuals:
|
||||
- type: BallisticMagazineVisualizer2D
|
||||
base_state: 12mml
|
||||
steps: 2
|
||||
|
||||
# Casings
|
||||
- type: entity
|
||||
id: ammo_casing_12g
|
||||
name: "12g casing"
|
||||
parent: BaseItem
|
||||
components:
|
||||
- type: BallisticBullet
|
||||
caliber: A12g
|
||||
projectile: pellet_12g
|
||||
projectilesfired : 6
|
||||
- type: Sprite
|
||||
sprite: Objects/Guns/Ammunition/ammo_casing.rsi
|
||||
state: s-casing
|
||||
drawdepth: FloorObjects
|
||||
- type: Icon
|
||||
sprite: Objects/Guns/Ammunition/ammo_casing.rsi
|
||||
state: s-casing
|
||||
@@ -0,0 +1,34 @@
|
||||
# Empty boxes
|
||||
- type: entity
|
||||
id: box_12g_empty
|
||||
name: "12g box - empty"
|
||||
parent: BaseItem
|
||||
abstract: true
|
||||
components:
|
||||
- type: AmmoBox
|
||||
caliber: A12g
|
||||
capacity: 30
|
||||
- type: Sprite
|
||||
netsync: false
|
||||
|
||||
# Ammo boxes
|
||||
- type: entity
|
||||
id: box_12g
|
||||
name: "12g box"
|
||||
parent: box_12g_empty
|
||||
components:
|
||||
- type: AmmoBox
|
||||
fill: ammo_casing_12g
|
||||
caliber: A12g
|
||||
capacity: 30
|
||||
- type: Icon
|
||||
sprite: Objects/Guns/Ammunition/Boxes/10mm/box10mm.rsi
|
||||
state: box10mm-1
|
||||
- type: Sprite
|
||||
sprite: Objects/Guns/Ammunition/Boxes/10mm/box10mm.rsi
|
||||
state: box10mm-1
|
||||
- type: Appearance
|
||||
visuals:
|
||||
- type: BallisticMagazineVisualizer2D
|
||||
base_state: box10mm
|
||||
steps: 2
|
||||
@@ -0,0 +1,10 @@
|
||||
- type: entity
|
||||
id: pellet_12g
|
||||
name: 12g Pellet
|
||||
parent: bullet_base
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 20
|
||||
damages:
|
||||
Brute: 10
|
||||
@@ -2,9 +2,9 @@
|
||||
id: bullet_20mm
|
||||
name: 20mm Bullet
|
||||
parent: bullet_base
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 20
|
||||
damages:
|
||||
Brute: 10
|
||||
Brute: 10
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
id: bullet_24mm
|
||||
name: 24mm Bullet
|
||||
parent: bullet_base
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 20
|
||||
@@ -13,7 +13,7 @@
|
||||
id: bullet_24mmf
|
||||
name: 24mm Bullet (Flash)
|
||||
parent: bullet_basef
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 20
|
||||
@@ -24,7 +24,7 @@
|
||||
id: bullet_24mmhv
|
||||
name: 24mm Bullet (High-Velocity)
|
||||
parent: bullet_basehv
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 27
|
||||
@@ -35,7 +35,7 @@
|
||||
id: bullet_24mml
|
||||
name: 24mm Bullet (L)
|
||||
parent: bullet_basel
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 20
|
||||
@@ -46,7 +46,7 @@
|
||||
id: bullet_24mmp
|
||||
name: 24mm Bullet (Practice)
|
||||
parent: bullet_basep
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 20
|
||||
@@ -57,7 +57,7 @@
|
||||
id: bullet_24mmr
|
||||
name: 24mm Bullet (Rubber)
|
||||
parent: bullet_baser
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 20
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
id: bullet_45mm
|
||||
name: .45mm Bullet
|
||||
parent: bullet_base
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 20
|
||||
@@ -13,7 +13,7 @@
|
||||
id: bullet_45mmf
|
||||
name: .45mm Bullet (Flash)
|
||||
parent: bullet_basef
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 20
|
||||
@@ -24,7 +24,7 @@
|
||||
id: bullet_45mmhv
|
||||
name: .45mm Bullet (High-Velocity)
|
||||
parent: bullet_basehv
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 30
|
||||
@@ -35,7 +35,7 @@
|
||||
id: bullet_45mml
|
||||
name: .45mm Bullet (L)
|
||||
parent: bullet_basel
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 20
|
||||
@@ -46,7 +46,7 @@
|
||||
id: bullet_45mmp
|
||||
name: .45mm Bullet (Practice)
|
||||
parent: bullet_basep
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 20
|
||||
@@ -57,7 +57,7 @@
|
||||
id: bullet_45mmr
|
||||
name: .45mm Bullet (Rubber)
|
||||
parent: bullet_baser
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 20
|
||||
@@ -2,7 +2,7 @@
|
||||
id: bullet_556mm
|
||||
name: 5.56mm Bullet
|
||||
parent: bullet_base
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 20
|
||||
@@ -13,7 +13,7 @@
|
||||
id: bullet_556mmf
|
||||
name: 5.56mm Bullet (Flash)
|
||||
parent: bullet_basef
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 20
|
||||
@@ -24,7 +24,7 @@
|
||||
id: bullet_556mmhv
|
||||
name: 5.56mm Bullet (High-Velocity)
|
||||
parent: bullet_basehv
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 30
|
||||
@@ -35,7 +35,7 @@
|
||||
id: bullet_556mml
|
||||
name: 5.56mm Bullet (L)
|
||||
parent: bullet_basel
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 20
|
||||
@@ -46,7 +46,7 @@
|
||||
id: bullet_556mmp
|
||||
name: 5.56mm Bullet (Practice)
|
||||
parent: bullet_basep
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 20
|
||||
@@ -57,7 +57,7 @@
|
||||
id: bullet_556mmr
|
||||
name: 5.56mm Bullet (Rubber)
|
||||
parent: bullet_baser
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 20
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
id: bullet_65mm
|
||||
name: 6.5mm Bullet
|
||||
parent: bullet_base
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 20
|
||||
@@ -13,7 +13,7 @@
|
||||
id: bullet_65mmf
|
||||
name: 6.5mm Bullet (Flash)
|
||||
parent: bullet_basef
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 20
|
||||
@@ -24,7 +24,7 @@
|
||||
id: bullet_65mmhv
|
||||
name: 6.5mm Bullet (High-Velocity)
|
||||
parent: bullet_basehv
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 30
|
||||
@@ -35,7 +35,7 @@
|
||||
id: bullet_65mml
|
||||
name: 6.5mm Bullet (L)
|
||||
parent: bullet_basel
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 20
|
||||
@@ -46,7 +46,7 @@
|
||||
id: bullet_65mmp
|
||||
name: 6.5mm Bullet (Practice)
|
||||
parent: bullet_basep
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 20
|
||||
@@ -57,7 +57,7 @@
|
||||
id: bullet_65mmr
|
||||
name: 6.5mm Bullet (Rubber)
|
||||
parent: bullet_baser
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 20
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
id: bullet_762mm
|
||||
name: 7.62mm Bullet
|
||||
parent: bullet_base
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 20
|
||||
@@ -13,7 +13,7 @@
|
||||
id: bullet_762mmf
|
||||
name: 7.62mm Bullet (Flash)
|
||||
parent: bullet_base
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 20
|
||||
@@ -24,7 +24,7 @@
|
||||
id: bullet_762mmhv
|
||||
name: 7.62mm Bullet (High-Velocity)
|
||||
parent: bullet_base
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 30
|
||||
@@ -35,7 +35,7 @@
|
||||
id: bullet_762mml
|
||||
name: 7.62mm Bullet (L)
|
||||
parent: bullet_base
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 20
|
||||
@@ -46,7 +46,7 @@
|
||||
id: bullet_762mmp
|
||||
name: 7.62mm Bullet (Practice)
|
||||
parent: bullet_base
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 20
|
||||
@@ -57,7 +57,7 @@
|
||||
id: bullet_762mmr
|
||||
name: 7.62mm Bullet (Rubber)
|
||||
parent: bullet_base
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 20
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
id: bullet_9mm
|
||||
name: 9mm Bullet
|
||||
parent: bullet_base
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 20
|
||||
@@ -13,7 +13,7 @@
|
||||
id: bullet_9mmf
|
||||
name: 9mm Bullet (Flash)
|
||||
parent: bullet_base
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 20
|
||||
@@ -24,7 +24,7 @@
|
||||
id: bullet_9mmhv
|
||||
name: 9mm Bullet (High-Velocity)
|
||||
parent: bullet_base
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 30
|
||||
@@ -35,7 +35,7 @@
|
||||
id: bullet_9mml
|
||||
name: 9mm Bullet (L)
|
||||
parent: bullet_base
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 20
|
||||
@@ -46,7 +46,7 @@
|
||||
id: bullet_9mmp
|
||||
name: 9mm Bullet (Practice)
|
||||
parent: bullet_base
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 20
|
||||
@@ -57,7 +57,7 @@
|
||||
id: bullet_9mmr
|
||||
name: 9mm Bullet (Rubber)
|
||||
parent: bullet_base
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 20
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
id: bullet_32
|
||||
name: .32 Bullet
|
||||
parent: bullet_base
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 20
|
||||
@@ -13,7 +13,7 @@
|
||||
id: bullet_32f
|
||||
name: .32 Bullet (Flash)
|
||||
parent: bullet_basef
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 20
|
||||
@@ -24,7 +24,7 @@
|
||||
id: bullet_32hv
|
||||
name: .32 Bullet (High-Velocity)
|
||||
parent: bullet_basehv
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 30
|
||||
@@ -35,7 +35,7 @@
|
||||
id: bullet_32l
|
||||
name: .32 Bullet (L)
|
||||
parent: bullet_basel
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 20
|
||||
@@ -46,7 +46,7 @@
|
||||
id: bullet_32p
|
||||
name: .32 Bullet (Practice)
|
||||
parent: bullet_basep
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 20
|
||||
@@ -57,7 +57,7 @@
|
||||
id: bullet_32r
|
||||
name: .32 Bullet (Rubber)
|
||||
parent: bullet_baser
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 20
|
||||
@@ -2,7 +2,7 @@
|
||||
id: bullet_357
|
||||
name: .357 Bullet
|
||||
parent: bullet_base
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 20
|
||||
@@ -13,7 +13,7 @@
|
||||
id: bullet_357f
|
||||
name: .357 Bullet (Flash)
|
||||
parent: bullet_basef
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 20
|
||||
@@ -24,7 +24,7 @@
|
||||
id: bullet_357hv
|
||||
name: .357 Bullet (High-Velocity)
|
||||
parent: bullet_basehv
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 30
|
||||
@@ -35,7 +35,7 @@
|
||||
id: bullet_357l
|
||||
name: .357 Bullet (L)
|
||||
parent: bullet_basel
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 20
|
||||
@@ -46,7 +46,7 @@
|
||||
id: bullet_357p
|
||||
name: .357 Bullet (Practice)
|
||||
parent: bullet_basep
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 20
|
||||
@@ -57,7 +57,7 @@
|
||||
id: bullet_357r
|
||||
name: .357 Bullet (Rubber)
|
||||
parent: bullet_baser
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 20
|
||||
@@ -2,7 +2,7 @@
|
||||
id: bullet_44
|
||||
name: .44 Bullet
|
||||
parent: bullet_base
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 20
|
||||
@@ -13,7 +13,7 @@
|
||||
id: bullet_44f
|
||||
name: .44 Bullet (Flash)
|
||||
parent: bullet_basef
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 20
|
||||
@@ -24,7 +24,7 @@
|
||||
id: bullet_44hv
|
||||
name: .44 Bullet (High-Velocity)
|
||||
parent: bullet_basehv
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 30
|
||||
@@ -35,7 +35,7 @@
|
||||
id: bullet_44l
|
||||
name: .44 Bullet (L)
|
||||
parent: bullet_basel
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 20
|
||||
@@ -46,7 +46,7 @@
|
||||
id: bullet_44p
|
||||
name: .44 Bullet (Practice)
|
||||
parent: bullet_basep
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 20
|
||||
@@ -57,7 +57,7 @@
|
||||
id: bullet_44r
|
||||
name: .44 Bullet (Rubber)
|
||||
parent: bullet_baser
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 20
|
||||
@@ -2,7 +2,7 @@
|
||||
id: bullet_50
|
||||
name: .50 cal Bullet
|
||||
parent: bullet_base
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 20
|
||||
@@ -13,7 +13,7 @@
|
||||
id: bullet_50f
|
||||
name: .50 cal Bullet (Flash)
|
||||
parent: bullet_basef
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 20
|
||||
@@ -24,7 +24,7 @@
|
||||
id: bullet_50hv
|
||||
name: .50 cal Bullet (High-Velocity)
|
||||
parent: bullet_basehv
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 30
|
||||
@@ -35,7 +35,7 @@
|
||||
id: bullet_50l
|
||||
name: .50 cal Bullet (L)
|
||||
parent: bullet_basel
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 20
|
||||
@@ -46,7 +46,7 @@
|
||||
id: bullet_50p
|
||||
name: .50 cal Bullet (Practice)
|
||||
parent: bullet_basep
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 20
|
||||
@@ -57,7 +57,7 @@
|
||||
id: bullet_50r
|
||||
name: .50 cal Bullet (Rubber)
|
||||
parent: bullet_baser
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
velocity: 20
|
||||
@@ -2,9 +2,10 @@
|
||||
- type: entity
|
||||
id: bullet_base
|
||||
name: bullet_base
|
||||
description: If you can see this you're dead!
|
||||
description: If you can see this you're probably dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Clickable
|
||||
- type: Sprite
|
||||
directional: false
|
||||
texture: Objects/Projectiles/bullet.png
|
||||
@@ -34,7 +35,6 @@
|
||||
id: bullet_basef
|
||||
name: Base Bullet Flash
|
||||
parent: bullet_base
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
@@ -46,7 +46,6 @@
|
||||
id: bullet_basehv
|
||||
name: Base Bullet High-Velocity
|
||||
parent: bullet_base
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
@@ -58,7 +57,6 @@
|
||||
id: bullet_basel
|
||||
name: Base Bullet L
|
||||
parent: bullet_base
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
@@ -70,7 +68,6 @@
|
||||
id: bullet_basep
|
||||
name: Base Bullet Practice
|
||||
parent: bullet_base
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
@@ -82,7 +79,6 @@
|
||||
id: bullet_baser
|
||||
name: Base Bullet Rubber
|
||||
parent: bullet_base
|
||||
description: If you can see this you're dead!
|
||||
abstract: true
|
||||
components:
|
||||
- type: Projectile
|
||||
|
||||
@@ -81,7 +81,7 @@
|
||||
steps: 1
|
||||
- type: Item
|
||||
Size: 24
|
||||
sprite: Objects/Guns/Rifles/black-AK.rsi
|
||||
sprite: Objects/Guns/Rifles/black-ak.rsi
|
||||
|
||||
- type: entity
|
||||
name: Carbine
|
||||
|
||||
47
Resources/Prototypes/Entities/Weapons/Shotguns/shotguns.yml
Normal file
@@ -0,0 +1,47 @@
|
||||
- type: entity
|
||||
name: Shotgun
|
||||
parent: BaseItem
|
||||
id: BaseShotgun
|
||||
description: A rooty tooty point and shooty.
|
||||
abstract: true
|
||||
components:
|
||||
- type: Sound
|
||||
- type: RangedWeapon
|
||||
automatic: false
|
||||
firerate: 20
|
||||
- type: BallisticMagazineWeapon
|
||||
caliber: A12g
|
||||
evenspread : 40
|
||||
magazines:
|
||||
- A12g
|
||||
default_magazine: magazine_12g_shotgun
|
||||
auto_eject_magazine: false
|
||||
sound_auto_eject: /Audio/Guns/EmptyAlarm/smg_empty_alarm.ogg
|
||||
sound_magazine_in: /Audio/Guns/MagIn/smg_magin.ogg
|
||||
sound_magazine_out: /Audio/Guns/MagOut/smg_magout.ogg
|
||||
sound_empty: /Audio/Guns/Empty/empty.ogg
|
||||
sound_gunshot: /Audio/Guns/Gunshots/smg.ogg
|
||||
|
||||
- type: entity
|
||||
name: Magazine Fed Shotgun
|
||||
parent: BaseShotgun
|
||||
id: MagazineFedShotgun
|
||||
components:
|
||||
- type: Sprite
|
||||
netsync: false
|
||||
sprite: Objects/Guns/SMGs/c20r.rsi
|
||||
state: c20r-5
|
||||
- type: Icon
|
||||
sprite: Objects/Guns/SMGs/c20r.rsi
|
||||
state: c20r-5
|
||||
- type: Appearance
|
||||
visuals:
|
||||
- type: BallisticMagazineWeaponVisualizer2D
|
||||
base_state: c20r
|
||||
steps: 6
|
||||
- type: Item
|
||||
Size: 24
|
||||
sprite: Objects/Guns/SMGs/c20r.rsi
|
||||
- type: Item
|
||||
Size: 24
|
||||
sprite: Objects/Guns/SMGs/wt550.rsi
|
||||
@@ -83,8 +83,17 @@
|
||||
static: true
|
||||
products:
|
||||
- cargo.dice
|
||||
- cargo.flashlight
|
||||
- cargo.Medkit
|
||||
- cargo.flashlight
|
||||
- cargo.lightblub
|
||||
- cargo.fireextinguisher
|
||||
- cargo.pen
|
||||
- cargo.bikehorn
|
||||
- cargo.cleaver
|
||||
- cargo.fueltank
|
||||
- cargo.medscanner
|
||||
- cargo.glass
|
||||
- cargo.cable
|
||||
- type: UserInterface
|
||||
interfaces:
|
||||
- key: enum.CargoConsoleUiKey.Key
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
- type: Collidable
|
||||
shapes:
|
||||
- !type:PhysShapeAabb
|
||||
bounds: "-0.5,-0.25,0.5,0.25"
|
||||
bounds: "-0.5,0,0.5,1"
|
||||
layer: 15
|
||||
IsScrapingFloor: true
|
||||
- type: Physics
|
||||
|
||||
@@ -124,119 +124,119 @@
|
||||
name: Flashlight Crate (x5)
|
||||
parent: crate_generic
|
||||
components:
|
||||
- type: StorageFill
|
||||
contents:
|
||||
- Flashlight
|
||||
- Flashlight
|
||||
- Flashlight
|
||||
- Flashlight
|
||||
- Flashlight
|
||||
- type: StorageFill
|
||||
contents:
|
||||
- FlashlightLantern
|
||||
- FlashlightLantern
|
||||
- FlashlightLantern
|
||||
- FlashlightLantern
|
||||
- FlashlightLantern
|
||||
|
||||
- type: entity
|
||||
id: crate_light_bulb
|
||||
name: Light Bulb Crate (x10)
|
||||
parent: crate_generic
|
||||
components:
|
||||
- type: StorageFill
|
||||
contents:
|
||||
- Light Bulb
|
||||
- Light Bulb
|
||||
- Light Bulb
|
||||
- Light Bulb
|
||||
- Light Bulb
|
||||
- Light Bulb
|
||||
- Light Bulb
|
||||
- Light Bulb
|
||||
- Light Bulb
|
||||
- Light Bulb
|
||||
- type: StorageFill
|
||||
contents:
|
||||
- LightBulb
|
||||
- LightBulb
|
||||
- LightBulb
|
||||
- LightBulb
|
||||
- LightBulb
|
||||
- LightBulb
|
||||
- LightBulb
|
||||
- LightBulb
|
||||
- LightBulb
|
||||
- LightBulb
|
||||
|
||||
- type: entity
|
||||
id: crate_fire_extinguisher
|
||||
name: Fire Extinguisher Crate (x3)
|
||||
parent: crate_generic
|
||||
components:
|
||||
- type: StorageFill
|
||||
contents:
|
||||
- Fire Extinguisher
|
||||
- Fire Extinguisher
|
||||
- Fire Extinguisher
|
||||
- type: StorageFill
|
||||
contents:
|
||||
- fire_extinguisher
|
||||
- fire_extinguisher
|
||||
- fire_extinguisher
|
||||
|
||||
- type: entity
|
||||
id: crate_pen
|
||||
name: Pen Crate (x10)
|
||||
parent: crate_generic
|
||||
components:
|
||||
- type: StorageFill
|
||||
contents:
|
||||
- Pen
|
||||
- Pen
|
||||
- Pen
|
||||
- Pen
|
||||
- Pen
|
||||
- Pen
|
||||
- Pen
|
||||
- Pen
|
||||
- Pen
|
||||
- Pen
|
||||
- type: StorageFill
|
||||
contents:
|
||||
- Pen
|
||||
- Pen
|
||||
- Pen
|
||||
- Pen
|
||||
- Pen
|
||||
- Pen
|
||||
- Pen
|
||||
- Pen
|
||||
- Pen
|
||||
- Pen
|
||||
|
||||
- type: entity
|
||||
id: crate_bikehorn
|
||||
name: Bike Horn Crate (x5)
|
||||
parent: crate_generic
|
||||
components:
|
||||
- type: StorageFill
|
||||
contents:
|
||||
- Bike Horn
|
||||
- Bike Horn
|
||||
- Bike Horn
|
||||
- Bike Horn
|
||||
- Bike Horn
|
||||
- type: StorageFill
|
||||
contents:
|
||||
- BikeHorn
|
||||
- BikeHorn
|
||||
- BikeHorn
|
||||
- BikeHorn
|
||||
- BikeHorn
|
||||
|
||||
- type: entity
|
||||
id: crate_cleaver
|
||||
name: Cleaver Crate (x5)
|
||||
parent: crate_generic
|
||||
components:
|
||||
- type: StorageFill
|
||||
contents:
|
||||
- Cleaver
|
||||
- Cleaver
|
||||
- Cleaver
|
||||
- Cleaver
|
||||
- Cleaver
|
||||
- type: StorageFill
|
||||
contents:
|
||||
- ButchCleaver
|
||||
- ButchCleaver
|
||||
- ButchCleaver
|
||||
- ButchCleaver
|
||||
- ButchCleaver
|
||||
|
||||
- type: entity
|
||||
id: crate_fueltank
|
||||
name: Fuel Tank
|
||||
parent: crate_generic
|
||||
components:
|
||||
- type: StorageFill
|
||||
contents:
|
||||
- Fuel Tank
|
||||
- type: StorageFill
|
||||
contents:
|
||||
- weldtank
|
||||
|
||||
- type: entity
|
||||
id: crate_medscanner
|
||||
name: Medical Scanner
|
||||
parent: crate_generic
|
||||
components:
|
||||
- type: StorageFill
|
||||
contents:
|
||||
- Medical Scanner
|
||||
- type: StorageFill
|
||||
contents:
|
||||
- medical_scanner
|
||||
|
||||
- type: entity
|
||||
id: crate_glass
|
||||
name: Glass Sheet Crate (x50)
|
||||
parent: crate_generic
|
||||
components:
|
||||
- type: StorageFill
|
||||
contents:
|
||||
- GlassStack
|
||||
- type: StorageFill
|
||||
contents:
|
||||
- GlassStack
|
||||
|
||||
- type: entity
|
||||
id: crate_cable
|
||||
name: Cable Coil Crate (x50)
|
||||
parent: crate_generic
|
||||
components:
|
||||
- type: StorageFill
|
||||
contents:
|
||||
- CableStack
|
||||
- type: StorageFill
|
||||
contents:
|
||||
- CableStack
|
||||
|
||||
@@ -167,32 +167,6 @@
|
||||
- type: Clothing
|
||||
sprite: Clothing/Gloves/ce_rig_sealed.rsi
|
||||
|
||||
- type: entity
|
||||
parent: GlovesBase
|
||||
id: GlovesChalAppara1
|
||||
name: Chal Appara 1 gloves
|
||||
description: ''
|
||||
components:
|
||||
- type: Sprite
|
||||
sprite: Clothing/Gloves/chal_appara_1.rsi
|
||||
- type: Icon
|
||||
sprite: Clothing/Gloves/chal_appara_1.rsi
|
||||
- type: Clothing
|
||||
sprite: Clothing/Gloves/chal_appara_1.rsi
|
||||
|
||||
- type: entity
|
||||
parent: GlovesBase
|
||||
id: GlovesChalAppara12
|
||||
name: Chal Appara 12 gloves
|
||||
description: ''
|
||||
components:
|
||||
- type: Sprite
|
||||
sprite: Clothing/Gloves/chal_appara_12.rsi
|
||||
- type: Icon
|
||||
sprite: Clothing/Gloves/chal_appara_12.rsi
|
||||
- type: Clothing
|
||||
sprite: Clothing/Gloves/chal_appara_12.rsi
|
||||
|
||||
- type: entity
|
||||
parent: GlovesBase
|
||||
id: GlovesEngineeringRig
|
||||
|
||||
24
Resources/Prototypes/Entities/items/skub.yml
Normal file
@@ -0,0 +1,24 @@
|
||||
- type: entity
|
||||
name: Skub
|
||||
parent: BaseItem
|
||||
id: Skub
|
||||
description: Skub is the fifth Chaos God.
|
||||
components:
|
||||
- type: Sprite
|
||||
sprite: Objects/Misc/skub.rsi
|
||||
state: icon
|
||||
|
||||
- type: Icon
|
||||
sprite: Objects/Misc/skub.rsi
|
||||
state: icon
|
||||
|
||||
- type: Item
|
||||
sprite: Objects/Misc/skub.rsi
|
||||
- type: ItemCooldown
|
||||
|
||||
- type: Sound
|
||||
- type: EmitSoundOnUse
|
||||
sound: /Audio/items/skub.ogg
|
||||
|
||||
- type: UseDelay
|
||||
delay: 2.0
|
||||
@@ -1 +1 @@
|
||||
{"version": 1, "size": {"x": 32, "y": 32}, "license": "CC-BY-SA-3.0", "copyright": "Taken from https://github.com/discordia-space/CEV-Eris/blob/c0293684320e7b70cbcac932b8dddeee35f3a51f/icons/obj/structures/windows.dmi", "states": [{"name": "window0", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "window1", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "window2", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "window3", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "window4", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "window5", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "window6", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "window7", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}]}
|
||||
{"version": 1, "size": {"x": 32, "y": 32}, "license": "CC-BY-SA-3.0", "copyright": "Taken from https://github.com/discordia-space/CEV-Eris/blob/c0293684320e7b70cbcac932b8dddeee35f3a51f/icons/obj/structures/windows.dmi", "states": [{"name": "window0", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "window1", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "window2", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "window3", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "window4", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "window5", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "window6", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "window7", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}]}
|
||||
|
||||
|
Before Width: | Height: | Size: 348 B |
|
Before Width: | Height: | Size: 111 B |
|
Before Width: | Height: | Size: 189 B |
|
Before Width: | Height: | Size: 185 B |
@@ -1 +0,0 @@
|
||||
{"version": 1, "size": {"x": 32, "y": 32}, "license": "CC-BY-SA-3.0", "copyright": "https://github.com/discordia-space/CEV-Eris/raw/cb5bda251807e38fe5eae6b1def12f0c243b4d0a/icons/inventory/hands/mob.dmi", "states": [{"name": "equipped-HAND", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "icon", "directions": 1, "delays": [[1.0]]}, {"name": "inhand-left", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "inhand-right", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}]}
|
||||
|
Before Width: | Height: | Size: 172 B |
|
Before Width: | Height: | Size: 111 B |
|
Before Width: | Height: | Size: 146 B |
|
Before Width: | Height: | Size: 143 B |
@@ -1 +0,0 @@
|
||||
{"version": 1, "size": {"x": 32, "y": 32}, "license": "CC-BY-SA-3.0", "copyright": "https://github.com/discordia-space/CEV-Eris/raw/cb5bda251807e38fe5eae6b1def12f0c243b4d0a/icons/inventory/hands/mob.dmi", "states": [{"name": "equipped-HAND", "directions": 1}, {"name": "icon", "directions": 1, "delays": [[1.0]]}, {"name": "inhand-left", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "inhand-right", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}]}
|
||||
BIN
Resources/Textures/Objects/Misc/skub.rsi/icon.png
Normal file
|
After Width: | Height: | Size: 490 B |
BIN
Resources/Textures/Objects/Misc/skub.rsi/inhand-left.png
Normal file
|
After Width: | Height: | Size: 555 B |
BIN
Resources/Textures/Objects/Misc/skub.rsi/inhand-right.png
Normal file
|
After Width: | Height: | Size: 563 B |
1
Resources/Textures/Objects/Misc/skub.rsi/meta.json
Normal file
@@ -0,0 +1 @@
|
||||
{"version": 1, "size": {"x": 32, "y": 32}, "license": "CC-BY-SA-3.0", "copyright": "Taken from https://github.com/tgstation/tgstation", "states": [{"name": "icon", "directions": 1, "delays": [[1.0]]}, {"name": "inhand-left", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "inhand-right", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}]}
|
||||