[April Fools] Leggy (#36133)
* leggy * shader * fix visuals for other clients * static
173
Content.Client/Silicons/StationAi/StationAiVisualizerSystem.cs
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
using Content.Shared.Silicons.StationAi;
|
||||
using Robust.Client.Animations;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.Graphics;
|
||||
|
||||
namespace Content.Client.Silicons.StationAi;
|
||||
|
||||
public sealed partial class StationAiVisualizerSystem : VisualizerSystem<StationAiCoreComponent>
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<StationAiCoreComponent, AnimationCompletedEvent>(OnAnimationCompleted);
|
||||
}
|
||||
|
||||
private static readonly Animation CoreUpAnimation = new()
|
||||
{
|
||||
Length = TimeSpan.FromSeconds(0.8f),
|
||||
AnimationTracks =
|
||||
{
|
||||
new AnimationTrackSpriteFlick
|
||||
{
|
||||
LayerKey = StationAiVisualLayers.CoreStanding,
|
||||
KeyFrames =
|
||||
{
|
||||
new AnimationTrackSpriteFlick.KeyFrame(new RSI.StateId("up"), 0f)
|
||||
}
|
||||
},
|
||||
new AnimationTrackSpriteFlick
|
||||
{
|
||||
LayerKey = StationAiVisualLayers.ScreenStanding,
|
||||
KeyFrames =
|
||||
{
|
||||
new AnimationTrackSpriteFlick.KeyFrame(new RSI.StateId("ai_up"), 0f)
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private static readonly Animation CoreDownAnimation = new()
|
||||
{
|
||||
Length = TimeSpan.FromSeconds(0.8f),
|
||||
AnimationTracks =
|
||||
{
|
||||
new AnimationTrackSpriteFlick
|
||||
{
|
||||
LayerKey = StationAiVisualLayers.CoreStanding,
|
||||
KeyFrames =
|
||||
{
|
||||
new AnimationTrackSpriteFlick.KeyFrame(new RSI.StateId("down"), 0f)
|
||||
}
|
||||
},
|
||||
new AnimationTrackSpriteFlick
|
||||
{
|
||||
LayerKey = StationAiVisualLayers.ScreenStanding,
|
||||
KeyFrames =
|
||||
{
|
||||
new AnimationTrackSpriteFlick.KeyFrame(new RSI.StateId("ai_down"), 0f)
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
protected override void OnAppearanceChange(EntityUid uid, StationAiCoreComponent component, ref AppearanceChangeEvent args)
|
||||
{
|
||||
if (args.Sprite == null)
|
||||
return;
|
||||
if (!TryComp<AnimationPlayerComponent>(uid, out var animPlayer))
|
||||
return;
|
||||
|
||||
if (!AppearanceSystem.TryGetData<StationAiState>(uid, StationAiVisualState.Key, out var state, args.Component))
|
||||
state = StationAiState.Empty;
|
||||
|
||||
UpdateVisuals(uid, state, component, args.Sprite, animPlayer);
|
||||
}
|
||||
|
||||
private void OnAnimationCompleted(EntityUid uid, StationAiCoreComponent comp, AnimationCompletedEvent args)
|
||||
{
|
||||
if (args.Key != StationAiCoreComponent.AnimationKey)
|
||||
return;
|
||||
if (!TryComp<SpriteComponent>(uid, out var sprite))
|
||||
return;
|
||||
if (!TryComp<AnimationPlayerComponent>(uid, out var animPlayer))
|
||||
return;
|
||||
|
||||
if (!AppearanceSystem.TryGetData<StationAiState>(uid, StationAiVisualState.Key, out var state))
|
||||
state = comp.CurrentState;
|
||||
|
||||
// Convert to finished state
|
||||
StationAiState targetState;
|
||||
switch (state)
|
||||
{
|
||||
case StationAiState.Up:
|
||||
targetState = StationAiState.Standing;
|
||||
break;
|
||||
case StationAiState.Down:
|
||||
targetState = StationAiState.Occupied;
|
||||
break;
|
||||
default:
|
||||
targetState = state;
|
||||
break;
|
||||
}
|
||||
|
||||
UpdateVisuals(uid, targetState, comp, sprite, animPlayer);
|
||||
}
|
||||
|
||||
private void UpdateVisuals(EntityUid uid, StationAiState state, StationAiCoreComponent comp, SpriteComponent sprite, AnimationPlayerComponent? animPlayer = null)
|
||||
{
|
||||
if (state == comp.CurrentState)
|
||||
return;
|
||||
if (!Resolve(uid, ref animPlayer))
|
||||
return;
|
||||
if (AnimationSystem.HasRunningAnimation(uid, animPlayer, StationAiCoreComponent.AnimationKey))
|
||||
return;
|
||||
|
||||
var targetState = state;
|
||||
if (comp.CurrentState == StationAiState.Occupied && state == StationAiState.Standing)
|
||||
targetState = StationAiState.Up; // play standing up animation first
|
||||
else if (comp.CurrentState == StationAiState.Standing && state == StationAiState.Occupied)
|
||||
targetState = StationAiState.Down; // play sitting down animation first
|
||||
|
||||
comp.CurrentState = targetState;
|
||||
|
||||
switch (targetState)
|
||||
{
|
||||
case StationAiState.Empty:
|
||||
sprite.LayerSetVisible(StationAiVisualLayers.Core, true);
|
||||
sprite.LayerSetVisible(StationAiVisualLayers.Screen, true);
|
||||
sprite.LayerSetVisible(StationAiVisualLayers.CoreStanding, false);
|
||||
sprite.LayerSetVisible(StationAiVisualLayers.ScreenStanding, false);
|
||||
sprite.LayerSetState(StationAiVisualLayers.Screen, new RSI.StateId("ai_empty"));
|
||||
break;
|
||||
case StationAiState.Occupied:
|
||||
sprite.LayerSetVisible(StationAiVisualLayers.Core, true);
|
||||
sprite.LayerSetVisible(StationAiVisualLayers.Screen, true);
|
||||
sprite.LayerSetVisible(StationAiVisualLayers.CoreStanding, false);
|
||||
sprite.LayerSetVisible(StationAiVisualLayers.ScreenStanding, false);
|
||||
sprite.LayerSetState(StationAiVisualLayers.Screen, new RSI.StateId("ai"));
|
||||
break;
|
||||
case StationAiState.Dead:
|
||||
sprite.LayerSetVisible(StationAiVisualLayers.Core, true);
|
||||
sprite.LayerSetVisible(StationAiVisualLayers.Screen, true);
|
||||
sprite.LayerSetVisible(StationAiVisualLayers.CoreStanding, false);
|
||||
sprite.LayerSetVisible(StationAiVisualLayers.ScreenStanding, false);
|
||||
sprite.LayerSetState(StationAiVisualLayers.Screen, new RSI.StateId("ai_dead"));
|
||||
break;
|
||||
case StationAiState.Up:
|
||||
sprite.LayerSetVisible(StationAiVisualLayers.Core, false);
|
||||
sprite.LayerSetVisible(StationAiVisualLayers.Screen, false);
|
||||
sprite.LayerSetVisible(StationAiVisualLayers.CoreStanding, true);
|
||||
sprite.LayerSetVisible(StationAiVisualLayers.ScreenStanding, true);
|
||||
AnimationSystem.Play((uid, animPlayer), CoreUpAnimation, StationAiCoreComponent.AnimationKey);
|
||||
break;
|
||||
case StationAiState.Down:
|
||||
sprite.LayerSetVisible(StationAiVisualLayers.Core, false);
|
||||
sprite.LayerSetVisible(StationAiVisualLayers.Screen, false);
|
||||
sprite.LayerSetVisible(StationAiVisualLayers.CoreStanding, true);
|
||||
sprite.LayerSetVisible(StationAiVisualLayers.ScreenStanding, true);
|
||||
AnimationSystem.Play((uid, animPlayer), CoreDownAnimation, StationAiCoreComponent.AnimationKey);
|
||||
break;
|
||||
case StationAiState.Standing:
|
||||
sprite.LayerSetVisible(StationAiVisualLayers.Core, false);
|
||||
sprite.LayerSetVisible(StationAiVisualLayers.Screen, false);
|
||||
sprite.LayerSetVisible(StationAiVisualLayers.CoreStanding, true);
|
||||
sprite.LayerSetVisible(StationAiVisualLayers.ScreenStanding, true);
|
||||
sprite.LayerSetState(StationAiVisualLayers.CoreStanding, new RSI.StateId("base_high"));
|
||||
sprite.LayerSetState(StationAiVisualLayers.ScreenStanding, new RSI.StateId("ai_high"));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ using System.Diagnostics.CodeAnalysis;
|
|||
using Content.Shared.Actions.Events;
|
||||
using Content.Shared.IdentityManagement;
|
||||
using Content.Shared.Interaction.Events;
|
||||
using Content.Shared.Mind.Components;
|
||||
using Content.Shared.Popups;
|
||||
using Content.Shared.Verbs;
|
||||
using Robust.Shared.Serialization;
|
||||
|
|
@ -27,6 +28,8 @@ public abstract partial class SharedStationAiSystem
|
|||
SubscribeLocalEvent<StationAiHeldComponent, InteractionAttemptEvent>(OnHeldInteraction);
|
||||
SubscribeLocalEvent<StationAiHeldComponent, AttemptRelayActionComponentChangeEvent>(OnHeldRelay);
|
||||
SubscribeLocalEvent<StationAiHeldComponent, JumpToCoreEvent>(OnCoreJump);
|
||||
SubscribeLocalEvent<StationAiHeldComponent, VisitCoreEvent>(OnCoreVisit);
|
||||
SubscribeLocalEvent<VisitingMindComponent, UnVisitCoreEvent>(OnCoreUnVisit);
|
||||
SubscribeLocalEvent<TryGetIdentityShortInfoEvent>(OnTryGetIdentityShortInfo);
|
||||
}
|
||||
|
||||
|
|
@ -50,7 +53,46 @@ public abstract partial class SharedStationAiSystem
|
|||
if (!TryGetCore(ent.Owner, out var core) || core.Comp?.RemoteEntity == null)
|
||||
return;
|
||||
|
||||
_xforms.DropNextTo(core.Comp.RemoteEntity.Value, core.Owner) ;
|
||||
_xforms.DropNextTo(core.Comp.RemoteEntity.Value, core.Owner);
|
||||
}
|
||||
|
||||
private void OnCoreVisit(Entity<StationAiHeldComponent> ent, ref VisitCoreEvent args)
|
||||
{
|
||||
if (!TryGetCore(ent.Owner, out var core) || core.Comp?.RemoteEntity == null)
|
||||
return;
|
||||
|
||||
if (!_mind.TryGetMind(ent.Owner, out var mindId, out var mind))
|
||||
return;
|
||||
|
||||
// move the player's mind to the core
|
||||
_mind.Visit(mindId, core, mind);
|
||||
_xforms.Unanchor(core);
|
||||
|
||||
if (!TryComp<AppearanceComponent>(core, out var app))
|
||||
return;
|
||||
|
||||
_appearance.SetData(core, StationAiVisualState.Key, StationAiState.Standing, app);
|
||||
}
|
||||
|
||||
private void OnCoreUnVisit(Entity<VisitingMindComponent> ent, ref UnVisitCoreEvent args)
|
||||
{
|
||||
if (!Transform(ent.Owner).Anchored && !_xforms.AnchorEntity(ent.Owner))
|
||||
return;
|
||||
|
||||
// move the player's mind back to the camera
|
||||
if (ent.Comp.MindId != null)
|
||||
_mind.UnVisit(ent.Comp.MindId.Value);
|
||||
|
||||
if (!TryComp(ent.Owner, out StationAiCoreComponent? coreComp) || coreComp.RemoteEntity == null)
|
||||
return;
|
||||
|
||||
// move the camera back to the core
|
||||
_xforms.DropNextTo(coreComp.RemoteEntity.Value, ent.Owner);
|
||||
|
||||
if (!TryComp<AppearanceComponent>(ent.Owner, out var app))
|
||||
return;
|
||||
|
||||
_appearance.SetData(ent.Owner, StationAiVisualState.Key, StationAiState.Occupied, app);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -164,7 +206,7 @@ public abstract partial class SharedStationAiSystem
|
|||
var verb = new AlternativeVerb
|
||||
{
|
||||
Text = isOpen ? Loc.GetString("ai-close") : Loc.GetString("ai-open"),
|
||||
Act = () =>
|
||||
Act = () =>
|
||||
{
|
||||
// no need to show menu if device is not powered.
|
||||
if (!PowerReceiver.IsPowered(ent.Owner))
|
||||
|
|
|
|||
|
|
@ -460,6 +460,9 @@ public abstract partial class SharedStationAiSystem : EntitySystem
|
|||
|
||||
private void OnAiRemove(Entity<StationAiCoreComponent> ent, ref EntRemovedFromContainerMessage args)
|
||||
{
|
||||
if (args.Container.ID != StationAiCoreComponent.Container)
|
||||
return;
|
||||
|
||||
if (_timing.ApplyingState)
|
||||
return;
|
||||
|
||||
|
|
@ -538,6 +541,16 @@ public sealed partial class JumpToCoreEvent : InstantActionEvent
|
|||
|
||||
}
|
||||
|
||||
public sealed partial class VisitCoreEvent : InstantActionEvent
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public sealed partial class UnVisitCoreEvent : InstantActionEvent
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed partial class IntellicardDoAfterEvent : SimpleDoAfterEvent;
|
||||
|
||||
|
|
@ -548,10 +561,21 @@ public enum StationAiVisualState : byte
|
|||
Key,
|
||||
}
|
||||
|
||||
public enum StationAiVisualLayers : byte
|
||||
{
|
||||
Core,
|
||||
Screen,
|
||||
CoreStanding,
|
||||
ScreenStanding,
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public enum StationAiState : byte
|
||||
{
|
||||
Empty,
|
||||
Occupied,
|
||||
Dead,
|
||||
Up,
|
||||
Down,
|
||||
Standing,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,4 +39,16 @@ public sealed partial class StationAiCoreComponent : Component
|
|||
public EntProtoId? PhysicalEntityProto = "StationAiHoloLocal";
|
||||
|
||||
public const string Container = "station_ai_mind_slot";
|
||||
|
||||
/// <summary>
|
||||
/// The key used to index the leggy animation.
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
public const string AnimationKey = "leggy_animation";
|
||||
|
||||
/// <summary>
|
||||
/// The current visual state of the core.
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
public StationAiState CurrentState = StationAiState.Empty;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,36 @@
|
|||
state: ai_core
|
||||
event: !type:JumpToCoreEvent
|
||||
|
||||
- type: entity
|
||||
id: ActionVisitCore
|
||||
name: Leggy
|
||||
description: Move around using your legs.
|
||||
components:
|
||||
- type: InstantAction
|
||||
priority: -20
|
||||
itemIconStyle: BigAction
|
||||
icon:
|
||||
sprite: Interface/Actions/actions_ai.rsi
|
||||
state: leg
|
||||
event: !type:VisitCoreEvent
|
||||
useDelay: 2
|
||||
startDelay: true
|
||||
|
||||
- type: entity
|
||||
id: ActionUnVisitCore
|
||||
name: No Leggy
|
||||
description: Return back to the remote.
|
||||
components:
|
||||
- type: InstantAction
|
||||
priority: -20
|
||||
itemIconStyle: BigAction
|
||||
icon:
|
||||
sprite: Interface/Actions/actions_ai.rsi
|
||||
state: leg
|
||||
event: !type:UnVisitCoreEvent
|
||||
useDelay: 2
|
||||
startDelay: true
|
||||
|
||||
- type: entity
|
||||
id: ActionSurvCameraLights
|
||||
name: Toggle camera lights
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
- type: ActionGrant
|
||||
actions:
|
||||
- ActionJumpToCore
|
||||
- ActionVisitCore
|
||||
- ActionSurvCameraLights
|
||||
- ActionAIViewLaws
|
||||
- type: UserInterface
|
||||
|
|
@ -325,10 +326,13 @@
|
|||
name: AI Core
|
||||
description: The latest in Artificial Intelligences.
|
||||
parent:
|
||||
- BaseMob
|
||||
- BaseStructure
|
||||
- AiHolder
|
||||
suffix: Empty
|
||||
components:
|
||||
- type: Transform
|
||||
noRot: true
|
||||
- type: WarpPoint
|
||||
- type: ContainerComp
|
||||
proto: AiHeld
|
||||
|
|
@ -350,25 +354,77 @@
|
|||
- type: StationAiVision
|
||||
- type: InteractionOutline
|
||||
- type: Sprite
|
||||
sprite: Mobs/Silicon/station_ai.rsi
|
||||
noRot: true
|
||||
layers:
|
||||
- state: base
|
||||
sprite: Mobs/Silicon/station_ai.rsi
|
||||
map: ["enum.StationAiVisualLayers.Core"]
|
||||
- state: ai_empty
|
||||
map: ["unshaded"]
|
||||
sprite: Mobs/Silicon/station_ai.rsi
|
||||
shader: unshaded
|
||||
map: ["enum.StationAiVisualLayers.Screen"]
|
||||
- state: base_high
|
||||
sprite: Mobs/Silicon/leggy.rsi
|
||||
map: ["enum.StationAiVisualLayers.CoreStanding"]
|
||||
offset: "0.0,0.5"
|
||||
visible: false
|
||||
- state: ai_high
|
||||
sprite: Mobs/Silicon/leggy.rsi
|
||||
shader: unshaded
|
||||
map: ["enum.StationAiVisualLayers.ScreenStanding"]
|
||||
offset: "0.0,0.5"
|
||||
visible: false
|
||||
- type: Appearance
|
||||
- type: AnimationPlayer
|
||||
- type: ActionGrant
|
||||
actions:
|
||||
- ActionUnVisitCore
|
||||
- type: Anchorable
|
||||
flags:
|
||||
- None
|
||||
- type: Physics
|
||||
bodyType: Static
|
||||
- type: Tag
|
||||
tags:
|
||||
- DoorBumpOpener
|
||||
- FootstepSound
|
||||
- Structure
|
||||
- type: Access
|
||||
groups:
|
||||
- AllAccess
|
||||
- type: IntrinsicRadioReceiver
|
||||
- type: IntrinsicRadioTransmitter
|
||||
channels:
|
||||
- Binary
|
||||
- Common
|
||||
- Command
|
||||
- Engineering
|
||||
- Medical
|
||||
- Science
|
||||
- Security
|
||||
- Service
|
||||
- Supply
|
||||
- type: ActiveRadio
|
||||
channels:
|
||||
- Binary
|
||||
- Common
|
||||
- Command
|
||||
- Engineering
|
||||
- Medical
|
||||
- Science
|
||||
- Security
|
||||
- Service
|
||||
- Supply
|
||||
- type: ShowJobIcons
|
||||
- type: Speech
|
||||
speechVerb: Robotic
|
||||
speechSounds: Borg
|
||||
- type: InteractionPopup
|
||||
interactSuccessString: petting-success-station-ai
|
||||
interactFailureString: petting-failure-station-ai
|
||||
messagePerceivedByOthers: petting-success-station-ai-others # Otherwise AI cannot tell its being pet as It's just a brain inside of the core, not the core itself.
|
||||
interactSuccessSound:
|
||||
path: /Audio/Ambience/Objects/periodic_beep.ogg
|
||||
- type: GenericVisualizer
|
||||
visuals:
|
||||
enum.StationAiVisualState.Key:
|
||||
unshaded:
|
||||
Empty: { state: ai_empty }
|
||||
Occupied: { state: ai }
|
||||
- type: Telephone
|
||||
compatibleRanges:
|
||||
- Grid
|
||||
|
|
@ -396,12 +452,6 @@
|
|||
- type: ContainerSpawnPoint
|
||||
containerId: station_ai_mind_slot
|
||||
job: StationAi
|
||||
- type: Sprite
|
||||
sprite: Mobs/Silicon/station_ai.rsi
|
||||
layers:
|
||||
- state: base
|
||||
- state: ai
|
||||
shader: unshaded
|
||||
|
||||
# The actual brain inside the core
|
||||
- type: entity
|
||||
|
|
|
|||
BIN
Resources/Textures/Interface/Actions/actions_ai.rsi/leg.png
Normal file
|
After Width: | Height: | Size: 2 KiB |
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"version": 1,
|
||||
"license": "CC-BY-SA-3.0",
|
||||
"copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/blob/c473a8bcc28fbd80827dfca5660d81ca6e833e2c/icons/hud/screen_ai.dmi , some sprites updated by ScarKy0(Discord), door actions by ScarKy0(Discord) and @Max_tanuki(Twitter)",
|
||||
"copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/blob/c473a8bcc28fbd80827dfca5660d81ca6e833e2c/icons/hud/screen_ai.dmi , some sprites updated by ScarKy0(Discord), door actions by ScarKy0(Discord) and @Max_tanuki(Twitter), leg made by muburu_ (Dicord) and adjusted by slarticodefast",
|
||||
"size": {
|
||||
"x": 32,
|
||||
"y": 32
|
||||
|
|
@ -48,6 +48,9 @@
|
|||
},
|
||||
{
|
||||
"name": "door_overcharge_off"
|
||||
},
|
||||
{
|
||||
"name": "leg"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
BIN
Resources/Textures/Mobs/Silicon/leggy.rsi/ai_down.png
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
Resources/Textures/Mobs/Silicon/leggy.rsi/ai_high.png
Normal file
|
After Width: | Height: | Size: 6.4 KiB |
BIN
Resources/Textures/Mobs/Silicon/leggy.rsi/ai_up.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
Resources/Textures/Mobs/Silicon/leggy.rsi/base_high.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
Resources/Textures/Mobs/Silicon/leggy.rsi/down.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
96
Resources/Textures/Mobs/Silicon/leggy.rsi/meta.json
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
{
|
||||
"version": 1,
|
||||
"license": "CC-BY-SA-3.0",
|
||||
"copyright": "Taken from tgstation at https://github.com/tgstation/tgstation/blob/2a19963297f91efb452dbb5c1d4eb28a14776b0a/icons/mob/silicon/ai.dmi, leg sprites made by muburu_ (Dicord) and adjusted by slarticodefast",
|
||||
"size": {
|
||||
"x": 32,
|
||||
"y": 64
|
||||
},
|
||||
"states": [
|
||||
{
|
||||
"name": "ai_high",
|
||||
"delays": [
|
||||
[
|
||||
0.2,
|
||||
0.2,
|
||||
0.1,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.1
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "base_high"
|
||||
},
|
||||
{
|
||||
"name": "down",
|
||||
"delays": [
|
||||
[
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "ai_down",
|
||||
"delays": [
|
||||
[
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "up",
|
||||
"delays": [
|
||||
[
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "ai_up",
|
||||
"delays": [
|
||||
[
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1
|
||||
]
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
BIN
Resources/Textures/Mobs/Silicon/leggy.rsi/up.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |