Mag gloves (#147)

* created yml

* +mechanics

* textures

* full implementation of magnetic gloves without lathe crafts and researches

* finale

* meeerge

* Fixed
This commit is contained in:
Viktor
2024-03-21 02:08:17 +02:00
committed by GitHub
parent 4199fb2669
commit 1b2b313804
36 changed files with 556 additions and 5 deletions

View File

@@ -4,6 +4,7 @@ using Content.Server.Inventory;
using Content.Server.Pulling;
using Content.Server.Stack;
using Content.Server.Stunnable;
using Content.Shared._White.MagGloves;
using Content.Shared.ActionBlocker;
using Content.Shared.Body.Part;
using Content.Shared.CombatMode;
@@ -93,6 +94,9 @@ namespace Content.Server.Hands.Systems
if (args.Handled)
return;
if (HasComp<PreventDisarmComponent>(uid))
return;
// Break any pulls
if (TryComp(uid, out SharedPullerComponent? puller) && puller.Pulling is EntityUid pulled &&
TryComp(pulled, out SharedPullableComponent? pullable))

View File

@@ -3,6 +3,7 @@ using Content.Shared.Hands.Components;
using Content.Shared.Hands.EntitySystems;
using Content.Shared.Standing;
using Content.Shared.Throwing;
using Content.Shared._White.MagGloves;
using Robust.Shared.Physics.Components;
using Robust.Shared.Random;
@@ -31,8 +32,11 @@ public sealed class StandingStateSystem : EntitySystem
if (hand.HeldEntity is not EntityUid held)
continue;
if (!_handsSystem.TryDrop(uid, hand, null, checkActionBlocker: false, handsComp: handsComp))
continue;
if (!HasComp<KeepItemsOnFallComponent>(uid))
{
if (!_handsSystem.TryDrop(uid, hand, null, checkActionBlocker: false, handsComp: handsComp))
continue;
}
_throwingSystem.TryThrow(held,
_random.NextAngle().RotateVec(direction / dropAngle + worldRotation / 50),

View File

@@ -18,6 +18,7 @@ using Content.Shared.Popups;
using Content.Shared.Strip;
using Content.Shared.Strip.Components;
using Content.Shared.Verbs;
using Content.Shared._White.MagGloves;
using Robust.Server.GameObjects;
using Robust.Shared.Player;
using Robust.Shared.Utility;
@@ -71,6 +72,13 @@ namespace Content.Server.Strip
!TryComp<HandsComponent>(user, out var userHands))
return;
if ((args.Slot == "gloves" || args.IsHand) && TryComp(strippable, out PreventStrippingFromHandsAndGlovesComponent? mag))
{
var message = Loc.GetString("maggloves-cant-strip");
_popup.PopupEntity(message, user, user);
return;
}
if (args.IsHand)
{
StripHand(user, args.Slot, strippable, userHands);

View File

@@ -0,0 +1,116 @@
using Content.Server.Emp;
using Content.Server.Power.Components;
using Content.Shared.Examine;
using Content.Shared.Inventory.Events;
using Content.Shared._White.MagGloves;
using Content.Shared.Popups;
using Robust.Shared.Containers;
using Robust.Shared.Timing;
namespace Content.Server._White.MagGloves;
/// <summary>
/// This handles...
/// </summary>
public sealed class MagneticGlovesSystem : EntitySystem
{
[Dependency] private readonly SharedContainerSystem _sharedContainer = default!;
[Dependency] private readonly IGameTiming _gameTiming = default!;
[Dependency] private readonly SharedPopupSystem _popup = default!;
/// <inheritdoc/>
public override void Initialize()
{
SubscribeLocalEvent<MagneticGlovesComponent, GotEquippedEvent>(OnGotEquipped);
SubscribeLocalEvent<MagneticGlovesComponent, GotUnequippedEvent>(OnGotUnequipped);
SubscribeLocalEvent<MagneticGlovesComponent, ExaminedEvent>(OnExamined);
SubscribeLocalEvent<MagneticGlovesComponent, EmpPulseEvent>(OnEmp);
}
public override void Update(float frameTime)
{
var query = EntityQueryEnumerator<MagneticGlovesComponent>();
while (query.MoveNext(out var uid, out var gloves))
{
if (_gameTiming.CurTime > gloves.GlovesLastActivation + gloves.GlovesActiveTime && gloves.Enabled)
{
RaiseLocalEvent(uid, new ToggleMagneticGlovesEvent());
}
}
}
public void OnEmp(EntityUid uid, MagneticGlovesComponent component, EmpPulseEvent args)
{
if (component.Enabled)
{
RaiseLocalEvent(uid, new ToggleMagneticGlovesEvent());
}
}
public void OnGotUnequipped(EntityUid uid, MagneticGlovesComponent component, GotUnequippedEvent args)
{
if (args.Slot == "gloves")
{
ToggleGloves(args.Equipee, component, false, uid);
}
if (component.Enabled)
{
_popup.PopupEntity(Loc.GetString("maggloves-deactivated"), uid, args.Equipee);
RaiseLocalEvent(uid, new ToggleMagneticGlovesEvent());
}
}
public void OnGotEquipped(EntityUid uid, MagneticGlovesComponent component, GotEquippedEvent args)
{
if (args.Slot == "gloves")
{
ToggleGloves(args.Equipee, component, true, uid);
}
}
public void ToggleGloves(EntityUid owner, MagneticGlovesComponent component, bool active, EntityUid uid)
{
if (!active)
{
RemComp<KeepItemsOnFallComponent>(owner);
if (TryComp<MagneticGlovesAdvancedComponent>(uid, out var adv))
{
RemComp<PreventDisarmComponent>(owner);
RemComp<PreventStrippingFromHandsAndGlovesComponent>(owner);
}
}
else if (component.Enabled)
{
EnsureComp<KeepItemsOnFallComponent>(owner);
if (TryComp<MagneticGlovesAdvancedComponent>(uid, out var adv))
{
EnsureComp<PreventDisarmComponent>(owner);
EnsureComp<PreventStrippingFromHandsAndGlovesComponent>(owner);
}
}
}
public void OnExamined(EntityUid uid, MagneticGlovesComponent component, ExaminedEvent args)
{
if (!args.IsInDetailsRange)
return;
var message = Loc.GetString("maggloves-ready-in") + " " + component.GlovesReadyAt.Subtract(_gameTiming.CurTime).TotalSeconds.ToString("0");
if (component.GlovesReadyAt < _gameTiming.CurTime)
{
message = Loc.GetString("maggloves-ready");
}
if (component.Enabled)
{
message = Loc.GetString("maggloves-enabled-till") + " " + (component.GlovesLastActivation
.Add(component.GlovesActiveTime).Subtract(_gameTiming.CurTime).TotalSeconds.ToString("0"));
}
args.PushMarkup(message);
}
}

View File

@@ -22,6 +22,7 @@ using Content.Shared.Weapons.Ranged.Components;
using Content.Shared.Weapons.Ranged.Events;
using Content.Shared.Weapons.Ranged.Systems;
using Content.Shared._White;
using Content.Shared._White.MagGloves;
using Content.Shared._White.Chaplain;
using Robust.Shared.Audio;
using Robust.Shared.Audio.Systems;

View File

@@ -0,0 +1,10 @@
namespace Content.Shared._White.MagGloves;
/// <summary>
/// This is used to prevent entity loose it's items on fall.
/// </summary>
[RegisterComponent]
public sealed partial class KeepItemsOnFallComponent : Component
{
}

View File

@@ -0,0 +1,16 @@
using Robust.Shared.Prototypes;
namespace Content.Shared._White.MagGloves;
/// <summary>
/// This is used as a marker for advanced magnetic gloves.
/// </summary>
[RegisterComponent, AutoGenerateComponentState]
public sealed partial class MagneticGlovesAdvancedComponent : Component
{
[DataField, AutoNetworkedField]
public EntityUid? ToggleActionEntity;
[DataField]
public EntProtoId ToggleAction = "ActionToggleMagneticGlovesAdvanced";
}

View File

@@ -0,0 +1,31 @@
using Robust.Shared.Prototypes;
namespace Content.Shared._White.MagGloves;
/// <summary>
/// This is used for...
/// </summary>
[RegisterComponent, AutoGenerateComponentState]
public sealed partial class MagneticGlovesComponent : Component
{
[ViewVariables]
public bool Enabled { get; set; } = false;
[DataField, AutoNetworkedField]
public EntityUid? ToggleActionEntity;
[DataField("action")]
public EntProtoId ToggleAction = "ActionToggleMagneticGloves";
[ViewVariables(VVAccess.ReadOnly)]
public TimeSpan GlovesReadyAt = TimeSpan.Zero;
[ViewVariables(VVAccess.ReadOnly)]
public TimeSpan GlovesLastActivation = TimeSpan.Zero;
[DataField("glovesCooldown")]
public TimeSpan GlovesCooldown = TimeSpan.FromSeconds(60);
[DataField("glovesActiveTime")]
public TimeSpan GlovesActiveTime = TimeSpan.FromSeconds(60);
}

View File

@@ -0,0 +1,10 @@
namespace Content.Shared._White.MagGloves;
/// <summary>
/// This is used to prevent disarming when magnetic gloves are enabled.
/// </summary>
[RegisterComponent]
public sealed partial class PreventDisarmComponent : Component
{
}

View File

@@ -0,0 +1,10 @@
namespace Content.Shared._White.MagGloves;
/// <summary>
/// This is used to block stripping when magnetic gloves are enabled.
/// </summary>
[RegisterComponent]
public sealed partial class PreventStrippingFromHandsAndGlovesComponent : Component
{
}

View File

@@ -0,0 +1,107 @@
using Content.Shared.Actions;
using Content.Shared.Clothing.EntitySystems;
using Content.Shared.Inventory;
using Content.Shared.Item;
using Content.Shared.Popups;
using Content.Shared.Toggleable;
using Robust.Shared.Containers;
using Robust.Shared.Network;
using Robust.Shared.Timing;
namespace Content.Shared._White.MagGloves;
/// <summary>
/// This handles...
/// </summary>
public sealed class SharedMagneticGlovesSystem : EntitySystem
{
[Dependency] private readonly SharedActionsSystem _sharedActions = default!;
[Dependency] private readonly InventorySystem _inventory = default!;
[Dependency] private readonly SharedContainerSystem _sharedContainer = default!;
[Dependency] private readonly SharedItemSystem _item = default!;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly ClothingSystem _clothing = default!;
[Dependency] private readonly IGameTiming _gameTiming = default!;
[Dependency] private readonly SharedPopupSystem _popup = default!;
[Dependency] private readonly INetManager _net = default!;
public override void Initialize()
{
SubscribeLocalEvent<MagneticGlovesComponent, GetItemActionsEvent>(OnGetActions);
SubscribeLocalEvent<MagneticGlovesComponent, ToggleMagneticGlovesEvent>(OnToggleGloves);
}
public void OnGetActions(EntityUid uid, MagneticGlovesComponent component, GetItemActionsEvent args)
{
if (!args.InHands)
{
args.AddAction(ref component.ToggleActionEntity, component.ToggleAction);
}
}
public void OnToggleGloves(EntityUid uid, MagneticGlovesComponent component, ToggleMagneticGlovesEvent args)
{
if (args.Handled || _net.IsClient)
return;
_sharedContainer.TryGetContainingContainer(uid, out var container);
if (!component.Enabled)
{
if (component.GlovesReadyAt > _gameTiming.CurTime)
{
if (container != null)
{
_popup.PopupEntity(Loc.GetString("maggloves-not-ready"), uid, container.Owner);
}
return;
}
// If the gloves are not enabled, we want to activate them.
component.Enabled = true;
component.GlovesLastActivation = _gameTiming.CurTime;
_sharedActions.SetToggled(component.ToggleActionEntity, component.Enabled);
if (container != null)
{
_popup.PopupEntity(Loc.GetString("maggloves-activated"), uid, container.Owner);
EnsureComp<KeepItemsOnFallComponent>(container.Owner);
if (TryComp<MagneticGlovesAdvancedComponent>(uid, out var adv))
{
EnsureComp<PreventDisarmComponent>(container.Owner);
EnsureComp<PreventStrippingFromHandsAndGlovesComponent>(container.Owner);
}
}
}
else
{
component.Enabled = false;
_sharedActions.SetToggled(component.ToggleActionEntity, component.Enabled);
component.GlovesReadyAt = _gameTiming.CurTime + component.GlovesCooldown;
if (container != null)
{
_popup.PopupEntity(Loc.GetString("maggloves-deactivated"), uid, container.Owner);
RemComp<KeepItemsOnFallComponent>(container.Owner);
if (TryComp<MagneticGlovesAdvancedComponent>(uid, out var adv))
{
RemComp<PreventDisarmComponent>(container.Owner);
RemComp<PreventStrippingFromHandsAndGlovesComponent>(container.Owner);
}
}
}
if (TryComp<AppearanceComponent>(uid, out var appearance) &&
TryComp<ItemComponent>(uid, out var item))
{
_item.SetHeldPrefix(uid, component.Enabled ? "on" : "off", false, item);
_appearance.SetData(uid, ToggleVisuals.Toggled, component.Enabled, appearance);
_clothing.SetEquippedPrefix(uid, component.Enabled ? "on" : null);
}
args.Handled = true;
}
}
public sealed partial class ToggleMagneticGlovesEvent : InstantActionEvent {}

View File

@@ -0,0 +1,10 @@
maggloves-ready = Gloves are ready to use.
maggloves-ready-in = Gloves will be ready in
research-technology-lightweight-magnets = Lightweight Magnets
research-technology-advanced-grips = Advanced Grips
maggloves-not-ready = The gloves are not ready yet
maggloves-already-active = The gloves are already active
maggloves-enabled-till = The gloves are enabled for
maggloves-cant-strip = Magnetic gloves are strongly attached to the item
maggloves-activated = Magnetic gloves activated
maggloves-deactivated = Magnetic gloves deactivated

View File

@@ -0,0 +1,19 @@
ent-ClothingHandsGlovesMagnetic = магнитные перчатки
.desc = перчатки оснащенные специальными магнитными захватами, что позволяют вещам оставаться в ваших руках после свободного падения.
ent-ClothingHandsGlovesMagneticAdvanced = продвинутые магнитные перчатки
.desc = продвинутые магнитные перчатки оснащенные более мощными захватами, что дополнительно предотвращают возможность разоружения и кражи из рук носителя.
ent-ActionToggleMagneticGloves = активировать магнитные перчатки
.desc = Предотвращает выпадение предметов из рук при падении.
ent-ActionToggleMagneticGlovesAdvanced = активировать продвинутые магнитные перчатки
.desc = Предотвращает выпадение предметов из рук при падении и предотвращает возможность разоружения и кражи из рук носителя.
maggloves-ready = Перчатки готовы к использованию
maggloves-ready-in = Перчатки будут готовы к использованию через
research-technology-lightweight-magnets = Облегчённые магниты
research-technology-advanced-grips = Продвинутые захваты
maggloves-not-ready = Перчатки не готовы к использованию
maggloves-already-active = Перчатки уже активированы
maggloves-enabled-till = Перчатки будут активны еще
maggloves-cant-strip = Магнитные перчатки надежно удерживают предмет
maggloves-activated = Магнитные перчатки включены
maggloves-deactivated = Магнитные перчатки выключены

View File

@@ -762,6 +762,8 @@
- ShuttleGunPerforatorCircuitboard
- ShuttleGunFriendshipCircuitboard
- ShuttleGunDusterCircuitboard
- ClothingHandsGlovesMagnetic
- ClothingHandsGlovesMagneticAdvanced
- type: EmagLatheRecipes
emagStaticRecipes:
- MagazineLightRifleBox

View File

@@ -166,6 +166,7 @@
- ProjectileBatteryAmmoProvider
- Stunbaton
- TwoModeEnergyAmmoProvider
- MagneticGloves
- type: entity
parent: BaseItemRecharger
@@ -190,6 +191,7 @@
- Stunbaton
- TwoModeEnergyAmmoProvider
- PowerCell
- MagneticGloves
blacklist:
tags:
- PotatoBattery

View File

@@ -0,0 +1,77 @@
- type: entity
parent: ClothingHandsBase
id: ClothingHandsGlovesMagnetic
name: magnetic gloves
description: A pair of gloves with magnetic palms. Slip proof.
components:
- type: Sprite
sprite: White/MagGloves/maggloves.rsi
layers:
- state: icon
# map: [ "enum.ToggleVisuals.Layer" ]
- type: Clothing
sprite: White/MagGloves/maggloves.rsi
- type: Appearance
- type: GenericVisualizer
visuals:
enum.ToggleVisuals.Toggled:
enum.ToggleVisuals.Layer:
True: {state: icon-on}
False: {state: icon}
- type: GloveHeatResistance
heatResistance: 1400
- type: Fiber
fiberMaterial: fibers-nanomachines
- type: FingerprintMask
- type: MagneticGloves
glovesActiveTime: 60
glovesCooldown: 60
- type: entity
id: ClothingHandsGlovesMagneticAdvanced
parent: ClothingHandsGlovesMagnetic
name: advanced magnetic gloves
description: A pair of gloves with magnetic palms. Slip proof.
components:
- type: Sprite
sprite: White/MagGloves/magglovesadvanced.rsi
layers:
- state: icon
- type: Clothing
sprite: White/MagGloves/magglovesadvanced.rsi
- type: MagneticGlovesAdvanced
- type: MagneticGloves
action: ActionToggleMagneticGlovesAdvanced
glovesActiveTime: 80
- type: entity
id: ActionToggleMagneticGlovesBase
name: Toggle Magnetic Gloves
description: Toggles Magnetic Gloves on and off
noSpawn: true
components:
- type: InstantAction
itemIconStyle: NoItem
event: !type:ToggleMagneticGlovesEvent
- type: entity
id: ActionToggleMagneticGloves
parent: ActionToggleMagneticGlovesBase
name: Toggle Magnetic Gloves
description: Prevents owner from losing items from hands on fall.
noSpawn: true
components:
- type: InstantAction
icon: { sprite: White/MagGloves/maggloves.rsi, state: icon }
iconOn: { sprite: White/MagGloves/maggloves.rsi, state: icon-on }
- type: entity
id: ActionToggleMagneticGlovesAdvanced
parent: ActionToggleMagneticGlovesBase
name: Toggle Magnetic Gloves
description: Prevents owner from losing items from hands on fall, being disarmed or robbed.
noSpawn: true
components:
- type: InstantAction
icon: { sprite: White/MagGloves/magglovesadvanced.rsi, state: icon }
iconOn: { sprite: White/MagGloves/magglovesadvanced.rsi, state: icon-on }

View File

@@ -647,3 +647,21 @@
Plastic: 100
Glass: 20
- type: latheRecipe
id: ClothingHandsGlovesMagnetic
result: ClothingHandsGlovesMagnetic
completetime: 3
materials:
Cloth: 200
Steel: 100
Plastic: 50
- type: latheRecipe
id: ClothingHandsGlovesMagneticAdvanced
result: ClothingHandsGlovesMagneticAdvanced
completetime: 3
materials:
Cloth: 200
Steel: 100
Plastic: 50
Silver: 50

View File

@@ -104,6 +104,18 @@
# Tier 2
- type: technology
id: LightweightMagnets
name: research-technology-lightweight-magnets
icon:
sprite: White/MagGloves/maggloves.rsi
state: icon
discipline: Arsenal
tier: 2
cost: 7500
recipeUnlocks:
- ClothingHandsGlovesMagnetic
- type: technology
id: ExplosiveTechnology
name: research-technology-explosive-technology
@@ -149,7 +161,7 @@
- type: technology
id: BasicShuttleArmament
name: research-technology-basic-shuttle-armament
icon:
icon:
sprite: Structures/Power/cage_recharger.rsi
state: full
discipline: Arsenal
@@ -169,6 +181,18 @@
# Tier 3
- type: technology
id: AdvancedGrips
name: research-technology-advanced-grips
icon:
sprite: White/MagGloves/magglovesadvanced.rsi
state: icon
discipline: Arsenal
tier: 3
cost: 10000
recipeUnlocks:
- ClothingHandsGlovesMagneticAdvanced
- type: technology
id: PortableMicrofusionWeaponry
name: research-technology-portable-microfusion-weaponry
@@ -192,11 +216,11 @@
cost: 15000
recipeUnlocks:
- WeaponLaserSvalinn
- type: technology
id: AdvancedShuttleWeapon
name: research-technology-advanced-shuttle-weapon
icon:
icon:
sprite: Objects/Weapons/Guns/Ammunition/Magazine/Grenade/grenade_cartridge.rsi
state: icon
discipline: Arsenal

Binary file not shown.

After

Width:  |  Height:  |  Size: 335 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 682 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 683 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 280 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 289 B

View File

@@ -0,0 +1,41 @@
{
"version": 1,
"license": "CC-BY-SA-3.0",
"copyright": "Taken from tgstation at https://github.com/tgstation/tgstation/pull/69842/commits/d8138946b0ed06fced522729ac8eaa0596864329 edited by Skarletto (github)",
"size": {
"x": 32,
"y": 32
},
"states": [
{
"name": "icon"
},
{
"name": "icon-on"
},
{
"name": "equipped-HAND",
"directions": 4
},
{
"name": "on-equipped-HAND",
"directions": 4
},
{
"name": "inhand-left",
"directions": 4
},
{
"name": "on-inhand-left",
"directions": 4
},
{
"name": "inhand-right",
"directions": 4
},
{
"name": "on-inhand-right",
"directions": 4
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 332 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 266 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 274 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 353 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 698 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 706 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 289 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 306 B

View File

@@ -0,0 +1,41 @@
{
"version": 1,
"license": "CC-BY-SA-3.0",
"copyright": "Taken from tgstation at https://github.com/tgstation/tgstation/pull/69842/commits/d8138946b0ed06fced522729ac8eaa0596864329 edited by Skarletto (github)",
"size": {
"x": 32,
"y": 32
},
"states": [
{
"name": "icon"
},
{
"name": "icon-on"
},
{
"name": "equipped-HAND",
"directions": 4
},
{
"name": "on-equipped-HAND",
"directions": 4
},
{
"name": "inhand-left",
"directions": 4
},
{
"name": "on-inhand-left",
"directions": 4
},
{
"name": "inhand-right",
"directions": 4
},
{
"name": "on-inhand-right",
"directions": 4
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 350 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 271 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 291 B