using Content.Server.Power.Components; using Content.Shared.Damage; using Content.Shared.Damage.Events; using Content.Shared.FixedPoint; using Content.Shared.Projectiles; using Content.Shared.Weapons.Ranged; using Content.Shared.Weapons.Ranged.Components; using Robust.Shared.Prototypes; namespace Content.Server.Weapons.Ranged.Systems; public sealed partial class GunSystem { protected override void InitializeBattery() { base.InitializeBattery(); // Hitscan SubscribeLocalEvent(OnBatteryStartup); SubscribeLocalEvent(OnBatteryChargeChange); SubscribeLocalEvent(OnBatteryDamageExamine); // Projectile SubscribeLocalEvent(OnBatteryStartup); SubscribeLocalEvent(OnBatteryChargeChange); SubscribeLocalEvent(OnBatteryDamageExamine); } private void OnBatteryStartup(EntityUid uid, BatteryAmmoProviderComponent component, ComponentStartup args) { UpdateShots(uid, component); } private void OnBatteryChargeChange(EntityUid uid, BatteryAmmoProviderComponent component, ref ChargeChangedEvent args) { UpdateShots(uid, component, args.Charge, args.MaxCharge); } private void UpdateShots(EntityUid uid, BatteryAmmoProviderComponent component) { if (!TryComp(uid, out var battery)) return; UpdateShots(uid, component, battery.CurrentCharge, battery.MaxCharge); } private void UpdateShots(EntityUid uid, BatteryAmmoProviderComponent component, float charge, float maxCharge) { var shots = (int) (charge / component.FireCost); var maxShots = (int) (maxCharge / component.FireCost); if (component.Shots != shots || component.Capacity != maxShots) { Dirty(uid, component); } component.Shots = shots; component.Capacity = maxShots; UpdateBatteryAppearance(uid, component); } private void OnBatteryDamageExamine(EntityUid uid, BatteryAmmoProviderComponent component, ref DamageExamineEvent args) { var damageSpec = GetDamage(component); if (damageSpec == null) return; var damageType = component switch { HitscanBatteryAmmoProviderComponent => Loc.GetString("damage-hitscan"), ProjectileBatteryAmmoProviderComponent => Loc.GetString("damage-projectile"), _ => throw new ArgumentOutOfRangeException(), }; _damageExamine.AddDamageExamine(args.Message, Damageable.ApplyUniversalAllModifiers(damageSpec), damageType); } private DamageSpecifier? GetDamage(BatteryAmmoProviderComponent component) { if (component is ProjectileBatteryAmmoProviderComponent battery) { if (ProtoManager.Index(battery.Prototype).Components .TryGetValue(_factory.GetComponentName(typeof(ProjectileComponent)), out var projectile)) { var p = (ProjectileComponent) projectile.Component; if (!p.Damage.Empty) { return p.Damage * Damageable.UniversalProjectileDamageModifier; } } return null; } if (component is HitscanBatteryAmmoProviderComponent hitscan) { var dmg = ProtoManager.Index(hitscan.Prototype).Damage; return dmg == null ? dmg : dmg * Damageable.UniversalHitscanDamageModifier; } return null; } protected override void TakeCharge(EntityUid uid, BatteryAmmoProviderComponent component) { // Will raise ChargeChangedEvent _battery.UseCharge(uid, component.FireCost); } }