Merge pull request #1516 from crystallpunk-14/ed-08-07-2025-shader-sea

Status effect spells
This commit is contained in:
Red
2025-07-09 09:16:49 +03:00
committed by GitHub
parent 668e79111c
commit 5b4440d18d
14 changed files with 282 additions and 42 deletions

View File

@@ -1,3 +1,5 @@
using Content.Shared.Damage;
using Content.Shared.Damage.Events;
using Content.Shared.StatusEffectNew.Components;
using Robust.Shared.Player;
@@ -7,6 +9,10 @@ public abstract partial class SharedStatusEffectsSystem
{
protected void InitializeRelay()
{
//CP14 Zone
SubscribeLocalEvent<StatusEffectContainerComponent, DamageModifyEvent>(RelayStatusEffectEvent);
//CP14 Zone end
SubscribeLocalEvent<StatusEffectContainerComponent, LocalPlayerAttachedEvent>(RelayStatusEffectEvent);
SubscribeLocalEvent<StatusEffectContainerComponent, LocalPlayerDetachedEvent>(RelayStatusEffectEvent);
}

View File

@@ -0,0 +1,29 @@
using Content.Shared.StatusEffectNew;
using Robust.Shared.Prototypes;
namespace Content.Shared._CP14.MagicSpell.Spells;
public sealed partial class CP14SpellApplyStatusEffect : CP14SpellEffect
{
[DataField(required: true)]
public EntProtoId StatusEffect = default;
[DataField(required: true)]
public TimeSpan Duration = TimeSpan.FromSeconds(1f);
[DataField]
public bool Refresh = true;
public override void Effect(EntityManager entManager, CP14SpellEffectBaseArgs args)
{
if (args.Target is null)
return;
var effectSys = entManager.System<SharedStatusEffectsSystem>();
if (!Refresh)
effectSys.TryAddStatusEffectDuration(args.Target.Value, StatusEffect, Duration);
else
effectSys.TrySetStatusEffectDuration(args.Target.Value, StatusEffect, Duration);
}
}

View File

@@ -0,0 +1,24 @@
using Content.Shared._CP14.MagicSpell.Spells;
using Robust.Shared.GameStates;
namespace Content.Shared._CP14.StatusEffect;
[RegisterComponent, NetworkedComponent, AutoGenerateComponentPause]
[Access(typeof(CP14ApplySpellStatusEffectSystem))]
public sealed partial class CP14ApplySpellStatusEffectComponent : Component
{
[DataField(serverOnly: true)]
public List<CP14SpellEffect> StartEffect = new();
[DataField(serverOnly: true)]
public List<CP14SpellEffect> EndEffect = new();
[DataField(serverOnly: true)]
public List<CP14SpellEffect> UpdateEffect = new();
[DataField]
public TimeSpan UpdateFrequency = TimeSpan.FromSeconds(1f);
[DataField, AutoPausedField]
public TimeSpan NextUpdateTime = TimeSpan.Zero;
}

View File

@@ -0,0 +1,74 @@
using Content.Shared._CP14.MagicSpell.Spells;
using Content.Shared.Damage;
using Content.Shared.StatusEffectNew;
using Content.Shared.StatusEffectNew.Components;
using Robust.Shared.Timing;
namespace Content.Shared._CP14.StatusEffect;
public sealed partial class CP14ApplySpellStatusEffectSystem : EntitySystem
{
[Dependency] private readonly IGameTiming _timing = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<CP14ApplySpellStatusEffectComponent, StatusEffectAppliedEvent>(SpellEffectApply);
SubscribeLocalEvent<CP14ApplySpellStatusEffectComponent, StatusEffectRemovedEvent>(SpellEffectRemove);
SubscribeLocalEvent<CP14DamageModifierStatusEffectComponent, StatusEffectRelayedEvent<DamageModifyEvent>>(OnDamageModify);
}
private void OnDamageModify(Entity<CP14DamageModifierStatusEffectComponent> ent, ref StatusEffectRelayedEvent<DamageModifyEvent> args)
{
DamageSpecifier newDamage = new();
foreach (var (type, damage) in args.Args.Damage.DamageDict)
{
var dmg = damage * ent.Comp.GlobalDefence;
if (ent.Comp.Defence is not null && ent.Comp.Defence.TryGetValue(type, out var typeDefence))
dmg *= typeDefence;
newDamage.DamageDict[type] = dmg;
}
args.Args.Damage = newDamage;
}
public override void Update(float frameTime)
{
base.Update(frameTime);
var query = EntityQueryEnumerator<CP14ApplySpellStatusEffectComponent, StatusEffectComponent>();
while (query.MoveNext(out var ent, out var spellEffect, out var statusEffect))
{
if (spellEffect.NextUpdateTime > _timing.CurTime)
continue;
if (statusEffect.AppliedTo is null)
continue;
spellEffect.NextUpdateTime += spellEffect.UpdateFrequency;
foreach (var effect in spellEffect.UpdateEffect)
{
effect.Effect(EntityManager, new CP14SpellEffectBaseArgs(null, null, statusEffect.AppliedTo, Transform(statusEffect.AppliedTo.Value).Coordinates));
}
}
}
private void SpellEffectApply(Entity<CP14ApplySpellStatusEffectComponent> ent, ref StatusEffectAppliedEvent args)
{
foreach (var effect in ent.Comp.StartEffect)
{
effect.Effect(EntityManager, new CP14SpellEffectBaseArgs(null, null, args.Target, Transform(args.Target).Coordinates));
}
}
private void SpellEffectRemove(Entity<CP14ApplySpellStatusEffectComponent> ent, ref StatusEffectRemovedEvent args)
{
foreach (var effect in ent.Comp.EndEffect)
{
effect.Effect(EntityManager, new CP14SpellEffectBaseArgs(null, null, args.Target, Transform(args.Target).Coordinates));
}
}
}

