107 lines
3.8 KiB
C#
107 lines
3.8 KiB
C#
using Content.Server.Projectiles.Components;
|
|
using Content.Server.Weapon.Ranged.Barrels.Components;
|
|
using Content.Shared.PowerCell.Components;
|
|
using Content.Shared.Weapons.Ranged.Barrels.Components;
|
|
using Robust.Shared.Containers;
|
|
using Robust.Shared.Map;
|
|
|
|
namespace Content.Server.Weapon.Ranged;
|
|
|
|
public sealed partial class GunSystem
|
|
{
|
|
private void OnBatteryInit(EntityUid uid, BatteryBarrelComponent component, ComponentInit args)
|
|
{
|
|
if (component.AmmoPrototype != null)
|
|
{
|
|
component.AmmoContainer = uid.EnsureContainer<ContainerSlot>($"{component.GetType()}-ammo-container");
|
|
}
|
|
|
|
component.Dirty(EntityManager);
|
|
}
|
|
|
|
private void OnBatteryMapInit(EntityUid uid, BatteryBarrelComponent component, MapInitEvent args)
|
|
{
|
|
UpdateBatteryAppearance(component);
|
|
}
|
|
|
|
private void OnCellSlotUpdated(EntityUid uid, BatteryBarrelComponent component, PowerCellChangedEvent args)
|
|
{
|
|
UpdateBatteryAppearance(component);
|
|
}
|
|
|
|
public void UpdateBatteryAppearance(BatteryBarrelComponent component)
|
|
{
|
|
if (!EntityManager.TryGetComponent(component.Owner, out AppearanceComponent? appearanceComponent)) return;
|
|
|
|
appearanceComponent.SetData(MagazineBarrelVisuals.MagLoaded, _cell.TryGetBatteryFromSlot(component.Owner, out _));
|
|
appearanceComponent.SetData(AmmoVisuals.AmmoCount, component.ShotsLeft);
|
|
appearanceComponent.SetData(AmmoVisuals.AmmoMax, component.Capacity);
|
|
}
|
|
|
|
public EntityUid? PeekAmmo(BatteryBarrelComponent component)
|
|
{
|
|
// Spawn a dummy entity because it's easier to work with I guess
|
|
// This will get re-used for the projectile
|
|
var ammo = component.AmmoContainer.ContainedEntity;
|
|
if (ammo == null)
|
|
{
|
|
ammo = EntityManager.SpawnEntity(component.AmmoPrototype, Transform(component.Owner).Coordinates);
|
|
component.AmmoContainer.Insert(ammo.Value);
|
|
}
|
|
|
|
return ammo.Value;
|
|
}
|
|
|
|
public EntityUid? TakeProjectile(BatteryBarrelComponent component, EntityCoordinates spawnAt)
|
|
{
|
|
if (!_cell.TryGetBatteryFromSlot(component.Owner, out var capacitor))
|
|
return null;
|
|
|
|
if (capacitor.CurrentCharge < component.LowerChargeLimit)
|
|
return null;
|
|
|
|
// Can fire confirmed
|
|
// Multiply the entity's damage / whatever by the percentage of charge the shot has.
|
|
EntityUid? entity;
|
|
var chargeChange = Math.Min(capacitor.CurrentCharge, component.BaseFireCost);
|
|
if (capacitor.UseCharge(chargeChange) < component.LowerChargeLimit)
|
|
{
|
|
// Handling of funny exploding cells.
|
|
return null;
|
|
}
|
|
var energyRatio = chargeChange / component.BaseFireCost;
|
|
|
|
if (component.AmmoContainer.ContainedEntity != null)
|
|
{
|
|
entity = component.AmmoContainer.ContainedEntity;
|
|
component.AmmoContainer.Remove(entity.Value);
|
|
Transform(entity.Value).Coordinates = spawnAt;
|
|
}
|
|
else
|
|
{
|
|
entity = EntityManager.SpawnEntity(component.AmmoPrototype, spawnAt);
|
|
}
|
|
|
|
if (TryComp(entity.Value, out ProjectileComponent? projectileComponent))
|
|
{
|
|
if (energyRatio < 1.0)
|
|
{
|
|
projectileComponent.Damage *= energyRatio;
|
|
}
|
|
}
|
|
else if (TryComp(entity.Value, out HitscanComponent? hitscanComponent))
|
|
{
|
|
hitscanComponent.Damage *= energyRatio;
|
|
hitscanComponent.ColorModifier = energyRatio;
|
|
}
|
|
else
|
|
{
|
|
throw new InvalidOperationException("Ammo doesn't have hitscan or projectile?");
|
|
}
|
|
|
|
// capacitor.UseCharge() triggers a PowerCellChangedEvent which will cause appearance to be updated.
|
|
// So let's not double-call UpdateAppearance() here.
|
|
return entity.Value;
|
|
}
|
|
}
|