Энергетические щиты (#404)

* setup codebase

* add content

* cococontent!

* i try to understand git, and fix merge conflict.

* clean up

* fix attribution

* wtf?

* reuse PowerCellDraw

* reuse UseDelay

* minor clean up

* fix ugly hack

* change bad sound license

* integrate devicenetwork system, some fixes

* add medium-size circle barrier

* deltanedas 3/4 fix

* check fixes

* check fix 2

* remove HoS barrier, add CE barrier. sorted some function

* increase craft cost turtle, remove CE barrier, add Maxim barrier, move syndie barrier to Nuke uplink only

* Shitcode update! Add support to wire network energy shield

* some clean up + BIG dome sprite

* just checking slowdown field

* translate

* refactoring to current ver

* Я даун

* buff energy shields

* fix linter

---------

Co-authored-by: Ed <edwardxperia2000@gmail.com>
Co-authored-by: Ed <96445749+TheShuEd@users.noreply.github.com>
This commit is contained in:
Rinary 2024-09-26 20:09:00 +03:00 committed by GitHub
parent b96ec59f04
commit c826b076bb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
44 changed files with 1068 additions and 7 deletions

View file

@ -0,0 +1,15 @@
namespace Content.Server.EnergyDome;
/// <summary>
/// marker component that allows linking the dome generator with the dome itself
/// </summary>
[RegisterComponent, Access(typeof(EnergyDomeSystem))]
public sealed partial class EnergyDomeComponent : Component
{
/// <summary>
/// A linked generator that uses energy
/// </summary>
[DataField]
public EntityUid? Generator;
}

View file

@ -0,0 +1,85 @@
using Content.Shared.DeviceLinking;
using Robust.Shared.Audio;
using Robust.Shared.Prototypes;
namespace Content.Server.EnergyDome;
/// <summary>
/// component, allows an entity to generate a battery-powered energy dome of a specific type.
/// </summary>
[RegisterComponent, Access(typeof(EnergyDomeSystem))] //Access add
public sealed partial class EnergyDomeGeneratorComponent : Component
{
[DataField]
public bool Enabled = false;
/// <summary>
/// How much energy will be spent from the battery per unit of damage taken by the shield.
/// </summary>
[DataField]
public float DamageEnergyDraw = 10f;
/// <summary>
/// Whether or not the dome can be toggled via standard interactions
/// (alt verbs, using in hand, etc)
/// </summary>
[DataField]
public bool CanInteractUse = true;
/// <summary>
/// Can the NetworkDevice system activate and deactivate the barrier?
/// </summary>
[DataField]
public bool CanDeviceNetworkUse = false;
//Dome
[DataField, ViewVariables(VVAccess.ReadWrite)]
public EntProtoId DomePrototype = "EnergyDomeSmallRed";
[DataField]
public EntityUid? SpawnedDome;
/// <summary>
/// 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.
/// </summary>
[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<SinkPortPrototype> TogglePort = "Toggle";
[DataField]
public ProtoId<SinkPortPrototype> OnPort = "On";
[DataField]
public ProtoId<SinkPortPrototype> OffPort = "Off";
}

View file

@ -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<EnergyDomeGeneratorComponent, MapInitEvent>(OnInit);
SubscribeLocalEvent<EnergyDomeGeneratorComponent, ActivateInWorldEvent>(OnActivatedInWorld);
SubscribeLocalEvent<EnergyDomeGeneratorComponent, AfterInteractEvent>(OnAfterInteract);
SubscribeLocalEvent<EnergyDomeGeneratorComponent, SignalReceivedEvent>(OnSignalReceived);
SubscribeLocalEvent<EnergyDomeGeneratorComponent, GetItemActionsEvent>(OnGetActions);
SubscribeLocalEvent<EnergyDomeGeneratorComponent, ToggleActionEvent>(OnToggleAction);
SubscribeLocalEvent<EnergyDomeGeneratorComponent, PowerCellChangedEvent>(OnPowerCellChanged);
SubscribeLocalEvent<EnergyDomeGeneratorComponent, PowerCellSlotEmptyEvent>(OnPowerCellSlotEmpty);
SubscribeLocalEvent<EnergyDomeGeneratorComponent, ChargeChangedEvent>(OnChargeChanged);
SubscribeLocalEvent<EnergyDomeGeneratorComponent, EntParentChangedMessage>(OnParentChanged);
SubscribeLocalEvent<EnergyDomeGeneratorComponent, GetVerbsEvent<ActivationVerb>>(AddToggleDomeVerb);
SubscribeLocalEvent<EnergyDomeGeneratorComponent, ExaminedEvent>(OnExamine);
SubscribeLocalEvent<EnergyDomeGeneratorComponent, ComponentRemove>(OnComponentRemove);
//Dome events
SubscribeLocalEvent<EnergyDomeComponent, DamageChangedEvent>(OnDomeDamaged);
}
private void OnInit(Entity<EnergyDomeGeneratorComponent> 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<EnergyDomeGeneratorComponent> 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<EnergyDomeGeneratorComponent> generator, ref AfterInteractEvent args)
{
if (generator.Comp.CanInteractUse)
AttemptToggle(generator, !generator.Comp.Enabled);
}
private void OnActivatedInWorld(Entity<EnergyDomeGeneratorComponent> generator, ref ActivateInWorldEvent args)
{
if (generator.Comp.CanInteractUse)
AttemptToggle(generator, !generator.Comp.Enabled);
}
private void OnExamine(Entity<EnergyDomeGeneratorComponent> 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<EnergyDomeGeneratorComponent> generator, ref GetVerbsEvent<ActivationVerb> 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<EnergyDomeGeneratorComponent> generator, ref GetItemActionsEvent args)
{
if (generator.Comp.CanInteractUse)
args.AddAction(ref generator.Comp.ToggleActionEntity, generator.Comp.ToggleAction);
}
private void OnToggleAction(Entity<EnergyDomeGeneratorComponent> generator, ref ToggleActionEvent args)
{
if (args.Handled)
return;
AttemptToggle(generator, !generator.Comp.Enabled);
args.Handled = true;
}
// System interactions
private void OnPowerCellSlotEmpty(Entity<EnergyDomeGeneratorComponent> generator, ref PowerCellSlotEmptyEvent args)
{
TurnOff(generator, true);
}
private void OnPowerCellChanged(Entity<EnergyDomeGeneratorComponent> generator, ref PowerCellChangedEvent args)
{
if (args.Ejected || !_powerCell.HasDrawCharge(generator))
TurnOff(generator, true);
}
private void OnChargeChanged(Entity<EnergyDomeGeneratorComponent> generator, ref ChargeChangedEvent args)
{
if (args.Charge == 0)
TurnOff(generator, true);
}
private void OnDomeDamaged(Entity<EnergyDomeComponent> dome, ref DamageChangedEvent args)
{
if (dome.Comp.Generator == null)
return;
var generatorUid = dome.Comp.Generator.Value;
if (!TryComp<EnergyDomeGeneratorComponent>(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<PowerCellDrawComponent>(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<BatteryComponent>(generatorUid, out var battery)) {
_battery.UseCharge(generatorUid, energyLeak);
if (battery.CurrentCharge == 0)
TurnOff((generatorUid, generatorComp), true);
}
}
private void OnParentChanged(Entity<EnergyDomeGeneratorComponent> 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<EnergyDomeGeneratorComponent> generator, ref ComponentRemove args)
{
TurnOff(generator, false);
}
// Functional
public bool AttemptToggle(Entity<EnergyDomeGeneratorComponent> generator, bool status)
{
if (TryComp<UseDelayComponent>(generator, out var useDelay) && _useDelay.IsDelayed(new Entity<UseDelayComponent>(generator, useDelay)))
{
_audio.PlayPvs(generator.Comp.TurnOffSound, generator);
_popup.PopupEntity(
Loc.GetString("energy-dome-recharging"),
generator);
return false;
}
if (TryComp<PowerCellSlotComponent>(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<BatteryComponent>(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<EnergyDomeGeneratorComponent> generator, bool status)
{
if (status)
TurnOn(generator);
else
TurnOff(generator, false);
}
private void TurnOn(Entity<EnergyDomeGeneratorComponent> 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<EnergyDomeComponent>(newDome, out var domeComp))
{
domeComp.Generator = generator;
}
if (TryComp<PowerCellDrawComponent>(generator.Owner, out var powerCellDrawComponent))
{
_powerCell.SetDrawEnabled(generator.Owner, true);
}
if (TryComp<BatterySelfRechargerComponent>(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<EnergyDomeGeneratorComponent> generator, bool startReloading)
{
if (!generator.Comp.Enabled)
return;
generator.Comp.Enabled = false;
QueueDel(generator.Comp.SpawnedDome);
if (TryComp<PowerCellDrawComponent>(generator.Owner, out var powerCellDrawComponent))
{
_powerCell.SetDrawEnabled(generator.Owner, false);
}
if (TryComp<BatterySelfRechargerComponent>(generator, out var recharger))
{
recharger.AutoRecharge = false;
}
_audio.PlayPvs(generator.Comp.TurnOffSound, generator);
if (startReloading)
{
_audio.PlayPvs(generator.Comp.EnergyOutSound, generator);
if (TryComp<UseDelayComponent>(generator, out var useDelay))
{
_useDelay.TryResetDelay(new Entity<UseDelayComponent>(generator, useDelay));
}
}
}
// Util
private EntityUid GetProtectedEntity(EntityUid entity)
{
return (_container.TryGetOuterContainer(entity, Transform(entity), out var container))
? container.Owner
: entity;
}
}

View file

@ -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);
}
}
}

View file

@ -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/"

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -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

View file

@ -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

View file

@ -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.

View file

@ -0,0 +1,4 @@
ent-EnergyDomeGeneratorPersonalSyndie = Кроваво-красный генератор барьера
.desc = Генератор щита, защищающий владельца от лазеров и пуль, но не позволяющий самому использовать оружие дальнего боя. Использует батареи.
ent-EnergyDomeDirectionalTurtle = BR-40c "Черепаха"
.desc = Двуручный тяжелый энергетический барьер с чрезвычайно низким пассивным потреблением энергии. Можно подключить с помощью мультитула.

View file

@ -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 = Включить энергетический барьер

View file

@ -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 = Основы робототехники

View file

@ -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 = Фальшивый диск ядерной авторизации

View file

@ -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

View file

@ -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

View file

@ -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:

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -358,6 +358,7 @@
- FauxTileAstroSnow
- OreBagOfHolding
- DeviceQuantumSpinInverter
- EnergyDomeDirectionalTurtle
- type: EmagLatheRecipes
emagDynamicRecipes:
# Sunrise-Start

View file

@ -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

View file

@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

View file

@ -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
]
]
}
]
}

View file

@ -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
]
]
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View file

@ -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
]
]
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

View file

@ -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
]
]
}
]
}

View file

@ -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
]
]
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 816 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 KiB

View file

@ -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
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 812 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 535 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 702 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 718 B

View file

@ -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
}
]
}