using Content.Server.Power.Components; using Content.Shared.Damage; using Content.Shared.Damage.Events; using Content.Shared.FixedPoint; using Content.Shared.PowerCell.Components; using Content.Shared.Projectiles; using Content.Shared.Weapons.Ranged; using Content.Shared.Weapons.Ranged.Components; using Content.Shared.Weapons.Ranged.Events; 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); SubscribeLocalEvent(OnPowerCellChanged); // Projectile SubscribeLocalEvent(OnBatteryStartup); SubscribeLocalEvent(OnBatteryChargeChange); SubscribeLocalEvent(OnBatteryDamageExamine); SubscribeLocalEvent(OnPowerCellChanged); } private void OnBatteryStartup(Entity entity, ref ComponentStartup args) where T : BatteryAmmoProviderComponent { UpdateShots(entity, entity.Comp); } private void OnBatteryChargeChange(Entity entity, ref ChargeChangedEvent args) where T : BatteryAmmoProviderComponent { UpdateShots(entity, entity.Comp, args.Charge, args.MaxCharge); } private void OnPowerCellChanged(Entity entity, ref PowerCellChangedEvent args) where T : BatteryAmmoProviderComponent { UpdateShots(entity, entity.Comp); } private void UpdateShots(EntityUid uid, BatteryAmmoProviderComponent component) { var ev = new GetChargeEvent(); RaiseLocalEvent(uid, ref ev); UpdateShots(uid, component, ev.CurrentCharge, ev.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; if (maxShots > 0) component.Capacity = maxShots; UpdateBatteryAppearance(uid, component); var updateAmmoEv = new UpdateClientAmmoEvent(); RaiseLocalEvent(uid, ref updateAmmoEv); } private void OnBatteryDamageExamine(Entity entity, ref DamageExamineEvent args) where T : BatteryAmmoProviderComponent { var damageSpec = GetDamage(entity.Comp); if (damageSpec == null) return; var damageType = entity.Comp 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(Entity entity) { var ev = new ChangeChargeEvent(-entity.Comp.FireCost); RaiseLocalEvent(entity, ref ev); } }