From d3b1178428e9e0e714e51523558335589078a76c Mon Sep 17 00:00:00 2001 From: beck-thompson <107373427+beck-thompson@users.noreply.github.com> Date: Wed, 24 Apr 2024 19:19:16 -0700 Subject: [PATCH] Radio jammer update! (#25912) * Added selectable power level to radio jammer * Cleaned up OnGetVerb * Settings are now stored in the .yml file. Simplified stuff a lot! * Minor fixes! * Small little baby fix :) * Added the power level switch to the examine menu and also removed the ftl file as it was in the incorrect location. * Minor code cleanup * Changed byte -> int * Update sprite * Fixed licence * Added power LED that changes if the jammer is on low power. * Removed tabs * Changed github link to the commit * Changed all the RemComp to RemComDeferred * Moved NetworkedComponent to shared * Changed radio jammer textures back with minor edits * Added a space because it was annoying me * Jammer now updates range for suit sensors properly! Thanks nikthechampiongr :) * Removed useless comment * Cleaned up code that updates the range of tracking devices. * Fixed client namespace and removed newline * Cleaned up ChangeLEDState and ChangeChargeLevel. * Added comments * Read only * Fixed another comment * Locked in * Made server inherit shared * Update Content.Shared/Radio/EntitySystems/SharedJammerSystem.cs * Update Content.Shared/Radio/EntitySystems/SharedJammerSystem.cs * review fixes --------- Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> Co-authored-by: metalgearsloth --- Content.Client/DeviceNetwork/JammerSystem.cs | 8 ++ .../Radio/Components/RadioJammerComponent.cs | 20 ----- .../Radio/EntitySystems/JammerSystem.cs | 68 ++++++++++----- .../Components/SharedRadioJammerComponent.cs | 74 +++++++++++++++++ .../Radio/EntitySystems/SharedJammerSystem.cs | 78 ++++++++++++++++++ Content.Shared/Verbs/VerbCategory.cs | 2 + .../components/radio-jammer-component.ftl | 10 +++ Resources/Locale/en-US/verbs/verb-system.ftl | 1 + .../Entities/Objects/Tools/jammer.yml | 32 ++++++- .../Objects/Devices/jammer.rsi/jammer.png | Bin 495 -> 939 bytes .../Devices/jammer.rsi/jammer_high_charge.png | Bin 0 -> 609 bytes .../Devices/jammer.rsi/jammer_low_charge.png | Bin 0 -> 617 bytes .../jammer.rsi/jammer_medium_charge.png | Bin 0 -> 608 bytes .../Objects/Devices/jammer.rsi/meta.json | 22 ++++- 14 files changed, 272 insertions(+), 43 deletions(-) create mode 100644 Content.Client/DeviceNetwork/JammerSystem.cs delete mode 100644 Content.Server/Radio/Components/RadioJammerComponent.cs create mode 100644 Content.Shared/Radio/Components/SharedRadioJammerComponent.cs create mode 100644 Content.Shared/Radio/EntitySystems/SharedJammerSystem.cs create mode 100644 Resources/Textures/Objects/Devices/jammer.rsi/jammer_high_charge.png create mode 100644 Resources/Textures/Objects/Devices/jammer.rsi/jammer_low_charge.png create mode 100644 Resources/Textures/Objects/Devices/jammer.rsi/jammer_medium_charge.png diff --git a/Content.Client/DeviceNetwork/JammerSystem.cs b/Content.Client/DeviceNetwork/JammerSystem.cs new file mode 100644 index 0000000000..c7dbf8c8fe --- /dev/null +++ b/Content.Client/DeviceNetwork/JammerSystem.cs @@ -0,0 +1,8 @@ +using Content.Shared.Radio.EntitySystems; + +namespace Content.Client.DeviceNetwork; + +public sealed class JammerSystem : SharedJammerSystem +{ + +} diff --git a/Content.Server/Radio/Components/RadioJammerComponent.cs b/Content.Server/Radio/Components/RadioJammerComponent.cs deleted file mode 100644 index 93504ef957..0000000000 --- a/Content.Server/Radio/Components/RadioJammerComponent.cs +++ /dev/null @@ -1,20 +0,0 @@ -using Content.Server.Radio.EntitySystems; - -namespace Content.Server.Radio.Components; - -/// -/// When activated () prevents from sending messages in range -/// -[RegisterComponent] -[Access(typeof(JammerSystem))] -public sealed partial class RadioJammerComponent : Component -{ - [DataField("range"), ViewVariables(VVAccess.ReadWrite)] - public float Range = 8f; - - /// - /// Power usage per second when enabled - /// - [DataField("wattage"), ViewVariables(VVAccess.ReadWrite)] - public float Wattage = 2f; -} diff --git a/Content.Server/Radio/EntitySystems/JammerSystem.cs b/Content.Server/Radio/EntitySystems/JammerSystem.cs index 5a2a854017..4f58cb21e1 100644 --- a/Content.Server/Radio/EntitySystems/JammerSystem.cs +++ b/Content.Server/Radio/EntitySystems/JammerSystem.cs @@ -1,26 +1,22 @@ using Content.Server.DeviceNetwork.Components; -using Content.Server.DeviceNetwork.Systems; -using Content.Server.Medical.CrewMonitoring; using Content.Server.Popups; using Content.Server.Power.EntitySystems; using Content.Server.PowerCell; using Content.Server.Radio.Components; -using Content.Server.Station.Systems; using Content.Shared.DeviceNetwork.Components; using Content.Shared.Examine; using Content.Shared.Interaction; using Content.Shared.PowerCell.Components; +using Content.Shared.RadioJammer; +using Content.Shared.Radio.EntitySystems; namespace Content.Server.Radio.EntitySystems; -public sealed class JammerSystem : EntitySystem +public sealed class JammerSystem : SharedJammerSystem { [Dependency] private readonly PowerCellSystem _powerCell = default!; [Dependency] private readonly BatterySystem _battery = default!; - [Dependency] private readonly PopupSystem _popup = default!; [Dependency] private readonly SharedTransformSystem _transform = default!; - [Dependency] private readonly StationSystem _stationSystem = default!; - [Dependency] private readonly SingletonDeviceNetServerSystem _singletonServerSystem = default!; public override void Initialize() { @@ -35,14 +31,37 @@ public sealed class JammerSystem : EntitySystem public override void Update(float frameTime) { var query = EntityQueryEnumerator(); + while (query.MoveNext(out var uid, out var _, out var jam)) { - if (_powerCell.TryGetBatteryFromSlot(uid, out var batteryUid, out var battery) && - !_battery.TryUseCharge(batteryUid.Value, jam.Wattage * frameTime, battery)) + + if (_powerCell.TryGetBatteryFromSlot(uid, out var batteryUid, out var battery)) { - RemComp(uid); - RemComp(uid); + if (!_battery.TryUseCharge(batteryUid.Value, GetCurrentWattage(jam) * frameTime, battery)) + { + ChangeLEDState(false, uid); + RemComp(uid); + RemComp(uid); + } + else + { + var percentCharged = battery.CurrentCharge / battery.MaxCharge; + if (percentCharged > .50) + { + ChangeChargeLevel(RadioJammerChargeLevel.High, uid); + } + else if (percentCharged < .15) + { + ChangeChargeLevel(RadioJammerChargeLevel.Low, uid); + } + else + { + ChangeChargeLevel(RadioJammerChargeLevel.Medium, uid); + } + } + } + } } @@ -50,40 +69,49 @@ public sealed class JammerSystem : EntitySystem { var activated = !HasComp(uid) && _powerCell.TryGetBatteryFromSlot(uid, out var battery) && - battery.CurrentCharge > comp.Wattage; + battery.CurrentCharge > GetCurrentWattage(comp); if (activated) { + ChangeLEDState(true, uid); EnsureComp(uid); EnsureComp(uid, out var jammingComp); - jammingComp.Range = comp.Range; + jammingComp.Range = GetCurrentRange(comp); jammingComp.JammableNetworks.Add(DeviceNetworkComponent.DeviceNetIdDefaults.Wireless.ToString()); Dirty(uid, jammingComp); } else { - RemComp(uid); - RemComp(uid); + ChangeLEDState(false, uid); + RemCompDeferred(uid); + RemCompDeferred(uid); } var state = Loc.GetString(activated ? "radio-jammer-component-on-state" : "radio-jammer-component-off-state"); var message = Loc.GetString("radio-jammer-component-on-use", ("state", state)); - _popup.PopupEntity(message, args.User, args.User); + Popup.PopupEntity(message, args.User, args.User); args.Handled = true; } private void OnPowerCellChanged(EntityUid uid, ActiveRadioJammerComponent comp, PowerCellChangedEvent args) { if (args.Ejected) - RemComp(uid); + { + ChangeLEDState(false, uid); + RemCompDeferred(uid); + } } private void OnExamine(EntityUid uid, RadioJammerComponent comp, ExaminedEvent args) { if (args.IsInDetailsRange) { - var msg = HasComp(uid) + var powerIndicator = HasComp(uid) ? Loc.GetString("radio-jammer-component-examine-on-state") : Loc.GetString("radio-jammer-component-examine-off-state"); - args.PushMarkup(msg); + args.PushMarkup(powerIndicator); + + var powerLevel = Loc.GetString(comp.Settings[comp.SelectedPowerLevel].Name); + var switchIndicator = Loc.GetString("radio-jammer-component-switch-setting", ("powerLevel", powerLevel)); + args.PushMarkup(switchIndicator); } } @@ -102,7 +130,7 @@ public sealed class JammerSystem : EntitySystem while (query.MoveNext(out _, out _, out var jam, out var transform)) { - if (source.InRange(EntityManager, _transform, transform.Coordinates, jam.Range)) + if (source.InRange(EntityManager, _transform, transform.Coordinates, GetCurrentRange(jam))) { return true; } diff --git a/Content.Shared/Radio/Components/SharedRadioJammerComponent.cs b/Content.Shared/Radio/Components/SharedRadioJammerComponent.cs new file mode 100644 index 0000000000..e5e52a3e47 --- /dev/null +++ b/Content.Shared/Radio/Components/SharedRadioJammerComponent.cs @@ -0,0 +1,74 @@ +using Robust.Shared.Serialization; +using Robust.Shared.GameStates; + +namespace Content.Shared.RadioJammer; + +/// +/// When activated () prevents from sending messages in range +/// Suit sensors will also stop working. +/// +[NetworkedComponent, RegisterComponent] +public sealed partial class RadioJammerComponent : Component +{ + [DataDefinition] + public partial struct RadioJamSetting + { + /// + /// Power usage per second when enabled. + /// + [DataField(required: true)] + public float Wattage; + + /// + /// Range of the jammer. + /// + [DataField(required: true)] + public float Range; + + /// + /// The message that is displayed when switched + /// to this setting. + /// + [DataField(required: true)] + public LocId Message = string.Empty; + + /// + /// Name of the setting. + /// + [DataField(required: true)] + public LocId Name = string.Empty; + } + + /// + /// List of all the settings for the radio jammer. + /// + [DataField(required: true), ViewVariables(VVAccess.ReadOnly)] + public RadioJamSetting[] Settings; + + /// + /// Index of the currently selected setting. + /// + [DataField] + public int SelectedPowerLevel = 1; +} + +[Serializable, NetSerializable] +public enum RadioJammerChargeLevel : byte +{ + Low, + Medium, + High +} + +[Serializable, NetSerializable] +public enum RadioJammerLayers : byte +{ + LED +} + +[Serializable, NetSerializable] +public enum RadioJammerVisuals : byte +{ + ChargeLevel, + LEDOn +} diff --git a/Content.Shared/Radio/EntitySystems/SharedJammerSystem.cs b/Content.Shared/Radio/EntitySystems/SharedJammerSystem.cs new file mode 100644 index 0000000000..e1f632735c --- /dev/null +++ b/Content.Shared/Radio/EntitySystems/SharedJammerSystem.cs @@ -0,0 +1,78 @@ +using Content.Shared.Popups; +using Content.Shared.DeviceNetwork.Components; +using Content.Shared.Verbs; +using Content.Shared.RadioJammer; + +namespace Content.Shared.Radio.EntitySystems; + +public abstract class SharedJammerSystem : EntitySystem +{ + [Dependency] private readonly SharedAppearanceSystem _appearance = default!; + [Dependency] protected readonly SharedPopupSystem Popup = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent>(OnGetVerb); + } + + private void OnGetVerb(Entity entity, ref GetVerbsEvent args) + { + if (!args.CanAccess || !args.CanInteract) + return; + + var user = args.User; + + byte index = 0; + foreach (var setting in entity.Comp.Settings) + { + // This is because Act wont work with index. + // Needs it to be saved in the loop. + var currIndex = index; + var verb = new Verb + { + Priority = currIndex, + Category = VerbCategory.PowerLevel, + Disabled = entity.Comp.SelectedPowerLevel == currIndex, + Act = () => + { + entity.Comp.SelectedPowerLevel = currIndex; + if (TryComp(entity.Owner, out var jammerComp)) + { + // This is a little sketcy but only way to do it. + jammerComp.Range = GetCurrentRange(entity.Comp); + Dirty(entity.Owner, jammerComp); + } + Popup.PopupPredicted(Loc.GetString(setting.Message), user, user); + }, + Text = Loc.GetString(setting.Name), + }; + args.Verbs.Add(verb); + index++; + } + } + + public float GetCurrentWattage(RadioJammerComponent jammer) + { + return jammer.Settings[jammer.SelectedPowerLevel].Wattage; + } + + public float GetCurrentRange(RadioJammerComponent jammer) + { + return jammer.Settings[jammer.SelectedPowerLevel].Range; + } + + protected void ChangeLEDState(bool isLEDOn, EntityUid uid, + AppearanceComponent? appearance = null) + { + _appearance.SetData(uid, RadioJammerVisuals.LEDOn, isLEDOn, appearance); + } + + protected void ChangeChargeLevel(RadioJammerChargeLevel chargeLevel, EntityUid uid, + AppearanceComponent? appearance = null) + { + _appearance.SetData(uid, RadioJammerVisuals.ChargeLevel, chargeLevel, appearance); + } + +} diff --git a/Content.Shared/Verbs/VerbCategory.cs b/Content.Shared/Verbs/VerbCategory.cs index d22041396f..9b9197249a 100644 --- a/Content.Shared/Verbs/VerbCategory.cs +++ b/Content.Shared/Verbs/VerbCategory.cs @@ -83,5 +83,7 @@ namespace Content.Shared.Verbs public static readonly VerbCategory Lever = new("verb-categories-lever", null); public static readonly VerbCategory SelectType = new("verb-categories-select-type", null); + + public static readonly VerbCategory PowerLevel = new("verb-categories-power-level", null); } } diff --git a/Resources/Locale/en-US/radio/components/radio-jammer-component.ftl b/Resources/Locale/en-US/radio/components/radio-jammer-component.ftl index 68efbf8d4e..eb540ee971 100644 --- a/Resources/Locale/en-US/radio/components/radio-jammer-component.ftl +++ b/Resources/Locale/en-US/radio/components/radio-jammer-component.ftl @@ -4,3 +4,13 @@ radio-jammer-component-off-state = off radio-jammer-component-examine-on-state = The light is currently [color=darkgreen]on[/color]. radio-jammer-component-examine-off-state = The light is currently [color=darkred]off[/color]. + +radio-jammer-component-setting-high = High +radio-jammer-component-setting-medium = Medium +radio-jammer-component-setting-low = Low + +radio-jammer-component-set-message-high = The jammer is now operating at high power. +radio-jammer-component-set-message-medium = The jammer is now operating at medium power. +radio-jammer-component-set-message-low = The jammer is now operating at low power. + +radio-jammer-component-switch-setting = The power level switch is set to "[color=yellow]{$powerLevel}[/color]". diff --git a/Resources/Locale/en-US/verbs/verb-system.ftl b/Resources/Locale/en-US/verbs/verb-system.ftl index 2bebddca61..c626e41ce1 100644 --- a/Resources/Locale/en-US/verbs/verb-system.ftl +++ b/Resources/Locale/en-US/verbs/verb-system.ftl @@ -28,6 +28,7 @@ verb-categories-timer = Set Delay verb-categories-lever = Lever verb-categories-select-type = Select Type verb-categories-fax = Set Destination +verb-categories-power-level = Power Level verb-common-toggle-light = Toggle light verb-common-close = Close diff --git a/Resources/Prototypes/Entities/Objects/Tools/jammer.yml b/Resources/Prototypes/Entities/Objects/Tools/jammer.yml index beb3695627..b456a23f1f 100644 --- a/Resources/Prototypes/Entities/Objects/Tools/jammer.yml +++ b/Resources/Prototypes/Entities/Objects/Tools/jammer.yml @@ -6,8 +6,26 @@ components: - type: Sprite sprite: Objects/Devices/jammer.rsi - state: jammer + layers: + - state: jammer + - state: jammer_high_charge + map: ["enum.RadioJammerLayers.LED"] + shader: unshaded + visible: false - type: RadioJammer + settings: + - wattage: 1 + range: 2.5 + message: radio-jammer-component-set-message-low + name: radio-jammer-component-setting-low + - wattage: 2 + range: 6 + message: radio-jammer-component-set-message-medium + name: radio-jammer-component-setting-medium + - wattage: 12 + range: 12 + message: radio-jammer-component-set-message-high + name: radio-jammer-component-setting-high - type: PowerCellSlot cellSlotId: cell_slot - type: ContainerContainer @@ -18,3 +36,15 @@ cell_slot: name: power-cell-slot-component-slot-name-default startingItem: PowerCellMedium + - type: Appearance + - type: GenericVisualizer + visuals: + enum.RadioJammerVisuals.LEDOn: + RadioJammerLayers.LED: + True: { visible: True } + False: { visible: False } + enum.RadioJammerVisuals.ChargeLevel: + RadioJammerLayers.LED: + Low: {state: jammer_low_charge} + Medium: {state: jammer_medium_charge} + High: {state: jammer_high_charge} diff --git a/Resources/Textures/Objects/Devices/jammer.rsi/jammer.png b/Resources/Textures/Objects/Devices/jammer.rsi/jammer.png index 6de27ba924f109e4b6bcf08e517a0ec822575e90..e1db2d05b65b8ea456bd56b17f35d59002099610 100644 GIT binary patch delta 918 zcmV;H18My41FHv+BYy#dX+uL$Nkc;*aB^>EX>4Tx04R}tkv&MmKpe$iQ^g_`2Rn#3 zWT;M7L`8JdDionYs1;guFuC*#nlvOSE{=k0!NHHks)LKOt`4q(Aou~|?BJy6A|?JW zDYS_3;J6>}?mh0_0YbgZG^=9_&~)2OCE{WxyDE0QB8U)x8Gnq*%rfRADGA^4b&mjF z?_xa5|JTxw zGo6|zju4B5Hdfl06-|wJk~perI^_!)k5$fFoV9Y5HSft^7|!V{%Uq{9hy)g~1PLM( zR8c}1He$5uq<>gQ(SF>=Kj8W$aw+60fstbY6=;xMKlmT~?$*jrjC)DpIMDgxI3Ghm z*DlbgInMX7<1|iy;4^TgxBQhlF#Sn-t))eefZlE3;<}|Nd%)!m(Ent}rtC^VnnFGg zyr0oGWr4n1pnJ{ht+|iW2Ov#dC2xR(LtwZ-+3P;<4u7@x_V1Zye?O3)a3o6NxxVLw_vB$HgKTV|bZN008cC8F508kH=#W zLXcSirIgnUBkcON*TVyVPP+|NRWX~-0RYqKH2mj!Fu=hw;5bgia@TbctXAP%;QI)C zf3Gl0Nee5L3U8QZ_= z5PvD^Pg|`-+mPxMsEUHJrlG89kfiPAJ$qi*{lNs7gz!eaj-o81*=*vKF+2`$A}ZFc z79w`ppV|QtLff*!IbnaCi0{Y~hfs9?wpc*db#%L3k%`PGr0IU;d9W=DB8a~xU{~O> sBGo-mDt)~Hwr&5Mq8vGL{5yOCMF5?%sSj!)^8f$<07*qoM6N<$f?9c$mjD0& delta 470 zcmV;{0V)2g2k!%rBYyx1a7bBm000ie000ie0hKEb8vpAR8@)rJF92xgwHvl{N zZX!X?BpI70XxV-kFW{)C5(7r$bP&DDXosQQ>mwy>VU^gL+{!e{8hHN%Fk6vFnIgha~02CWN zO~fF?1t19A0fhr_uW956ilRu`&1N$&B476agrM#HA&CGYfPVw<4UbB;qCIR_?*IS* M07*qoM6N<$f`zNd1ONa4 diff --git a/Resources/Textures/Objects/Devices/jammer.rsi/jammer_high_charge.png b/Resources/Textures/Objects/Devices/jammer.rsi/jammer_high_charge.png new file mode 100644 index 0000000000000000000000000000000000000000..e288427e7175f4e467ff323b90478f0e8e4d8485 GIT binary patch literal 609 zcmV-n0-pVeP)EX>4Tx04R}tkv&MmKpe$iQ^g_`2Rn#3WT;M7L`8JdDionYs1;guFuC*#nlvOS zE{=k0!NHHks)LKOt`4q(Aou~|?BJy6A|?JWDYS_3;J6>}?mh0_0YbgZG^=9_&~)2O zCE{WxyDE0QB8U)x8H~!zGUg;H3E%N`j{slqVm!4LCuVzla{SV+-++{ZuQ`XzEHEX>4Tx04R}tkv&MmKpe$iQ^g_`2Rn#3WT;M7L`8JdDionYs1;guFuC*#nlvOS zE{=k0!NHHks)LKOt`4q(Aou~|?BJy6A|?JWDYS_3;J6>}?mh0_0YbgZG^=9_&~)2O zCE{WxyDE0QB8U)x8H~!zGUg;H3E%N`j{slqVm!4LCuVzla{SV+-++{ZuQ`XzEHEX>4Tx04R}tkv&MmKpe$iQ^g_`2Rn#3WT;M7L`8JdDionYs1;guFuC*#nlvOS zE{=k0!NHHks)LKOt`4q(Aou~|?BJy6A|?JWDYS_3;J6>}?mh0_0YbgZG^=9_&~)2O zCE{WxyDE0QB8U)x8H~!zGUg;H3E%N`j{slqVm!4LCuVzla{SV+-++{ZuQ`XzEH8FWQhbVF}#ZDnqB07G(RVRU6= zAa`kWXdp*PO;A^X4i^9b069rSK~z}7?a?t203ZxQ(Hs_P2LDbvQ~)&)Ja8;<|Ls3Z uBme+jWXmhVH@3z})HRhAJOKaz{;&bN4GGL2ctrmI0000