View File

@@ -0,0 +1,16 @@
using Content.Shared.Damage.Prototypes;
using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;
namespace Content.Shared._CP14.StatusEffect;
[RegisterComponent, NetworkedComponent]
[Access(typeof(CP14ApplySpellStatusEffectSystem))]
public sealed partial class CP14DamageModifierStatusEffectComponent : Component
{
[DataField]
public Dictionary<ProtoId<DamageTypePrototype>, float>? Defence = null;
[DataField]
public float GlobalDefence = 1f;
}

View File

@@ -0,0 +1,11 @@
- type: alert
id: CP14Glowing
icons:
- sprite: _CP14/Actions/Spells/light.rsi
state: sphere_of_light
- type: alert
id: CP14MagicArmor
icons:
- sprite: _CP14/Actions/Spells/meta.rsi
state: magic_armor

View File

@@ -15,9 +15,9 @@
- !type:CP14SpellSpawnEntityOnTarget
spawns:
- CP14ImpactEffectSphereOfLight
- !type:CP14SpellSpawnInHandEntity
spawns:
- CP14SphereOfLight
- !type:CP14SpellApplyStatusEffect
statusEffect: CP14StatusEffectGlowing
duration: 120
- type: CP14MagicEffectVerbalAspect
startSpeech: "Appare in manu tua..."
endSpeech: "sphaera lucis"
@@ -28,8 +28,15 @@
icon:
sprite: _CP14/Actions/Spells/light.rsi
state: sphere_of_light
- type: InstantAction
event: !type:CP14DelayedInstantActionEvent
- type: TargetAction
range: 5
- type: EntityTargetAction
whitelist:
components:
- MobState
- Item
- Anchorable
event: !type:CP14DelayedEntityTargetActionEvent
cooldown: 30
castDelay: 0.5
breakOnMove: false
@@ -60,43 +67,6 @@
color: "#efedff"
shader: unshaded
- type: entity
id: CP14SphereOfLight
name: Sphere of light
parent: BaseItem
description: A lump of bright light in the shape of a sphere.
categories: [ ForkFiltered ]
components:
- type: TimedDespawn
lifetime: 120 # 2 min
- type: Sprite
sprite: _CP14/Effects/Magic/sphere_of_light.rsi
noRot: true
layers:
- state: icon
shader: unshaded
- type: Item
size: Ginormous
inhandVisuals:
left:
- state: inhand-left-unshaded
shader: unshaded
right:
- state: inhand-right-unshaded
shader: unshaded
- type: LandAtCursor
- type: MovementIgnoreGravity
- type: PointLight
radius: 5.0
energy: 1
color: "#efedff"
- type: Damageable
- type: EmitSoundOnLand
sound:
path: /Audio/Effects/drop.ogg
params:
volume: -100 #Yes, it's stupid, but it's easier
- type: entity
parent: CP14BaseSpellScrollLight
id: CP14SpellScrollSphereOfLight

