using Content.Shared.Access.Components; using Content.Shared.Access.Systems; using Content.Shared.Database; using Content.Shared.Examine; using Content.Shared.Interaction.Events; using Content.Shared.Popups; using Content.Shared.Verbs; using Content.Shared.Weapons.Ranged.Components; using Content.Shared.Weapons.Ranged.Events; using Robust.Shared.Prototypes; namespace Content.Shared.Weapons.Ranged.Systems; public sealed class BatteryWeaponFireModesSystem : EntitySystem { [Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly SharedPopupSystem _popupSystem = default!; [Dependency] private readonly AccessReaderSystem _accessReaderSystem = default!; [Dependency] private readonly SharedAppearanceSystem _appearanceSystem = default!; public override void Initialize() { base.Initialize(); SubscribeLocalEvent(OnUseInHandEvent); SubscribeLocalEvent>(OnGetVerb); SubscribeLocalEvent(OnExamined); } private void OnExamined(EntityUid uid, BatteryWeaponFireModesComponent component, ExaminedEvent args) { if (component.FireModes.Count < 2) return; var fireMode = GetMode(component); if (!_prototypeManager.TryIndex(fireMode.Prototype, out var proto)) return; args.PushMarkup(Loc.GetString("gun-set-fire-mode", ("mode", proto.Name))); } private BatteryWeaponFireMode GetMode(BatteryWeaponFireModesComponent component) { return component.FireModes[component.CurrentFireMode]; } private void OnGetVerb(EntityUid uid, BatteryWeaponFireModesComponent component, GetVerbsEvent args) { if (!args.CanAccess || !args.CanInteract || !args.CanComplexInteract) return; if (component.FireModes.Count < 2) return; if (!_accessReaderSystem.IsAllowed(args.User, uid)) return; for (var i = 0; i < component.FireModes.Count; i++) { var fireMode = component.FireModes[i]; var entProto = _prototypeManager.Index(fireMode.Prototype); var index = i; var v = new Verb { Priority = 1, Category = VerbCategory.SelectType, Text = entProto.Name, Disabled = i == component.CurrentFireMode, Impact = LogImpact.Medium, DoContactInteraction = true, Act = () => { TrySetFireMode(uid, component, index, args.User); } }; args.Verbs.Add(v); } } private void OnUseInHandEvent(EntityUid uid, BatteryWeaponFireModesComponent component, UseInHandEvent args) { if(args.Handled) return; args.Handled = true; TryCycleFireMode(uid, component, args.User); } public void TryCycleFireMode(EntityUid uid, BatteryWeaponFireModesComponent component, EntityUid? user = null) { if (component.FireModes.Count < 2) return; var index = (component.CurrentFireMode + 1) % component.FireModes.Count; TrySetFireMode(uid, component, index, user); } public bool TrySetFireMode(EntityUid uid, BatteryWeaponFireModesComponent component, int index, EntityUid? user = null) { if (index < 0 || index >= component.FireModes.Count) return false; if (user != null && !_accessReaderSystem.IsAllowed(user.Value, uid)) return false; SetFireMode(uid, component, index, user); return true; } private void SetFireMode(EntityUid uid, BatteryWeaponFireModesComponent component, int index, EntityUid? user = null) { var fireMode = component.FireModes[index]; component.CurrentFireMode = index; Dirty(uid, component); if (_prototypeManager.TryIndex(fireMode.Prototype, out var prototype)) { if (TryComp(uid, out var appearance)) _appearanceSystem.SetData(uid, BatteryWeaponFireModeVisuals.State, prototype.ID, appearance); if (user != null) _popupSystem.PopupClient(Loc.GetString("gun-set-fire-mode", ("mode", prototype.Name)), uid, user.Value); } if (TryComp(uid, out ProjectileBatteryAmmoProviderComponent? projectileBatteryAmmoProviderComponent)) { // TODO: Have this get the info directly from the batteryComponent when power is moved to shared. var OldFireCost = projectileBatteryAmmoProviderComponent.FireCost; projectileBatteryAmmoProviderComponent.Prototype = fireMode.Prototype; projectileBatteryAmmoProviderComponent.FireCost = fireMode.FireCost; float FireCostDiff = (float)fireMode.FireCost / (float)OldFireCost; projectileBatteryAmmoProviderComponent.Shots = (int)Math.Round(projectileBatteryAmmoProviderComponent.Shots / FireCostDiff); projectileBatteryAmmoProviderComponent.Capacity = (int)Math.Round(projectileBatteryAmmoProviderComponent.Capacity / FireCostDiff); Dirty(uid, projectileBatteryAmmoProviderComponent); var updateClientAmmoEvent = new UpdateClientAmmoEvent(); RaiseLocalEvent(uid, ref updateClientAmmoEvent); } } }