Energy crystal (#243)
* init magic container system * charging and discharging * add energy regenerator * thaumaturgy glasses, scanning energy * add energy quartz prorotypes and sprites * light power controller * commit special for _des * simple normalizer crystal slot * YEEEEEEE BOIII, examined crystalls inside things * кристал теперь видно, когда он вставлен в стабилизатор * TryUseCharge приборами * hello deserty, how are you doing? * rename regenerator to EnergyDraw, allow draw from slot * normalizer жрет magic energy файналли * Update normalizer.yml * visual polishing * Update crystal.yml
@@ -1,3 +1,7 @@
|
||||
using Content.Server._CP14.MagicEnergy;
|
||||
using Content.Server.Audio;
|
||||
using Content.Shared._CP14.MagicEnergy.Components;
|
||||
using Content.Shared.Audio;
|
||||
using Content.Shared.Chemistry.Components.SolutionManager;
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
@@ -12,18 +16,35 @@ public sealed partial class CP14SolutionNormalizerSystem : EntitySystem
|
||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||
[Dependency] private readonly IGameTiming _timing = default!;
|
||||
[Dependency] private readonly SharedSolutionContainerSystem _solutionContainer = default!;
|
||||
[Dependency] private readonly CP14MagicEnergyCrystalSlotSystem _magicSlot = default!;
|
||||
[Dependency] private readonly AmbientSoundSystem _ambient = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SubscribeLocalEvent<CP14SolutionNormalizerComponent,CP14SlotCrystalPowerChangedEvent>(OnSlotPowerChanged);
|
||||
}
|
||||
|
||||
private void OnSlotPowerChanged(Entity<CP14SolutionNormalizerComponent> ent, ref CP14SlotCrystalPowerChangedEvent args)
|
||||
{
|
||||
if (TryComp<AmbientSoundComponent>(ent, out var ambient))
|
||||
{
|
||||
_ambient.SetAmbience(ent, args.Powered);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Update(float frameTime)
|
||||
{
|
||||
base.Update(frameTime);
|
||||
|
||||
var query = EntityQueryEnumerator<CP14SolutionNormalizerComponent, SolutionContainerManagerComponent>();
|
||||
|
||||
while (query.MoveNext(out var uid, out var normalizer, out var containerManager))
|
||||
{
|
||||
if (_timing.CurTime <= normalizer.NextUpdateTime)
|
||||
continue;
|
||||
|
||||
if (!_magicSlot.HasEnergy(uid, 1))
|
||||
continue;
|
||||
|
||||
normalizer.NextUpdateTime = _timing.CurTime + normalizer.UpdateFrequency;
|
||||
|
||||
var solutionManager = new Entity<SolutionContainerManagerComponent?>(uid, containerManager);
|
||||
|
||||
@@ -0,0 +1,150 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Content.Shared._CP14.MagicEnergy;
|
||||
using Content.Shared._CP14.MagicEnergy.Components;
|
||||
using Content.Shared.Containers.ItemSlots;
|
||||
using Content.Shared.Examine;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.Popups;
|
||||
using Robust.Shared.Containers;
|
||||
|
||||
namespace Content.Server._CP14.MagicEnergy;
|
||||
|
||||
public sealed partial class CP14MagicEnergyCrystalSlotSystem : SharedCP14MagicEnergyCrystalSlotSystem
|
||||
{
|
||||
|
||||
[Dependency] private readonly ItemSlotsSystem _itemSlots = default!;
|
||||
[Dependency] private readonly CP14MagicEnergySystem _magicEnergy = default!;
|
||||
[Dependency] private readonly SharedPopupSystem _popup = default!;
|
||||
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
|
||||
[Dependency] private readonly SharedContainerSystem _container = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SubscribeLocalEvent<CP14MagicEnergyCrystalComponent, CP14MagicEnergyLevelChangeEvent>(OnEnergyChanged);
|
||||
SubscribeLocalEvent<CP14MagicEnergyCrystalSlotComponent, ExaminedEvent>(OnExamined);
|
||||
SubscribeLocalEvent<CP14MagicEnergyCrystalSlotComponent, CP14SlotCrystalChangedEvent>(OnCrystalChanged);
|
||||
}
|
||||
|
||||
private void OnCrystalChanged(Entity<CP14MagicEnergyCrystalSlotComponent> ent, ref CP14SlotCrystalChangedEvent args)
|
||||
{
|
||||
var realPowered = TryGetEnergyCrystalFromSlot(ent, out var energyEnt, out var energyComp);
|
||||
|
||||
if (energyComp != null)
|
||||
realPowered = energyComp.Energy > 0;
|
||||
|
||||
if (ent.Comp.Powered != realPowered)
|
||||
{
|
||||
ent.Comp.Powered = realPowered;
|
||||
_appearance.SetData(ent, CP14MagicSlotVisuals.Powered, realPowered);
|
||||
RaiseLocalEvent(ent, new CP14SlotCrystalPowerChangedEvent(realPowered));
|
||||
}
|
||||
}
|
||||
|
||||
private void OnEnergyChanged(Entity<CP14MagicEnergyCrystalComponent> crystal, ref CP14MagicEnergyLevelChangeEvent args)
|
||||
{
|
||||
if (_container.TryGetContainingContainer(crystal, out var container)
|
||||
&& TryComp(container.Owner, out CP14MagicEnergyCrystalSlotComponent? slot)
|
||||
&& _itemSlots.TryGetSlot(container.Owner, slot.SlotId, out var itemSlot))
|
||||
{
|
||||
if (itemSlot.Item == crystal)
|
||||
{
|
||||
RaiseLocalEvent(container.Owner, new CP14SlotCrystalChangedEvent(false));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnExamined(Entity<CP14MagicEnergyCrystalSlotComponent> ent, ref ExaminedEvent args)
|
||||
{
|
||||
if (!TryGetEnergyCrystalFromSlot(ent, out var crystalUid, out var crystalComp, ent.Comp))
|
||||
return;
|
||||
|
||||
var scanEvent = new CP14MagicEnergyScanEvent();
|
||||
RaiseLocalEvent(args.Examiner, scanEvent);
|
||||
|
||||
if (!scanEvent.CanScan)
|
||||
return;
|
||||
|
||||
args.PushMarkup(_magicEnergy.GetEnergyExaminedText(crystalUid.Value, crystalComp));
|
||||
}
|
||||
|
||||
public bool TryGetEnergyCrystalFromSlot(EntityUid uid,
|
||||
[NotNullWhen(true)] out CP14MagicEnergyContainerComponent? energyComp,
|
||||
CP14MagicEnergyCrystalSlotComponent? component = null)
|
||||
{
|
||||
return TryGetEnergyCrystalFromSlot(uid, out _, out energyComp, component);
|
||||
}
|
||||
|
||||
public bool TryGetEnergyCrystalFromSlot(EntityUid uid,
|
||||
[NotNullWhen(true)] out EntityUid? energyEnt,
|
||||
[NotNullWhen(true)] out CP14MagicEnergyContainerComponent? energyComp,
|
||||
CP14MagicEnergyCrystalSlotComponent? component = null)
|
||||
{
|
||||
if (!Resolve(uid, ref component, false))
|
||||
{
|
||||
energyEnt = null;
|
||||
energyComp = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_itemSlots.TryGetSlot(uid, component.SlotId, out ItemSlot? slot))
|
||||
{
|
||||
energyEnt = slot.Item;
|
||||
return TryComp(slot.Item, out energyComp);
|
||||
}
|
||||
|
||||
energyEnt = null;
|
||||
energyComp = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool HasEnergy(EntityUid uid,
|
||||
FixedPoint2 energy,
|
||||
CP14MagicEnergyCrystalSlotComponent? component = null,
|
||||
EntityUid? user = null)
|
||||
{
|
||||
if (!TryGetEnergyCrystalFromSlot(uid, out var energyEnt, out var energyComp, component))
|
||||
{
|
||||
if (user != null)
|
||||
_popup.PopupEntity(Loc.GetString("cp14-magic-energy-no-crystal"), uid,user.Value);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (energyComp.Energy < energy)
|
||||
{
|
||||
if (user != null)
|
||||
_popup.PopupEntity(Loc.GetString("cp14-magic-energy-insufficient"), uid, user.Value);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
public bool TryUseEnergy(EntityUid uid,
|
||||
FixedPoint2 energy,
|
||||
CP14MagicEnergyCrystalSlotComponent? component = null,
|
||||
EntityUid? user = null,
|
||||
bool safe = false)
|
||||
{
|
||||
if (!TryGetEnergyCrystalFromSlot(uid, out var energyEnt, out var energyComp, component))
|
||||
{
|
||||
if (user != null)
|
||||
_popup.PopupEntity(Loc.GetString("cp14-magic-energy-no-crystal"), uid,user.Value);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_magicEnergy.TryConsumeEnergy(energyEnt.Value, energy, energyComp, safe))
|
||||
{
|
||||
if (user != null)
|
||||
_popup.PopupEntity(
|
||||
Loc.GetString(safe ? "cp14-magic-energy-insufficient" : "cp14-magic-energy-insufficient-unsafe"),
|
||||
uid,
|
||||
user.Value);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
152
Content.Server/_CP14/MagicEnergy/CP14MagicEnergySystem.cs
Normal file
@@ -0,0 +1,152 @@
|
||||
using Content.Server._CP14.MagicEnergy.Components;
|
||||
using Content.Shared._CP14.MagicEnergy;
|
||||
using Content.Shared._CP14.MagicEnergy.Components;
|
||||
using Content.Shared.Examine;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.Inventory;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Server._CP14.MagicEnergy;
|
||||
|
||||
public sealed partial class CP14MagicEnergySystem : SharedCP14MagicEnergySystem
|
||||
{
|
||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||
[Dependency] private readonly PointLightSystem _light = default!;
|
||||
[Dependency] private readonly CP14MagicEnergyCrystalSlotSystem _magicSlot = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SubscribeLocalEvent<CP14MagicEnergyDrawComponent, MapInitEvent>(OnMapInit);
|
||||
SubscribeLocalEvent<CP14MagicEnergyPointLightControllerComponent, CP14MagicEnergyLevelChangeEvent>(OnEnergyChange);
|
||||
|
||||
SubscribeLocalEvent<CP14MagicEnergyExaminableComponent, ExaminedEvent>(OnExamined);
|
||||
SubscribeLocalEvent<CP14MagicEnergyScannerComponent, CP14MagicEnergyScanEvent>(OnMagicScanAttempt);
|
||||
SubscribeLocalEvent<CP14MagicEnergyScannerComponent, InventoryRelayedEvent<CP14MagicEnergyScanEvent>>((e, c, ev) => OnMagicScanAttempt(e, c, ev.Args));
|
||||
}
|
||||
|
||||
private void OnEnergyChange(Entity<CP14MagicEnergyPointLightControllerComponent> ent, ref CP14MagicEnergyLevelChangeEvent args)
|
||||
{
|
||||
if (!TryComp<PointLightComponent>(ent, out var light))
|
||||
return;
|
||||
|
||||
var lightEnergy = MathHelper.Lerp(ent.Comp.MinEnergy, ent.Comp.MaxEnergy, (float)(args.NewValue / args.MaxValue));
|
||||
_light.SetEnergy(ent, lightEnergy, light);
|
||||
}
|
||||
|
||||
private void OnMapInit(Entity<CP14MagicEnergyDrawComponent> ent, ref MapInitEvent args)
|
||||
{
|
||||
ent.Comp.NextUpdateTime = _gameTiming.CurTime + TimeSpan.FromSeconds(ent.Comp.Delay);
|
||||
}
|
||||
|
||||
private void OnMagicScanAttempt(EntityUid uid, CP14MagicEnergyScannerComponent component, CP14MagicEnergyScanEvent args)
|
||||
{
|
||||
args.CanScan = true;
|
||||
}
|
||||
|
||||
private void OnExamined(Entity<CP14MagicEnergyExaminableComponent> ent, ref ExaminedEvent args)
|
||||
{
|
||||
if (!TryComp<CP14MagicEnergyContainerComponent>(ent, out var magicContainer))
|
||||
return;
|
||||
|
||||
var scanEvent = new CP14MagicEnergyScanEvent();
|
||||
RaiseLocalEvent(args.Examiner, scanEvent);
|
||||
|
||||
if (!scanEvent.CanScan)
|
||||
return;
|
||||
|
||||
args.PushMarkup(GetEnergyExaminedText(ent, magicContainer));
|
||||
}
|
||||
|
||||
|
||||
|
||||
public override void Update(float frameTime)
|
||||
{
|
||||
base.Update(frameTime);
|
||||
|
||||
var query = EntityQueryEnumerator<CP14MagicEnergyDrawComponent, CP14MagicEnergyContainerComponent>();
|
||||
while (query.MoveNext(out var uid, out var draw, out var magicContainer))
|
||||
{
|
||||
if (draw.NextUpdateTime >= _gameTiming.CurTime)
|
||||
continue;
|
||||
|
||||
draw.NextUpdateTime = _gameTiming.CurTime + TimeSpan.FromSeconds(draw.Delay);
|
||||
|
||||
ChangeEnergy(uid, magicContainer, draw.Energy, safe: draw.Safe);
|
||||
}
|
||||
|
||||
var query2 = EntityQueryEnumerator<CP14MagicEnergyDrawComponent, CP14MagicEnergyCrystalSlotComponent>();
|
||||
while (query2.MoveNext(out var uid, out var draw, out var slot))
|
||||
{
|
||||
if (!draw.Enable)
|
||||
continue;
|
||||
|
||||
if (draw.NextUpdateTime >= _gameTiming.CurTime)
|
||||
continue;
|
||||
|
||||
draw.NextUpdateTime = _gameTiming.CurTime + TimeSpan.FromSeconds(draw.Delay);
|
||||
|
||||
if (!_magicSlot.TryGetEnergyCrystalFromSlot(uid, out var energyEnt, out var energyComp))
|
||||
continue;
|
||||
|
||||
ChangeEnergy(energyEnt.Value, energyComp, draw.Energy, draw.Safe);
|
||||
}
|
||||
}
|
||||
|
||||
public bool TryConsumeEnergy(EntityUid uid, FixedPoint2 energy, CP14MagicEnergyContainerComponent? component = null, bool safe = false)
|
||||
{
|
||||
if (!Resolve(uid, ref component))
|
||||
return false;
|
||||
|
||||
if (energy <= 0)
|
||||
return true;
|
||||
|
||||
// Attempting to absorb more energy than is contained in the carrier will still waste all the energy
|
||||
if (component.Energy < energy)
|
||||
{
|
||||
ChangeEnergy(uid, component, -component.Energy);
|
||||
return false;
|
||||
}
|
||||
|
||||
ChangeEnergy(uid, component, -energy, safe);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void ChangeEnergy(EntityUid uid, CP14MagicEnergyContainerComponent component, FixedPoint2 energy, bool safe = false)
|
||||
{
|
||||
if (!safe)
|
||||
{
|
||||
//Overload
|
||||
if (component.Energy + energy > component.MaxEnergy)
|
||||
{
|
||||
RaiseLocalEvent(uid, new CP14MagicEnergyOverloadEvent()
|
||||
{
|
||||
OverloadEnergy = (component.Energy + energy) - component.MaxEnergy,
|
||||
});
|
||||
}
|
||||
|
||||
//Burn out
|
||||
if (component.Energy + energy < 0)
|
||||
{
|
||||
RaiseLocalEvent(uid, new CP14MagicEnergyBurnOutEvent()
|
||||
{
|
||||
BurnOutEnergy = -energy - component.Energy
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var oldEnergy = component.Energy;
|
||||
var newEnergy = Math.Clamp((float)component.Energy + (float)energy, 0, (float)component.MaxEnergy);
|
||||
component.Energy = newEnergy;
|
||||
|
||||
if (oldEnergy != newEnergy)
|
||||
{
|
||||
RaiseLocalEvent(uid, new CP14MagicEnergyLevelChangeEvent()
|
||||
{
|
||||
OldValue = component.Energy,
|
||||
NewValue = newEnergy,
|
||||
MaxValue = component.MaxEnergy,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
using Content.Shared.FixedPoint;
|
||||
|
||||
namespace Content.Server._CP14.MagicEnergy.Components;
|
||||
|
||||
/// <summary>
|
||||
/// Allows you to restore or deplete the magical energy in the item
|
||||
/// </summary>
|
||||
[RegisterComponent, Access(typeof(CP14MagicEnergySystem))]
|
||||
public sealed partial class CP14MagicEnergyDrawComponent : Component
|
||||
{
|
||||
[DataField]
|
||||
public bool Enable = true;
|
||||
|
||||
[DataField]
|
||||
public FixedPoint2 Energy = 1f;
|
||||
|
||||
/// <summary>
|
||||
/// If not safe, restoring or drawing power across boundaries call dangerous events, that may destroy crystals
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public bool Safe = true;
|
||||
|
||||
/// <summary>
|
||||
/// how often objects will try to change magic energy. In Seconds
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public float Delay = 5f;
|
||||
|
||||
/// <summary>
|
||||
/// the time of the next magic energy change
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public TimeSpan NextUpdateTime { get; set; } = TimeSpan.Zero;
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
using Content.Shared._CP14.MagicEnergy;
|
||||
using Content.Shared.Chemistry;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Electrocution;
|
||||
@@ -36,6 +37,7 @@ public partial class InventorySystem
|
||||
SubscribeLocalEvent<InventoryComponent, GetEyeProtectionEvent>(RelayInventoryEvent);
|
||||
SubscribeLocalEvent<InventoryComponent, GetBlurEvent>(RelayInventoryEvent);
|
||||
SubscribeLocalEvent<InventoryComponent, SolutionScanEvent>(RelayInventoryEvent);
|
||||
SubscribeLocalEvent<InventoryComponent, CP14MagicEnergyScanEvent>(RelayInventoryEvent); //CP14 Magic scanning
|
||||
|
||||
// ComponentActivatedClientSystems
|
||||
SubscribeLocalEvent<InventoryComponent, RefreshEquipmentHudEvent<ShowJobIconsComponent>>(RelayInventoryEvent);
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
using Content.Shared.FixedPoint;
|
||||
|
||||
namespace Content.Shared._CP14.MagicEnergy.Components;
|
||||
|
||||
/// <summary>
|
||||
/// Allows an item to store magical energy within itself.
|
||||
/// </summary>
|
||||
[RegisterComponent, Access(typeof(SharedCP14MagicEnergySystem))]
|
||||
public sealed partial class CP14MagicEnergyContainerComponent : Component
|
||||
{
|
||||
[DataField]
|
||||
public FixedPoint2 Energy = 0f;
|
||||
|
||||
[DataField]
|
||||
public FixedPoint2 MaxEnergy = 100f;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace Content.Shared._CP14.MagicEnergy.Components;
|
||||
|
||||
/// <summary>
|
||||
/// allows the object to be inserted into CP14MagicEnergyCrystalSlot
|
||||
/// </summary>
|
||||
[RegisterComponent, Access(typeof(SharedCP14MagicEnergyCrystalSlotSystem))]
|
||||
public sealed partial class CP14MagicEnergyCrystalComponent : Component
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared._CP14.MagicEnergy.Components;
|
||||
|
||||
/// <summary>
|
||||
/// Allows you to examine how much energy is in that object
|
||||
/// </summary>
|
||||
[RegisterComponent, Access(typeof(SharedCP14MagicEnergyCrystalSlotSystem))]
|
||||
public sealed partial class CP14MagicEnergyCrystalSlotComponent : Component
|
||||
{
|
||||
[DataField(required: true)]
|
||||
public string SlotId = string.Empty;
|
||||
|
||||
public bool Powered = false;
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public enum CP14MagicSlotVisuals : byte
|
||||
{
|
||||
Inserted,
|
||||
Powered
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Is called when the state of the crystal is changed: it is pulled out, inserted, or the amount of energy in it has changed.
|
||||
/// </summary>
|
||||
public sealed class CP14SlotCrystalChangedEvent : EntityEventArgs
|
||||
{
|
||||
public readonly bool Ejected;
|
||||
|
||||
public CP14SlotCrystalChangedEvent(bool ejected)
|
||||
{
|
||||
Ejected = ejected;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Is called when the power status of the device changes.
|
||||
/// </summary>
|
||||
public sealed class CP14SlotCrystalPowerChangedEvent : EntityEventArgs
|
||||
{
|
||||
public readonly bool Powered;
|
||||
public CP14SlotCrystalPowerChangedEvent(bool powered)
|
||||
{
|
||||
Powered = powered;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace Content.Shared._CP14.MagicEnergy.Components;
|
||||
|
||||
/// <summary>
|
||||
/// Allows you to examine how much energy is in that object
|
||||
/// </summary>
|
||||
[RegisterComponent, Access(typeof(SharedCP14MagicEnergySystem))]
|
||||
public sealed partial class CP14MagicEnergyExaminableComponent : Component
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using Content.Shared.Inventory;
|
||||
|
||||
namespace Content.Shared._CP14.MagicEnergy.Components;
|
||||
|
||||
/// <summary>
|
||||
/// Controls the strength of the PointLight component, depending on the amount of mana in the object
|
||||
/// </summary>
|
||||
[RegisterComponent, Access(typeof(SharedCP14MagicEnergySystem))]
|
||||
public sealed partial class CP14MagicEnergyPointLightControllerComponent : Component
|
||||
{
|
||||
[DataField]
|
||||
public float MaxEnergy = 1f;
|
||||
|
||||
[DataField]
|
||||
public float MinEnergy = 0f;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
using Content.Shared.Inventory;
|
||||
|
||||
namespace Content.Shared._CP14.MagicEnergy.Components;
|
||||
|
||||
/// <summary>
|
||||
/// Allows you to see how much magic energy is stored in objects
|
||||
/// </summary>
|
||||
[RegisterComponent, Access(typeof(SharedCP14MagicEnergySystem))]
|
||||
public sealed partial class CP14MagicEnergyScannerComponent : Component
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
using Content.Shared._CP14.MagicEnergy.Components;
|
||||
using Content.Shared.Containers.ItemSlots;
|
||||
using Robust.Shared.Containers;
|
||||
|
||||
namespace Content.Shared._CP14.MagicEnergy;
|
||||
|
||||
public partial class SharedCP14MagicEnergyCrystalSlotSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly ItemSlotsSystem _itemSlots = default!;
|
||||
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
|
||||
[Dependency] private readonly SharedContainerSystem _containerSystem = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<CP14MagicEnergyCrystalSlotComponent, EntInsertedIntoContainerMessage>(OnCrystalInserted);
|
||||
SubscribeLocalEvent<CP14MagicEnergyCrystalSlotComponent, EntRemovedFromContainerMessage>(OnCrystalRemoved);
|
||||
}
|
||||
|
||||
private void OnCrystalRemoved(Entity<CP14MagicEnergyCrystalSlotComponent> slot, ref EntRemovedFromContainerMessage args)
|
||||
{
|
||||
if (args.Container.ID != slot.Comp.SlotId)
|
||||
return;
|
||||
|
||||
_appearance.SetData(slot, CP14MagicSlotVisuals.Inserted, false);
|
||||
_appearance.SetData(slot, CP14MagicSlotVisuals.Powered, false);
|
||||
RaiseLocalEvent(slot, new CP14SlotCrystalChangedEvent(true));
|
||||
}
|
||||
|
||||
private void OnCrystalInserted(Entity<CP14MagicEnergyCrystalSlotComponent> slot, ref EntInsertedIntoContainerMessage args)
|
||||
{
|
||||
if (!slot.Comp.Initialized)
|
||||
return;
|
||||
|
||||
if (args.Container.ID != slot.Comp.SlotId)
|
||||
return;
|
||||
|
||||
_appearance.SetData(slot, CP14MagicSlotVisuals.Inserted, true);
|
||||
RaiseLocalEvent(slot, new CP14SlotCrystalChangedEvent(false));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
using Content.Shared._CP14.MagicEnergy.Components;
|
||||
using Content.Shared.Examine;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.Inventory;
|
||||
|
||||
namespace Content.Shared._CP14.MagicEnergy;
|
||||
|
||||
public partial class SharedCP14MagicEnergySystem : EntitySystem
|
||||
{
|
||||
public string GetEnergyExaminedText(EntityUid uid, CP14MagicEnergyContainerComponent ent)
|
||||
{
|
||||
var power = (int)((ent.Energy / ent.MaxEnergy) * 100);
|
||||
|
||||
var color = "#3fc488";
|
||||
if (power < 66)
|
||||
color = "#f2a93a";
|
||||
if (power < 33)
|
||||
color = "#c23030";
|
||||
|
||||
return Loc.GetString("cp14-magic-energy-scan-result",
|
||||
("item", MetaData(uid).EntityName),
|
||||
("power", power),
|
||||
("color", color));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// It's triggered when the energy change in MagicEnergyContainer
|
||||
/// </summary>
|
||||
public sealed class CP14MagicEnergyLevelChangeEvent : EntityEventArgs
|
||||
{
|
||||
public FixedPoint2 OldValue;
|
||||
public FixedPoint2 NewValue;
|
||||
public FixedPoint2 MaxValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// It's triggered when more energy enters the MagicEnergyContainer than it can hold.
|
||||
/// </summary>
|
||||
public sealed class CP14MagicEnergyOverloadEvent : EntityEventArgs
|
||||
{
|
||||
public FixedPoint2 OverloadEnergy;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// It's triggered they something try to get energy out of MagicEnergyContainer that is lacking there.
|
||||
/// </summary>
|
||||
public sealed class CP14MagicEnergyBurnOutEvent : EntityEventArgs
|
||||
{
|
||||
public FixedPoint2 BurnOutEnergy;
|
||||
}
|
||||
|
||||
public sealed class CP14MagicEnergyScanEvent : EntityEventArgs, IInventoryRelayEvent
|
||||
{
|
||||
public bool CanScan;
|
||||
public SlotFlags TargetSlots { get; } = SlotFlags.EYES;
|
||||
}
|
||||
BIN
Resources/Audio/_CP14/Ambience/ambiAlchemy.ogg
Normal file
@@ -21,4 +21,9 @@
|
||||
- files: ["weatherWindy.ogg"]
|
||||
license: "CC-BY-4.0"
|
||||
copyright: 'by Benboncan of Freesound.org. Mixed from stereo to mono.'
|
||||
source: "https://freesound.org/people/Benboncan/sounds/134699/"
|
||||
source: "https://freesound.org/people/Benboncan/sounds/134699/"
|
||||
|
||||
- files: ["ambiAlchemy.ogg"]
|
||||
license: "CC-BY-4.0"
|
||||
copyright: 'by be-steele of Freesound.org.'
|
||||
source: "https://freesound.org/people/be-steele/sounds/130753/"
|
||||
BIN
Resources/Audio/_CP14/Ambience/normalizer_working.ogg
Normal file
@@ -31,4 +31,14 @@
|
||||
- files: ["shovel_dig1.ogg", "shovel_dig2.ogg", "shovel_dig3.ogg", "shovel_dig4.ogg", "shovel_dig5.ogg"]
|
||||
license: "CC0-1.0"
|
||||
copyright: 'by Ali_6868 of Freesound.org. Cropped and mixed from stereo to mono.'
|
||||
source: "https://freesound.org/people/Ali_6868/sounds/384361/"
|
||||
source: "https://freesound.org/people/Ali_6868/sounds/384361/"
|
||||
|
||||
- files: ["crystal_eject.ogg", "crystal_insert.ogg"]
|
||||
license: "CC-BY-4.0"
|
||||
copyright: 'by Joachim_Berger of Freesound.org. Cropped by TheShuEd.'
|
||||
source: "https://freesound.org/people/Joachim_Berger/sounds/660526/"
|
||||
|
||||
- files: ["normalizer_working.ogg"]
|
||||
license: "CC0-1.0"
|
||||
copyright: 'by craigsmith of Freesound.org. Cropped by TheShuEd.'
|
||||
source: "https://freesound.org/people/craigsmith/sounds/438604/"
|
||||
BIN
Resources/Audio/_CP14/Items/crystal_eject.ogg
Normal file
BIN
Resources/Audio/_CP14/Items/crystal_insert.ogg
Normal file
@@ -0,0 +1,7 @@
|
||||
cp14-magic-energy-scan-result = The {$item} is filled with [color={$color}]{$power}%[/color] magical energy
|
||||
|
||||
cp14-magic-energy-crystal-slot-name = Energy crystal
|
||||
|
||||
cp14-magic-energy-no-crystal = No energy crystal!
|
||||
cp14-magic-energy-insufficient = Not enough energy!
|
||||
cp14-magic-energy-insufficient-unsafe = Crystal cracks from lack of energy!
|
||||
@@ -0,0 +1,7 @@
|
||||
cp14-magic-energy-scan-result = {$item} заполнен магической энергией на [color={$color}]{$power}%[/color]
|
||||
|
||||
cp14-magic-energy-crystal-slot-name = Энергокристалл
|
||||
|
||||
cp14-magic-energy-no-crystal = Отсутствует энергокристалл!
|
||||
cp14-magic-energy-insufficient = Не достаточно энергии!
|
||||
cp14-magic-energy-insufficient-unsafe = Кристалл трескается от нехватки энергии!
|
||||
@@ -60,3 +60,22 @@
|
||||
sprite: _CP14/Clothing/Eyes/alchemy_glasses.rsi
|
||||
- type: SolutionScanner
|
||||
|
||||
- type: entity
|
||||
parent: CP14ClothingEyesBase
|
||||
id: CP14ClothingEyesThaumaturgyGlasses
|
||||
name: thaumaturgy glasses
|
||||
description: Goggles that allow you to scan magical items and creatures to clearly see the amount of energy left in them.
|
||||
components:
|
||||
- type: Foldable
|
||||
canFoldInsideContainer: true
|
||||
unfoldVerbText: fold-flip-verb
|
||||
foldVerbText: fold-flip-verb
|
||||
- type: FoldableClothing
|
||||
foldedEquippedPrefix: flipped
|
||||
foldedHeldPrefix: flipped
|
||||
- type: Sprite
|
||||
sprite: _CP14/Clothing/Eyes/alchemy_glasses.rsi #TODO sprite
|
||||
- type: Clothing
|
||||
sprite: _CP14/Clothing/Eyes/alchemy_glasses.rsi
|
||||
- type: CP14MagicEnergyScanner
|
||||
|
||||
|
||||
@@ -157,8 +157,8 @@
|
||||
- type: entity
|
||||
id: CP14QuartzShard
|
||||
parent: BaseItem
|
||||
name: quartz shard
|
||||
description: a shard of once luminous crystal. Unfortunately, careless handling destroyed much of the potential.
|
||||
name: rough quartz
|
||||
description: a natural crystal that is a natural storage of magical energy. Its color reflects the quality of the crystal - the higher the emission spectrum, the higher the level of energy leakage.
|
||||
components:
|
||||
- type: Tag
|
||||
tags:
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
- type: entity
|
||||
id: CP14EnergyCrystalBase
|
||||
parent: BaseItem
|
||||
abstract: true
|
||||
description: Processed quartz crystals are excellent repositories of magical energy. And special connectors allow you to conveniently insert them into magical devices, turning them into energy batteries.
|
||||
components:
|
||||
- type: CP14MagicEnergyCrystal
|
||||
- type: Item
|
||||
size: Tiny
|
||||
- type: Sprite
|
||||
sprite: _CP14/Objects/Specific/Thaumaturgy/crystal.rsi
|
||||
- type: CP14MagicEnergyContainer
|
||||
- type: CP14MagicEnergyExaminable
|
||||
- type: CP14MagicEnergyPointLightController
|
||||
|
||||
|
||||
- type: entity
|
||||
id: CP14EnergyCrystalSmall
|
||||
parent: CP14EnergyCrystalBase
|
||||
name: small energy crystal
|
||||
suffix: Full
|
||||
components:
|
||||
- type: Sprite
|
||||
layers:
|
||||
- state: small1
|
||||
shader: unshaded
|
||||
map: ["random"]
|
||||
- state: small_connector
|
||||
- type: RandomSprite
|
||||
available:
|
||||
- random:
|
||||
small1: ""
|
||||
small2: ""
|
||||
small3: ""
|
||||
- type: CP14MagicEnergyContainer
|
||||
energy: 30
|
||||
maxEnergy: 30
|
||||
|
||||
- type: entity
|
||||
id: CP14EnergyCrystalSmallEmpty
|
||||
parent: CP14EnergyCrystalSmall
|
||||
suffix: Empty
|
||||
components:
|
||||
- type: CP14MagicEnergyContainer
|
||||
energy: 0
|
||||
|
||||
|
||||
- type: entity
|
||||
id: CP14EnergyCrystalMedium
|
||||
parent: CP14EnergyCrystalBase
|
||||
name: energy crystal
|
||||
suffix: Full
|
||||
components:
|
||||
- type: PointLight
|
||||
radius: 1.2
|
||||
- type: Sprite
|
||||
layers:
|
||||
- state: medium1
|
||||
shader: unshaded
|
||||
map: ["random"]
|
||||
- state: medium_connector
|
||||
- type: RandomSprite
|
||||
available:
|
||||
- random:
|
||||
medium1: ""
|
||||
medium2: ""
|
||||
medium3: ""
|
||||
- type: CP14MagicEnergyContainer
|
||||
energy: 100
|
||||
maxEnergy: 100
|
||||
|
||||
- type: entity
|
||||
id: CP14EnergyCrystalMediumEmpty
|
||||
parent: CP14EnergyCrystalMedium
|
||||
suffix: Empty
|
||||
components:
|
||||
- type: CP14MagicEnergyContainer
|
||||
energy: 0
|
||||
@@ -1,7 +1,7 @@
|
||||
- type: entity
|
||||
id: CP14AlchemyNormalizer
|
||||
parent: BaseStructureDynamic
|
||||
name: solution stabilizer
|
||||
name: solution normalizer
|
||||
description: An alchemical device that removes fine precipitates from solutions, and stabilizes it for further work
|
||||
placement:
|
||||
mode: PlaceFree
|
||||
@@ -14,13 +14,31 @@
|
||||
offset: 0, 0.2
|
||||
sprite: _CP14/Structures/Specific/Alchemy/normalizer.rsi
|
||||
layers:
|
||||
- state: rotate_back
|
||||
- state: rotate_back_stop
|
||||
map: ["poweredBack"]
|
||||
- state: liq-1
|
||||
map: ["enum.SolutionContainerLayers.Fill"]
|
||||
visible: false
|
||||
- state: base
|
||||
- state: rotate_front
|
||||
state: base
|
||||
- state: rotate_front_stop
|
||||
map: ["poweredFront"]
|
||||
- state: crystal
|
||||
shader: unshaded
|
||||
map: ["crystal"]
|
||||
visible: false
|
||||
- type: GenericVisualizer
|
||||
visuals:
|
||||
enum.CP14MagicSlotVisuals.Inserted:
|
||||
crystal:
|
||||
True: { visible: true }
|
||||
False: { visible: false }
|
||||
enum.CP14MagicSlotVisuals.Powered:
|
||||
poweredFront:
|
||||
True: { state: rotate_front }
|
||||
False: { state: rotate_front_stop }
|
||||
poweredBack:
|
||||
True: { state: rotate_back }
|
||||
False: { state: rotate_back_stop }
|
||||
- type: Fixtures
|
||||
fixtures:
|
||||
fix1:
|
||||
@@ -48,7 +66,37 @@
|
||||
solution: normalizer
|
||||
- type: CP14SolutionNormalizer
|
||||
solution: normalizer
|
||||
- type: AmbientSound
|
||||
enabled: false
|
||||
range: 6
|
||||
volume: -3
|
||||
sound:
|
||||
path: /Audio/_CP14/Ambience/normalizer_working.ogg
|
||||
- type: Appearance
|
||||
- type: SolutionContainerVisuals
|
||||
maxFillLevels: 5
|
||||
fillBaseName: liq-
|
||||
fillBaseName: liq-
|
||||
- type: CP14MagicEnergyDraw
|
||||
energy: -0.2
|
||||
delay: 1
|
||||
- type: CP14MagicEnergyCrystalSlot
|
||||
slotId: crystal_slot
|
||||
- type: ContainerContainer
|
||||
containers:
|
||||
crystal_slot: !type:ContainerSlot
|
||||
- type: ItemSlots
|
||||
slots:
|
||||
crystal_slot:
|
||||
insertSound:
|
||||
path: /Audio/_CP14/Items/crystal_insert.ogg
|
||||
params:
|
||||
variation: 0.05
|
||||
ejectSound:
|
||||
path: /Audio/_CP14/Items/crystal_eject.ogg
|
||||
params:
|
||||
variation: 0.05
|
||||
ejectOnInteract: true
|
||||
name: cp14-magic-energy-crystal-slot-name
|
||||
whitelist:
|
||||
components:
|
||||
- CP14MagicEnergyCrystal
|
||||
|
After Width: | Height: | Size: 283 B |
|
After Width: | Height: | Size: 276 B |
|
After Width: | Height: | Size: 267 B |
|
After Width: | Height: | Size: 204 B |
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"version": 1,
|
||||
"size": {
|
||||
"x": 32,
|
||||
"y": 32
|
||||
},
|
||||
"license": "CC-BY-SA-3.0",
|
||||
"copyright": "Created by TheShuEd (Github) for CrystallPunk14",
|
||||
"states": [
|
||||
{
|
||||
"name": "small1"
|
||||
},
|
||||
{
|
||||
"name": "small2"
|
||||
},
|
||||
{
|
||||
"name": "small3"
|
||||
},
|
||||
{
|
||||
"name": "small_connector"
|
||||
},
|
||||
{
|
||||
"name": "medium1"
|
||||
},
|
||||
{
|
||||
"name": "medium2"
|
||||
},
|
||||
{
|
||||
"name": "medium3"
|
||||
},
|
||||
{
|
||||
"name": "medium_connector"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
After Width: | Height: | Size: 218 B |
|
After Width: | Height: | Size: 206 B |
|
After Width: | Height: | Size: 275 B |
|
After Width: | Height: | Size: 196 B |
|
Before Width: | Height: | Size: 726 B After Width: | Height: | Size: 731 B |
|
After Width: | Height: | Size: 187 B |
@@ -25,6 +25,15 @@
|
||||
{
|
||||
"name": "liq-5"
|
||||
},
|
||||
{
|
||||
"name": "crystal"
|
||||
},
|
||||
{
|
||||
"name": "rotate_back_stop"
|
||||
},
|
||||
{
|
||||
"name": "rotate_front_stop"
|
||||
},
|
||||
{
|
||||
"name": "rotate_back",
|
||||
"delays": [
|
||||
|
||||
|
After Width: | Height: | Size: 230 B |
|
After Width: | Height: | Size: 179 B |