Shitty combat mode & animations. (#367)
* Combat mode UI & targeting zones. * Fix inventory hud positioning. * Crappy attack animations. * Import TG combat sounds * More work on arcs. * Implement hit sounds. * Lunging, hit effects, some more stuff.
@@ -62,7 +62,6 @@ namespace Content.Client
|
||||
"EmitSoundOnUse",
|
||||
"FootstepModifier",
|
||||
"HeatResistance",
|
||||
"CombatMode",
|
||||
"Teleportable",
|
||||
"ItemTeleporter",
|
||||
"Portal",
|
||||
|
||||
@@ -29,6 +29,10 @@ namespace Content.Client.GameObjects.Components.Mobs
|
||||
|
||||
private EyeComponent _eye;
|
||||
|
||||
// Basically I needed a way to chain this effect for the attack lunge animation.
|
||||
// Sorry!
|
||||
public Vector2 BaseOffset { get; set; }
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
@@ -95,7 +99,7 @@ namespace Content.Client.GameObjects.Components.Mobs
|
||||
|
||||
private void _updateEye()
|
||||
{
|
||||
_eye.Offset = _currentKick;
|
||||
_eye.Offset = BaseOffset + _currentKick;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
using Content.Client.UserInterface;
|
||||
using Content.Shared.GameObjects.Components.Mobs;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Interfaces.GameObjects;
|
||||
using Robust.Shared.Interfaces.Network;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Content.Client.GameObjects.Components.Mobs
|
||||
{
|
||||
[RegisterComponent]
|
||||
public sealed class CombatModeComponent : SharedCombatModeComponent
|
||||
{
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public bool IsInCombatMode { get; private set; }
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public TargetingZone ActiveZone { get; private set; }
|
||||
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly IGameHud _gameHud;
|
||||
#pragma warning restore 649
|
||||
|
||||
public override void HandleComponentState(ComponentState curState, ComponentState nextState)
|
||||
{
|
||||
base.HandleComponentState(curState, nextState);
|
||||
|
||||
var state = (CombatModeComponentState) curState;
|
||||
|
||||
IsInCombatMode = state.IsInCombatMode;
|
||||
ActiveZone = state.TargetingZone;
|
||||
UpdateHud();
|
||||
}
|
||||
|
||||
public override void HandleMessage(ComponentMessage message, INetChannel netChannel = null, IComponent component = null)
|
||||
{
|
||||
base.HandleMessage(message, netChannel, component);
|
||||
|
||||
switch (message)
|
||||
{
|
||||
case PlayerAttachedMsg _:
|
||||
_gameHud.CombatPanelVisible = true;
|
||||
UpdateHud();
|
||||
break;
|
||||
|
||||
case PlayerDetachedMsg _:
|
||||
_gameHud.CombatPanelVisible = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateHud()
|
||||
{
|
||||
_gameHud.CombatModeActive = IsInCombatMode;
|
||||
_gameHud.TargetingZone = ActiveZone;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.Interfaces.GameObjects.Components;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Maths;
|
||||
|
||||
namespace Content.Client.GameObjects.Components.Mobs
|
||||
{
|
||||
[RegisterComponent]
|
||||
public sealed class MeleeLungeComponent : Component
|
||||
{
|
||||
public override string Name => "MeleeLunge";
|
||||
|
||||
private const float ResetTime = 0.3f;
|
||||
private const float BaseOffset = 0.25f;
|
||||
|
||||
private Angle _angle;
|
||||
private float _time;
|
||||
|
||||
public void SetData(Angle angle)
|
||||
{
|
||||
_angle = angle;
|
||||
_time = 0;
|
||||
}
|
||||
|
||||
public void Update(float frameTime)
|
||||
{
|
||||
_time += frameTime;
|
||||
|
||||
var offset = Vector2.Zero;
|
||||
var deleteSelf = false;
|
||||
|
||||
if (_time > ResetTime)
|
||||
{
|
||||
deleteSelf = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
offset = _angle.RotateVec((BaseOffset, 0));
|
||||
offset *= (ResetTime - _time) / ResetTime;
|
||||
}
|
||||
|
||||
if (Owner.TryGetComponent(out CameraRecoilComponent recoilComponent))
|
||||
{
|
||||
recoilComponent.BaseOffset = offset;
|
||||
}
|
||||
else if (Owner.TryGetComponent(out EyeComponent eyeComponent))
|
||||
{
|
||||
eyeComponent.Offset = offset;
|
||||
}
|
||||
|
||||
if (Owner.TryGetComponent(out ISpriteComponent spriteComponent))
|
||||
{
|
||||
// We have to account for rotation so the offset still checks out.
|
||||
// SpriteComponent.Offset is applied before transform rotation (as expected).
|
||||
var worldRotation = Owner.Transform.WorldRotation;
|
||||
spriteComponent.Offset = new Angle(-worldRotation).RotateVec(offset);
|
||||
}
|
||||
|
||||
if (deleteSelf)
|
||||
{
|
||||
Owner.RemoveComponent<MeleeLungeComponent>();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
using Content.Shared.GameObjects.Components.Weapons.Melee;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Maths;
|
||||
|
||||
namespace Content.Client.GameObjects.Components.Weapons.Melee
|
||||
{
|
||||
[RegisterComponent]
|
||||
public sealed class MeleeWeaponArcAnimationComponent : Component
|
||||
{
|
||||
public override string Name => "MeleeWeaponArcAnimation";
|
||||
|
||||
private MeleeWeaponAnimationPrototype _meleeWeaponAnimation;
|
||||
|
||||
private float _timer;
|
||||
private SpriteComponent _sprite;
|
||||
private Angle _baseAngle;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
_sprite = Owner.GetComponent<SpriteComponent>();
|
||||
}
|
||||
|
||||
public void SetData(MeleeWeaponAnimationPrototype prototype, Angle baseAngle)
|
||||
{
|
||||
_meleeWeaponAnimation = prototype;
|
||||
_sprite.AddLayer(new RSI.StateId(prototype.State));
|
||||
_baseAngle = baseAngle;
|
||||
}
|
||||
|
||||
internal void Update(float frameTime)
|
||||
{
|
||||
if (_meleeWeaponAnimation == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_timer += frameTime;
|
||||
|
||||
var (r, g, b, a) =
|
||||
Vector4.Clamp(_meleeWeaponAnimation.Color + _meleeWeaponAnimation.ColorDelta * _timer, Vector4.Zero, Vector4.One);
|
||||
_sprite.Color = new Color(r, g, b, a);
|
||||
|
||||
switch (_meleeWeaponAnimation.ArcType)
|
||||
{
|
||||
case WeaponArcType.Slash:
|
||||
var angle = Angle.FromDegrees(_meleeWeaponAnimation.Width)/2;
|
||||
Owner.Transform.LocalRotation =
|
||||
_baseAngle + Angle.Lerp(-angle, angle, (float) (_timer / _meleeWeaponAnimation.Length.TotalSeconds));
|
||||
break;
|
||||
|
||||
case WeaponArcType.Poke:
|
||||
_sprite.Offset += (_meleeWeaponAnimation.Speed * frameTime, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (_meleeWeaponAnimation.Length.TotalSeconds <= _timer)
|
||||
{
|
||||
Owner.Delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
33
Content.Client/GameObjects/EntitySystems/CombatModeSystem.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using Content.Client.UserInterface;
|
||||
using Content.Shared.GameObjects.Components.Mobs;
|
||||
using Content.Shared.GameObjects.EntitySystemMessages;
|
||||
using Robust.Shared.GameObjects.Systems;
|
||||
using Robust.Shared.IoC;
|
||||
|
||||
namespace Content.Client.GameObjects.EntitySystems
|
||||
{
|
||||
public sealed class CombatModeSystem : EntitySystem
|
||||
{
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly IGameHud _gameHud;
|
||||
#pragma warning restore 649
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
_gameHud.OnCombatModeChanged = OnCombatModeChanged;
|
||||
_gameHud.OnTargetingZoneChanged = OnTargetingZoneChanged;
|
||||
}
|
||||
|
||||
private void OnTargetingZoneChanged(TargetingZone obj)
|
||||
{
|
||||
RaiseNetworkEvent(new CombatModeSystemMessages.SetTargetZoneMessage(obj));
|
||||
}
|
||||
|
||||
private void OnCombatModeChanged(bool obj)
|
||||
{
|
||||
RaiseNetworkEvent(new CombatModeSystemMessages.SetCombatModeActiveMessage(obj));
|
||||
}
|
||||
}
|
||||
}
|
||||
28
Content.Client/GameObjects/EntitySystems/MeleeLungeSystem.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using Content.Client.GameObjects.Components.Mobs;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameObjects.Systems;
|
||||
|
||||
namespace Content.Client.GameObjects.EntitySystems
|
||||
{
|
||||
[UsedImplicitly]
|
||||
public sealed class MeleeLungeSystem : EntitySystem
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
EntityQuery = new TypeEntityQuery<MeleeLungeComponent>();
|
||||
}
|
||||
|
||||
public override void FrameUpdate(float frameTime)
|
||||
{
|
||||
base.FrameUpdate(frameTime);
|
||||
|
||||
foreach (var entity in RelevantEntities)
|
||||
{
|
||||
entity.GetComponent<MeleeLungeComponent>().Update(frameTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
101
Content.Client/GameObjects/EntitySystems/MeleeWeaponSystem.cs
Normal file
@@ -0,0 +1,101 @@
|
||||
using System.Linq;
|
||||
using Content.Client.GameObjects.Components.Mobs;
|
||||
using Content.Client.GameObjects.Components.Weapons.Melee;
|
||||
using Content.Shared.GameObjects.Components.Weapons.Melee;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.Interfaces.GameObjects.Components;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameObjects.Systems;
|
||||
using Robust.Shared.Interfaces.Network;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Timers;
|
||||
using static Content.Shared.GameObjects.EntitySystemMessages.MeleeWeaponSystemMessages;
|
||||
|
||||
namespace Content.Client.GameObjects.EntitySystems
|
||||
{
|
||||
[UsedImplicitly]
|
||||
public sealed class MeleeWeaponSystem : EntitySystem
|
||||
{
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager;
|
||||
#pragma warning restore 649
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
EntityQuery = new TypeEntityQuery(typeof(MeleeWeaponArcAnimationComponent));
|
||||
}
|
||||
|
||||
public override void RegisterMessageTypes()
|
||||
{
|
||||
base.RegisterMessageTypes();
|
||||
|
||||
RegisterMessageType<PlayMeleeWeaponAnimationMessage>();
|
||||
}
|
||||
|
||||
public override void HandleNetMessage(INetChannel channel, EntitySystemMessage message)
|
||||
{
|
||||
base.HandleNetMessage(channel, message);
|
||||
|
||||
switch (message)
|
||||
{
|
||||
case PlayMeleeWeaponAnimationMessage playMsg:
|
||||
PlayWeaponArc(playMsg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override void FrameUpdate(float frameTime)
|
||||
{
|
||||
base.FrameUpdate(frameTime);
|
||||
|
||||
foreach (var entity in RelevantEntities)
|
||||
{
|
||||
entity.GetComponent<MeleeWeaponArcAnimationComponent>().Update(frameTime);
|
||||
}
|
||||
}
|
||||
|
||||
private void PlayWeaponArc(PlayMeleeWeaponAnimationMessage msg)
|
||||
{
|
||||
if (!_prototypeManager.TryIndex(msg.ArcPrototype, out MeleeWeaponAnimationPrototype weaponArc))
|
||||
{
|
||||
Logger.Error("Tried to play unknown weapon arc prototype '{0}'", msg.ArcPrototype);
|
||||
return;
|
||||
}
|
||||
|
||||
var attacker = EntityManager.GetEntity(msg.Attacker);
|
||||
|
||||
var lunge = attacker.EnsureComponent<MeleeLungeComponent>();
|
||||
lunge.SetData(msg.Angle);
|
||||
|
||||
var entity = EntityManager.SpawnEntityAt("WeaponArc", attacker.Transform.GridPosition);
|
||||
entity.Transform.LocalRotation = msg.Angle;
|
||||
|
||||
var weaponArcAnimation = entity.GetComponent<MeleeWeaponArcAnimationComponent>();
|
||||
weaponArcAnimation.SetData(weaponArc, msg.Angle);
|
||||
|
||||
|
||||
foreach (var hitEntity in msg.Hits.Select(u => EntityManager.GetEntity(u)))
|
||||
{
|
||||
if (!hitEntity.TryGetComponent(out ISpriteComponent sprite)) continue;
|
||||
|
||||
var originalColor = sprite.Color;
|
||||
var newColor = Color.Red * originalColor;
|
||||
sprite.Color = newColor;
|
||||
|
||||
Timer.Spawn(100, () =>
|
||||
{
|
||||
// Only reset back to the original color if something else didn't change the color in the mean time.
|
||||
if (sprite.Color == newColor)
|
||||
{
|
||||
sprite.Color = originalColor;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -27,8 +27,7 @@ namespace Content.Client.Input
|
||||
human.AddFunction(ContentKeyFunctions.OpenCraftingMenu);
|
||||
human.AddFunction(ContentKeyFunctions.OpenInventoryMenu);
|
||||
human.AddFunction(ContentKeyFunctions.MouseMiddle);
|
||||
// Disabled until there is feedback, so hitting tab doesn't suddenly break interaction.
|
||||
// human.AddFunction(ContentKeyFunctions.ToggleCombatMode);
|
||||
human.AddFunction(ContentKeyFunctions.ToggleCombatMode);
|
||||
|
||||
var ghost = contexts.New("ghost", "common");
|
||||
ghost.AddFunction(EngineKeyFunctions.MoveUp);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using Content.Client.Utility;
|
||||
using Content.Shared.GameObjects.Components.Mobs;
|
||||
using Content.Shared.Input;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.Graphics.Drawing;
|
||||
@@ -48,6 +49,13 @@ namespace Content.Client.UserInterface
|
||||
Control HandsContainer { get; }
|
||||
Control InventoryQuickButtonContainer { get; }
|
||||
|
||||
bool CombatPanelVisible { get; set; }
|
||||
bool CombatModeActive { get; set; }
|
||||
TargetingZone TargetingZone { get; set; }
|
||||
Action<bool> OnCombatModeChanged { get; set; }
|
||||
Action<TargetingZone> OnTargetingZoneChanged { get; set; }
|
||||
|
||||
|
||||
// Init logic.
|
||||
void Initialize();
|
||||
}
|
||||
@@ -62,6 +70,9 @@ namespace Content.Client.UserInterface
|
||||
private TopButton _buttonCraftingMenu;
|
||||
private TopButton _buttonSandboxMenu;
|
||||
private TutorialWindow _tutorialWindow;
|
||||
private TargetingDoll _targetingDoll;
|
||||
private Button _combatModeButton;
|
||||
private VBoxContainer _combatPanelContainer;
|
||||
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly IResourceCache _resourceCache;
|
||||
@@ -71,6 +82,26 @@ namespace Content.Client.UserInterface
|
||||
|
||||
public Control HandsContainer { get; private set; }
|
||||
public Control InventoryQuickButtonContainer { get; private set; }
|
||||
public bool CombatPanelVisible
|
||||
{
|
||||
get => _combatPanelContainer.Visible;
|
||||
set => _combatPanelContainer.Visible = value;
|
||||
}
|
||||
|
||||
public bool CombatModeActive
|
||||
{
|
||||
get => _combatModeButton.Pressed;
|
||||
set => _combatModeButton.Pressed = value;
|
||||
}
|
||||
|
||||
public TargetingZone TargetingZone
|
||||
{
|
||||
get => _targetingDoll.ActiveZone;
|
||||
set => _targetingDoll.ActiveZone = value;
|
||||
}
|
||||
|
||||
public Action<bool> OnCombatModeChanged { get; set; }
|
||||
public Action<TargetingZone> OnTargetingZoneChanged { get; set; }
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
@@ -179,16 +210,35 @@ namespace Content.Client.UserInterface
|
||||
{
|
||||
GrowHorizontal = Control.GrowDirection.Begin,
|
||||
GrowVertical = Control.GrowDirection.Begin,
|
||||
SizeFlagsVertical = Control.SizeFlags.ShrinkEnd
|
||||
};
|
||||
|
||||
HandsContainer = new MarginContainer
|
||||
{
|
||||
GrowHorizontal = Control.GrowDirection.Both,
|
||||
GrowVertical = Control.GrowDirection.Begin
|
||||
GrowVertical = Control.GrowDirection.Begin,
|
||||
SizeFlagsVertical = Control.SizeFlags.ShrinkEnd
|
||||
};
|
||||
|
||||
_combatPanelContainer = new VBoxContainer
|
||||
{
|
||||
Children =
|
||||
{
|
||||
(_combatModeButton = new Button
|
||||
{
|
||||
Text = _loc.GetString("Combat Mode"),
|
||||
ToggleMode = true
|
||||
}),
|
||||
(_targetingDoll = new TargetingDoll(_resourceCache))
|
||||
}
|
||||
};
|
||||
|
||||
_combatModeButton.OnToggled += args => OnCombatModeChanged?.Invoke(args.Pressed);
|
||||
_targetingDoll.OnZoneChanged += args => OnTargetingZoneChanged?.Invoke(args);
|
||||
|
||||
inventoryContainer.Children.Add(HandsContainer);
|
||||
inventoryContainer.Children.Add(InventoryQuickButtonContainer);
|
||||
inventoryContainer.Children.Add(_combatPanelContainer);
|
||||
}
|
||||
|
||||
private void ButtonTutorialOnOnToggled()
|
||||
|
||||
@@ -481,6 +481,23 @@ namespace Content.Client.UserInterface
|
||||
{
|
||||
new StyleProperty(Label.StylePropertyFont, notoSansDisplayBold14),
|
||||
}),
|
||||
|
||||
// Targeting doll
|
||||
|
||||
new StyleRule(new SelectorElement(typeof(TextureButton), new []{TargetingDoll.StyleClassTargetDollZone}, null, new [] {TextureButton.StylePseudoClassNormal}), new []
|
||||
{
|
||||
new StyleProperty(Control.StylePropertyModulateSelf, Color.FromHex("#F00")),
|
||||
}),
|
||||
|
||||
new StyleRule(new SelectorElement(typeof(TextureButton), new []{TargetingDoll.StyleClassTargetDollZone}, null, new [] {TextureButton.StylePseudoClassHover}), new []
|
||||
{
|
||||
new StyleProperty(Control.StylePropertyModulateSelf, Color.FromHex("#0F0")),
|
||||
}),
|
||||
|
||||
new StyleRule(new SelectorElement(typeof(TextureButton), new []{TargetingDoll.StyleClassTargetDollZone}, null, new [] {TextureButton.StylePseudoClassPressed}), new []
|
||||
{
|
||||
new StyleProperty(Control.StylePropertyModulateSelf, Color.FromHex("#00F")),
|
||||
}),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
82
Content.Client/UserInterface/TargetingDoll.cs
Normal file
@@ -0,0 +1,82 @@
|
||||
using System;
|
||||
using Content.Client.Utility;
|
||||
using Content.Shared.GameObjects.Components.Mobs;
|
||||
using Robust.Client.Interfaces.ResourceManagement;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
|
||||
namespace Content.Client.UserInterface
|
||||
{
|
||||
public sealed class TargetingDoll : VBoxContainer
|
||||
{
|
||||
private TargetingZone _activeZone = TargetingZone.Middle;
|
||||
public const string StyleClassTargetDollZone = "target-doll-zone";
|
||||
|
||||
private const string TextureHigh = "/Textures/UserInterface/target-doll-high.svg.96dpi.png";
|
||||
private const string TextureMiddle = "/Textures/UserInterface/target-doll-middle.svg.96dpi.png";
|
||||
private const string TextureLow = "/Textures/UserInterface/target-doll-low.svg.96dpi.png";
|
||||
|
||||
private readonly TextureButton _buttonHigh;
|
||||
private readonly TextureButton _buttonMiddle;
|
||||
private readonly TextureButton _buttonLow;
|
||||
|
||||
public TargetingZone ActiveZone
|
||||
{
|
||||
get => _activeZone;
|
||||
set
|
||||
{
|
||||
if (_activeZone == value)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_activeZone = value;
|
||||
OnZoneChanged?.Invoke(value);
|
||||
|
||||
UpdateButtons();
|
||||
}
|
||||
}
|
||||
|
||||
public event Action<TargetingZone> OnZoneChanged;
|
||||
|
||||
public TargetingDoll(IResourceCache resourceCache)
|
||||
{
|
||||
_buttonHigh = new TextureButton
|
||||
{
|
||||
TextureNormal = resourceCache.GetTexture(TextureHigh),
|
||||
StyleClasses = {StyleClassTargetDollZone},
|
||||
SizeFlagsHorizontal = SizeFlags.ShrinkCenter
|
||||
};
|
||||
|
||||
_buttonMiddle = new TextureButton
|
||||
{
|
||||
TextureNormal = resourceCache.GetTexture(TextureMiddle),
|
||||
StyleClasses = {StyleClassTargetDollZone},
|
||||
SizeFlagsHorizontal = SizeFlags.ShrinkCenter
|
||||
};
|
||||
|
||||
_buttonLow = new TextureButton
|
||||
{
|
||||
TextureNormal = resourceCache.GetTexture(TextureLow),
|
||||
StyleClasses = {StyleClassTargetDollZone},
|
||||
SizeFlagsHorizontal = SizeFlags.ShrinkCenter
|
||||
};
|
||||
|
||||
_buttonHigh.OnPressed += _ => ActiveZone = TargetingZone.High;
|
||||
_buttonMiddle.OnPressed += _ => ActiveZone = TargetingZone.Middle;
|
||||
_buttonLow.OnPressed += _ => ActiveZone = TargetingZone.Low;
|
||||
|
||||
AddChild(_buttonHigh);
|
||||
AddChild(_buttonMiddle);
|
||||
AddChild(_buttonLow);
|
||||
|
||||
UpdateButtons();
|
||||
}
|
||||
|
||||
private void UpdateButtons()
|
||||
{
|
||||
_buttonHigh.Pressed = _activeZone == TargetingZone.High;
|
||||
_buttonMiddle.Pressed = _activeZone == TargetingZone.Middle;
|
||||
_buttonLow.Pressed = _activeZone == TargetingZone.Low;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
using Content.Shared.GameObjects.Components.Mobs;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
@@ -9,11 +10,36 @@ namespace Content.Server.GameObjects.Components.Mobs
|
||||
/// using *everything* as a weapon.
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
public sealed class CombatModeComponent : Component
|
||||
public sealed class CombatModeComponent : SharedCombatModeComponent
|
||||
{
|
||||
public override string Name => "CombatMode";
|
||||
private bool _isInCombatMode;
|
||||
private TargetingZone _activeZone;
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public bool IsInCombatMode { get; set; }
|
||||
public bool IsInCombatMode
|
||||
{
|
||||
get => _isInCombatMode;
|
||||
set
|
||||
{
|
||||
_isInCombatMode = value;
|
||||
Dirty();
|
||||
}
|
||||
}
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public TargetingZone ActiveZone
|
||||
{
|
||||
get => _activeZone;
|
||||
set
|
||||
{
|
||||
_activeZone = value;
|
||||
Dirty();
|
||||
}
|
||||
}
|
||||
|
||||
public override ComponentState GetComponentState()
|
||||
{
|
||||
return new CombatModeComponentState(IsInCombatMode, ActiveZone);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,43 +1,91 @@
|
||||
using Content.Server.GameObjects.EntitySystems;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Content.Server.GameObjects.Components.Mobs;
|
||||
using Content.Server.GameObjects.EntitySystems;
|
||||
using Content.Shared.GameObjects;
|
||||
using Robust.Server.GameObjects.EntitySystems;
|
||||
using Robust.Server.Interfaces.GameObjects;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Interfaces.GameObjects;
|
||||
using Robust.Shared.Interfaces.Map;
|
||||
using Robust.Shared.Interfaces.Timing;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Content.Server.GameObjects.Components.Weapon.Melee
|
||||
{
|
||||
[RegisterComponent]
|
||||
public class MeleeWeaponComponent : Component, IAttack
|
||||
{
|
||||
public override string Name => "MeleeWeapon";
|
||||
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly IMapManager _mapManager;
|
||||
[Dependency] private readonly IServerEntityManager _serverEntityManager;
|
||||
[Dependency] private readonly IEntitySystemManager _entitySystemManager;
|
||||
[Dependency] private readonly IGameTiming _gameTiming;
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager;
|
||||
#pragma warning restore 649
|
||||
|
||||
public override string Name => "MeleeWeapon";
|
||||
private int _damage = 1;
|
||||
private float _range = 1;
|
||||
private float _arcWidth = 90;
|
||||
private string _arc;
|
||||
private string _hitSound;
|
||||
|
||||
public int Damage = 1;
|
||||
public float Range = 1;
|
||||
public float ArcWidth = 90;
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public string Arc
|
||||
{
|
||||
get => _arc;
|
||||
set => _arc = value;
|
||||
}
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public float ArcWidth
|
||||
{
|
||||
get => _arcWidth;
|
||||
set => _arcWidth = value;
|
||||
}
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public float Range
|
||||
{
|
||||
get => _range;
|
||||
set => _range = value;
|
||||
}
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public int Damage
|
||||
{
|
||||
get => _damage;
|
||||
set => _damage = value;
|
||||
}
|
||||
|
||||
public override void ExposeData(ObjectSerializer serializer)
|
||||
{
|
||||
base.ExposeData(serializer);
|
||||
|
||||
serializer.DataField(ref Damage, "damage", 5);
|
||||
serializer.DataField(ref Range, "range", 1);
|
||||
serializer.DataField(ref ArcWidth, "arcwidth", 90);
|
||||
serializer.DataField(ref _damage, "damage", 5);
|
||||
serializer.DataField(ref _range, "range", 1);
|
||||
serializer.DataField(ref _arcWidth, "arcwidth", 90);
|
||||
serializer.DataField(ref _arc, "arc", "default");
|
||||
serializer.DataField(ref _hitSound, "hitSound", "/Audio/weapons/genhit1.ogg");
|
||||
}
|
||||
|
||||
void IAttack.Attack(AttackEventArgs eventArgs)
|
||||
{
|
||||
var location = eventArgs.User.Transform.GridPosition;
|
||||
var angle = new Angle(eventArgs.ClickLocation.ToWorld(_mapManager).Position - location.ToWorld(_mapManager).Position);
|
||||
var entities = _serverEntityManager.GetEntitiesInArc(eventArgs.User.Transform.GridPosition, Range, angle, ArcWidth);
|
||||
var angle = new Angle(eventArgs.ClickLocation.ToWorld(_mapManager).Position -
|
||||
location.ToWorld(_mapManager).Position);
|
||||
|
||||
// This should really be improved. GetEntitiesInArc uses pos instead of bounding boxes.
|
||||
var entities =
|
||||
_serverEntityManager.GetEntitiesInArc(eventArgs.User.Transform.GridPosition, Range, angle, ArcWidth);
|
||||
|
||||
var hitEntities = new List<IEntity>();
|
||||
foreach (var entity in entities)
|
||||
{
|
||||
if (!entity.Transform.IsMapTransform || entity == eventArgs.User)
|
||||
@@ -46,7 +94,17 @@ namespace Content.Server.GameObjects.Components.Weapon.Melee
|
||||
if (entity.TryGetComponent(out DamageableComponent damageComponent))
|
||||
{
|
||||
damageComponent.TakeDamage(DamageType.Brute, Damage);
|
||||
}
|
||||
hitEntities.Add(entity);
|
||||
}
|
||||
}
|
||||
|
||||
var audioSystem = _entitySystemManager.GetEntitySystem<AudioSystem>();
|
||||
audioSystem.Play(hitEntities.Count > 0 ? _hitSound : "/Audio/weapons/punchmiss.ogg");
|
||||
|
||||
if (Arc != null)
|
||||
{
|
||||
var sys = _entitySystemManager.GetEntitySystem<MeleeWeaponSystem>();
|
||||
sys.SendAnimation(Arc, angle, eventArgs.User, hitEntities);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,25 @@
|
||||
using Content.Server.GameObjects.Components.Mobs;
|
||||
using Content.Shared.Input;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Server.GameObjects.EntitySystems;
|
||||
using Robust.Server.Interfaces.Player;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameObjects.Systems;
|
||||
using Robust.Shared.Input;
|
||||
using Robust.Shared.Interfaces.Network;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Players;
|
||||
using static Content.Shared.GameObjects.EntitySystemMessages.CombatModeSystemMessages;
|
||||
|
||||
namespace Content.Server.GameObjects.EntitySystems
|
||||
{
|
||||
[UsedImplicitly]
|
||||
public sealed class CombatModeSystem : EntitySystem
|
||||
{
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly IPlayerManager _playerManager;
|
||||
#pragma warning restore 649
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
@@ -19,7 +29,15 @@ namespace Content.Server.GameObjects.EntitySystems
|
||||
InputCmdHandler.FromDelegate(CombatModeToggled));
|
||||
}
|
||||
|
||||
private void CombatModeToggled(ICommonSession session)
|
||||
public override void RegisterMessageTypes()
|
||||
{
|
||||
base.RegisterMessageTypes();
|
||||
|
||||
RegisterMessageType<SetTargetZoneMessage>();
|
||||
RegisterMessageType<SetCombatModeActiveMessage>();
|
||||
}
|
||||
|
||||
private static void CombatModeToggled(ICommonSession session)
|
||||
{
|
||||
var playerSession = (IPlayerSession) session;
|
||||
|
||||
@@ -31,5 +49,28 @@ namespace Content.Server.GameObjects.EntitySystems
|
||||
|
||||
combatModeComponent.IsInCombatMode = !combatModeComponent.IsInCombatMode;
|
||||
}
|
||||
|
||||
public override void HandleNetMessage(INetChannel channel, EntitySystemMessage message)
|
||||
{
|
||||
base.HandleNetMessage(channel, message);
|
||||
|
||||
var player = _playerManager.GetSessionByChannel(channel);
|
||||
if (player.AttachedEntity == null
|
||||
|| !player.AttachedEntity.TryGetComponent(out CombatModeComponent combatModeComponent))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (message)
|
||||
{
|
||||
case SetTargetZoneMessage setTargetZone:
|
||||
combatModeComponent.ActiveZone = setTargetZone.TargetZone;
|
||||
break;
|
||||
|
||||
case SetCombatModeActiveMessage setActive:
|
||||
combatModeComponent.IsInCombatMode = setActive.Active;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Content.Shared.GameObjects.EntitySystemMessages;
|
||||
using Robust.Shared.GameObjects.Systems;
|
||||
using Robust.Shared.Interfaces.GameObjects;
|
||||
using Robust.Shared.Maths;
|
||||
|
||||
namespace Content.Server.GameObjects.EntitySystems
|
||||
{
|
||||
public sealed class MeleeWeaponSystem : EntitySystem
|
||||
{
|
||||
public void SendAnimation(string arc, Angle angle, IEntity attacker, IEnumerable<IEntity> hits)
|
||||
{
|
||||
RaiseNetworkEvent(new MeleeWeaponSystemMessages.PlayMeleeWeaponAnimationMessage(arc, angle, attacker.Uid,
|
||||
hits.Select(e => e.Uid).ToList()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared.GameObjects.Components.Mobs
|
||||
{
|
||||
public abstract class SharedCombatModeComponent : Component
|
||||
{
|
||||
public sealed override uint? NetID => ContentNetIDs.COMBATMODE;
|
||||
public override string Name => "CombatMode";
|
||||
public sealed override Type StateType => typeof(CombatModeComponentState);
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
protected sealed class CombatModeComponentState : ComponentState
|
||||
{
|
||||
public bool IsInCombatMode { get; }
|
||||
public TargetingZone TargetingZone { get; }
|
||||
|
||||
public CombatModeComponentState(bool isInCombatMode, TargetingZone targetingZone)
|
||||
: base(ContentNetIDs.COMBATMODE)
|
||||
{
|
||||
IsInCombatMode = isInCombatMode;
|
||||
TargetingZone = targetingZone;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
27
Content.Shared/GameObjects/Components/Mobs/TargetingZone.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared.GameObjects.Components.Mobs
|
||||
{
|
||||
/// <summary>
|
||||
/// Zones the player can target for attacks.
|
||||
/// </summary>
|
||||
[Serializable, NetSerializable]
|
||||
public enum TargetingZone
|
||||
{
|
||||
/// <summary>
|
||||
/// Torso/arm area.
|
||||
/// </summary>
|
||||
Middle,
|
||||
|
||||
/// <summary>
|
||||
/// Legs/groin area.
|
||||
/// </summary>
|
||||
Low,
|
||||
|
||||
/// <summary>
|
||||
/// Go for the head.
|
||||
/// </summary>
|
||||
High
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
using System;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.ViewVariables;
|
||||
using YamlDotNet.RepresentationModel;
|
||||
|
||||
namespace Content.Shared.GameObjects.Components.Weapons.Melee
|
||||
{
|
||||
[Prototype("MeleeWeaponAnimation")]
|
||||
public sealed class MeleeWeaponAnimationPrototype : IPrototype, IIndexedPrototype
|
||||
{
|
||||
private string _state;
|
||||
private string _id;
|
||||
private Vector4 _colorDelta;
|
||||
private Vector4 _color;
|
||||
private TimeSpan _length;
|
||||
private float _speed;
|
||||
private float _width;
|
||||
private WeaponArcType _arcType;
|
||||
|
||||
[ViewVariables] public string ID => _id;
|
||||
[ViewVariables] public string State => _state;
|
||||
[ViewVariables] public TimeSpan Length => _length;
|
||||
[ViewVariables] public float Speed => _speed;
|
||||
[ViewVariables] public Vector4 Color => _color;
|
||||
[ViewVariables] public Vector4 ColorDelta => _colorDelta;
|
||||
[ViewVariables] public WeaponArcType ArcType => _arcType;
|
||||
[ViewVariables] public float Width => _width;
|
||||
|
||||
public void LoadFrom(YamlMappingNode mapping)
|
||||
{
|
||||
var serializer = YamlObjectSerializer.NewReader(mapping);
|
||||
|
||||
serializer.DataField(ref _state, "state", null);
|
||||
serializer.DataField(ref _id, "id", null);
|
||||
serializer.DataField(ref _colorDelta, "colorDelta", Vector4.Zero);
|
||||
serializer.DataField(ref _color, "color", new Vector4(1, 1, 1, 1));
|
||||
if (serializer.TryReadDataField("length", out float length))
|
||||
{
|
||||
_length = TimeSpan.FromSeconds(length);
|
||||
}
|
||||
else
|
||||
{
|
||||
_length = TimeSpan.FromSeconds(0.5f);
|
||||
}
|
||||
|
||||
serializer.DataField(ref _speed, "speed", 1);
|
||||
serializer.DataField(ref _arcType, "arcType", WeaponArcType.Slash);
|
||||
serializer.DataField(ref _width, "width", 90);
|
||||
}
|
||||
}
|
||||
|
||||
public enum WeaponArcType
|
||||
{
|
||||
Slash,
|
||||
Poke,
|
||||
}
|
||||
}
|
||||
@@ -28,5 +28,6 @@
|
||||
public const uint TECHNOLOGY_DATABASE = 1022;
|
||||
public const uint RESEARCH_CONSOLE = 1023;
|
||||
public const uint WIRES = 1024;
|
||||
public const uint COMBATMODE = 1025;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
using System;
|
||||
using Content.Shared.GameObjects.Components.Mobs;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared.GameObjects.EntitySystemMessages
|
||||
{
|
||||
public static class CombatModeSystemMessages
|
||||
{
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class SetTargetZoneMessage : EntitySystemMessage
|
||||
{
|
||||
public SetTargetZoneMessage(TargetingZone targetZone)
|
||||
{
|
||||
TargetZone = targetZone;
|
||||
}
|
||||
|
||||
public TargetingZone TargetZone { get; }
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class SetCombatModeActiveMessage : EntitySystemMessage
|
||||
{
|
||||
public SetCombatModeActiveMessage(bool active)
|
||||
{
|
||||
Active = active;
|
||||
}
|
||||
|
||||
public bool Active { get; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared.GameObjects.EntitySystemMessages
|
||||
{
|
||||
public static class MeleeWeaponSystemMessages
|
||||
{
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class PlayMeleeWeaponAnimationMessage : EntitySystemMessage
|
||||
{
|
||||
public PlayMeleeWeaponAnimationMessage(string arcPrototype, Angle angle, EntityUid attacker, List<EntityUid> hits)
|
||||
{
|
||||
ArcPrototype = arcPrototype;
|
||||
Angle = angle;
|
||||
Attacker = attacker;
|
||||
Hits = hits;
|
||||
}
|
||||
|
||||
public string ArcPrototype { get; }
|
||||
public Angle Angle { get; }
|
||||
public EntityUid Attacker { get; }
|
||||
public List<EntityUid> Hits { get; }
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
Resources/Audio/weapons/bladeslice.ogg
Normal file
BIN
Resources/Audio/weapons/genhit1.ogg
Normal file
BIN
Resources/Audio/weapons/genhit2.ogg
Normal file
BIN
Resources/Audio/weapons/genhit3.ogg
Normal file
BIN
Resources/Audio/weapons/punch1.ogg
Normal file
BIN
Resources/Audio/weapons/punch2.ogg
Normal file
BIN
Resources/Audio/weapons/punch3.ogg
Normal file
BIN
Resources/Audio/weapons/punch4.ogg
Normal file
BIN
Resources/Audio/weapons/punchmiss.ogg
Normal file
BIN
Resources/Audio/weapons/smash.ogg
Normal file
10
Resources/Prototypes/Entities/Effects/WeaponArc.yml
Normal file
@@ -0,0 +1,10 @@
|
||||
- type: entity
|
||||
id: WeaponArc
|
||||
save: false
|
||||
components:
|
||||
- type: Sprite
|
||||
sprite: Effects/weapons/arcs.rsi
|
||||
directional: false
|
||||
offset: 0.85, 0
|
||||
drawdepth: Overlays
|
||||
- type: MeleeWeaponArcAnimation
|
||||
@@ -1,6 +1,17 @@
|
||||
- type: entity
|
||||
id: ToolboxBase
|
||||
parent: BaseItem
|
||||
components:
|
||||
- type: Storage
|
||||
Capacity: 60
|
||||
- type: Item
|
||||
Size: 9999
|
||||
- type: MeleeWeapon
|
||||
hitSound: "/Audio/weapons/smash.ogg"
|
||||
|
||||
- type: entity
|
||||
name: Emergency Toolbox
|
||||
parent: BaseItem
|
||||
parent: ToolboxBase
|
||||
id: RedToolboxItem
|
||||
description: A bright red toolbox, stocked with emergency tools
|
||||
components:
|
||||
@@ -8,14 +19,10 @@
|
||||
texture: Objects/Tools/toolbox_r.png
|
||||
- type: Icon
|
||||
texture: Objects/Tools/toolbox_r.png
|
||||
- type: Storage
|
||||
Capacity: 60
|
||||
- type: Item
|
||||
Size: 9999
|
||||
|
||||
- type: entity
|
||||
name: Mechanical Toolbox
|
||||
parent: BaseItem
|
||||
parent: ToolboxBase
|
||||
id: BlueToolboxItem
|
||||
description: A blue box, stocked with mechanical tools
|
||||
components:
|
||||
@@ -23,14 +30,10 @@
|
||||
texture: Objects/Tools/Toolbox_b.png
|
||||
- type: Icon
|
||||
texture: Objects/Tools/Toolbox_b.png
|
||||
- type: Storage
|
||||
Capacity: 60
|
||||
- type: Item
|
||||
Size: 9999
|
||||
|
||||
- type: entity
|
||||
name: Electrical Toolbox
|
||||
parent: BaseItem
|
||||
parent: ToolboxBase
|
||||
id: YellowToolboxItem
|
||||
description: A toolbox typically stocked with electrical gear
|
||||
components:
|
||||
@@ -38,10 +41,6 @@
|
||||
texture: Objects/Tools/Toolbox_y.png
|
||||
- type: Icon
|
||||
texture: Objects/Tools/Toolbox_y.png
|
||||
- type: Storage
|
||||
Capacity: 60
|
||||
- type: Item
|
||||
Size: 9999
|
||||
|
||||
- type: entity
|
||||
id: YellowToolboxItemFilled
|
||||
|
||||
@@ -12,7 +12,18 @@
|
||||
state: spear
|
||||
|
||||
- type: MeleeWeapon
|
||||
range: 1.5
|
||||
arcwidth: 10
|
||||
arc: spear
|
||||
|
||||
- type: Item
|
||||
Size: 24
|
||||
sprite: Objects/Melee/spear.rsi
|
||||
prefix: inhand
|
||||
|
||||
- type: MeleeWeaponAnimation
|
||||
id: spear
|
||||
state: spear
|
||||
length: 0.10
|
||||
speed: 6
|
||||
arcType: Poke
|
||||
|
||||
7
Resources/Prototypes/MeleeWeaponAnimations/default.yml
Normal file
@@ -0,0 +1,7 @@
|
||||
- type: MeleeWeaponAnimation
|
||||
id: default
|
||||
state: slash
|
||||
arcType: Slash
|
||||
length: 0.1
|
||||
color: 255,255,255,1020
|
||||
colorDelta: 0,0,0,-5100
|
||||
18
Resources/Textures/Effects/weapons/arcs.rsi/meta.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"version": 1,
|
||||
"size": {
|
||||
"x": 32,
|
||||
"y": 32
|
||||
},
|
||||
|
||||
"states": [
|
||||
{
|
||||
"name": "spear",
|
||||
"directions": 1
|
||||
},
|
||||
{
|
||||
"name": "slash",
|
||||
"directions": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
BIN
Resources/Textures/Effects/weapons/arcs.rsi/slash.png
Normal file
|
After Width: | Height: | Size: 273 B |
BIN
Resources/Textures/Effects/weapons/arcs.rsi/spear.png
Normal file
|
After Width: | Height: | Size: 234 B |
68
Resources/Textures/UserInterface/target-doll-high.svg
Normal file
@@ -0,0 +1,68 @@
|
||||
<?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="6.1054072mm"
|
||||
height="5.5663342mm"
|
||||
viewBox="0 0 6.1054072 5.5663342"
|
||||
version="1.1"
|
||||
id="svg3494"
|
||||
inkscape:version="0.92.4 5da689c313, 2019-01-14"
|
||||
sodipodi:docname="target-doll-high.svg">
|
||||
<defs
|
||||
id="defs3488" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1.4"
|
||||
inkscape:cx="-27.670735"
|
||||
inkscape:cy="-44.325776"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:pagecheckerboard="true"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1043"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata3491">
|
||||
<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></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-24.917534,-38.704927)">
|
||||
<ellipse
|
||||
inkscape:label="Head"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.35841459"
|
||||
ry="2.7831671"
|
||||
rx="3.0527036"
|
||||
cy="41.488094"
|
||||
cx="27.970238"
|
||||
id="Oval"
|
||||
inkscape:export-xdpi="96"
|
||||
inkscape:export-ydpi="96" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
BIN
Resources/Textures/UserInterface/target-doll-high.svg.96dpi.png
Normal file
|
After Width: | Height: | Size: 427 B |
73
Resources/Textures/UserInterface/target-doll-low.svg
Normal file
@@ -0,0 +1,73 @@
|
||||
<?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="32"
|
||||
height="54.584877"
|
||||
viewBox="0 0 8.4666669 14.442248"
|
||||
version="1.1"
|
||||
id="svg2285"
|
||||
inkscape:version="0.92.4 5da689c313, 2019-01-14"
|
||||
sodipodi:docname="target-doll-low.svg"
|
||||
inkscape:export-filename="/home/pj/Projects/space-station-14/Resources/Textures/UserInterface/target-doll-low.svg.96dpi.png"
|
||||
inkscape:export-xdpi="96"
|
||||
inkscape:export-ydpi="96">
|
||||
<defs
|
||||
id="defs2279" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="7.919596"
|
||||
inkscape:cx="10.248134"
|
||||
inkscape:cy="37.492927"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:pagecheckerboard="true"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1043"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
units="px"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0" />
|
||||
<metadata
|
||||
id="metadata2282">
|
||||
<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></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-129.69328,-72.06459)">
|
||||
<path
|
||||
sodipodi:nodetypes="ccssccssccc"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.35841459"
|
||||
inkscape:connector-curvature="0"
|
||||
id="Combined-Shape"
|
||||
d="m 138.02997,72.06459 0.007,12.860185 c 0,0.932522 -0.80549,1.571841 -1.59705,1.581941 -0.8089,0.01032 -1.60425,-0.628996 -1.60425,-1.581941 V 73.365601 h -1.56762 v 11.559174 c 0,0.8692 -0.79482,1.581941 -1.77407,1.581941 -0.97993,0 -1.67772,-0.712741 -1.67772,-1.581941 l 0.0103,-12.860185 z"
|
||||
inkscape:label="Legs" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.5 KiB |
BIN
Resources/Textures/UserInterface/target-doll-low.svg.96dpi.png
Normal file
|
After Width: | Height: | Size: 420 B |
72
Resources/Textures/UserInterface/target-doll-middle.svg
Normal file
@@ -0,0 +1,72 @@
|
||||
<?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="14.761317mm"
|
||||
height="12.411281mm"
|
||||
viewBox="0 0 14.761317 12.411281"
|
||||
version="1.1"
|
||||
id="svg2871"
|
||||
sodipodi:docname="target-doll-middle.svg"
|
||||
inkscape:version="0.92.4 5da689c313, 2019-01-14">
|
||||
<defs
|
||||
id="defs2865" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="3.959798"
|
||||
inkscape:cx="12.344179"
|
||||
inkscape:cy="40.151172"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:pagecheckerboard="true"
|
||||
inkscape:window-width="506"
|
||||
inkscape:window-height="416"
|
||||
inkscape:window-x="737"
|
||||
inkscape:window-y="125"
|
||||
inkscape:window-maximized="0" />
|
||||
<metadata
|
||||
id="metadata2868">
|
||||
<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></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-10.762198,-63.252693)">
|
||||
<g
|
||||
transform="matrix(0.35841461,0,0,0.35841461,2.5098095,57.743415)"
|
||||
style="fill:none;fill-rule:evenodd;stroke:none;stroke-width:1"
|
||||
id="g2227"
|
||||
inkscape:export-xdpi="96"
|
||||
inkscape:export-ydpi="96">
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:1"
|
||||
d="m 25.617188,18.316406 c -3.668766,-0.05227 -7.262714,0.181254 -9.824219,0.681641 -2.551079,0.498351 -1.047616,0.156792 -2.542969,0.511719 -2.314857,0.549439 -3.5665384,0.789355 -4.8964844,5.476562 -1.144246,4.032732 -2.0775479,11.023827 -3.2949218,23.515625 -0.541004,4.214675 5.5660002,4.497851 6.0878902,0.478516 0.812159,-6.314445 1.251033,-14.240793 3.007813,-20.582031 l 0.01953,24.539062 c 7.628906,0 15.257813,0 22.886719,0 h 0.002 l 0.01758,-24.539062 c 1.75678,6.341238 2.197607,14.267586 3.009766,20.582031 0.52189,4.019335 6.626941,3.736159 6.085937,-0.478516 C 44.958455,36.010155 44.027106,29.01906 42.88286,24.986328 41.552915,20.299121 40.29928,20.059205 37.984423,19.509766 36.48907,19.154839 37.994483,19.496396 35.443407,18.998047 32.881902,18.49766 29.286001,18.264136 25.617236,18.316406 Z"
|
||||
transform="translate(18,-2.937978)"
|
||||
id="path308"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cssscccccccccssscc" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 1021 B |
116
Resources/Textures/UserInterface/target-doll.svg
Normal file
@@ -0,0 +1,116 @@
|
||||
<?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="55.790806"
|
||||
height="128"
|
||||
viewBox="0 0 14.761317 33.866665"
|
||||
version="1.1"
|
||||
id="svg1561"
|
||||
sodipodi:docname="target-doll.svg"
|
||||
inkscape:version="0.92.4 5da689c313, 2019-01-14">
|
||||
<defs
|
||||
id="defs1555">
|
||||
<inkscape:path-effect
|
||||
center_point="43.625,24.812736"
|
||||
end_point="43.625,52.938449"
|
||||
start_point="43.625,-3.3129772"
|
||||
effect="mirror_symmetry"
|
||||
id="path-effect2208"
|
||||
is_visible="true"
|
||||
mode="free"
|
||||
discard_orig_path="false"
|
||||
fuse_paths="false"
|
||||
oposite_fuse="false" />
|
||||
<inkscape:path-effect
|
||||
effect="mirror_symmetry"
|
||||
start_point="44,-2.937978"
|
||||
end_point="44,92.800469"
|
||||
center_point="44,44.931246"
|
||||
id="path-effect2206"
|
||||
is_visible="true"
|
||||
mode="vertical"
|
||||
discard_orig_path="false"
|
||||
fuse_paths="false"
|
||||
oposite_fuse="false" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="2.8284271"
|
||||
inkscape:cx="-11.723079"
|
||||
inkscape:cy="59.646363"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:pagecheckerboard="true"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1043"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
units="px"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0" />
|
||||
<metadata
|
||||
id="metadata1558">
|
||||
<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></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-66.160433,-111.91867)">
|
||||
<g
|
||||
style="fill:none;fill-rule:evenodd;stroke:none;stroke-width:1"
|
||||
id="Target-Doll"
|
||||
transform="matrix(0.35841461,0,0,0.35841461,57.908044,112.67527)">
|
||||
<ellipse
|
||||
inkscape:label="Head"
|
||||
style="fill:#ffffff;fill-opacity:1"
|
||||
ry="7.7652173"
|
||||
rx="8.5172415"
|
||||
cy="5.6542549"
|
||||
cx="43.7285"
|
||||
id="Oval" />
|
||||
<path
|
||||
sodipodi:nodetypes="ccssccssccc"
|
||||
style="fill:#ffffff;fill-opacity:1"
|
||||
inkscape:connector-curvature="0"
|
||||
id="Combined-Shape"
|
||||
d="m 55.060955,52.084422 0.01936,35.880749 c 0,2.601799 -2.24735,4.385539 -4.455865,4.41372 -2.25688,0.0288 -4.475973,-1.754942 -4.475973,-4.41372 V 55.714329 h -4.373759 v 32.250842 c 0,2.425126 -2.2176,4.41372 -4.949759,4.41372 -2.73408,0 -4.680959,-1.988594 -4.680959,-4.41372 l 0.02877,-35.880749 z"
|
||||
inkscape:label="Legs" />
|
||||
<g
|
||||
id="g2227">
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:1"
|
||||
d="m 25.617188,18.316406 c -3.668766,-0.05227 -7.262714,0.181254 -9.824219,0.681641 -2.551079,0.498351 -1.047616,0.156792 -2.542969,0.511719 -2.314857,0.549439 -3.5665384,0.789355 -4.8964844,5.476562 -1.144246,4.032732 -2.0775479,11.023827 -3.2949218,23.515625 -0.541004,4.214675 5.5660002,4.497851 6.0878902,0.478516 0.812159,-6.314445 1.251033,-14.240793 3.007813,-20.582031 l 0.01953,24.539062 c 7.628906,0 15.257813,0 22.886719,0 h 0.002 l 0.01758,-24.539062 c 1.75678,6.341238 2.197607,14.267586 3.009766,20.582031 0.52189,4.019335 6.626941,3.736159 6.085937,-0.478516 C 44.958455,36.010155 44.027106,29.01906 42.88286,24.986328 41.552915,20.299121 40.29928,20.059205 37.984423,19.509766 36.48907,19.154839 37.994483,19.496396 35.443407,18.998047 32.881902,18.49766 29.286001,18.264136 25.617236,18.316406 Z"
|
||||
transform="translate(18,-2.937978)"
|
||||
id="path308"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cssscccccccccssscc" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.4 KiB |
@@ -82,7 +82,7 @@ binds:
|
||||
key: MouseRight
|
||||
canFocus: true
|
||||
- function: ToggleCombatMode
|
||||
type: Toggle
|
||||
type: State
|
||||
key: Tab
|
||||
- function: OpenCraftingMenu
|
||||
type: state
|
||||
|
||||