146 lines
5.6 KiB
C#
146 lines
5.6 KiB
C#
using System.Linq;
|
|
using Content.Shared.Administration.Logs;
|
|
using Content.Shared.Database;
|
|
using Content.Shared.Examine;
|
|
using Content.Shared.Interaction;
|
|
using Content.Shared.Popups;
|
|
using Content.Shared.Projectiles;
|
|
using Content.Shared.Tag;
|
|
using Content.Shared.Weapons.Ranged.Events;
|
|
using Content.Shared.Weapons.Ranged.Systems;
|
|
using Content.Shared.Weapons.Ranged.Upgrades.Components;
|
|
using Content.Shared.Whitelist;
|
|
using Robust.Shared.Audio.Systems;
|
|
using Robust.Shared.Containers;
|
|
using Robust.Shared.Prototypes;
|
|
|
|
namespace Content.Shared.Weapons.Ranged.Upgrades;
|
|
|
|
public sealed class GunUpgradeSystem : EntitySystem
|
|
{
|
|
[Dependency] private readonly ISharedAdminLogManager _adminLog = default!;
|
|
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
|
[Dependency] private readonly SharedContainerSystem _container = default!;
|
|
[Dependency] private readonly SharedGunSystem _gun = default!;
|
|
[Dependency] private readonly EntityWhitelistSystem _entityWhitelist = default!;
|
|
[Dependency] private readonly SharedPopupSystem _popup = default!;
|
|
|
|
/// <inheritdoc/>
|
|
public override void Initialize()
|
|
{
|
|
SubscribeLocalEvent<UpgradeableGunComponent, ComponentInit>(OnInit);
|
|
SubscribeLocalEvent<UpgradeableGunComponent, AfterInteractUsingEvent>(OnAfterInteractUsing);
|
|
SubscribeLocalEvent<UpgradeableGunComponent, ExaminedEvent>(OnExamine);
|
|
|
|
SubscribeLocalEvent<UpgradeableGunComponent, GunRefreshModifiersEvent>(RelayEvent);
|
|
SubscribeLocalEvent<UpgradeableGunComponent, GunShotEvent>(RelayEvent);
|
|
|
|
SubscribeLocalEvent<GunUpgradeFireRateComponent, GunRefreshModifiersEvent>(OnFireRateRefresh);
|
|
SubscribeLocalEvent<GunUpgradeSpeedComponent, GunRefreshModifiersEvent>(OnSpeedRefresh);
|
|
SubscribeLocalEvent<GunUpgradeDamageComponent, GunShotEvent>(OnDamageGunShot);
|
|
}
|
|
|
|
private void RelayEvent<T>(Entity<UpgradeableGunComponent> ent, ref T args) where T : notnull
|
|
{
|
|
foreach (var upgrade in GetCurrentUpgrades(ent))
|
|
{
|
|
RaiseLocalEvent(upgrade, ref args);
|
|
}
|
|
}
|
|
|
|
private void OnExamine(Entity<UpgradeableGunComponent> ent, ref ExaminedEvent args)
|
|
{
|
|
using (args.PushGroup(nameof(UpgradeableGunComponent)))
|
|
{
|
|
foreach (var upgrade in GetCurrentUpgrades(ent))
|
|
{
|
|
args.PushMarkup(Loc.GetString(upgrade.Comp.ExamineText));
|
|
}
|
|
}
|
|
}
|
|
|
|
private void OnInit(Entity<UpgradeableGunComponent> ent, ref ComponentInit args)
|
|
{
|
|
_container.EnsureContainer<Container>(ent, ent.Comp.UpgradesContainerId);
|
|
}
|
|
|
|
private void OnAfterInteractUsing(Entity<UpgradeableGunComponent> ent, ref AfterInteractUsingEvent args)
|
|
{
|
|
if (args.Handled || !args.CanReach || !TryComp<GunUpgradeComponent>(args.Used, out var upgradeComponent))
|
|
return;
|
|
|
|
if (GetCurrentUpgrades(ent).Count >= ent.Comp.MaxUpgradeCount)
|
|
{
|
|
_popup.PopupPredicted(Loc.GetString("upgradeable-gun-popup-upgrade-limit"), ent, args.User);
|
|
return;
|
|
}
|
|
|
|
if (_entityWhitelist.IsWhitelistFail(ent.Comp.Whitelist, args.Used))
|
|
return;
|
|
|
|
if (GetCurrentUpgradeTags(ent).ToHashSet().IsSupersetOf(upgradeComponent.Tags))
|
|
{
|
|
_popup.PopupPredicted(Loc.GetString("upgradeable-gun-popup-already-present"), ent, args.User);
|
|
return;
|
|
}
|
|
|
|
_audio.PlayPredicted(ent.Comp.InsertSound, ent, args.User);
|
|
_popup.PopupClient(Loc.GetString("gun-upgrade-popup-insert", ("upgrade", args.Used),("gun", ent.Owner)), args.User);
|
|
_gun.RefreshModifiers(ent.Owner);
|
|
args.Handled = _container.Insert(args.Used, _container.GetContainer(ent, ent.Comp.UpgradesContainerId));
|
|
|
|
_adminLog.Add(LogType.Action, LogImpact.Low, $"{ToPrettyString(args.User):player} inserted gun upgrade {ToPrettyString(args.Used)} into {ToPrettyString(ent.Owner)}.");
|
|
}
|
|
|
|
private void OnFireRateRefresh(Entity<GunUpgradeFireRateComponent> ent, ref GunRefreshModifiersEvent args)
|
|
{
|
|
args.FireRate *= ent.Comp.Coefficient;
|
|
}
|
|
|
|
private void OnSpeedRefresh(Entity<GunUpgradeSpeedComponent> ent, ref GunRefreshModifiersEvent args)
|
|
{
|
|
args.ProjectileSpeed *= ent.Comp.Coefficient;
|
|
}
|
|
|
|
private void OnDamageGunShot(Entity<GunUpgradeDamageComponent> ent, ref GunShotEvent args)
|
|
{
|
|
foreach (var (ammo, _) in args.Ammo)
|
|
{
|
|
if (TryComp<ProjectileComponent>(ammo, out var proj))
|
|
proj.Damage += ent.Comp.Damage;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the entities inside the gun's upgrade container.
|
|
/// </summary>
|
|
public HashSet<Entity<GunUpgradeComponent>> GetCurrentUpgrades(Entity<UpgradeableGunComponent> ent)
|
|
{
|
|
if (!_container.TryGetContainer(ent, ent.Comp.UpgradesContainerId, out var container))
|
|
return new HashSet<Entity<GunUpgradeComponent>>();
|
|
|
|
var upgrades = new HashSet<Entity<GunUpgradeComponent>>();
|
|
foreach (var contained in container.ContainedEntities)
|
|
{
|
|
if (TryComp<GunUpgradeComponent>(contained, out var upgradeComp))
|
|
upgrades.Add((contained, upgradeComp));
|
|
}
|
|
|
|
return upgrades;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the tags of the upgrades currently applied.
|
|
/// </summary>
|
|
public IEnumerable<ProtoId<TagPrototype>> GetCurrentUpgradeTags(Entity<UpgradeableGunComponent> ent)
|
|
{
|
|
foreach (var upgrade in GetCurrentUpgrades(ent))
|
|
{
|
|
foreach (var tag in upgrade.Comp.Tags)
|
|
{
|
|
yield return tag;
|
|
}
|
|
}
|
|
}
|
|
}
|