View File

@@ -0,0 +1,37 @@
- type: entity
id: CP14ActionSpellMagicArmor
parent: CP14ActionSpellBase
name: Magic Armor
description: You surround the target with a short-lived magical barrier that absorbs some of the damage it receives.
components:
- type: CP14MagicEffectCastSlowdown
speedMultiplier: 0.5
- type: CP14MagicEffectManaCost
manaCost: 15
- type: CP14MagicEffectCastingVisual
proto: CP14RuneManaTrance
- type: CP14MagicEffect
magicType: Fire
effects:
- !type:CP14SpellSpawnEntityOnTarget
spawns:
- CP14ImpactEffectManaGift
- !type:CP14SpellApplyStatusEffect
statusEffect: CP14StatusEffectMagicArmor
duration: 20
- type: Action
icon:
sprite: _CP14/Actions/Spells/meta.rsi
state: magic_armor
- type: TargetAction
range: 5
- type: EntityTargetAction
whitelist:
components:
- MobState
- Item
- Anchorable
event: !type:CP14DelayedEntityTargetActionEvent
cooldown: 10
castDelay: 1.0
breakOnMove: false

View File

@@ -0,0 +1,45 @@
- type: entity
id: CP14StatusEffectGlowing
components:
- type: StatusEffect
alert: CP14Glowing
- type: Sprite
drawdepth: Effects
sprite: _CP14/Effects/Magic/sphere_of_light.rsi
offset: 0, 1
noRot: true
layers:
- state: icon
shader: unshaded
- type: PointLight
radius: 5.0
energy: 1
color: "#efedff"
- type: entity
id: CP14StatusEffectMagicArmor
components:
- type: StatusEffect
alert: CP14MagicArmor
- type: Sprite
drawdepth: Mobs
sprite: _CP14/Effects/Magic/cast_rune.rsi
noRot: true
layers:
- state: sphere
shader: unshaded
color: "#5096d488"
- state: circle_increase
sprite: _CP14/Effects/Magic/cast_impact.rsi
shader: unshaded
color: "#74eaf222"
- type: PointLight
radius: 2.5
energy: 0.9
color: "#5096d4"
- type: CP14DamageModifierStatusEffect
globalDefence: 0.6
#defence: #TODO When stone armor spell appears, divide responsibilities: magical armor protects against elemental damage, stone armor protects against physical damage.
# Cold: 0.5
# Heat: 0.5
# Shock: 0.5

View File

@@ -153,6 +153,20 @@
- !type:NeedPrerequisite
prerequisite: MetamagicT2
- type: cp14Skill
id: CP14ActionSpellMagicArmor
skillUiPosition: 8, 4
tree: Metamagic
icon:
sprite: _CP14/Actions/Spells/meta.rsi
state: magic_armor
effects:
- !type:AddAction
action: CP14ActionSpellMagicArmor
restrictions:
- !type:NeedPrerequisite
prerequisite: MetamagicT2
# T3
- type: cp14Skill

Binary file not shown.

After

Width:  |  Height:  |  Size: 606 B

View File

@@ -13,6 +13,9 @@
{
"name": "counter_spell_small"
},
{
"name": "magic_armor"
},
{
"name": "magic_music"
},

View File

@@ -66,6 +66,17 @@
0.2
]
]
},
{
"name": "sphere",
"delays": [
[
0.2,
0.2,
0.2,
0.2
]
]
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB