diff --git a/interfaces/ISpawnable.cs b/interfaces/ISpawnable.cs index 1cd8c0d9..ccec2a82 100644 --- a/interfaces/ISpawnable.cs +++ b/interfaces/ISpawnable.cs @@ -3,5 +3,5 @@ using Godot; interface ISpawnable { - void Initialize(); + void Init(); } \ No newline at end of file diff --git a/maps/_templates/MainSceneTemplate.cs b/maps/_templates/MainSceneTemplate.cs index 41d6c5a8..1398bfef 100644 --- a/maps/_templates/MainSceneTemplate.cs +++ b/maps/_templates/MainSceneTemplate.cs @@ -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 +public partial class MainSceneTemplate : Node3D, IProvide, IProvide, IProvide { public override void _Notification(int what) => this.Notify(what); @@ -34,16 +37,19 @@ public partial class MainSceneTemplate : Node3D, IProvide public required InventoryManager InventoryManager { get; set; } InventoryManager IProvide.Value() => InventoryManager; + TagsManager IProvide.Value() => ForgeManagers.Instance.TagsManager; + CuesManager IProvide.Value() => ForgeManagers.Instance.CuesManager; + public void OnReady() { PlayerFellPlane.BodyEntered += StartResetPlayerAnimation; DeathPlane.BodyEntered += KillEnemy; - + InventoryManager = new InventoryManager(); if (InitialWeaponInventory != null) InventoryManager.InitializeFromResource(InitialWeaponInventory); - AddChild(InventoryManager); + this.Provide(); } diff --git a/scenes/enemies/Enemy.cs b/scenes/enemies/Enemy.cs index 70256e03..40ad39ba 100644 --- a/scenes/enemies/Enemy.cs +++ b/scenes/enemies/Enemy.cs @@ -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, @@ -31,6 +32,15 @@ public partial class Enemy : CharacterBody3D, IForgeEntity { public override void _Notification(int what) => this.Notify(what); + + #region Dependencies + + [Dependency] + public TagsManager TagsManager => this.DependOn(); + [Dependency] + public CuesManager CuesManager => this.DependOn(); + + #endregion // Signals and events public event Action DamageTaken = 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("DamageBox"); _target = GetNode("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() diff --git a/scenes/player_controller/PlayerUi.cs b/scenes/player_controller/PlayerUi.cs index a9b3fc02..410eadd9 100644 --- a/scenes/player_controller/PlayerUi.cs +++ b/scenes/player_controller/PlayerUi.cs @@ -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(); + #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) diff --git a/scenes/player_controller/components/weapon/WeaponSystem.cs b/scenes/player_controller/components/weapon/WeaponSystem.cs index dc7f4acc..1acaf2ba 100644 --- a/scenes/player_controller/components/weapon/WeaponSystem.cs +++ b/scenes/player_controller/components/weapon/WeaponSystem.cs @@ -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; diff --git a/scenes/player_controller/scripts/PlayerController.cs b/scenes/player_controller/scripts/PlayerController.cs index 1770b32a..29842885 100644 --- a/scenes/player_controller/scripts/PlayerController.cs +++ b/scenes/player_controller/scripts/PlayerController.cs @@ -39,6 +39,10 @@ public partial class PlayerController : CharacterBody3D, IForgeEntity, ICueHandl #region Dependencies [Dependency] public InventoryManager InventoryManager => this.DependOn(); + [Dependency] + public TagsManager TagsManager => this.DependOn(); + [Dependency] + public CuesManager CuesManager => this.DependOn(); #endregion #region Utils @@ -73,27 +77,31 @@ 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; } - [Node("HeadSystem/MantleSystem")] public required MantleSystem MantleSystem { get; set; } - [Node("DashSystem")] public required DashSystem DashSystem { get; set; } + [Node("HeadSystem")] public required HeadSystem HeadSystem { get; set; } + [Node("StairsSystem")] public required StairsSystem StairsSystem { get; set; } + [Node("HeadSystem/MantleSystem")] public required MantleSystem MantleSystem { get; set; } + [Node("DashSystem")] public required DashSystem DashSystem { get; set; } [Node("StandingCollider")] public required CollisionShape3D StandingCollider { get; set; } [Node("SlideCollider")] public required CollisionShape3D SlideCollider { get; set; } - [Node("WeaponSystem")] public required WeaponSystem WeaponSystem { get; set; } - [Node("WallHugSystem")] public required WallHugSystem WallHugSystem { get; set; } - [Node("UI")] public required PlayerUi PlayerUi { get; set; } - [Node("GroundDetector")] public required ShapeCast3D GroundDetector { get; set; } - [Node("CeilingDetector")] public required ShapeCast3D CeilingDetector { get; set; } - [Node("DirectGroundDetector")] public required RayCast3D DirectGroundDetector { get; set; } - [Node("%WeaponHitbox")] public required Area3D WeaponHitbox { get; set; } + [Node("WeaponSystem")] public required WeaponSystem WeaponSystem { get; set; } + [Node("WallHugSystem")] public required WallHugSystem WallHugSystem { get; set; } + [Node("UI")] public required PlayerUi PlayerUi { get; set; } + [Node("GroundDetector")] public required ShapeCast3D GroundDetector { get; set; } + [Node("CeilingDetector")] public required ShapeCast3D CeilingDetector { get; set; } + [Node("DirectGroundDetector")] public required RayCast3D DirectGroundDetector { get; set; } + [Node("%WeaponHitbox")] public required Area3D WeaponHitbox { get; set; } [Node("SFXPlayer")] public required AudioStreamPlayer3D SfxPlayer { get; set; } [Node("DashDamage")] public required ShapeCast3D DashDamageDetector { get; set; } [Node("SlidingEnemyDetector")] public required Area3D SlidingEnemyDetector { get; set; } [Node("%CloseEnemyDetector")] public required ShapeCast3D CloseEnemyDetector { get; set; } [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!; @@ -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("UI"); - CloseEnemyDetector = GetNode("%CloseEnemyDetector"); - CloseEnemyDetector.TargetPosition = CloseEnemyDetector.TargetPosition.Normalized() * TargetingDistance; - AimAssistRayCast = GetNode("AimAssistRayCast"); - AimAssistRayCast.TargetPosition = AimAssistRayCast.TargetPosition.Normalized() * (TargetingDistance*1.5f); - - #region Forge - - var tagsManager = ForgeManagers.Instance.TagsManager; - var cuesManager = ForgeManagers.Instance.CuesManager; List 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(); + + PlayerUi.Init(HealthAttribute, ManaAttribute); + + CloseEnemyDetector.TargetPosition = CloseEnemyDetector.TargetPosition.Normalized() * TargetingDistance; + AimAssistRayCast.TargetPosition = AimAssistRayCast.TargetPosition.Normalized() * (TargetingDistance*1.5f); - 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(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 - // DashIndicator = GetNode("%DashIndicator"); TargetSpeed = WalkSpeed; - SfxPlayer = GetNode("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("%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(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()!, diff --git a/scenes/spawners/Spawner.cs b/scenes/spawners/Spawner.cs index fcdc6944..298fff0e 100644 --- a/scenes/spawners/Spawner.cs +++ b/scenes/spawners/Spawner.cs @@ -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() diff --git a/scenes/ui/resourcebar/ResourceBar.cs b/scenes/ui/resourcebar/ResourceBar.cs index ca5cb72c..f2e230fe 100644 --- a/scenes/ui/resourcebar/ResourceBar.cs +++ b/scenes/ui/resourcebar/ResourceBar.cs @@ -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); @@ -33,8 +33,8 @@ public partial class ResourceBar : ProgressBar, ICueHandler if (BarStyle != null) AddThemeStyleboxOverride("fill", BarStyle); } - - public void Initialize(EntityAttribute attribute, Tag cueTag) + + public void Init(EntityAttribute attribute, Tag cueTag) { _currentValue = attribute.BaseValue; MaxValue = attribute.Max;