Add power cell and weapon chargers (#430)
* Add power cell and weapon chargers Functionality's similar to SS13. The cell charger won't show the discrete charging levels because effort to not make it spam appearance updates over the network. There's some stuff I wasn't sure on: 1. Updating power? Particularly around fixing rounding 2. Duplicating the full and empty sprites as I couldn't figure out a way to not have AppearanceVisualizer throw if the state isn't found 3. I made a BaseCharger abstract class under the assumption that when a mech / borg charger is added it would also inherit from it. 4. GetText currently isn't localized * Address PJB's feedback Updated the BaseCharger * Change nullref exception to invalidoperation * If the user doesn't have hands it will just return instead
@@ -97,6 +97,8 @@ namespace Content.Client
|
||||
"BallisticBullet",
|
||||
"HitscanWeaponCapacitor",
|
||||
"PowerCell",
|
||||
"WeaponCapacitorCharger",
|
||||
"PowerCellCharger",
|
||||
"AiController",
|
||||
"PlayerInputMover",
|
||||
"Computer",
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
using Content.Shared.GameObjects.Components.Power;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.Interfaces.GameObjects.Components;
|
||||
using Robust.Shared.Interfaces.GameObjects;
|
||||
|
||||
namespace Content.Client.GameObjects.Components.Power
|
||||
{
|
||||
[UsedImplicitly]
|
||||
public class PowerChargerVisualizer2D : AppearanceVisualizer
|
||||
{
|
||||
public override void InitializeEntity(IEntity entity)
|
||||
{
|
||||
base.InitializeEntity(entity);
|
||||
|
||||
var sprite = entity.GetComponent<ISpriteComponent>();
|
||||
|
||||
// Base item
|
||||
sprite.LayerMapSet(Layers.Base, sprite.AddLayerState("empty"));
|
||||
|
||||
// Light
|
||||
sprite.LayerMapSet(Layers.Light, sprite.AddLayerState("light-off"));
|
||||
sprite.LayerSetShader(Layers.Light, "unshaded");
|
||||
}
|
||||
|
||||
public override void OnChangeData(AppearanceComponent component)
|
||||
{
|
||||
base.OnChangeData(component);
|
||||
|
||||
var sprite = component.Owner.GetComponent<ISpriteComponent>();
|
||||
|
||||
// Update base item
|
||||
if (component.TryGetData(CellVisual.Occupied, out bool occupied))
|
||||
{
|
||||
// TODO: don't throw if it doesn't have a full state
|
||||
sprite.LayerSetState(Layers.Base, occupied ? "full" : "empty");
|
||||
}
|
||||
else
|
||||
{
|
||||
sprite.LayerSetState(Layers.Base, "empty");
|
||||
}
|
||||
|
||||
// Update lighting
|
||||
if (component.TryGetData(CellVisual.Light, out CellChargerStatus status))
|
||||
{
|
||||
switch (status)
|
||||
{
|
||||
case CellChargerStatus.Off:
|
||||
sprite.LayerSetState(Layers.Light, "light-off");
|
||||
break;
|
||||
case CellChargerStatus.Empty:
|
||||
sprite.LayerSetState(Layers.Light, "light-empty");
|
||||
break;
|
||||
case CellChargerStatus.Charging:
|
||||
sprite.LayerSetState(Layers.Light, "light-charging");
|
||||
break;
|
||||
case CellChargerStatus.Charged:
|
||||
sprite.LayerSetState(Layers.Light, "light-charged");
|
||||
break;
|
||||
default:
|
||||
sprite.LayerSetState(Layers.Light, "light-off");
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sprite.LayerSetState(Layers.Light, "light-off");
|
||||
}
|
||||
}
|
||||
|
||||
enum Layers
|
||||
{
|
||||
Base,
|
||||
Light,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
using System;
|
||||
using Content.Shared.GameObjects.Components.Power;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Server.GameObjects.Components.Container;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Interfaces.GameObjects;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Content.Server.GameObjects.Components.Power.Chargers
|
||||
{
|
||||
public abstract class BaseCharger : Component
|
||||
{
|
||||
|
||||
protected IEntity _heldItem;
|
||||
protected ContainerSlot _container;
|
||||
protected PowerDeviceComponent _powerDevice;
|
||||
public CellChargerStatus Status => _status;
|
||||
protected CellChargerStatus _status;
|
||||
|
||||
protected AppearanceComponent _appearanceComponent;
|
||||
|
||||
public abstract double CellChargePercent { get; }
|
||||
|
||||
// Powered items have their own charge rates, this is just a way to have chargers with different rates as well
|
||||
public float TransferRatio => _transferRatio;
|
||||
[ViewVariables]
|
||||
protected float _transferRatio;
|
||||
|
||||
public float TransferEfficiency => _transferEfficiency;
|
||||
[ViewVariables]
|
||||
protected float _transferEfficiency;
|
||||
|
||||
public override void ExposeData(ObjectSerializer serializer)
|
||||
{
|
||||
base.ExposeData(serializer);
|
||||
|
||||
serializer.DataField(ref _transferRatio, "transfer_ratio", 0.1f);
|
||||
serializer.DataField(ref _transferEfficiency, "transfer_efficiency", 0.85f);
|
||||
}
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
_powerDevice = Owner.GetComponent<PowerDeviceComponent>();
|
||||
if (_powerDevice == null)
|
||||
{
|
||||
var exc = new InvalidOperationException("Chargers requires a PowerDevice to function");
|
||||
Logger.FatalS("charger", exc.Message);
|
||||
throw exc;
|
||||
}
|
||||
_container =
|
||||
ContainerManagerComponent.Ensure<ContainerSlot>($"{Name}-powerCellContainer", Owner);
|
||||
_appearanceComponent = Owner.GetComponent<AppearanceComponent>();
|
||||
// Default state in the visualizer is OFF, so when this gets powered on during initialization it will generally show empty
|
||||
_powerDevice.OnPowerStateChanged += PowerUpdate;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This will remove the item directly into the user's hand rather than the floor
|
||||
/// </summary>
|
||||
/// <param name="user"></param>
|
||||
public void RemoveItemToHand(IEntity user)
|
||||
{
|
||||
var heldItem = _container.ContainedEntity;
|
||||
if (heldItem == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
RemoveItem();
|
||||
|
||||
if (user.TryGetComponent(out HandsComponent handsComponent) &&
|
||||
heldItem.TryGetComponent(out ItemComponent itemComponent))
|
||||
{
|
||||
handsComponent.PutInHand(itemComponent);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Will put the charger's item on the floor if available
|
||||
/// </summary>
|
||||
public void RemoveItem()
|
||||
{
|
||||
if (_container.ContainedEntity == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_container.Remove(_heldItem);
|
||||
UpdateStatus();
|
||||
}
|
||||
|
||||
protected void PowerUpdate(object sender, PowerStateEventArgs eventArgs)
|
||||
{
|
||||
UpdateStatus();
|
||||
}
|
||||
|
||||
protected abstract CellChargerStatus GetStatus();
|
||||
protected abstract void TransferPower(float frameTime);
|
||||
|
||||
protected void UpdateStatus()
|
||||
{
|
||||
// Not called UpdateAppearance just because it messes with the load
|
||||
var status = GetStatus();
|
||||
|
||||
if (_status == status)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_status = status;
|
||||
|
||||
switch (_status)
|
||||
{
|
||||
// Update load just in case
|
||||
case CellChargerStatus.Off:
|
||||
_powerDevice.Load = 0;
|
||||
_appearanceComponent?.SetData(CellVisual.Light, CellChargerStatus.Off);
|
||||
break;
|
||||
case CellChargerStatus.Empty:
|
||||
_powerDevice.Load = 0;
|
||||
_appearanceComponent?.SetData(CellVisual.Light, CellChargerStatus.Empty); ;
|
||||
break;
|
||||
case CellChargerStatus.Charging:
|
||||
_appearanceComponent?.SetData(CellVisual.Light, CellChargerStatus.Charging);
|
||||
break;
|
||||
case CellChargerStatus.Charged:
|
||||
_powerDevice.Load = 0;
|
||||
_appearanceComponent?.SetData(CellVisual.Light, CellChargerStatus.Charged);
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
|
||||
_appearanceComponent?.SetData(CellVisual.Occupied, _container.ContainedEntity != null);
|
||||
|
||||
_status = status;
|
||||
}
|
||||
|
||||
public void OnUpdate(float frameTime)
|
||||
{
|
||||
if (_status == CellChargerStatus.Empty || _status == CellChargerStatus.Charged ||
|
||||
_container.ContainedEntity == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
TransferPower(frameTime);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,192 @@
|
||||
using System;
|
||||
using Content.Server.GameObjects.EntitySystems;
|
||||
using Content.Shared.GameObjects;
|
||||
using Content.Shared.GameObjects.Components.Power;
|
||||
using Content.Shared.Interfaces;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Server.GameObjects.Components.Container;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Interfaces.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Localization;
|
||||
|
||||
namespace Content.Server.GameObjects.Components.Power.Chargers
|
||||
{
|
||||
/// <summary>
|
||||
/// This is used for the standalone cell rechargers (e.g. from a flashlight)
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
[ComponentReference(typeof(IActivate))]
|
||||
[ComponentReference(typeof(IAttackBy))]
|
||||
public sealed class PowerCellChargerComponent : BaseCharger, IActivate, IAttackBy
|
||||
{
|
||||
public override string Name => "PowerCellCharger";
|
||||
public override double CellChargePercent => _container.ContainedEntity != null ?
|
||||
_container.ContainedEntity.GetComponent<PowerCellComponent>().Charge /
|
||||
_container.ContainedEntity.GetComponent<PowerCellComponent>().Capacity * 100 : 0.0f;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
_powerDevice = Owner.GetComponent<PowerDeviceComponent>();
|
||||
_container =
|
||||
ContainerManagerComponent.Ensure<ContainerSlot>($"{Name}-powerCellContainer", Owner);
|
||||
_appearanceComponent = Owner.GetComponent<AppearanceComponent>();
|
||||
// Default state in the visualizer is OFF, so when this gets powered on during initialization it will generally show empty
|
||||
_powerDevice.OnPowerStateChanged += PowerUpdate;
|
||||
}
|
||||
|
||||
bool IAttackBy.AttackBy(AttackByEventArgs eventArgs)
|
||||
{
|
||||
var result = TryInsertItem(eventArgs.AttackWith);
|
||||
if (result)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
var localizationManager = IoCManager.Resolve<ILocalizationManager>();
|
||||
eventArgs.User.PopupMessage(Owner, localizationManager.GetString("Unable to insert capacitor"));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void IActivate.Activate(ActivateEventArgs eventArgs)
|
||||
{
|
||||
RemoveItemToHand(eventArgs.User);
|
||||
}
|
||||
|
||||
[Verb]
|
||||
private sealed class InsertVerb : Verb<PowerCellChargerComponent>
|
||||
{
|
||||
protected override string GetText(IEntity user, PowerCellChargerComponent component)
|
||||
{
|
||||
if (!user.TryGetComponent(out HandsComponent handsComponent) || handsComponent.GetActiveHand == null)
|
||||
{
|
||||
return "Insert";
|
||||
}
|
||||
return $"Insert {handsComponent.GetActiveHand.Owner.Name}";
|
||||
}
|
||||
|
||||
protected override VerbVisibility GetVisibility(IEntity user, PowerCellChargerComponent component)
|
||||
{
|
||||
if (!user.TryGetComponent(out HandsComponent handsComponent))
|
||||
{
|
||||
return VerbVisibility.Invisible;
|
||||
}
|
||||
|
||||
if (component._container.ContainedEntity != null || handsComponent.GetActiveHand == null)
|
||||
{
|
||||
return VerbVisibility.Disabled;
|
||||
}
|
||||
|
||||
return VerbVisibility.Visible;
|
||||
}
|
||||
|
||||
protected override void Activate(IEntity user, PowerCellChargerComponent component)
|
||||
{
|
||||
if (!user.TryGetComponent(out HandsComponent handsComponent))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (handsComponent.GetActiveHand == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var userItem = handsComponent.GetActiveHand.Owner;
|
||||
handsComponent.Drop(userItem);
|
||||
component.TryInsertItem(userItem);
|
||||
}
|
||||
}
|
||||
|
||||
[Verb]
|
||||
private sealed class EjectVerb : Verb<PowerCellChargerComponent>
|
||||
{
|
||||
protected override string GetText(IEntity user, PowerCellChargerComponent component)
|
||||
{
|
||||
if (component._container.ContainedEntity == null)
|
||||
{
|
||||
return "Eject";
|
||||
}
|
||||
return $"Eject {component._container.ContainedEntity.Name}";
|
||||
}
|
||||
|
||||
protected override VerbVisibility GetVisibility(IEntity user, PowerCellChargerComponent component)
|
||||
{
|
||||
if (component._container.ContainedEntity == null)
|
||||
{
|
||||
return VerbVisibility.Disabled;
|
||||
}
|
||||
return VerbVisibility.Visible;
|
||||
}
|
||||
|
||||
protected override void Activate(IEntity user, PowerCellChargerComponent component)
|
||||
{
|
||||
component.RemoveItem();
|
||||
}
|
||||
}
|
||||
|
||||
public bool TryInsertItem(IEntity entity)
|
||||
{
|
||||
if (!entity.HasComponent<PowerCellComponent>() ||
|
||||
_container.ContainedEntity != null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
_heldItem = entity;
|
||||
if (!_container.Insert(_heldItem))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
UpdateStatus();
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override CellChargerStatus GetStatus()
|
||||
{
|
||||
if (!_powerDevice.Powered)
|
||||
{
|
||||
return CellChargerStatus.Off;
|
||||
}
|
||||
|
||||
if (_container.ContainedEntity == null)
|
||||
{
|
||||
return CellChargerStatus.Empty;
|
||||
}
|
||||
|
||||
if (_container.ContainedEntity.TryGetComponent(out PowerCellComponent component) &&
|
||||
Math.Abs(component.Capacity - component.Charge) < 0.01)
|
||||
{
|
||||
return CellChargerStatus.Charged;
|
||||
}
|
||||
|
||||
return CellChargerStatus.Charging;
|
||||
}
|
||||
|
||||
protected override void TransferPower(float frameTime)
|
||||
{
|
||||
// Two numbers: One for how much power actually goes into the device (chargeAmount) and
|
||||
// chargeLoss which is how much is drawn from the powernet
|
||||
_container.ContainedEntity.TryGetComponent(out PowerCellComponent cellComponent);
|
||||
var chargeLoss = cellComponent.RequestCharge(frameTime) * _transferRatio;
|
||||
_powerDevice.Load = chargeLoss;
|
||||
|
||||
if (!_powerDevice.Powered)
|
||||
{
|
||||
// No power: Event should update to Off status
|
||||
return;
|
||||
}
|
||||
|
||||
var chargeAmount = chargeLoss * _transferEfficiency;
|
||||
|
||||
cellComponent.AddCharge(chargeAmount);
|
||||
// Just so the sprite won't be set to 99.99999% visibility
|
||||
if (cellComponent.Capacity - cellComponent.Charge < 0.01)
|
||||
{
|
||||
cellComponent.Charge = cellComponent.Capacity;
|
||||
}
|
||||
UpdateStatus();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
using System;
|
||||
using Content.Server.GameObjects.Components.Weapon.Ranged.Hitscan;
|
||||
using Content.Server.GameObjects.EntitySystems;
|
||||
using Content.Shared.GameObjects;
|
||||
using Content.Shared.GameObjects.Components.Power;
|
||||
using Content.Shared.Interfaces;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Server.GameObjects.Components.Container;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Interfaces.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Content.Server.GameObjects.Components.Power.Chargers
|
||||
{
|
||||
/// <summary>
|
||||
/// This is used for the lasergun / flash rechargers
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
[ComponentReference(typeof(IActivate))]
|
||||
[ComponentReference(typeof(IAttackBy))]
|
||||
public sealed class WeaponCapacitorChargerComponent : BaseCharger, IActivate, IAttackBy
|
||||
{
|
||||
public override string Name => "WeaponCapacitorCharger";
|
||||
public override double CellChargePercent => _container.ContainedEntity != null ?
|
||||
_container.ContainedEntity.GetComponent<HitscanWeaponCapacitorComponent>().Charge /
|
||||
_container.ContainedEntity.GetComponent<HitscanWeaponCapacitorComponent>().Capacity * 100 : 0.0f;
|
||||
|
||||
bool IAttackBy.AttackBy(AttackByEventArgs eventArgs)
|
||||
{
|
||||
var result = TryInsertItem(eventArgs.AttackWith);
|
||||
if (!result)
|
||||
{
|
||||
var localizationManager = IoCManager.Resolve<ILocalizationManager>();
|
||||
eventArgs.User.PopupMessage(Owner, localizationManager.GetString("Unable to insert capacitor"));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void IActivate.Activate(ActivateEventArgs eventArgs)
|
||||
{
|
||||
RemoveItemToHand(eventArgs.User);
|
||||
}
|
||||
|
||||
[Verb]
|
||||
private sealed class InsertVerb : Verb<WeaponCapacitorChargerComponent>
|
||||
{
|
||||
protected override string GetText(IEntity user, WeaponCapacitorChargerComponent component)
|
||||
{
|
||||
if (!user.TryGetComponent(out HandsComponent handsComponent) || handsComponent.GetActiveHand == null)
|
||||
{
|
||||
return "Insert";
|
||||
}
|
||||
return $"Insert {handsComponent.GetActiveHand.Owner.Name}";
|
||||
}
|
||||
|
||||
protected override VerbVisibility GetVisibility(IEntity user, WeaponCapacitorChargerComponent component)
|
||||
{
|
||||
if (!user.TryGetComponent(out HandsComponent handsComponent))
|
||||
{
|
||||
return VerbVisibility.Invisible;
|
||||
}
|
||||
|
||||
if (component._container.ContainedEntity != null || handsComponent.GetActiveHand == null)
|
||||
{
|
||||
return VerbVisibility.Disabled;
|
||||
}
|
||||
|
||||
return VerbVisibility.Visible;
|
||||
}
|
||||
|
||||
protected override void Activate(IEntity user, WeaponCapacitorChargerComponent component)
|
||||
{
|
||||
if (!user.TryGetComponent(out HandsComponent handsComponent))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (handsComponent.GetActiveHand == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var userItem = handsComponent.GetActiveHand.Owner;
|
||||
handsComponent.Drop(userItem);
|
||||
component.TryInsertItem(userItem);
|
||||
}
|
||||
}
|
||||
|
||||
[Verb]
|
||||
private sealed class EjectVerb : Verb<WeaponCapacitorChargerComponent>
|
||||
{
|
||||
protected override string GetText(IEntity user, WeaponCapacitorChargerComponent component)
|
||||
{
|
||||
if (component._container.ContainedEntity == null)
|
||||
{
|
||||
return "Eject";
|
||||
}
|
||||
return $"Eject {component._container.ContainedEntity.Name}";
|
||||
}
|
||||
|
||||
protected override VerbVisibility GetVisibility(IEntity user, WeaponCapacitorChargerComponent component)
|
||||
{
|
||||
if (component._container.ContainedEntity == null)
|
||||
{
|
||||
return VerbVisibility.Disabled;
|
||||
}
|
||||
return VerbVisibility.Visible;
|
||||
}
|
||||
|
||||
protected override void Activate(IEntity user, WeaponCapacitorChargerComponent component)
|
||||
{
|
||||
component.RemoveItem();
|
||||
}
|
||||
}
|
||||
|
||||
public bool TryInsertItem(IEntity entity)
|
||||
{
|
||||
if (!entity.HasComponent<HitscanWeaponCapacitorComponent>() ||
|
||||
_container.ContainedEntity != null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
_heldItem = entity;
|
||||
if (!_container.Insert(_heldItem))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
UpdateStatus();
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override CellChargerStatus GetStatus()
|
||||
{
|
||||
if (!_powerDevice.Powered)
|
||||
{
|
||||
return CellChargerStatus.Off;
|
||||
}
|
||||
|
||||
if (_container.ContainedEntity == null)
|
||||
{
|
||||
return CellChargerStatus.Empty;
|
||||
}
|
||||
|
||||
if (_container.ContainedEntity.TryGetComponent(out HitscanWeaponCapacitorComponent component) &&
|
||||
Math.Abs(component.Capacity - component.Charge) < 0.01)
|
||||
{
|
||||
return CellChargerStatus.Charged;
|
||||
}
|
||||
|
||||
return CellChargerStatus.Charging;
|
||||
}
|
||||
|
||||
protected override void TransferPower(float frameTime)
|
||||
{
|
||||
// Two numbers: One for how much power actually goes into the device (chargeAmount) and
|
||||
// chargeLoss which is how much is drawn from the powernet
|
||||
_container.ContainedEntity.TryGetComponent(out HitscanWeaponCapacitorComponent weaponCapacitorComponent);
|
||||
var chargeLoss = weaponCapacitorComponent.RequestCharge(frameTime) * _transferRatio;
|
||||
_powerDevice.Load = chargeLoss;
|
||||
|
||||
if (!_powerDevice.Powered)
|
||||
{
|
||||
// No power: Event should update to Off status
|
||||
return;
|
||||
}
|
||||
|
||||
var chargeAmount = chargeLoss * _transferEfficiency;
|
||||
|
||||
weaponCapacitorComponent.AddCharge(chargeAmount);
|
||||
// Just so the sprite won't be set to 99.99999% visibility
|
||||
if (weaponCapacitorComponent.Capacity - weaponCapacitorComponent.Charge < 0.01)
|
||||
{
|
||||
weaponCapacitorComponent.Charge = weaponCapacitorComponent.Capacity;
|
||||
}
|
||||
UpdateStatus();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using Content.Server.GameObjects.Components.Power.Chargers;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameObjects.Systems;
|
||||
|
||||
namespace Content.Server.GameObjects.EntitySystems
|
||||
{
|
||||
[UsedImplicitly]
|
||||
internal class CellChargerSystem : EntitySystem
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
EntityQuery = new TypeEntityQuery(typeof(PowerCellChargerComponent));
|
||||
}
|
||||
|
||||
public override void Update(float frameTime)
|
||||
{
|
||||
foreach (var entity in RelevantEntities)
|
||||
{
|
||||
var comp = entity.GetComponent<PowerCellChargerComponent>();
|
||||
comp.OnUpdate(frameTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using Content.Server.GameObjects.Components.Power;
|
||||
using Content.Server.GameObjects.Components.Power.Chargers;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameObjects.Systems;
|
||||
|
||||
namespace Content.Server.GameObjects.EntitySystems
|
||||
{
|
||||
[UsedImplicitly]
|
||||
internal class WeaponCapacitorChargerSystem : EntitySystem
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
EntityQuery = new TypeEntityQuery(typeof(WeaponCapacitorChargerComponent));
|
||||
}
|
||||
|
||||
public override void Update(float frameTime)
|
||||
{
|
||||
foreach (var entity in RelevantEntities)
|
||||
{
|
||||
var comp = entity.GetComponent<WeaponCapacitorChargerComponent>();
|
||||
comp.OnUpdate(frameTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared.GameObjects.Components.Power
|
||||
{
|
||||
[Serializable, NetSerializable]
|
||||
public enum CellChargerStatus
|
||||
{
|
||||
Off,
|
||||
Empty,
|
||||
Charging,
|
||||
Charged,
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public enum CellVisual
|
||||
{
|
||||
Occupied, // If there's an item in it
|
||||
Light,
|
||||
}
|
||||
}
|
||||
@@ -94,3 +94,95 @@
|
||||
visuals:
|
||||
- type: PowerCellVisualizer2D
|
||||
prefix: s_hy
|
||||
|
||||
- type: entity
|
||||
name: Cell Recharger
|
||||
id: PowerCellRecharger
|
||||
components:
|
||||
- type: Sprite
|
||||
netsync: false
|
||||
sprite: Objects/Power/PowerCells/cell_recharger.rsi
|
||||
drawdepth: Items
|
||||
- type: PowerCellCharger
|
||||
transfer_ratio: 0.10
|
||||
transfer_efficiency: 0.85
|
||||
- type: PowerDevice
|
||||
priority: Low
|
||||
- type: Icon
|
||||
sprite: Objects/Power/PowerCells/cell_recharger.rsi
|
||||
state: empty
|
||||
- type: Appearance
|
||||
visuals:
|
||||
- type: PowerChargerVisualizer2D
|
||||
- type: Wrenchable
|
||||
- type: Physics
|
||||
mass: 5
|
||||
- type: Clickable
|
||||
- type: Collidable
|
||||
shapes:
|
||||
- !type:PhysShapeAabb
|
||||
bounds: "-0.25,-0.25,0.25,0.25"
|
||||
mask: 19
|
||||
layer: 16
|
||||
IsScrapingFloor: true
|
||||
|
||||
- type: entity
|
||||
name: Recharger
|
||||
id: WeaponCapacitorRecharger
|
||||
components:
|
||||
- type: Sprite
|
||||
netsync: false
|
||||
sprite: Objects/Power/PowerCells/recharger.rsi
|
||||
drawdepth: Items
|
||||
- type: WeaponCapacitorCharger
|
||||
transfer_ratio: 0.10
|
||||
transfer_efficiency: 0.85
|
||||
- type: PowerDevice
|
||||
priority: Low
|
||||
- type: Icon
|
||||
sprite: Objects/Power/PowerCells/recharger.rsi
|
||||
state: empty
|
||||
- type: Appearance
|
||||
visuals:
|
||||
- type: PowerChargerVisualizer2D
|
||||
- type: Wrenchable
|
||||
- type: Physics
|
||||
mass: 5
|
||||
- type: Clickable
|
||||
- type: Collidable
|
||||
shapes:
|
||||
- !type:PhysShapeAabb
|
||||
bounds: "-0.25,-0.25,0.25,0.25"
|
||||
mask: 19
|
||||
layer: 16
|
||||
IsScrapingFloor: true
|
||||
|
||||
- type: entity
|
||||
name: Wall recharger
|
||||
id: WallWeaponCapacitorRecharger
|
||||
components:
|
||||
- type: Sprite
|
||||
netsync: false
|
||||
sprite: Objects/Power/PowerCells/wall_recharger.rsi
|
||||
drawdepth: Items
|
||||
- type: WeaponCapacitorCharger
|
||||
transfer_ratio: 0.15
|
||||
transfer_efficiency: 0.95
|
||||
- type: PowerDevice
|
||||
priority: Low
|
||||
- type: Icon
|
||||
sprite: Objects/Power/PowerCells/wall_recharger.rsi
|
||||
state: empty
|
||||
- type: Appearance
|
||||
visuals:
|
||||
- type: PowerChargerVisualizer2D
|
||||
- type: Physics
|
||||
mass: 5
|
||||
- type: Clickable
|
||||
- type: Collidable
|
||||
shapes:
|
||||
- !type:PhysShapeAabb
|
||||
bounds: "-0.25,-0.25,0.25,0.25"
|
||||
mask: 19
|
||||
layer: 16
|
||||
IsScrapingFloor: true
|
||||
|
||||
|
After Width: | Height: | Size: 328 B |
|
After Width: | Height: | Size: 450 B |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 214 B |
|
After Width: | Height: | Size: 1.8 KiB |
@@ -0,0 +1,59 @@
|
||||
{
|
||||
"version": 1,
|
||||
"size": {
|
||||
"x": 32,
|
||||
"y": 32
|
||||
},
|
||||
"license": "CC-BY-SA-3.0",
|
||||
"copyright": "https://github.com/vgstation-coders/vgstation13/raw/78a32d846158a67dcd0ca2375e408fec298b46a0/icons/obj/power.dmi",
|
||||
"states": [
|
||||
{
|
||||
"name": "light-off",
|
||||
"directions": 1
|
||||
},
|
||||
{
|
||||
"name": "empty",
|
||||
"directions": 1
|
||||
},
|
||||
{
|
||||
"name": "full",
|
||||
"directions": 1
|
||||
},
|
||||
{
|
||||
"name": "open",
|
||||
"directions": 1
|
||||
},
|
||||
{
|
||||
"name": "light-charging",
|
||||
"directions": 1,
|
||||
"delays": [
|
||||
[
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "light-charged",
|
||||
"directions": 1,
|
||||
"delays": [
|
||||
[
|
||||
0.5,
|
||||
0.5
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "light-empty",
|
||||
"directions": 1,
|
||||
"delays": [
|
||||
[
|
||||
0.5,
|
||||
0.5
|
||||
]
|
||||
]
|
||||
},
|
||||
]
|
||||
}
|
||||
|
After Width: | Height: | Size: 345 B |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 6.4 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
@@ -0,0 +1,74 @@
|
||||
{
|
||||
"version": 1,
|
||||
"size": {
|
||||
"x": 32,
|
||||
"y": 32
|
||||
},
|
||||
"license": "CC-BY-SA-3.0",
|
||||
"copyright": "https://github.com/discordia-space/CEV-Eris/raw/9ea3eccbe22e18d24653949067f3d7dd12194ea9/icons/obj/stationobjs.dmi",
|
||||
"states": [
|
||||
{
|
||||
"name": "empty",
|
||||
"directions": 1,
|
||||
"delays": [
|
||||
[
|
||||
1.0
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "full",
|
||||
"directions": 1,
|
||||
"delays": [
|
||||
[
|
||||
1.0
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "light-off",
|
||||
"directions": 1,
|
||||
"delays": [
|
||||
[
|
||||
1
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "light-empty",
|
||||
"directions": 1,
|
||||
"delays": [
|
||||
[
|
||||
1,
|
||||
0.2
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "light-charging",
|
||||
"directions": 1,
|
||||
"delays": [
|
||||
[
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "light-charged",
|
||||
"directions": 1,
|
||||
"delays": [
|
||||
[
|
||||
0.2,
|
||||
0.1
|
||||
]
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 3.5 KiB |
|
After Width: | Height: | Size: 5.6 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
@@ -0,0 +1,71 @@
|
||||
{
|
||||
"version": 1,
|
||||
"size": {
|
||||
"x": 32,
|
||||
"y": 32
|
||||
},
|
||||
"license": "CC-BY-SA-3.0",
|
||||
"copyright": "https://github.com/discordia-space/CEV-Eris/raw/9ea3eccbe22e18d24653949067f3d7dd12194ea9/icons/obj/stationobjs.dmi",
|
||||
"states": [
|
||||
{
|
||||
"name": "empty",
|
||||
"directions": 1,
|
||||
"delays": [
|
||||
[
|
||||
1.0
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "full",
|
||||
"directions": 1,
|
||||
"delays": [
|
||||
[
|
||||
1.0
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "light-off",
|
||||
"directions": 1,
|
||||
"delays": [
|
||||
[
|
||||
1
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "light-empty",
|
||||
"directions": 1,
|
||||
"delays": [
|
||||
[
|
||||
1,
|
||||
0.2
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "light-charging",
|
||||
"directions": 1,
|
||||
"delays": [
|
||||
[
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "light-charged",
|
||||
"directions": 1,
|
||||
"delays": [
|
||||
[
|
||||
0.2,
|
||||
0.1
|
||||
]
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||