Add SkillManager class and integrate with PlayerController and SkillUnlockerComponent (#10)

This commit is contained in:
2025-08-31 13:04:50 +02:00
committed by GitHub
parent 2d520a708f
commit bd40c797d4
11 changed files with 116 additions and 32 deletions

View File

@@ -16,6 +16,7 @@ public partial class ConsoleManager : Node
{
_gameManager = GetNode<GameManager>("/root/GameManager");
_achievementManager = GetNode<AchievementManager>("/root/AchievementManager");
_skillManager = GetNode<SkillManager>("/root/SkillManager");
RegisterConsoleCommands();
}
@@ -96,13 +97,12 @@ public partial class ConsoleManager : Node
private bool GetSkillManagement()
{
var player = _gameManager.Player;
if (player == null)
if (player == null || !IsInstanceValid(player))
{
LimboConsole.Warn("Player node not found.");
LimboConsole.Warn("Player node not found or is invalid.");
return false;
}
_skillManager ??= player.GetNode<SkillManager>("SkillManager");
_skillUnlockerComponent ??= player.GetNode<SkillUnlockerComponent>("SkillUnlockerComponent");
if (_skillManager != null && _skillUnlockerComponent != null) return true;

View File

@@ -58,6 +58,10 @@ public partial class GameManager : Node
private void OnNodeRemoved(Node node)
{
_sceneNodes.Remove(node);
if (node == _player)
{
_player = null;
}
}
public void AddCoins(int amount)
@@ -231,7 +235,9 @@ public partial class GameManager : Node
public PlayerController GetPlayer()
{
if (_player != null) return _player;
if (_player != null && IsInstanceValid(_player)) return _player;
_player = null;
foreach (var node in _sceneNodes)
{

View File

@@ -1,15 +1,18 @@
using System.Collections.Generic;
using System.Linq;
using Godot;
using Godot.Collections;
using Mr.BrickAdventures.Autoloads;
using Mr.BrickAdventures.scripts.components;
using Mr.BrickAdventures.scripts.interfaces;
using Mr.BrickAdventures.scripts.Resources;
namespace Mr.BrickAdventures.scripts;
namespace Mr.BrickAdventures.Autoloads;
public partial class SkillManager : Node
{
private GameManager _gameManager;
private PlayerController _player;
[Export] public Array<SkillData> AvailableSkills { get; set; } = [];
public Dictionary ActiveComponents { get; private set; } = new();
@@ -20,11 +23,52 @@ public partial class SkillManager : Node
public override void _Ready()
{
_gameManager = GetNode<GameManager>("/root/GameManager");
}
/// <summary>
/// Called by the PlayerController from its _Ready method to register itself with the manager.
/// </summary>
public void RegisterPlayer(PlayerController player)
{
if (_player == player) return;
// If a player is already registered (e.g., from a previous scene), unregister it first.
if (_player != null && IsInstanceValid(_player))
{
UnregisterPlayer();
}
_player = player;
if (_player != null)
{
// Automatically unregister when the player node is removed from the scene.
_player.TreeExiting += UnregisterPlayer;
ApplyUnlockedSkills();
}
}
/// <summary>
/// Cleans up skills and references related to the current player.
/// </summary>
private void UnregisterPlayer()
{
if (_player != null && IsInstanceValid(_player))
{
_player.TreeExiting -= UnregisterPlayer;
RemoveAllActiveSkills();
}
_player = null;
}
public void AddSkill(SkillData skillData)
{
// Ensure a valid player is registered before adding a skill.
if (_player == null || !IsInstanceValid(_player))
{
GD.Print("SkillManager: Player not available to add skill.");
return;
}
if (ActiveComponents.ContainsKey(skillData.Name))
return;
@@ -42,6 +86,7 @@ public partial class SkillManager : Node
break;
}
}
// Remove other throw skills if a new one is added
if (data is { Type: SkillType.Throw })
RemoveSkill(data.Name);
}
@@ -50,7 +95,8 @@ public partial class SkillManager : Node
var instance = skillData.Node.Instantiate();
if (instance is ISkill skill)
{
skill.Initialize(Owner, skillData);
// Initialize the skill with the registered player instance.
skill.Initialize(_player, skillData);
skill.Activate();
}
else
@@ -60,7 +106,8 @@ public partial class SkillManager : Node
return;
}
Owner.AddChild(instance);
// Add the skill node as a child of the player.
_player.AddChild(instance);
ActiveComponents[skillData.Name] = instance;
if (instance is BrickThrowComponent btc)
@@ -89,7 +136,7 @@ public partial class SkillManager : Node
inst.QueueFree();
var skills = _gameManager.GetUnlockedSkills();
foreach (SkillData s in skills)
foreach (var s in skills)
{
if (s.Name == skillName)
{
@@ -100,8 +147,22 @@ public partial class SkillManager : Node
ActiveComponents.Remove(skillName);
}
private void RemoveAllActiveSkills()
{
// Create a copy of keys to avoid modification during iteration
var keys = ActiveComponents.Keys.ToArray();
var skillNames = keys.Select(key => key.ToString()).ToList();
foreach (var skillName in skillNames)
{
RemoveSkill(skillName);
}
}
public void ApplyUnlockedSkills()
{
if (_player == null || !IsInstanceValid(_player)) return;
foreach (var sd in AvailableSkills)
{
if (_gameManager.IsSkillUnlocked(sd))

View File

@@ -0,0 +1 @@
uid://dru77vj07e18s

View File

@@ -1,4 +1,4 @@
[gd_scene load_steps=60 format=3 uid="uid://bqi5s710xb1ju"]
[gd_scene load_steps=53 format=3 uid="uid://bqi5s710xb1ju"]
[ext_resource type="Script" uid="uid://csel4s0e4g5uf" path="res://scripts/components/PlayerController.cs" id="1_yysbb"]
[ext_resource type="Shader" uid="uid://bs4xvm4qkurpr" path="res://shaders/hit_flash.tres" id="2_lgb3u"]
@@ -27,16 +27,9 @@
[ext_resource type="Script" uid="uid://dtg6115je7b5s" path="res://scripts/components/StompDamageComponent.cs" id="17_bl1gx"]
[ext_resource type="AudioStream" uid="uid://duj2q0rqytaxg" path="res://sfx/jump.wav" id="18_pysae"]
[ext_resource type="AudioStream" uid="uid://bmfn6p88gy575" path="res://sfx/player_hurt.wav" id="19_7anly"]
[ext_resource type="Script" uid="uid://d4crrfmbgxnqf" path="res://scripts/Resources/SkillData.cs" id="19_yysbb"]
[ext_resource type="AudioStream" uid="uid://ycgtf6wj7mto" path="res://sfx/heal.wav" id="20_bptj5"]
[ext_resource type="Resource" uid="uid://dw5ee2lpeypnb" path="res://resources/skills/brick_throw.tres" id="20_o1ihh"]
[ext_resource type="Resource" uid="uid://cdp8sex36vdq2" path="res://resources/skills/explosive_brick.tres" id="21_ur2y5"]
[ext_resource type="Resource" uid="uid://cr5lo4h8wm0jc" path="res://resources/skills/fire_brick.tres" id="22_7til7"]
[ext_resource type="Resource" uid="uid://ceakv6oqob6m7" path="res://resources/skills/ice_brick.tres" id="23_e5pae"]
[ext_resource type="Resource" uid="uid://d3bjre2etov1n" path="res://resources/skills/magnetic.tres" id="24_xuhvf"]
[ext_resource type="Script" uid="uid://dlh5xcv2sy82s" path="res://scripts/components/SkillUnlockerComponent.cs" id="25_yysbb"]
[ext_resource type="Script" uid="uid://bo506l4x0808e" path="res://scripts/components/HitComponent.cs" id="26_6n1ss"]
[ext_resource type="Script" uid="uid://di572axt0c3s8" path="res://scripts/SkillManager.cs" id="26_uno3u"]
[ext_resource type="Script" uid="uid://cjcc7fia15wu3" path="res://scripts/components/CanBeLaunchedComponent.cs" id="27_oefns"]
[ext_resource type="PackedScene" uid="uid://bg76mtpcmfm2j" path="res://objects/ui/charging_bar_layer.tscn" id="28_3f5nm"]
[ext_resource type="Script" uid="uid://cqau0810tjk4d" path="res://scripts/components/TriggerLeverComponent.cs" id="28_bnap0"]
@@ -223,13 +216,8 @@ Damage = 4.0
Area = NodePath("../StompDamageArea")
Root = NodePath("..")
[node name="SkillManager" type="Node" parent="."]
script = ExtResource("26_uno3u")
AvailableSkills = Array[ExtResource("19_yysbb")]([ExtResource("20_o1ihh"), ExtResource("21_ur2y5"), ExtResource("22_7til7"), ExtResource("23_e5pae"), ExtResource("24_xuhvf")])
[node name="SkillUnlockerComponent" type="Node" parent="." node_paths=PackedStringArray("SkillManager")]
[node name="SkillUnlockerComponent" type="Node" parent="."]
script = ExtResource("25_yysbb")
SkillManager = NodePath("../SkillManager")
[node name="HitComponent" type="Node" parent="." node_paths=PackedStringArray("Sprite", "Health", "HitFx")]
script = ExtResource("26_6n1ss")
@@ -267,12 +255,11 @@ bus = &"sfx"
stream = ExtResource("32_x2b7c")
bus = &"sfx"
[node name="ChargingBarLayer" parent="." node_paths=PackedStringArray("_skillManager") instance=ExtResource("28_3f5nm")]
[node name="ChargingBarLayer" parent="." instance=ExtResource("28_3f5nm")]
offset_left = -17.0
offset_top = -30.0
offset_right = 23.0
offset_bottom = -20.0
_skillManager = NodePath("../SkillManager")
[node name="HitParticles" parent="." instance=ExtResource("28_jh5m0")]
process_material = SubResource("ParticleProcessMaterial_lgb3u")

View File

@@ -0,0 +1,13 @@
[gd_scene load_steps=8 format=3 uid="uid://bi6v7u17vg1ww"]
[ext_resource type="Script" uid="uid://dru77vj07e18s" path="res://Autoloads/SkillManager.cs" id="1_31033"]
[ext_resource type="Script" uid="uid://d4crrfmbgxnqf" path="res://scripts/Resources/SkillData.cs" id="2_87da4"]
[ext_resource type="Resource" uid="uid://dw5ee2lpeypnb" path="res://resources/skills/brick_throw.tres" id="3_shjvi"]
[ext_resource type="Resource" uid="uid://cdp8sex36vdq2" path="res://resources/skills/explosive_brick.tres" id="4_53vnv"]
[ext_resource type="Resource" uid="uid://cr5lo4h8wm0jc" path="res://resources/skills/fire_brick.tres" id="5_77gav"]
[ext_resource type="Resource" uid="uid://ceakv6oqob6m7" path="res://resources/skills/ice_brick.tres" id="6_gib8v"]
[ext_resource type="Resource" uid="uid://d3bjre2etov1n" path="res://resources/skills/magnetic.tres" id="7_6wy8o"]
[node name="SkillManager" type="Node"]
script = ExtResource("1_31033")
AvailableSkills = Array[ExtResource("2_87da4")]([ExtResource("3_shjvi"), ExtResource("4_53vnv"), ExtResource("5_77gav"), ExtResource("6_gib8v"), ExtResource("7_6wy8o")])

View File

@@ -41,6 +41,7 @@ DialogueManager="*res://addons/dialogue_manager/dialogue_manager.gd"
SteamManager="*res://Autoloads/SteamManager.cs"
AchievementManager="*res://objects/achievement_manager.tscn"
DamageNumberManager="*res://objects/damage_number_manager.tscn"
SkillManager="*res://objects/skill_manager.tscn"
[debug]

View File

@@ -1 +0,0 @@
uid://di572axt0c3s8

View File

@@ -8,8 +8,8 @@ namespace Mr.BrickAdventures.scripts.UI;
public partial class ChargeProgressBar : ProgressBar
{
[Export] public ProgressBar ProgressBar { get; set; }
[Export] private SkillManager _skillManager;
private SkillManager _skillManager;
private BrickThrowComponent _throwComponent;
private ChargeThrowInputResource _throwInput;
@@ -17,8 +17,10 @@ public partial class ChargeProgressBar : ProgressBar
{
ProgressBar.Hide();
_skillManager = GetNodeOrNull<SkillManager>("/root/SkillManager");
if (_skillManager == null)
{
GD.PrintErr("ChargeProgressBar: SkillManager autoload not found.");
return;
}
@@ -27,11 +29,20 @@ public partial class ChargeProgressBar : ProgressBar
SetupDependencies();
}
public override void _ExitTree()
{
if (_skillManager != null && IsInstanceValid(_skillManager))
{
_skillManager.ActiveThrowSkillChanged -= OnActiveThrowSkillChanged;
}
OnOwnerExiting();
}
private void OnActiveThrowSkillChanged(BrickThrowComponent throwComponent)
{
OnOwnerExiting();
if (throwComponent == null) return;
if (throwComponent == null || !IsInstanceValid(throwComponent)) return;
_throwComponent = throwComponent;
_throwComponent.TreeExiting += OnOwnerExiting;

View File

@@ -2,6 +2,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Godot;
using Mr.BrickAdventures.Autoloads;
namespace Mr.BrickAdventures.scripts.components;
@@ -31,6 +32,9 @@ public partial class PlayerController : CharacterBody2D
public override void _Ready()
{
var skillManager = GetNodeOrNull<SkillManager>("/root/SkillManager");
skillManager?.RegisterPlayer(this);
_inputHandler = GetNode<PlayerInputHandler>("PlayerInputHandler");
foreach (var child in MovementAbilitiesContainer.GetChildren())
{

View File

@@ -8,7 +8,7 @@ namespace Mr.BrickAdventures.scripts.components;
public partial class SkillUnlockerComponent : Node
{
[Export] public SkillManager SkillManager { get; set; }
public SkillManager SkillManager { get; private set; }
[Signal]
public delegate void SkillUnlockedEventHandler(SkillData skill);
@@ -18,6 +18,7 @@ public partial class SkillUnlockerComponent : Node
public override void _Ready()
{
_gameManager = GetNode<GameManager>("/root/GameManager");
SkillManager = GetNode<SkillManager>("/root/SkillManager");
}
private bool HasEnoughCoins(int amount)