used DI for forge managers where possible

This commit is contained in:
2026-04-28 16:34:10 +02:00
parent ec44306d48
commit 24f057c15f
8 changed files with 129 additions and 112 deletions

View File

@@ -3,5 +3,5 @@ using Godot;
interface ISpawnable
{
void Initialize();
void Init();
}

View File

@@ -2,6 +2,9 @@ using Godot;
using System;
using Chickensoft.AutoInject;
using Chickensoft.Introspection;
using Gamesmiths.Forge.Cues;
using Gamesmiths.Forge.Godot.Core;
using Gamesmiths.Forge.Tags;
using Movementtests.interfaces;using Movementtests.managers;
using Movementtests.systems;
@@ -10,7 +13,7 @@ using Movementtests.systems;
typeof(IAutoConnect),
typeof(IProvider)
)]
public partial class MainSceneTemplate : Node3D, IProvide<InventoryManager>
public partial class MainSceneTemplate : Node3D, IProvide<InventoryManager>, IProvide<TagsManager>, IProvide<CuesManager>
{
public override void _Notification(int what) => this.Notify(what);
@@ -34,6 +37,9 @@ public partial class MainSceneTemplate : Node3D, IProvide<InventoryManager>
public required InventoryManager InventoryManager { get; set; }
InventoryManager IProvide<InventoryManager>.Value() => InventoryManager;
TagsManager IProvide<TagsManager>.Value() => ForgeManagers.Instance.TagsManager;
CuesManager IProvide<CuesManager>.Value() => ForgeManagers.Instance.CuesManager;
public void OnReady()
{
PlayerFellPlane.BodyEntered += StartResetPlayerAnimation;
@@ -42,8 +48,8 @@ public partial class MainSceneTemplate : Node3D, IProvide<InventoryManager>
InventoryManager = new InventoryManager();
if (InitialWeaponInventory != null)
InventoryManager.InitializeFromResource(InitialWeaponInventory);
AddChild(InventoryManager);
this.Provide();
}

View File

@@ -3,6 +3,7 @@ using Chickensoft.AutoInject;
using Chickensoft.Introspection;
using Gamesmiths.Forge.Abilities;
using Gamesmiths.Forge.Core;
using Gamesmiths.Forge.Cues;
using Gamesmiths.Forge.Effects;
using Gamesmiths.Forge.Events;
using Gamesmiths.Forge.Godot.Core;
@@ -18,7 +19,7 @@ using Movementtests.systems;
using Movementtests.tools;
using Node = Godot.Node;
[GlobalClass, Icon("res://assets/ui/IconGodotNode/node_3D/icon_beetle.png"), Meta(typeof(IAutoOn), typeof(IAutoConnect))]
[GlobalClass, Icon("res://assets/ui/IconGodotNode/node_3D/icon_beetle.png"), Meta(typeof(IAutoNode))]
public partial class Enemy : CharacterBody3D,
IDamageable,
IHealthable,
@@ -32,6 +33,15 @@ public partial class Enemy : CharacterBody3D,
{
public override void _Notification(int what) => this.Notify(what);
#region Dependencies
[Dependency]
public TagsManager TagsManager => this.DependOn<TagsManager>();
[Dependency]
public CuesManager CuesManager => this.DependOn<CuesManager>();
#endregion
// Signals and events
public event Action<IDamageable, DamageRecord> DamageTaken = null!;
public event Action<IHealthable, HealthChangedRecord> HealthChanged = null!;
@@ -109,15 +119,15 @@ public partial class Enemy : CharacterBody3D,
private ResourceBar _resourceBar = null!;
private ForgeEntity _forgeEntity;
public override void _Ready()
private AbilityHandle? _hitAbilityHandle;
public void OnReady()
{
Initialize();
Init();
SetupSignals();
}
private AbilityHandle? _hitAbilityHandle;
public void Initialize()
public void Init()
{
_damageBox = GetNode<Area3D>("DamageBox");
_target = GetNode<Node3D>("CTarget");
@@ -137,9 +147,12 @@ public partial class Enemy : CharacterBody3D,
if (HitAbility != null)
_hitAbilityHandle = Abilities.GrantAbilityPermanently(HitAbility.GetAbilityData(), 1, LevelComparison.None, this);
}
Events.Subscribe(Tag.RequestTag(ForgeManagers.Instance.TagsManager, "events.combat.hit"),
data => {});
public void OnResolved()
{
Events.Subscribe(Tag.RequestTag(TagsManager, "events.combat.hit"),
data => {GD.Print("Hit!");});
}
public void SetupSignals()

View File

@@ -10,11 +10,14 @@ using Gamesmiths.Forge.Tags;
using Movementtests.interfaces;
using Movementtests.tools;
[GlobalClass, Icon("res://assets/ui/IconGodotNode/control/icon_text_panel.png"), Meta(typeof(IAutoOn), typeof(IAutoConnect))]
[GlobalClass, Icon("res://assets/ui/IconGodotNode/control/icon_text_panel.png"), Meta(typeof(IAutoNode))]
public partial class PlayerUi : Control
{
public override void _Notification(int what) => this.Notify(what);
[Dependency]
public TagsManager TagsManager => this.DependOn<TagsManager>();
#region Utils
public enum TargetState
@@ -44,12 +47,19 @@ public partial class PlayerUi : Control
#endregion
public void Initialize(EntityAttribute health, EntityAttribute mana)
private EntityAttribute? _health;
private EntityAttribute? _mana;
public void Init(EntityAttribute health, EntityAttribute mana)
{
var tagsManager = ForgeManagers.Instance.TagsManager;
Healthbar.Initialize(health, Tag.RequestTag(tagsManager, "cues.resources.health"));
Manabar.Initialize(mana, Tag.RequestTag(tagsManager, "cues.resources.mana"));
_health = health;
_mana = mana;
}
public void OnResolved()
{
if (_health == null || _mana == null) throw new Exception("Health and mana attributes are not set");
Healthbar.Init(_health, Tag.RequestTag(TagsManager, "cues.resources.health"));
Manabar.Init(_mana, Tag.RequestTag(TagsManager, "cues.resources.mana"));
}
public void SetEnemyTargetProperties(TargetProperties targetProperties)

View File

@@ -19,12 +19,7 @@ using Gamesmiths.Forge.Tags;
using Godot;
using GodotStateCharts;
using Movementtests.addons.godot_state_charts.csharp;
using Movementtests.forge.abilities;
using Movementtests.interfaces;
using Movementtests.scenes.player_controller.components.weapon;
using Movementtests.systems.damage;
using Movementtests.tools;
using Movementtests.tools.calculators;
using Node = Godot.Node;
namespace Movementtests.systems;

View File

@@ -39,6 +39,10 @@ public partial class PlayerController : CharacterBody3D, IForgeEntity, ICueHandl
#region Dependencies
[Dependency]
public InventoryManager InventoryManager => this.DependOn<InventoryManager>();
[Dependency]
public TagsManager TagsManager => this.DependOn<TagsManager>();
[Dependency]
public CuesManager CuesManager => this.DependOn<CuesManager>();
#endregion
#region Utils
@@ -73,7 +77,7 @@ public partial class PlayerController : CharacterBody3D, IForgeEntity, ICueHandl
#endregion
#region Publics
#region Nodes
[Node("HeadSystem")] public required HeadSystem HeadSystem { get; set; }
[Node("StairsSystem")] public required StairsSystem StairsSystem { get; set; }
@@ -95,6 +99,10 @@ public partial class PlayerController : CharacterBody3D, IForgeEntity, ICueHandl
[Node("AimAssistRayCast")] public required RayCast3D AimAssistRayCast { get; set; }
[Node("HeadSystem/CameraSmooth/Camera3D")] public required Camera3D Camera { get; set; }
#endregion
#region Publics
public EntityAttributes Attributes { get; set; } = null!;
public EntityTags Tags { get; set; } = null!;
public EffectsManager EffectsManager { get; set; } = null!;
@@ -423,7 +431,6 @@ public partial class PlayerController : CharacterBody3D, IForgeEntity, ICueHandl
InvincibleTag.GetTag().GetSingleTagContainer()!
)
]);
GD.Print("Applying invincibility");
_invincibleEffect = EffectsManager.ApplyEffect(new Effect(invincibility,
new EffectOwnership(this, this)));
@@ -432,7 +439,6 @@ public partial class PlayerController : CharacterBody3D, IForgeEntity, ICueHandl
if (_invincibleEffect == null) return;
EffectsManager.RemoveEffect(_invincibleEffect);
GD.Print("Removing effect");
_invincibleEffect = null;
}
@@ -447,16 +453,6 @@ public partial class PlayerController : CharacterBody3D, IForgeEntity, ICueHandl
LoadSettings();
// General use stuff
PlayerUi = GetNode<PlayerUi>("UI");
CloseEnemyDetector = GetNode<ShapeCast3D>("%CloseEnemyDetector");
CloseEnemyDetector.TargetPosition = CloseEnemyDetector.TargetPosition.Normalized() * TargetingDistance;
AimAssistRayCast = GetNode<RayCast3D>("AimAssistRayCast");
AimAssistRayCast.TargetPosition = AimAssistRayCast.TargetPosition.Normalized() * (TargetingDistance*1.5f);
#region Forge
var tagsManager = ForgeManagers.Instance.TagsManager;
var cuesManager = ForgeManagers.Instance.CuesManager;
List<AttributeSet> attributeSetList = [];
foreach (Node node in GetChildren())
{
@@ -471,59 +467,21 @@ public partial class PlayerController : CharacterBody3D, IForgeEntity, ICueHandl
}
}
Attributes = new EntityAttributes([.. attributeSetList]);
Tags = new(BaseTags.GetTagContainer());
EffectsManager = new EffectsManager(this, cuesManager);
Abilities = new(this);
Events = new();
HealthAttribute = Attributes["PlayerAttributeSet.Health"];
ManaAttribute = Attributes["PlayerAttributeSet.Mana"];
cuesManager.RegisterCue(Tag.RequestTag(tagsManager, "cues.resources.health"), this);
Tags = new(BaseTags.GetTagContainer());
Abilities = new(this);
Events = new();
if (EmpoweredActionAbility != null)
{
_empoweredActionHandle = Abilities.GrantAbilityPermanently(
EmpoweredActionAbility.GetAbilityData(),
abilityLevel: 1,
levelOverridePolicy: LevelComparison.None,
sourceEntity: this);
}
PlayerUi.Init(HealthAttribute, ManaAttribute);
foreach (var defaultGrantedAbility in DefaultGrantedAbilities)
{
Abilities.GrantAbilityPermanently(
defaultGrantedAbility.GetAbilityData(),
abilityLevel: 1,
levelOverridePolicy: LevelComparison.None,
sourceEntity: this);
}
// Apply all default effects
foreach (var effect in DefaultPermanentEffects)
{
EffectsManager.ApplyEffect(new Effect(effect.GetEffectData(), new EffectOwnership(this, this)));
}
// Subscribe default empowered actions effects to the Empowered Action Used event
foreach (var effect in EmpoweredActionEffects)
{
Events.Subscribe<EmpoweredActionPayload>(EmpoweredActionUsed.GetTag(), data =>
{
EffectsManager.ApplyEffect(new Effect(effect.GetEffectData(), new EffectOwnership(this, this)));
});
}
Events.Subscribe(Tag.RequestTag(ForgeManagers.Instance.TagsManager, "events.combat.damage"), OnDamageReceived);
Events.Subscribe(Tag.RequestTag(ForgeManagers.Instance.TagsManager, "events.combat.death"), OnDeath);
PlayerUi.Initialize(HealthAttribute, ManaAttribute);
#endregion
CloseEnemyDetector.TargetPosition = CloseEnemyDetector.TargetPosition.Normalized() * TargetingDistance;
AimAssistRayCast.TargetPosition = AimAssistRayCast.TargetPosition.Normalized() * (TargetingDistance*1.5f);
// DashIndicator = GetNode<TextureRect>("%DashIndicator");
TargetSpeed = WalkSpeed;
SfxPlayer = GetNode<AudioStreamPlayer3D>("SFXPlayer");
_audioStream = (SfxPlayer.GetStreamPlayback() as AudioStreamPlaybackInteractive)!;
// Camera stuff
@@ -544,7 +502,6 @@ public partial class PlayerController : CharacterBody3D, IForgeEntity, ICueHandl
_playerRadius = playerShape.Radius;
// Combat stuff
WeaponHitbox = GetNode<Area3D>("%WeaponHitbox");
WeaponHitbox.Monitoring = false;
WeaponHitbox.BodyEntered += RegisterHitEnnemy;
@@ -728,6 +685,47 @@ public partial class PlayerController : CharacterBody3D, IForgeEntity, ICueHandl
public void OnResolved()
{
#region Forge
EffectsManager = new EffectsManager(this, CuesManager);
CuesManager.RegisterCue(Tag.RequestTag(TagsManager, "cues.resources.health"), this);
if (EmpoweredActionAbility != null)
{
_empoweredActionHandle = Abilities.GrantAbilityPermanently(
EmpoweredActionAbility.GetAbilityData(),
abilityLevel: 1,
levelOverridePolicy: LevelComparison.None,
sourceEntity: this);
}
foreach (var defaultGrantedAbility in DefaultGrantedAbilities)
{
Abilities.GrantAbilityPermanently(
defaultGrantedAbility.GetAbilityData(),
abilityLevel: 1,
levelOverridePolicy: LevelComparison.None,
sourceEntity: this);
}
// Apply all default effects
foreach (var effect in DefaultPermanentEffects)
{
EffectsManager.ApplyEffect(new Effect(effect.GetEffectData(), new EffectOwnership(this, this)));
}
// Subscribe default empowered actions effects to the Empowered Action Used event
foreach (var effect in EmpoweredActionEffects)
{
Events.Subscribe<EmpoweredActionPayload>(EmpoweredActionUsed.GetTag(), data =>
{
EffectsManager.ApplyEffect(new Effect(effect.GetEffectData(), new EffectOwnership(this, this)));
});
}
Events.Subscribe(Tag.RequestTag(TagsManager, "events.combat.damage"), OnDamageReceived);
Events.Subscribe(Tag.RequestTag(TagsManager, "events.combat.death"), OnDeath);
#endregion
// Initialize weapon with inventory abilities
WeaponSystem.RemoveAllEventAbilities();
foreach (var (weaponEvent, abilities) in InventoryManager.WeaponEventsInventory)
@@ -757,7 +755,7 @@ public partial class PlayerController : CharacterBody3D, IForgeEntity, ICueHandl
{
var target = data.Target;
var tagsManager = ForgeManagers.Instance.TagsManager;
var tagsManager = TagsManager;
var weaponLeftTag = Tag.RequestTag(tagsManager, "abilities.weapon.left").GetSingleTagContainer();
if (weaponLeftTag == null) return;
Abilities.TryActivateAbilitiesByTag(weaponLeftTag, target, out var landedFailures);
@@ -770,7 +768,7 @@ public partial class PlayerController : CharacterBody3D, IForgeEntity, ICueHandl
var magnitude = data.EventMagnitude;
var weaponLandPayload = data.Payload;
var tagsManager = ForgeManagers.Instance.TagsManager;
var tagsManager = TagsManager;
var weaponLandTag = Tag.RequestTag(tagsManager, "abilities.weapon.land").GetSingleTagContainer();
if (weaponLandTag == null) return;
@@ -2337,11 +2335,6 @@ public partial class PlayerController : CharacterBody3D, IForgeEntity, ICueHandl
// private float _oldMana = 100;
public override void _Process(double delta)
{
if (Engine.GetProcessFrames() % 60 == 0)
{
GD.Print(_invincibleEffect);
GD.Print(Tags.CombinedTags.Count);
}
EffectsManager.UpdateEffects(delta);
}
@@ -2644,7 +2637,7 @@ public partial class PlayerController : CharacterBody3D, IForgeEntity, ICueHandl
var newHealth = HealthAttribute.CurrentValue + data.EventMagnitude;
if (newHealth > HealthAttribute.Min) return;
var tagsManager = ForgeManagers.Instance.TagsManager;
var tagsManager = TagsManager;
Events.Raise(new EventData
{
EventTags = Tag.RequestTag(tagsManager, "events.combat.death").GetSingleTagContainer()!,

View File

@@ -5,14 +5,14 @@ using System;
public partial class Spawner : Node3D
{
[Export(PropertyHint.NodeType)]
public PackedScene EnemyToSpawn { get; set; }
public PackedScene? EnemyToSpawn { get; set; }
[Export]
public RMovement MovementInputs { get; set; }
public RMovement? MovementInputs { get; set; }
[Export]
public RHealth HealthInputs { get; set; }
public RHealth? HealthInputs { get; set; }
[Export]
public RDamage DamageInputs { get; set; }
public RDamage? DamageInputs { get; set; }
[Export]
public Node3D Target { get; set; }
@@ -37,7 +37,7 @@ public partial class Spawner : Node3D
if (EnemyToSpawn == null || !EnemyToSpawn.CanInstantiate()) return;
if (EnemyToSpawn.Instantiate() is not Enemy spawnedInstance) return;
spawnedInstance.RequestReady();
GetTree().GetCurrentScene().AddChild(spawnedInstance);
spawnedInstance.GlobalPosition = GlobalPosition;
@@ -45,7 +45,7 @@ public partial class Spawner : Node3D
spawnedInstance.RMovement = MovementInputs;
spawnedInstance.RDamage = DamageInputs;
spawnedInstance.RHealth = HealthInputs;
spawnedInstance.Initialize();
spawnedInstance.Init();
}
public void StartSpawning()

View File

@@ -8,7 +8,7 @@ using Gamesmiths.Forge.Cues;
using Gamesmiths.Forge.Godot.Core;
using Gamesmiths.Forge.Tags;
[GlobalClass, Icon("res://assets/ui/IconGodotNode/control/icon_heart.png"), Meta(typeof(IAutoOn), typeof(IAutoConnect))]
[GlobalClass, Icon("res://assets/ui/IconGodotNode/control/icon_heart.png"), Meta(typeof(IAutoNode))]
public partial class ResourceBar : ProgressBar, ICueHandler
{
public override void _Notification(int what) => this.Notify(what);
@@ -34,7 +34,7 @@ public partial class ResourceBar : ProgressBar, ICueHandler
AddThemeStyleboxOverride("fill", BarStyle);
}
public void Initialize(EntityAttribute attribute, Tag cueTag)
public void Init(EntityAttribute attribute, Tag cueTag)
{
_currentValue = attribute.BaseValue;
MaxValue = attribute.Max;