--- /dev/null
+using System.Numerics;
+using Content.Shared.Mining.Components;
+using Robust.Client.GameObjects;
+using Robust.Client.Graphics;
+using Robust.Client.Player;
+using Robust.Shared.Enums;
+using Robust.Shared.Timing;
+using Robust.Shared.Utility;
+
+namespace Content.Client.Mining;
+
+public sealed class MiningOverlay : Overlay
+{
+ [Dependency] private readonly IEntityManager _entityManager = default!;
+ [Dependency] private readonly IGameTiming _timing = default!;
+ [Dependency] private readonly IPlayerManager _player = default!;
+ private readonly EntityLookupSystem _lookup;
+ private readonly SpriteSystem _sprite;
+ private readonly TransformSystem _xform;
+
+ private readonly EntityQuery<SpriteComponent> _spriteQuery;
+ private readonly EntityQuery<TransformComponent> _xformQuery;
+
+ public override OverlaySpace Space => OverlaySpace.WorldSpace;
+ public override bool RequestScreenTexture => false;
+
+ private readonly HashSet<Entity<MiningScannerViewableComponent>> _viewableEnts = new();
+
+ public MiningOverlay()
+ {
+ IoCManager.InjectDependencies(this);
+
+ _lookup = _entityManager.System<EntityLookupSystem>();
+ _sprite = _entityManager.System<SpriteSystem>();
+ _xform = _entityManager.System<TransformSystem>();
+
+ _spriteQuery = _entityManager.GetEntityQuery<SpriteComponent>();
+ _xformQuery = _entityManager.GetEntityQuery<TransformComponent>();
+ }
+
+ protected override void Draw(in OverlayDrawArgs args)
+ {
+ var handle = args.WorldHandle;
+
+ if (_player.LocalEntity is not { } localEntity ||
+ !_entityManager.TryGetComponent<MiningScannerViewerComponent>(localEntity, out var viewerComp))
+ return;
+
+ if (viewerComp.LastPingLocation == null)
+ return;
+
+ var scaleMatrix = Matrix3Helpers.CreateScale(Vector2.One);
+
+ _viewableEnts.Clear();
+ _lookup.GetEntitiesInRange(viewerComp.LastPingLocation.Value, viewerComp.ViewRange, _viewableEnts);
+ foreach (var ore in _viewableEnts)
+ {
+ if (!_xformQuery.TryComp(ore, out var xform) ||
+ !_spriteQuery.TryComp(ore, out var sprite))
+ continue;
+
+ if (xform.MapID != args.MapId || !sprite.Visible)
+ continue;
+
+ if (!sprite.LayerMapTryGet(MiningScannerVisualLayers.Overlay, out var idx))
+ continue;
+ var layer = sprite[idx];
+
+ if (layer.ActualRsi?.Path == null || layer.RsiState.Name == null)
+ continue;
+
+ var gridRot = xform.GridUid == null ? 0 : _xformQuery.CompOrNull(xform.GridUid.Value)?.LocalRotation ?? 0;
+ var rotationMatrix = Matrix3Helpers.CreateRotation(gridRot);
+
+ var worldMatrix = Matrix3Helpers.CreateTranslation(_xform.GetWorldPosition(xform));
+ var scaledWorld = Matrix3x2.Multiply(scaleMatrix, worldMatrix);
+ var matty = Matrix3x2.Multiply(rotationMatrix, scaledWorld);
+ handle.SetTransform(matty);
+
+ var spriteSpec = new SpriteSpecifier.Rsi(layer.ActualRsi.Path, layer.RsiState.Name);
+ var texture = _sprite.GetFrame(spriteSpec, TimeSpan.FromSeconds(layer.AnimationTime));
+
+ var animTime = (viewerComp.NextPingTime - _timing.CurTime).TotalSeconds;
+
+
+ var alpha = animTime < viewerComp.AnimationDuration
+ ? 0
+ : (float) Math.Clamp((animTime - viewerComp.AnimationDuration) / viewerComp.AnimationDuration, 0f, 1f);
+ var color = Color.White.WithAlpha(alpha);
+
+ handle.DrawTexture(texture, -(Vector2) texture.Size / 2f / EyeManager.PixelsPerMeter, layer.Rotation, modulate: color);
+
+ }
+ handle.SetTransform(Matrix3x2.Identity);
+ }
+}
--- /dev/null
+using Content.Shared.Mining.Components;
+using Robust.Client.Graphics;
+using Robust.Client.Player;
+using Robust.Shared.Player;
+
+namespace Content.Client.Mining;
+
+/// <summary>
+/// This handles the lifetime of the <see cref="MiningOverlay"/> for a given entity.
+/// </summary>
+public sealed class MiningOverlaySystem : EntitySystem
+{
+ [Dependency] private readonly IPlayerManager _player = default!;
+ [Dependency] private readonly IOverlayManager _overlayMan = default!;
+
+ private MiningOverlay _overlay = default!;
+
+ /// <inheritdoc/>
+ public override void Initialize()
+ {
+ SubscribeLocalEvent<MiningScannerViewerComponent, ComponentInit>(OnInit);
+ SubscribeLocalEvent<MiningScannerViewerComponent, ComponentShutdown>(OnShutdown);
+ SubscribeLocalEvent<MiningScannerViewerComponent, LocalPlayerAttachedEvent>(OnPlayerAttached);
+ SubscribeLocalEvent<MiningScannerViewerComponent, LocalPlayerDetachedEvent>(OnPlayerDetached);
+
+ _overlay = new();
+ }
+
+ private void OnPlayerAttached(Entity<MiningScannerViewerComponent> ent, ref LocalPlayerAttachedEvent args)
+ {
+ _overlayMan.AddOverlay(_overlay);
+ }
+
+ private void OnPlayerDetached(Entity<MiningScannerViewerComponent> ent, ref LocalPlayerDetachedEvent args)
+ {
+ _overlayMan.RemoveOverlay(_overlay);
+ }
+
+ private void OnInit(Entity<MiningScannerViewerComponent> ent, ref ComponentInit args)
+ {
+ if (_player.LocalEntity == ent)
+ {
+ _overlayMan.AddOverlay(_overlay);
+ }
+ }
+
+ private void OnShutdown(Entity<MiningScannerViewerComponent> ent, ref ComponentShutdown args)
+ {
+ if (_player.LocalEntity == ent)
+ {
+ _overlayMan.RemoveOverlay(_overlay);
+ }
+ }
+}
+++ /dev/null
-namespace Content.Client.Mining;
-
-public sealed class OreVeinVisualsComponent
-{
-
-}
-using Content.Server.Mining.Components;
using Content.Shared.Destructible;
using Content.Shared.Mining;
+using Content.Shared.Mining.Components;
using Content.Shared.Random;
using Content.Shared.Random.Helpers;
using Robust.Shared.Prototypes;
if (comp.ActiveSound != null && comp.PlayingStream == null)
{
- var loop = AudioParams.Default.WithLoop(true);
+ var loop = comp.ActiveSound.Params.WithLoop(true);
var stream = args.Predicted
? _audio.PlayPredicted(comp.ActiveSound, uid, args.User, loop)
: _audio.PlayPvs(comp.ActiveSound, uid, loop);
--- /dev/null
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Mining.Components;
+
+/// <summary>
+/// This is a component that, when held in the inventory or pocket of a player, gives the the MiningOverlay.
+/// </summary>
+[RegisterComponent, NetworkedComponent, Access(typeof(MiningScannerSystem))]
+public sealed partial class MiningScannerComponent : Component
+{
+ [DataField]
+ public float Range = 5;
+}
--- /dev/null
+using Robust.Shared.GameStates;
+using Robust.Shared.Serialization;
+
+namespace Content.Shared.Mining.Components;
+
+[RegisterComponent, NetworkedComponent, Access(typeof(MiningScannerSystem))]
+public sealed partial class MiningScannerViewableComponent : Component;
+
+[Serializable, NetSerializable]
+public enum MiningScannerVisualLayers : byte
+{
+ Overlay
+}
--- /dev/null
+using Robust.Shared.Audio;
+using Robust.Shared.GameStates;
+using Robust.Shared.Map;
+
+namespace Content.Shared.Mining.Components;
+
+[RegisterComponent, NetworkedComponent, AutoGenerateComponentState, AutoGenerateComponentPause, Access(typeof(MiningScannerSystem))]
+public sealed partial class MiningScannerViewerComponent : Component
+{
+ [DataField, ViewVariables(VVAccess.ReadOnly), AutoNetworkedField]
+ public float ViewRange;
+
+ [DataField, AutoNetworkedField]
+ public float AnimationDuration = 1.5f;
+
+ [DataField, AutoNetworkedField]
+ public TimeSpan PingDelay = TimeSpan.FromSeconds(5);
+
+ [DataField, AutoNetworkedField, AutoPausedField]
+ public TimeSpan NextPingTime = TimeSpan.MaxValue;
+
+ [DataField]
+ public EntityCoordinates? LastPingLocation;
+
+ [DataField, AutoNetworkedField]
+ public SoundSpecifier? PingSound = new SoundPathSpecifier("/Audio/Machines/sonar-ping.ogg")
+ {
+ Params = new AudioParams
+ {
+ Volume = -3,
+ }
+ };
+
+ [DataField]
+ public bool QueueRemoval;
+}
-using Content.Shared.Mining;
using Content.Shared.Random;
-using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
+using Robust.Shared.Prototypes;
-namespace Content.Server.Mining.Components;
+namespace Content.Shared.Mining.Components;
/// <summary>
/// Defines an entity that will drop a random ore after being destroyed.
/// How often an entity will be seeded with ore. Note: the amount of ore
/// that is dropped is dependent on the ore prototype. <see crefalso="OrePrototype"/>
/// </summary>
- [DataField("oreChance")]
+ [DataField]
public float OreChance = 0.1f;
/// <summary>
/// The weighted random prototype used for determining what ore will be dropped.
/// </summary>
- [DataField("oreRarityPrototypeId", customTypeSerializer: typeof(PrototypeIdSerializer<WeightedRandomOrePrototype>))]
- public string? OreRarityPrototypeId;
+ [DataField]
+ public ProtoId<WeightedRandomOrePrototype>? OreRarityPrototypeId;
/// <summary>
/// The ore that this entity holds.
/// If set in the prototype, it will not be overriden.
/// </summary>
- [DataField("currentOre", customTypeSerializer: typeof(PrototypeIdSerializer<OrePrototype>)), ViewVariables(VVAccess.ReadWrite)]
- public string? CurrentOre;
+ [DataField]
+ public ProtoId<OrePrototype>? CurrentOre;
}
--- /dev/null
+using Content.Shared.Inventory;
+using Content.Shared.Item.ItemToggle.Components;
+using Content.Shared.Mining.Components;
+using Robust.Shared.Audio.Systems;
+using Robust.Shared.Containers;
+using Robust.Shared.Network;
+using Robust.Shared.Timing;
+
+namespace Content.Shared.Mining;
+
+public sealed class MiningScannerSystem : EntitySystem
+{
+ [Dependency] private readonly IGameTiming _timing = default!;
+ [Dependency] private readonly INetManager _net = default!;
+ [Dependency] private readonly SharedAudioSystem _audio = default!;
+ [Dependency] private readonly SharedContainerSystem _container = default!;
+ [Dependency] private readonly InventorySystem _inventory = default!;
+
+ /// <inheritdoc/>
+ public override void Initialize()
+ {
+ SubscribeLocalEvent<MiningScannerComponent, EntGotInsertedIntoContainerMessage>(OnInserted);
+ SubscribeLocalEvent<MiningScannerComponent, EntGotRemovedFromContainerMessage>(OnRemoved);
+ SubscribeLocalEvent<MiningScannerComponent, ItemToggledEvent>(OnToggled);
+ }
+
+ private void OnInserted(Entity<MiningScannerComponent> ent, ref EntGotInsertedIntoContainerMessage args)
+ {
+ UpdateViewerComponent(args.Container.Owner);
+ }
+
+ private void OnRemoved(Entity<MiningScannerComponent> ent, ref EntGotRemovedFromContainerMessage args)
+ {
+ UpdateViewerComponent(args.Container.Owner);
+ }
+
+ private void OnToggled(Entity<MiningScannerComponent> ent, ref ItemToggledEvent args)
+ {
+ if (_container.TryGetContainingContainer((ent.Owner, null, null), out var container))
+ UpdateViewerComponent(container.Owner);
+ }
+
+ public void UpdateViewerComponent(EntityUid uid)
+ {
+ Entity<MiningScannerComponent>? scannerEnt = null;
+
+ var ents = _inventory.GetHandOrInventoryEntities(uid);
+ foreach (var ent in ents)
+ {
+ if (!TryComp<MiningScannerComponent>(ent, out var scannerComponent) ||
+ !TryComp<ItemToggleComponent>(ent, out var toggle))
+ continue;
+
+ if (!toggle.Activated)
+ continue;
+
+ if (scannerEnt == null || scannerComponent.Range > scannerEnt.Value.Comp.Range)
+ scannerEnt = (ent, scannerComponent);
+ }
+
+ if (_net.IsServer)
+ {
+ if (scannerEnt == null)
+ {
+ if (TryComp<MiningScannerViewerComponent>(uid, out var viewer))
+ viewer.QueueRemoval = true;
+ }
+ else
+ {
+ var viewer = EnsureComp<MiningScannerViewerComponent>(uid);
+ viewer.ViewRange = scannerEnt.Value.Comp.Range;
+ viewer.QueueRemoval = false;
+ viewer.NextPingTime = _timing.CurTime + viewer.PingDelay;
+ Dirty(uid, viewer);
+ }
+ }
+ }
+
+ public override void Update(float frameTime)
+ {
+ base.Update(frameTime);
+
+ var query = EntityQueryEnumerator<MiningScannerViewerComponent, TransformComponent>();
+ while (query.MoveNext(out var uid, out var viewer, out var xform))
+ {
+ if (viewer.QueueRemoval)
+ {
+ RemCompDeferred(uid, viewer);
+ continue;
+ }
+
+ if (_timing.CurTime < viewer.NextPingTime)
+ continue;
+
+ viewer.NextPingTime = _timing.CurTime + viewer.PingDelay;
+ viewer.LastPingLocation = xform.Coordinates;
+ if (_net.IsClient && _timing.IsFirstTimePredicted)
+ _audio.PlayEntity(viewer.PingSound, uid, uid);
+ }
+ }
+}
using Robust.Shared.Prototypes;
-using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
+using Robust.Shared.Utility;
namespace Content.Shared.Mining;
/// <summary>
/// This is a prototype for defining ores that generate in rock
/// </summary>
-[Prototype("ore")]
+[Prototype]
public sealed partial class OrePrototype : IPrototype
{
/// <inheritdoc/>
[IdDataField]
public string ID { get; private set; } = default!;
- [DataField("oreEntity", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
- public string? OreEntity;
+ [DataField]
+ public EntProtoId? OreEntity;
- [DataField("minOreYield")]
+ [DataField]
public int MinOreYield = 1;
- [DataField("maxOreYield")]
+ [DataField]
public int MaxOreYield = 1;
- //TODO: add sprites for ores for things like mining analyzer
+ [DataField]
+ public SpriteSpecifier? OreSprite;
}
copyright: "/tg/station"
source: "https://github.com/tgstation/tgstation/blob/3eeba3899f22638595333c63b7b7433001f91bb2/sound/machines/eject.ogg"
+- files: ["sonar-ping.ogg"]
+ license: "CC-BY-SA-3.0"
+ copyright: "/tg/station"
+ source: "https://github.com/tgstation/tgstation/blob/002051a3d5e4a35af504e52c0990bf4e22a908dc/sound/machines/sonar-ping.ogg"
+
- files: ["scanning.ogg"]
license: "CC0-1.0"
copyright: "Samuel Gremaud on freesound.org"
- id: ClothingEyesGlassesMeson
- id: ClothingBeltSalvageWebbing
- id: SeismicCharge
+ - id: MineralScanner
+ weight: 0.5
- id: WeaponCrusher
weight: 0.5
- !type:GroupSelector
id: SalvageEquipmentLegendary
table: !type:GroupSelector
children:
+ - id: AdvancedMineralScanner
- id: BlueprintFulton
- id: BlueprintSeismicCharge
- id: WeaponCrusherGlaive
items:
- MiningDrill
- Shovel
+ - MineralScannerUnpowered
- OreBag
- Crowbar
- RadioHandheld
--- /dev/null
+- type: entity
+ id: MineralScannerUnpowered
+ parent: BaseItem
+ name: mineral scanner
+ description: A scanner that checks surrounding rock for useful minerals. It must be in your hand or pocket to work.
+ suffix: Unpowered
+ components:
+ - type: Sprite
+ sprite: Objects/Specific/Mining/mineral_scanner.rsi
+ layers:
+ - state: icon
+ - state: icon-o
+ shader: unshaded
+ visible: false
+ map: ["enum.ToggleVisuals.Layer"]
+ - type: ItemToggleActiveSound
+ activeSound:
+ path: /Audio/Ambience/Objects/light_hum.ogg
+ params:
+ volume: -10
+ maxDistance: 1
+ - type: Appearance
+ - type: GenericVisualizer
+ visuals:
+ enum.ToggleVisuals.Toggled:
+ enum.ToggleVisuals.Layer:
+ True: { visible: true }
+ False: { visible: false }
+ - type: ItemToggle
+ soundActivate:
+ path: /Audio/Weapons/click.ogg
+ params:
+ maxDistance: 1
+ - type: MiningScanner
+
+- type: entity
+ id: MineralScanner
+ parent: [ MineralScannerUnpowered, PowerCellSlotMediumItem ]
+ suffix: Powered
+ components:
+ - type: ToggleCellDraw
+ - type: PowerCellDraw
+ drawRate: 2.4 # ~5 minutes on a medium power cell.
+ useRate: 0
+
+- type: entity
+ id: MineralScannerEmpty
+ parent: MineralScanner
+ suffix: Empty
+ components:
+ - type: ItemSlots
+ slots:
+ cell_slot:
+ name: power-cell-slot-component-slot-name-default
+
+- type: entity
+ id: AdvancedMineralScannerUnpowered
+ parent: MineralScannerUnpowered
+ name: advanced mineral scanner
+ description: A scanner that checks surrounding rock for useful minerals. It must be in your hand or pocket to work. This one has an extended range.
+ suffix: Unpowered
+ components:
+ - type: Sprite
+ layers:
+ - state: adv
+ - state: adv-o
+ shader: unshaded
+ visible: false
+ map: ["enum.ToggleVisuals.Layer"]
+ - type: MiningScanner
+ range: 10
+
+- type: entity
+ id: AdvancedMineralScanner
+ parent: [ AdvancedMineralScannerUnpowered, PowerCellSlotMediumItem ]
+ suffix: Powered
+ components:
+ - type: ToggleCellDraw
+ - type: PowerCellDraw
+ drawRate: 1.2 # ~10 minutes on a medium power cell.
+ useRate: 0
+
+- type: entity
+ id: AdvancedMineralScannerEmpty
+ parent: AdvancedMineralScanner
+ suffix: Empty
+ components:
+ - type: ItemSlots
+ slots:
+ cell_slot:
+ name: power-cell-slot-component-slot-name-default
- PowerCellHigh
- WeaponPistolCHIMP
- ClothingMaskWeldingGas
+ - MineralScannerEmpty
+ - AdvancedMineralScannerEmpty
- WeaponGauntletGorilla
- SynthesizerInstrument
- ClothingShoesBootsMagSci
state: rock_asteroid_north
- map: [ "enum.EdgeLayer.West" ]
state: rock_asteroid_west
+ - type: MiningScannerViewable
- type: Damageable
damageContainer: StructuralInorganic
damageModifierSet: Rock
- map: [ "enum.EdgeLayer.West" ]
state: rock_asteroid_west
- state: rock_coal
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: AsteroidRockGold
- map: [ "enum.EdgeLayer.West" ]
state: rock_asteroid_west
- state: rock_gold
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: AsteroidRockDiamond
- map: [ "enum.EdgeLayer.West" ]
state: rock_asteroid_west
- state: rock_diamond
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: AsteroidRockPlasma
- map: [ "enum.EdgeLayer.West" ]
state: rock_asteroid_west
- state: rock_phoron
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: AsteroidRockQuartz
- map: [ "enum.EdgeLayer.West" ]
state: rock_asteroid_west
- state: rock_quartz
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: AsteroidRockQuartzCrab
- map: [ "enum.EdgeLayer.West" ]
state: rock_asteroid_west
- state: rock_quartz
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: AsteroidRockSilver
- map: [ "enum.EdgeLayer.West" ]
state: rock_asteroid_west
- state: rock_silver
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: AsteroidRockSilverCrab
- map: [ "enum.EdgeLayer.West" ]
state: rock_asteroid_west
- state: rock_tin
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: AsteroidRockTinCrab
- map: [ "enum.EdgeLayer.West" ]
state: rock_asteroid_west
- state: rock_uranium
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: AsteroidRockUraniumCrab
- map: [ "enum.EdgeLayer.West" ]
state: rock_asteroid_west
- state: rock_bananium
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: AsteroidRockSalt
- map: [ "enum.EdgeLayer.West" ]
state: rock_asteroid_west
- state: rock_salt
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: AsteroidRockArtifactFragment
- map: [ "enum.EdgeLayer.West" ]
state: rock_asteroid_west
- state: rock_artifact_fragment
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: AsteroidRockMining
- map: [ "enum.EdgeLayer.West" ]
state: ironrock_west
- state: rock_coal
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: IronRockGold
- map: [ "enum.EdgeLayer.West" ]
state: ironrock_west
- state: rock_gold
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: IronRockPlasma
- map: [ "enum.EdgeLayer.West" ]
state: ironrock_west
- state: rock_phoron
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: IronRockQuartz
- map: [ "enum.EdgeLayer.West" ]
state: ironrock_west
- state: rock_quartz
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: IronRockSilver
- map: [ "enum.EdgeLayer.West" ]
state: ironrock_west
- state: rock_silver
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: IronRockIron
- map: [ "enum.EdgeLayer.West" ]
state: ironrock_west
- state: rock_tin
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: IronRockUranium
- map: [ "enum.EdgeLayer.West" ]
state: ironrock_west
- state: rock_uranium
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: IronRockBananium
- map: [ "enum.EdgeLayer.West" ]
state: ironrock_west
- state: rock_bananium
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: IronRockSalt
- map: [ "enum.EdgeLayer.West" ]
state: ironrock_west
- state: rock_salt
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: IronRockArtifactFragment
- map: [ "enum.EdgeLayer.West" ]
state: ironrock_west
- state: rock_artifact_fragment
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: IronRockDiamond
- map: [ "enum.EdgeLayer.West" ]
state: ironrock_west
- state: rock_diamond
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
# Rocks and ore veins
- type: entity
- type: Icon
sprite: Structures/Walls/rock.rsi
state: rock
+ - type: MiningScannerViewable
- type: SmoothEdge
- type: Sprite
sprite: Structures/Walls/rock.rsi
- map: [ "enum.EdgeLayer.West" ]
state: rock_west
- state: rock_coal
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: WallRockGold
- map: [ "enum.EdgeLayer.West" ]
state: rock_west
- state: rock_gold
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: WallRockDiamond
- map: [ "enum.EdgeLayer.West" ]
state: rock_west
- state: rock_diamond
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: WallRockPlasma
- map: [ "enum.EdgeLayer.West" ]
state: rock_west
- state: rock_phoron
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: WallRockQuartz
- map: [ "enum.EdgeLayer.West" ]
state: rock_west
- state: rock_quartz
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: WallRockSilver
- map: [ "enum.EdgeLayer.West" ]
state: rock_west
- state: rock_silver
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
# Yes I know it drops steel but we may get smelting at some point
- type: entity
- map: [ "enum.EdgeLayer.West" ]
state: rock_west
- state: rock_tin
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: WallRockUranium
- map: [ "enum.EdgeLayer.West" ]
state: rock_west
- state: rock_uranium
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
- map: [ "enum.EdgeLayer.West" ]
state: rock_west
- state: rock_bananium
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: WallRockArtifactFragment
- map: [ "enum.EdgeLayer.West" ]
state: rock_west
- state: rock_artifact_fragment
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: WallRockSalt
- map: [ "enum.EdgeLayer.West" ]
state: rock_west
- state: rock_salt
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
# Basalt variants
- type: entity
- map: [ "enum.EdgeLayer.West" ]
state: rock_wall_west
- state: rock_coal
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: WallRockBasaltGold
- map: [ "enum.EdgeLayer.West" ]
state: rock_wall_west
- state: rock_gold
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: WallRockBasaltDiamond
- map: [ "enum.EdgeLayer.West" ]
state: rock_wall_west
- state: rock_diamond
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: WallRockBasaltPlasma
- map: [ "enum.EdgeLayer.West" ]
state: rock_wall_west
- state: rock_phoron
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: WallRockBasaltQuartz
- map: [ "enum.EdgeLayer.West" ]
state: rock_wall_west
- state: rock_quartz
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: WallRockBasaltSilver
- map: [ "enum.EdgeLayer.West" ]
state: rock_wall_west
- state: rock_silver
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: WallRockBasaltTin
- map: [ "enum.EdgeLayer.West" ]
state: rock_wall_west
- state: rock_tin
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: WallRockBasaltUranium
- map: [ "enum.EdgeLayer.West" ]
state: rock_wall_west
- state: rock_uranium
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
- map: [ "enum.EdgeLayer.West" ]
state: rock_wall_west
- state: rock_bananium
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: WallRockBasaltArtifactFragment
- map: [ "enum.EdgeLayer.West" ]
state: rock_wall_west
- state: rock_artifact_fragment
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: WallRockBasaltSalt
- map: [ "enum.EdgeLayer.West" ]
state: rock_wall_west
- state: rock_salt
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
# Snow variants
- type: entity
- map: [ "enum.EdgeLayer.West" ]
state: rock_snow_west
- state: rock_coal
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: WallRockSnowGold
- map: [ "enum.EdgeLayer.West" ]
state: rock_snow_west
- state: rock_gold
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: WallRockSnowDiamond
- map: [ "enum.EdgeLayer.West" ]
state: rock_snow_west
- state: rock_diamond
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: WallRockSnowPlasma
- map: [ "enum.EdgeLayer.West" ]
state: rock_snow_west
- state: rock_phoron
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: WallRockSnowQuartz
- map: [ "enum.EdgeLayer.West" ]
state: rock_snow_west
- state: rock_quartz
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: WallRockSnowSilver
- map: [ "enum.EdgeLayer.West" ]
state: rock_snow_west
- state: rock_silver
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: WallRockSnowTin
- map: [ "enum.EdgeLayer.West" ]
state: rock_snow_west
- state: rock_tin
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: WallRockSnowUranium
- map: [ "enum.EdgeLayer.West" ]
state: rock_snow_west
- state: rock_uranium
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
- map: [ "enum.EdgeLayer.West" ]
state: rock_snow_west
- state: rock_bananium
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: WallRockSnowArtifactFragment
- map: [ "enum.EdgeLayer.West" ]
state: rock_snow_west
- state: rock_artifact_fragment
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: WallRockSnowSalt
- map: [ "enum.EdgeLayer.West" ]
state: rock_snow_west
- state: rock_salt
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
# Sand variants
- type: entity
- map: [ "enum.EdgeLayer.West" ]
state: rock_sand_west
- state: rock_coal
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: WallRockSandGold
- map: [ "enum.EdgeLayer.West" ]
state: rock_sand_west
- state: rock_gold
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: WallRockSandDiamond
- map: [ "enum.EdgeLayer.West" ]
state: rock_sand_west
- state: rock_diamond
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: WallRockSandPlasma
- map: [ "enum.EdgeLayer.West" ]
state: rock_sand_west
- state: rock_phoron
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: WallRockSandQuartz
- map: [ "enum.EdgeLayer.West" ]
state: rock_sand_west
- state: rock_quartz
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: WallRockSandSilver
- map: [ "enum.EdgeLayer.West" ]
state: rock_sand_west
- state: rock_silver
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: WallRockSandTin
- map: [ "enum.EdgeLayer.West" ]
state: rock_sand_west
- state: rock_tin
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: WallRockSandUranium
- map: [ "enum.EdgeLayer.West" ]
state: rock_sand_west
- state: rock_uranium
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: WallRockSandBananium
- map: [ "enum.EdgeLayer.West" ]
state: rock_sand_west
- state: rock_bananium
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: WallRockSandArtifactFragment
- map: [ "enum.EdgeLayer.West" ]
state: rock_sand_west
- state: rock_artifact_fragment
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: WallRockSandSalt
- map: [ "enum.EdgeLayer.West" ]
state: rock_sand_west
- state: rock_salt
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
# Chromite variants
- type: entity
- map: [ "enum.EdgeLayer.West" ]
state: rock_chromite_west
- state: rock_coal
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: WallRockChromiteGold
- map: [ "enum.EdgeLayer.West" ]
state: rock_chromite_west
- state: rock_gold
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: WallRockChromiteDiamond
- map: [ "enum.EdgeLayer.West" ]
state: rock_chromite_west
- state: rock_diamond
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: WallRockChromitePlasma
- map: [ "enum.EdgeLayer.West" ]
state: rock_chromite_west
- state: rock_phoron
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: WallRockChromiteQuartz
- map: [ "enum.EdgeLayer.West" ]
state: rock_chromite_west
- state: rock_quartz
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: WallRockChromiteSilver
- map: [ "enum.EdgeLayer.West" ]
state: rock_chromite_west
- state: rock_silver
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: WallRockChromiteTin
- map: [ "enum.EdgeLayer.West" ]
state: rock_chromite_west
- state: rock_tin
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: WallRockChromiteUranium
- map: [ "enum.EdgeLayer.West" ]
state: rock_chromite_west
- state: rock_uranium
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
- map: [ "enum.EdgeLayer.West" ]
state: rock_chromite_west
- state: rock_bananium
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: WallRockChromiteArtifactFragment
- map: [ "enum.EdgeLayer.West" ]
state: rock_chromite_west
- state: rock_artifact_fragment
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: WallRockChromiteSalt
- map: [ "enum.EdgeLayer.West" ]
state: rock_chromite_west
- state: rock_salt
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
# Andesite variants
- type: entity
- map: [ "enum.EdgeLayer.West" ]
state: rock_andesite_west
- state: rock_coal
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: WallRockAndesiteGold
- map: [ "enum.EdgeLayer.West" ]
state: rock_andesite_west
- state: rock_gold
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: WallRockAndesiteDiamond
- map: [ "enum.EdgeLayer.West" ]
state: rock_andesite_west
- state: rock_diamond
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: WallRockAndesitePlasma
- map: [ "enum.EdgeLayer.West" ]
state: rock_andesite_west
- state: rock_phoron
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: WallRockAndesiteQuartz
- map: [ "enum.EdgeLayer.West" ]
state: rock_andesite_west
- state: rock_quartz
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: WallRockAndesiteSilver
- map: [ "enum.EdgeLayer.West" ]
state: rock_andesite_west
- state: rock_silver
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: WallRockAndesiteTin
- map: [ "enum.EdgeLayer.West" ]
state: rock_andesite_west
- state: rock_tin
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: WallRockAndesiteUranium
- map: [ "enum.EdgeLayer.West" ]
state: rock_andesite_west
- state: rock_uranium
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
- map: [ "enum.EdgeLayer.West" ]
state: rock_andesite_west
- state: rock_bananium
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: WallRockAndesiteArtifactFragment
- map: [ "enum.EdgeLayer.West" ]
state: rock_andesite_west
- state: rock_artifact_fragment
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
- type: entity
id: WallRockAndesiteSalt
- map: [ "enum.EdgeLayer.West" ]
state: rock_andesite_west
- state: rock_salt
+ map: [ "enum.MiningScannerVisualLayers.Overlay" ]
+- type: latheRecipe
+ id: MineralScannerEmpty
+ result: MineralScannerEmpty
+ completetime: 3
+ materials:
+ Steel: 1000
+ Glass: 300
+ Plastic: 300
+ Gold: 500
+
+- type: latheRecipe
+ id: AdvancedMineralScannerEmpty
+ result: AdvancedMineralScannerEmpty
+ completetime: 1
+ materials:
+ Steel: 1000
+ Glass: 300
+ Plastic: 300
+ Uranium: 500
+
- type: latheRecipe
id: Fulton
result: Fulton1
cost: 7500
recipeUnlocks:
- MiningDrill
+ - MineralScannerEmpty
- BorgModuleMining
- BorgModuleGrapplingGun
- OreProcessorIndustrialMachineCircuitboard
recipeUnlocks:
- OreBagOfHolding
- MiningDrillDiamond
+ - AdvancedMineralScannerEmpty
# Tier 3
--- /dev/null
+{
+ "version": 1,
+ "license": "CC-BY-SA-3.0",
+ "copyright": "Taken from vgstation at https://github.com/vgstation-coders/vgstation13/commit/125c975f1b3bf9826b37029e9ab5a5f89e975a7e. adv and adv-o by EmoGarbage404",
+ "size": {
+ "x": 32,
+ "y": 32
+ },
+ "states": [
+ {
+ "name": "icon"
+ },
+ {
+ "name": "icon-o"
+ },
+ {
+ "name": "adv"
+ },
+ {
+ "name": "adv-o"
+ }
+ ]
+}