diff --git a/Content.Server/EnergyDome/EnergyDomeComponent.cs b/Content.Server/EnergyDome/EnergyDomeComponent.cs new file mode 100644 index 0000000000..b1efc631ec --- /dev/null +++ b/Content.Server/EnergyDome/EnergyDomeComponent.cs @@ -0,0 +1,15 @@ +namespace Content.Server.EnergyDome; + +/// +/// marker component that allows linking the dome generator with the dome itself +/// + +[RegisterComponent, Access(typeof(EnergyDomeSystem))] +public sealed partial class EnergyDomeComponent : Component +{ + /// + /// A linked generator that uses energy + /// + [DataField] + public EntityUid? Generator; +} diff --git a/Content.Server/EnergyDome/EnergyDomeGeneratorComponent.cs b/Content.Server/EnergyDome/EnergyDomeGeneratorComponent.cs new file mode 100644 index 0000000000..24189f518f --- /dev/null +++ b/Content.Server/EnergyDome/EnergyDomeGeneratorComponent.cs @@ -0,0 +1,85 @@ +using Content.Shared.DeviceLinking; +using Robust.Shared.Audio; +using Robust.Shared.Prototypes; + +namespace Content.Server.EnergyDome; + +/// +/// component, allows an entity to generate a battery-powered energy dome of a specific type. +/// +[RegisterComponent, Access(typeof(EnergyDomeSystem))] //Access add +public sealed partial class EnergyDomeGeneratorComponent : Component +{ + [DataField] + public bool Enabled = false; + + /// + /// How much energy will be spent from the battery per unit of damage taken by the shield. + /// + [DataField] + public float DamageEnergyDraw = 10f; + + /// + /// Whether or not the dome can be toggled via standard interactions + /// (alt verbs, using in hand, etc) + /// + [DataField] + public bool CanInteractUse = true; + + /// + /// Can the NetworkDevice system activate and deactivate the barrier? + /// + [DataField] + public bool CanDeviceNetworkUse = false; + + //Dome + [DataField, ViewVariables(VVAccess.ReadWrite)] + public EntProtoId DomePrototype = "EnergyDomeSmallRed"; + + [DataField] + public EntityUid? SpawnedDome; + + /// + /// the entity on which the shield will be hung. This is either the container containing + /// the item or the item itself. Determined when the shield is activated, + /// it is stored in the component for changing the protected entity. + /// + [DataField] + public EntityUid? DomeParentEntity; + + //Action + [DataField] + public EntProtoId ToggleAction = "ActionToggleDome"; + + [DataField] + public EntityUid? ToggleActionEntity; + + //Sounds + [DataField] + public SoundSpecifier AccessDeniedSound = new SoundPathSpecifier("/Audio/Machines/custom_deny.ogg"); + + [DataField] + public SoundSpecifier TurnOnSound = new SoundPathSpecifier("/Audio/Machines/anomaly_sync_connect.ogg"); + + [DataField] + public SoundSpecifier EnergyOutSound = new SoundPathSpecifier("/Audio/Machines/energyshield_down.ogg"); + + [DataField] + public SoundSpecifier TurnOffSound = new SoundPathSpecifier("/Audio/Machines/button.ogg"); + + [DataField] + public SoundSpecifier ParrySound = new SoundPathSpecifier("/Audio/Machines/energyshield_parry.ogg") + { + Params = AudioParams.Default.WithVariation(0.05f) + }; + + //Ports + [DataField] + public ProtoId TogglePort = "Toggle"; + + [DataField] + public ProtoId OnPort = "On"; + + [DataField] + public ProtoId OffPort = "Off"; +} diff --git a/Content.Server/EnergyDome/EnergyDomeSystem.cs b/Content.Server/EnergyDome/EnergyDomeSystem.cs new file mode 100644 index 0000000000..72173cfecf --- /dev/null +++ b/Content.Server/EnergyDome/EnergyDomeSystem.cs @@ -0,0 +1,336 @@ +using Content.Server.DeviceLinking.Events; +using Content.Server.DeviceLinking.Systems; +using Content.Server.Power.Components; +using Content.Server.Power.EntitySystems; +using Content.Server.PowerCell; +using Content.Shared.Actions; +using Content.Shared.Damage; +using Content.Shared.Examine; +using Content.Shared.Interaction; +using Content.Shared.Popups; +using Content.Shared.PowerCell; +using Content.Shared.PowerCell.Components; +using Content.Shared.Timing; +using Content.Shared.Toggleable; +using Content.Shared.Verbs; +using Robust.Shared.Audio.Systems; +using Robust.Shared.Containers; + +namespace Content.Server.EnergyDome; + +public sealed partial class EnergyDomeSystem : EntitySystem +{ + [Dependency] private readonly SharedAudioSystem _audio = default!; + [Dependency] private readonly BatterySystem _battery = default!; + [Dependency] private readonly SharedContainerSystem _container = default!; + [Dependency] private readonly UseDelaySystem _useDelay = default!; + [Dependency] private readonly SharedTransformSystem _transform = default!; + [Dependency] private readonly SharedPopupSystem _popup = default!; + [Dependency] private readonly PowerCellSystem _powerCell = default!; + [Dependency] private readonly DeviceLinkSystem _signalSystem = default!; + + public override void Initialize() + { + base.Initialize(); + + //Generator events + SubscribeLocalEvent(OnInit); + + SubscribeLocalEvent(OnActivatedInWorld); + SubscribeLocalEvent(OnAfterInteract); + SubscribeLocalEvent(OnSignalReceived); + SubscribeLocalEvent(OnGetActions); + SubscribeLocalEvent(OnToggleAction); + + SubscribeLocalEvent(OnPowerCellChanged); + SubscribeLocalEvent(OnPowerCellSlotEmpty); + SubscribeLocalEvent(OnChargeChanged); + + SubscribeLocalEvent(OnParentChanged); + + SubscribeLocalEvent>(AddToggleDomeVerb); + SubscribeLocalEvent(OnExamine); + + + SubscribeLocalEvent(OnComponentRemove); + + //Dome events + SubscribeLocalEvent(OnDomeDamaged); + } + + + private void OnInit(Entity generator, ref MapInitEvent args) + { + if (generator.Comp.CanDeviceNetworkUse) + _signalSystem.EnsureSinkPorts(generator, generator.Comp.TogglePort, generator.Comp.OnPort, generator.Comp.OffPort); + } + + //different ways of use + + private void OnSignalReceived(Entity generator, ref SignalReceivedEvent args) + { + if (!generator.Comp.CanDeviceNetworkUse) + return; + + if (args.Port == generator.Comp.OnPort) + { + AttemptToggle(generator, true); + } + if (args.Port == generator.Comp.OffPort) + { + AttemptToggle(generator, false); + } + if (args.Port == generator.Comp.TogglePort) + { + AttemptToggle(generator, !generator.Comp.Enabled); + } + } + + private void OnAfterInteract(Entity generator, ref AfterInteractEvent args) + { + if (generator.Comp.CanInteractUse) + AttemptToggle(generator, !generator.Comp.Enabled); + } + + private void OnActivatedInWorld(Entity generator, ref ActivateInWorldEvent args) + { + if (generator.Comp.CanInteractUse) + AttemptToggle(generator, !generator.Comp.Enabled); + } + + private void OnExamine(Entity generator, ref ExaminedEvent args) + { + args.PushMarkup(Loc.GetString( + (generator.Comp.Enabled) + ? "energy-dome-on-examine-is-on-message" + : "energy-dome-on-examine-is-off-message" + )); + } + + private void AddToggleDomeVerb(Entity generator, ref GetVerbsEvent args) + { + if (!args.CanAccess || !args.CanInteract || !generator.Comp.CanInteractUse) + return; + + var @event = args; + ActivationVerb verb = new() + { + Text = Loc.GetString("energy-dome-verb-toggle"), + Act = () => AttemptToggle(generator, !generator.Comp.Enabled) + }; + + args.Verbs.Add(verb); + } + private void OnGetActions(Entity generator, ref GetItemActionsEvent args) + { + if (generator.Comp.CanInteractUse) + args.AddAction(ref generator.Comp.ToggleActionEntity, generator.Comp.ToggleAction); + } + + private void OnToggleAction(Entity generator, ref ToggleActionEvent args) + { + if (args.Handled) + return; + + AttemptToggle(generator, !generator.Comp.Enabled); + + args.Handled = true; + } + + // System interactions + + private void OnPowerCellSlotEmpty(Entity generator, ref PowerCellSlotEmptyEvent args) + { + TurnOff(generator, true); + } + + private void OnPowerCellChanged(Entity generator, ref PowerCellChangedEvent args) + { + if (args.Ejected || !_powerCell.HasDrawCharge(generator)) + TurnOff(generator, true); + } + + private void OnChargeChanged(Entity generator, ref ChargeChangedEvent args) + { + if (args.Charge == 0) + TurnOff(generator, true); + } + private void OnDomeDamaged(Entity dome, ref DamageChangedEvent args) + { + if (dome.Comp.Generator == null) + return; + + var generatorUid = dome.Comp.Generator.Value; + + if (!TryComp(generatorUid, out var generatorComp)) + return; + + if (args.DamageDelta == null) + return; + + float totalDamage = args.DamageDelta.GetTotal().Float(); + var energyLeak = totalDamage * generatorComp.DamageEnergyDraw; + + _audio.PlayPvs(generatorComp.ParrySound, dome); + + if (HasComp(generatorUid)) + { + _powerCell.TryGetBatteryFromSlot(generatorUid, out var cell); + if (cell != null) + { + _battery.UseCharge(cell.Owner, energyLeak); + + if (cell.CurrentCharge == 0) + TurnOff((generatorUid, generatorComp), true); + } + } + + //it seems to me it would not work well to hang both a powercell and an internal battery with wire charging on the object.... + if (TryComp(generatorUid, out var battery)) { + _battery.UseCharge(generatorUid, energyLeak); + + if (battery.CurrentCharge == 0) + TurnOff((generatorUid, generatorComp), true); + } + } + + private void OnParentChanged(Entity generator, ref EntParentChangedMessage args) + { + //To do: taking the active barrier in hand for some reason does not manage to change the parent in this case, + //and the barrier is not turned off. + // + //Laying down works well (-_-) + if (GetProtectedEntity(generator) != generator.Comp.DomeParentEntity) + TurnOff(generator, false); + } + + private void OnComponentRemove(Entity generator, ref ComponentRemove args) + { + TurnOff(generator, false); + } + + // Functional + + public bool AttemptToggle(Entity generator, bool status) + { + if (TryComp(generator, out var useDelay) && _useDelay.IsDelayed(new Entity(generator, useDelay))) + { + _audio.PlayPvs(generator.Comp.TurnOffSound, generator); + _popup.PopupEntity( + Loc.GetString("energy-dome-recharging"), + generator); + return false; + } + + if (TryComp(generator, out var powerCellSlot)) + { + if (!_powerCell.TryGetBatteryFromSlot(generator, out var cell) && !TryComp(generator, out cell)) + { + _audio.PlayPvs(generator.Comp.TurnOffSound, generator); + _popup.PopupEntity( + Loc.GetString("energy-dome-no-cell"), + generator); + return false; + } + + if (!_powerCell.HasDrawCharge(generator)) + { + _audio.PlayPvs(generator.Comp.TurnOffSound, generator); + _popup.PopupEntity( + Loc.GetString("energy-dome-no-power"), + generator); + return false; + } + } + + if (TryComp(generator, out var battery)) + { + if (battery.CurrentCharge == 0) + { + _audio.PlayPvs(generator.Comp.TurnOffSound, generator); + _popup.PopupEntity( + Loc.GetString("energy-dome-no-power"), + generator); + return false; + } + } + + Toggle(generator, status); + return true; + } + + private void Toggle(Entity generator, bool status) + { + if (status) + TurnOn(generator); + else + TurnOff(generator, false); + } + + private void TurnOn(Entity generator) + { + if (generator.Comp.Enabled) + return; + + var protectedEntity = GetProtectedEntity(generator); + + var newDome = Spawn(generator.Comp.DomePrototype, Transform(protectedEntity).Coordinates); + generator.Comp.DomeParentEntity = protectedEntity; + _transform.SetParent(newDome, protectedEntity); + + if (TryComp(newDome, out var domeComp)) + { + domeComp.Generator = generator; + } + + if (TryComp(generator.Owner, out var powerCellDrawComponent)) + { + _powerCell.SetDrawEnabled(generator.Owner, true); + } + + if (TryComp(generator, out var recharger)) { + recharger.AutoRecharge = true; + } + + generator.Comp.SpawnedDome = newDome; + _audio.PlayPvs(generator.Comp.TurnOnSound, generator); + generator.Comp.Enabled = true; + } + + private void TurnOff(Entity generator, bool startReloading) + { + if (!generator.Comp.Enabled) + return; + + generator.Comp.Enabled = false; + QueueDel(generator.Comp.SpawnedDome); + + if (TryComp(generator.Owner, out var powerCellDrawComponent)) + { + _powerCell.SetDrawEnabled(generator.Owner, false); + } + if (TryComp(generator, out var recharger)) + { + recharger.AutoRecharge = false; + } + + _audio.PlayPvs(generator.Comp.TurnOffSound, generator); + if (startReloading) + { + _audio.PlayPvs(generator.Comp.EnergyOutSound, generator); + if (TryComp(generator, out var useDelay)) + { + _useDelay.TryResetDelay(new Entity(generator, useDelay)); + } + } + } + + // Util + + private EntityUid GetProtectedEntity(EntityUid entity) + { + return (_container.TryGetOuterContainer(entity, Transform(entity), out var container)) + ? container.Owner + : entity; + } +} diff --git a/Content.Server/Power/EntitySystems/BatterySystem.cs b/Content.Server/Power/EntitySystems/BatterySystem.cs index 0a0f2068b5..d1be6fab15 100644 --- a/Content.Server/Power/EntitySystems/BatterySystem.cs +++ b/Content.Server/Power/EntitySystems/BatterySystem.cs @@ -84,8 +84,17 @@ namespace Content.Server.Power.EntitySystems while (query.MoveNext(out var uid, out var comp, out var batt)) { if (!comp.AutoRecharge) continue; - if (batt.IsFullyCharged) continue; - SetCharge(uid, batt.CurrentCharge + comp.AutoRechargeRate * frameTime, batt); + + if (comp.AutoRechargeRate > 0) + { + if (batt.IsFullyCharged) continue; + SetCharge(uid, batt.CurrentCharge + comp.AutoRechargeRate * frameTime, batt); + } + if (comp.AutoRechargeRate < 0) //self discharging + { + if (batt.CurrentCharge == 0) continue; + UseCharge(uid, -comp.AutoRechargeRate * frameTime, batt); + } } } diff --git a/Resources/Audio/Machines/attributions.yml b/Resources/Audio/Machines/attributions.yml index 1ebd2f981e..1be245d7f5 100644 --- a/Resources/Audio/Machines/attributions.yml +++ b/Resources/Audio/Machines/attributions.yml @@ -176,3 +176,23 @@ license: "CC0-1.0" copyright: "by Ko4erga" source: "https://github.com/space-wizards/space-station-14/pull/30431" + +- files: ["energyshield_up.ogg"] + license: "CC0-1.0" + copyright: "unfa on freesound.org" + source: "https://freesound.org/people/unfa/sounds/584173/" + +- files: ["energyshield_down.ogg"] + license: "CC-BY-4.0" + copyright: "SilverIllusionist on freesound.org" + source: "https://freesound.org/people/SilverIllusionist/sounds/673556/" + +- files: ["energyshield_ambient.ogg"] + license: "CC0-1.0" + copyright: "julianmateo_ on freesound.org" + source: "https://freesound.org/people/julianmateo_/sounds/524165/" + +- files: ["energyshield_parry.ogg"] + license: "CC-BY-4.0" + copyright: "Robinhood76 on freesound.org" + source: "https://freesound.org/people/Robinhood76/sounds/107613/" diff --git a/Resources/Audio/Machines/energyshield_ambient.ogg b/Resources/Audio/Machines/energyshield_ambient.ogg new file mode 100644 index 0000000000..ea560a076b Binary files /dev/null and b/Resources/Audio/Machines/energyshield_ambient.ogg differ diff --git a/Resources/Audio/Machines/energyshield_down.ogg b/Resources/Audio/Machines/energyshield_down.ogg new file mode 100644 index 0000000000..a92915ff07 Binary files /dev/null and b/Resources/Audio/Machines/energyshield_down.ogg differ diff --git a/Resources/Audio/Machines/energyshield_parry.ogg b/Resources/Audio/Machines/energyshield_parry.ogg new file mode 100644 index 0000000000..4c5d1517a2 Binary files /dev/null and b/Resources/Audio/Machines/energyshield_parry.ogg differ diff --git a/Resources/Audio/Machines/energyshield_up.ogg b/Resources/Audio/Machines/energyshield_up.ogg new file mode 100644 index 0000000000..9f0121a7b5 Binary files /dev/null and b/Resources/Audio/Machines/energyshield_up.ogg differ diff --git a/Resources/Locale/en-US/_strings/energydome/energydome.ftl b/Resources/Locale/en-US/_strings/energydome/energydome.ftl new file mode 100644 index 0000000000..e9a42503d8 --- /dev/null +++ b/Resources/Locale/en-US/_strings/energydome/energydome.ftl @@ -0,0 +1,9 @@ +energy-dome-access-denied = Access denied +energy-dome-recharging = Recharging... +energy-dome-no-power = Low battery +energy-dome-no-cell = There is no power source + +energy-dome-on-examine-is-on-message = The energy barrier is [color=darkgreen]up[/color]. +energy-dome-on-examine-is-off-message = The energy barrier is [color=darkred]down[/color]. + +energy-dome-verb-toggle = Toggle energy dome \ No newline at end of file diff --git a/Resources/Locale/en-US/_strings/research/technologies.ftl b/Resources/Locale/en-US/_strings/research/technologies.ftl index 9f5891213d..c8aac6abfe 100644 --- a/Resources/Locale/en-US/_strings/research/technologies.ftl +++ b/Resources/Locale/en-US/_strings/research/technologies.ftl @@ -35,6 +35,7 @@ research-technology-wave-particle-harnessing = Wave Particle Harnessing research-technology-advanced-riot-control = Advanced Riot Control research-technology-portable-microfusion-weaponry = Portable Microfusion Weaponry research-technology-experimental-battery-ammo = Experimental Battery Ammo +research-technology-energy_barriers = Energy Barriers research-technology-basic-shuttle-armament = Shuttle basic armament research-technology-advanced-shuttle-weapon = Advanced shuttle weapons research-technology-energy-gun = Energy weaponry diff --git a/Resources/Locale/en-US/_strings/store/uplink-catalog.ftl b/Resources/Locale/en-US/_strings/store/uplink-catalog.ftl index 7e0ea30413..7fc3ffe35b 100644 --- a/Resources/Locale/en-US/_strings/store/uplink-catalog.ftl +++ b/Resources/Locale/en-US/_strings/store/uplink-catalog.ftl @@ -330,6 +330,9 @@ uplink-hardsuit-syndieelite-desc = An elite version of the blood-red hardsuit, w uplink-clothing-outer-hardsuit-juggernaut-name = Cybersun Juggernaut Suit uplink-clothing-outer-hardsuit-juggernaut-desc = Hyper resilient armor made of materials tested in the Tau chromosphere facility. The only thing that's going to be slowing you down is this suit... and tasers. +uplink-energy-dome-name = Personal energy dome +uplink-energy-dome-desc = A personal shield generator that protects the wearer from lasers and bullets but prevents from using ranged weapons himself. Comes with a small power cell. + # Misc uplink-cyberpen-name = Cybersun Pen uplink-cyberpen-desc = Cybersun's legal department pen, invaluable for forging documents and escaping prisons. Smells vaguely of hard-light and war profiteering. diff --git a/Resources/Locale/ru-RU/_prototypes/entities/objects/tools/energydome.ftl b/Resources/Locale/ru-RU/_prototypes/entities/objects/tools/energydome.ftl new file mode 100644 index 0000000000..83a3538faf --- /dev/null +++ b/Resources/Locale/ru-RU/_prototypes/entities/objects/tools/energydome.ftl @@ -0,0 +1,4 @@ +ent-EnergyDomeGeneratorPersonalSyndie = Кроваво-красный генератор барьера + .desc = Генератор щита, защищающий владельца от лазеров и пуль, но не позволяющий самому использовать оружие дальнего боя. Использует батареи. +ent-EnergyDomeDirectionalTurtle = BR-40c "Черепаха" + .desc = Двуручный тяжелый энергетический барьер с чрезвычайно низким пассивным потреблением энергии. Можно подключить с помощью мультитула. \ No newline at end of file diff --git a/Resources/Locale/ru-RU/_strings/energydome/energydome.ftl b/Resources/Locale/ru-RU/_strings/energydome/energydome.ftl new file mode 100644 index 0000000000..8b1989da83 --- /dev/null +++ b/Resources/Locale/ru-RU/_strings/energydome/energydome.ftl @@ -0,0 +1,9 @@ +energy-dome-access-denied = Недостаточный доступ +energy-dome-recharging = Перезарядка... +energy-dome-no-power = Низкий уровень заряда +energy-dome-no-cell = Требуется батарея + +energy-dome-on-examine-is-on-message = Энергетический барьер [color=darkgreen]поднят[/color]. +energy-dome-on-examine-is-off-message = Энергетический барьер [color=darkred]выключен[/color]. + +energy-dome-verb-toggle = Включить энергетический барьер \ No newline at end of file diff --git a/Resources/Locale/ru-RU/_strings/research/technologies.ftl b/Resources/Locale/ru-RU/_strings/research/technologies.ftl index d102cc6743..6c3b983286 100644 --- a/Resources/Locale/ru-RU/_strings/research/technologies.ftl +++ b/Resources/Locale/ru-RU/_strings/research/technologies.ftl @@ -36,6 +36,7 @@ research-technology-wave-particle-harnessing = Применение волнов research-technology-advanced-riot-control = Продвинутое противодействие беспорядкам research-technology-portable-microfusion-weaponry = Оруженый портативный микросинтез research-technology-experimental-battery-ammo = Экспериментальные батарейные боеприпасы +research-technology-energy_barriers = Энергетические барьеры research-technology-basic-shuttle-armament = Базовое корабельное вооружение research-technology-advanced-shuttle-weapon = Продвинутое корабельное оружие research-technology-basic-robotics = Основы робототехники diff --git a/Resources/Locale/ru-RU/_strings/store/uplink-catalog.ftl b/Resources/Locale/ru-RU/_strings/store/uplink-catalog.ftl index cf4d634a95..17bed0f05d 100644 --- a/Resources/Locale/ru-RU/_strings/store/uplink-catalog.ftl +++ b/Resources/Locale/ru-RU/_strings/store/uplink-catalog.ftl @@ -228,6 +228,8 @@ uplink-hardsuit-syndieelite-name = Элитный скафандр Синдик uplink-hardsuit-syndieelite-desc = Элитная версия кроваво-красного скафандра, отличающаяся повышенной мобильностью и огнеупорностью. Собственность Мародёров Горлекса. uplink-clothing-outer-hardsuit-juggernaut-name = Скафандр джаггернаута Cybersun uplink-clothing-outer-hardsuit-juggernaut-desc = Сверхпрочная броня из материалов, испытанных в хромосферном комплексе Тау. Единственное, что сможет вас задержать - этот костюм... и тазеры. +uplink-energy-dome-name = Энергетический барьер +uplink-energy-dome-desc = Генератор щита, защищающий владельца от лазеров и пуль, но не позволяющий самому использовать оружие дальнего боя. Использует батареи. uplink-cyberpen-name = Ручка Cybersun uplink-cyberpen-desc = Ручка юридического отдела Cybersun, бесценная при необходимости подделать документы и сбежать из тюрьмы. Смутно пахнет хардлайтом и спекуляциями на войне. uplink-decoy-disk-name = Фальшивый диск ядерной авторизации diff --git a/Resources/Prototypes/Actions/types.yml b/Resources/Prototypes/Actions/types.yml index 5430a3f005..afd1031b52 100644 --- a/Resources/Prototypes/Actions/types.yml +++ b/Resources/Prototypes/Actions/types.yml @@ -42,6 +42,15 @@ iconOn: { sprite: Objects/Tools/flashlight.rsi, state: flashlight-on } event: !type:ToggleActionEvent +- type: entity + id: ActionToggleDome + name: Toggle energy dome + description: Turn the energy barrier on or off. + components: + - type: InstantAction + icon: { sprite: Objects/Weapons/Melee/e_shield.rsi, state: eshield-on } + event: !type:ToggleActionEvent + - type: entity id: ActionOpenStorageImplant name: Toggle Storage Implant diff --git a/Resources/Prototypes/Catalog/uplink_catalog.yml b/Resources/Prototypes/Catalog/uplink_catalog.yml index e7e75450df..ebb8e39d17 100644 --- a/Resources/Prototypes/Catalog/uplink_catalog.yml +++ b/Resources/Prototypes/Catalog/uplink_catalog.yml @@ -1577,6 +1577,21 @@ categories: - UplinkWearables +- type: listing + id: UplinkEnergyDomeSyndie + name: uplink-energy-dome-name + description: uplink-energy-dome-desc + productEntity: EnergyDomeGeneratorPersonalSyndie + cost: + Telecrystal: 10 + categories: + - UplinkWearables + conditions: + - !type:StoreWhitelistCondition + whitelist: + tags: + - NukeOpsUplink + - type: listing id: UplinkClothingEyesHudSyndicate name: uplink-clothing-eyes-hud-syndicate-name diff --git a/Resources/Prototypes/Damage/modifier_sets.yml b/Resources/Prototypes/Damage/modifier_sets.yml index 6f07a16e80..10034d3d30 100644 --- a/Resources/Prototypes/Damage/modifier_sets.yml +++ b/Resources/Prototypes/Damage/modifier_sets.yml @@ -175,6 +175,16 @@ flatReductions: Heat: 3 +- type: damageModifierSet + id: HardLightBarrier + coefficients: + Heat: 0.8 + Blunt: 0.8 + Slash: 0.8 + Piercing: 0.8 + Cold: 0.8 + Shock: 1.6 + - type: damageModifierSet id: Scale # Skin tougher, bones weaker, strong stomachs, cold-blooded (kindof) coefficients: diff --git a/Resources/Prototypes/Entities/Clothing/OuterClothing/hardsuits.yml b/Resources/Prototypes/Entities/Clothing/OuterClothing/hardsuits.yml index 5db4944600..64107049a7 100644 --- a/Resources/Prototypes/Entities/Clothing/OuterClothing/hardsuits.yml +++ b/Resources/Prototypes/Entities/Clothing/OuterClothing/hardsuits.yml @@ -162,7 +162,7 @@ parent: [ClothingOuterHardsuitBase, BaseCargoContraband] id: ClothingOuterHardsuitMaxim name: salvager maxim hardsuit - description: Fire. Heat. These things forge great weapons, they also forge great salvagers. + description: Fire. Heat. These things forge great weapons, they also forge great salvagers. Has built-in battery-powered energy barrier technology. components: - type: Sprite sprite: Clothing/OuterClothing/Hardsuits/maxim.rsi @@ -177,9 +177,9 @@ - type: Armor modifiers: coefficients: - Blunt: 0.6 - Slash: 0.6 - Piercing: 0.5 + Blunt: 0.7 + Slash: 0.7 + Piercing: 0.6 Heat: 0.3 Radiation: 0.1 - type: ExplosionResistance @@ -188,7 +188,30 @@ heatingCoefficient: 0.001 coolingCoefficient: 0.001 - type: ToggleableClothing - clothingPrototype: ClothingHeadHelmetHardsuitMaxim + clothingPrototype: ClothingHeadHelmetHardsuitMaxim + - type: ContainerContainer + containers: + cell_slot: !type:ContainerSlot + toggleable-clothing: !type:ContainerSlot + - type: PowerCellSlot + cellSlotId: cell_slot + - type: ItemSlots + slots: + cell_slot: + name: power-cell-slot-component-slot-name-default + startingItem: PowerCellSmall + whitelist: + tags: + - PowerCell + - PowerCellSmall + - type: EnergyDomeGenerator + damageEnergyDraw: 6 + domePrototype: EnergyDomeSmallPink + - type: PowerCellDraw + drawRate: 8 + useRate: 0 + - type: UseDelay + delay: 10.0 #Security Hardsuit - type: entity diff --git a/Resources/Prototypes/Entities/Effects/dome.yml b/Resources/Prototypes/Entities/Effects/dome.yml new file mode 100644 index 0000000000..21b3bd9744 --- /dev/null +++ b/Resources/Prototypes/Entities/Effects/dome.yml @@ -0,0 +1,129 @@ +- type: entity + id: EnergyDomeBase + abstract: true + components: + - type: Sprite + drawdepth: Effects + noRot: true + - type: Fixtures + fixtures: + fix1: + shape: + !type:PhysShapeCircle + radius: 0.8 + density: 0 + mask: + - None + layer: + - BulletImpassable + - Opaque + - type: Physics + bodyType: Static + - type: Damageable + damageContainer: Inorganic + damageModifierSet: HardLightBarrier + - type: AmbientSound + volume: 35 + range: 5 + sound: + path: /Audio/Machines/energyshield_ambient.ogg + - type: EnergyDome + - type: Tag + tags: + - HideContextMenu + +- type: entity + id: EnergyDomeSmallPink + categories: [ HideSpawnMenu ] + parent: EnergyDomeBase + components: + - type: Sprite + sprite: Effects/EnergyDome/energydome_small.rsi + layers: + - state: small + color: "#f5166b" + - type: PointLight + enabled: true + radius: 5 + power: 2 + color: "#f5166b" + +- type: entity + id: EnergyDomeSmallRed + categories: [ HideSpawnMenu ] + parent: EnergyDomeBase + components: + - type: Sprite + drawdepth: Effects + noRot: true + sprite: Effects/EnergyDome/energydome_small.rsi + layers: + - state: small + color: "#b00000" + - type: PointLight + enabled: true + radius: 5 + power: 2 + color: "#b00000" + +- type: entity + id: EnergyDomeMediumBlue + categories: [ HideSpawnMenu ] + parent: EnergyDomeBase + components: + - type: Fixtures + fixtures: + fix1: + shape: + !type:PhysShapeCircle + radius: 1.8 + density: 0 + mask: + - None + layer: + - BulletImpassable + - Opaque + - type: Sprite + sprite: Effects/EnergyDome/energydome_medium.rsi + layers: + - state: medium + color: "#64b9de" + - type: PointLight + enabled: true + radius: 5 + power: 10 + color: "#64b9de" + +- type: entity + id: EnergyDomeSlowing + categories: [ HideSpawnMenu ] + parent: EnergyDomeBase + components: + - type: Fixtures + fixtures: + fix1: + shape: + !type:PhysShapeCircle + radius: 2.8 + density: 0 + hard: false + mask: + - None + layer: + - MidImpassable + - type: Sprite + drawdepth: LowFloors + sprite: Effects/EnergyDome/energydome_slowdown_big.rsi + layers: + - state: big + color: "#a3d177" + - type: PointLight + enabled: true + radius: 5 + power: 30 + color: "#a3d177" + - type: DamageContacts + damage: + types: + Slash: -1.5 + Piercing: -1.5 \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Objects/Tools/energydome.yml b/Resources/Prototypes/Entities/Objects/Tools/energydome.yml new file mode 100644 index 0000000000..f194edac4b --- /dev/null +++ b/Resources/Prototypes/Entities/Objects/Tools/energydome.yml @@ -0,0 +1,179 @@ +- type: entity + name: blood red personal shield generator + description: A personal shield generator that protects the wearer from lasers and bullets but prevents from using ranged weapons himself. Uses a power cell. + id: EnergyDomeGeneratorPersonalSyndie + parent: BaseItem + components: + - type: Item + size: Ginormous + - type: Clothing + quickEquip: false + slots: + - Belt + - type: Sprite + sprite: Objects/Tools/EnergyDome/syndie.rsi + layers: + - state: icon + - type: ContainerContainer + containers: + cell_slot: !type:ContainerSlot + - type: PowerCellSlot + cellSlotId: cell_slot + - type: ItemSlots + slots: + cell_slot: + name: power-cell-slot-component-slot-name-default + startingItem: PowerCellSmall + whitelist: + tags: + - PowerCell + - PowerCellSmall + - type: EnergyDomeGenerator + damageEnergyDraw: 3 + domePrototype: EnergyDomeSmallRed + - type: PowerCellDraw + drawRate: 5 + useRate: 0 + - type: UseDelay + delay: 10.0 + +- type: entity + name: BR-40c "Turtle" + description: A two-handed and heavy energy barrier with extremely low passive energy consumption. Can be tethered with a multitool. + id: EnergyDomeDirectionalTurtle + parent: BaseItem + components: + - type: Sprite + sprite: Objects/Tools/EnergyDome/reinhardt.rsi + layers: + - state: icon + - type: InteractionOutline + - type: MultiHandedItem + - type: Fixtures + fixtures: + fix1: + shape: + !type:PhysShapeAabb + bounds: "-0.25,-0.25,0.25,0.25" + density: 20 + mask: + - ItemMask + restitution: 0.3 + friction: 0.2 + - type: Item + size: Ginormous + - type: HeldSpeedModifier + walkModifier: 0.7 + sprintModifier: 0.7 + - type: ContainerContainer + containers: + cell_slot: !type:ContainerSlot + - type: PowerCellSlot + cellSlotId: cell_slot + - type: ItemSlots + slots: + cell_slot: + name: power-cell-slot-component-slot-name-default + startingItem: PowerCellSmall + whitelist: + tags: + - PowerCell + - PowerCellSmall + - type: EnergyDomeGenerator + damageEnergyDraw: 3 + domePrototype: EnergyDomeMediumBlue + canDeviceNetworkUse: true + - type: PowerCellDraw + drawRate: 2 + useRate: 0 + - type: UseDelay + delay: 10.0 + - type: DeviceNetwork + deviceNetId: Wireless + receiveFrequencyId: BasicDevice + - type: WirelessNetworkConnection + range: 200 + - type: DeviceLinkSink + ports: + - Toggle + - On + - Off + +- type: entity + id: EnergyDomeWiredTest + name: Static Dome + description: Test energy barrier powered by station wiring. I don't know how the hell to balance it..... + parent: BaseMachine + suffix: DO NOT MERGE + placement: + mode: SnapgridCenter + components: + - type: Transform + anchored: true + - type: Physics + bodyType: Static + - type: Fixtures + fixtures: + fix1: + shape: + !type:PhysShapeAabb + bounds: "-0.45,-0.45,0.45,0.45" + density: 190 + mask: + - MachineMask + layer: + - MachineLayer + - type: Sprite + sprite: Structures/Power/Generation/Tesla/coil.rsi + snapCardinals: true + noRot: true + layers: + - state: coil + - type: ExaminableBattery + - type: Battery + maxCharge: 30000 #<- max supply + startingCharge: 10000 + - type: PowerNetworkBattery + maxSupply: 30000 + maxChargeRate: 1000 #<- passive charging frow power net + supplyRampTolerance: 500 + supplyRampRate: 50 + - type: BatteryCharger + voltage: Medium + - type: NodeContainer + examinable: true + nodes: + input: + !type:CableDeviceNode + nodeGroupID: MVPower + - type: BatterySelfRecharger + autoRecharge: false # true only when active + autoRechargeRate: -800 #<- discharge per second while active + - type: Damageable + damageContainer: Inorganic + damageModifierSet: Metallic + - type: Destructible + thresholds: + - trigger: + !type:DamageTrigger + damage: 200 + behaviors: + - !type:DoActsBehavior + acts: [ "Destruction" ] + - type: UseDelay + delay: 30.0 + - type: DeviceNetwork + deviceNetId: Wireless + receiveFrequencyId: BasicDevice + - type: WirelessNetworkConnection + range: 200 + - type: DeviceLinkSink + ports: + - Toggle + - On + - Off + - type: EnergyDomeGenerator + enabled: true + damageEnergyDraw: 100 + domePrototype: EnergyDomeSlowing + canDeviceNetworkUse: true \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml index 533003fba7..f611e9612c 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml @@ -358,6 +358,7 @@ - FauxTileAstroSnow - OreBagOfHolding - DeviceQuantumSpinInverter + - EnergyDomeDirectionalTurtle - type: EmagLatheRecipes emagDynamicRecipes: # Sunrise-Start diff --git a/Resources/Prototypes/Recipes/Lathes/security.yml b/Resources/Prototypes/Recipes/Lathes/security.yml index 29227fb9db..50f0b794de 100644 --- a/Resources/Prototypes/Recipes/Lathes/security.yml +++ b/Resources/Prototypes/Recipes/Lathes/security.yml @@ -622,6 +622,16 @@ Glass: 500 Plastic: 500 +- type: latheRecipe + id: EnergyDomeDirectionalTurtle + result: EnergyDomeDirectionalTurtle + completetime: 12 + materials: + Steel: 1000 + Plastic: 500 + Gold: 250 + Uranium: 50 + - type: latheRecipe id: MagazineGrenadeEmpty result: MagazineGrenadeEmpty diff --git a/Resources/Prototypes/Research/arsenal.yml b/Resources/Prototypes/Research/arsenal.yml index 7d5f523ac8..2bb221a0ac 100644 --- a/Resources/Prototypes/Research/arsenal.yml +++ b/Resources/Prototypes/Research/arsenal.yml @@ -163,6 +163,18 @@ recipeUnlocks: - WeaponXrayCannon +- type: technology + id: EnergyBarriers + name: research-technology-energy_barriers + icon: + sprite: Objects/Tools/EnergyDome/reinhardt.rsi + state: icon + discipline: Arsenal + tier: 2 + cost: 6000 + recipeUnlocks: + - EnergyDomeDirectionalTurtle + - type: technology id: BasicShuttleArmament name: research-technology-basic-shuttle-armament diff --git a/Resources/Textures/Effects/EnergyDome/energydome_big.rsi/big.png b/Resources/Textures/Effects/EnergyDome/energydome_big.rsi/big.png new file mode 100644 index 0000000000..eb8e2a5bf5 Binary files /dev/null and b/Resources/Textures/Effects/EnergyDome/energydome_big.rsi/big.png differ diff --git a/Resources/Textures/Effects/EnergyDome/energydome_big.rsi/meta.json b/Resources/Textures/Effects/EnergyDome/energydome_big.rsi/meta.json new file mode 100644 index 0000000000..a8ac036154 --- /dev/null +++ b/Resources/Textures/Effects/EnergyDome/energydome_big.rsi/meta.json @@ -0,0 +1,26 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Created by TheShuEd (github) for Space Station 14", + "size": { + "x": 192, + "y": 192 + }, + "states": [ + { + "name": "big", + "delays": [ + [ + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2 + ] + ] + } + ] +} diff --git a/Resources/Textures/Effects/EnergyDome/energydome_directed.rsi/meta.json b/Resources/Textures/Effects/EnergyDome/energydome_directed.rsi/meta.json new file mode 100644 index 0000000000..7097ca861e --- /dev/null +++ b/Resources/Textures/Effects/EnergyDome/energydome_directed.rsi/meta.json @@ -0,0 +1,26 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Created by TheShuEd (github) for Space Station 14", + "size": { + "x": 96, + "y": 64 + }, + "states": [ + { + "name": "small", + "delays": [ + [ + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2 + ] + ] + } + ] +} diff --git a/Resources/Textures/Effects/EnergyDome/energydome_directed.rsi/small.png b/Resources/Textures/Effects/EnergyDome/energydome_directed.rsi/small.png new file mode 100644 index 0000000000..cabd6d68cc Binary files /dev/null and b/Resources/Textures/Effects/EnergyDome/energydome_directed.rsi/small.png differ diff --git a/Resources/Textures/Effects/EnergyDome/energydome_medium.rsi/medium.png b/Resources/Textures/Effects/EnergyDome/energydome_medium.rsi/medium.png new file mode 100644 index 0000000000..823012cea3 Binary files /dev/null and b/Resources/Textures/Effects/EnergyDome/energydome_medium.rsi/medium.png differ diff --git a/Resources/Textures/Effects/EnergyDome/energydome_medium.rsi/meta.json b/Resources/Textures/Effects/EnergyDome/energydome_medium.rsi/meta.json new file mode 100644 index 0000000000..fc29522c65 --- /dev/null +++ b/Resources/Textures/Effects/EnergyDome/energydome_medium.rsi/meta.json @@ -0,0 +1,26 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Created by TheShuEd (github) for Space Station 14", + "size": { + "x": 128, + "y": 128 + }, + "states": [ + { + "name": "medium", + "delays": [ + [ + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2 + ] + ] + } + ] +} diff --git a/Resources/Textures/Effects/EnergyDome/energydome_slowdown_big.rsi/big.png b/Resources/Textures/Effects/EnergyDome/energydome_slowdown_big.rsi/big.png new file mode 100644 index 0000000000..9e403c300a Binary files /dev/null and b/Resources/Textures/Effects/EnergyDome/energydome_slowdown_big.rsi/big.png differ diff --git a/Resources/Textures/Effects/EnergyDome/energydome_slowdown_big.rsi/meta.json b/Resources/Textures/Effects/EnergyDome/energydome_slowdown_big.rsi/meta.json new file mode 100644 index 0000000000..a8ac036154 --- /dev/null +++ b/Resources/Textures/Effects/EnergyDome/energydome_slowdown_big.rsi/meta.json @@ -0,0 +1,26 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Created by TheShuEd (github) for Space Station 14", + "size": { + "x": 192, + "y": 192 + }, + "states": [ + { + "name": "big", + "delays": [ + [ + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2 + ] + ] + } + ] +} diff --git a/Resources/Textures/Effects/EnergyDome/energydome_small.rsi/meta.json b/Resources/Textures/Effects/EnergyDome/energydome_small.rsi/meta.json new file mode 100644 index 0000000000..c0c836ef1e --- /dev/null +++ b/Resources/Textures/Effects/EnergyDome/energydome_small.rsi/meta.json @@ -0,0 +1,27 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Created by TheShuEd (github) for Space Station 14", + "size": { + "x": 64, + "y": 64 + }, + "states": [ + { + "name": "small", + "delays": [ + [ + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2 + ] + ] + } + ] +} diff --git a/Resources/Textures/Effects/EnergyDome/energydome_small.rsi/small.png b/Resources/Textures/Effects/EnergyDome/energydome_small.rsi/small.png new file mode 100644 index 0000000000..96cfa6029d Binary files /dev/null and b/Resources/Textures/Effects/EnergyDome/energydome_small.rsi/small.png differ diff --git a/Resources/Textures/Objects/Tools/EnergyDome/reinhardt.rsi/icon.png b/Resources/Textures/Objects/Tools/EnergyDome/reinhardt.rsi/icon.png new file mode 100644 index 0000000000..24e7549af4 Binary files /dev/null and b/Resources/Textures/Objects/Tools/EnergyDome/reinhardt.rsi/icon.png differ diff --git a/Resources/Textures/Objects/Tools/EnergyDome/reinhardt.rsi/inhand-left.png b/Resources/Textures/Objects/Tools/EnergyDome/reinhardt.rsi/inhand-left.png new file mode 100644 index 0000000000..9a8a439994 Binary files /dev/null and b/Resources/Textures/Objects/Tools/EnergyDome/reinhardt.rsi/inhand-left.png differ diff --git a/Resources/Textures/Objects/Tools/EnergyDome/reinhardt.rsi/inhand-right.png b/Resources/Textures/Objects/Tools/EnergyDome/reinhardt.rsi/inhand-right.png new file mode 100644 index 0000000000..9a8a439994 Binary files /dev/null and b/Resources/Textures/Objects/Tools/EnergyDome/reinhardt.rsi/inhand-right.png differ diff --git a/Resources/Textures/Objects/Tools/EnergyDome/reinhardt.rsi/meta.json b/Resources/Textures/Objects/Tools/EnergyDome/reinhardt.rsi/meta.json new file mode 100644 index 0000000000..cc4ea1dab9 --- /dev/null +++ b/Resources/Textures/Objects/Tools/EnergyDome/reinhardt.rsi/meta.json @@ -0,0 +1,22 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Created by TheShuEd (github) for Space Station 14", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon" + }, + { + "name": "inhand-left", + "directions": 4 + }, + { + "name": "inhand-right", + "directions": 4 + } + ] +} diff --git a/Resources/Textures/Objects/Tools/EnergyDome/syndie.rsi/equipped-BELT.png b/Resources/Textures/Objects/Tools/EnergyDome/syndie.rsi/equipped-BELT.png new file mode 100644 index 0000000000..5df8249cd2 Binary files /dev/null and b/Resources/Textures/Objects/Tools/EnergyDome/syndie.rsi/equipped-BELT.png differ diff --git a/Resources/Textures/Objects/Tools/EnergyDome/syndie.rsi/icon.png b/Resources/Textures/Objects/Tools/EnergyDome/syndie.rsi/icon.png new file mode 100644 index 0000000000..4824044f0b Binary files /dev/null and b/Resources/Textures/Objects/Tools/EnergyDome/syndie.rsi/icon.png differ diff --git a/Resources/Textures/Objects/Tools/EnergyDome/syndie.rsi/inhand-left.png b/Resources/Textures/Objects/Tools/EnergyDome/syndie.rsi/inhand-left.png new file mode 100644 index 0000000000..74dbff9699 Binary files /dev/null and b/Resources/Textures/Objects/Tools/EnergyDome/syndie.rsi/inhand-left.png differ diff --git a/Resources/Textures/Objects/Tools/EnergyDome/syndie.rsi/inhand-right.png b/Resources/Textures/Objects/Tools/EnergyDome/syndie.rsi/inhand-right.png new file mode 100644 index 0000000000..8dda54bcc0 Binary files /dev/null and b/Resources/Textures/Objects/Tools/EnergyDome/syndie.rsi/inhand-right.png differ diff --git a/Resources/Textures/Objects/Tools/EnergyDome/syndie.rsi/meta.json b/Resources/Textures/Objects/Tools/EnergyDome/syndie.rsi/meta.json new file mode 100644 index 0000000000..52a03b1a90 --- /dev/null +++ b/Resources/Textures/Objects/Tools/EnergyDome/syndie.rsi/meta.json @@ -0,0 +1,26 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Created by TheShuEd (github) for Space Station 14", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon" + }, + { + "name": "equipped-BELT", + "directions": 4 + }, + { + "name": "inhand-left", + "directions": 4 + }, + { + "name": "inhand-right", + "directions": 4 + } + ] +}