Essence splitter (#948)

* disable rotting

* pipipi

* essence storage

* energy splitter

* Update essence_splitter.yml

* Update impact.png

* visual fixes

* sound fix

* Update twoHandedStaffs.yml

* unhardcode

* Update meta.json

* fix
This commit is contained in:
Ed
2025-02-27 13:48:38 +03:00
committed by GitHub
parent c6cc4daa3f
commit 5524e029f4
32 changed files with 350 additions and 74 deletions

View File

@@ -34,7 +34,9 @@ public sealed partial class CP14ManaChange : EntityEffect
}
var magicSystem = args.EntityManager.System<CP14MagicEnergySystem>();
magicSystem.ChangeEnergy(args.TargetEntity, ManaDelta * scale, out _, out _, safe: Safe);
magicSystem.ChangeEnergy(args.TargetEntity, ManaDelta * scale, out var changed, out var overload, safe: Safe);
scale -= FixedPoint2.Abs(changed + overload);
if (args.EntityManager.TryGetComponent<CP14MagicEnergyCrystalSlotComponent>(args.TargetEntity,
out var crystalSlot))

View File

@@ -1,23 +1,13 @@
using Content.Shared._CP14.MagicEnergy;
using Content.Shared._CP14.MagicEnergy.Components;
using Content.Shared.Examine;
using Content.Shared.Inventory;
namespace Content.Server._CP14.MagicEnergy;
public partial class CP14MagicEnergySystem
{
private void InitializeScanner()
{
SubscribeLocalEvent<CP14MagicEnergyExaminableComponent, ExaminedEvent>(OnExamined);
SubscribeLocalEvent<CP14MagicEnergyScannerComponent, CP14MagicEnergyScanEvent>(OnMagicScanAttempt);
SubscribeLocalEvent<CP14MagicEnergyScannerComponent, InventoryRelayedEvent<CP14MagicEnergyScanEvent>>((e, c, ev) => OnMagicScanAttempt(e, c, ev.Args));
}
private void OnMagicScanAttempt(EntityUid uid, CP14MagicEnergyScannerComponent component, CP14MagicEnergyScanEvent args)
{
args.CanScan = true;
}
private void OnExamined(Entity<CP14MagicEnergyExaminableComponent> ent, ref ExaminedEvent args)
@@ -28,12 +18,6 @@ public partial class CP14MagicEnergySystem
if (!args.IsInDetailsRange)
return;
//var scanEvent = new CP14MagicEnergyScanEvent();
//RaiseLocalEvent(args.Examiner, scanEvent);
//
//if (!scanEvent.CanScan)
// return;
args.PushMarkup(GetEnergyExaminedText(ent, magicContainer));
}
}

View File

