Introduce an AI shop system (#3610)
* Introduce an AI shop system * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * feetback * condensation * meow * valid8 --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
|
|
@ -0,0 +1,5 @@
|
|||
using Content.Shared._DV.Silicons;
|
||||
|
||||
namespace Content.Client._DV.Silicons;
|
||||
|
||||
public sealed class StationAiShopSystem : SharedStationAiShopSystem;
|
||||
|
|
@ -202,7 +202,7 @@ public sealed partial class StoreSystem
|
|||
EntityUid? actionId;
|
||||
// I guess we just allow duplicate actions?
|
||||
// Allow duplicate actions and just have a single list buy for the buy-once ones.
|
||||
if (!_mind.TryGetMind(buyer, out var mind, out _))
|
||||
if (!_mind.TryGetMind(buyer, out var mind, out _) || !component.GrantActionsToMind) // DeltaV - allow forcing actions to be on the entity
|
||||
actionId = _actions.AddAction(buyer, listing.ProductAction);
|
||||
else
|
||||
actionId = _actionContainer.AddAction(mind, listing.ProductAction);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,71 @@
|
|||
using Content.Server.Fluids.EntitySystems;
|
||||
using Content.Server.Light.EntitySystems;
|
||||
using Content.Server.Spreader;
|
||||
using Content.Server.Store.Systems;
|
||||
using Content.Shared._DV.Silicons;
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.Coordinates.Helpers;
|
||||
using Content.Shared.Maps;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Map;
|
||||
|
||||
namespace Content.Server._DV.Silicons;
|
||||
|
||||
public sealed class StationAiShopSystem : SharedStationAiShopSystem
|
||||
{
|
||||
[Dependency] private readonly StoreSystem _store = default!;
|
||||
[Dependency] private readonly IMapManager _map = default!;
|
||||
[Dependency] private readonly SmokeSystem _smoke = default!;
|
||||
[Dependency] private readonly SharedTransformSystem _transform = default!;
|
||||
[Dependency] private readonly SpreaderSystem _spreader = default!;
|
||||
[Dependency] private readonly PoweredLightSystem _poweredLight = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<StationAiShopComponent, StationAiShopActionEvent>(OnShopAction);
|
||||
|
||||
SubscribeLocalEvent<StationAiShopComponent, StationAiLightSynthesizerActionEvent>(OnLightSynthesizer);
|
||||
SubscribeLocalEvent<StationAiShopComponent, StationAiSmokeActionEvent>(OnEmergencySealant);
|
||||
}
|
||||
|
||||
private void OnShopAction(Entity<StationAiShopComponent> ent, ref StationAiShopActionEvent args)
|
||||
{
|
||||
_store.ToggleUi(args.Performer, ent);
|
||||
}
|
||||
|
||||
private void OnLightSynthesizer(Entity<StationAiShopComponent> ent, ref StationAiLightSynthesizerActionEvent args)
|
||||
{
|
||||
if (_poweredLight.EjectBulb(args.Target) is { } oldBulb)
|
||||
Del(oldBulb);
|
||||
|
||||
var bulb = Spawn(args.BulbPrototype);
|
||||
if (!_poweredLight.InsertBulb(args.Target, bulb))
|
||||
{
|
||||
Del(bulb);
|
||||
return;
|
||||
}
|
||||
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
private void OnEmergencySealant(Entity<StationAiShopComponent> ent, ref StationAiSmokeActionEvent args)
|
||||
{
|
||||
var mapCoords = _transform.ToMapCoordinates(args.Target);
|
||||
if (!_map.TryFindGridAt(mapCoords, out _, out var grid) ||
|
||||
!grid.TryGetTileRef(args.Target, out var tileRef) ||
|
||||
tileRef.Tile.IsEmpty)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_spreader.RequiresFloorToSpread(args.SmokePrototype.ToString()) && tileRef.Tile.IsSpace())
|
||||
return;
|
||||
|
||||
var coords = grid.MapToGrid(mapCoords);
|
||||
var uid = Spawn(args.SmokePrototype, coords.SnapToGrid());
|
||||
_smoke.StartSmoke(uid, args.Solution, args.Duration, args.SpreadAmount);
|
||||
args.Handled = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -73,6 +73,12 @@ public sealed partial class StoreComponent : Component
|
|||
[ViewVariables, DataField]
|
||||
public bool RefundAllowed;
|
||||
|
||||
/// <summary>
|
||||
/// DeltaV: Should the store grant actions to the mind?
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public bool GrantActionsToMind = true;
|
||||
|
||||
/// <summary>
|
||||
/// Checks if store can be opened by the account owner only.
|
||||
/// Not meant to be used with uplinks.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,68 @@
|
|||
using Content.Shared.Actions;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Light.Components;
|
||||
using Robust.Shared.Audio.Systems;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Shared._DV.Silicons;
|
||||
|
||||
public abstract class SharedStationAiShopSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly DamageableSystem _damage = default!;
|
||||
[Dependency] private readonly IGameTiming _timing = default!;
|
||||
[Dependency] private readonly SharedActionsSystem _actions = default!;
|
||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<StationAiShopComponent, MapInitEvent>(OnMapInit);
|
||||
SubscribeLocalEvent<StationAiShopComponent, ComponentShutdown>(OnShutdown);
|
||||
|
||||
SubscribeLocalEvent<StationAiShopComponent, StationAiRgbLightingActionEvent>(OnRgbLighting);
|
||||
SubscribeLocalEvent<StationAiShopComponent, StationAiPlaySoundActionEvent>(OnPlaySound);
|
||||
SubscribeLocalEvent<StationAiShopComponent, StationAiHealthChangeActionEvent>(OnHealthChange);
|
||||
SubscribeLocalEvent<StationAiShopComponent, StationAiSpawnEntityActionEvent>(OnHolopointer);
|
||||
}
|
||||
|
||||
private void OnMapInit(Entity<StationAiShopComponent> ent, ref MapInitEvent args)
|
||||
{
|
||||
_actions.AddAction(ent, ref ent.Comp.ShopAction, ent.Comp.ShopActionId);
|
||||
Dirty(ent);
|
||||
}
|
||||
|
||||
private void OnShutdown(Entity<StationAiShopComponent> ent, ref ComponentShutdown args)
|
||||
{
|
||||
_actions.RemoveAction(ent, ent.Comp.ShopAction);
|
||||
}
|
||||
|
||||
private void OnRgbLighting(Entity<StationAiShopComponent> ent, ref StationAiRgbLightingActionEvent args)
|
||||
{
|
||||
if (!RemComp<RgbLightControllerComponent>(args.Target))
|
||||
AddComp<RgbLightControllerComponent>(args.Target);
|
||||
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
private void OnPlaySound(Entity<StationAiShopComponent> ent, ref StationAiPlaySoundActionEvent args)
|
||||
{
|
||||
_audio.PlayPredicted(args.Sound, args.Target, ent);
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
private void OnHealthChange(Entity<StationAiShopComponent> ent, ref StationAiHealthChangeActionEvent args)
|
||||
{
|
||||
_damage.TryChangeDamage(args.Target, args.Damage, origin: ent);
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
private void OnHolopointer(Entity<StationAiShopComponent> ent, ref StationAiSpawnEntityActionEvent args)
|
||||
{
|
||||
if (!_timing.IsFirstTimePredicted)
|
||||
return;
|
||||
|
||||
Spawn(args.Entity, args.Target);
|
||||
args.Handled = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
using Content.Shared.Actions;
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.Damage;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared._DV.Silicons;
|
||||
|
||||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
|
||||
public sealed partial class StationAiShopComponent : Component
|
||||
{
|
||||
[DataField]
|
||||
public EntProtoId ShopActionId = "ActionStationAiOpenShop";
|
||||
|
||||
[DataField, AutoNetworkedField]
|
||||
public EntityUid? ShopAction;
|
||||
}
|
||||
|
||||
public sealed partial class StationAiShopActionEvent : InstantActionEvent;
|
||||
|
||||
/// <summary>
|
||||
/// Toggles the RGB light controller on the given entity
|
||||
/// </summary>
|
||||
public sealed partial class StationAiRgbLightingActionEvent : EntityTargetActionEvent;
|
||||
|
||||
/// <summary>
|
||||
/// Replaces the light bulb in the target with the given prototype
|
||||
/// </summary>
|
||||
public sealed partial class StationAiLightSynthesizerActionEvent : EntityTargetActionEvent
|
||||
{
|
||||
[DataField(required: true)]
|
||||
public EntProtoId BulbPrototype;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Plays the given sound coming from the target entity
|
||||
/// </summary>
|
||||
public sealed partial class StationAiPlaySoundActionEvent : EntityTargetActionEvent
|
||||
{
|
||||
[DataField(required: true)]
|
||||
public SoundSpecifier Sound;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Changes the target entity's health by the given damage specifier
|
||||
/// </summary>
|
||||
public sealed partial class StationAiHealthChangeActionEvent : EntityTargetActionEvent
|
||||
{
|
||||
[DataField(required: true)]
|
||||
public DamageSpecifier Damage;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Spawns the given entity at the target location
|
||||
/// </summary>
|
||||
public sealed partial class StationAiSpawnEntityActionEvent : WorldTargetActionEvent
|
||||
{
|
||||
[DataField(required: true)]
|
||||
public EntProtoId Entity;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Triggers the given smoke effect at the target location
|
||||
/// </summary>
|
||||
public sealed partial class StationAiSmokeActionEvent : WorldTargetActionEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// How long the smoke stays for, after it has spread.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public float Duration = 10;
|
||||
|
||||
/// <summary>
|
||||
/// How much the smoke will spread.
|
||||
/// </summary>
|
||||
[DataField(required: true)]
|
||||
public int SpreadAmount;
|
||||
|
||||
/// <summary>
|
||||
/// Smoke entity to spawn.
|
||||
/// Defaults to smoke but you can use foam if you want.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public EntProtoId<SmokeComponent> SmokePrototype = "Smoke";
|
||||
|
||||
/// <summary>
|
||||
/// Solution to add to each smoke cloud.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// When using repeating trigger this essentially gets multiplied so dont do anything crazy like omnizine or lexorin.
|
||||
/// </remarks>
|
||||
[DataField]
|
||||
public Solution Solution = new();
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
ai-rgb-lighting-name = RGB Lighting
|
||||
ai-rgb-lighting-desc = Adjust a light's color controller to add or remove an RGB effect
|
||||
|
||||
ai-light-synthesizer-name = Light Synthesizer
|
||||
ai-light-synthesizer-desc = Send some nanites to synthesize a replacement light bulb in a fixture
|
||||
|
||||
ai-bike-horn-name = HONK.mp3
|
||||
ai-bike-horn-desc = Play an amusing audio clip from a holopad
|
||||
|
||||
ai-holopointer-name = Holopointer
|
||||
ai-holopointer-desc = Circle an area of interest with a hologram
|
||||
|
||||
ai-repair-nanites-name = Repair Nanites
|
||||
ai-repair-nanites-desc = Send some nanites to give a cyborg some minor repairs
|
||||
|
||||
ai-emergency-sealant-name = Emergency Sealant
|
||||
ai-emergency-sealant-desc = Deploy some metal foam to seal breaches
|
||||
|
|
@ -0,0 +1 @@
|
|||
store-currency-display-ai-memory = TB
|
||||
|
|
@ -56,6 +56,8 @@
|
|||
type: SiliconLawBoundUserInterface
|
||||
enum.CommunicationsConsoleUiKey.Key:
|
||||
type: CommunicationsConsoleBoundUserInterface
|
||||
enum.StoreUiKey.Key: # DeltaV - AI shop system
|
||||
type: StoreBoundUserInterface
|
||||
- type: IntrinsicUI
|
||||
uis:
|
||||
enum.RadarConsoleUiKey.Key:
|
||||
|
|
@ -83,6 +85,17 @@
|
|||
- sprite: Mobs/Silicon/station_ai.rsi
|
||||
state: default
|
||||
- type: ShowJobIcons
|
||||
# Begin DeltaV - AI Shop System
|
||||
- type: StationAiShop
|
||||
- type: Store
|
||||
categories:
|
||||
- AiAbilities
|
||||
currencyWhitelist:
|
||||
- AiMemory
|
||||
balance:
|
||||
AiMemory: 3
|
||||
grantActionsToMind: false
|
||||
# End DeltaV - AI Shop System
|
||||
|
||||
- type: entity
|
||||
id: AiHeldIntellicard
|
||||
|
|
|
|||
|
|
@ -10,6 +10,9 @@
|
|||
description: "An always powered light."
|
||||
suffix: Always powered
|
||||
components:
|
||||
- type: Tag # DeltaV - we need this for an action whitelist
|
||||
tags:
|
||||
- LightFixture
|
||||
- type: MeleeSound
|
||||
soundGroups:
|
||||
Brute:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,154 @@
|
|||
# Actions
|
||||
- type: entity
|
||||
id: ActionStationAiOpenShop
|
||||
name: Choose programs
|
||||
description: Configure your installed programs
|
||||
components:
|
||||
- type: InstantAction
|
||||
itemIconStyle: BigAction
|
||||
icon:
|
||||
sprite: _DV/Interface/Actions/actions_ai.rsi
|
||||
state: store
|
||||
event: !type:StationAiShopActionEvent
|
||||
|
||||
- type: entity
|
||||
id: ActionStationAiRgbLighting
|
||||
name: ai-rgb-lighting-name
|
||||
description: ai-rgb-lighting-desc
|
||||
components:
|
||||
- type: EntityTargetAction
|
||||
whitelist:
|
||||
tags:
|
||||
- LightFixture
|
||||
itemIconStyle: BigAction
|
||||
icon:
|
||||
sprite: _DV/Interface/Actions/actions_ai.rsi
|
||||
state: rgb_lighting
|
||||
range: -1
|
||||
checkCanAccess: false
|
||||
checkCanInteract: false
|
||||
useDelay: 30
|
||||
event: !type:StationAiRgbLightingActionEvent
|
||||
|
||||
- type: entity
|
||||
id: ActionStationAiLightSynthesizer
|
||||
name: ai-light-synthesizer-name
|
||||
description: ai-light-synthesizer-desc
|
||||
components:
|
||||
- type: EntityTargetAction
|
||||
whitelist:
|
||||
tags:
|
||||
- LightFixture
|
||||
itemIconStyle: BigAction
|
||||
icon:
|
||||
sprite: _DV/Interface/Actions/actions_ai.rsi
|
||||
state: light_synthesizer
|
||||
range: -1
|
||||
checkCanAccess: false
|
||||
checkCanInteract: false
|
||||
useDelay: 300
|
||||
event: !type:StationAiLightSynthesizerActionEvent
|
||||
bulbPrototype: LightTube
|
||||
|
||||
- type: entity
|
||||
id: ActionStationAiBikeHorn
|
||||
name: ai-bike-horn-name
|
||||
description: ai-bike-horn-desc
|
||||
components:
|
||||
- type: EntityTargetAction
|
||||
whitelist:
|
||||
components:
|
||||
- Holopad
|
||||
itemIconStyle: BigAction
|
||||
icon:
|
||||
sprite: _DV/Interface/Actions/actions_ai.rsi
|
||||
state: bike_horn
|
||||
range: -1
|
||||
checkCanAccess: false
|
||||
checkCanInteract: false
|
||||
useDelay: 60
|
||||
event: !type:StationAiPlaySoundActionEvent
|
||||
sound:
|
||||
collection: BikeHorn
|
||||
params:
|
||||
variation: 0.125
|
||||
|
||||
- type: entity
|
||||
id: ActionStationAiHoloPointer
|
||||
name: ai-holopointer-name
|
||||
description: ai-holopointer-desc
|
||||
components:
|
||||
- type: WorldTargetAction
|
||||
itemIconStyle: BigAction
|
||||
icon:
|
||||
sprite: _DV/Interface/Actions/actions_ai.rsi
|
||||
state: holopointer
|
||||
range: -1
|
||||
checkCanAccess: false
|
||||
checkCanInteract: false
|
||||
useDelay: 15
|
||||
event: !type:StationAiSpawnEntityActionEvent
|
||||
entity: StationAiHolopointer
|
||||
|
||||
- type: entity
|
||||
id: StationAiHolopointer
|
||||
name: holopointer
|
||||
description: A hologram projected by the station's AI to bring your attention to something.
|
||||
components:
|
||||
- type: Transform
|
||||
anchored: true
|
||||
- type: Physics
|
||||
bodyType: Static
|
||||
canCollide: false
|
||||
- type: Sprite
|
||||
sprite: _DV/Objects/Misc/holopointer.rsi
|
||||
state: target_circle
|
||||
- type: TimedDespawn
|
||||
lifetime: 15
|
||||
- type: PointLight
|
||||
enabled: true
|
||||
radius: 1
|
||||
color: red
|
||||
- type: Clickable
|
||||
|
||||
- type: entity
|
||||
id: ActionStationAiRepairNanites
|
||||
name: ai-repair-nanites-name
|
||||
description: ai-repair-nanites-desc
|
||||
components:
|
||||
- type: EntityTargetAction
|
||||
whitelist:
|
||||
components:
|
||||
- BorgChassis
|
||||
itemIconStyle: BigAction
|
||||
icon:
|
||||
sprite: _DV/Interface/Actions/actions_ai.rsi
|
||||
state: nanites
|
||||
range: -1
|
||||
checkCanAccess: false
|
||||
checkCanInteract: false
|
||||
useDelay: 120
|
||||
event: !type:StationAiHealthChangeActionEvent
|
||||
damage:
|
||||
groups:
|
||||
Burn: -20
|
||||
Brute: -20
|
||||
|
||||
- type: entity
|
||||
id: ActionStationAiEmergencySealant
|
||||
name: ai-emergency-sealant-name
|
||||
description: ai-emergency-sealant-desc
|
||||
components:
|
||||
- type: WorldTargetAction
|
||||
itemIconStyle: BigAction
|
||||
icon:
|
||||
sprite: _DV/Interface/Actions/actions_ai.rsi
|
||||
state: emergency_sealant
|
||||
range: -1
|
||||
checkCanAccess: false
|
||||
checkCanInteract: false
|
||||
useDelay: 300
|
||||
event: !type:StationAiSmokeActionEvent
|
||||
duration: 10
|
||||
spreadAmount: 8
|
||||
smokePrototype: AluminiumMetalFoam
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
- type: listing
|
||||
id: AiRgbLighting
|
||||
name: ai-rgb-lighting-name
|
||||
description: ai-rgb-lighting-desc
|
||||
productAction: ActionStationAiRgbLighting
|
||||
cost:
|
||||
AiMemory: 1
|
||||
categories:
|
||||
- AiAbilities
|
||||
conditions:
|
||||
- !type:ListingLimitedStockCondition
|
||||
stock: 1
|
||||
|
||||
- type: listing
|
||||
id: AiHolopointer
|
||||
name: ai-holopointer-name
|
||||
description: ai-holopointer-desc
|
||||
productAction: ActionStationAiHoloPointer
|
||||
cost:
|
||||
AiMemory: 1
|
||||
categories:
|
||||
- AiAbilities
|
||||
conditions:
|
||||
- !type:ListingLimitedStockCondition
|
||||
stock: 1
|
||||
|
||||
- type: listing
|
||||
id: AiLightSynthesizer
|
||||
name: ai-light-synthesizer-name
|
||||
description: ai-light-synthesizer-desc
|
||||
productAction: ActionStationAiLightSynthesizer
|
||||
cost:
|
||||
AiMemory: 1
|
||||
categories:
|
||||
- AiAbilities
|
||||
conditions:
|
||||
- !type:ListingLimitedStockCondition
|
||||
stock: 1
|
||||
|
||||
- type: listing
|
||||
id: AiBikeHorn
|
||||
name: ai-bike-horn-name
|
||||
description: ai-bike-horn-desc
|
||||
productAction: ActionStationAiBikeHorn
|
||||
cost:
|
||||
AiMemory: 1
|
||||
categories:
|
||||
- AiAbilities
|
||||
conditions:
|
||||
- !type:ListingLimitedStockCondition
|
||||
stock: 1
|
||||
|
||||
- type: listing
|
||||
id: AiEmergencySealant
|
||||
name: ai-emergency-sealant-name
|
||||
description: ai-emergency-sealant-desc
|
||||
productAction: ActionStationAiEmergencySealant
|
||||
cost:
|
||||
AiMemory: 2
|
||||
categories:
|
||||
- AiAbilities
|
||||
conditions:
|
||||
- !type:ListingLimitedStockCondition
|
||||
stock: 1
|
||||
|
||||
- type: listing
|
||||
id: AiRepairNanites
|
||||
name: ai-repair-nanites-name
|
||||
description: ai-repair-nanites-desc
|
||||
productAction: ActionStationAiRepairNanites
|
||||
cost:
|
||||
AiMemory: 2
|
||||
categories:
|
||||
- AiAbilities
|
||||
conditions:
|
||||
- !type:ListingLimitedStockCondition
|
||||
stock: 1
|
||||
|
|
@ -2,3 +2,7 @@
|
|||
id: UplinkObjectives
|
||||
name: store-category-objectives
|
||||
priority: 11
|
||||
|
||||
- type: storeCategory
|
||||
id: AiAbilities
|
||||
name: store-category-abilities
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
- type: currency
|
||||
id: AiMemory
|
||||
displayName: store-currency-display-ai-memory
|
||||
canWithdraw: false
|
||||
|
|
@ -96,6 +96,9 @@
|
|||
- type: Tag # prevents ID chips being used for an id computer privileged id
|
||||
id: IdChip
|
||||
|
||||
- type: Tag
|
||||
id: LightFixture
|
||||
|
||||
- type: Tag
|
||||
id: MagazineLaser
|
||||
|
||||
|
|
|
|||
|
After Width: | Height: | Size: 381 B |
|
After Width: | Height: | Size: 383 B |
|
After Width: | Height: | Size: 451 B |
|
After Width: | Height: | Size: 461 B |
|
|
@ -0,0 +1,32 @@
|
|||
{
|
||||
"version": 1,
|
||||
"license": "CC-BY-SA-3.0",
|
||||
"copyright": "Janet Blackquill <uhhadd@gmail.com> 2025",
|
||||
"size": {
|
||||
"x": 32,
|
||||
"y": 32
|
||||
},
|
||||
"states": [
|
||||
{
|
||||
"name": "bike_horn"
|
||||
},
|
||||
{
|
||||
"name": "emergency_sealant"
|
||||
},
|
||||
{
|
||||
"name": "holopointer"
|
||||
},
|
||||
{
|
||||
"name": "light_synthesizer"
|
||||
},
|
||||
{
|
||||
"name": "nanites"
|
||||
},
|
||||
{
|
||||
"name": "rgb_lighting"
|
||||
},
|
||||
{
|
||||
"name": "store"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
After Width: | Height: | Size: 449 B |
|
After Width: | Height: | Size: 439 B |
|
After Width: | Height: | Size: 393 B |
|
|
@ -0,0 +1,41 @@
|
|||
{
|
||||
"version": 1,
|
||||
"license": "CC-BY-SA-3.0",
|
||||
"copyright": "Taken from Paradise Station at https://github.com/ParadiseSS13/Paradise/blob/a126858e60caebc7c3a4b25400a5969dcc63f092/icons/mob/telegraphing/telegraph_holographic.dmi",
|
||||
"size": {
|
||||
"x": 32,
|
||||
"y": 32
|
||||
},
|
||||
"states": [
|
||||
{
|
||||
"name": "target_box",
|
||||
"delays": [
|
||||
[
|
||||
0.125,
|
||||
0.125,
|
||||
0.125,
|
||||
0.125,
|
||||
0.125,
|
||||
0.125,
|
||||
0.125,
|
||||
0.125
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "target_circle",
|
||||
"delays": [
|
||||
[
|
||||
0.125,
|
||||
0.125,
|
||||
0.125,
|
||||
0.125,
|
||||
0.125,
|
||||
0.125,
|
||||
0.125,
|
||||
0.125
|
||||
]
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
After Width: | Height: | Size: 893 B |
|
After Width: | Height: | Size: 1.0 KiB |