Add ItemStatus to energy weapons (#1921)
* -ItemStatus for BatteryGuns -EjectCell Verb -Using the gun throws the battery also on the ground * Copy the flashlight and call it a day * Name a red fruit * Remove SoundGunshot
This commit is contained in:
@@ -0,0 +1,160 @@
|
||||
using Content.Client.UserInterface.Stylesheets;
|
||||
using Content.Shared.GameObjects;
|
||||
using Content.Shared.GameObjects.Components.Weapons.Ranged.Barrels;
|
||||
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.ViewVariables;
|
||||
using System;
|
||||
|
||||
namespace Content.Client.GameObjects.Components.Weapons.Ranged.Barrels
|
||||
{
|
||||
[RegisterComponent]
|
||||
public class ClientBatteryBarrelComponent : Component, IItemStatus
|
||||
{
|
||||
public override string Name => "BatteryBarrel";
|
||||
public override uint? NetID => ContentNetIDs.BATTERY_BARREL;
|
||||
|
||||
private StatusControl _statusControl;
|
||||
|
||||
/// <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; }
|
||||
|
||||
public override void HandleComponentState(ComponentState curState, ComponentState nextState)
|
||||
{
|
||||
if (!(curState is BatteryBarrelComponentState cast))
|
||||
return;
|
||||
|
||||
MagazineCount = cast.Magazine;
|
||||
_statusControl?.Update();
|
||||
}
|
||||
|
||||
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 ClientBatteryBarrelComponent _parent;
|
||||
private readonly HBoxContainer _bulletsList;
|
||||
private readonly Label _noBatteryLabel;
|
||||
private readonly Label _ammoCount;
|
||||
|
||||
public StatusControl(ClientBatteryBarrelComponent parent)
|
||||
{
|
||||
_parent = parent;
|
||||
SizeFlagsHorizontal = SizeFlags.FillExpand;
|
||||
SizeFlagsVertical = SizeFlags.ShrinkCenter;
|
||||
|
||||
AddChild(new HBoxContainer
|
||||
{
|
||||
SizeFlagsHorizontal = SizeFlags.FillExpand,
|
||||
Children =
|
||||
{
|
||||
new Control
|
||||
{
|
||||
SizeFlagsHorizontal = SizeFlags.FillExpand,
|
||||
Children =
|
||||
{
|
||||
(_bulletsList = new HBoxContainer
|
||||
{
|
||||
SizeFlagsVertical = SizeFlags.ShrinkCenter,
|
||||
SeparationOverride = 4
|
||||
}),
|
||||
(_noBatteryLabel = new Label
|
||||
{
|
||||
Text = "No Battery!",
|
||||
StyleClasses = {StyleNano.StyleClassItemStatus}
|
||||
})
|
||||
}
|
||||
},
|
||||
new Control() { CustomMinimumSize = (5,0) },
|
||||
(_ammoCount = new Label
|
||||
{
|
||||
StyleClasses = {StyleNano.StyleClassItemStatus},
|
||||
SizeFlagsHorizontal = SizeFlags.ShrinkEnd,
|
||||
}),
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
_bulletsList.RemoveAllChildren();
|
||||
|
||||
if (_parent.MagazineCount == null)
|
||||
{
|
||||
_noBatteryLabel.Visible = true;
|
||||
_ammoCount.Visible = false;
|
||||
return;
|
||||
}
|
||||
|
||||
var (count, capacity) = _parent.MagazineCount.Value;
|
||||
|
||||
_noBatteryLabel.Visible = false;
|
||||
_ammoCount.Visible = true;
|
||||
|
||||
_ammoCount.Text = $"x{count:00}";
|
||||
capacity = Math.Min(capacity, 8);
|
||||
FillBulletRow(_bulletsList, count, capacity);
|
||||
}
|
||||
|
||||
private static void FillBulletRow(Control container, int count, int capacity)
|
||||
{
|
||||
var colorGone = Color.FromHex("#000000");
|
||||
var color = Color.FromHex("#E00000");
|
||||
|
||||
// Draw the empty ones
|
||||
for (var i = count; i < capacity; i++)
|
||||
{
|
||||
container.AddChild(new PanelContainer
|
||||
{
|
||||
PanelOverride = new StyleBoxFlat()
|
||||
{
|
||||
BackgroundColor = colorGone,
|
||||
},
|
||||
CustomMinimumSize = (10, 15),
|
||||
});
|
||||
}
|
||||
|
||||
// Draw the full ones, but limit the count to the capacity
|
||||
count = Math.Min(count, capacity);
|
||||
for (var i = 0; i < count; i++)
|
||||
{
|
||||
container.AddChild(new PanelContainer
|
||||
{
|
||||
PanelOverride = new StyleBoxFlat()
|
||||
{
|
||||
BackgroundColor = color,
|
||||
},
|
||||
CustomMinimumSize = (10, 15),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
protected override Vector2 CalculateMinimumSize()
|
||||
{
|
||||
return Vector2.ComponentMax((0, 15), base.CalculateMinimumSize());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -105,7 +105,6 @@
|
||||
"SecureEntityStorage",
|
||||
"PresetIdCard",
|
||||
"SolarControlConsole",
|
||||
"BatteryBarrel",
|
||||
"FlashExplosive",
|
||||
"FlashProjectile",
|
||||
"Utensil",
|
||||
|
||||
@@ -6,7 +6,10 @@ using Content.Server.GameObjects.Components.Items.Storage;
|
||||
using Content.Server.GameObjects.Components.Power;
|
||||
using Content.Server.GameObjects.Components.Projectiles;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.GameObjects;
|
||||
using Content.Shared.GameObjects.Components.Weapons.Ranged.Barrels;
|
||||
using Content.Shared.GameObjects.EntitySystems;
|
||||
using Content.Shared.GameObjects.Verbs;
|
||||
using Content.Shared.Interfaces.GameObjects.Components;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Server.GameObjects.Components.Container;
|
||||
@@ -25,6 +28,7 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Barrels
|
||||
public sealed class ServerBatteryBarrelComponent : ServerRangedBarrelComponent
|
||||
{
|
||||
public override string Name => "BatteryBarrel";
|
||||
public override uint? NetID => ContentNetIDs.BATTERY_BARREL;
|
||||
|
||||
// The minimum change we need before we can fire
|
||||
[ViewVariables] private float _lowerChargeLimit;
|
||||
@@ -88,6 +92,15 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Barrels
|
||||
serializer.DataField(ref _soundPowerCellEject, "soundPowerCellEject", null);
|
||||
}
|
||||
|
||||
public override ComponentState GetComponentState()
|
||||
{
|
||||
(int, int)? count = (ShotsLeft, Capacity);
|
||||
|
||||
return new BatteryBarrelComponentState(
|
||||
FireRateSelector,
|
||||
count);
|
||||
}
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
@@ -108,6 +121,7 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Barrels
|
||||
_appearanceComponent = appearanceComponent;
|
||||
}
|
||||
|
||||
Dirty();
|
||||
UpdateAppearance();
|
||||
}
|
||||
|
||||
@@ -188,8 +202,8 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Barrels
|
||||
throw new InvalidOperationException("Ammo doesn't have hitscan or projectile?");
|
||||
}
|
||||
|
||||
Dirty();
|
||||
UpdateAppearance();
|
||||
//Dirty();
|
||||
return entity;
|
||||
}
|
||||
|
||||
@@ -211,30 +225,12 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Barrels
|
||||
}
|
||||
|
||||
_powerCellContainer.Insert(entity);
|
||||
|
||||
Dirty();
|
||||
UpdateAppearance();
|
||||
//Dirty();
|
||||
return true;
|
||||
}
|
||||
|
||||
private IEntity RemovePowerCell()
|
||||
{
|
||||
if (!_powerCellRemovable || _powerCellContainer.ContainedEntity == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var entity = _powerCellContainer.ContainedEntity;
|
||||
_powerCellContainer.Remove(entity);
|
||||
if (_soundPowerCellEject != null)
|
||||
{
|
||||
EntitySystem.Get<AudioSystem>().PlayAtCoords(_soundPowerCellEject, Owner.Transform.GridPosition, AudioParams.Default.WithVolume(-2));
|
||||
}
|
||||
|
||||
UpdateAppearance();
|
||||
//Dirty();
|
||||
return entity;
|
||||
}
|
||||
|
||||
public override bool UseEntity(UseEntityEventArgs eventArgs)
|
||||
{
|
||||
if (!_powerCellRemovable)
|
||||
@@ -242,22 +238,44 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Barrels
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!eventArgs.User.TryGetComponent(out HandsComponent handsComponent) ||
|
||||
PowerCellEntity == null)
|
||||
if (PowerCellEntity == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var itemComponent = PowerCellEntity.GetComponent<ItemComponent>();
|
||||
if (!handsComponent.CanPutInHand(itemComponent))
|
||||
return TryEjectCell(eventArgs.User);
|
||||
}
|
||||
|
||||
private bool TryEjectCell(IEntity user)
|
||||
{
|
||||
if (PowerCell == null || !_powerCellRemovable)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var powerCell = RemovePowerCell();
|
||||
handsComponent.PutInHand(itemComponent);
|
||||
powerCell.Transform.GridPosition = eventArgs.User.Transform.GridPosition;
|
||||
if (!user.TryGetComponent(out HandsComponent hands))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var cell = PowerCell;
|
||||
if (!_powerCellContainer.Remove(cell.Owner))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Dirty();
|
||||
UpdateAppearance();
|
||||
|
||||
if (!hands.PutInHand(cell.Owner.GetComponent<ItemComponent>()))
|
||||
{
|
||||
cell.Owner.Transform.GridPosition = user.Transform.GridPosition;
|
||||
}
|
||||
|
||||
if (_soundPowerCellEject != null)
|
||||
{
|
||||
EntitySystem.Get<AudioSystem>().PlayAtCoords(_soundPowerCellEject, Owner.Transform.GridPosition, AudioParams.Default.WithVolume(-2));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -270,5 +288,33 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Barrels
|
||||
|
||||
return TryInsertPowerCell(eventArgs.Using);
|
||||
}
|
||||
|
||||
[Verb]
|
||||
public sealed class EjectCellVerb : Verb<ServerBatteryBarrelComponent>
|
||||
{
|
||||
protected override void GetData(IEntity user, ServerBatteryBarrelComponent component, VerbData data)
|
||||
{
|
||||
if (!ActionBlockerSystem.CanInteract(user) || !component._powerCellRemovable)
|
||||
{
|
||||
data.Visibility = VerbVisibility.Invisible;
|
||||
return;
|
||||
}
|
||||
|
||||
if (component.PowerCell == null)
|
||||
{
|
||||
data.Text = "Eject cell (cell missing)";
|
||||
data.Visibility = VerbVisibility.Disabled;
|
||||
}
|
||||
else
|
||||
{
|
||||
data.Text = "Eject cell";
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Activate(IEntity user, ServerBatteryBarrelComponent component)
|
||||
{
|
||||
component.TryEjectCell(user);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Serialization;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Content.Shared.GameObjects.Components.Weapons.Ranged.Barrels
|
||||
{
|
||||
[Serializable, NetSerializable]
|
||||
public class BatteryBarrelComponentState : ComponentState
|
||||
{
|
||||
public FireRateSelector FireRateSelector { get; }
|
||||
public (int count, int max)? Magazine { get; }
|
||||
|
||||
public BatteryBarrelComponentState(
|
||||
FireRateSelector fireRateSelector,
|
||||
(int count, int max)? magazine) :
|
||||
base(ContentNetIDs.BATTERY_BARREL)
|
||||
{
|
||||
FireRateSelector = fireRateSelector;
|
||||
Magazine = magazine;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -70,6 +70,7 @@
|
||||
public const uint REVOLVER_BARREL = 1064;
|
||||
public const uint CUFFED = 1065;
|
||||
public const uint HANDCUFFS = 1066;
|
||||
public const uint BATTERY_BARREL = 1067;
|
||||
|
||||
// Net IDs for integration tests.
|
||||
public const uint PREDICTION_TEST = 10001;
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
- Single
|
||||
fireRate: 2
|
||||
powerCellPrototype: PowerCellSmallStandard
|
||||
powerCellRemovable: true
|
||||
ammoPrototype: RedLaser
|
||||
soundGunshot: /Audio/Weapons/Guns/Gunshots/laser.ogg
|
||||
- type: Appearance
|
||||
@@ -71,6 +72,7 @@
|
||||
angleIncrease: 15
|
||||
angleDecay: 45
|
||||
powerCellPrototype: PowerCellSmallSuper
|
||||
powerCellRemovable: true
|
||||
ammoPrototype: RedHeavyLaser
|
||||
soundGunshot: /Audio/Weapons/Guns/Gunshots/laser_cannon.ogg
|
||||
- type: Appearance
|
||||
@@ -112,6 +114,7 @@
|
||||
angleIncrease: 15
|
||||
angleDecay: 45
|
||||
powerCellPrototype: PowerCellSmallSuper
|
||||
powerCellRemovable: true
|
||||
base_fire_cost: 600
|
||||
ammoPrototype: XrayLaser
|
||||
soundGunshot: /Audio/Weapons/Guns/Gunshots/laser3.ogg
|
||||
@@ -155,6 +158,7 @@
|
||||
angleIncrease: 20
|
||||
angleDecay: 15
|
||||
powerCellPrototype: PowerCellSmallStandard
|
||||
powerCellRemovable: false
|
||||
ammoPrototype: BulletTaser
|
||||
soundGunshot: /Audio/Weapons/Guns/Gunshots/taser.ogg
|
||||
- type: Appearance
|
||||
|
||||
Reference in New Issue
Block a user