@@ -1,4 +1,4 @@
using Content.Shared._CP14.MagicEnergy;
using Content.Shared._CP14.MagicEssence;
using Content.Shared._CP14.MagicSpell.Events;
using Content.Shared.Armor;
using Content.Shared.Chat;
@@ -30,9 +30,8 @@ public partial class InventorySystem
public void InitializeRelay()
{
//CP14 Relayed events
SubscribeLocalEvent<InventoryComponent, CP14MagicEnergyScanEvent>(RelayInventoryEvent);
SubscribeLocalEvent<InventoryComponent, CP14MagicEssenceScanEvent>(RelayInventoryEvent);
SubscribeLocalEvent<InventoryComponent, CP14CalculateManacostEvent>(RelayInventoryEvent);
//CP14 End
SubscribeLocalEvent<InventoryComponent, DamageModifyEvent>(RelayInventoryEvent);

View File

@@ -3,17 +3,20 @@ using Robust.Shared.Prototypes;
namespace Content.Shared._CP14.MagicRitual.Prototypes;
/// <summary>
/// A round-start setup preset, such as which antagonists to spawn.
/// Represents a type of magic
/// </summary>
[Prototype("magicType")]
public sealed partial class CP14MagicTypePrototype : IPrototype
public sealed class CP14MagicTypePrototype : IPrototype
{
[IdDataField]
public string ID { get; private set; } = default!;
[DataField(required: true)]
public string Name = string.Empty;
public LocId Name = string.Empty;
[DataField(required: true)]
public Color Color = Color.White;
[DataField]
public EntProtoId? EssenceProto;
}

View File

@@ -1,11 +0,0 @@
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
{
}

View File

@@ -55,7 +55,7 @@ public partial class SharedCP14MagicEnergySystem : EntitySystem
changedEnergy = 0;
overloadEnergy = 0;
if (!Resolve(uid, ref component))
if (!Resolve(uid, ref component, false))
return;
if (!safe)
@@ -178,9 +178,3 @@ public sealed class CP14MagicEnergyBurnOutEvent : EntityEventArgs
{
public FixedPoint2 BurnOutEnergy;
}
public sealed class CP14MagicEnergyScanEvent : EntityEventArgs, IInventoryRelayEvent
{
public bool CanScan;
public SlotFlags TargetSlots { get; } = SlotFlags.EYES;
}

View File

@@ -0,0 +1,16 @@
using Content.Shared._CP14.MagicRitual.Prototypes;
using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;
namespace Content.Shared._CP14.MagicEssence;
/// <summary>
/// Reflects the amount of essence stored in this item. The item can be destroyed to release the essence from it.
/// </summary>
[RegisterComponent, NetworkedComponent]
[Access(typeof(CP14MagicEssenceSystem))]
public sealed partial class CP14MagicEssenceContainerComponent : Component
{
[DataField]
public Dictionary<ProtoId<CP14MagicTypePrototype>, int> Essences = new();
}

View File

@@ -0,0 +1,11 @@
using Content.Shared._CP14.MagicEnergy;
namespace Content.Shared._CP14.MagicEssence;
/// <summary>
/// Allows you to see how much magic essence is stored in objects
/// </summary>
[RegisterComponent, Access(typeof(SharedCP14MagicEnergySystem))]
public sealed partial class CP14MagicEssenceScannerComponent : Component
{
}

View File

@@ -0,0 +1,22 @@
using Content.Shared.Whitelist;
using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;
namespace Content.Shared._CP14.MagicEssence;
/// <summary>
///
/// </summary>
[RegisterComponent, NetworkedComponent]
[Access(typeof(CP14MagicEssenceSystem))]
public sealed partial class CP14MagicEssenceSplitterComponent : Component
{
[DataField]
public EntProtoId ImpactEffect = "CP14EssenceSplitterImpactEffect";
[DataField]
public float ThrowForce = 10f;
[DataField]
public EntityWhitelist? Whitelist;
}

View File

@@ -0,0 +1,114 @@
using System.Text;
using Content.Shared._CP14.MagicEnergy;
using Content.Shared._CP14.MagicEnergy.Components;
using Content.Shared.Examine;
using Content.Shared.Inventory;
using Content.Shared.Throwing;
using Content.Shared.Whitelist;
using Robust.Shared.Network;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
namespace Content.Shared._CP14.MagicEssence;
public partial class CP14MagicEssenceSystem : EntitySystem
{
[Dependency] private readonly IPrototypeManager _proto = default!;
[Dependency] private readonly SharedTransformSystem _transform = default!;
[Dependency] private readonly EntityLookupSystem _lookup = default!;
[Dependency] private readonly ThrowingSystem _throwing = default!;
[Dependency] private readonly EntityWhitelistSystem _whitelist = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly INetManager _net = default!;
[Dependency] private readonly SharedCP14MagicEnergySystem _magicEnergy = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<CP14MagicEssenceContainerComponent, ExaminedEvent>(OnExamine);
SubscribeLocalEvent<CP14MagicEssenceScannerComponent, CP14MagicEssenceScanEvent>(OnMagicScanAttempt);
SubscribeLocalEvent<CP14MagicEssenceScannerComponent, InventoryRelayedEvent<CP14MagicEssenceScanEvent>>((e, c, ev) => OnMagicScanAttempt(e, c, ev.Args));
SubscribeLocalEvent<CP14MagicEssenceSplitterComponent, CP14MagicEnergyOverloadEvent>(OnEnergyOverload);
}
private void OnEnergyOverload(Entity<CP14MagicEssenceSplitterComponent> ent, ref CP14MagicEnergyOverloadEvent args)
{
if (!TryComp<CP14MagicEnergyContainerComponent>(ent, out var energyContainer))
return;
_magicEnergy.ChangeEnergy(ent, -energyContainer.Energy, out _, out _, energyContainer, safe: true);
//TODO move to server
if (_net.IsClient)
return;
var entities = _lookup.GetEntitiesInRange(ent, 0.5f, LookupFlags.Uncontained);
foreach (var entUid in entities)
{
var splitting = !(ent.Comp.Whitelist is not null && !_whitelist.IsValid(ent.Comp.Whitelist, entUid));
if (splitting)
TrySplitToEssence(entUid);
//Vector from splitter to item
var dir = (Transform(entUid).Coordinates.Position - Transform(ent).Coordinates.Position).Normalized() * ent.Comp.ThrowForce;
_throwing.TryThrow(entUid, dir, ent.Comp.ThrowForce);
}
SpawnAttachedTo(ent.Comp.ImpactEffect, Transform(ent).Coordinates);
}
private void OnMagicScanAttempt(EntityUid uid, CP14MagicEssenceScannerComponent component, CP14MagicEssenceScanEvent args)
{
args.CanScan = true;
}
private bool TrySplitToEssence(EntityUid uid)
{
if (!TryComp<CP14MagicEssenceContainerComponent>(uid, out var essenceContainer))
return false;
foreach (var essence in essenceContainer.Essences)
{
if (_proto.TryIndex(essence.Key, out var magicType))
{
for (var i = 0; i < essence.Value; i++)
{
var spawned = SpawnAtPosition(magicType.EssenceProto, Transform(uid).Coordinates);
_transform.AttachToGridOrMap(spawned);
}
}
}
QueueDel(uid);
return true;
}
private void OnExamine(Entity<CP14MagicEssenceContainerComponent> ent, ref ExaminedEvent args)
{
var scanEvent = new CP14MagicEssenceScanEvent();
RaiseLocalEvent(args.Examiner, scanEvent);
if (!scanEvent.CanScan)
return;
var sb = new StringBuilder();
sb.Append(Loc.GetString("cp14-magic-essence-title") + "\n");
foreach (var essence in ent.Comp.Essences)
{
if (_proto.TryIndex(essence.Key, out var magicType))
{
sb.Append($"[color={magicType.Color.ToHex()}]{Loc.GetString(magicType.Name)}[/color]: x{essence.Value}\n");
}
}
args.PushMarkup(sb.ToString());
}
}
public sealed class CP14MagicEssenceScanEvent : EntityEventArgs, IInventoryRelayEvent
{
public bool CanScan;
public SlotFlags TargetSlots { get; } = SlotFlags.EYES;
}

