using System; using Content.Server.GameObjects.EntitySystems; using Content.Server.Utility; 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 { /// /// This is used for the standalone cell rechargers (e.g. from a flashlight) /// [RegisterComponent] [ComponentReference(typeof(IActivate))] [ComponentReference(typeof(IInteractUsing))] public sealed class PowerCellChargerComponent : BaseCharger, IActivate, IInteractUsing { public override string Name => "PowerCellCharger"; public override double CellChargePercent => _container.ContainedEntity != null ? _container.ContainedEntity.GetComponent().Charge / _container.ContainedEntity.GetComponent().Capacity * 100 : 0.0f; public override void Initialize() { base.Initialize(); _powerDevice = Owner.GetComponent(); _container = ContainerManagerComponent.Ensure($"{Name}-powerCellContainer", Owner); _appearanceComponent = Owner.GetComponent(); // Default state in the visualizer is OFF, so when this gets powered on during initialization it will generally show empty _powerDevice.OnPowerStateChanged += PowerUpdate; } bool IInteractUsing.InteractUsing(InteractUsingEventArgs eventArgs) { var result = TryInsertItem(eventArgs.Using); if (result) { return true; } var localizationManager = IoCManager.Resolve(); eventArgs.User.PopupMessage(Owner, localizationManager.GetString("Unable to insert capacitor")); return false; } void IActivate.Activate(ActivateEventArgs eventArgs) { RemoveItem(eventArgs.User); } [Verb] private sealed class InsertVerb : Verb { protected override void GetData(IEntity user, PowerCellChargerComponent component, VerbData data) { if (!ActionBlockerSystem.CanInteract(user)) { data.Visibility = VerbVisibility.Invisible; return; } if (!user.TryGetComponent(out HandsComponent handsComponent)) { data.Visibility = VerbVisibility.Invisible; return; } if (component._container.ContainedEntity != null || handsComponent.GetActiveHand == null) { data.Visibility = VerbVisibility.Disabled; data.Text = "Insert"; return; } data.Text = $"Insert {handsComponent.GetActiveHand.Owner.Name}"; } 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 { protected override void GetData(IEntity user, PowerCellChargerComponent component, VerbData data) { if (!ActionBlockerSystem.CanInteract(user)) { data.Visibility = VerbVisibility.Invisible; return; } if (component._container.ContainedEntity == null) { data.Text = "Eject"; data.Visibility = VerbVisibility.Disabled; return; } data.Text = $"Eject {component._container.ContainedEntity.Name}"; } protected override void Activate(IEntity user, PowerCellChargerComponent component) { component.RemoveItem(user); } } public bool TryInsertItem(IEntity entity) { if (!entity.HasComponent() || _container.ContainedEntity != null) { return false; } if (!_container.Insert(entity)) { 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 var cellComponent = _container.ContainedEntity.GetComponent(); 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(); } } }