From cc70fb361bd1dcf4ee9e5b9127d03de087216bf8 Mon Sep 17 00:00:00 2001 From: Minimata Date: Sat, 28 Mar 2026 11:43:34 +0100 Subject: [PATCH] WIP: integrating forge systems into the game, now trying periodic abilities --- forge/ForgeManager.cs | 4 + forge/abilities/RAbilityBase.cs | 2 +- ...lodingSwordThrow.cs => RExplodingSword.cs} | 42 ++++++--- ...ordThrow.cs.uid => RExplodingSword.cs.uid} | 0 forge/calculators/FlyingWeaponExecution.cs | 67 ++++++++++++++ .../calculators/FlyingWeaponExecution.cs.uid | 1 + interfaces/IAbilityBase.cs | 2 +- .../player_controller/PlayerController.tscn | 10 +-- .../components/weapon/WeaponSystem.cs | 57 +++++++++++- .../components/weapon/weapon.tscn | 3 + .../forge/exploding_sword_throw.tres | 10 ++- .../scripts/PlayerController.cs | 87 ++++++++++++++++--- 12 files changed, 242 insertions(+), 43 deletions(-) rename forge/abilities/{RExplodingSwordThrow.cs => RExplodingSword.cs} (70%) rename forge/abilities/{RExplodingSwordThrow.cs.uid => RExplodingSword.cs.uid} (100%) create mode 100644 forge/calculators/FlyingWeaponExecution.cs create mode 100644 forge/calculators/FlyingWeaponExecution.cs.uid diff --git a/forge/ForgeManager.cs b/forge/ForgeManager.cs index 7bf580f8..4f110673 100644 --- a/forge/ForgeManager.cs +++ b/forge/ForgeManager.cs @@ -18,10 +18,14 @@ public partial class ForgeManager : Node // Abilities "abilities.weapon.land", + "abilities.weapon.flying", + "abilities.weapon.left", // Events "events.combat.damage", "events.combat.hit", + "events.weapon.left", + "events.weapon.flyingTick", "events.weapon.land", // Cooldowns diff --git a/forge/abilities/RAbilityBase.cs b/forge/abilities/RAbilityBase.cs index e9a8c5cd..bc37b174 100644 --- a/forge/abilities/RAbilityBase.cs +++ b/forge/abilities/RAbilityBase.cs @@ -24,7 +24,7 @@ public partial class RAbilityBase(float cost, float cooldown) : Resource, IAbili { } - public virtual AbilityData Ability(TagsManager tagsManager, Node3D owner) + public virtual AbilityData Ability(TagsManager tagsManager, TagContainer? tags, Node3D owner) { throw new NotImplementedException(); } diff --git a/forge/abilities/RExplodingSwordThrow.cs b/forge/abilities/RExplodingSword.cs similarity index 70% rename from forge/abilities/RExplodingSwordThrow.cs rename to forge/abilities/RExplodingSword.cs index 790c7cda..02e6311c 100644 --- a/forge/abilities/RExplodingSwordThrow.cs +++ b/forge/abilities/RExplodingSword.cs @@ -1,3 +1,4 @@ +using System; using Gamesmiths.Forge.Abilities; using Gamesmiths.Forge.Cues; using Gamesmiths.Forge.Effects; @@ -7,27 +8,28 @@ using Gamesmiths.Forge.Effects.Magnitudes; using Gamesmiths.Forge.Effects.Modifiers; using Gamesmiths.Forge.Tags; using Godot; +using Movementtests.systems; namespace Movementtests.forge.abilities; [GlobalClass, Icon("res://assets/ui/IconGodotNode/white/icon_projectile.png")] -public partial class RExplodingSwordThrow(PackedScene? explosion, float cost, float cooldown) : RAbilityBase(cost, cooldown) +public partial class RExplodingSword(PackedScene? explosion, float cost, float cooldown) : RAbilityBase(cost, cooldown) { [Export] public PackedScene? Explosion { get; set; } = explosion; - public RExplodingSwordThrow() : this(null, 20.0f, 0.0f) + public RExplodingSword() : this(null, 20.0f, 0.0f) { } - public override AbilityData Ability(TagsManager tagsManager, Node3D owner) + public override AbilityData Ability(TagsManager tagsManager, TagContainer? tags, Node3D owner) { return new AbilityData( name: "Exploding Sword Throw", costEffect: CostEffect(tagsManager), cooldownEffects: [CooldownEffect(tagsManager)], - abilityTags: Tag.RequestTag(tagsManager, "abilities.weapon.land").GetSingleTagContainer(), + abilityTags: tags, instancingPolicy: AbilityInstancingPolicy.PerEntity, - behaviorFactory: () => new ExplodingSwordThrowBehavior(owner, Explosion)); + behaviorFactory: () => new ExplodingSwordThrowBehavior(owner, Explosion)); } public override EffectData CostEffect(TagsManager tagsManager) @@ -77,21 +79,28 @@ public partial class RExplodingSwordThrow(PackedScene? explosion, float cost, fl } } -public class ExplodingSwordThrowBehavior(Node3D owner, PackedScene? explosion) : IAbilityBehavior +public class ExplodingSwordThrowBehavior(Node3D owner, PackedScene? explosion) : IAbilityBehavior { private Node3D _owner = owner; private PackedScene? _explosion = explosion; - public void OnStarted(AbilityBehaviorContext context) + public void OnStarted(AbilityBehaviorContext context, TPayload payload) { + GD.Print(payload); if (_explosion?.Instantiate() is not Explosion explosion) { context.InstanceHandle.End(); return; } + if (!_owner.IsInsideTree()) + { + context.InstanceHandle.End(); + return; + } + + explosion.Radius = 6f; - explosion.Radius = 10f; - _owner.GetTree().GetRoot().AddChild(explosion); - explosion.GlobalPosition = _owner.GlobalPosition; + _owner.GetTree().GetRoot().CallDeferred(Node.MethodName.AddChild, explosion); + explosion.CallDeferred(Node3D.MethodName.SetGlobalPosition, _owner.GlobalPosition); context.AbilityHandle.CommitAbility(); context.InstanceHandle.End(); @@ -99,6 +108,17 @@ public class ExplodingSwordThrowBehavior(Node3D owner, PackedScene? explosion) : public void OnEnded(AbilityBehaviorContext context) { - } +} + +public class TestBehavior( + Action callback) : IAbilityBehavior +{ + public void OnStarted(AbilityBehaviorContext context, TPayload data) + { + callback(context, data); + context.InstanceHandle.End(); + } + + public void OnEnded(AbilityBehaviorContext context){} } \ No newline at end of file diff --git a/forge/abilities/RExplodingSwordThrow.cs.uid b/forge/abilities/RExplodingSword.cs.uid similarity index 100% rename from forge/abilities/RExplodingSwordThrow.cs.uid rename to forge/abilities/RExplodingSword.cs.uid diff --git a/forge/calculators/FlyingWeaponExecution.cs b/forge/calculators/FlyingWeaponExecution.cs new file mode 100644 index 00000000..7226350f --- /dev/null +++ b/forge/calculators/FlyingWeaponExecution.cs @@ -0,0 +1,67 @@ +using System.Collections.Generic; +using Gamesmiths.Forge.Attributes; +using Gamesmiths.Forge.Core; +using Gamesmiths.Forge.Effects; +using Gamesmiths.Forge.Effects.Calculator; +using Gamesmiths.Forge.Effects.Magnitudes; +using Gamesmiths.Forge.Effects.Modifiers; +using Godot; + +namespace Movementtests.tools.calculators; + +public class FlyingWeaponExecution : CustomExecution +{ + private readonly Node3D _comboSystem; + + public AttributeCaptureDefinition TargetHealth { get; } + public AttributeCaptureDefinition AttackerStrength { get; } + + public FlyingWeaponExecution() + { + + TargetHealth = new AttributeCaptureDefinition( + "CombatAttributeSet.CurrentHealth", + AttributeCaptureSource.Target, + Snapshot: false); + + AttackerStrength = new AttributeCaptureDefinition( + "StatAttributeSet.Strength", + AttributeCaptureSource.Source, + Snapshot: true); + + AttributesToCapture.Add(TargetHealth); + AttributesToCapture.Add(AttackerStrength); + + CustomCueParameters.Add("cues.combat.combo_count", 0); + CustomCueParameters.Add("cues.combat.combo_damage", 0f); + } + + public override ModifierEvaluatedData[] EvaluateExecution(Effect effect, IForgeEntity target, EffectEvaluatedData? effectEvaluatedData) + { + var results = new List(); + + int strength = CaptureAttributeMagnitude(AttackerStrength, effect, target, effectEvaluatedData); + int comboCount = 0; + + // Calculate combo damage + float baseDamage = strength * 0.8f; + float comboDamage = baseDamage * (1 + comboCount * 0.2f); + + // Apply health damage + if (TargetHealth.TryGetAttribute(target, out EntityAttribute? healthAttribute)) + { + results.Add(new ModifierEvaluatedData( + healthAttribute, + ModifierOperation.FlatBonus, + -comboDamage, // Negative for damage + channel: 0 + )); + } + + // Add combo to cue parameters + CustomCueParameters["cues.combat.combo_count"] = comboCount; + CustomCueParameters["cues.combat.combo_damage"] = comboDamage; + + return results.ToArray(); + } +} \ No newline at end of file diff --git a/forge/calculators/FlyingWeaponExecution.cs.uid b/forge/calculators/FlyingWeaponExecution.cs.uid new file mode 100644 index 00000000..4fad87a1 --- /dev/null +++ b/forge/calculators/FlyingWeaponExecution.cs.uid @@ -0,0 +1 @@ +uid://br7ut4lbau66w diff --git a/interfaces/IAbilityBase.cs b/interfaces/IAbilityBase.cs index d305e2b3..ac097a0d 100644 --- a/interfaces/IAbilityBase.cs +++ b/interfaces/IAbilityBase.cs @@ -7,7 +7,7 @@ namespace Movementtests.interfaces; public interface IAbilityBase { - AbilityData Ability(TagsManager tagsManager, Node3D owner); + AbilityData Ability(TagsManager tagsManager, TagContainer? tags, Node3D owner); EffectData CostEffect(TagsManager tagsManager); EffectData CooldownEffect(TagsManager tagsManager); } \ No newline at end of file diff --git a/scenes/player_controller/PlayerController.tscn b/scenes/player_controller/PlayerController.tscn index 869cf672..396489b8 100644 --- a/scenes/player_controller/PlayerController.tscn +++ b/scenes/player_controller/PlayerController.tscn @@ -7,7 +7,7 @@ [ext_resource type="Resource" uid="uid://bl5crtu1gkrtr" path="res://inputs/base_mode/base_mode.tres" id="3_cresl"] [ext_resource type="Resource" uid="uid://dtmhtlix2amme" path="res://scenes/player_controller/resources/player_mana_regen.tres" id="3_n24vh"] [ext_resource type="PackedScene" uid="uid://c4ikbhojckpnc" path="res://scenes/components/health/CHealth.tscn" id="3_q7bng"] -[ext_resource type="Script" uid="uid://rux15j7q78e8" path="res://forge/abilities/RExplodingSwordThrow.cs" id="4_11013"] +[ext_resource type="Resource" uid="uid://cdxbwirfiaipi" path="res://scenes/player_controller/resources/forge/exploding_sword_throw.tres" id="4_11013"] [ext_resource type="Script" uid="uid://baiapod3csndf" path="res://scenes/components/health/RHealth.cs" id="4_abfq8"] [ext_resource type="Resource" uid="uid://bjyd801wvverk" path="res://scenes/player_controller/resources/player_health.tres" id="4_m8gvy"] [ext_resource type="Resource" uid="uid://cpdaw41ah5gic" path="res://inputs/base_mode/rotate_y.tres" id="4_rxwoh"] @@ -56,12 +56,6 @@ [ext_resource type="Texture2D" uid="uid://c40orhfdgsim" path="res://assets/ui/IconGodotNode/white/icon_circle.png" id="45_u8rdp"] [ext_resource type="PackedScene" uid="uid://cyw8p0p6a78tl" path="res://scenes/ui/healthbar/healthbar.tscn" id="47_76kmc"] -[sub_resource type="Resource" id="Resource_5b7hb"] -script = ExtResource("4_11013") -Explosion = ExtResource("5_ue7xq") -Cost = 10.0 -metadata/_custom_type_script = "uid://rux15j7q78e8" - [sub_resource type="Resource" id="Resource_cb2lu"] script = ExtResource("2_x835q") DamageDealt = 10.0 @@ -126,7 +120,7 @@ collision_mask = 272 script = ExtResource("1_poq2x") EmpoweredAction = ExtResource("7_qheee") ManaRegen = ExtResource("3_n24vh") -AbilityLoadout = [SubResource("Resource_5b7hb")] +AbilityLoadout = [ExtResource("4_11013")] AimAssistStrength = 0.3 AimAssistReductionWhenCloseToTarget = 0.1 AimAssistReductionStartDistance = 8.0 diff --git a/scenes/player_controller/components/weapon/WeaponSystem.cs b/scenes/player_controller/components/weapon/WeaponSystem.cs index c2d59464..04a3ba24 100644 --- a/scenes/player_controller/components/weapon/WeaponSystem.cs +++ b/scenes/player_controller/components/weapon/WeaponSystem.cs @@ -12,7 +12,9 @@ using Movementtests.tools; namespace Movementtests.systems; -public record struct WeaponLandPayload(int Damage, bool IsCritical); +public record struct WeaponLandPayload(); +public record struct WeaponFlyingPayload(string Message); +public record struct WeaponLeftPayload(); [GlobalClass, Icon("res://assets/ui/IconGodotNode/node_3D/icon_sword.png")] public partial class WeaponSystem : RigidBody3D, IDamageDealer, IForgeEntity @@ -41,6 +43,7 @@ public partial class WeaponSystem : RigidBody3D, IDamageDealer, IForgeEntity public StateChartState FlyingState = null!; public StateChartState PlantedState = null!; private ShapeCast3D _dashCast3D = null!; + public Timer WeaponFlyingTick = null!; private Transform3D _startTransform; private Vector3 _startMeshRotation; @@ -53,7 +56,9 @@ public partial class WeaponSystem : RigidBody3D, IDamageDealer, IForgeEntity public MeshInstance3D WeaponLocationIndicator { get; set; } = null!; public StandardMaterial3D WeaponLocationIndicatorMaterial { get; set; } = null!; public MeshInstance3D WeaponMesh { get; set; } = null!; - + + public Tag WeaponLeftTag; + public Tag WeaponFlyingTickTag; public Tag WeaponLandTag; public void Init() @@ -66,6 +71,8 @@ public partial class WeaponSystem : RigidBody3D, IDamageDealer, IForgeEntity WeaponLocationIndicator = GetNode("WeaponLocationIndicator"); WeaponLocationIndicator.Visible = false; WeaponLocationIndicatorMaterial = (WeaponLocationIndicator.GetActiveMaterial(0) as StandardMaterial3D)!; + + WeaponFlyingTick = GetNode("WeaponFlyingTick"); WeaponMesh = GetNode("Weapon"); _startMeshRotation = WeaponMesh.Rotation; @@ -88,12 +95,29 @@ public partial class WeaponSystem : RigidBody3D, IDamageDealer, IForgeEntity Abilities = new(this); Events = new(); + WeaponLeftTag = Tag.RequestTag(tagsManager, "events.weapon.left"); + WeaponFlyingTickTag = Tag.RequestTag(tagsManager, "events.weapon.flyingTick"); WeaponLandTag = Tag.RequestTag(tagsManager, "events.weapon.land"); BodyEntered += OnThrownWeaponReachesGround; InHandState.StateExited += WeaponLeft; InHandState.StateEntered += WeaponBack; + FlyingState.StateEntered += FlyingStarted; + FlyingState.StateExited += FlyingEnded; + + WeaponFlyingTick.Timeout += RaiseWeaponFlyingTickEvent; + } + + public void FlyingStarted() + { + RaiseWeaponFlyingTickEvent(); + WeaponFlyingTick.Start(); + } + + public void FlyingEnded() + { + WeaponFlyingTick.Stop(); } public void WeaponLeft() @@ -121,6 +145,7 @@ public partial class WeaponSystem : RigidBody3D, IDamageDealer, IForgeEntity public void ThrowWeapon(Vector3 end, bool hasHit, Vector3 collisionLocation, Vector3 collisionNormal, Node collidedObject) { _weaponState.SendEvent("throw"); + RaiseWeaponLeftEvent(); // WeaponLocationIndicatorMaterial.StencilColor = new Color(1f, 1f, 1f); @@ -129,7 +154,6 @@ public partial class WeaponSystem : RigidBody3D, IDamageDealer, IForgeEntity PlantNormal = collisionNormal; LookAt(end); - var tween = GetTree().CreateTween(); tween.TweenProperty(this, "global_position", end, StraightThrowDuration); if (hasHit) @@ -149,7 +173,30 @@ public partial class WeaponSystem : RigidBody3D, IDamageDealer, IForgeEntity Source = this, Target = victim, EventMagnitude = 25f, - Payload = new WeaponLandPayload(Damage: 25, IsCritical: true) + Payload = new WeaponLandPayload() + }); + } + + public void RaiseWeaponLeftEvent() + { + Events.Raise(new EventData + { + EventTags = WeaponLeftTag.GetSingleTagContainer(), + Source = this, + EventMagnitude = 25f, + Payload = new WeaponLeftPayload() + }); + } + + + public void RaiseWeaponFlyingTickEvent() + { + Events.Raise(new EventData + { + EventTags = WeaponFlyingTickTag.GetSingleTagContainer(), + Source = this, + EventMagnitude = 12f, + Payload = new WeaponFlyingPayload(Message: "flying") }); } @@ -170,6 +217,8 @@ public partial class WeaponSystem : RigidBody3D, IDamageDealer, IForgeEntity public void RethrowWeapon() { _weaponState.SendEvent("throw"); + RaiseWeaponLeftEvent(); + _throwDirection = Vector3.Up; ThrowWeaponOnCurve(); } diff --git a/scenes/player_controller/components/weapon/weapon.tscn b/scenes/player_controller/components/weapon/weapon.tscn index 5905b367..1c4ad019 100644 --- a/scenes/player_controller/components/weapon/weapon.tscn +++ b/scenes/player_controller/components/weapon/weapon.tscn @@ -50,6 +50,9 @@ max_contacts_reported = 1 script = ExtResource("1_csqwk") RDamage = SubResource("Resource_jpdh0") +[node name="WeaponFlyingTick" type="Timer" parent="." unique_id=656309486] +wait_time = 0.2 + [node name="CollisionShape3D" type="CollisionShape3D" parent="." unique_id=884463982] transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0, 0, 0) shape = SubResource("CylinderShape3D_avini") diff --git a/scenes/player_controller/resources/forge/exploding_sword_throw.tres b/scenes/player_controller/resources/forge/exploding_sword_throw.tres index 5eb1f54f..9632548b 100644 --- a/scenes/player_controller/resources/forge/exploding_sword_throw.tres +++ b/scenes/player_controller/resources/forge/exploding_sword_throw.tres @@ -1,8 +1,10 @@ -[gd_resource type="Resource" script_class="RExplodingSwordThrow" format=3 uid="uid://cdxbwirfiaipi"] +[gd_resource type="Resource" script_class="RExplodingSword" format=3 uid="uid://cdxbwirfiaipi"] -[ext_resource type="Script" uid="uid://rux15j7q78e8" path="res://forge/abilities/RExplodingSwordThrow.cs" id="1_5iq8v"] +[ext_resource type="PackedScene" uid="uid://duju3atqgltkg" path="res://scenes/explosion/explosion.tscn" id="1_aru71"] +[ext_resource type="Script" path="res://forge/abilities/RExplodingSword.cs" id="2_syk3q"] [resource] -script = ExtResource("1_5iq8v") -Cost = 20.0 +script = ExtResource("2_syk3q") +Explosion = ExtResource("1_aru71") +Cost = 10.0 metadata/_custom_type_script = "uid://rux15j7q78e8" diff --git a/scenes/player_controller/scripts/PlayerController.cs b/scenes/player_controller/scripts/PlayerController.cs index f36c07a2..3a3a10cf 100644 --- a/scenes/player_controller/scripts/PlayerController.cs +++ b/scenes/player_controller/scripts/PlayerController.cs @@ -6,7 +6,10 @@ using Gamesmiths.Forge.Effects; using Gamesmiths.Forge.Effects.Components; using Gamesmiths.Forge.Effects.Duration; using Gamesmiths.Forge.Effects.Magnitudes; +using Gamesmiths.Forge.Effects.Modifiers; +using Gamesmiths.Forge.Effects.Periodic; using Gamesmiths.Forge.Events; +using Gamesmiths.Forge.Godot.Resources.Abilities; using Gamesmiths.Forge.Tags; using Godot; @@ -707,25 +710,83 @@ public partial class PlayerController : CharacterBody3D, foreach (var weaponLandAbility in AbilityLoadout) { - var grantAbilityConfig = new GrantAbilityConfig( - weaponLandAbility.Ability(tagsManager, WeaponSystem), + // var weaponLeftTag = Tag.RequestTag(tagsManager,"abilities.weapon.left").GetSingleTagContainer(); + // var leftGrantAbilityConfig = new GrantAbilityConfig( + // weaponLandAbility.Ability(tagsManager, weaponLeftTag, WeaponSystem), + // ScalableLevel: new ScalableInt(1), + // RemovalPolicy: AbilityDeactivationPolicy.CancelImmediately, + // InhibitionPolicy: AbilityDeactivationPolicy.CancelImmediately, + // TryActivateOnGrant: false, + // TryActivateOnEnable: false, + // LevelOverridePolicy: LevelComparison.Higher); + // + // var leftGrantComponent = new GrantAbilityEffectComponent([leftGrantAbilityConfig]); + // var leftGrantEffect = new EffectData( + // "Grant Weapon Left Ability", + // new DurationData(DurationType.Infinite), + // effectComponents: [leftGrantComponent]); + // EffectsManager.ApplyEffect(new Effect(leftGrantEffect, new EffectOwnership(this, this))); + // + // var weaponLandedTag = Tag.RequestTag(tagsManager, "abilities.weapon.land").GetSingleTagContainer(); + // var landGrantAbilityConfig = new GrantAbilityConfig( + // weaponLandAbility.Ability(tagsManager, weaponLandedTag, WeaponSystem), + // ScalableLevel: new ScalableInt(1), + // RemovalPolicy: AbilityDeactivationPolicy.CancelImmediately, + // InhibitionPolicy: AbilityDeactivationPolicy.CancelImmediately, + // TryActivateOnGrant: false, + // TryActivateOnEnable: false, + // LevelOverridePolicy: LevelComparison.Higher); + // + // var landGrantComponent = new GrantAbilityEffectComponent([landGrantAbilityConfig]); + // var landGrantEffect = new EffectData( + // "Grant Weapon Land Ability", + // new DurationData(DurationType.Infinite), + // effectComponents: [landGrantComponent]); + // EffectsManager.ApplyEffect(new Effect(landGrantEffect, new EffectOwnership(this, this))); + // + ////////////////////////////////////////////// + + var weaponFlyingTag = Tag.RequestTag(tagsManager,"abilities.weapon.flying").GetSingleTagContainer(); + var weaponFlyingAbilityData = new AbilityData( + name: "Exploding Flying Sword", + abilityTags: weaponFlyingTag, + instancingPolicy: AbilityInstancingPolicy.PerEntity, + abilityTriggerData: AbilityTriggerData.ForEvent(WeaponSystem.WeaponFlyingTickTag), + behaviorFactory: () => new ExplodingSwordThrowBehavior(WeaponSystem, Explosion)); + + var flyingGrantAbilityConfig = new GrantAbilityConfig( + weaponFlyingAbilityData, ScalableLevel: new ScalableInt(1), RemovalPolicy: AbilityDeactivationPolicy.CancelImmediately, InhibitionPolicy: AbilityDeactivationPolicy.CancelImmediately, TryActivateOnGrant: false, - TryActivateOnEnable: false, + TryActivateOnEnable: true, LevelOverridePolicy: LevelComparison.Higher); - - var grantComponent = new GrantAbilityEffectComponent([grantAbilityConfig]); - var grantEffect = new EffectData( - "Grant Weapon Land Ability", + + var flyingGrantComponent = new GrantAbilityEffectComponent([flyingGrantAbilityConfig]); + var flyingGrantEffect = new EffectData( + "Grant Weapon Flying Ability", new DurationData(DurationType.Infinite), - effectComponents: [grantComponent]); - EffectsManager.ApplyEffect(new Effect(grantEffect, new EffectOwnership(this, this))); + effectComponents: [flyingGrantComponent] + ); + + EffectsManager.ApplyEffect(new Effect(flyingGrantEffect, new EffectOwnership(this, this))); + } - // Forge events - EventSubscriptionToken token = WeaponSystem.Events.Subscribe(WeaponSystem.WeaponLandTag, OnWeaponLanded); + var weaponLeftToken = WeaponSystem.Events.Subscribe(WeaponSystem.WeaponLeftTag, OnWeaponLeft); + var weaponFlyingToken = WeaponSystem.Events.Subscribe(WeaponSystem.WeaponFlyingTickTag, data => Events.Raise(data)); + var weaponLandedToken = WeaponSystem.Events.Subscribe(WeaponSystem.WeaponLandTag, OnWeaponLanded); + } + + public void OnWeaponLeft(EventData data) + { + var target = data.Target; + + var tagsManager = ForgeManager.GetTagsManager(this); + var weaponLeftTag = Tag.RequestTag(tagsManager, "abilities.weapon.left").GetSingleTagContainer(); + if (weaponLeftTag == null) return; + Abilities.TryActivateAbilitiesByTag(weaponLeftTag, target, out var landedFailures); } public void OnWeaponLanded(EventData data) @@ -736,15 +797,13 @@ public partial class PlayerController : CharacterBody3D, var weaponLandPayload = data.Payload; var tagsManager = ForgeManager.GetTagsManager(this); + var weaponLandTag = Tag.RequestTag(tagsManager, "abilities.weapon.land").GetSingleTagContainer(); if (weaponLandTag == null) return; var anyActivated = Abilities.TryActivateAbilitiesByTag( weaponLandTag, target, out var failures); - if (anyActivated) - { - } } ///////////////////////////