View File

@@ -1,11 +1,12 @@
cp14-magic-type-fire = Fire
cp14-magic-type-water = Water
cp14-magic-type-earth = Earth
cp14-magic-type-healing = Healing
cp14-magic-type-healing = Life
cp14-magic-type-light = Light
cp14-magic-type-dimension = Dimension
cp14-magic-type-meta = Metamagic
cp14-magic-type-necro = Necromancy
cp14-magic-type-death = Death
cp14-magic-manacost = Manacost
cp14-magic-magic-type = Magic type
cp14-magic-magic-type = Magic type
cp14-magic-essence-title = From here, essences can be extracted:

View File

@@ -1,11 +1,13 @@
cp14-magic-type-fire = Огонь
cp14-magic-type-water = Вода
cp14-magic-type-earth = Земля
cp14-magic-type-healing = Исцеление
cp14-magic-type-healing = Жизнь
cp14-magic-type-light = Свет
cp14-magic-type-dimension = Пространство
cp14-magic-type-meta = Метамагия
cp14-magic-type-necro = Некромантия
cp14-magic-type-death = Смерть
cp14-magic-type-electric = Молния
cp14-magic-manacost = Затраты маны
cp14-magic-magic-type = Тип магии
cp14-magic-magic-type = Тип магии
cp14-magic-essence-title = Отсюда можно извлечь эссенции:

View File

@@ -264,7 +264,7 @@
shiveringHeatRegulation: 2000
normalBodyTemperature: 310.15
thermalRegulationTemperatureThreshold: 25
- type: Perishable
#- type: Perishable #CP14 - disable rotting
- type: Butcherable
butcheringType: Spike # TODO human.
spawned:

View File

@@ -11,7 +11,7 @@
- type: CP14MagicEffectManaCost
manaCost: 100
- type: CP14MagicEffect
magicType: Necromancy
magicType: Death
telegraphyEffects:
- !type:CP14SpellSpawnEntityOnTarget
spawns:

View File

