using System.Collections.Generic; using Gamesmiths.Forge.Core; using Gamesmiths.Forge.Effects; using Gamesmiths.Forge.Effects.Calculator; using Gamesmiths.Forge.Effects.Magnitudes; using Gamesmiths.Forge.Events; using Gamesmiths.Forge.Godot.Resources; using Gamesmiths.Forge.Godot.Resources.Calculators; using Godot; using Movementtests.forge.abilities; using Movementtests.scenes.components.knockback; namespace Movementtests.tools.calculators; public record KnockbackDone(float KnockbackValue, Vector3 knockbackDirection); public class KnockbackExecution : CustomExecution { private readonly RKnockback _knockback; private readonly ForgeTag _knockbackTag; private readonly ForgeTagContainer? _knockbackReceiverEventTags; private readonly ForgeTagContainer? _knockbackDealerEventTags; public AttributeCaptureDefinition TargetIncomingDamage { get; } public KnockbackExecution(ForgeTag knockbackTag, RKnockback knockback, ForgeTagContainer? knockbackDealerEventTags, ForgeTagContainer? knockbackReceiverEventTags) { _knockback = knockback; _knockbackTag = knockbackTag; _knockbackDealerEventTags = knockbackDealerEventTags; _knockbackReceiverEventTags = knockbackReceiverEventTags; TargetIncomingDamage = new AttributeCaptureDefinition( "MetaAttributeSet.IncomingDamage", AttributeCaptureSource.Target); AttributesToCapture.Add(TargetIncomingDamage); } public override ModifierEvaluatedData[] EvaluateExecution(Effect effect, IForgeEntity target, EffectEvaluatedData? effectEvaluatedData) { var results = new List(); if (!target.Tags.CombinedTags.HasTag(_knockbackTag.GetTag())) return [.. results]; float targetIncomingDamage = CaptureAttributeMagnitude( TargetIncomingDamage, effect, target, effectEvaluatedData); if (targetIncomingDamage <= 0) return [.. results]; var knockbackValue = _knockback.Modifier * targetIncomingDamage / 100.0f; if (_knockbackReceiverEventTags is null) return [.. results]; var knockbackDirection = Vector3.Zero; if (effectEvaluatedData?.TryGetContextData(out SimpleHitEffectData? hitEffectData) == true) { knockbackDirection = hitEffectData.SourceLocation.DirectionTo(hitEffectData.TargetLocation); } target.Events.Raise(new EventData { EventTags = _knockbackReceiverEventTags.GetTagContainer(), Source = effect.Ownership.Owner, Target = target, EventMagnitude = knockbackValue, Payload = new KnockbackDone(knockbackValue, knockbackDirection) }); if (effect.Ownership.Source is null || _knockbackDealerEventTags is null) return [.. results]; effect.Ownership.Source.Events.Raise(new EventData { EventTags = _knockbackDealerEventTags.GetTagContainer(), Source = effect.Ownership.Owner, Target = target, EventMagnitude = knockbackValue, Payload = new KnockbackDone(knockbackValue, knockbackDirection) }); return [.. results]; } } [GlobalClass] public partial class ForgeKnockbackExecution : ForgeCustomExecution { [Export] public ForgeTag? KnockbackableTag { get; set; } [Export] public RKnockback? Knockback { get; set; } [Export] public ForgeTagContainer? KnockbackDealerEventTags { get; set; } [Export] public ForgeTagContainer? KnockbackReceiverEventTags { get; set; } public override CustomExecution GetExecutionClass() { if (Knockback == null || KnockbackableTag == null) throw new System.ArgumentException("Knockback or KnockbackableTag is null"); return new KnockbackExecution(KnockbackableTag, Knockback, KnockbackDealerEventTags, KnockbackReceiverEventTags); } }