Some shit (#380)

* telegraphy effects

* shadow step spell backend

* add component spell

* predict sharpening

* Update ring.yml

* locale sync

* Update entities.ftl

* icon shadow step
This commit is contained in:
Ed
2024-08-02 13:51:54 +03:00
committed by GitHub
parent 31c9485e3b
commit 599c599a4e
22 changed files with 410 additions and 171 deletions

View File

@@ -36,6 +36,10 @@ public partial class CP14SharedMagicSystem : EntitySystem
SubscribeLocalEvent<CP14MagicEffectComponent, CP14BeforeCastMagicEffectEvent>(OnBeforeCastMagicEffect);
SubscribeLocalEvent<CP14DelayedInstantActionEvent>(OnInstantAction);
SubscribeLocalEvent<CP14DelayedEntityTargetActionEvent>(OnEntityTargetAction);
SubscribeLocalEvent<CP14DelayedWorldTargetActionEvent>(OnWorldTargetAction);
SubscribeLocalEvent<CP14MagicEffectComponent, CP14DelayedInstantActionDoAfterEvent>(OnDelayedInstantActionDoAfter);
SubscribeLocalEvent<CP14MagicEffectComponent, CP14DelayedEntityTargetActionDoAfterEvent>(OnDelayedEntityTargetDoAfter);
SubscribeLocalEvent<CP14MagicEffectComponent, CP14DelayedWorldTargetActionDoAfterEvent>(OnDelayedWorldTargetDoAfter);
@@ -47,15 +51,132 @@ public partial class CP14SharedMagicSystem : EntitySystem
SubscribeLocalEvent<CP14MagicEffectComponent, CP14AfterCastMagicEffectEvent>(OnAfterCastMagicEffect);
SubscribeLocalEvent<CP14DelayedInstantActionEvent>(OnInstantAction);
SubscribeLocalEvent<CP14DelayedEntityTargetActionEvent>(OnEntityTargetAction);
SubscribeLocalEvent<CP14DelayedWorldTargetActionEvent>(OnWorldTargetAction);
}
private void OnBeforeCastMagicEffect(Entity<CP14MagicEffectComponent> ent, ref CP14BeforeCastMagicEffectEvent args)
{
if (!TryComp<CP14MagicEnergyContainerComponent>(args.Performer, out var magicContainer))
{
args.Cancel();
return;
}
if (!_magicEnergy.HasEnergy(args.Performer, ent.Comp.ManaCost, magicContainer, ent.Comp.Safe))
{
args.PushReason(Loc.GetString("cp14-magic-spell-not-enough-mana"));
args.Cancel();
}
else if(!_magicEnergy.HasEnergy(args.Performer, ent.Comp.ManaCost, magicContainer, true) && _net.IsServer)
{
_popup.PopupEntity(Loc.GetString("cp14-magic-spell-not-enough-mana-cast-warning-"+_random.Next(5)), args.Performer, args.Performer, PopupType.SmallCaution);
}
}
private void OnInstantAction(CP14DelayedInstantActionEvent args)
{
if (args.Handled)
return;
args.Handled = true;
if (args is not ICP14DelayedMagicEffect delayedEffect)
return;
if (!TryCastSpell(args.Action, args.Performer))
return;
var doAfterEventArgs = new DoAfterArgs(EntityManager, args.Performer, delayedEffect.Delay, new CP14DelayedInstantActionDoAfterEvent(), args.Action)
{
BreakOnMove = delayedEffect.BreakOnMove,
BreakOnDamage = delayedEffect.BreakOnDamage,
BlockDuplicate = true,
};
_doAfter.TryStartDoAfter(doAfterEventArgs);
//Telegraphy effects
if (_net.IsServer && TryComp<CP14MagicEffectComponent>(args.Action, out var magicEffect))
{
foreach (var effect in magicEffect.TelegraphyEffects)
{
effect.Effect(EntityManager, new CP14SpellEffectBaseArgs(args.Performer, args.Performer, Transform(args.Performer).Coordinates));
}
}
}
private void OnWorldTargetAction(CP14DelayedWorldTargetActionEvent args)
{
if (args.Handled)
return;
args.Handled = true;
if (args is not ICP14DelayedMagicEffect delayedEffect)
return;
if (!TryCastSpell(args.Action, args.Performer))
return;
var doAfter = new CP14DelayedWorldTargetActionDoAfterEvent()
{
Target = EntityManager.GetNetCoordinates(args.Target)
};
var doAfterEventArgs = new DoAfterArgs(EntityManager, args.Performer, delayedEffect.Delay, doAfter, args.Action)
{
BreakOnMove = delayedEffect.BreakOnMove,
BreakOnDamage = delayedEffect.BreakOnDamage,
BlockDuplicate = true,
};
_doAfter.TryStartDoAfter(doAfterEventArgs);
//Telegraphy effects
if (_net.IsServer && TryComp<CP14MagicEffectComponent>(args.Action, out var magicEffect))
{
foreach (var effect in magicEffect.TelegraphyEffects)
{
effect.Effect(EntityManager, new CP14SpellEffectBaseArgs(args.Performer, null, args.Target));
}
}
}
private void OnEntityTargetAction(CP14DelayedEntityTargetActionEvent args)
{
if (args.Handled)
return;
args.Handled = true;
if (args is not ICP14DelayedMagicEffect delayedEffect)
return;
if (!TryCastSpell(args.Action, args.Performer))
return;
var doAfterEventArgs = new DoAfterArgs(EntityManager, args.Performer, delayedEffect.Delay, new CP14DelayedEntityTargetActionDoAfterEvent(), args.Action, args.Target)
{
BreakOnMove = delayedEffect.BreakOnMove,
BreakOnDamage = delayedEffect.BreakOnDamage,
BlockDuplicate = true,
};
_doAfter.TryStartDoAfter(doAfterEventArgs);
//Telegraphy effects
if (_net.IsServer && TryComp<CP14MagicEffectComponent>(args.Action, out var magicEffect))
{
foreach (var effect in magicEffect.TelegraphyEffects)
{
effect.Effect(EntityManager, new CP14SpellEffectBaseArgs(args.Performer, args.Target, null));
}
}
}
private void OnDelayedWorldTargetDoAfter(Entity<CP14MagicEffectComponent> ent, ref CP14DelayedWorldTargetActionDoAfterEvent args)
{
var stopEv = new CP14StopCastMagicEffectEvent();
RaiseLocalEvent(ent, ref stopEv);
var endEv = new CP14EndCastMagicEffectEvent();
RaiseLocalEvent(ent, ref endEv);
if (args.Cancelled || !_net.IsServer)
return;
@@ -71,8 +192,8 @@ public partial class CP14SharedMagicSystem : EntitySystem
private void OnDelayedEntityTargetDoAfter(Entity<CP14MagicEffectComponent> ent, ref CP14DelayedEntityTargetActionDoAfterEvent args)
{
var stopEv = new CP14StopCastMagicEffectEvent();
RaiseLocalEvent(ent, ref stopEv);
var endEv = new CP14EndCastMagicEffectEvent();
RaiseLocalEvent(ent, ref endEv);
if (args.Cancelled || !_net.IsServer)
return;
@@ -88,8 +209,8 @@ public partial class CP14SharedMagicSystem : EntitySystem
private void OnDelayedInstantActionDoAfter(Entity<CP14MagicEffectComponent> ent, ref CP14DelayedInstantActionDoAfterEvent args)
{
var stopEv = new CP14StopCastMagicEffectEvent();
RaiseLocalEvent(ent, ref stopEv);
var endEv = new CP14EndCastMagicEffectEvent();
RaiseLocalEvent(ent, ref endEv);
if (args.Cancelled || !_net.IsServer)
return;
@@ -154,80 +275,6 @@ public partial class CP14SharedMagicSystem : EntitySystem
RaiseLocalEvent(ent, ref ev);
}
private void OnInstantAction(CP14DelayedInstantActionEvent args)
{
if (args.Handled)
return;
args.Handled = true;
if (args is not ICP14DelayedMagicEffect delayedEffect)
return;
if (!TryCastSpell(args.Action, args.Performer))
return;
var doAfterEventArgs = new DoAfterArgs(EntityManager, args.Performer, delayedEffect.Delay, new CP14DelayedInstantActionDoAfterEvent(), args.Action)
{
BreakOnMove = delayedEffect.BreakOnMove,
BreakOnDamage = delayedEffect.BreakOnDamage,
BlockDuplicate = true,
};
_doAfter.TryStartDoAfter(doAfterEventArgs);
}
private void OnWorldTargetAction(CP14DelayedWorldTargetActionEvent args)
{
if (args.Handled)
return;
args.Handled = true;
if (args is not ICP14DelayedMagicEffect delayedEffect)
return;
if (!TryCastSpell(args.Action, args.Performer))
return;
var doAfter = new CP14DelayedWorldTargetActionDoAfterEvent()
{
Target = EntityManager.GetNetCoordinates(args.Target)
};
var doAfterEventArgs = new DoAfterArgs(EntityManager, args.Performer, delayedEffect.Delay, doAfter, args.Action)
{
BreakOnMove = delayedEffect.BreakOnMove,
BreakOnDamage = delayedEffect.BreakOnDamage,
BlockDuplicate = true,
};
_doAfter.TryStartDoAfter(doAfterEventArgs);
}
private void OnEntityTargetAction(CP14DelayedEntityTargetActionEvent args)
{
if (args.Handled)
return;
args.Handled = true;
if (args is not ICP14DelayedMagicEffect delayedEffect)
return;
if (!TryCastSpell(args.Action, args.Performer))
return;
var doAfterEventArgs = new DoAfterArgs(EntityManager, args.Performer, delayedEffect.Delay, new CP14DelayedEntityTargetActionDoAfterEvent(), args.Action, args.Target)
{
BreakOnMove = delayedEffect.BreakOnMove,
BreakOnDamage = delayedEffect.BreakOnDamage,
BlockDuplicate = true,
};
_doAfter.TryStartDoAfter(doAfterEventArgs);
}
private bool TryCastSpell(EntityUid spell, EntityUid performer)
{
var ev = new CP14BeforeCastMagicEffectEvent
@@ -251,25 +298,6 @@ public partial class CP14SharedMagicSystem : EntitySystem
return !ev.Cancelled;
}
private void OnBeforeCastMagicEffect(Entity<CP14MagicEffectComponent> ent, ref CP14BeforeCastMagicEffectEvent args)
{
if (!TryComp<CP14MagicEnergyContainerComponent>(args.Performer, out var magicContainer))
{
args.Cancel();
return;
}
if (!_magicEnergy.HasEnergy(args.Performer, ent.Comp.ManaCost, magicContainer, ent.Comp.Safe))
{
args.PushReason(Loc.GetString("cp14-magic-spell-not-enough-mana"));
args.Cancel();
}
else if(!_magicEnergy.HasEnergy(args.Performer, ent.Comp.ManaCost, magicContainer, true) && _net.IsServer)
{
_popup.PopupEntity(Loc.GetString("cp14-magic-spell-not-enough-mana-cast-warning-"+_random.Next(5)), args.Performer, args.Performer, PopupType.SmallCaution);
}
}
private void OnAfterCastMagicEffect(Entity<CP14MagicEffectComponent> ent, ref CP14AfterCastMagicEffectEvent args)
{
if (_net.IsClient)

View File

@@ -15,6 +15,12 @@ public sealed partial class CP14MagicEffectComponent : Component
[DataField]
public bool Safe = false;
/// <summary>
/// Effects that will trigger at the beginning of the cast, before mana is spent. Should have no gameplay importance, just special effects, popups and sounds.
/// </summary>
[DataField]
public List<CP14SpellEffect> TelegraphyEffects = new();
[DataField]
public List<CP14SpellEffect> Effects = new();
}

View File

@@ -34,7 +34,7 @@ public sealed class CP14StartCastMagicEffectEvent : EntityEventArgs
/// is invoked on the spell itself when the spell process has been completed or interrupted
/// </summary>
[ByRefEvent]
public sealed class CP14StopCastMagicEffectEvent : EntityEventArgs
public sealed class CP14EndCastMagicEffectEvent : EntityEventArgs
{
}

View File

@@ -0,0 +1,17 @@
using Robust.Shared.Prototypes;
namespace Content.Shared._CP14.MagicSpell.Spells;
public sealed partial class CP14SpellAddComponent : CP14SpellEffect
{
[DataField]
public ComponentRegistry Components = new();
public override void Effect(EntityManager entManager, CP14SpellEffectBaseArgs args)
{
if (args.Target is null)
return;
entManager.AddComponents(args.Target.Value, Components);
}
}

View File

@@ -0,0 +1,23 @@
using Robust.Shared.Map;
using Robust.Shared.Prototypes;
namespace Content.Shared._CP14.MagicSpell.Spells;
public sealed partial class CP14SpellCasterTeleport : CP14SpellEffect
{
public override void Effect(EntityManager entManager, CP14SpellEffectBaseArgs args)
{
EntityCoordinates? targetPoint = null;
if (args.Position is not null)
targetPoint = args.Position.Value;
else if (args.Target is not null && entManager.TryGetComponent<TransformComponent>(args.Target.Value, out var transformComponent))
targetPoint = transformComponent.Coordinates;
if (targetPoint is null || args.User is null)
return;
var transform = entManager.System<SharedTransformSystem>();
transform.SetCoordinates(args.User.Value, targetPoint.Value);
}
}

View File

@@ -0,0 +1,16 @@
using Content.Shared.Damage;
namespace Content.Shared._CP14.MeleeWeapon.Components;
[RegisterComponent]
public sealed partial class CP14MeleeSelfDamageComponent : Component
{
[DataField]
public DamageSpecifier DamageToSelf = new()
{
DamageDict = new()
{
{ "Blunt", 1 },
}
};
}

View File

@@ -0,0 +1,16 @@
using Content.Shared._CP14.MeleeWeapon.EntitySystems;
namespace Content.Shared._CP14.MeleeWeapon.Components;
/// <summary>
/// allows the object to become blunt with use
/// </summary>
[RegisterComponent, Access(typeof(CP14SharpeningSystem))]
public sealed partial class CP14SharpenedComponent : Component
{
[DataField]
public float Sharpness = 1f;
[DataField]
public float SharpnessDamageBy1Damage = 0.002f; //500 damage
}

View File

@@ -0,0 +1,52 @@
using Content.Shared._CP14.MeleeWeapon.EntitySystems;
using Content.Shared.Damage;
using Robust.Shared.Audio;
namespace Content.Shared._CP14.MeleeWeapon.Components;
/// <summary>
/// component allows you to sharpen objects by restoring their damage.
/// </summary>
[RegisterComponent, Access(typeof(CP14SharpeningSystem))]
public sealed partial class CP14SharpeningStoneComponent : Component
{
/// <summary>
/// the amount of acuity recoverable per use
/// </summary>
[DataField]
public float SharpnessHeal = 0.05f;
/// <summary>
/// sound when used
/// </summary>
[DataField]
public SoundSpecifier SharpeningSound =
new SoundPathSpecifier("/Audio/_CP14/Items/sharpening_stone.ogg")
{
Params = AudioParams.Default.WithVariation(0.02f),
};
/// <summary>
/// the damage that the sharpening stone does to itself for use
/// </summary>
[DataField]
public DamageSpecifier SelfDamage = new()
{
DamageDict = new()
{
{ "Blunt", 1 },
}
};
/// <summary>
/// the damage the sharpening stone does to the target
/// </summary>
[DataField]
public DamageSpecifier TargetDamage = new()
{
DamageDict = new()
{
{ "Blunt", 1 },
}
};
}

View File

@@ -0,0 +1,24 @@
using Content.Shared._CP14.MeleeWeapon.Components;
using Content.Shared.Damage;
using Content.Shared.Weapons.Melee.Events;
namespace Content.Shared._CP14.MeleeWeapon.EntitySystems;
public sealed class CP14MeleeSelfDamageSystem : EntitySystem
{
[Dependency] private readonly DamageableSystem _damageable = default!;
public override void Initialize()
{
SubscribeLocalEvent<CP14MeleeSelfDamageComponent, MeleeHitEvent>(OnMeleeHit);
}
private void OnMeleeHit(Entity<CP14MeleeSelfDamageComponent> ent, ref MeleeHitEvent args)
{
if (!args.IsHit)
return;
if (args.HitEntities.Count == 0)
return;
_damageable.TryChangeDamage(ent, ent.Comp.DamageToSelf);
}
}

View File

@@ -0,0 +1,138 @@
using System.Linq;
using Content.Shared._CP14.MeleeWeapon.Components;
using Content.Shared.Damage;
using Content.Shared.Examine;
using Content.Shared.Interaction;
using Content.Shared.Placeable;
using Content.Shared.Popups;
using Content.Shared.Timing;
using Content.Shared.Weapons.Melee.Events;
using Content.Shared.Wieldable;
using Robust.Shared.Audio.Systems;
namespace Content.Shared._CP14.MeleeWeapon.EntitySystems;
public sealed class CP14SharpeningSystem : EntitySystem
{
[Dependency] private readonly DamageableSystem _damageableSystem = default!;
[Dependency] private readonly UseDelaySystem _useDelay = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly SharedPopupSystem _popup = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<CP14SharpenedComponent, GetMeleeDamageEvent>(OnGetMeleeDamage, after: new[] { typeof(WieldableSystem) });
SubscribeLocalEvent<CP14SharpenedComponent, ExaminedEvent>(OnExamined);
SubscribeLocalEvent<CP14SharpenedComponent, MeleeHitEvent>(OnMeleeHit);
SubscribeLocalEvent<CP14SharpeningStoneComponent, AfterInteractEvent>(OnAfterInteract);
SubscribeLocalEvent<CP14SharpeningStoneComponent, ActivateInWorldEvent>(OnInteract);
}
private void OnMeleeHit(Entity<CP14SharpenedComponent> sharpened, ref MeleeHitEvent args)
{
if (!args.HitEntities.Any())
return;
sharpened.Comp.Sharpness = MathHelper.Clamp(sharpened.Comp.Sharpness - args.BaseDamage.GetTotal().Float() * sharpened.Comp.SharpnessDamageBy1Damage, 0.1f, 1f);
}
private void OnInteract(Entity<CP14SharpeningStoneComponent> stone, ref ActivateInWorldEvent args)
{
if (args.Handled)
return;
if (!TryComp<ItemPlacerComponent>(stone, out var itemPlacer))
return;
if (itemPlacer.PlacedEntities.Count <= 0)
return;
foreach (var item in itemPlacer.PlacedEntities)
{
if (!TryComp<CP14SharpenedComponent>(item, out var sharpened))
continue;
SharpThing(stone, item, sharpened, args.User);
return;
}
}
private void OnAfterInteract(Entity<CP14SharpeningStoneComponent> stone, ref AfterInteractEvent args)
{
if (!args.CanReach || args.Target == null || !TryComp<CP14SharpenedComponent>(args.Target, out var sharpened))
return;
if (TryComp<UseDelayComponent>(stone, out var useDelay) && _useDelay.IsDelayed( new Entity<UseDelayComponent>(stone, useDelay)))
return;
SharpThing(stone, args.Target.Value, sharpened, args.User);
}
private void SharpThing(Entity<CP14SharpeningStoneComponent> stone, EntityUid target, CP14SharpenedComponent component, EntityUid user)
{
var ev = new SharpingEvent()
{
User = user,
Target = target,
};
RaiseLocalEvent(stone, ev);
if (!ev.Canceled)
{
_audio.PlayPvs(stone.Comp.SharpeningSound, target);
Spawn("EffectSparks", Transform(target).Coordinates);
_damageableSystem.TryChangeDamage(stone, stone.Comp.SelfDamage);
_damageableSystem.TryChangeDamage(target, stone.Comp.TargetDamage);
component.Sharpness = MathHelper.Clamp01(component.Sharpness + stone.Comp.SharpnessHeal);
if (component.Sharpness >= 0.99)
_popup.PopupEntity(Loc.GetString("sharpening-ready"), target, user);
}
_useDelay.TryResetDelay(stone);
}
private void OnExamined(Entity<CP14SharpenedComponent> sharpened, ref ExaminedEvent args)
{
if (sharpened.Comp.Sharpness > 0.95f)
{
args.PushMarkup(Loc.GetString("sharpening-examined-95"));
return;
}
if (sharpened.Comp.Sharpness > 0.75f)
{
args.PushMarkup(Loc.GetString("sharpening-examined-75"));
return;
}
if (sharpened.Comp.Sharpness > 0.5f)
{
args.PushMarkup(Loc.GetString("sharpening-examined-50"));
return;
}
args.PushMarkup(Loc.GetString("sharpening-examined-25"));
}
private void OnGetMeleeDamage(Entity<CP14SharpenedComponent> sharpened, ref GetMeleeDamageEvent args)
{
args.Damage *= sharpened.Comp.Sharpness;
}
}
/// <summary>
/// Caused on a sharpening stone when someone tries to sharpen an object with it
/// </summary>
public sealed class SharpingEvent : EntityEventArgs
{
public bool Canceled = false;
public EntityUid User;
public EntityUid Target;
}