@@ -11,7 +11,7 @@
- type: CP14MagicEffectManaCost
manaCost: 10
- type: CP14MagicEffect
magicType: Healing
magicType: Life
telegraphyEffects:
- !type:CP14SpellSpawnEntityOnTarget
spawns:

View File

@@ -11,7 +11,7 @@
- type: CP14MagicEffectManaCost
manaCost: 10
- type: CP14MagicEffect
magicType: Healing
magicType: Life
telegraphyEffects:
- !type:CP14SpellSpawnEntityOnTarget
spawns:

View File

@@ -11,7 +11,7 @@
- type: CP14MagicEffectManaCost
manaCost: 10
- type: CP14MagicEffect
magicType: Healing
magicType: Life
telegraphyEffects:
- !type:CP14SpellSpawnEntityOnTarget
spawns:

View File

@@ -11,7 +11,7 @@
- type: CP14MagicEffectManaCost
manaCost: 5
- type: CP14MagicEffect
magicType: Healing
magicType: Life
effects:
- !type:CP14SpellSpawnEntityOnTarget
spawns:

View File

@@ -11,7 +11,7 @@
- type: CP14MagicEffectManaCost
manaCost: 5
- type: CP14MagicEffect
magicType: Healing
magicType: Life
effects:
- !type:CP14SpellSpawnEntityOnTarget
spawns:

View File

@@ -11,7 +11,7 @@
- type: CP14MagicEffectManaCost
manaCost: 5
- type: CP14MagicEffect
magicType: Healing
magicType: Life
telegraphyEffects:
- !type:CP14SpellSpawnEntityOnTarget
spawns:

View File

@@ -11,7 +11,7 @@
- type: CP14MagicEffectManaCost
manaCost: 5
- type: CP14MagicEffect
magicType: Healing
magicType: Life
effects:
- !type:CP14SpellSpawnEntityOnTarget
spawns:

View File

@@ -98,5 +98,5 @@
sprite: _CP14/Clothing/Eyes/thaumaturgy_glasses.rsi
- type: Clothing
sprite: _CP14/Clothing/Eyes/thaumaturgy_glasses.rsi
- type: CP14MagicEnergyScanner
- type: CP14MagicEssenceScanner

View File

@@ -35,6 +35,14 @@
restitution: 0.3 # fite me
friction: 0.2
- type: entity
parent: CP14BaseEssence
id: CP14EssenceEarth
name: earth essence
components:
- type: Sprite
color: "#70533f"
- type: entity
parent: CP14BaseEssence
id: CP14EssenceFire
@@ -45,11 +53,11 @@
- type: entity
parent: CP14BaseEssence
id: CP14EssenceEarth
name: earth essence
id: CP14EssenceLife
name: life essence
components:
- type: Sprite
color: "#70533f"
color: "#89e04f"
- type: entity
parent: CP14BaseEssence
@@ -69,8 +77,24 @@
- type: entity
parent: CP14BaseEssence
id: CP14EssenceDarkness
name: darkness essence
id: CP14EssenceDimension
name: dimension essence
components:
- type: Sprite
color: "#391c57"
color: "#391c57"
- type: entity
parent: CP14BaseEssence
id: CP14EssenceDeath
name: death essence
components:
- type: Sprite
color: "#55877a"
- type: entity
parent: CP14BaseEssence
id: CP14EssenceElectric
name: electric essence
components:
- type: Sprite
color: "#caed72"

View File

@@ -66,7 +66,7 @@
- CP14ActionSpellResurrection
- type: CP14MagicManacostModify
modifiers:
Healing: 1.4
Life: 1.4
- type: CP14MagicEnergyExaminable
- type: CP14MagicEnergyContainer
energy: 80

View File

@@ -35,14 +35,20 @@
components:
- type: Sprite
color: "#5eabeb"
- type: CP14MagicEssenceContainer
essences:
Water: 3
- type: entity
parent: CP14CrystalShardBase
id: CP14CrystalShardHealing
suffix: Healing
suffix: Life
components:
- type: Sprite
color: "#3de063"
- type: CP14MagicEssenceContainer
essences:
Life: 3
- type: entity
parent: CP14CrystalShardBase
@@ -51,6 +57,9 @@
components:
- type: Sprite
color: "#ed731c"
- type: CP14MagicEssenceContainer
essences:
Fire: 3
- type: entity
parent: CP14CrystalShardBase
@@ -59,6 +68,9 @@
components:
- type: Sprite
color: "#f1c7ff"
- type: CP14MagicEssenceContainer
essences:
Light: 3
- type: entity
parent: CP14CrystalShardBase
@@ -67,11 +79,17 @@
components:
- type: Sprite
color: "#e6ff6b"
- type: CP14MagicEssenceContainer
essences:
Electric: 3
- type: entity
parent: CP14CrystalShardBase
id: CP14CrystalShardDarkness
suffix: Darkness
suffix: Dimension
components:
- type: Sprite
color: "#391c57"
color: "#391c57"
- type: CP14MagicEssenceContainer
essences:
Dimension: 3

