From 50c502f598a7c1ee5f8a6a5dc75c494b075699d6 Mon Sep 17 00:00:00 2001 From: Ed <96445749+TheShuEd@users.noreply.github.com> Date: Fri, 17 Jan 2025 01:01:44 +0300 Subject: [PATCH] AOE Spells (#758) * AoE gameplay * Update T1_fire_rune.yml * test * add cool AoE visual --- .../CP14AreaEntityEffectComponent.cs | 27 +++++ .../_CP14/MagicSpell/CP14MagicSystem.cs | 28 ++++++ .../CP14SharedMagicSystem.DelayedActions.cs | 10 +- .../Actions/Spells/Fire/T1_fire_rune.yml | 94 ++++++++++++++++++ .../Magic/area_impact.rsi/area_impact_in.png | Bin 0 -> 3328 bytes .../Magic/area_impact.rsi/area_impact_out.png | Bin 0 -> 3366 bytes .../Effects/Magic/area_impact.rsi/meta.json | 37 +++++++ 7 files changed, 191 insertions(+), 5 deletions(-) create mode 100644 Content.Server/_CP14/MagicSpell/CP14AreaEntityEffectComponent.cs create mode 100644 Resources/Prototypes/_CP14/Entities/Actions/Spells/Fire/T1_fire_rune.yml create mode 100644 Resources/Textures/_CP14/Effects/Magic/area_impact.rsi/area_impact_in.png create mode 100644 Resources/Textures/_CP14/Effects/Magic/area_impact.rsi/area_impact_out.png create mode 100644 Resources/Textures/_CP14/Effects/Magic/area_impact.rsi/meta.json diff --git a/Content.Server/_CP14/MagicSpell/CP14AreaEntityEffectComponent.cs b/Content.Server/_CP14/MagicSpell/CP14AreaEntityEffectComponent.cs new file mode 100644 index 0000000000..0e5959d85d --- /dev/null +++ b/Content.Server/_CP14/MagicSpell/CP14AreaEntityEffectComponent.cs @@ -0,0 +1,27 @@ +using Content.Shared._CP14.MagicSpell.Spells; +using Content.Shared.Whitelist; +using Robust.Shared.Prototypes; + +namespace Content.Server._CP14.MagicSpell; + +/// +/// +/// +[RegisterComponent] +public sealed partial class CP14AreaEntityEffectComponent : Component +{ + [DataField(required: true)] + public float Range = 1f; + + /// + /// How many entities can be subject to EntityEffect? Leave 0 to remove the restriction. + /// + [DataField] + public int MaxTargets = 0; + + [DataField(required: true, serverOnly: true)] + public List Effects = new(); + + [DataField] + public EntityWhitelist? Whitelist; +} diff --git a/Content.Server/_CP14/MagicSpell/CP14MagicSystem.cs b/Content.Server/_CP14/MagicSpell/CP14MagicSystem.cs index 6bbda67805..c8a451b35f 100644 --- a/Content.Server/_CP14/MagicSpell/CP14MagicSystem.cs +++ b/Content.Server/_CP14/MagicSpell/CP14MagicSystem.cs @@ -4,6 +4,9 @@ using Content.Shared._CP14.MagicEnergy.Components; using Content.Shared._CP14.MagicSpell; using Content.Shared._CP14.MagicSpell.Components; using Content.Shared._CP14.MagicSpell.Events; +using Content.Shared._CP14.MagicSpell.Spells; +using Content.Shared.EntityEffects; +using Content.Shared.Whitelist; using Robust.Server.GameObjects; namespace Content.Server._CP14.MagicSpell; @@ -13,11 +16,14 @@ public sealed partial class CP14MagicSystem : CP14SharedMagicSystem [Dependency] private readonly ChatSystem _chat = default!; [Dependency] private readonly TransformSystem _transform = default!; [Dependency] private readonly CP14MagicEnergySystem _magicEnergy = default!; + [Dependency] private readonly EntityLookupSystem _lookup = default!; + [Dependency] private readonly EntityWhitelistSystem _whitelist = default!; public override void Initialize() { base.Initialize(); + SubscribeLocalEvent(OnAoEMapInit); SubscribeLocalEvent(OnSpellSpoken); SubscribeLocalEvent(OnSpawnMagicVisualEffect); @@ -26,6 +32,28 @@ public sealed partial class CP14MagicSystem : CP14SharedMagicSystem SubscribeLocalEvent(OnManaConsume); } + private void OnAoEMapInit(Entity ent, ref MapInitEvent args) + { + var entitiesAround = _lookup.GetEntitiesInRange(ent, ent.Comp.Range, LookupFlags.Uncontained); + + var count = 0; + foreach (var entity in entitiesAround) + { + if (ent.Comp.Whitelist is not null && !_whitelist.IsValid(ent.Comp.Whitelist, entity)) + continue; + + foreach (var effect in ent.Comp.Effects) + { + effect.Effect(EntityManager, new CP14SpellEffectBaseArgs(ent, null, entity, Transform(entity).Coordinates)); + } + + count++; + + if (ent.Comp.MaxTargets > 0 && count >= ent.Comp.MaxTargets) + break; + } + } + private void OnSpellSpoken(Entity ent, ref CP14VerbalAspectSpeechEvent args) { if (args.Performer is not null && args.Speech is not null) diff --git a/Content.Shared/_CP14/MagicSpell/CP14SharedMagicSystem.DelayedActions.cs b/Content.Shared/_CP14/MagicSpell/CP14SharedMagicSystem.DelayedActions.cs index 5d2339fe8b..3ca6d055a3 100644 --- a/Content.Shared/_CP14/MagicSpell/CP14SharedMagicSystem.DelayedActions.cs +++ b/Content.Shared/_CP14/MagicSpell/CP14SharedMagicSystem.DelayedActions.cs @@ -56,7 +56,7 @@ public abstract partial class CP14SharedMagicSystem _action.CP14StartCustomDelay(action, TimeSpan.FromSeconds(cooldown.Value)); } - private void UseDelayedAction(ICP14DelayedMagicEffect delayedEffect, Entity action, DoAfterEvent doAfter, EntityUid performer) + private void UseDelayedAction(ICP14DelayedMagicEffect delayedEffect, Entity action, DoAfterEvent doAfter, EntityUid performer, EntityUid? target = null, EntityCoordinates? worldTarget = null) { if (!CanCastSpell(action, performer)) return; @@ -71,7 +71,7 @@ public abstract partial class CP14SharedMagicSystem RaiseLocalEvent(action, ref evStart); var spellArgs = - new CP14SpellEffectBaseArgs(performer, action.Comp.SpellStorage, performer, Transform(performer).Coordinates); + new CP14SpellEffectBaseArgs(performer, action.Comp.SpellStorage, target, worldTarget); CastTelegraphy(action, spellArgs); } @@ -93,7 +93,7 @@ public abstract partial class CP14SharedMagicSystem return; var doAfter = new CP14DelayedInstantActionDoAfterEvent(args.Cooldown); - UseDelayedAction(delayedEffect, (args.Action, magicEffect), doAfter, args.Performer); + UseDelayedAction(delayedEffect, (args.Action, magicEffect), doAfter, args.Performer, args.Performer); args.Handled = true; } @@ -116,7 +116,7 @@ public abstract partial class CP14SharedMagicSystem EntityManager.GetNetCoordinates(args.Coords), EntityManager.GetNetEntity(args.Entity), args.Cooldown); - UseDelayedAction(delayedEffect, (args.Action, magicEffect), doAfter, args.Performer); + UseDelayedAction(delayedEffect, (args.Action, magicEffect), doAfter, args.Performer, args.Entity, args.Coords); args.Handled = true; } @@ -136,7 +136,7 @@ public abstract partial class CP14SharedMagicSystem return; var doAfter = new CP14DelayedEntityTargetActionDoAfterEvent(EntityManager.GetNetEntity(args.Target), args.Cooldown); - UseDelayedAction(delayedEffect, (args.Action, magicEffect), doAfter, args.Performer); + UseDelayedAction(delayedEffect, (args.Action, magicEffect), doAfter, args.Performer, args.Target); args.Handled = true; } diff --git a/Resources/Prototypes/_CP14/Entities/Actions/Spells/Fire/T1_fire_rune.yml b/Resources/Prototypes/_CP14/Entities/Actions/Spells/Fire/T1_fire_rune.yml new file mode 100644 index 0000000000..57c69314f6 --- /dev/null +++ b/Resources/Prototypes/_CP14/Entities/Actions/Spells/Fire/T1_fire_rune.yml @@ -0,0 +1,94 @@ +- type: entity + id: CP14ActionSpellFireRune + name: Fire rune + description: You create an area where a scalding stream of fire occurs with little delay. + components: + - type: Sprite + sprite: _CP14/Effects/Magic/spells_icons.rsi + state: earth_wall + - type: CP14MagicEffectCastSlowdown + speedMultiplier: 0.5 + - type: CP14MagicEffectManaCost + manaCost: 15 + - type: CP14MagicEffect + magicType: Fire + telegraphyEffects: + - !type:CP14SpellSpawnEntityOnTarget + spawns: + - CP14TelegraphyFireRune + effects: + - !type:CP14SpellSpawnEntityOnTarget + spawns: + - CP14AreaEntityEffectFireRune + - type: CP14MagicEffectCastingVisual + proto: CP14RuneEarthWall + - type: EntityWorldTargetAction + range: 10 + itemIconStyle: BigAction + sound: !type:SoundPathSpecifier + path: /Audio/Magic/rumble.ogg + icon: + sprite: _CP14/Effects/Magic/spells_icons.rsi + state: earth_wall + event: !type:CP14DelayedEntityWorldTargetActionEvent + cooldown: 10 + +- type: entity + id: CP14TelegraphyFireRune + parent: CP14BaseMagicImpact + components: + - type: PointLight + color: "#eea911" + - type: TimedDespawn + lifetime: 0.8 + - type: Sprite + noRot: true + drawdepth: BelowFloor + sprite: _CP14/Effects/Magic/area_impact.rsi + layers: + - state: area_impact_in + color: "#eea911" + scale: 2, 2 + shader: unshaded + +- type: entity + id: CP14AreaEntityEffectFireRune + parent: CP14BaseMagicImpact + components: + - type: PointLight + color: "#eea911" + - type: Sprite + noRot: true + drawdepth: BelowFloor + sprite: _CP14/Effects/Magic/area_impact.rsi + layers: + - state: area_impact_out + color: "#eea911" + scale: 2, 2 + shader: unshaded + - type: TimedDespawn + lifetime: 0.8 + - type: CP14AreaEntityEffect + range: 1 + whitelist: + components: + - Damageable + effects: + - !type:CP14SpellSpawnEntityOnTarget + spawns: + - CP14ImpactEffectTieflingRevenge + - !type:CP14SpellApplyEntityEffect + effects: + - !type:HealthChange + damage: + types: + Heat: 10 + +- type: entity + parent: CP14BaseSpellScrollFire + id: CP14SpellScrollFireRune + name: fire rune spell scroll + components: + - type: CP14SpellStorage + spells: + - CP14ActionSpellFireRune \ No newline at end of file diff --git a/Resources/Textures/_CP14/Effects/Magic/area_impact.rsi/area_impact_in.png b/Resources/Textures/_CP14/Effects/Magic/area_impact.rsi/area_impact_in.png new file mode 100644 index 0000000000000000000000000000000000000000..3773311ddd67347035c142679d50dd5b748b1212 GIT binary patch literal 3328 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 ZbU7n6Rt7%g+>1y9urReYX)^Lk{2y9UOFaMp literal 0 HcmV?d00001 diff --git a/Resources/Textures/_CP14/Effects/Magic/area_impact.rsi/area_impact_out.png b/Resources/Textures/_CP14/Effects/Magic/area_impact.rsi/area_impact_out.png new file mode 100644 index 0000000000000000000000000000000000000000..f707361eaf134d76a572eea771ff6ae9630d39ab GIT binary patch literal 3366 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 C^qkKC literal 0 HcmV?d00001 diff --git a/Resources/Textures/_CP14/Effects/Magic/area_impact.rsi/meta.json b/Resources/Textures/_CP14/Effects/Magic/area_impact.rsi/meta.json new file mode 100644 index 0000000000..948de02946 --- /dev/null +++ b/Resources/Textures/_CP14/Effects/Magic/area_impact.rsi/meta.json @@ -0,0 +1,37 @@ +{ + "version": 1, + "size": { + "x": 64, + "y": 64 + }, + "license": "CLA", + "copyright": "Created by TheShuEd", + "states": [ + { + "name": "area_impact_in", + "delays": [ + [ + 0.15, + 0.15, + 0.15, + 0.15, + 0.15, + 1.1 + ] + ] + }, + { + "name": "area_impact_out", + "delays": [ + [ + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 1.1 + ] + ] + } + ] +}