Blocking and Shields (#8584)
* Blocking * Fixes Bodytype bug * Blocking Damage Modifier * Storing bodytype * Consolidates Stop Blocking code * Consolidates more methods * Some cleanup, hitbox fix * Shield Textures * Passive blocking modifier check * Localization, popups, and more cleanup * Small cleanup * Relay event * Fixes a shutdown bug, adds specific containers and sets * Popups and sounds * Fixes typo * Removes whitespace, adds comment * Some requested changes * Remove Shared * Audio fix * More changes * More requested changes * Properly remove on shutdown * Adds riot shields to seclathes * SecTech Riot shield * Constant variable * Relay transfer to user blocking system * More destruction behavior * Adds a shape field * Riot shield cleanup * More requested changes. * Prevents blocking attempt where a user cannot be anchored * Listen for anchor change * Unused using cleanup * More shields. * Buckler * Construction * Linter fix
194
Content.Shared/Blocking/BlockingSystem.cs
Normal file
@@ -0,0 +1,194 @@
|
|||||||
|
using Content.Shared.Actions;
|
||||||
|
using Content.Shared.Actions.ActionTypes;
|
||||||
|
using Content.Shared.Hands;
|
||||||
|
using Content.Shared.Hands.EntitySystems;
|
||||||
|
using Content.Shared.Physics;
|
||||||
|
using Content.Shared.Popups;
|
||||||
|
using Content.Shared.Toggleable;
|
||||||
|
using Robust.Shared.Physics;
|
||||||
|
using Robust.Shared.Physics.Dynamics;
|
||||||
|
using Robust.Shared.Player;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
|
namespace Content.Shared.Blocking;
|
||||||
|
|
||||||
|
public sealed class BlockingSystem : EntitySystem
|
||||||
|
{
|
||||||
|
[Dependency] private readonly SharedActionsSystem _actionsSystem = default!;
|
||||||
|
[Dependency] private readonly IPrototypeManager _proto = default!;
|
||||||
|
[Dependency] private readonly SharedTransformSystem _transformSystem = default!;
|
||||||
|
[Dependency] private readonly FixtureSystem _fixtureSystem = default!;
|
||||||
|
[Dependency] private readonly SharedHandsSystem _handsSystem = default!;
|
||||||
|
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
|
||||||
|
SubscribeLocalEvent<BlockingComponent, GotEquippedHandEvent>(OnEquip);
|
||||||
|
SubscribeLocalEvent<BlockingComponent, GotUnequippedHandEvent>(OnUnequip);
|
||||||
|
|
||||||
|
SubscribeLocalEvent<BlockingComponent, GetItemActionsEvent>(OnGetActions);
|
||||||
|
SubscribeLocalEvent<BlockingComponent, ToggleActionEvent>(OnToggleAction);
|
||||||
|
|
||||||
|
SubscribeLocalEvent<BlockingComponent, ComponentShutdown>(OnShutdown);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnEquip(EntityUid uid, BlockingComponent component, GotEquippedHandEvent args)
|
||||||
|
{
|
||||||
|
component.User = args.User;
|
||||||
|
|
||||||
|
//To make sure that this bodytype doesn't get set as anything but the original
|
||||||
|
if (TryComp<PhysicsComponent>(args.User, out var physicsComponent) && physicsComponent.BodyType != BodyType.Static
|
||||||
|
&& !TryComp<BlockingUserComponent>(args.User, out var blockingUserComponent))
|
||||||
|
{
|
||||||
|
var userComp = EnsureComp<BlockingUserComponent>(args.User);
|
||||||
|
userComp.BlockingItem = uid;
|
||||||
|
userComp.OriginalBodyType = physicsComponent.BodyType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnUnequip(EntityUid uid, BlockingComponent component, GotUnequippedHandEvent args)
|
||||||
|
{
|
||||||
|
BlockingShutdownHelper(uid, component, args.User);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnGetActions(EntityUid uid, BlockingComponent component, GetItemActionsEvent args)
|
||||||
|
{
|
||||||
|
if (component.BlockingToggleAction == null
|
||||||
|
&& _proto.TryIndex(component.BlockingToggleActionId, out InstantActionPrototype? act))
|
||||||
|
{
|
||||||
|
component.BlockingToggleAction = new(act);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (component.BlockingToggleAction != null)
|
||||||
|
args.Actions.Add(component.BlockingToggleAction);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnToggleAction(EntityUid uid, BlockingComponent component, ToggleActionEvent args)
|
||||||
|
{
|
||||||
|
if(args.Handled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (component.IsBlocking)
|
||||||
|
StopBlocking(uid, component, args.Performer);
|
||||||
|
else
|
||||||
|
StartBlocking(uid, component, args.Performer);
|
||||||
|
|
||||||
|
args.Handled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnShutdown(EntityUid uid, BlockingComponent component, ComponentShutdown args)
|
||||||
|
{
|
||||||
|
//In theory the user should not be null when this fires off
|
||||||
|
if (component.User != null)
|
||||||
|
{
|
||||||
|
_actionsSystem.RemoveProvidedActions(component.User.Value, uid);
|
||||||
|
BlockingShutdownHelper(uid, component, component.User.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called where you want the user to start blocking
|
||||||
|
/// Creates a new hard fixture to bodyblock
|
||||||
|
/// Also makes the user static to prevent prediction issues
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="uid"> The entity with the blocking component</param>
|
||||||
|
/// <param name="component"> The <see cref="BlockingComponent"/></param>
|
||||||
|
/// <param name="user"> The entity who's using the item to block</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public bool StartBlocking(EntityUid item, BlockingComponent component, EntityUid user)
|
||||||
|
{
|
||||||
|
if (component.IsBlocking) return false;
|
||||||
|
|
||||||
|
var xform = Transform(user);
|
||||||
|
|
||||||
|
var shieldName = Name(item);
|
||||||
|
|
||||||
|
var msgUser = Loc.GetString("action-popup-blocking-user", ("shield", shieldName));
|
||||||
|
var msgOther = Loc.GetString("action-popup-blocking-other", ("blockerName", Name(user)), ("shield", shieldName));
|
||||||
|
|
||||||
|
if (component.BlockingToggleAction != null)
|
||||||
|
{
|
||||||
|
_transformSystem.AnchorEntity(xform);
|
||||||
|
if (!xform.Anchored)
|
||||||
|
{
|
||||||
|
var msgError = Loc.GetString("action-popup-blocking-user-cant-block");
|
||||||
|
_popupSystem.PopupEntity(msgError, user, Filter.Entities(user));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
_actionsSystem.SetToggled(component.BlockingToggleAction, true);
|
||||||
|
_popupSystem.PopupEntity(msgUser, user, Filter.Entities(user));
|
||||||
|
_popupSystem.PopupEntity(msgOther, user, Filter.Pvs(user).RemoveWhereAttachedEntity(e => e == user));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TryComp<PhysicsComponent>(user, out var physicsComponent))
|
||||||
|
{
|
||||||
|
var fixture = new Fixture(physicsComponent, component.Shape)
|
||||||
|
{
|
||||||
|
ID = BlockingComponent.BlockFixtureID,
|
||||||
|
Hard = true,
|
||||||
|
CollisionLayer = (int) CollisionGroup.WallLayer
|
||||||
|
};
|
||||||
|
|
||||||
|
_fixtureSystem.TryCreateFixture(physicsComponent, fixture);
|
||||||
|
}
|
||||||
|
|
||||||
|
component.IsBlocking = true;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called where you want the user to stop blocking.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="item"> The entity with the blocking component</param>
|
||||||
|
/// <param name="component"> The <see cref="BlockingComponent"/></param>
|
||||||
|
/// <param name="user"> The entity who's using the item to block</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public bool StopBlocking(EntityUid item, BlockingComponent component, EntityUid user)
|
||||||
|
{
|
||||||
|
if (!component.IsBlocking) return false;
|
||||||
|
|
||||||
|
var xform = Transform(user);
|
||||||
|
|
||||||
|
var shieldName = Name(item);
|
||||||
|
|
||||||
|
var msgUser = Loc.GetString("action-popup-blocking-disabling-user", ("shield", shieldName));
|
||||||
|
var msgOther = Loc.GetString("action-popup-blocking-disabling-other", ("blockerName", Name(user)), ("shield", shieldName));
|
||||||
|
|
||||||
|
//If the component blocking toggle isn't null, grab the users SharedBlockingUserComponent and PhysicsComponent
|
||||||
|
//then toggle the action to false, unanchor the user, remove the hard fixture
|
||||||
|
//and set the users bodytype back to their original type
|
||||||
|
if (component.BlockingToggleAction != null && TryComp<BlockingUserComponent>(user, out var blockingUserComponent)
|
||||||
|
&& TryComp<PhysicsComponent>(user, out var physicsComponent))
|
||||||
|
{
|
||||||
|
_transformSystem.Unanchor(xform);
|
||||||
|
_actionsSystem.SetToggled(component.BlockingToggleAction, false);
|
||||||
|
_fixtureSystem.DestroyFixture(physicsComponent, BlockingComponent.BlockFixtureID);
|
||||||
|
physicsComponent.BodyType = blockingUserComponent.OriginalBodyType;
|
||||||
|
_popupSystem.PopupEntity(msgUser, user, Filter.Entities(user));
|
||||||
|
_popupSystem.PopupEntity(msgOther, user, Filter.Pvs(user).RemoveWhereAttachedEntity(e => e == user));
|
||||||
|
}
|
||||||
|
|
||||||
|
component.IsBlocking = false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called where you want someone to stop blocking and to remove the <see cref="BlockingUserComponent"/> from them
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="uid"> The item the component is attached to</param>
|
||||||
|
/// <param name="component"> The <see cref="BlockingComponent"/> </param>
|
||||||
|
/// <param name="user"> The person holding the blocking item </param>
|
||||||
|
private void BlockingShutdownHelper(EntityUid uid, BlockingComponent component, EntityUid user)
|
||||||
|
{
|
||||||
|
if (component.IsBlocking)
|
||||||
|
StopBlocking(uid, component, user);
|
||||||
|
|
||||||
|
RemComp<BlockingUserComponent>(user);
|
||||||
|
component.User = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
60
Content.Shared/Blocking/BlockingUserSystem.cs
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
using Content.Shared.Audio;
|
||||||
|
using Content.Shared.Damage;
|
||||||
|
using Content.Shared.Damage.Prototypes;
|
||||||
|
using Content.Shared.Hands.EntitySystems;
|
||||||
|
using Robust.Shared.Audio;
|
||||||
|
using Robust.Shared.Player;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
|
namespace Content.Shared.Blocking;
|
||||||
|
|
||||||
|
public sealed class BlockingUserSystem : EntitySystem
|
||||||
|
{
|
||||||
|
[Dependency] private readonly SharedHandsSystem _handsSystem = default!;
|
||||||
|
[Dependency] private readonly IPrototypeManager _proto = default!;
|
||||||
|
[Dependency] private readonly BlockingSystem _blockingSystem = default!;
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
|
||||||
|
SubscribeLocalEvent<BlockingUserComponent, DamageChangedEvent>(OnDamageChanged);
|
||||||
|
SubscribeLocalEvent<BlockingUserComponent, DamageModifyEvent>(OnUserDamageModified);
|
||||||
|
|
||||||
|
SubscribeLocalEvent<BlockingUserComponent, AnchorStateChangedEvent>(OnAnchorChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnAnchorChanged(EntityUid uid, BlockingUserComponent component, ref AnchorStateChangedEvent args)
|
||||||
|
{
|
||||||
|
if (!args.Anchored)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (TryComp<BlockingComponent>(component.BlockingItem, out var blockComp) && blockComp.IsBlocking)
|
||||||
|
{
|
||||||
|
_blockingSystem.StopBlocking(component.BlockingItem.Value, blockComp, uid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnDamageChanged(EntityUid uid, BlockingUserComponent component, DamageChangedEvent args)
|
||||||
|
{
|
||||||
|
if (component.BlockingItem != null)
|
||||||
|
{
|
||||||
|
RaiseLocalEvent(component.BlockingItem.Value, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnUserDamageModified(EntityUid uid, BlockingUserComponent component, DamageModifyEvent args)
|
||||||
|
{
|
||||||
|
if (TryComp<BlockingComponent>(component.BlockingItem, out var blockingComponent))
|
||||||
|
{
|
||||||
|
if (_proto.TryIndex(blockingComponent.PassiveBlockDamageModifer, out DamageModifierSetPrototype? passiveblockModifier) && !blockingComponent.IsBlocking)
|
||||||
|
args.Damage = DamageSpecifier.ApplyModifierSet(args.Damage, passiveblockModifier);
|
||||||
|
|
||||||
|
if (_proto.TryIndex(blockingComponent.ActiveBlockDamageModifier, out DamageModifierSetPrototype? activeBlockModifier) && blockingComponent.IsBlocking)
|
||||||
|
{
|
||||||
|
args.Damage = DamageSpecifier.ApplyModifierSet(args.Damage, activeBlockModifier);
|
||||||
|
SoundSystem.Play(blockingComponent.BlockSound.GetSound(), Filter.Pvs(component.Owner, entityManager: EntityManager), component.Owner, AudioHelpers.WithVariation(0.2f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
64
Content.Shared/Blocking/Components/BlockingComponent.cs
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
using Content.Shared.Actions.ActionTypes;
|
||||||
|
using Content.Shared.Sound;
|
||||||
|
using Robust.Shared.Physics.Collision.Shapes;
|
||||||
|
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||||
|
|
||||||
|
namespace Content.Shared.Blocking;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This component goes on an item that you want to use to block
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent]
|
||||||
|
public sealed class BlockingComponent : Component
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The entity that's blocking
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables]
|
||||||
|
public EntityUid? User;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Is it currently blocking?
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables]
|
||||||
|
public bool IsBlocking;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The ID for the fixture that's dynamically created when blocking
|
||||||
|
/// </summary>
|
||||||
|
public const string BlockFixtureID = "blocking-active";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The shape of the blocking fixture that will be dynamically spawned
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
[DataField("shape")]
|
||||||
|
public IPhysShape Shape = new PhysShapeCircle {Radius = 0.5F};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The damage modifer to use while passively blocking
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
[DataField("passiveBlockModifier")]
|
||||||
|
public string PassiveBlockDamageModifer = "Metallic";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The damage modifier to use while actively blocking.
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
[DataField("activeBlockModifier")]
|
||||||
|
public string ActiveBlockDamageModifier = "Metallic";
|
||||||
|
|
||||||
|
[DataField("blockingToggleActionId", customTypeSerializer:typeof(PrototypeIdSerializer<InstantActionPrototype>))]
|
||||||
|
public string BlockingToggleActionId = "ToggleBlock";
|
||||||
|
|
||||||
|
[DataField("blockingToggleAction")]
|
||||||
|
public InstantAction? BlockingToggleAction;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The sound to be played when you get hit while actively blocking
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables]
|
||||||
|
[DataField("blockSound")]
|
||||||
|
public SoundSpecifier BlockSound = new SoundPathSpecifier("/Audio/Weapons/block_metal1.ogg");
|
||||||
|
}
|
||||||
31
Content.Shared/Blocking/Components/BlockingUserComponent.cs
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
using Content.Shared.Damage;
|
||||||
|
using Robust.Shared.Physics;
|
||||||
|
|
||||||
|
namespace Content.Shared.Blocking;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This component gets dynamically added to an Entity via the <see cref="BlockingSystem"/>
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent]
|
||||||
|
public sealed class BlockingUserComponent : Component
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The entity that's being used to block
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables]
|
||||||
|
[DataField("blockingItem")]
|
||||||
|
public EntityUid? BlockingItem;
|
||||||
|
|
||||||
|
[ViewVariables]
|
||||||
|
[DataField("modifiers")]
|
||||||
|
public DamageModifierSet Modifiers = default!;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Stores the entities original bodytype
|
||||||
|
/// Used so that it can be put back to what it was after anchoring
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables]
|
||||||
|
[DataField("originalBodyType")]
|
||||||
|
public BodyType OriginalBodyType;
|
||||||
|
|
||||||
|
}
|
||||||
BIN
Resources/Audio/Weapons/block_metal1.ogg
Normal file
@@ -5,3 +5,5 @@ grille_hit.ogg taken from https://github.com/tgstation/tgstation/blob/803ca4537d
|
|||||||
slash.ogg taken from https://github.com/tgstation/tgstation/blob/5d264fbea0124e5af511af3fed24203e196d108b/sound/weapons/slash.ogg under CC BY-SA 3.0
|
slash.ogg taken from https://github.com/tgstation/tgstation/blob/5d264fbea0124e5af511af3fed24203e196d108b/sound/weapons/slash.ogg under CC BY-SA 3.0
|
||||||
|
|
||||||
tap.ogg taken from https://github.com/tgstation/tgstation/blob/803ca4537df35cf252b056d8460d510be8a4f353/sound/weapons/tap.ogg under CC BY-SA 3.0
|
tap.ogg taken from https://github.com/tgstation/tgstation/blob/803ca4537df35cf252b056d8460d510be8a4f353/sound/weapons/tap.ogg under CC BY-SA 3.0
|
||||||
|
|
||||||
|
block_metal1.ogg taken from https://github.com/Citadel-Station-13/Citadel-Station-13/commit/31c5996a5db8cce0cb431cb1dc20d99cac83f268 under CC BY-SA 3.0
|
||||||
10
Resources/Locale/en-US/actions/actions/blocking.ftl
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
action-name-blocking = Block
|
||||||
|
action-description-blocking = Raise or lower your shield.
|
||||||
|
|
||||||
|
action-popup-blocking-user = You raise your {$shield}!
|
||||||
|
action-popup-blocking-disabling-user = You lower your {$shield}!
|
||||||
|
|
||||||
|
action-popup-blocking-other = {$blockerName} raises their {$shield}!
|
||||||
|
action-popup-blocking-disabling-other = {$blockerName} lowers their {$shield}!
|
||||||
|
|
||||||
|
action-popup-blocking-user-cant-block = The gravity here prevents you from blocking.
|
||||||
@@ -54,3 +54,11 @@
|
|||||||
description: vending-machine-action-description
|
description: vending-machine-action-description
|
||||||
useDelay: 30
|
useDelay: 30
|
||||||
event: !type:VendingMachineSelfDispenseEvent
|
event: !type:VendingMachineSelfDispenseEvent
|
||||||
|
|
||||||
|
- type: instantAction
|
||||||
|
id: ToggleBlock
|
||||||
|
name: action-name-blocking
|
||||||
|
description: action-description-blocking
|
||||||
|
icon: Objects/Weapons/Melee/shields.rsi/teleriot-icon.png
|
||||||
|
iconOn: Objects/Weapons/Melee/shields.rsi/teleriot-on.png
|
||||||
|
event: !type:ToggleActionEvent
|
||||||
|
|||||||
@@ -158,6 +158,7 @@
|
|||||||
- Flash
|
- Flash
|
||||||
- Handcuffs
|
- Handcuffs
|
||||||
- Stunbaton
|
- Stunbaton
|
||||||
|
- RiotShield
|
||||||
- FlashPayload
|
- FlashPayload
|
||||||
|
|
||||||
- type: technology
|
- type: technology
|
||||||
|
|||||||
@@ -11,6 +11,9 @@
|
|||||||
ClothingEyesGlassesSunglasses: 2
|
ClothingEyesGlassesSunglasses: 2
|
||||||
ClothingBeltSecurityWebbing: 5
|
ClothingBeltSecurityWebbing: 5
|
||||||
Zipties: 12
|
Zipties: 12
|
||||||
|
RiotShield: 2
|
||||||
|
RiotLaserShield: 2
|
||||||
|
RiotBulletShield: 2
|
||||||
# security officers need to follow a diet regimen!
|
# security officers need to follow a diet regimen!
|
||||||
contrabandInventory:
|
contrabandInventory:
|
||||||
FoodDonutHomer: 12
|
FoodDonutHomer: 12
|
||||||
|
|||||||
@@ -15,3 +15,12 @@
|
|||||||
- Heat
|
- Heat
|
||||||
- Shock
|
- Shock
|
||||||
- Structural # this probably should be in separate container
|
- Structural # this probably should be in separate container
|
||||||
|
|
||||||
|
- type: damageContainer
|
||||||
|
id: Shield
|
||||||
|
supportedGroups:
|
||||||
|
- Brute
|
||||||
|
supportedTypes:
|
||||||
|
- Heat
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -151,3 +151,138 @@
|
|||||||
Bloodloss: 0.0 # no double dipping
|
Bloodloss: 0.0 # no double dipping
|
||||||
Cellular: 0.0
|
Cellular: 0.0
|
||||||
|
|
||||||
|
# Represents what a riot shield should block passively
|
||||||
|
# Each shield will probably have their own passive and active modifier sets
|
||||||
|
# Honestly it should not be too high
|
||||||
|
- type: damageModifierSet
|
||||||
|
id: PassiveRiotShieldBlock
|
||||||
|
coefficients:
|
||||||
|
Blunt: 0.9
|
||||||
|
Slash: 0.9
|
||||||
|
Piercing: 0.9
|
||||||
|
Heat: 0.9
|
||||||
|
|
||||||
|
# Represents what a riot shield should block while active
|
||||||
|
# Should be a higher reduction because you're anchored
|
||||||
|
- type: damageModifierSet
|
||||||
|
id: ActiveRiotShieldBlock
|
||||||
|
coefficients:
|
||||||
|
Blunt: 0.8
|
||||||
|
Slash: 0.8
|
||||||
|
Piercing: 0.8
|
||||||
|
Heat: 0.8
|
||||||
|
flatReductions:
|
||||||
|
Blunt: 1
|
||||||
|
Slash: 1
|
||||||
|
Piercing: 1
|
||||||
|
Heat: 1
|
||||||
|
|
||||||
|
- type: damageModifierSet
|
||||||
|
id: PassiveRiotLaserShieldBlock
|
||||||
|
coefficients:
|
||||||
|
Heat: 0.8
|
||||||
|
|
||||||
|
- type: damageModifierSet
|
||||||
|
id: ActiveRiotLaserShieldBlock
|
||||||
|
coefficients:
|
||||||
|
Heat: 0.7
|
||||||
|
flatReductions:
|
||||||
|
Heat: 2
|
||||||
|
|
||||||
|
- type: damageModifierSet
|
||||||
|
id: PassiveRiotBulletShieldBlock
|
||||||
|
coefficients:
|
||||||
|
Blunt: 0.8
|
||||||
|
Piercing: 0.8
|
||||||
|
|
||||||
|
- type: damageModifierSet
|
||||||
|
id: ActiveRiotBulletShieldBlock
|
||||||
|
coefficients:
|
||||||
|
Blunt: 0.7
|
||||||
|
Piercing: 0.7
|
||||||
|
flatReductions:
|
||||||
|
Blunt: 1.5
|
||||||
|
Piercing: 1.5
|
||||||
|
|
||||||
|
#It's made from wood, so it should probably take more heat/laser damage
|
||||||
|
- type: damageModifierSet
|
||||||
|
id: PassiveBucklerBlock
|
||||||
|
coefficients:
|
||||||
|
Blunt: 0.95
|
||||||
|
Slash: 0.95
|
||||||
|
Piercing: 0.95
|
||||||
|
Heat: 2
|
||||||
|
|
||||||
|
- type: damageModifierSet
|
||||||
|
id: ActiveBucklerBlock
|
||||||
|
coefficients:
|
||||||
|
Blunt: 0.85
|
||||||
|
Slash: 0.85
|
||||||
|
Piercing: 0.85
|
||||||
|
Heat: 2
|
||||||
|
flatReductions:
|
||||||
|
Blunt: 1
|
||||||
|
Slash: 1
|
||||||
|
Piercing: 1
|
||||||
|
|
||||||
|
#It's a really crummy shield
|
||||||
|
- type: damageModifierSet
|
||||||
|
id: PassiveMakeshiftBlock
|
||||||
|
coefficients:
|
||||||
|
Blunt: 0.95
|
||||||
|
Slash: 0.95
|
||||||
|
Piercing: 0.95
|
||||||
|
Heat: 0.9
|
||||||
|
|
||||||
|
- type: damageModifierSet
|
||||||
|
id: ActiveMakeshiftBlock
|
||||||
|
coefficients:
|
||||||
|
Blunt: 0.85
|
||||||
|
Slash: 0.85
|
||||||
|
Piercing: 0.85
|
||||||
|
Heat: 0.8
|
||||||
|
flatReductions:
|
||||||
|
Blunt: 0.5
|
||||||
|
Slash: 0.5
|
||||||
|
Piercing: 0.5
|
||||||
|
Heat: 1
|
||||||
|
|
||||||
|
#Clockwork generally takes more laser/heat damage
|
||||||
|
- type: damageModifierSet
|
||||||
|
id: PassiveClockworkShieldBlock
|
||||||
|
coefficients:
|
||||||
|
Blunt: 0.8
|
||||||
|
Slash: 0.8
|
||||||
|
Piercing: 0.8
|
||||||
|
Heat: 1.5
|
||||||
|
|
||||||
|
- type: damageModifierSet
|
||||||
|
id: ActiveClockworkShieldBlock
|
||||||
|
coefficients:
|
||||||
|
Blunt: 0.7
|
||||||
|
Slash: 0.7
|
||||||
|
Piercing: 0.7
|
||||||
|
Heat: 1.5
|
||||||
|
flatReductions:
|
||||||
|
Blunt: 1
|
||||||
|
Slash: 1
|
||||||
|
Piercing: 1
|
||||||
|
|
||||||
|
#Mirror shield should reflect heat/laser eventually, but be relatively weak to everything else.
|
||||||
|
- type: damageModifierSet
|
||||||
|
id: PassiveMirrorShieldBlock
|
||||||
|
coefficients:
|
||||||
|
Blunt: 1.2
|
||||||
|
Slash: 1.2
|
||||||
|
Piercing: 1.2
|
||||||
|
Heat: .7
|
||||||
|
|
||||||
|
- type: damageModifierSet
|
||||||
|
id: ActiveMirrorShieldBlock
|
||||||
|
coefficients:
|
||||||
|
Blunt: 1.2
|
||||||
|
Slash: 1.2
|
||||||
|
Piercing: 1.2
|
||||||
|
Heat: .6
|
||||||
|
flatReductions:
|
||||||
|
Heat: 1
|
||||||
|
|||||||
194
Resources/Prototypes/Entities/Objects/Shields/shields.yml
Normal file
@@ -0,0 +1,194 @@
|
|||||||
|
- type: entity
|
||||||
|
name: base shield
|
||||||
|
parent: BaseItem
|
||||||
|
id: BaseShield
|
||||||
|
description: A shield!
|
||||||
|
abstract: true
|
||||||
|
components:
|
||||||
|
- type: Sprite
|
||||||
|
sprite: Objects/Weapons/Melee/shields.rsi
|
||||||
|
state: riot-icon
|
||||||
|
netsync: false
|
||||||
|
- type: Item
|
||||||
|
sprite: Objects/Weapons/Melee/shields.rsi
|
||||||
|
size: 100
|
||||||
|
HeldPrefix: riot
|
||||||
|
- type: Blocking
|
||||||
|
passiveBlockModifier: PassiveRiotShieldBlock
|
||||||
|
activeBlockModifier: ActiveRiotShieldBlock
|
||||||
|
blockingToggleAction:
|
||||||
|
name: action-name-blocking
|
||||||
|
description: action-description-blocking
|
||||||
|
icon: Objects/Weapons/Melee/shields.rsi/teleriot-icon.png
|
||||||
|
iconOn: Objects/Weapons/Melee/shields.rsi/teleriot-on.png
|
||||||
|
event: !type:ToggleActionEvent
|
||||||
|
- type: Damageable
|
||||||
|
damageContainer: Shield
|
||||||
|
- type: Destructible
|
||||||
|
thresholds:
|
||||||
|
- trigger:
|
||||||
|
!type:DamageTrigger
|
||||||
|
damage: 40 #This is probably enough damage before it breaks
|
||||||
|
behaviors:
|
||||||
|
- !type:DoActsBehavior
|
||||||
|
acts: [ "Destruction" ]
|
||||||
|
- !type:PlaySoundBehavior
|
||||||
|
sound: /Audio/Effects/metalbreak.ogg
|
||||||
|
- !type:SpawnEntitiesBehavior
|
||||||
|
spawn:
|
||||||
|
SheetSteel:
|
||||||
|
min: 5
|
||||||
|
max: 5
|
||||||
|
SheetGlass:
|
||||||
|
min: 5
|
||||||
|
max: 5
|
||||||
|
|
||||||
|
#Security Shields
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
name: riot shield
|
||||||
|
parent: BaseShield
|
||||||
|
id: RiotShield
|
||||||
|
description: A large tower shield. Good for controlling crowds.
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
name: riot laser shield
|
||||||
|
parent: BaseShield
|
||||||
|
id: RiotLaserShield
|
||||||
|
description: A riot shield built for withstanding lasers, but not much else.
|
||||||
|
components:
|
||||||
|
- type: Sprite
|
||||||
|
state: riot_laser-icon
|
||||||
|
- type: Item
|
||||||
|
HeldPrefix: riot_laser
|
||||||
|
- type: Blocking
|
||||||
|
passiveBlockModifier: PassiveRiotLaserShieldBlock
|
||||||
|
activeBlockModifier: ActiveRiotLaserShieldBlock
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
name: riot bullet shield
|
||||||
|
parent: BaseShield
|
||||||
|
id: RiotBulletShield
|
||||||
|
description: A ballistic riot shield built for withstanding bullets, but not much else.
|
||||||
|
components:
|
||||||
|
- type: Sprite
|
||||||
|
state: riot_bullet-icon
|
||||||
|
- type: Item
|
||||||
|
HeldPrefix: riot_bullet
|
||||||
|
- type: Blocking
|
||||||
|
passiveBlockModifier: PassiveRiotBulletShieldBlock
|
||||||
|
activeBlockModifier: ActiveRiotBulletShieldBlock
|
||||||
|
|
||||||
|
#Craftable shields
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
name: wooden buckler
|
||||||
|
parent: BaseShield
|
||||||
|
id: WoodenBuckler
|
||||||
|
description: A small round wooden makeshift shield.
|
||||||
|
components:
|
||||||
|
- type: Sprite
|
||||||
|
state: buckler-icon
|
||||||
|
- type: Item
|
||||||
|
HeldPrefix: buckler
|
||||||
|
- type: Blocking
|
||||||
|
passiveBlockModifier: PassiveBucklerBlock
|
||||||
|
activeBlockModifier: ActiveBucklerBlock
|
||||||
|
- type: Construction
|
||||||
|
graph: WoodenBuckler
|
||||||
|
node: woodenBuckler
|
||||||
|
- type: Destructible
|
||||||
|
thresholds:
|
||||||
|
- trigger:
|
||||||
|
!type:DamageTrigger
|
||||||
|
damage: 30 #Weaker shield
|
||||||
|
behaviors:
|
||||||
|
- !type:DoActsBehavior
|
||||||
|
acts: [ "Destruction" ]
|
||||||
|
- !type:PlaySoundBehavior
|
||||||
|
sound: /Audio/Effects/metalbreak.ogg
|
||||||
|
- !type:SpawnEntitiesBehavior
|
||||||
|
spawn:
|
||||||
|
MaterialWoodPlank:
|
||||||
|
min: 5
|
||||||
|
max: 5
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
name: makeshift shield
|
||||||
|
parent: BaseShield
|
||||||
|
id: MakeshiftShield
|
||||||
|
description: A rundown looking shield, not good for much.
|
||||||
|
components:
|
||||||
|
- type: Sprite
|
||||||
|
state: makeshift-icon
|
||||||
|
- type: Item
|
||||||
|
HeldPrefix: metal
|
||||||
|
- type: Blocking
|
||||||
|
passiveBlockModifier: PassiveMakeshiftBlock
|
||||||
|
activeBlockModifier: ActiveMakeshiftBlock
|
||||||
|
- type: Construction
|
||||||
|
graph: MakeshiftShield
|
||||||
|
node: makeshiftShield
|
||||||
|
- type: Destructible
|
||||||
|
thresholds:
|
||||||
|
- trigger:
|
||||||
|
!type:DamageTrigger
|
||||||
|
damage: 20 #Very weak shield
|
||||||
|
behaviors:
|
||||||
|
- !type:DoActsBehavior
|
||||||
|
acts: [ "Destruction" ]
|
||||||
|
- !type:PlaySoundBehavior
|
||||||
|
sound: /Audio/Effects/metalbreak.ogg
|
||||||
|
- !type:SpawnEntitiesBehavior
|
||||||
|
spawn:
|
||||||
|
SheetSteel:
|
||||||
|
min: 1
|
||||||
|
max: 2
|
||||||
|
|
||||||
|
#Magic/Cult Shields (give these to wizard for now)
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
name: Clockwork Shield
|
||||||
|
parent: BaseShield
|
||||||
|
id: ClockworkShield
|
||||||
|
description: Ratvar oyrffrf lbh jvgu uvf cebgrpgvba.
|
||||||
|
components:
|
||||||
|
- type: Sprite
|
||||||
|
state: ratvarian-icon
|
||||||
|
- type: Item
|
||||||
|
HeldPrefix: ratvarian
|
||||||
|
- type: Blocking
|
||||||
|
passiveBlockModifier: PassiveClockworkShieldBlock
|
||||||
|
activeBlockModifier: ActiveClockworkShieldBlock
|
||||||
|
#Have it break into brass when clock cult is in
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
name: Mirror Shield
|
||||||
|
parent: BaseShield
|
||||||
|
id: MirrorShield
|
||||||
|
description: Eerily glows red... you hear the geometer whispering
|
||||||
|
components:
|
||||||
|
- type: Sprite
|
||||||
|
state: mirror-icon
|
||||||
|
- type: Item
|
||||||
|
HeldPrefix: mirror
|
||||||
|
- type: Blocking
|
||||||
|
passiveBlockModifier: PassiveMirrorShieldBlock
|
||||||
|
activeBlockModifier: ActiveMirrorShieldBlock
|
||||||
|
blockSound: !type:SoundPathSpecifier
|
||||||
|
path: /Audio/Effects/glass_step.ogg
|
||||||
|
- type: Destructible
|
||||||
|
thresholds:
|
||||||
|
- trigger:
|
||||||
|
!type:DamageTrigger
|
||||||
|
damage: 40
|
||||||
|
behaviors:
|
||||||
|
- !type:DoActsBehavior
|
||||||
|
acts: [ "Destruction" ]
|
||||||
|
- !type:PlaySoundBehavior
|
||||||
|
sound: /Audio/Effects/glass_break1.ogg
|
||||||
|
- !type:SpawnEntitiesBehavior
|
||||||
|
spawn:
|
||||||
|
SheetGlass:
|
||||||
|
min: 5
|
||||||
|
max: 5
|
||||||
@@ -305,6 +305,7 @@
|
|||||||
- Flash
|
- Flash
|
||||||
- Handcuffs
|
- Handcuffs
|
||||||
- Stunbaton
|
- Stunbaton
|
||||||
|
- RiotShield
|
||||||
- CartridgePistol
|
- CartridgePistol
|
||||||
- ShellShotgun
|
- ShellShotgun
|
||||||
- CartridgeLightRifle
|
- CartridgeLightRifle
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
- type: constructionGraph
|
||||||
|
id: MakeshiftShield
|
||||||
|
start: start
|
||||||
|
graph:
|
||||||
|
- node: start
|
||||||
|
edges:
|
||||||
|
- to: makeshiftShield
|
||||||
|
steps:
|
||||||
|
- material: Cable
|
||||||
|
amount: 15
|
||||||
|
doAfter: 2
|
||||||
|
- material: Steel
|
||||||
|
amount: 30
|
||||||
|
doAfter: 2
|
||||||
|
|
||||||
|
- node: makeshiftShield
|
||||||
|
entity: MakeshiftShield
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
- type: constructionGraph
|
||||||
|
id: WoodenBuckler
|
||||||
|
start: start
|
||||||
|
graph:
|
||||||
|
- node: start
|
||||||
|
edges:
|
||||||
|
- to: woodenBuckler
|
||||||
|
steps:
|
||||||
|
- tag: Handcuffs
|
||||||
|
icon:
|
||||||
|
sprite: Objects/Misc/cablecuffs.rsi
|
||||||
|
state: cuff
|
||||||
|
color: red
|
||||||
|
name: cuffs
|
||||||
|
doAfter: 2
|
||||||
|
- material: WoodPlank
|
||||||
|
amount: 20
|
||||||
|
doAfter: 2
|
||||||
|
- material: Steel
|
||||||
|
amount: 10
|
||||||
|
doAfter: 2
|
||||||
|
|
||||||
|
- node: woodenBuckler
|
||||||
|
entity: WoodenBuckler
|
||||||
@@ -31,3 +31,24 @@
|
|||||||
icon: Objects/Weapons/Guns/Battery/makeshift.rsi/icon.png
|
icon: Objects/Weapons/Guns/Battery/makeshift.rsi/icon.png
|
||||||
objectType: Item
|
objectType: Item
|
||||||
|
|
||||||
|
- type: construction
|
||||||
|
name: wooden buckler
|
||||||
|
id: WoodenBuckler
|
||||||
|
graph: WoodenBuckler
|
||||||
|
startNode: start
|
||||||
|
targetNode: woodenBuckler
|
||||||
|
category: Weapons
|
||||||
|
description: A nicely carved wooden shield!
|
||||||
|
icon: Objects/Weapons/Melee/shields.rsi/buckler-icon.png
|
||||||
|
objectType: Item
|
||||||
|
|
||||||
|
- type: construction
|
||||||
|
name: makeshift shield
|
||||||
|
id: MakeshiftShield
|
||||||
|
graph: MakeshiftShield
|
||||||
|
startNode: start
|
||||||
|
targetNode: makeshiftShield
|
||||||
|
category: Weapons
|
||||||
|
description: Crude and falling apart. Why would you make this?
|
||||||
|
icon: Objects/Weapons/Melee/shields.rsi/makeshift-icon.png
|
||||||
|
objectType: Item
|
||||||
|
|||||||
@@ -19,6 +19,17 @@
|
|||||||
Steel: 300
|
Steel: 300
|
||||||
Plastic: 300
|
Plastic: 300
|
||||||
|
|
||||||
|
- type: latheRecipe
|
||||||
|
id: RiotShield
|
||||||
|
icon:
|
||||||
|
sprite: Objects/Weapons/Melee/shields.rsi
|
||||||
|
state: riot-icon
|
||||||
|
result: RiotShield
|
||||||
|
completetime: 4
|
||||||
|
materials:
|
||||||
|
Steel: 400
|
||||||
|
Glass: 400
|
||||||
|
|
||||||
- type: latheRecipe
|
- type: latheRecipe
|
||||||
id: Flash
|
id: Flash
|
||||||
icon:
|
icon:
|
||||||
|
|||||||
|
After Width: | Height: | Size: 786 B |
|
After Width: | Height: | Size: 844 B |
|
After Width: | Height: | Size: 890 B |
|
After Width: | Height: | Size: 171 B |
|
After Width: | Height: | Size: 339 B |
|
After Width: | Height: | Size: 834 B |
|
After Width: | Height: | Size: 351 B |
|
After Width: | Height: | Size: 462 B |
|
After Width: | Height: | Size: 833 B |
|
After Width: | Height: | Size: 488 B |
195
Resources/Textures/Objects/Weapons/Melee/shields.rsi/meta.json
Normal file
@@ -0,0 +1,195 @@
|
|||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"license": "CC-BY-SA-3.0",
|
||||||
|
"copyright": "Taken from https://github.com/Citadel-Station-13/Citadel-Station-13/commit/84223c65f5caf667a84f3c0f49bc2a41cdc6c4e3",
|
||||||
|
"size": {
|
||||||
|
"x": 32,
|
||||||
|
"y": 32
|
||||||
|
},
|
||||||
|
"states": [
|
||||||
|
{
|
||||||
|
"name": "riot-icon"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "riot-inhand-right",
|
||||||
|
"directions": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "riot-inhand-left",
|
||||||
|
"directions": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "riot_laser-icon"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "riot_laser-inhand-right",
|
||||||
|
"directions": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "riot_laser-inhand-left",
|
||||||
|
"directions": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "riot_bullet-icon"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "riot_bullet-inhand-right",
|
||||||
|
"directions": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "riot_bullet-inhand-left",
|
||||||
|
"directions": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ratvarian-icon"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ratvarian-inhand-right",
|
||||||
|
"directions": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ratvarian-inhand-left",
|
||||||
|
"directions": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mirror-icon",
|
||||||
|
"delays": [
|
||||||
|
[
|
||||||
|
0.5,
|
||||||
|
0.05,
|
||||||
|
0.1,
|
||||||
|
0.1
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mirror-inhand-right",
|
||||||
|
"directions": 4,
|
||||||
|
"delays": [
|
||||||
|
[
|
||||||
|
0.5,
|
||||||
|
0.05,
|
||||||
|
0.1,
|
||||||
|
0.1
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0.5,
|
||||||
|
0.05,
|
||||||
|
0.1,
|
||||||
|
0.1
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0.5,
|
||||||
|
0.05,
|
||||||
|
0.1,
|
||||||
|
0.1
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0.5,
|
||||||
|
0.05,
|
||||||
|
0.1,
|
||||||
|
0.1
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mirror-inhand-left",
|
||||||
|
"directions": 4,
|
||||||
|
"delays": [
|
||||||
|
[
|
||||||
|
0.5,
|
||||||
|
0.05,
|
||||||
|
0.1,
|
||||||
|
0.1
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0.5,
|
||||||
|
0.05,
|
||||||
|
0.1,
|
||||||
|
0.1
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0.5,
|
||||||
|
0.05,
|
||||||
|
0.1,
|
||||||
|
0.1
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0.5,
|
||||||
|
0.05,
|
||||||
|
0.1,
|
||||||
|
0.1
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "buckler-icon"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "buckler-inhand-right",
|
||||||
|
"directions": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "buckler-inhand-left",
|
||||||
|
"directions": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "metal-icon"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "metal-inhand-right",
|
||||||
|
"directions": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "metal-inhand-left",
|
||||||
|
"directions": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "makeshift-icon"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "teleriot-icon"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "teleriot-inhand-right",
|
||||||
|
"directions": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "teleriot-inhand-left",
|
||||||
|
"directions": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "teleriot-on"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "teleriot-inhand-right-on",
|
||||||
|
"directions": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "teleriot-inhand-left-on",
|
||||||
|
"directions": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "eshield-icon"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "eshield-inhand-right",
|
||||||
|
"directions": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "eshield-inhand-left",
|
||||||
|
"directions": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "eshield-on"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "eshield-inhand-right-on",
|
||||||
|
"directions": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "eshield1-inhand-left-on",
|
||||||
|
"directions": 4
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 205 B |
|
After Width: | Height: | Size: 606 B |
|
After Width: | Height: | Size: 628 B |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 502 B |
|
After Width: | Height: | Size: 914 B |
|
After Width: | Height: | Size: 885 B |
|
After Width: | Height: | Size: 383 B |
|
After Width: | Height: | Size: 847 B |
|
After Width: | Height: | Size: 863 B |
|
After Width: | Height: | Size: 496 B |
|
After Width: | Height: | Size: 1003 B |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 540 B |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 352 B |
|
After Width: | Height: | Size: 751 B |
|
After Width: | Height: | Size: 658 B |
|
After Width: | Height: | Size: 784 B |
|
After Width: | Height: | Size: 667 B |
|
After Width: | Height: | Size: 396 B |