FlashLightVisualizer refactor + low power handheld light light radius fix (#11768)
* refactor: Removes FlashLightVisualizer (based on obsolete code) in favor or merging its functionality with HandheldLightComponent fix: Low power lighting radius animations for lanterns, floodlights and flashlights now properly restore the original light radius when going back to full power * refactor: Use the LightBehaviour component to animate HandheldLights refactor: Remove unneeded HandheldLight definitions in some yaml files (already inherited by parents) fix: Properly change the server side PointLightComponent Enabled property when turning HandheldLights on/off feat: ReverseWhenFinished property on Fade light behaviours * Empty commit to rerun CI with the new engine PR * fix: Restore the correct HandheldLight addPrefix property, whoops * refactor: blinkingBehaviourID -> blinkingBehaviourId, radiatingBehaviourID -> radiatingBehaviourId
This commit is contained in:
@@ -177,6 +177,14 @@ namespace Content.Client.Light.Components
|
||||
[UsedImplicitly]
|
||||
public sealed class FadeBehaviour : LightBehaviourAnimationTrack
|
||||
{
|
||||
/// <summary>
|
||||
/// Automatically reverse the animation when EndValue is reached. In this particular case, MaxTime specifies the
|
||||
/// time of the full animation, including the reverse interpolation.
|
||||
/// </summary>
|
||||
[DataField("reverseWhenFinished")]
|
||||
[ViewVariables]
|
||||
public bool ReverseWhenFinished { get; set; }
|
||||
|
||||
public override (int KeyFrameIndex, float FramePlayingTime) AdvancePlayback(
|
||||
object context, int prevKeyFrameIndex, float prevPlayingTime, float frameTime)
|
||||
{
|
||||
@@ -189,22 +197,42 @@ namespace Content.Client.Light.Components
|
||||
return (-1, playingTime);
|
||||
}
|
||||
|
||||
switch (InterpolateMode)
|
||||
// From 0 to MaxTime/2, we go from StartValue to EndValue. From MaxTime/2 to MaxTime, we reverse this interpolation.
|
||||
if (ReverseWhenFinished)
|
||||
{
|
||||
case AnimationInterpolationMode.Linear:
|
||||
ApplyProperty(InterpolateLinear(StartValue, EndValue, interpolateValue));
|
||||
break;
|
||||
case AnimationInterpolationMode.Cubic:
|
||||
ApplyProperty(InterpolateCubic(EndValue, StartValue, EndValue, StartValue, interpolateValue));
|
||||
break;
|
||||
default:
|
||||
case AnimationInterpolationMode.Nearest:
|
||||
ApplyProperty(interpolateValue < 0.5f ? StartValue : EndValue);
|
||||
break;
|
||||
if (interpolateValue < 0.5f)
|
||||
{
|
||||
ApplyInterpolation(StartValue, EndValue, interpolateValue*2);
|
||||
}
|
||||
else
|
||||
{
|
||||
ApplyInterpolation(EndValue, StartValue, (interpolateValue-0.5f)*2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ApplyInterpolation(StartValue, EndValue, interpolateValue);
|
||||
}
|
||||
|
||||
return (-1, playingTime);
|
||||
}
|
||||
|
||||
private void ApplyInterpolation(float start, float end, float interpolateValue)
|
||||
{
|
||||
switch (InterpolateMode)
|
||||
{
|
||||
case AnimationInterpolationMode.Linear:
|
||||
ApplyProperty(InterpolateLinear(start, end, interpolateValue));
|
||||
break;
|
||||
case AnimationInterpolationMode.Cubic:
|
||||
ApplyProperty(InterpolateCubic(end, start, end, start, interpolateValue));
|
||||
break;
|
||||
default:
|
||||
case AnimationInterpolationMode.Nearest:
|
||||
ApplyProperty(interpolateValue < 0.5f ? start : end);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -369,11 +397,8 @@ namespace Content.Client.Light.Components
|
||||
[ViewVariables(VVAccess.ReadOnly)]
|
||||
private readonly List<AnimationContainer> _animations = new();
|
||||
|
||||
private float _originalRadius;
|
||||
private float _originalEnergy;
|
||||
private Angle _originalRotation;
|
||||
private Color _originalColor;
|
||||
private bool _originalEnabled;
|
||||
[ViewVariables(VVAccess.ReadOnly)]
|
||||
private Dictionary<string, object> _originalPropertyValues = new();
|
||||
|
||||
void ISerializationHooks.AfterDeserialization()
|
||||
{
|
||||
@@ -395,8 +420,6 @@ namespace Content.Client.Light.Components
|
||||
{
|
||||
base.Startup();
|
||||
|
||||
CopyLightSettings();
|
||||
|
||||
// TODO: Do NOT ensure component here. And use eventbus events instead...
|
||||
Owner.EnsureComponent<AnimationPlayerComponent>();
|
||||
|
||||
@@ -445,15 +468,15 @@ namespace Content.Client.Light.Components
|
||||
/// <summary>
|
||||
/// If we disable all the light behaviours we want to be able to revert the light to its original state.
|
||||
/// </summary>
|
||||
private void CopyLightSettings()
|
||||
private void CopyLightSettings(string property)
|
||||
{
|
||||
if (_entMan.TryGetComponent(Owner, out PointLightComponent? light))
|
||||
{
|
||||
_originalColor = light.Color;
|
||||
_originalEnabled = light.Enabled;
|
||||
_originalEnergy = light.Energy;
|
||||
_originalRadius = light.Radius;
|
||||
_originalRotation = light.Rotation;
|
||||
var propertyValue = AnimationHelper.GetAnimatableProperty(light, property);
|
||||
if (propertyValue != null)
|
||||
{
|
||||
_originalPropertyValues.Add(property, propertyValue);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -479,6 +502,7 @@ namespace Content.Client.Light.Components
|
||||
{
|
||||
if (!animation.HasRunningAnimation(KeyPrefix + container.Key))
|
||||
{
|
||||
CopyLightSettings(container.LightBehaviour.Property);
|
||||
container.LightBehaviour.UpdatePlaybackValues(container.Animation);
|
||||
animation.Play(container.Animation, KeyPrefix + container.Key);
|
||||
}
|
||||
@@ -526,12 +550,27 @@ namespace Content.Client.Light.Components
|
||||
|
||||
if (resetToOriginalSettings && _entMan.TryGetComponent(Owner, out PointLightComponent? light))
|
||||
{
|
||||
light.Color = _originalColor;
|
||||
light.Enabled = _originalEnabled;
|
||||
light.Energy = _originalEnergy;
|
||||
light.Radius = _originalRadius;
|
||||
light.Rotation = _originalRotation;
|
||||
foreach (var (property, value) in _originalPropertyValues)
|
||||
{
|
||||
AnimationHelper.SetAnimatableProperty(light, property, value);
|
||||
}
|
||||
}
|
||||
|
||||
_originalPropertyValues.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if at least one behaviour is running.
|
||||
/// </summary>
|
||||
/// <returns>Whether at least one behaviour is running, false if none is.</returns>
|
||||
public bool HasRunningBehaviours()
|
||||
{
|
||||
if (!_entMan.TryGetComponent(Owner, out AnimationPlayerComponent? animation))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return _animations.Any(container => animation.HasRunningAnimation(KeyPrefix + container.Key));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
using Content.Client.Items;
|
||||
using Content.Client.Light.Components;
|
||||
using Content.Shared.Light;
|
||||
using Content.Shared.Light.Component;
|
||||
using Content.Shared.Toggleable;
|
||||
using Robust.Client.Animations;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Shared.Animations;
|
||||
|
||||
namespace Content.Client.Light;
|
||||
|
||||
@@ -12,10 +15,56 @@ public sealed class HandheldLightSystem : SharedHandheldLightSystem
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<HandheldLightComponent, ItemStatusCollectMessage>(OnGetStatusControl);
|
||||
SubscribeLocalEvent<HandheldLightComponent, AppearanceChangeEvent>(OnAppearanceChange);
|
||||
}
|
||||
|
||||
private static void OnGetStatusControl(EntityUid uid, HandheldLightComponent component, ItemStatusCollectMessage args)
|
||||
{
|
||||
args.Controls.Add(new HandheldLightStatus(component));
|
||||
}
|
||||
|
||||
private void OnAppearanceChange(EntityUid uid, HandheldLightComponent? component, ref AppearanceChangeEvent args)
|
||||
{
|
||||
if (!Resolve(uid, ref component))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!args.Component.TryGetData(ToggleableLightVisuals.Enabled, out bool enabled))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!args.Component.TryGetData(HandheldLightVisuals.Power,
|
||||
out HandheldLightPowerStates state))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (TryComp<LightBehaviourComponent>(uid, out var lightBehaviour))
|
||||
{
|
||||
// Reset any running behaviour to reset the animated properties back to the original value, to avoid conflicts between resets
|
||||
if (lightBehaviour.HasRunningBehaviours())
|
||||
{
|
||||
lightBehaviour.StopLightBehaviour(resetToOriginalSettings: true);
|
||||
}
|
||||
|
||||
if (!enabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case HandheldLightPowerStates.FullPower:
|
||||
break; // We just needed to reset all behaviours
|
||||
case HandheldLightPowerStates.LowPower:
|
||||
lightBehaviour.StartLightBehaviour(component.RadiatingBehaviourId);
|
||||
break;
|
||||
case HandheldLightPowerStates.Dying:
|
||||
lightBehaviour.StartLightBehaviour(component.BlinkingBehaviourId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
using System;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.Animations;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Shared.Animations;
|
||||
using Robust.Shared.GameObjects;
|
||||
|
||||
namespace Content.Client.Light
|
||||
{
|
||||
[UsedImplicitly]
|
||||
public sealed class LanternVisualizer : AppearanceVisualizer
|
||||
{
|
||||
private readonly Animation _radiatingLightAnimation = new()
|
||||
{
|
||||
Length = TimeSpan.FromSeconds(5),
|
||||
AnimationTracks =
|
||||
{
|
||||
new AnimationTrackComponentProperty
|
||||
{
|
||||
ComponentType = typeof(PointLightComponent),
|
||||
InterpolationMode = AnimationInterpolationMode.Linear,
|
||||
Property = nameof(PointLightComponent.Radius),
|
||||
KeyFrames =
|
||||
{
|
||||
new AnimationTrackProperty.KeyFrame(3.0f, 0),
|
||||
new AnimationTrackProperty.KeyFrame(2.0f, 1.5f),
|
||||
new AnimationTrackProperty.KeyFrame(3.0f, 3f)
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
[Obsolete("Subscribe to AppearanceChangeEvent instead.")]
|
||||
public override void OnChangeData(AppearanceComponent component)
|
||||
{
|
||||
base.OnChangeData(component);
|
||||
|
||||
if (!component.Initialized)
|
||||
return;
|
||||
|
||||
PlayAnimation(component);
|
||||
}
|
||||
|
||||
private void PlayAnimation(AppearanceComponent component)
|
||||
{
|
||||
component.Owner.EnsureComponent(out AnimationPlayerComponent animationPlayer);
|
||||
if (animationPlayer.HasRunningAnimation("radiatingLight")) return;
|
||||
animationPlayer.Play(_radiatingLightAnimation, "radiatingLight");
|
||||
animationPlayer.AnimationCompleted += s => animationPlayer.Play(_radiatingLightAnimation, s);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,115 +0,0 @@
|
||||
using System;
|
||||
using Content.Shared.Light;
|
||||
using Content.Shared.Light.Component;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.Animations;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Shared.Animations;
|
||||
using Robust.Shared.GameObjects;
|
||||
|
||||
namespace Content.Client.Light.Visualizers
|
||||
{
|
||||
[UsedImplicitly]
|
||||
public sealed class FlashLightVisualizer : AppearanceVisualizer
|
||||
{
|
||||
private readonly Animation _radiatingLightAnimation = new()
|
||||
{
|
||||
Length = TimeSpan.FromSeconds(1),
|
||||
AnimationTracks =
|
||||
{
|
||||
new AnimationTrackComponentProperty
|
||||
{
|
||||
ComponentType = typeof(PointLightComponent),
|
||||
InterpolationMode = AnimationInterpolationMode.Linear,
|
||||
Property = nameof(PointLightComponent.Radius),
|
||||
KeyFrames =
|
||||
{
|
||||
new AnimationTrackProperty.KeyFrame(3.0f, 0),
|
||||
new AnimationTrackProperty.KeyFrame(2.0f, 0.5f),
|
||||
new AnimationTrackProperty.KeyFrame(3.0f, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private readonly Animation _blinkingLightAnimation = new()
|
||||
{
|
||||
Length = TimeSpan.FromSeconds(1),
|
||||
AnimationTracks =
|
||||
{
|
||||
new AnimationTrackComponentProperty()
|
||||
{
|
||||
ComponentType = typeof(PointLightComponent),
|
||||
//To create the blinking effect we go from nearly zero radius, to the light radius, and back
|
||||
//We do this instead of messing with the `PointLightComponent.enabled` because we don't want the animation to affect component behavior
|
||||
InterpolationMode = AnimationInterpolationMode.Nearest,
|
||||
Property = nameof(PointLightComponent.Radius),
|
||||
KeyFrames =
|
||||
{
|
||||
new AnimationTrackProperty.KeyFrame(0.1f, 0),
|
||||
new AnimationTrackProperty.KeyFrame(2f, 0.5f),
|
||||
new AnimationTrackProperty.KeyFrame(0.1f, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private Action<string>? _radiatingCallback;
|
||||
private Action<string>? _blinkingCallback;
|
||||
|
||||
[Obsolete("Subscribe to AppearanceChangeEvent instead.")]
|
||||
public override void OnChangeData(AppearanceComponent component)
|
||||
{
|
||||
base.OnChangeData(component);
|
||||
|
||||
if (component.TryGetData(HandheldLightVisuals.Power,
|
||||
out HandheldLightPowerStates state))
|
||||
{
|
||||
PlayAnimation(component, state);
|
||||
}
|
||||
}
|
||||
|
||||
private void PlayAnimation(AppearanceComponent component, HandheldLightPowerStates state)
|
||||
{
|
||||
component.Owner.EnsureComponent(out AnimationPlayerComponent animationPlayer);
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case HandheldLightPowerStates.LowPower:
|
||||
if (!animationPlayer.HasRunningAnimation("radiatingLight"))
|
||||
{
|
||||
animationPlayer.Play(_radiatingLightAnimation, "radiatingLight");
|
||||
_radiatingCallback = (s) => animationPlayer.Play(_radiatingLightAnimation, s);
|
||||
animationPlayer.AnimationCompleted += _radiatingCallback;
|
||||
}
|
||||
|
||||
break;
|
||||
case HandheldLightPowerStates.Dying:
|
||||
animationPlayer.Stop("radiatingLight");
|
||||
animationPlayer.AnimationCompleted -= _radiatingCallback;
|
||||
if (!animationPlayer.HasRunningAnimation("blinkingLight"))
|
||||
{
|
||||
animationPlayer.Play(_blinkingLightAnimation, "blinkingLight");
|
||||
_blinkingCallback = (s) => animationPlayer.Play(_blinkingLightAnimation, s);
|
||||
animationPlayer.AnimationCompleted += _blinkingCallback;
|
||||
}
|
||||
|
||||
break;
|
||||
case HandheldLightPowerStates.FullPower:
|
||||
if (animationPlayer.HasRunningAnimation("blinkingLight"))
|
||||
{
|
||||
animationPlayer.Stop("blinkingLight");
|
||||
animationPlayer.AnimationCompleted -= _blinkingCallback;
|
||||
}
|
||||
|
||||
if (animationPlayer.HasRunningAnimation("radiatingLight"))
|
||||
{
|
||||
animationPlayer.Stop("radiatingLight");
|
||||
animationPlayer.AnimationCompleted -= _radiatingCallback;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -187,8 +187,12 @@ namespace Content.Server.Light.EntitySystems
|
||||
|
||||
public bool TurnOff(HandheldLightComponent component, bool makeNoise = true)
|
||||
{
|
||||
if (!component.Activated) return false;
|
||||
if (!component.Activated || !TryComp<PointLightComponent>(component.Owner, out var pointLightComponent))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
pointLightComponent.Enabled = false;
|
||||
SetActivated(component.Owner, false, component, makeNoise);
|
||||
component.Level = null;
|
||||
_activeLights.Remove(component);
|
||||
@@ -197,7 +201,10 @@ namespace Content.Server.Light.EntitySystems
|
||||
|
||||
public bool TurnOn(EntityUid user, HandheldLightComponent component)
|
||||
{
|
||||
if (component.Activated) return false;
|
||||
if (component.Activated || !TryComp<PointLightComponent>(component.Owner, out var pointLightComponent))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!_powerCell.TryGetBatteryFromSlot(component.Owner, out var battery) &&
|
||||
!TryComp(component.Owner, out battery))
|
||||
@@ -217,6 +224,7 @@ namespace Content.Server.Light.EntitySystems
|
||||
return false;
|
||||
}
|
||||
|
||||
pointLightComponent.Enabled = true;
|
||||
SetActivated(component.Owner, true, component, true);
|
||||
_activeLights.Add(component);
|
||||
|
||||
|
||||
@@ -45,6 +45,20 @@ namespace Content.Shared.Light
|
||||
|
||||
public const int StatusLevels = 6;
|
||||
|
||||
/// <summary>
|
||||
/// Specify the ID of the light behaviour to use when the state of the light is Dying
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
[DataField("blinkingBehaviourId")]
|
||||
public string BlinkingBehaviourId { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Specify the ID of the light behaviour to use when the state of the light is LowPower
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
[DataField("radiatingBehaviourId")]
|
||||
public string RadiatingBehaviourId { get; set; } = string.Empty;
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class HandheldLightComponentState : ComponentState
|
||||
{
|
||||
|
||||
@@ -54,10 +54,31 @@
|
||||
mask: /Textures/Effects/LightMasks/cone.png
|
||||
autoRot: true
|
||||
- type: Appearance
|
||||
visuals:
|
||||
- type: FlashLightVisualizer
|
||||
- type: HandheldLight
|
||||
addPrefix: true
|
||||
blinkingBehaviourId: blinking
|
||||
radiatingBehaviourId: radiating
|
||||
- type: LightBehaviour
|
||||
behaviours:
|
||||
- !type:FadeBehaviour
|
||||
id: radiating
|
||||
interpolate: Linear
|
||||
maxDuration: 2.0
|
||||
startValue: 3.0
|
||||
endValue: 2.0
|
||||
isLooped: true
|
||||
property: Radius
|
||||
enabled: false
|
||||
reverseWhenFinished: true
|
||||
- !type:PulseBehaviour
|
||||
id: blinking
|
||||
interpolate: Nearest
|
||||
maxDuration: 1.0
|
||||
minValue: 0.1
|
||||
maxValue: 2.0
|
||||
isLooped: true
|
||||
property: Radius
|
||||
enabled: false
|
||||
- type: PowerCellSlot
|
||||
cellSlotId: cell_slot
|
||||
- type: ItemSlots
|
||||
@@ -155,10 +176,31 @@
|
||||
mask: /Textures/Effects/LightMasks/cone.png
|
||||
autoRot: true
|
||||
- type: Appearance
|
||||
visuals:
|
||||
- type: FlashLightVisualizer
|
||||
- type: HandheldLight
|
||||
addPrefix: true
|
||||
blinkingBehaviourId: blinking
|
||||
radiatingBehaviourId: radiating
|
||||
- type: LightBehaviour
|
||||
behaviours:
|
||||
- !type:FadeBehaviour
|
||||
id: radiating
|
||||
interpolate: Linear
|
||||
maxDuration: 2.0
|
||||
startValue: 3.0
|
||||
endValue: 2.0
|
||||
isLooped: true
|
||||
property: Radius
|
||||
enabled: false
|
||||
reverseWhenFinished: true
|
||||
- !type:PulseBehaviour
|
||||
id: blinking
|
||||
interpolate: Nearest
|
||||
maxDuration: 1.0
|
||||
minValue: 0.1
|
||||
maxValue: 2.0
|
||||
isLooped: true
|
||||
property: Radius
|
||||
enabled: false
|
||||
- type: Battery
|
||||
maxCharge: 600 #lights drain 3/s but recharge of 2 makes this 1/s. Therefore 600 is 10 minutes of light.
|
||||
startingCharge: 600
|
||||
|
||||
@@ -20,10 +20,31 @@
|
||||
autoRot: true
|
||||
radius: 3
|
||||
- type: Appearance
|
||||
visuals:
|
||||
- type: FlashLightVisualizer
|
||||
- type: HandheldLight
|
||||
addPrefix: false
|
||||
blinkingBehaviourId: blinking
|
||||
radiatingBehaviourId: radiating
|
||||
- type: LightBehaviour
|
||||
behaviours:
|
||||
- !type:FadeBehaviour
|
||||
id: radiating
|
||||
interpolate: Linear
|
||||
maxDuration: 2.0
|
||||
startValue: 3.0
|
||||
endValue: 2.0
|
||||
isLooped: true
|
||||
property: Radius
|
||||
enabled: false
|
||||
reverseWhenFinished: true
|
||||
- !type:PulseBehaviour
|
||||
id: blinking
|
||||
interpolate: Nearest
|
||||
maxDuration: 1.0
|
||||
minValue: 0.1
|
||||
maxValue: 2.0
|
||||
isLooped: true
|
||||
property: Radius
|
||||
enabled: false
|
||||
- type: ToggleableLightVisuals
|
||||
spriteLayer: light
|
||||
inhandVisuals:
|
||||
|
||||
@@ -6,6 +6,29 @@
|
||||
components:
|
||||
- type: HandheldLight
|
||||
addPrefix: true
|
||||
blinkingBehaviourId: blinking
|
||||
radiatingBehaviourId: radiating
|
||||
- type: LightBehaviour
|
||||
behaviours:
|
||||
- !type:FadeBehaviour
|
||||
id: radiating
|
||||
interpolate: Linear
|
||||
maxDuration: 2.0
|
||||
startValue: 3.0
|
||||
endValue: 2.0
|
||||
isLooped: true
|
||||
property: Radius
|
||||
enabled: false
|
||||
reverseWhenFinished: true
|
||||
- !type:PulseBehaviour
|
||||
id: blinking
|
||||
interpolate: Nearest
|
||||
maxDuration: 1.0
|
||||
minValue: 0.1
|
||||
maxValue: 2.0
|
||||
isLooped: true
|
||||
property: Radius
|
||||
enabled: false
|
||||
- type: PowerCellSlot
|
||||
cellSlotId: cell_slot
|
||||
- type: ItemSlots
|
||||
@@ -29,8 +52,6 @@
|
||||
energy: 2
|
||||
- type: ToggleableLightVisuals
|
||||
- type: Appearance
|
||||
visuals:
|
||||
- type: FlashLightVisualizer # todo move to light visuals component.
|
||||
|
||||
- type: entity
|
||||
name: lamp
|
||||
|
||||
@@ -10,6 +10,29 @@
|
||||
- DroneUsable
|
||||
- type: HandheldLight
|
||||
addPrefix: false
|
||||
blinkingBehaviourId: blinking
|
||||
radiatingBehaviourId: radiating
|
||||
- type: LightBehaviour
|
||||
behaviours:
|
||||
- !type:FadeBehaviour
|
||||
id: radiating
|
||||
interpolate: Linear
|
||||
maxDuration: 2.0
|
||||
startValue: 3.0
|
||||
endValue: 2.0
|
||||
isLooped: true
|
||||
property: Radius
|
||||
enabled: false
|
||||
reverseWhenFinished: true
|
||||
- !type:PulseBehaviour
|
||||
id: blinking
|
||||
interpolate: Nearest
|
||||
maxDuration: 1.0
|
||||
minValue: 0.1
|
||||
maxValue: 2.0
|
||||
isLooped: true
|
||||
property: Radius
|
||||
enabled: false
|
||||
toggleAction:
|
||||
name: action-name-toggle-light
|
||||
description: action-description-toggle-light
|
||||
@@ -53,8 +76,6 @@
|
||||
autoRot: true
|
||||
radius: 4.5
|
||||
- type: Appearance
|
||||
visuals:
|
||||
- type: FlashLightVisualizer
|
||||
- type: StaticPrice
|
||||
price: 40
|
||||
|
||||
|
||||
@@ -6,6 +6,29 @@
|
||||
components:
|
||||
- type: HandheldLight
|
||||
addPrefix: true
|
||||
blinkingBehaviourId: blinking
|
||||
radiatingBehaviourId: radiating
|
||||
- type: LightBehaviour
|
||||
behaviours:
|
||||
- !type:FadeBehaviour
|
||||
id: radiating
|
||||
interpolate: Linear
|
||||
maxDuration: 2.0
|
||||
startValue: 3.0
|
||||
endValue: 2.0
|
||||
isLooped: true
|
||||
property: Radius
|
||||
enabled: false
|
||||
reverseWhenFinished: true
|
||||
- !type:PulseBehaviour
|
||||
id: blinking
|
||||
interpolate: Nearest
|
||||
maxDuration: 1.0
|
||||
minValue: 0.1
|
||||
maxValue: 2.0
|
||||
isLooped: true
|
||||
property: Radius
|
||||
enabled: false
|
||||
- type: Sprite
|
||||
sprite: Objects/Tools/lantern.rsi
|
||||
layers:
|
||||
@@ -24,8 +47,6 @@
|
||||
energy: 2.5
|
||||
color: "#FFC458"
|
||||
- type: Appearance
|
||||
visuals:
|
||||
- type: LanternVisualizer
|
||||
- type: ToggleableLightVisuals
|
||||
- type: PowerCellSlot
|
||||
cellSlotId: cell_slot
|
||||
|
||||
Reference in New Issue
Block a user