diff --git a/Content.Server/_CP14/Magic/Container/MagickSpellContainerComponent.cs b/Content.Server/_CP14/Magic/Container/MagickSpellContainerComponent.cs new file mode 100644 index 0000000000..5465064be6 --- /dev/null +++ b/Content.Server/_CP14/Magic/Container/MagickSpellContainerComponent.cs @@ -0,0 +1,10 @@ +using Robust.Shared.Prototypes; + +namespace Content.Server._CP14.Magic.Container; + +[RegisterComponent] +public sealed partial class MagicSpellContainerComponent : Component +{ + [DataField] + public List> Spells = new(); +} diff --git a/Content.Server/_CP14/Magic/Container/MagickSpellContainerSystem.cs b/Content.Server/_CP14/Magic/Container/MagickSpellContainerSystem.cs new file mode 100644 index 0000000000..228d0464e8 --- /dev/null +++ b/Content.Server/_CP14/Magic/Container/MagickSpellContainerSystem.cs @@ -0,0 +1,11 @@ +namespace Content.Server._CP14.Magic.Container; + +public sealed class MagickSpellContainerSystem : EntitySystem +{ + [Dependency] private readonly MagicSpellSystem _magicSpell = default!; + + public void CastSpell(Entity container) + { + _magicSpell.Cast(container, container.Comp.Spells); + } +} diff --git a/Content.Server/_CP14/Magic/MagicSpell.cs b/Content.Server/_CP14/Magic/MagicSpell.cs new file mode 100644 index 0000000000..a4fd56e4f0 --- /dev/null +++ b/Content.Server/_CP14/Magic/MagicSpell.cs @@ -0,0 +1,20 @@ +namespace Content.Server._CP14.Magic; + +[Serializable, DataDefinition] +public abstract class MagicSpell +{ + protected readonly IEntityManager EntityManager; + + public MagicSpell() + { + EntityManager = IoCManager.Resolve(); + } + + [DataField] + public virtual int BaseCost { get; set; } = 10; + + public virtual void Modify(MagicSpellContext context) + { + context.Cost += BaseCost; + } +} diff --git a/Content.Server/_CP14/Magic/MagicSpellContext.cs b/Content.Server/_CP14/Magic/MagicSpellContext.cs new file mode 100644 index 0000000000..2299fc4089 --- /dev/null +++ b/Content.Server/_CP14/Magic/MagicSpellContext.cs @@ -0,0 +1,14 @@ +using Robust.Shared.Map; + +namespace Content.Server._CP14.Magic; + +public sealed class MagicSpellContext +{ + public EntityUid Caster; + + public MapCoordinates SourcePoint; + public MapCoordinates TargetPoint; + + public int MaxCost = 100; + public int Cost; +} diff --git a/Content.Server/_CP14/Magic/MagicSpellPrototype.cs b/Content.Server/_CP14/Magic/MagicSpellPrototype.cs new file mode 100644 index 0000000000..8945a39a19 --- /dev/null +++ b/Content.Server/_CP14/Magic/MagicSpellPrototype.cs @@ -0,0 +1,13 @@ +using Robust.Shared.Prototypes; + +namespace Content.Server._CP14.Magic; + +[Prototype("magicSpell")] +public sealed class MagicSpellPrototype : IPrototype +{ + [IdDataField] + public string ID { get; } = string.Empty; + + [DataField] + public required MagicSpell Action; +} diff --git a/Content.Server/_CP14/Magic/MagicSpellSystem.cs b/Content.Server/_CP14/Magic/MagicSpellSystem.cs new file mode 100644 index 0000000000..e8dff1f5b9 --- /dev/null +++ b/Content.Server/_CP14/Magic/MagicSpellSystem.cs @@ -0,0 +1,60 @@ +using System.Runtime.CompilerServices; +using Robust.Server.GameObjects; +using Robust.Shared.Prototypes; + +namespace Content.Server._CP14.Magic; + +public sealed class MagicSpellSystem : EntitySystem +{ + [Robust.Shared.IoC.Dependency] private readonly IPrototypeManager _prototype = default!; + [Robust.Shared.IoC.Dependency] private readonly TransformSystem _transform = default!; + + public IReadOnlyDictionary, MagicSpellPrototype> Spells => _spells; + + private readonly Dictionary, MagicSpellPrototype> _spells = new(); + + public override void Initialize() + { + base.Initialize(); + + Enumerate(); + _prototype.PrototypesReloaded += OnProtoReload; + } + + public void Cast(EntityUid caster, IReadOnlyList> spells) + { + var casterPosition = _transform.GetMapCoordinates(caster); + + var context = new MagicSpellContext + { + SourcePoint = casterPosition, + TargetPoint = casterPosition + }; + + foreach (var spellProto in spells) + { + if (!Spells.TryGetValue(spellProto, out var spell)) + continue; + + spell.Action.Modify(context); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private void Enumerate() + { + var prototypes = _prototype.EnumeratePrototypes(); + foreach (var prototype in prototypes) + { + _spells.Add(prototype.ID, prototype); + } + } + + private void OnProtoReload(PrototypesReloadedEventArgs args) + { + if (!args.WasModified()) + return; + + Enumerate(); + } +} diff --git a/Content.Server/_CP14/Magic/Spells/MagicSpellPointRandomMob.cs b/Content.Server/_CP14/Magic/Spells/MagicSpellPointRandomMob.cs new file mode 100644 index 0000000000..cec6e2c670 --- /dev/null +++ b/Content.Server/_CP14/Magic/Spells/MagicSpellPointRandomMob.cs @@ -0,0 +1,44 @@ +using Content.Shared.Mobs.Components; +using Robust.Server.GameObjects; +using Robust.Shared.Map; +using Robust.Shared.Random; + +namespace Content.Server._CP14.Magic.Spells; + +[Serializable, DataDefinition] +public abstract class MagicSpellPointRandomMob : MagicSpell +{ + private readonly EntityLookupSystem _entityLookupSystem; + private readonly IRobustRandom _random; + private readonly TransformSystem _transform; + + [DataField] + public virtual float Range { get; set; } = 5f; + + [DataField] + public override int BaseCost { get; set; } = 50; + + public MagicSpellPointRandomMob() + { + _entityLookupSystem = EntityManager.System(); + _transform = EntityManager.System(); + + _random = IoCManager.Resolve(); + } + + public override void Modify(MagicSpellContext context) + { + base.Modify(context); + + var targets = _entityLookupSystem.GetEntitiesInRange(context.SourcePoint, Range); + if (targets.Count == 0) + return; + + var target = _random.Pick(targets); + var coordinates = _transform.GetMapCoordinates(target); + + ApplyCoordinates(context, coordinates); + } + + public abstract void ApplyCoordinates(MagicSpellContext context, MapCoordinates coordinates); +} diff --git a/Content.Server/_CP14/Magic/Spells/SourcePoint/MagicSpellSourcePointRandomMob.cs b/Content.Server/_CP14/Magic/Spells/SourcePoint/MagicSpellSourcePointRandomMob.cs new file mode 100644 index 0000000000..cc5af26af0 --- /dev/null +++ b/Content.Server/_CP14/Magic/Spells/SourcePoint/MagicSpellSourcePointRandomMob.cs @@ -0,0 +1,12 @@ +using Robust.Shared.Map; + +namespace Content.Server._CP14.Magic.Spells.SourcePoint; + +[Serializable, DataDefinition] +public sealed partial class MagicSpellSourcePointRandomMob : MagicSpellPointRandomMob +{ + public override void ApplyCoordinates(MagicSpellContext context, MapCoordinates coordinates) + { + context.SourcePoint = coordinates; + } +} diff --git a/Content.Server/_CP14/Magic/Spells/TargetPoint/MagicSpellTargetPointRandomMob.cs b/Content.Server/_CP14/Magic/Spells/TargetPoint/MagicSpellTargetPointRandomMob.cs new file mode 100644 index 0000000000..3ee1b90868 --- /dev/null +++ b/Content.Server/_CP14/Magic/Spells/TargetPoint/MagicSpellTargetPointRandomMob.cs @@ -0,0 +1,12 @@ +using Robust.Shared.Map; + +namespace Content.Server._CP14.Magic.Spells.TargetPoint; + +[Serializable, DataDefinition] +public sealed class MagicSpellTargetPointRandomMob : MagicSpellPointRandomMob +{ + public override void ApplyCoordinates(MagicSpellContext context, MapCoordinates coordinates) + { + context.TargetPoint = coordinates; + } +} diff --git a/Resources/Prototypes/_CP14/MagickSpells/source_point.yml b/Resources/Prototypes/_CP14/MagickSpells/source_point.yml new file mode 100644 index 0000000000..5df3c24b6a --- /dev/null +++ b/Resources/Prototypes/_CP14/MagickSpells/source_point.yml @@ -0,0 +1,7 @@ +- type: magicSpell + id: sourcePointRandomMob + action: + !type:MagicSpellSourcePointRandomMob + range: 5 + baseCost: 25 +