diff --git a/Movement tests.sln.DotSettings b/Movement tests.sln.DotSettings
new file mode 100644
index 00000000..3d8771c9
--- /dev/null
+++ b/Movement tests.sln.DotSettings
@@ -0,0 +1,2 @@
+
+ False
\ No newline at end of file
diff --git a/forge/ForgeManager.cs b/forge/ForgeManager.cs
index 6bd319c0..7bf580f8 100644
--- a/forge/ForgeManager.cs
+++ b/forge/ForgeManager.cs
@@ -9,11 +9,43 @@ public partial class ForgeManager : Node
public CuesManager CuesManager { get; private set; } = new CuesManager();
public TagsManager TagsManager { get; private set; } = new TagsManager(
[
+ // entities
"character.player",
+ "weapon",
+
+ // Statuses
"status.stunned",
+
+ // Abilities
+ "abilities.weapon.land",
+
+ // Events
"events.combat.damage",
"events.combat.hit",
+ "events.weapon.land",
+
+ // Cooldowns
"cooldown.empoweredAction",
+ "cooldown.empoweredSwordThrow",
+
+ // Cues
"cues.resources.mana",
]);
-}
\ No newline at end of file
+
+ public static ForgeManager GetForgeManager(Node node)
+ {
+ return node.GetTree().Root.GetNode("ForgeManager");
+ }
+
+ public static TagsManager GetTagsManager(Node node)
+ {
+ return GetForgeManager(node).TagsManager;
+ }
+
+ public static CuesManager GetCuesManager(Node node)
+ {
+ return GetForgeManager(node).CuesManager;
+ }
+
+}
+
diff --git a/forge/abilities/RAbilityBase.cs b/forge/abilities/RAbilityBase.cs
new file mode 100644
index 00000000..e9a8c5cd
--- /dev/null
+++ b/forge/abilities/RAbilityBase.cs
@@ -0,0 +1,41 @@
+using System;
+using Gamesmiths.Forge.Abilities;
+using Gamesmiths.Forge.Cues;
+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.Tags;
+using Godot;
+using Movementtests.interfaces;
+
+namespace Movementtests.forge.abilities;
+
+[GlobalClass]
+public partial class RAbilityBase(float cost, float cooldown) : Resource, IAbilityBase
+{
+ [Export(PropertyHint.Range, "0,100,1,or_greater")]
+ public float Cost { get; set; } = cost;
+ [Export(PropertyHint.Range, "0,10,0.1,or_greater")]
+ public float Cooldown { get; set; } = cooldown;
+
+ public RAbilityBase() : this(20.0f, 0.0f)
+ {
+ }
+
+ public virtual AbilityData Ability(TagsManager tagsManager, Node3D owner)
+ {
+ throw new NotImplementedException();
+ }
+
+ public virtual EffectData CostEffect(TagsManager tagsManager)
+ {
+ throw new NotImplementedException();
+ }
+
+ public virtual EffectData CooldownEffect(TagsManager tagsManager)
+ {
+ throw new NotImplementedException();
+ }
+}
\ No newline at end of file
diff --git a/forge/abilities/RAbilityBase.cs.uid b/forge/abilities/RAbilityBase.cs.uid
new file mode 100644
index 00000000..7f28b56d
--- /dev/null
+++ b/forge/abilities/RAbilityBase.cs.uid
@@ -0,0 +1 @@
+uid://4eosgwb3h528
diff --git a/forge/abilities/REmpoweredAction.cs b/forge/abilities/REmpoweredAction.cs
index 6f6079e8..9f1655a7 100644
--- a/forge/abilities/REmpoweredAction.cs
+++ b/forge/abilities/REmpoweredAction.cs
@@ -26,6 +26,16 @@ public partial class REmpoweredAction(float cost, float cooldown, float manaRege
{
}
+ public AbilityData Ability(TagsManager tagsManager)
+ {
+ return new AbilityData(
+ name: "Empowered Action",
+ costEffect: CostEffect(tagsManager),
+ cooldownEffects: [CooldownEffect(tagsManager)],
+ instancingPolicy: AbilityInstancingPolicy.PerEntity,
+ behaviorFactory: () => new EmpoweredActionBehavior());
+ }
+
public EffectData CostEffect(TagsManager tagsManager)
{
return new(
diff --git a/forge/abilities/RExplodingSwordThrow.cs b/forge/abilities/RExplodingSwordThrow.cs
new file mode 100644
index 00000000..790c7cda
--- /dev/null
+++ b/forge/abilities/RExplodingSwordThrow.cs
@@ -0,0 +1,104 @@
+using Gamesmiths.Forge.Abilities;
+using Gamesmiths.Forge.Cues;
+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.Tags;
+using Godot;
+
+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)
+{
+ [Export] public PackedScene? Explosion { get; set; } = explosion;
+
+ public RExplodingSwordThrow() : this(null, 20.0f, 0.0f)
+ {
+ }
+
+ public override AbilityData Ability(TagsManager tagsManager, Node3D owner)
+ {
+ return new AbilityData(
+ name: "Exploding Sword Throw",
+ costEffect: CostEffect(tagsManager),
+ cooldownEffects: [CooldownEffect(tagsManager)],
+ abilityTags: Tag.RequestTag(tagsManager, "abilities.weapon.land").GetSingleTagContainer(),
+ instancingPolicy: AbilityInstancingPolicy.PerEntity,
+ behaviorFactory: () => new ExplodingSwordThrowBehavior(owner, Explosion));
+ }
+
+ public override EffectData CostEffect(TagsManager tagsManager)
+ {
+ return new(
+ "Exploding Sword Throw Mana Cost",
+ new DurationData(DurationType.Instant),
+ new[]
+ {
+ new Modifier(
+ "PlayerAttributeSet.Mana",
+ ModifierOperation.FlatBonus,
+ new ModifierMagnitude(
+ MagnitudeCalculationType.ScalableFloat,
+ new ScalableFloat(-Cost)
+ )
+ )
+ },
+ cues: new []
+ {
+ new CueData(
+ CueTags: Tag.RequestTag(tagsManager, "cues.resources.mana").GetSingleTagContainer(),
+ MinValue: 0,
+ MaxValue: 100,
+ MagnitudeType: CueMagnitudeType.AttributeValueChange,
+ MagnitudeAttribute: "PlayerAttributeSet.Mana"
+ )
+ });
+ }
+
+
+ public override EffectData CooldownEffect(TagsManager tagsManager)
+ {
+ return new(
+ "Exploding Sword Throw Cooldown",
+ new DurationData(
+ DurationType.HasDuration,
+ new ModifierMagnitude(
+ MagnitudeCalculationType.ScalableFloat,
+ new ScalableFloat(Cooldown))),
+ effectComponents: new[]
+ {
+ new ModifierTagsEffectComponent(
+ tagsManager.RequestTagContainer(new[] { "cooldown.empoweredSwordThrow" })
+ )
+ });
+ }
+}
+
+public class ExplodingSwordThrowBehavior(Node3D owner, PackedScene? explosion) : IAbilityBehavior
+{
+ private Node3D _owner = owner;
+ private PackedScene? _explosion = explosion;
+ public void OnStarted(AbilityBehaviorContext context)
+ {
+ if (_explosion?.Instantiate() is not Explosion explosion)
+ {
+ context.InstanceHandle.End();
+ return;
+ }
+
+ explosion.Radius = 10f;
+ _owner.GetTree().GetRoot().AddChild(explosion);
+ explosion.GlobalPosition = _owner.GlobalPosition;
+
+ context.AbilityHandle.CommitAbility();
+ 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/RExplodingSwordThrow.cs.uid
new file mode 100644
index 00000000..58097a30
--- /dev/null
+++ b/forge/abilities/RExplodingSwordThrow.cs.uid
@@ -0,0 +1 @@
+uid://rux15j7q78e8
diff --git a/interfaces/IAbilityBase.cs b/interfaces/IAbilityBase.cs
new file mode 100644
index 00000000..d305e2b3
--- /dev/null
+++ b/interfaces/IAbilityBase.cs
@@ -0,0 +1,13 @@
+using Gamesmiths.Forge.Abilities;
+using Gamesmiths.Forge.Effects;
+using Gamesmiths.Forge.Tags;
+using Godot;
+
+namespace Movementtests.interfaces;
+
+public interface IAbilityBase
+{
+ AbilityData Ability(TagsManager tagsManager, Node3D owner);
+ EffectData CostEffect(TagsManager tagsManager);
+ EffectData CooldownEffect(TagsManager tagsManager);
+}
\ No newline at end of file
diff --git a/interfaces/IAbilityBase.cs.uid b/interfaces/IAbilityBase.cs.uid
new file mode 100644
index 00000000..6132cfe2
--- /dev/null
+++ b/interfaces/IAbilityBase.cs.uid
@@ -0,0 +1 @@
+uid://de881c2xsbutk
diff --git a/scenes/player_controller/PlayerController.tscn b/scenes/player_controller/PlayerController.tscn
index 514ce31f..869cf672 100644
--- a/scenes/player_controller/PlayerController.tscn
+++ b/scenes/player_controller/PlayerController.tscn
@@ -7,6 +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="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"]
@@ -18,7 +19,7 @@
[ext_resource type="Resource" uid="uid://t612lts1wi1s" path="res://inputs/base_mode/move_right.tres" id="6_q7bng"]
[ext_resource type="Script" uid="uid://cwbvxlfvmocc1" path="res://scenes/player_controller/scripts/StairsSystem.cs" id="7_bmt5a"]
[ext_resource type="Resource" uid="uid://brswsknpgwal2" path="res://inputs/base_mode/move_front.tres" id="7_m8gvy"]
-[ext_resource type="Resource" uid="uid://7dpkk5rk3di5" path="res://scenes/player_controller/resources/forge_empowered_action.tres" id="7_qheee"]
+[ext_resource type="Resource" uid="uid://7dpkk5rk3di5" path="res://scenes/player_controller/resources/forge/empowered_action.tres" id="7_qheee"]
[ext_resource type="PackedScene" uid="uid://bctpe34ddamg5" path="res://scenes/components/knockback/CKnockback.tscn" id="7_x835q"]
[ext_resource type="Resource" uid="uid://s1l0n1iitc6m" path="res://inputs/base_mode/move_back.tres" id="8_jb43f"]
[ext_resource type="Resource" uid="uid://j1o5ud0plk4" path="res://inputs/base_mode/aim_release.tres" id="8_lhb11"]
@@ -55,6 +56,12 @@
[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
@@ -119,6 +126,7 @@ collision_mask = 272
script = ExtResource("1_poq2x")
EmpoweredAction = ExtResource("7_qheee")
ManaRegen = ExtResource("3_n24vh")
+AbilityLoadout = [SubResource("Resource_5b7hb")]
AimAssistStrength = 0.3
AimAssistReductionWhenCloseToTarget = 0.1
AimAssistReductionStartDistance = 8.0
diff --git a/scenes/player_controller/PlayerUi.cs b/scenes/player_controller/PlayerUi.cs
index 9ee604c5..969c0bfe 100644
--- a/scenes/player_controller/PlayerUi.cs
+++ b/scenes/player_controller/PlayerUi.cs
@@ -93,32 +93,25 @@ public partial class PlayerUi : Control, ICueHandler
// One-shot effect (like impact)
// Called when an instant effect with this cue is applied
// Also called when a periodic effect with this cue executes its period
-
if (target == null || !parameters.HasValue) return;
// Extract parameters
float magnitude = parameters.Value.Magnitude;
- float normalizedMagnitude = parameters.Value.NormalizedMagnitude;
-
// Play effects scaled by magnitude
// PlayFireImpactSound(normalizedMagnitude);
// SpawnFireImpactParticles(target, magnitude);
- GD.Print(_manabar.CurrentHealth);
_manabar.CurrentHealth += magnitude;
}
public void OnApply(IForgeEntity? target, CueParameters? parameters)
{
- return;
}
public void OnRemove(IForgeEntity? target, bool interrupted)
{
- return;
}
public void OnUpdate(IForgeEntity? target, CueParameters? parameters)
{
- return;
}
}
diff --git a/scenes/player_controller/components/weapon/WeaponAttributeSet.cs b/scenes/player_controller/components/weapon/WeaponAttributeSet.cs
new file mode 100644
index 00000000..c721b6cc
--- /dev/null
+++ b/scenes/player_controller/components/weapon/WeaponAttributeSet.cs
@@ -0,0 +1,13 @@
+using Gamesmiths.Forge.Attributes;
+
+namespace Movementtests.scenes.player_controller.components.weapon;
+
+public class WeaponAttributeSet : AttributeSet
+{
+ public EntityAttribute Level { get; }
+
+ public WeaponAttributeSet()
+ {
+ Level = InitializeAttribute(nameof(Level), 1, 1, 10);
+ }
+}
\ No newline at end of file
diff --git a/scenes/player_controller/components/weapon/WeaponAttributeSet.cs.uid b/scenes/player_controller/components/weapon/WeaponAttributeSet.cs.uid
new file mode 100644
index 00000000..a36d0c86
--- /dev/null
+++ b/scenes/player_controller/components/weapon/WeaponAttributeSet.cs.uid
@@ -0,0 +1 @@
+uid://mvc3bv0p021
diff --git a/scenes/player_controller/components/weapon/WeaponSystem.cs b/scenes/player_controller/components/weapon/WeaponSystem.cs
index e9590a0e..c2d59464 100644
--- a/scenes/player_controller/components/weapon/WeaponSystem.cs
+++ b/scenes/player_controller/components/weapon/WeaponSystem.cs
@@ -1,13 +1,21 @@
using System;
+using Gamesmiths.Forge.Core;
+using Gamesmiths.Forge.Effects;
+using Gamesmiths.Forge.Events;
+using Gamesmiths.Forge.Tags;
using Godot;
using GodotStateCharts;
using Movementtests.interfaces;
+using Movementtests.scenes.player_controller.components.weapon;
using Movementtests.systems.damage;
+using Movementtests.tools;
namespace Movementtests.systems;
+public record struct WeaponLandPayload(int Damage, bool IsCritical);
+
[GlobalClass, Icon("res://assets/ui/IconGodotNode/node_3D/icon_sword.png")]
-public partial class WeaponSystem : RigidBody3D, IDamageDealer
+public partial class WeaponSystem : RigidBody3D, IDamageDealer, IForgeEntity
{
[Signal]
public delegate void WeaponThrownEventHandler();
@@ -22,6 +30,12 @@ public partial class WeaponSystem : RigidBody3D, IDamageDealer
[Export(PropertyHint.Range, "0,0.2,0.01,or_greater")]
public float StraightThrowDuration { get; set; } = 0.1f;
+ public EntityAttributes Attributes { get; set; } = null!;
+ public EntityTags Tags { get; set; } = null!;
+ public EffectsManager EffectsManager { get; set; } = null!;
+ public EntityAbilities Abilities { get; set; } = null!;
+ public EventManager Events { get; set; } = null!;
+
private StateChart _weaponState = null!;
public StateChartState InHandState = null!;
public StateChartState FlyingState = null!;
@@ -40,6 +54,8 @@ public partial class WeaponSystem : RigidBody3D, IDamageDealer
public StandardMaterial3D WeaponLocationIndicatorMaterial { get; set; } = null!;
public MeshInstance3D WeaponMesh { get; set; } = null!;
+ public Tag WeaponLandTag;
+
public void Init()
{
_weaponState = StateChart.Of(GetNode("StateChart"));
@@ -57,6 +73,22 @@ public partial class WeaponSystem : RigidBody3D, IDamageDealer
_startTransform = Transform;
Freeze = true;
Visible = false;
+
+ var tagsManager = ForgeManager.GetTagsManager(this);
+ var cuesManager = ForgeManager.GetCuesManager(this);
+ var baseTags = new TagContainer(
+ tagsManager,
+ [
+ Tag.RequestTag(tagsManager, "weapon")
+ ]);
+
+ Attributes = new EntityAttributes(new WeaponAttributeSet());
+ Tags = new EntityTags(baseTags);
+ EffectsManager = new EffectsManager(this, cuesManager);
+ Abilities = new(this);
+ Events = new();
+
+ WeaponLandTag = Tag.RequestTag(tagsManager, "events.weapon.land");
BodyEntered += OnThrownWeaponReachesGround;
@@ -109,11 +141,26 @@ public partial class WeaponSystem : RigidBody3D, IDamageDealer
tween.Finished += ThrowWeaponOnCurve;
}
+ public void RaiseWeaponLandEvent(IForgeEntity? victim = null)
+ {
+ Events.Raise(new EventData
+ {
+ EventTags = WeaponLandTag.GetSingleTagContainer(),
+ Source = this,
+ Target = victim,
+ EventMagnitude = 25f,
+ Payload = new WeaponLandPayload(Damage: 25, IsCritical: true)
+ });
+ }
+
public void PlantInEnemy(Node3D enemy)
{
GetTree().GetRoot().CallDeferred(Node.MethodName.RemoveChild, this);
enemy.CallDeferred(Node.MethodName.AddChild, this);
+ if (enemy is IForgeEntity victim) RaiseWeaponLandEvent(victim);
+ else RaiseWeaponLandEvent();
+
if (enemy is IDamageable damageable)
{
damageable.TakeDamage(new DamageRecord(GlobalPosition, RDamage));
@@ -145,6 +192,8 @@ public partial class WeaponSystem : RigidBody3D, IDamageDealer
{
PlantInEnemy(node);
}
+ else RaiseWeaponLandEvent();
+
CallDeferred(Node3D.MethodName.SetGlobalPosition, PlantLocation);
CallDeferred(Node3D.MethodName.LookAt, GlobalTransform.Origin + PlantNormal, Vector3.Up, true);
}
diff --git a/scenes/player_controller/resources/forge_empowered_action.tres b/scenes/player_controller/resources/forge/empowered_action.tres
similarity index 100%
rename from scenes/player_controller/resources/forge_empowered_action.tres
rename to scenes/player_controller/resources/forge/empowered_action.tres
diff --git a/scenes/player_controller/resources/forge/exploding_sword_throw.tres b/scenes/player_controller/resources/forge/exploding_sword_throw.tres
new file mode 100644
index 00000000..5eb1f54f
--- /dev/null
+++ b/scenes/player_controller/resources/forge/exploding_sword_throw.tres
@@ -0,0 +1,8 @@
+[gd_resource type="Resource" script_class="RExplodingSwordThrow" format=3 uid="uid://cdxbwirfiaipi"]
+
+[ext_resource type="Script" uid="uid://rux15j7q78e8" path="res://forge/abilities/RExplodingSwordThrow.cs" id="1_5iq8v"]
+
+[resource]
+script = ExtResource("1_5iq8v")
+Cost = 20.0
+metadata/_custom_type_script = "uid://rux15j7q78e8"
diff --git a/scenes/player_controller/scripts/PlayerController.cs b/scenes/player_controller/scripts/PlayerController.cs
index 4a7231e4..f36c07a2 100644
--- a/scenes/player_controller/scripts/PlayerController.cs
+++ b/scenes/player_controller/scripts/PlayerController.cs
@@ -3,6 +3,9 @@ using System.Collections.Generic;
using Gamesmiths.Forge.Abilities;
using Gamesmiths.Forge.Core;
using Gamesmiths.Forge.Effects;
+using Gamesmiths.Forge.Effects.Components;
+using Gamesmiths.Forge.Effects.Duration;
+using Gamesmiths.Forge.Effects.Magnitudes;
using Gamesmiths.Forge.Events;
using Gamesmiths.Forge.Tags;
@@ -102,6 +105,10 @@ public partial class PlayerController : CharacterBody3D,
[ExportGroup("General")]
[Export] public REmpoweredAction EmpoweredAction = null!;
[Export] public RManaRegen ManaRegen = null!;
+
+ [ExportGroup("Abilities")]
+ [ExportSubgroup("WeaponThrow")]
+ [Export] public RAbilityBase[] AbilityLoadout = [];
// Combat stuff
[ExportCategory("Combat")]
@@ -429,26 +436,21 @@ public partial class PlayerController : CharacterBody3D,
_aimAssisRayCast.TargetPosition = _aimAssisRayCast.TargetPosition.Normalized() * (TargetingDistance*1.5f);
// Forge stuff
- var forgeManager = GetTree().Root.GetNode("ForgeManager")!;
+ var tagsManager = ForgeManager.GetTagsManager(this);
+ var cuesManager = ForgeManager.GetCuesManager(this);
var baseTags = new TagContainer(
- forgeManager.TagsManager,
+ tagsManager,
[
- Tag.RequestTag(forgeManager.TagsManager, "character.player")
+ Tag.RequestTag(tagsManager, "character.player")
]);
Attributes = new EntityAttributes(new PlayerAttributeSet());
Tags = new EntityTags(baseTags);
- EffectsManager = new EffectsManager(this, forgeManager.CuesManager);
+ EffectsManager = new EffectsManager(this, cuesManager);
Abilities = new(this);
Events = new();
- var empoweredActionData = new AbilityData(
- name: "Empowered Action",
- costEffect: EmpoweredAction.CostEffect(forgeManager.TagsManager),
- cooldownEffects: [EmpoweredAction.CooldownEffect(forgeManager.TagsManager)],
- instancingPolicy: AbilityInstancingPolicy.PerEntity,
- behaviorFactory: () => new EmpoweredActionBehavior());
-
+ var empoweredActionData = EmpoweredAction.Ability(tagsManager);
// Grant permanently
_empoweredActionHandle = Abilities.GrantAbilityPermanently(
empoweredActionData,
@@ -456,7 +458,7 @@ public partial class PlayerController : CharacterBody3D,
levelOverridePolicy: LevelComparison.None,
sourceEntity: this);
- var manaRegenEffect = new Effect(ManaRegen.ManaRegen(forgeManager.TagsManager), new EffectOwnership(this, this));
+ var manaRegenEffect = new Effect(ManaRegen.ManaRegen(tagsManager), new EffectOwnership(this, this));
_manaRegenEffectHandle = EffectsManager.ApplyEffect(manaRegenEffect);
var health = Attributes["PlayerAttributeSet.Health"].CurrentValue; // 100
@@ -702,9 +704,47 @@ public partial class PlayerController : CharacterBody3D,
_attackDash.StateEntered += OnDashAttackStarted;
_parryStandard.StateEntered += OnStandardParryStarted;
_parryDash.StateEntered += OnDashParryStarted;
+
+ foreach (var weaponLandAbility in AbilityLoadout)
+ {
+ var grantAbilityConfig = new GrantAbilityConfig(
+ weaponLandAbility.Ability(tagsManager, WeaponSystem),
+ ScalableLevel: new ScalableInt(1),
+ RemovalPolicy: AbilityDeactivationPolicy.CancelImmediately,
+ InhibitionPolicy: AbilityDeactivationPolicy.CancelImmediately,
+ TryActivateOnGrant: false,
+ TryActivateOnEnable: false,
+ LevelOverridePolicy: LevelComparison.Higher);
+
+ var grantComponent = new GrantAbilityEffectComponent([grantAbilityConfig]);
+ var grantEffect = new EffectData(
+ "Grant Weapon Land Ability",
+ new DurationData(DurationType.Infinite),
+ effectComponents: [grantComponent]);
+ EffectsManager.ApplyEffect(new Effect(grantEffect, new EffectOwnership(this, this)));
+ }
- // Testing out kill
- // GetTree().CreateTimer(2).Timeout += () => Kill(this);
+ // Forge events
+ EventSubscriptionToken token = WeaponSystem.Events.Subscribe(WeaponSystem.WeaponLandTag, OnWeaponLanded);
+ }
+
+ public void OnWeaponLanded(EventData data)
+ {
+ var source = data.Source;
+ var target = data.Target;
+ var magnitude = data.EventMagnitude;
+ 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)
+ {
+ }
}
///////////////////////////