Item status!
@@ -33,4 +33,7 @@
|
|||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
<ProjectReference Include="..\Content.Shared\Content.Shared.csproj" />
|
<ProjectReference Include="..\Content.Shared\Content.Shared.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="Animations" />
|
||||||
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -74,7 +74,6 @@ namespace Content.Client
|
|||||||
"Wirecutter",
|
"Wirecutter",
|
||||||
"Screwdriver",
|
"Screwdriver",
|
||||||
"Multitool",
|
"Multitool",
|
||||||
"Welder",
|
|
||||||
"Wrench",
|
"Wrench",
|
||||||
"Crowbar",
|
"Crowbar",
|
||||||
"HitscanWeapon",
|
"HitscanWeapon",
|
||||||
@@ -82,7 +81,6 @@ namespace Content.Client
|
|||||||
"Projectile",
|
"Projectile",
|
||||||
"MeleeWeapon",
|
"MeleeWeapon",
|
||||||
"Storeable",
|
"Storeable",
|
||||||
"Stack",
|
|
||||||
"Dice",
|
"Dice",
|
||||||
"Construction",
|
"Construction",
|
||||||
"Apc",
|
"Apc",
|
||||||
@@ -90,12 +88,10 @@ namespace Content.Client
|
|||||||
"PoweredLight",
|
"PoweredLight",
|
||||||
"Smes",
|
"Smes",
|
||||||
"Powercell",
|
"Powercell",
|
||||||
"HandheldLight",
|
|
||||||
"LightBulb",
|
"LightBulb",
|
||||||
"Healing",
|
"Healing",
|
||||||
"Catwalk",
|
"Catwalk",
|
||||||
"BallisticMagazine",
|
"BallisticMagazine",
|
||||||
"BallisticMagazineWeapon",
|
|
||||||
"BallisticBullet",
|
"BallisticBullet",
|
||||||
"HitscanWeaponCapacitor",
|
"HitscanWeaponCapacitor",
|
||||||
"PowerCell",
|
"PowerCell",
|
||||||
|
|||||||
106
Content.Client/GameObjects/Components/HandheldLightComponent.cs
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
using System;
|
||||||
|
using Content.Shared.GameObjects.Components;
|
||||||
|
using Robust.Client.Graphics.Drawing;
|
||||||
|
using Robust.Client.UserInterface;
|
||||||
|
using Robust.Client.UserInterface.Controls;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.Maths;
|
||||||
|
using Robust.Shared.Timing;
|
||||||
|
using Robust.Shared.ViewVariables;
|
||||||
|
|
||||||
|
namespace Content.Client.GameObjects.Components
|
||||||
|
{
|
||||||
|
[RegisterComponent]
|
||||||
|
public sealed class HandheldLightComponent : SharedHandheldLightComponent, IItemStatus
|
||||||
|
{
|
||||||
|
[ViewVariables] public float? Charge { get; private set; }
|
||||||
|
|
||||||
|
public Control MakeControl()
|
||||||
|
{
|
||||||
|
return new StatusControl(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void HandleComponentState(ComponentState curState, ComponentState nextState)
|
||||||
|
{
|
||||||
|
var cast = (HandheldLightComponentState) curState;
|
||||||
|
|
||||||
|
Charge = cast.Charge;
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed class StatusControl : Control
|
||||||
|
{
|
||||||
|
private const float TimerCycle = 1;
|
||||||
|
|
||||||
|
private readonly HandheldLightComponent _parent;
|
||||||
|
private readonly PanelContainer[] _sections = new PanelContainer[5];
|
||||||
|
|
||||||
|
private float _timer;
|
||||||
|
|
||||||
|
private static readonly StyleBoxFlat _styleBoxLit = new StyleBoxFlat
|
||||||
|
{
|
||||||
|
BackgroundColor = Color.Green
|
||||||
|
};
|
||||||
|
|
||||||
|
private static readonly StyleBoxFlat _styleBoxUnlit = new StyleBoxFlat
|
||||||
|
{
|
||||||
|
BackgroundColor = Color.Black
|
||||||
|
};
|
||||||
|
|
||||||
|
public StatusControl(HandheldLightComponent parent)
|
||||||
|
{
|
||||||
|
_parent = parent;
|
||||||
|
|
||||||
|
var wrapper = new HBoxContainer
|
||||||
|
{
|
||||||
|
SeparationOverride = 4,
|
||||||
|
SizeFlagsHorizontal = SizeFlags.ShrinkCenter
|
||||||
|
};
|
||||||
|
|
||||||
|
AddChild(wrapper);
|
||||||
|
|
||||||
|
for (var i = 0; i < _sections.Length; i++)
|
||||||
|
{
|
||||||
|
var panel = new PanelContainer {CustomMinimumSize = (20, 20)};
|
||||||
|
wrapper.AddChild(panel);
|
||||||
|
_sections[i] = panel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Update(FrameEventArgs args)
|
||||||
|
{
|
||||||
|
base.Update(args);
|
||||||
|
|
||||||
|
_timer += args.DeltaSeconds;
|
||||||
|
_timer %= TimerCycle;
|
||||||
|
|
||||||
|
var charge = _parent.Charge ?? 0;
|
||||||
|
|
||||||
|
int level;
|
||||||
|
|
||||||
|
if (FloatMath.CloseTo(charge, 0))
|
||||||
|
{
|
||||||
|
level = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
level = 1 + (int) MathF.Round(charge * 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (level == 1)
|
||||||
|
{
|
||||||
|
// Flash the last light.
|
||||||
|
_sections[0].PanelOverride = _timer > TimerCycle / 2 ? _styleBoxLit : _styleBoxUnlit;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_sections[0].PanelOverride = level > 2 ? _styleBoxLit : _styleBoxUnlit;
|
||||||
|
}
|
||||||
|
|
||||||
|
_sections[1].PanelOverride = level > 3 ? _styleBoxLit : _styleBoxUnlit;
|
||||||
|
_sections[2].PanelOverride = level > 4 ? _styleBoxLit : _styleBoxUnlit;
|
||||||
|
_sections[3].PanelOverride = level > 5 ? _styleBoxLit : _styleBoxUnlit;
|
||||||
|
_sections[4].PanelOverride = level > 6 ? _styleBoxLit : _styleBoxUnlit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
33
Content.Client/GameObjects/Components/IItemStatus.cs
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
using Robust.Client.UserInterface;
|
||||||
|
|
||||||
|
namespace Content.Client.GameObjects.Components
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Allows a component to provide status tooltips next to the hands interface.
|
||||||
|
/// </summary>
|
||||||
|
public interface IItemStatus
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Called to get a control that represents the status for this component.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>
|
||||||
|
/// The control to render as status.
|
||||||
|
/// </returns>
|
||||||
|
public Control MakeControl();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called when the item no longer needs this status (say, dropped from hand)
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>
|
||||||
|
/// Useful to allow you to drop the control for the GC, if you need to.
|
||||||
|
/// </para>
|
||||||
|
/// <para>
|
||||||
|
/// Note that this may be called after a second invocation of <see cref="MakeControl"/> (for example if the user switches the item between two hands).
|
||||||
|
/// </para>
|
||||||
|
/// </remarks>
|
||||||
|
public void DestroyControl(Control control)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
|
||||||
|
namespace Content.Client.GameObjects
|
||||||
|
{
|
||||||
|
[RegisterComponent]
|
||||||
|
public class ItemStatusComponent : Component
|
||||||
|
{
|
||||||
|
public override string Name => "ItemStatus";
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
60
Content.Client/GameObjects/Components/StackComponent.cs
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
using Content.Client.UserInterface;
|
||||||
|
using Content.Client.Utility;
|
||||||
|
using Content.Shared.GameObjects.Components;
|
||||||
|
using Robust.Client.UserInterface;
|
||||||
|
using Robust.Client.UserInterface.Controls;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.Localization;
|
||||||
|
using Robust.Shared.Timing;
|
||||||
|
using Robust.Shared.ViewVariables;
|
||||||
|
|
||||||
|
namespace Content.Client.GameObjects.Components
|
||||||
|
{
|
||||||
|
[RegisterComponent]
|
||||||
|
public class StackComponent : SharedStackComponent, IItemStatus
|
||||||
|
{
|
||||||
|
[ViewVariables] public int Count { get; private set; }
|
||||||
|
[ViewVariables] public int MaxCount { get; private set; }
|
||||||
|
|
||||||
|
[ViewVariables(VVAccess.ReadWrite)] private bool _uiUpdateNeeded;
|
||||||
|
|
||||||
|
public Control MakeControl() => new StatusControl(this);
|
||||||
|
|
||||||
|
public override void HandleComponentState(ComponentState curState, ComponentState nextState)
|
||||||
|
{
|
||||||
|
var cast = (StackComponentState) curState;
|
||||||
|
|
||||||
|
Count = cast.Count;
|
||||||
|
MaxCount = cast.MaxCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed class StatusControl : Control
|
||||||
|
{
|
||||||
|
private readonly StackComponent _parent;
|
||||||
|
private readonly RichTextLabel _label;
|
||||||
|
|
||||||
|
public StatusControl(StackComponent parent)
|
||||||
|
{
|
||||||
|
_parent = parent;
|
||||||
|
_label = new RichTextLabel {StyleClasses = {NanoStyle.StyleClassItemStatus}};
|
||||||
|
AddChild(_label);
|
||||||
|
|
||||||
|
parent._uiUpdateNeeded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Update(FrameEventArgs args)
|
||||||
|
{
|
||||||
|
base.Update(args);
|
||||||
|
|
||||||
|
if (!_parent._uiUpdateNeeded)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_parent._uiUpdateNeeded = false;
|
||||||
|
|
||||||
|
_label.SetMarkup(Loc.GetString("Count: [color=white]{0}[/color]", _parent.Count));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,284 @@
|
|||||||
|
using System;
|
||||||
|
using Content.Client.Animations;
|
||||||
|
using Content.Client.UserInterface;
|
||||||
|
using Content.Client.Utility;
|
||||||
|
using Content.Shared.GameObjects;
|
||||||
|
using Content.Shared.GameObjects.Components.Weapons.Ranged;
|
||||||
|
using Robust.Client.Animations;
|
||||||
|
using Robust.Client.Graphics;
|
||||||
|
using Robust.Client.UserInterface;
|
||||||
|
using Robust.Client.UserInterface.Controls;
|
||||||
|
using Robust.Shared.Animations;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
|
using Robust.Shared.Interfaces.Network;
|
||||||
|
using Robust.Shared.Maths;
|
||||||
|
using Robust.Shared.Serialization;
|
||||||
|
using Robust.Shared.ViewVariables;
|
||||||
|
using static Content.Client.StaticIoC;
|
||||||
|
|
||||||
|
namespace Content.Client.GameObjects.Components.Weapons.Ranged
|
||||||
|
{
|
||||||
|
[RegisterComponent]
|
||||||
|
public class BallisticMagazineWeaponComponent : Component, IItemStatus
|
||||||
|
{
|
||||||
|
private static readonly Animation AlarmAnimationSmg = new Animation
|
||||||
|
{
|
||||||
|
Length = TimeSpan.FromSeconds(1.4),
|
||||||
|
AnimationTracks =
|
||||||
|
{
|
||||||
|
new AnimationTrackControlProperty
|
||||||
|
{
|
||||||
|
// These timings match the SMG audio file.
|
||||||
|
Property = nameof(Label.FontColorOverride),
|
||||||
|
InterpolationMode = AnimationInterpolationMode.Previous,
|
||||||
|
KeyFrames =
|
||||||
|
{
|
||||||
|
new AnimationTrackProperty.KeyFrame(Color.Red, 0.1f),
|
||||||
|
new AnimationTrackProperty.KeyFrame(null, 0.3f),
|
||||||
|
new AnimationTrackProperty.KeyFrame(Color.Red, 0.2f),
|
||||||
|
new AnimationTrackProperty.KeyFrame(null, 0.3f),
|
||||||
|
new AnimationTrackProperty.KeyFrame(Color.Red, 0.2f),
|
||||||
|
new AnimationTrackProperty.KeyFrame(null, 0.3f),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private static readonly Animation AlarmAnimationLmg = new Animation
|
||||||
|
{
|
||||||
|
Length = TimeSpan.FromSeconds(0.75),
|
||||||
|
AnimationTracks =
|
||||||
|
{
|
||||||
|
new AnimationTrackControlProperty
|
||||||
|
{
|
||||||
|
// These timings match the SMG audio file.
|
||||||
|
Property = nameof(Label.FontColorOverride),
|
||||||
|
InterpolationMode = AnimationInterpolationMode.Previous,
|
||||||
|
KeyFrames =
|
||||||
|
{
|
||||||
|
new AnimationTrackProperty.KeyFrame(Color.Red, 0.0f),
|
||||||
|
new AnimationTrackProperty.KeyFrame(null, 0.15f),
|
||||||
|
new AnimationTrackProperty.KeyFrame(Color.Red, 0.15f),
|
||||||
|
new AnimationTrackProperty.KeyFrame(null, 0.15f),
|
||||||
|
new AnimationTrackProperty.KeyFrame(Color.Red, 0.15f),
|
||||||
|
new AnimationTrackProperty.KeyFrame(null, 0.15f),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public override string Name => "BallisticMagazineWeapon";
|
||||||
|
public override uint? NetID => ContentNetIDs.BALLISTIC_MAGAZINE_WEAPON;
|
||||||
|
public override Type StateType => typeof(BallisticMagazineWeaponComponentState);
|
||||||
|
|
||||||
|
private StatusControl _statusControl;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// True if a bullet is chambered.
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables]
|
||||||
|
public bool Chambered { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Count of bullets in the magazine.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Null if no magazine is inserted.
|
||||||
|
/// </remarks>
|
||||||
|
[ViewVariables]
|
||||||
|
public (int count, int max)? MagazineCount { get; private set; }
|
||||||
|
|
||||||
|
[ViewVariables(VVAccess.ReadWrite)] private bool _isLmgAlarmAnimation;
|
||||||
|
|
||||||
|
public override void ExposeData(ObjectSerializer serializer)
|
||||||
|
{
|
||||||
|
base.ExposeData(serializer);
|
||||||
|
|
||||||
|
serializer.DataField(ref _isLmgAlarmAnimation, "lmg_alarm_animation", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void HandleComponentState(ComponentState curState, ComponentState nextState)
|
||||||
|
{
|
||||||
|
var cast = (BallisticMagazineWeaponComponentState) curState;
|
||||||
|
|
||||||
|
Chambered = cast.Chambered;
|
||||||
|
MagazineCount = cast.MagazineCount;
|
||||||
|
_statusControl?.Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void HandleMessage(ComponentMessage message, INetChannel netChannel = null,
|
||||||
|
IComponent component = null)
|
||||||
|
{
|
||||||
|
switch (message)
|
||||||
|
{
|
||||||
|
case BmwComponentAutoEjectedMessage _:
|
||||||
|
_statusControl?.PlayAlarmAnimation();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
base.HandleMessage(message, netChannel, component);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Control MakeControl()
|
||||||
|
{
|
||||||
|
_statusControl = new StatusControl(this);
|
||||||
|
_statusControl.Update();
|
||||||
|
return _statusControl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DestroyControl(Control control)
|
||||||
|
{
|
||||||
|
if (_statusControl == control)
|
||||||
|
{
|
||||||
|
_statusControl = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed class StatusControl : Control
|
||||||
|
{
|
||||||
|
private readonly BallisticMagazineWeaponComponent _parent;
|
||||||
|
private readonly HBoxContainer _bulletsListTop;
|
||||||
|
private readonly HBoxContainer _bulletsListBottom;
|
||||||
|
private readonly TextureRect _chamberedBullet;
|
||||||
|
private readonly Label _noMagazineLabel;
|
||||||
|
|
||||||
|
public StatusControl(BallisticMagazineWeaponComponent parent)
|
||||||
|
{
|
||||||
|
_parent = parent;
|
||||||
|
SizeFlagsHorizontal = SizeFlags.FillExpand;
|
||||||
|
SizeFlagsVertical = SizeFlags.ShrinkCenter;
|
||||||
|
AddChild(new VBoxContainer
|
||||||
|
{
|
||||||
|
SizeFlagsHorizontal = SizeFlags.FillExpand,
|
||||||
|
SizeFlagsVertical = SizeFlags.ShrinkCenter,
|
||||||
|
SeparationOverride = 0,
|
||||||
|
Children =
|
||||||
|
{
|
||||||
|
(_bulletsListTop = new HBoxContainer {SeparationOverride = 0}),
|
||||||
|
new HBoxContainer
|
||||||
|
{
|
||||||
|
SizeFlagsHorizontal = SizeFlags.FillExpand,
|
||||||
|
Children =
|
||||||
|
{
|
||||||
|
new Control
|
||||||
|
{
|
||||||
|
SizeFlagsHorizontal = SizeFlags.FillExpand,
|
||||||
|
Children =
|
||||||
|
{
|
||||||
|
(_bulletsListBottom = new HBoxContainer
|
||||||
|
{
|
||||||
|
SizeFlagsVertical = SizeFlags.ShrinkCenter,
|
||||||
|
SeparationOverride = 0
|
||||||
|
}),
|
||||||
|
(_noMagazineLabel = new Label
|
||||||
|
{
|
||||||
|
Text = "No Magazine!",
|
||||||
|
StyleClasses = {NanoStyle.StyleClassItemStatus}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
(_chamberedBullet = new TextureRect
|
||||||
|
{
|
||||||
|
Texture = ResC.GetTexture("/Textures/UserInterface/status/bullets/chambered.png"),
|
||||||
|
SizeFlagsVertical = SizeFlags.ShrinkCenter,
|
||||||
|
SizeFlagsHorizontal = SizeFlags.ShrinkEnd | SizeFlags.Fill,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Update()
|
||||||
|
{
|
||||||
|
_chamberedBullet.ModulateSelfOverride =
|
||||||
|
_parent.Chambered ? Color.FromHex("#d7df60") : Color.Black;
|
||||||
|
|
||||||
|
_bulletsListTop.RemoveAllChildren();
|
||||||
|
_bulletsListBottom.RemoveAllChildren();
|
||||||
|
|
||||||
|
if (_parent.MagazineCount == null)
|
||||||
|
{
|
||||||
|
_noMagazineLabel.Visible = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var (count, capacity) = _parent.MagazineCount.Value;
|
||||||
|
|
||||||
|
_noMagazineLabel.Visible = false;
|
||||||
|
|
||||||
|
string texturePath;
|
||||||
|
if (capacity <= 20)
|
||||||
|
{
|
||||||
|
texturePath = "/Textures/UserInterface/status/bullets/normal.png";
|
||||||
|
}
|
||||||
|
else if (capacity <= 30)
|
||||||
|
{
|
||||||
|
texturePath = "/Textures/UserInterface/status/bullets/small.png";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
texturePath = "/Textures/UserInterface/status/bullets/tiny.png";
|
||||||
|
}
|
||||||
|
|
||||||
|
var texture = ResC.GetTexture(texturePath);
|
||||||
|
|
||||||
|
const int tinyMaxRow = 60;
|
||||||
|
|
||||||
|
if (capacity > tinyMaxRow)
|
||||||
|
{
|
||||||
|
FillBulletRow(_bulletsListBottom, Math.Min(tinyMaxRow, count), tinyMaxRow, texture);
|
||||||
|
FillBulletRow(_bulletsListTop, Math.Max(0, count - tinyMaxRow), capacity - tinyMaxRow, texture);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FillBulletRow(_bulletsListBottom, count, capacity, texture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void FillBulletRow(Control container, int count, int capacity, Texture texture)
|
||||||
|
{
|
||||||
|
var colorA = Color.FromHex("#b68f0e");
|
||||||
|
var colorB = Color.FromHex("#d7df60");
|
||||||
|
var colorGoneA = Color.FromHex("#000000");
|
||||||
|
var colorGoneB = Color.FromHex("#222222");
|
||||||
|
|
||||||
|
var altColor = false;
|
||||||
|
|
||||||
|
for (var i = count; i < capacity; i++)
|
||||||
|
{
|
||||||
|
container.AddChild(new TextureRect
|
||||||
|
{
|
||||||
|
Texture = texture,
|
||||||
|
ModulateSelfOverride = altColor ? colorGoneA : colorGoneB
|
||||||
|
});
|
||||||
|
|
||||||
|
altColor ^= true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
container.AddChild(new TextureRect
|
||||||
|
{
|
||||||
|
Texture = texture,
|
||||||
|
ModulateSelfOverride = altColor ? colorA : colorB
|
||||||
|
});
|
||||||
|
|
||||||
|
altColor ^= true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Vector2 CalculateMinimumSize()
|
||||||
|
{
|
||||||
|
return Vector2.ComponentMax((0, 15), base.CalculateMinimumSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PlayAlarmAnimation()
|
||||||
|
{
|
||||||
|
var animation = _parent._isLmgAlarmAnimation ? AlarmAnimationLmg : AlarmAnimationSmg;
|
||||||
|
_noMagazineLabel.PlayAnimation(animation, "alarm");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
74
Content.Client/GameObjects/Components/WelderComponent.cs
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
using System;
|
||||||
|
using Content.Client.UserInterface;
|
||||||
|
using Content.Client.Utility;
|
||||||
|
using Content.Shared.GameObjects;
|
||||||
|
using Content.Shared.GameObjects.Components;
|
||||||
|
using Robust.Client.UserInterface;
|
||||||
|
using Robust.Client.UserInterface.Controls;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.Localization;
|
||||||
|
using Robust.Shared.Timing;
|
||||||
|
using Robust.Shared.ViewVariables;
|
||||||
|
|
||||||
|
namespace Content.Client.GameObjects.Components
|
||||||
|
{
|
||||||
|
[RegisterComponent]
|
||||||
|
public class WelderComponent : Component, IItemStatus
|
||||||
|
{
|
||||||
|
public override string Name => "Welder";
|
||||||
|
public override uint? NetID => ContentNetIDs.WELDER;
|
||||||
|
public override Type StateType => typeof(WelderComponentState);
|
||||||
|
|
||||||
|
[ViewVariables] public float FuelCapacity { get; private set; }
|
||||||
|
[ViewVariables] public float Fuel { get; private set; }
|
||||||
|
[ViewVariables] public bool Activated { get; private set; }
|
||||||
|
|
||||||
|
[ViewVariables(VVAccess.ReadWrite)] private bool _uiUpdateNeeded;
|
||||||
|
|
||||||
|
public override void HandleComponentState(ComponentState curState, ComponentState nextState)
|
||||||
|
{
|
||||||
|
var cast = (WelderComponentState) curState;
|
||||||
|
|
||||||
|
FuelCapacity = cast.FuelCapacity;
|
||||||
|
Fuel = cast.Fuel;
|
||||||
|
Activated = cast.Activated;
|
||||||
|
|
||||||
|
_uiUpdateNeeded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Control MakeControl() => new StatusControl(this);
|
||||||
|
|
||||||
|
private sealed class StatusControl : Control
|
||||||
|
{
|
||||||
|
private readonly WelderComponent _parent;
|
||||||
|
private readonly RichTextLabel _label;
|
||||||
|
|
||||||
|
public StatusControl(WelderComponent parent)
|
||||||
|
{
|
||||||
|
_parent = parent;
|
||||||
|
_label = new RichTextLabel {StyleClasses = {NanoStyle.StyleClassItemStatus}};
|
||||||
|
AddChild(_label);
|
||||||
|
|
||||||
|
parent._uiUpdateNeeded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Update(FrameEventArgs args)
|
||||||
|
{
|
||||||
|
base.Update(args);
|
||||||
|
|
||||||
|
if (!_parent._uiUpdateNeeded)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_parent._uiUpdateNeeded = false;
|
||||||
|
|
||||||
|
var fuelCap = _parent.FuelCapacity;
|
||||||
|
var fuel = _parent.Fuel;
|
||||||
|
|
||||||
|
_label.SetMarkup(Loc.GetString("Fuel: [color={0}]{1}/{2}[/color]",
|
||||||
|
fuel < fuelCap / 4f ? "darkorange" : "orange", Math.Round(fuel), fuelCap));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
10
Content.Client/StaticIoC.cs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
using Robust.Client.Interfaces.ResourceManagement;
|
||||||
|
using Robust.Shared.IoC;
|
||||||
|
|
||||||
|
namespace Content.Client
|
||||||
|
{
|
||||||
|
public static class StaticIoC
|
||||||
|
{
|
||||||
|
public static IResourceCache ResC => IoCManager.Resolve<IResourceCache>();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -214,11 +214,6 @@ namespace Content.Client.UserInterface
|
|||||||
SizeFlagsVertical = Control.SizeFlags.ShrinkEnd
|
SizeFlagsVertical = Control.SizeFlags.ShrinkEnd
|
||||||
};
|
};
|
||||||
|
|
||||||
HandsContainer = new MarginContainer
|
|
||||||
{
|
|
||||||
SizeFlagsVertical = Control.SizeFlags.ShrinkEnd
|
|
||||||
};
|
|
||||||
|
|
||||||
_combatPanelContainer = new VBoxContainer
|
_combatPanelContainer = new VBoxContainer
|
||||||
{
|
{
|
||||||
Children =
|
Children =
|
||||||
@@ -235,9 +230,20 @@ namespace Content.Client.UserInterface
|
|||||||
_combatModeButton.OnToggled += args => OnCombatModeChanged?.Invoke(args.Pressed);
|
_combatModeButton.OnToggled += args => OnCombatModeChanged?.Invoke(args.Pressed);
|
||||||
_targetingDoll.OnZoneChanged += args => OnTargetingZoneChanged?.Invoke(args);
|
_targetingDoll.OnZoneChanged += args => OnTargetingZoneChanged?.Invoke(args);
|
||||||
|
|
||||||
inventoryContainer.Children.Add(HandsContainer);
|
|
||||||
inventoryContainer.Children.Add(InventoryQuickButtonContainer);
|
inventoryContainer.Children.Add(InventoryQuickButtonContainer);
|
||||||
inventoryContainer.Children.Add(_combatPanelContainer);
|
inventoryContainer.Children.Add(_combatPanelContainer);
|
||||||
|
|
||||||
|
|
||||||
|
HandsContainer = new MarginContainer
|
||||||
|
{
|
||||||
|
SizeFlagsVertical = Control.SizeFlags.ShrinkEnd
|
||||||
|
};
|
||||||
|
|
||||||
|
RootControl.AddChild(HandsContainer);
|
||||||
|
|
||||||
|
LayoutContainer.SetAnchorAndMarginPreset(HandsContainer, LayoutContainer.LayoutPreset.CenterBottom);
|
||||||
|
LayoutContainer.SetGrowHorizontal(HandsContainer, LayoutContainer.GrowDirection.Both);
|
||||||
|
LayoutContainer.SetGrowVertical(HandsContainer, LayoutContainer.GrowDirection.Begin);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ButtonTutorialOnOnToggled()
|
private void ButtonTutorialOnOnToggled()
|
||||||
|
|||||||
@@ -23,9 +23,10 @@ namespace Content.Client.UserInterface
|
|||||||
{
|
{
|
||||||
public class HandsGui : Control
|
public class HandsGui : Control
|
||||||
{
|
{
|
||||||
|
private const string HandNameLeft = "left";
|
||||||
|
private const string HandNameRight = "right";
|
||||||
|
|
||||||
private const int CooldownLevels = 8;
|
private const int CooldownLevels = 8;
|
||||||
private const int BoxSpacing = 0;
|
|
||||||
private const int BoxSize = 64;
|
|
||||||
|
|
||||||
#pragma warning disable 0649
|
#pragma warning disable 0649
|
||||||
[Dependency] private readonly IPlayerManager _playerManager;
|
[Dependency] private readonly IPlayerManager _playerManager;
|
||||||
@@ -40,8 +41,6 @@ namespace Content.Client.UserInterface
|
|||||||
|
|
||||||
private IEntity LeftHand;
|
private IEntity LeftHand;
|
||||||
private IEntity RightHand;
|
private IEntity RightHand;
|
||||||
private UIBox2i _handL;
|
|
||||||
private UIBox2i _handR;
|
|
||||||
|
|
||||||
private readonly SpriteView LeftSpriteView;
|
private readonly SpriteView LeftSpriteView;
|
||||||
private readonly SpriteView RightSpriteView;
|
private readonly SpriteView RightSpriteView;
|
||||||
@@ -53,13 +52,13 @@ namespace Content.Client.UserInterface
|
|||||||
private readonly Control _leftContainer;
|
private readonly Control _leftContainer;
|
||||||
private readonly Control _rightContainer;
|
private readonly Control _rightContainer;
|
||||||
|
|
||||||
|
private readonly ItemStatusPanel _rightStatusPanel;
|
||||||
|
private readonly ItemStatusPanel _leftStatusPanel;
|
||||||
|
|
||||||
public HandsGui()
|
public HandsGui()
|
||||||
{
|
{
|
||||||
IoCManager.InjectDependencies(this);
|
IoCManager.InjectDependencies(this);
|
||||||
|
|
||||||
_handR = new UIBox2i(0, 0, BoxSize, BoxSize);
|
|
||||||
_handL = _handR.Translated((BoxSize + BoxSpacing, 0));
|
|
||||||
|
|
||||||
MouseFilter = MouseFilterMode.Stop;
|
MouseFilter = MouseFilterMode.Stop;
|
||||||
|
|
||||||
TextureHandLeft = _resourceCache.GetTexture("/Textures/UserInterface/Inventory/hand_l.png");
|
TextureHandLeft = _resourceCache.GetTexture("/Textures/UserInterface/Inventory/hand_l.png");
|
||||||
@@ -73,30 +72,37 @@ namespace Content.Client.UserInterface
|
|||||||
_resourceCache.GetTexture($"/Textures/UserInterface/Inventory/cooldown-{i}.png");
|
_resourceCache.GetTexture($"/Textures/UserInterface/Inventory/cooldown-{i}.png");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_rightStatusPanel = new ItemStatusPanel(true);
|
||||||
|
_leftStatusPanel = new ItemStatusPanel(false);
|
||||||
|
|
||||||
_leftContainer = new Control {MouseFilter = MouseFilterMode.Ignore};
|
_leftContainer = new Control {MouseFilter = MouseFilterMode.Ignore};
|
||||||
_rightContainer = new Control {MouseFilter = MouseFilterMode.Ignore};
|
_rightContainer = new Control {MouseFilter = MouseFilterMode.Ignore};
|
||||||
var hBox = new HBoxContainer
|
var hBox = new HBoxContainer
|
||||||
{
|
{
|
||||||
SeparationOverride = 0,
|
SeparationOverride = 0,
|
||||||
Children = {_rightContainer, _leftContainer},
|
Children = {_rightStatusPanel, _rightContainer, _leftContainer, _leftStatusPanel},
|
||||||
MouseFilter = MouseFilterMode.Ignore
|
MouseFilter = MouseFilterMode.Ignore
|
||||||
};
|
};
|
||||||
|
|
||||||
AddChild(hBox);
|
AddChild(hBox);
|
||||||
|
|
||||||
_leftContainer.AddChild(new TextureRect
|
var textureLeft = new TextureRect
|
||||||
{
|
{
|
||||||
MouseFilter = MouseFilterMode.Ignore,
|
|
||||||
Texture = TextureHandLeft,
|
Texture = TextureHandLeft,
|
||||||
TextureScale = (2, 2)
|
TextureScale = (2, 2)
|
||||||
});
|
};
|
||||||
|
textureLeft.OnKeyBindDown += args => HandKeyBindDown(args, HandNameLeft);
|
||||||
|
|
||||||
_rightContainer.AddChild(new TextureRect
|
_leftContainer.AddChild(textureLeft);
|
||||||
|
|
||||||
|
var textureRight = new TextureRect
|
||||||
{
|
{
|
||||||
MouseFilter = MouseFilterMode.Ignore,
|
|
||||||
Texture = TextureHandRight,
|
Texture = TextureHandRight,
|
||||||
TextureScale = (2, 2)
|
TextureScale = (2, 2)
|
||||||
});
|
};
|
||||||
|
textureRight.OnKeyBindDown += args => HandKeyBindDown(args, HandNameRight);
|
||||||
|
|
||||||
|
_rightContainer.AddChild(textureRight);
|
||||||
|
|
||||||
_leftContainer.AddChild(ActiveHandRect = new TextureRect
|
_leftContainer.AddChild(ActiveHandRect = new TextureRect
|
||||||
{
|
{
|
||||||
@@ -127,6 +133,7 @@ namespace Content.Client.UserInterface
|
|||||||
SizeFlagsHorizontal = SizeFlags.ShrinkCenter,
|
SizeFlagsHorizontal = SizeFlags.ShrinkCenter,
|
||||||
SizeFlagsVertical = SizeFlags.ShrinkCenter,
|
SizeFlagsVertical = SizeFlags.ShrinkCenter,
|
||||||
MouseFilter = MouseFilterMode.Ignore,
|
MouseFilter = MouseFilterMode.Ignore,
|
||||||
|
Stretch = TextureRect.StretchMode.KeepCentered,
|
||||||
TextureScale = (2, 2),
|
TextureScale = (2, 2),
|
||||||
Visible = false,
|
Visible = false,
|
||||||
});
|
});
|
||||||
@@ -136,6 +143,7 @@ namespace Content.Client.UserInterface
|
|||||||
SizeFlagsHorizontal = SizeFlags.ShrinkCenter,
|
SizeFlagsHorizontal = SizeFlags.ShrinkCenter,
|
||||||
SizeFlagsVertical = SizeFlags.ShrinkCenter,
|
SizeFlagsVertical = SizeFlags.ShrinkCenter,
|
||||||
MouseFilter = MouseFilterMode.Ignore,
|
MouseFilter = MouseFilterMode.Ignore,
|
||||||
|
Stretch = TextureRect.StretchMode.KeepCentered,
|
||||||
TextureScale = (2, 2),
|
TextureScale = (2, 2),
|
||||||
Visible = false
|
Visible = false
|
||||||
});
|
});
|
||||||
@@ -166,12 +174,13 @@ namespace Content.Client.UserInterface
|
|||||||
if (!TryGetHands(out var hands))
|
if (!TryGetHands(out var hands))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var left = hands.GetEntity("left");
|
var left = hands.GetEntity(HandNameLeft);
|
||||||
var right = hands.GetEntity("right");
|
var right = hands.GetEntity(HandNameRight);
|
||||||
|
|
||||||
ActiveHandRect.Parent.RemoveChild(ActiveHandRect);
|
ActiveHandRect.Parent.RemoveChild(ActiveHandRect);
|
||||||
var parent = hands.ActiveIndex == "left" ? _leftContainer : _rightContainer;
|
var parent = hands.ActiveIndex == HandNameLeft ? _leftContainer : _rightContainer;
|
||||||
parent.AddChild(ActiveHandRect);
|
parent.AddChild(ActiveHandRect);
|
||||||
|
ActiveHandRect.SetPositionInParent(1);
|
||||||
|
|
||||||
if (left != null)
|
if (left != null)
|
||||||
{
|
{
|
||||||
@@ -230,43 +239,13 @@ namespace Content.Client.UserInterface
|
|||||||
hands.AttackByInHand(hand);
|
hands.AttackByInHand(hand);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool HasPoint(Vector2 point)
|
private void HandKeyBindDown(GUIBoundKeyEventArgs args, string handIndex)
|
||||||
{
|
{
|
||||||
return _handL.Contains((Vector2i) point) || _handR.Contains((Vector2i) point);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void KeyBindDown(GUIBoundKeyEventArgs args)
|
|
||||||
{
|
|
||||||
base.KeyBindDown(args);
|
|
||||||
|
|
||||||
if (!args.CanFocus)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var leftHandContains = _handL.Contains((Vector2i) args.RelativePosition);
|
|
||||||
var rightHandContains = _handR.Contains((Vector2i) args.RelativePosition);
|
|
||||||
|
|
||||||
string handIndex;
|
|
||||||
if (leftHandContains)
|
|
||||||
{
|
|
||||||
handIndex = "left";
|
|
||||||
}
|
|
||||||
else if (rightHandContains)
|
|
||||||
{
|
|
||||||
handIndex = "right";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args.Function == EngineKeyFunctions.Use)
|
if (args.Function == EngineKeyFunctions.Use)
|
||||||
{
|
{
|
||||||
if (!TryGetHands(out var hands))
|
if (!TryGetHands(out var hands))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
||||||
if (hands.ActiveIndex == handIndex)
|
if (hands.ActiveIndex == handIndex)
|
||||||
{
|
{
|
||||||
UseActiveHand();
|
UseActiveHand();
|
||||||
@@ -276,21 +255,18 @@ namespace Content.Client.UserInterface
|
|||||||
AttackByInHand(handIndex);
|
AttackByInHand(handIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (args.Function == ContentKeyFunctions.ExamineEntity)
|
else if (args.Function == ContentKeyFunctions.ExamineEntity)
|
||||||
{
|
{
|
||||||
var examine = IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<ExamineSystem>();
|
var examine = IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<ExamineSystem>();
|
||||||
if (leftHandContains)
|
if (handIndex == HandNameLeft)
|
||||||
examine.DoExamine(LeftHand);
|
examine.DoExamine(LeftHand);
|
||||||
else if (rightHandContains)
|
else if (handIndex == HandNameRight)
|
||||||
examine.DoExamine(RightHand);
|
examine.DoExamine(RightHand);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (args.Function == ContentKeyFunctions.MouseMiddle)
|
else if (args.Function == ContentKeyFunctions.MouseMiddle)
|
||||||
{
|
{
|
||||||
SendSwitchHandTo(handIndex);
|
SendSwitchHandTo(handIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (args.Function == ContentKeyFunctions.OpenContextMenu)
|
else if (args.Function == ContentKeyFunctions.OpenContextMenu)
|
||||||
{
|
{
|
||||||
if (!TryGetHands(out var hands))
|
if (!TryGetHands(out var hands))
|
||||||
@@ -316,6 +292,9 @@ namespace Content.Client.UserInterface
|
|||||||
|
|
||||||
UpdateCooldown(CooldownCircleLeft, LeftHand);
|
UpdateCooldown(CooldownCircleLeft, LeftHand);
|
||||||
UpdateCooldown(CooldownCircleRight, RightHand);
|
UpdateCooldown(CooldownCircleRight, RightHand);
|
||||||
|
|
||||||
|
_rightStatusPanel.Update(RightHand);
|
||||||
|
_leftStatusPanel.Update(LeftHand);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateCooldown(TextureRect cooldownTexture, IEntity entity)
|
private void UpdateCooldown(TextureRect cooldownTexture, IEntity entity)
|
||||||
|
|||||||
121
Content.Client/UserInterface/ItemStatusPanel.cs
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using Content.Client.GameObjects.Components;
|
||||||
|
using Content.Client.Utility;
|
||||||
|
using Robust.Client.Graphics.Drawing;
|
||||||
|
using Robust.Client.UserInterface;
|
||||||
|
using Robust.Client.UserInterface.Controls;
|
||||||
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
|
using Robust.Shared.Maths;
|
||||||
|
using Robust.Shared.Utility;
|
||||||
|
using Robust.Shared.ViewVariables;
|
||||||
|
using static Content.Client.StaticIoC;
|
||||||
|
|
||||||
|
namespace Content.Client.UserInterface
|
||||||
|
{
|
||||||
|
public class ItemStatusPanel : Control
|
||||||
|
{
|
||||||
|
[ViewVariables]
|
||||||
|
private readonly List<(IItemStatus, Control)> _activeStatusComponents = new List<(IItemStatus, Control)>();
|
||||||
|
|
||||||
|
[ViewVariables]
|
||||||
|
private readonly Label _itemNameLabel;
|
||||||
|
[ViewVariables]
|
||||||
|
private readonly VBoxContainer _statusContents;
|
||||||
|
[ViewVariables]
|
||||||
|
private readonly PanelContainer _panel;
|
||||||
|
|
||||||
|
[ViewVariables]
|
||||||
|
private IEntity _entity;
|
||||||
|
|
||||||
|
public ItemStatusPanel(bool isRightHand)
|
||||||
|
{
|
||||||
|
// isRightHand means on the LEFT of the screen.
|
||||||
|
// Keep that in mind.
|
||||||
|
var panel = new StyleBoxTexture
|
||||||
|
{
|
||||||
|
Texture = ResC.GetTexture(isRightHand
|
||||||
|
? "/Nano/item_status_right.svg.96dpi.png"
|
||||||
|
: "/Nano/item_status_left.svg.96dpi.png")
|
||||||
|
};
|
||||||
|
panel.SetContentMarginOverride(StyleBox.Margin.Vertical, 4);
|
||||||
|
panel.SetContentMarginOverride(StyleBox.Margin.Horizontal, 6);
|
||||||
|
panel.SetPatchMargin((isRightHand ? StyleBox.Margin.Left : StyleBox.Margin.Right) | StyleBox.Margin.Top,
|
||||||
|
13);
|
||||||
|
|
||||||
|
AddChild(_panel = new PanelContainer
|
||||||
|
{
|
||||||
|
PanelOverride = panel,
|
||||||
|
ModulateSelfOverride = Color.White.WithAlpha(0.9f),
|
||||||
|
Children =
|
||||||
|
{
|
||||||
|
new VBoxContainer
|
||||||
|
{
|
||||||
|
SeparationOverride = 0,
|
||||||
|
Children =
|
||||||
|
{
|
||||||
|
(_statusContents = new VBoxContainer()),
|
||||||
|
(_itemNameLabel = new Label
|
||||||
|
{
|
||||||
|
ClipText = true,
|
||||||
|
StyleClasses = {NanoStyle.StyleClassItemStatus}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
SizeFlagsVertical = SizeFlags.ShrinkEnd;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Update(IEntity entity)
|
||||||
|
{
|
||||||
|
if (entity == null)
|
||||||
|
{
|
||||||
|
ClearOldStatus();
|
||||||
|
_entity = null;
|
||||||
|
_panel.Visible = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entity != _entity)
|
||||||
|
{
|
||||||
|
_entity = entity;
|
||||||
|
BuildNewEntityStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
_panel.Visible = true;
|
||||||
|
_itemNameLabel.Text = entity.Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ClearOldStatus()
|
||||||
|
{
|
||||||
|
_statusContents.RemoveAllChildren();
|
||||||
|
|
||||||
|
foreach (var (itemStatus, control) in _activeStatusComponents)
|
||||||
|
{
|
||||||
|
itemStatus.DestroyControl(control);
|
||||||
|
}
|
||||||
|
|
||||||
|
_activeStatusComponents.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BuildNewEntityStatus()
|
||||||
|
{
|
||||||
|
DebugTools.AssertNotNull(_entity);
|
||||||
|
|
||||||
|
ClearOldStatus();
|
||||||
|
|
||||||
|
foreach (var statusComponent in _entity.GetAllComponents<IItemStatus>())
|
||||||
|
{
|
||||||
|
var control = statusComponent.MakeControl();
|
||||||
|
_statusContents.AddChild(control);
|
||||||
|
|
||||||
|
_activeStatusComponents.Add((statusComponent, control));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Vector2 CalculateMinimumSize()
|
||||||
|
{
|
||||||
|
return Vector2.ComponentMax(base.CalculateMinimumSize(), (150, 00));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -30,11 +30,14 @@ namespace Content.Client.UserInterface
|
|||||||
public const string StyleClassPowerStateLow = "PowerStateLow";
|
public const string StyleClassPowerStateLow = "PowerStateLow";
|
||||||
public const string StyleClassPowerStateGood = "PowerStateGood";
|
public const string StyleClassPowerStateGood = "PowerStateGood";
|
||||||
|
|
||||||
|
public const string StyleClassItemStatus = "ItemStatus";
|
||||||
|
|
||||||
public Stylesheet Stylesheet { get; }
|
public Stylesheet Stylesheet { get; }
|
||||||
|
|
||||||
public NanoStyle()
|
public NanoStyle()
|
||||||
{
|
{
|
||||||
var resCache = IoCManager.Resolve<IResourceCache>();
|
var resCache = IoCManager.Resolve<IResourceCache>();
|
||||||
|
var notoSans8 = resCache.GetFont("/Nano/NotoSans/NotoSans-Regular.ttf", 8);
|
||||||
var notoSans10 = resCache.GetFont("/Nano/NotoSans/NotoSans-Regular.ttf", 10);
|
var notoSans10 = resCache.GetFont("/Nano/NotoSans/NotoSans-Regular.ttf", 10);
|
||||||
var notoSans12 = resCache.GetFont("/Nano/NotoSans/NotoSans-Regular.ttf", 12);
|
var notoSans12 = resCache.GetFont("/Nano/NotoSans/NotoSans-Regular.ttf", 12);
|
||||||
var notoSansBold12 = resCache.GetFont("/Nano/NotoSans/NotoSans-Bold.ttf", 12);
|
var notoSansBold12 = resCache.GetFont("/Nano/NotoSans/NotoSans-Bold.ttf", 12);
|
||||||
@@ -108,7 +111,8 @@ namespace Content.Client.UserInterface
|
|||||||
|
|
||||||
var vScrollBarGrabberNormal = new StyleBoxFlat
|
var vScrollBarGrabberNormal = new StyleBoxFlat
|
||||||
{
|
{
|
||||||
BackgroundColor = Color.Gray.WithAlpha(0.35f), ContentMarginLeftOverride = 10, ContentMarginTopOverride = 10
|
BackgroundColor = Color.Gray.WithAlpha(0.35f), ContentMarginLeftOverride = 10,
|
||||||
|
ContentMarginTopOverride = 10
|
||||||
};
|
};
|
||||||
var vScrollBarGrabberHover = new StyleBoxFlat
|
var vScrollBarGrabberHover = new StyleBoxFlat
|
||||||
{
|
{
|
||||||
@@ -482,7 +486,8 @@ namespace Content.Client.UserInterface
|
|||||||
}),
|
}),
|
||||||
|
|
||||||
// Bigger Label
|
// Bigger Label
|
||||||
new StyleRule(new SelectorElement(typeof(Label), new[] {StyleClassLabelHeadingBigger}, null, null), new[]
|
new StyleRule(new SelectorElement(typeof(Label), new[] {StyleClassLabelHeadingBigger}, null, null),
|
||||||
|
new[]
|
||||||
{
|
{
|
||||||
new StyleProperty(Label.StylePropertyFont, notoSansBold20),
|
new StyleProperty(Label.StylePropertyFont, notoSansBold20),
|
||||||
new StyleProperty(Label.StylePropertyFontColor, NanoGold),
|
new StyleProperty(Label.StylePropertyFontColor, NanoGold),
|
||||||
@@ -502,7 +507,8 @@ namespace Content.Client.UserInterface
|
|||||||
new StyleProperty(Label.StylePropertyFontColor, NanoGold)
|
new StyleProperty(Label.StylePropertyFontColor, NanoGold)
|
||||||
}),
|
}),
|
||||||
|
|
||||||
new StyleRule(new SelectorElement(typeof(Label), new[] {StyleClassLabelSecondaryColor}, null, null), new[]
|
new StyleRule(new SelectorElement(typeof(Label), new[] {StyleClassLabelSecondaryColor}, null, null),
|
||||||
|
new[]
|
||||||
{
|
{
|
||||||
new StyleProperty(Label.StylePropertyFont, notoSans12),
|
new StyleProperty(Label.StylePropertyFont, notoSans12),
|
||||||
new StyleProperty(Label.StylePropertyFontColor, Color.DarkGray),
|
new StyleProperty(Label.StylePropertyFontColor, Color.DarkGray),
|
||||||
@@ -608,6 +614,12 @@ namespace Content.Client.UserInterface
|
|||||||
{
|
{
|
||||||
new StyleProperty("font", notoSans16),
|
new StyleProperty("font", notoSans16),
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
// StyleClassItemStatus
|
||||||
|
new StyleRule(SelectorElement.Class(StyleClassItemStatus), new[]
|
||||||
|
{
|
||||||
|
new StyleProperty("font", notoSans10),
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
13
Content.Client/Utility/RichTextLabelExt.cs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
using Robust.Client.UserInterface.Controls;
|
||||||
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
|
namespace Content.Client.Utility
|
||||||
|
{
|
||||||
|
public static class RichTextLabelExt
|
||||||
|
{
|
||||||
|
public static void SetMarkup(this RichTextLabel label, string markup)
|
||||||
|
{
|
||||||
|
label.SetMessage(FormattedMessage.FromMarkup(markup));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ using Content.Server.GameObjects.Components.Sound;
|
|||||||
using Content.Server.GameObjects.EntitySystems;
|
using Content.Server.GameObjects.EntitySystems;
|
||||||
using Content.Server.Interfaces.GameObjects;
|
using Content.Server.Interfaces.GameObjects;
|
||||||
using Content.Shared.GameObjects;
|
using Content.Shared.GameObjects;
|
||||||
|
using Content.Shared.GameObjects.Components;
|
||||||
using Content.Shared.Interfaces;
|
using Content.Shared.Interfaces;
|
||||||
using Robust.Server.GameObjects;
|
using Robust.Server.GameObjects;
|
||||||
using Robust.Server.GameObjects.Components.Container;
|
using Robust.Server.GameObjects.Components.Container;
|
||||||
@@ -20,7 +21,7 @@ namespace Content.Server.GameObjects.Components.Interactable
|
|||||||
/// Component that represents a handheld lightsource which can be toggled on and off.
|
/// Component that represents a handheld lightsource which can be toggled on and off.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[RegisterComponent]
|
[RegisterComponent]
|
||||||
internal class HandheldLightComponent : Component, IUse, IExamine, IAttackBy, IMapInit
|
internal sealed class HandheldLightComponent : SharedHandheldLightComponent, IUse, IExamine, IAttackBy, IMapInit
|
||||||
{
|
{
|
||||||
#pragma warning disable 649
|
#pragma warning disable 649
|
||||||
[Dependency] private readonly ISharedNotifyManager _notifyManager;
|
[Dependency] private readonly ISharedNotifyManager _notifyManager;
|
||||||
@@ -45,9 +46,6 @@ namespace Content.Server.GameObjects.Components.Interactable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public override string Name => "HandheldLight";
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Status of light, whether or not it is emitting light.
|
/// Status of light, whether or not it is emitting light.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -73,7 +71,6 @@ namespace Content.Server.GameObjects.Components.Interactable
|
|||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IExamine.Examine(FormattedMessage message)
|
void IExamine.Examine(FormattedMessage message)
|
||||||
@@ -153,6 +150,7 @@ namespace Content.Server.GameObjects.Components.Interactable
|
|||||||
{
|
{
|
||||||
soundComponent.Play("/Audio/machines/button.ogg");
|
soundComponent.Play("/Audio/machines/button.ogg");
|
||||||
}
|
}
|
||||||
|
|
||||||
_notifyManager.PopupMessage(Owner, user, _localizationManager.GetString("Cell missing..."));
|
_notifyManager.PopupMessage(Owner, user, _localizationManager.GetString("Cell missing..."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -166,6 +164,7 @@ namespace Content.Server.GameObjects.Components.Interactable
|
|||||||
{
|
{
|
||||||
soundComponent.Play("/Audio/machines/button.ogg");
|
soundComponent.Play("/Audio/machines/button.ogg");
|
||||||
}
|
}
|
||||||
|
|
||||||
_notifyManager.PopupMessage(Owner, user, _localizationManager.GetString("Dead cell..."));
|
_notifyManager.PopupMessage(Owner, user, _localizationManager.GetString("Dead cell..."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -195,6 +194,8 @@ namespace Content.Server.GameObjects.Components.Interactable
|
|||||||
|
|
||||||
var cell = Cell;
|
var cell = Cell;
|
||||||
if (cell == null || !cell.TryDeductWattage(Wattage, frameTime)) TurnOff();
|
if (cell == null || !cell.TryDeductWattage(Wattage, frameTime)) TurnOff();
|
||||||
|
|
||||||
|
Dirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void EjectCell(IEntity user)
|
private void EjectCell(IEntity user)
|
||||||
@@ -227,6 +228,23 @@ namespace Content.Server.GameObjects.Components.Interactable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override ComponentState GetComponentState()
|
||||||
|
{
|
||||||
|
if (Cell == null)
|
||||||
|
{
|
||||||
|
return new HandheldLightComponentState(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Cell.AvailableCharge(1) < Wattage)
|
||||||
|
{
|
||||||
|
// Practically zero.
|
||||||
|
// This is so the item status works correctly.
|
||||||
|
return new HandheldLightComponentState(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new HandheldLightComponentState(Cell.Charge / Cell.Capacity);
|
||||||
|
}
|
||||||
|
|
||||||
[Verb]
|
[Verb]
|
||||||
public sealed class EjectCellVerb : Verb<HandheldLightComponent>
|
public sealed class EjectCellVerb : Verb<HandheldLightComponent>
|
||||||
{
|
{
|
||||||
@@ -252,6 +270,7 @@ namespace Content.Server.GameObjects.Components.Interactable
|
|||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var cell = Owner.EntityManager.SpawnEntity("PowerCellSmallHyper", Owner.Transform.GridPosition);
|
var cell = Owner.EntityManager.SpawnEntity("PowerCellSmallHyper", Owner.Transform.GridPosition);
|
||||||
_cellContainer.Insert(cell);
|
_cellContainer.Insert(cell);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
using System;
|
using System;
|
||||||
using Content.Server.GameObjects.EntitySystems;
|
using Content.Server.GameObjects.EntitySystems;
|
||||||
using Content.Shared.Audio;
|
using Content.Shared.Audio;
|
||||||
|
using Content.Shared.GameObjects;
|
||||||
|
using Content.Shared.GameObjects.Components;
|
||||||
using Robust.Server.GameObjects;
|
using Robust.Server.GameObjects;
|
||||||
using Robust.Server.GameObjects.EntitySystems;
|
using Robust.Server.GameObjects.EntitySystems;
|
||||||
using Robust.Shared.Audio;
|
using Robust.Shared.Audio;
|
||||||
@@ -32,6 +34,7 @@ namespace Content.Server.GameObjects.Components.Interactable.Tools
|
|||||||
#pragma warning restore 649
|
#pragma warning restore 649
|
||||||
|
|
||||||
public override string Name => "Welder";
|
public override string Name => "Welder";
|
||||||
|
public override uint? NetID => ContentNetIDs.WELDER;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Maximum fuel capacity the welder can hold
|
/// Maximum fuel capacity the welder can hold
|
||||||
@@ -40,8 +43,13 @@ namespace Content.Server.GameObjects.Components.Interactable.Tools
|
|||||||
public float FuelCapacity
|
public float FuelCapacity
|
||||||
{
|
{
|
||||||
get => _fuelCapacity;
|
get => _fuelCapacity;
|
||||||
set => _fuelCapacity = value;
|
set
|
||||||
|
{
|
||||||
|
_fuelCapacity = value;
|
||||||
|
Dirty();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private float _fuelCapacity = 50;
|
private float _fuelCapacity = 50;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -51,9 +59,15 @@ namespace Content.Server.GameObjects.Components.Interactable.Tools
|
|||||||
public float Fuel
|
public float Fuel
|
||||||
{
|
{
|
||||||
get => _fuel;
|
get => _fuel;
|
||||||
set => _fuel = value;
|
set
|
||||||
|
{
|
||||||
|
_fuel = value;
|
||||||
|
Dirty();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private float _fuel = 0;
|
private float _fuel = 0;
|
||||||
|
private bool _activated = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Default Cost of using the welder fuel for an action
|
/// Default Cost of using the welder fuel for an action
|
||||||
@@ -69,7 +83,15 @@ namespace Content.Server.GameObjects.Components.Interactable.Tools
|
|||||||
/// Status of welder, whether it is ignited
|
/// Status of welder, whether it is ignited
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
public bool Activated { get; private set; } = false;
|
public bool Activated
|
||||||
|
{
|
||||||
|
get => _activated;
|
||||||
|
private set
|
||||||
|
{
|
||||||
|
_activated = value;
|
||||||
|
Dirty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//private string OnSprite { get; set; }
|
//private string OnSprite { get; set; }
|
||||||
//private string OffSprite { get; set; }
|
//private string OffSprite { get; set; }
|
||||||
@@ -87,6 +109,7 @@ namespace Content.Server.GameObjects.Components.Interactable.Tools
|
|||||||
|
|
||||||
serializer.DataField(ref _fuelCapacity, "Capacity", 50);
|
serializer.DataField(ref _fuelCapacity, "Capacity", 50);
|
||||||
serializer.DataField(ref _fuel, "Fuel", FuelCapacity);
|
serializer.DataField(ref _fuel, "Fuel", FuelCapacity);
|
||||||
|
serializer.DataField(ref _activated, "Activated", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnUpdate(float frameTime)
|
public void OnUpdate(float frameTime)
|
||||||
@@ -185,5 +208,10 @@ namespace Content.Server.GameObjects.Components.Interactable.Tools
|
|||||||
_entitySystemManager.GetEntitySystem<AudioSystem>()
|
_entitySystemManager.GetEntitySystem<AudioSystem>()
|
||||||
.Play(file, AudioParams.Default.WithVolume(volume));
|
.Play(file, AudioParams.Default.WithVolume(volume));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override ComponentState GetComponentState()
|
||||||
|
{
|
||||||
|
return new WelderComponentState(FuelCapacity, Fuel, Activated);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using Content.Server.GameObjects.EntitySystems;
|
using Content.Server.GameObjects.EntitySystems;
|
||||||
|
using Content.Shared.GameObjects.Components;
|
||||||
using Content.Shared.Interfaces;
|
using Content.Shared.Interfaces;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
using Robust.Shared.Interfaces.Reflection;
|
using Robust.Shared.Interfaces.Reflection;
|
||||||
@@ -16,7 +17,7 @@ namespace Content.Server.GameObjects.Components.Stack
|
|||||||
|
|
||||||
// TODO: Naming and presentation and such could use some improvement.
|
// TODO: Naming and presentation and such could use some improvement.
|
||||||
[RegisterComponent]
|
[RegisterComponent]
|
||||||
public class StackComponent : Component, IAttackBy, IExamine
|
public class StackComponent : SharedStackComponent, IAttackBy, IExamine
|
||||||
{
|
{
|
||||||
#pragma warning disable 649
|
#pragma warning disable 649
|
||||||
[Dependency] private readonly ISharedNotifyManager _sharedNotifyManager;
|
[Dependency] private readonly ISharedNotifyManager _sharedNotifyManager;
|
||||||
@@ -26,8 +27,6 @@ namespace Content.Server.GameObjects.Components.Stack
|
|||||||
private int _count = 50;
|
private int _count = 50;
|
||||||
private int _maxCount = 50;
|
private int _maxCount = 50;
|
||||||
|
|
||||||
public override string Name => "Stack";
|
|
||||||
|
|
||||||
[ViewVariables(VVAccess.ReadWrite)]
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
public int Count
|
public int Count
|
||||||
{
|
{
|
||||||
@@ -39,11 +38,20 @@ namespace Content.Server.GameObjects.Components.Stack
|
|||||||
{
|
{
|
||||||
Owner.Delete();
|
Owner.Delete();
|
||||||
}
|
}
|
||||||
|
Dirty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
public int MaxCount { get => _maxCount; private set => _maxCount = value; }
|
public int MaxCount
|
||||||
|
{
|
||||||
|
get => _maxCount;
|
||||||
|
private set
|
||||||
|
{
|
||||||
|
_maxCount = value;
|
||||||
|
Dirty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
public int AvailableSpace => MaxCount - Count;
|
public int AvailableSpace => MaxCount - Count;
|
||||||
@@ -155,6 +163,11 @@ namespace Content.Server.GameObjects.Components.Stack
|
|||||||
"There is [color=lightgray]1[/color] thing in the stack",
|
"There is [color=lightgray]1[/color] thing in the stack",
|
||||||
"There are [color=lightgray]{0}[/color] things in the stack.", Count, Count));
|
"There are [color=lightgray]{0}[/color] things in the stack.", Count, Count));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override ComponentState GetComponentState()
|
||||||
|
{
|
||||||
|
return new StackComponentState(Count, MaxCount);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum StackType
|
public enum StackType
|
||||||
|
|||||||
@@ -24,33 +24,27 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Projectile
|
|||||||
[RegisterComponent]
|
[RegisterComponent]
|
||||||
public class BallisticMagazineWeaponComponent : BallisticWeaponComponent, IUse, IAttackBy, IMapInit
|
public class BallisticMagazineWeaponComponent : BallisticWeaponComponent, IUse, IAttackBy, IMapInit
|
||||||
{
|
{
|
||||||
|
private const float BulletOffset = 0.2f;
|
||||||
|
|
||||||
public override string Name => "BallisticMagazineWeapon";
|
public override string Name => "BallisticMagazineWeapon";
|
||||||
|
public override uint? NetID => ContentNetIDs.BALLISTIC_MAGAZINE_WEAPON;
|
||||||
|
|
||||||
[ViewVariables]
|
[ViewVariables] private string _defaultMagazine;
|
||||||
private string _defaultMagazine;
|
|
||||||
|
|
||||||
[ViewVariables]
|
[ViewVariables] private ContainerSlot _magazineSlot;
|
||||||
private ContainerSlot _magazineSlot;
|
|
||||||
private List<BallisticMagazineType> _magazineTypes;
|
private List<BallisticMagazineType> _magazineTypes;
|
||||||
|
|
||||||
[ViewVariables]
|
[ViewVariables] public List<BallisticMagazineType> MagazineTypes => _magazineTypes;
|
||||||
public List<BallisticMagazineType> MagazineTypes => _magazineTypes;
|
[ViewVariables] private IEntity Magazine => _magazineSlot.ContainedEntity;
|
||||||
[ViewVariables]
|
|
||||||
private IEntity Magazine => _magazineSlot.ContainedEntity;
|
|
||||||
|
|
||||||
#pragma warning disable 649
|
#pragma warning disable 649
|
||||||
[Dependency] private readonly IRobustRandom _bulletDropRandom;
|
[Dependency] private readonly IRobustRandom _bulletDropRandom;
|
||||||
#pragma warning restore 649
|
#pragma warning restore 649
|
||||||
[ViewVariables]
|
[ViewVariables] private string _magInSound;
|
||||||
private string _magInSound;
|
[ViewVariables] private string _magOutSound;
|
||||||
[ViewVariables]
|
[ViewVariables] private string _autoEjectSound;
|
||||||
private string _magOutSound;
|
[ViewVariables] private bool _autoEjectMagazine;
|
||||||
[ViewVariables]
|
[ViewVariables] private AppearanceComponent _appearance;
|
||||||
private string _autoEjectSound;
|
|
||||||
[ViewVariables]
|
|
||||||
private bool _autoEjectMagazine;
|
|
||||||
[ViewVariables]
|
|
||||||
private AppearanceComponent _appearance;
|
|
||||||
|
|
||||||
private static readonly Direction[] _randomBulletDirs =
|
private static readonly Direction[] _randomBulletDirs =
|
||||||
{
|
{
|
||||||
@@ -137,6 +131,7 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Projectile
|
|||||||
}
|
}
|
||||||
|
|
||||||
_updateAppearance();
|
_updateAppearance();
|
||||||
|
Dirty();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,15 +148,17 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Projectile
|
|||||||
entity.Transform.GridPosition = Owner.Transform.GridPosition;
|
entity.Transform.GridPosition = Owner.Transform.GridPosition;
|
||||||
if (_magOutSound != null)
|
if (_magOutSound != null)
|
||||||
{
|
{
|
||||||
Owner.GetComponent<SoundComponent>().Play(_magOutSound);
|
Owner.GetComponent<SoundComponent>().Play(_magOutSound, AudioParams.Default.WithVolume(20));
|
||||||
}
|
}
|
||||||
|
|
||||||
_updateAppearance();
|
_updateAppearance();
|
||||||
|
Dirty();
|
||||||
entity.GetComponent<BallisticMagazineComponent>().OnAmmoCountChanged -= _magazineAmmoCountChanged;
|
entity.GetComponent<BallisticMagazineComponent>().OnAmmoCountChanged -= _magazineAmmoCountChanged;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
_updateAppearance();
|
_updateAppearance();
|
||||||
|
Dirty();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,7 +168,8 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Projectile
|
|||||||
|
|
||||||
// Eject chambered bullet.
|
// Eject chambered bullet.
|
||||||
var entity = RemoveFromChamber(chamber);
|
var entity = RemoveFromChamber(chamber);
|
||||||
entity.Transform.GridPosition = Owner.Transform.GridPosition;
|
var offsetPos = (CalcBulletOffset(), CalcBulletOffset());
|
||||||
|
entity.Transform.GridPosition = Owner.Transform.GridPosition.Offset(offsetPos);
|
||||||
entity.Transform.LocalRotation = _bulletDropRandom.Pick(_randomBulletDirs).ToAngle();
|
entity.Transform.LocalRotation = _bulletDropRandom.Pick(_randomBulletDirs).ToAngle();
|
||||||
var effect = $"/Audio/Guns/Casings/casingfall{_bulletDropRandom.Next(1, 4)}.ogg";
|
var effect = $"/Audio/Guns/Casings/casingfall{_bulletDropRandom.Next(1, 4)}.ogg";
|
||||||
Owner.GetComponent<SoundComponent>().Play(effect, AudioParams.Default.WithVolume(-3));
|
Owner.GetComponent<SoundComponent>().Play(effect, AudioParams.Default.WithVolume(-3));
|
||||||
@@ -187,15 +185,29 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Projectile
|
|||||||
|
|
||||||
if (magComponent.CountLoaded == 0 && _autoEjectMagazine)
|
if (magComponent.CountLoaded == 0 && _autoEjectMagazine)
|
||||||
{
|
{
|
||||||
|
DoAutoEject();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Dirty();
|
||||||
|
_updateAppearance();
|
||||||
|
}
|
||||||
|
|
||||||
|
private float CalcBulletOffset()
|
||||||
|
{
|
||||||
|
return _bulletDropRandom.NextFloat() * (BulletOffset * 2) - BulletOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DoAutoEject()
|
||||||
|
{
|
||||||
|
SendNetworkMessage(new BmwComponentAutoEjectedMessage());
|
||||||
EjectMagazine();
|
EjectMagazine();
|
||||||
if (_autoEjectSound != null)
|
if (_autoEjectSound != null)
|
||||||
{
|
{
|
||||||
Owner.GetComponent<SoundComponent>().Play(_autoEjectSound, AudioParams.Default.WithVolume(-5));
|
Owner.GetComponent<SoundComponent>().Play(_autoEjectSound, AudioParams.Default.WithVolume(-5));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_updateAppearance();
|
Dirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool UseEntity(UseEntityEventArgs eventArgs)
|
public bool UseEntity(UseEntityEventArgs eventArgs)
|
||||||
@@ -237,6 +249,7 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Projectile
|
|||||||
|
|
||||||
private void _magazineAmmoCountChanged()
|
private void _magazineAmmoCountChanged()
|
||||||
{
|
{
|
||||||
|
Dirty();
|
||||||
_updateAppearance();
|
_updateAppearance();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -257,6 +270,21 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Projectile
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override ComponentState GetComponentState()
|
||||||
|
{
|
||||||
|
var chambered = GetChambered(0) != null;
|
||||||
|
|
||||||
|
(int, int)? count = null;
|
||||||
|
|
||||||
|
if (Magazine != null)
|
||||||
|
{
|
||||||
|
var magComponent = Magazine.GetComponent<BallisticMagazineComponent>();
|
||||||
|
count = (magComponent.CountLoaded, magComponent.Capacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new BallisticMagazineWeaponComponentState(chambered, count);
|
||||||
|
}
|
||||||
|
|
||||||
[Verb]
|
[Verb]
|
||||||
public sealed class EjectMagazineVerb : Verb<BallisticMagazineWeaponComponent>
|
public sealed class EjectMagazineVerb : Verb<BallisticMagazineWeaponComponent>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
using System;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.Serialization;
|
||||||
|
|
||||||
|
namespace Content.Shared.GameObjects.Components
|
||||||
|
{
|
||||||
|
public abstract class SharedHandheldLightComponent : Component
|
||||||
|
{
|
||||||
|
public sealed override string Name => "HandheldLight";
|
||||||
|
public sealed override uint? NetID => ContentNetIDs.HANDHELD_LIGHT;
|
||||||
|
public sealed override Type StateType => typeof(HandheldLightComponentState);
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
protected sealed class HandheldLightComponentState : ComponentState
|
||||||
|
{
|
||||||
|
public HandheldLightComponentState(float? charge) : base(ContentNetIDs.HANDHELD_LIGHT)
|
||||||
|
{
|
||||||
|
Charge = charge;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float? Charge { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
using System;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.Serialization;
|
||||||
|
|
||||||
|
namespace Content.Shared.GameObjects.Components
|
||||||
|
{
|
||||||
|
public abstract class SharedStackComponent : Component
|
||||||
|
{
|
||||||
|
public sealed override string Name => "Stack";
|
||||||
|
public sealed override uint? NetID => ContentNetIDs.STACK;
|
||||||
|
public sealed override Type StateType => typeof(StackComponentState);
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
protected sealed class StackComponentState : ComponentState
|
||||||
|
{
|
||||||
|
public int Count { get; }
|
||||||
|
public int MaxCount { get; }
|
||||||
|
|
||||||
|
public StackComponentState(int count, int maxCount) : base(ContentNetIDs.STACK)
|
||||||
|
{
|
||||||
|
Count = count;
|
||||||
|
MaxCount = maxCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
using System;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.Serialization;
|
||||||
|
|
||||||
|
namespace Content.Shared.GameObjects.Components.Weapons.Ranged
|
||||||
|
{
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public class BallisticMagazineWeaponComponentState : ComponentState
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// True if a bullet is chambered.
|
||||||
|
/// </summary>
|
||||||
|
public bool Chambered { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Count of bullets in the magazine.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Null if no magazine is inserted.
|
||||||
|
/// </remarks>
|
||||||
|
public (int count, int max)? MagazineCount { get; }
|
||||||
|
|
||||||
|
public BallisticMagazineWeaponComponentState(bool chambered, (int count, int max)? magazineCount) : base(ContentNetIDs.BALLISTIC_MAGAZINE_WEAPON)
|
||||||
|
{
|
||||||
|
Chambered = chambered;
|
||||||
|
MagazineCount = magazineCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// BMW is "Ballistic Magazine Weapon" here.
|
||||||
|
/// <summary>
|
||||||
|
/// Fired server -> client when the magazine in a Ballistic Magazine Weapon got auto-ejected.
|
||||||
|
/// </summary>
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public sealed class BmwComponentAutoEjectedMessage : ComponentMessage
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
using System;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.Serialization;
|
||||||
|
|
||||||
|
namespace Content.Shared.GameObjects.Components
|
||||||
|
{
|
||||||
|
[NetSerializable, Serializable]
|
||||||
|
public class WelderComponentState : ComponentState
|
||||||
|
{
|
||||||
|
public float FuelCapacity { get; }
|
||||||
|
public float Fuel { get; }
|
||||||
|
public bool Activated { get; }
|
||||||
|
|
||||||
|
public WelderComponentState(float fuelCapacity, float fuel, bool activated) : base(ContentNetIDs.WELDER)
|
||||||
|
{
|
||||||
|
FuelCapacity = fuelCapacity;
|
||||||
|
Fuel = fuel;
|
||||||
|
Activated = activated;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -36,5 +36,9 @@
|
|||||||
public const uint GALACTIC_MARKET = 1031;
|
public const uint GALACTIC_MARKET = 1031;
|
||||||
public const uint HAIR = 1032;
|
public const uint HAIR = 1032;
|
||||||
public const uint INSTRUMENTS = 1033;
|
public const uint INSTRUMENTS = 1033;
|
||||||
|
public const uint WELDER = 1034;
|
||||||
|
public const uint STACK = 1035;
|
||||||
|
public const uint HANDHELD_LIGHT = 1036;
|
||||||
|
public const uint BALLISTIC_MAGAZINE_WEAPON = 1037;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
100
Resources/Nano/item_status_left.svg
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="16"
|
||||||
|
height="16"
|
||||||
|
viewBox="0 0 4.2333337 4.2333334"
|
||||||
|
version="1.1"
|
||||||
|
id="svg8"
|
||||||
|
inkscape:version="0.92.4 5da689c313, 2019-01-14"
|
||||||
|
sodipodi:docname="item_status_left.svg"
|
||||||
|
inkscape:export-filename="/home/pj/Projects/space-station-14/Resources/Nano/item_status_left.svg.96dpi.png"
|
||||||
|
inkscape:export-xdpi="96.000008"
|
||||||
|
inkscape:export-ydpi="96.000008">
|
||||||
|
<defs
|
||||||
|
id="defs2" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="22.627417"
|
||||||
|
inkscape:cx="9.7147126"
|
||||||
|
inkscape:cy="13.122502"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:pagecheckerboard="true"
|
||||||
|
units="px"
|
||||||
|
showguides="true"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1043"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="0"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:guide-bbox="true"
|
||||||
|
inkscape:snap-intersection-paths="true"
|
||||||
|
inkscape:snap-bbox="true"
|
||||||
|
inkscape:snap-page="true">
|
||||||
|
<inkscape:grid
|
||||||
|
type="xygrid"
|
||||||
|
id="grid817" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<metadata
|
||||||
|
id="metadata5">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title />
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1"
|
||||||
|
transform="translate(-26.597681,-208.71661)">
|
||||||
|
<path
|
||||||
|
style="opacity:1;vector-effect:none;fill:#25252a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.26458335;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||||
|
d="m 26.597681,212.94995 h 4.233334 v -1.58751 l -2.645833,-2.64583 -1.587501,-1e-5 z"
|
||||||
|
id="rect815"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="cccccc" />
|
||||||
|
<path
|
||||||
|
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#474747;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.26458335;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
d="m 45.902791,212.76114 v 3.23047 l 1.003906,1.00195 h 3.228516 v -3.22852 l -1.001953,-1.0039 h -0.05469 z m 0.263672,0.26367 h 2.855469 l 0.849609,0.84961 v 2.85547 h -2.855468 l -0.84961,-0.84961 z"
|
||||||
|
id="rect815-3"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#474747;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.26458335;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
d="m 46.344997,207.34832 -0.290893,0.17906 1.133594,1.1102 v 2.91047 h 0.264579 v -3.04271 z"
|
||||||
|
id="rect815-6"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="ccccccc" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#474747;stroke-width:0.5291667;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="m 38.473823,212.26371 v -3.175 l -1.058333,-1.05833"
|
||||||
|
id="path856-6"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="ccc" />
|
||||||
|
<path
|
||||||
|
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#474747;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.5291667;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
d="m 28.185182,208.71661 h -0.748024 l 2.86456,2.86457 v 1.36874 h 0.529297 v -1.58749 z"
|
||||||
|
id="path856-7"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="ccccccc" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 7.2 KiB |
BIN
Resources/Nano/item_status_left.svg.96dpi.png
Normal file
|
After Width: | Height: | Size: 225 B |
105
Resources/Nano/item_status_right.svg
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="16"
|
||||||
|
height="16"
|
||||||
|
viewBox="0 0 4.2333337 4.2333334"
|
||||||
|
version="1.1"
|
||||||
|
id="svg8"
|
||||||
|
inkscape:version="0.92.4 5da689c313, 2019-01-14"
|
||||||
|
sodipodi:docname="item_status_right.svg"
|
||||||
|
inkscape:export-filename="/home/pj/Projects/space-station-14/Resources/Nano/item_status_right.svg.96dpi.png"
|
||||||
|
inkscape:export-xdpi="96.000008"
|
||||||
|
inkscape:export-ydpi="96.000008">
|
||||||
|
<defs
|
||||||
|
id="defs2" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="22.627417"
|
||||||
|
inkscape:cx="-2.4386852"
|
||||||
|
inkscape:cy="13.122502"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:pagecheckerboard="true"
|
||||||
|
units="px"
|
||||||
|
showguides="true"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1043"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="0"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:guide-bbox="true"
|
||||||
|
inkscape:snap-intersection-paths="true"
|
||||||
|
inkscape:snap-bbox="true"
|
||||||
|
inkscape:snap-page="true">
|
||||||
|
<inkscape:grid
|
||||||
|
type="xygrid"
|
||||||
|
id="grid817" />
|
||||||
|
<sodipodi:guide
|
||||||
|
position="2.645833,3.0000002e-07"
|
||||||
|
orientation="0.70710806,0.7071055"
|
||||||
|
id="guide819"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<metadata
|
||||||
|
id="metadata5">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title />
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1"
|
||||||
|
transform="translate(-26.597681,-208.71661)">
|
||||||
|
<path
|
||||||
|
style="opacity:1;vector-effect:none;fill:#25252a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.26458335;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||||
|
d="m 30.831015,212.94995 h -4.233334 v -1.58751 l 2.645833,-2.64583 1.587501,-1e-5 z"
|
||||||
|
id="rect815"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="cccccc" />
|
||||||
|
<path
|
||||||
|
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#474747;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.26458335;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
d="m 45.902791,212.76114 v 3.23047 l 1.003906,1.00195 h 3.228516 v -3.22852 l -1.001953,-1.0039 h -0.05469 z m 0.263672,0.26367 h 2.855469 l 0.849609,0.84961 v 2.85547 h -2.855468 l -0.84961,-0.84961 z"
|
||||||
|
id="rect815-3"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#474747;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.26458335;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
d="m 46.344997,207.34832 -0.290893,0.17906 1.133594,1.1102 v 2.91047 h 0.264579 v -3.04271 z"
|
||||||
|
id="rect815-6"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="ccccccc" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#474747;stroke-width:0.5291667;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="m 38.473823,212.26371 v -3.175 l -1.058333,-1.05833"
|
||||||
|
id="path856-6"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="ccc" />
|
||||||
|
<path
|
||||||
|
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#474747;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.5291667;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
d="m 29.243514,208.71661 h 0.748024 l -2.86456,2.86457 v 1.36874 h -0.529297 v -1.58749 z"
|
||||||
|
id="path856-7"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="ccccccc" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 7.3 KiB |
BIN
Resources/Nano/item_status_right.svg.96dpi.png
Normal file
|
After Width: | Height: | Size: 228 B |
@@ -206,6 +206,7 @@
|
|||||||
- A65mm
|
- A65mm
|
||||||
default_magazine: magazine_65mm
|
default_magazine: magazine_65mm
|
||||||
auto_eject_magazine: true
|
auto_eject_magazine: true
|
||||||
|
lmg_alarm_animation: true
|
||||||
sound_auto_eject: /Audio/Guns/EmptyAlarm/lmg_empty_alarm.ogg
|
sound_auto_eject: /Audio/Guns/EmptyAlarm/lmg_empty_alarm.ogg
|
||||||
sound_gunshot: /Audio/Guns/Gunshots/rifle.ogg
|
sound_gunshot: /Audio/Guns/Gunshots/rifle.ogg
|
||||||
- type: Appearance
|
- type: Appearance
|
||||||
@@ -240,6 +241,7 @@
|
|||||||
- A65mm
|
- A65mm
|
||||||
default_magazine: magazine_65mm
|
default_magazine: magazine_65mm
|
||||||
auto_eject_magazine: true
|
auto_eject_magazine: true
|
||||||
|
lmg_alarm_animation: true
|
||||||
sound_auto_eject: /Audio/Guns/EmptyAlarm/lmg_empty_alarm.ogg
|
sound_auto_eject: /Audio/Guns/EmptyAlarm/lmg_empty_alarm.ogg
|
||||||
sound_gunshot: /Audio/Guns/Gunshots/rifle.ogg
|
sound_gunshot: /Audio/Guns/Gunshots/rifle.ogg
|
||||||
- type: Appearance
|
- type: Appearance
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
components:
|
components:
|
||||||
- type: Stack
|
- type: Stack
|
||||||
- type: Material
|
- type: Material
|
||||||
|
- type: ItemStatus
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
name: Steel Sheet
|
name: Steel Sheet
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
- type: MeleeWeapon
|
- type: MeleeWeapon
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
name: Welder
|
name: Welding Tool
|
||||||
parent: BaseItem
|
parent: BaseItem
|
||||||
id: Welder
|
id: Welder
|
||||||
description: Melts anything as long as it's fueled, don't forget your eye protection!
|
description: Melts anything as long as it's fueled, don't forget your eye protection!
|
||||||
@@ -46,6 +46,7 @@
|
|||||||
state: welder
|
state: welder
|
||||||
- type: ItemCooldown
|
- type: ItemCooldown
|
||||||
- type: MeleeWeapon
|
- type: MeleeWeapon
|
||||||
|
- type: ItemStatus
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
name: Wrench
|
name: Wrench
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 954 B After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 926 B After Width: | Height: | Size: 1.2 KiB |
BIN
Resources/Textures/UserInterface/status/bullets/chambered.png
Normal file
|
After Width: | Height: | Size: 496 B |
BIN
Resources/Textures/UserInterface/status/bullets/normal.png
Normal file
|
After Width: | Height: | Size: 498 B |
BIN
Resources/Textures/UserInterface/status/bullets/small.png
Normal file
|
After Width: | Height: | Size: 497 B |
BIN
Resources/Textures/UserInterface/status/bullets/tiny.png
Normal file
|
After Width: | Height: | Size: 479 B |