View File

@@ -6,10 +6,7 @@
name: solution normalizer
description: An alchemical device that removes fine precipitates from solutions, and stabilizes it for further work
categories: [ ForkFiltered ]
placement:
mode: PlaceFree
components:
# TODO: energy consuming (magic or fireplace)
- type: InteractionOutline
- type: Sprite
drawdepth: Items

View File

@@ -0,0 +1,60 @@
- type: entity
id: CP14EssenceSplitter
parent:
- BaseStructureDynamic
name: essence splitter
description: A device capable of splitting objects into magical essence when overloaded with energy.
categories: [ ForkFiltered ]
components:
- type: InteractionOutline
- type: Sprite
drawdepth: Items
noRot: true
offset: 0, 0.2
sprite: _CP14/Structures/Specific/Thaumaturgy/essence_splitter.rsi
layers:
- state: base
- type: Fixtures
fixtures:
fix1:
shape:
!type:PhysShapeAabb
bounds: "-0.25,-0.25,0.25,0.25"
density: 125
mask:
- TabletopMachineMask
- type: CP14MagicEnergyExaminable
- type: CP14MagicEnergyContainer
maxEnergy: 50
energy: 0
unsafeSupport: true
- type: CP14MagicEssenceSplitter
whitelist:
components:
- Item
- type: entity
id: CP14EssenceSplitterImpactEffect
name: essence splitter impact
categories: [ HideSpawnMenu ]
components:
- type: Sprite
drawdepth: Effects
noRot: true
offset: 0, 0.2
sprite: _CP14/Structures/Specific/Thaumaturgy/essence_splitter.rsi
layers:
- state: impact
shader: unshaded
- type: PointLight
radius: 1.5
- type: TimedDespawn
lifetime: 3.95
- type: EffectVisuals
- type: Tag
tags:
- HideContextMenu
- type: AnimationPlayer
- type: EmitSoundOnSpawn
sound:
path: /Audio/Magic/ethereal_enter.ogg

View File

@@ -2,26 +2,31 @@
id: Earth
name: cp14-magic-type-earth
color: "#70533f"
essenceProto: CP14EssenceEarth
- type: magicType
id: Fire
name: cp14-magic-type-fire
color: "#d9741c"
essenceProto: CP14EssenceFire
- type: magicType
id: Healing
id: Life
name: cp14-magic-type-healing
color: "#89e04f"
essenceProto: CP14EssenceLife
- type: magicType
id: Light
name: cp14-magic-type-light
color: "#ba97b8"
essenceProto: CP14EssenceLight
- type: magicType
id: Dimension
name: cp14-magic-type-dimension
color: "#4e0691"
essenceProto: CP14EssenceDimension
- type: magicType
id: Meta
@@ -32,8 +37,16 @@
id: Water
name: cp14-magic-type-water
color: "#1c94d9"
essenceProto: CP14EssenceWater
- type: magicType
id: Necromancy
name: cp14-magic-type-necro
color: "#55877a"
id: Death
name: cp14-magic-type-death
color: "#55877a"
essenceProto: CP14EssenceDeath
- type: magicType
id: Electric
name: cp14-magic-type-electric
color: "#caed72"
essenceProto: CP14EssenceElectric

Binary file not shown.

After

Width:  |  Height:  |  Size: 682 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@@ -0,0 +1,27 @@
{
"version": 1,
"license": "All right reserved",
"copyright": "Created by TheShuEd for CrystallEdge",
"size": {
"x": 32,
"y": 48
},
"states": [
{
"name": "base"
},
{
"name": "impact",
"delays": [
[
0.1,
0.2,
0.2,
0.2,
0.2,
3.3
]
]
}
]
}