Add new skills: Double Jump, Ground Pound, Brick Armor, and Brick Shield; implement skill removal signal in SkillManager (#11)

This commit is contained in:
2025-08-31 15:17:11 +02:00
committed by GitHub
parent bd40c797d4
commit ead52f6d51
89 changed files with 682 additions and 7 deletions

View File

@@ -19,6 +19,8 @@ public partial class SkillManager : Node
[Signal]
public delegate void ActiveThrowSkillChangedEventHandler(BrickThrowComponent throwComponent);
[Signal]
public delegate void SkillRemovedEventHandler(SkillData skillData);
public override void _Ready()
{
@@ -145,6 +147,8 @@ public partial class SkillManager : Node
}
}
ActiveComponents.Remove(skillName);
var sd = GetSkillByName(skillName);
if (sd != null) EmitSignalSkillRemoved(sd);
}
private void RemoveAllActiveSkills()

View File

@@ -1,4 +1,5 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ACamera2D_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E2_003Fresharper_002Dhost_003FSourcesCache_003Fa2e12a1a67ad701a97608de6be85250e3e353951ecf8058a02c703490c753_003FCamera2D_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ACanvasItem_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FSourcesCache_003Fef7b819b226fab796d1dfe66d415dd7510bcac87675020ddb8f03a828e763_003FCanvasItem_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ACecovym_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003Ftmp_003FJetBrainsPerUserTemp_002D1000_002D1_003FSandboxFiles_003FSadijuw_003FCecovym_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ACollisionShape2D_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FSourcesCache_003F2ca9b7334678f5c97c7c2a9fbe4837be71cae11b6a30408dd4791b18f997e4a_003FCollisionShape2D_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>

View File

@@ -90,7 +90,7 @@ color_ramp = SubResource("GradientTexture1D_lgb3u")
[node name="Brick Player" type="CharacterBody2D" node_paths=PackedStringArray("MovementAbilitiesContainer") groups=["player"]]
collision_layer = 4
collision_mask = 43
collision_mask = 107
script = ExtResource("1_yysbb")
MovementAbilitiesContainer = NodePath("Movements")
GroundMovementScene = ExtResource("2_oefns")

View File

@@ -13,7 +13,7 @@
radius = 4.0
[node name="Bullet" type="Area2D"]
collision_layer = 8
collision_layer = 64
collision_mask = 21
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
@@ -50,7 +50,6 @@ LifeTime = 10.0
[node name="LaunchComponent" type="Node2D" parent="."]
script = ExtResource("5_7bijt")
Speed = 120.0
metadata/_custom_type_script = "uid://873un8agkyja"
[node name="StraightMotionComponent" type="Node" parent="." node_paths=PackedStringArray("LaunchComponent")]
script = ExtResource("6_lycw2")
@@ -61,7 +60,6 @@ script = ExtResource("7_2aweg")
Area = NodePath("..")
TerrainHitFx = NodePath("../TerrainHitFX")
BulletSprite = NodePath("../Sprite2D")
metadata/_custom_type_script = "uid://cdnwrn8v05qhi"
[node name="TerrainHitFX" parent="." instance=ExtResource("8_6th6w")]
z_index = 3

View File

@@ -0,0 +1,23 @@
[gd_scene load_steps=4 format=3 uid="uid://d0074by8ith81"]
[ext_resource type="Script" uid="uid://2i7p7v135u7c" path="res://scripts/components/DamageComponent.cs" id="1_dkcj7"]
[ext_resource type="Script" uid="uid://oyf25mpc5etr" path="res://scripts/components/LifetimeComponent.cs" id="2_mcqxt"]
[sub_resource type="RectangleShape2D" id="RectangleShape2D_jwgyp"]
size = Vector2(128, 20)
[node name="Shockwave" type="Area2D"]
collision_layer = 0
collision_mask = 72
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
shape = SubResource("RectangleShape2D_jwgyp")
[node name="DamageComponent" type="Node" parent="." node_paths=PackedStringArray("Area")]
script = ExtResource("1_dkcj7")
Area = NodePath("..")
metadata/_custom_type_script = "uid://2i7p7v135u7c"
[node name="LifetimeComponent" type="Node" parent="."]
script = ExtResource("2_mcqxt")
LifeTime = 0.2

38
objects/items/shield.tscn Normal file
View File

@@ -0,0 +1,38 @@
[gd_scene load_steps=6 format=3 uid="uid://c6rgh0qn4jqlc"]
[ext_resource type="Texture2D" uid="uid://c0xtjfpmkfolk" path="res://sprites/explosive_brick_skill_icon.png" id="1_n5wbm"]
[ext_resource type="Script" uid="uid://dgb8bqcri7nsj" path="res://scripts/components/HealthComponent.cs" id="2_yw7rl"]
[ext_resource type="Script" uid="uid://ctfrbj52ejay4" path="res://scripts/components/DestroyableComponent.cs" id="3_6t8cd"]
[ext_resource type="Script" uid="uid://2i7p7v135u7c" path="res://scripts/components/DamageComponent.cs" id="4_yw7rl"]
[sub_resource type="CapsuleShape2D" id="CapsuleShape2D_n5wbm"]
radius = 26.0
height = 60.0
[node name="Shield" type="Sprite2D"]
modulate = Color(0.00784314, 1, 1, 1)
texture = ExtResource("1_n5wbm")
[node name="Area2D" type="Area2D" parent="."]
collision_layer = 4
collision_mask = 64
[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2D"]
position = Vector2(1, -3)
shape = SubResource("CapsuleShape2D_n5wbm")
[node name="HealthComponent" type="Node2D" parent="."]
script = ExtResource("2_yw7rl")
Health = 0.5
MaxHealth = 0.5
metadata/_custom_type_script = "uid://dgb8bqcri7nsj"
[node name="DestroyableComponent" type="Node2D" parent="." node_paths=PackedStringArray("Health")]
script = ExtResource("3_6t8cd")
Health = NodePath("../HealthComponent")
metadata/_custom_type_script = "uid://ctfrbj52ejay4"
[node name="DamageComponent" type="Node" parent="." node_paths=PackedStringArray("Area")]
script = ExtResource("4_yw7rl")
Area = NodePath("../Area2D")
metadata/_custom_type_script = "uid://2i7p7v135u7c"

View File

@@ -0,0 +1,7 @@
[gd_scene load_steps=2 format=3 uid="uid://bktuhojquwesl"]
[ext_resource type="Script" uid="uid://xc0j26e88np7" path="res://scripts/components/Movement/DoubleJumpAbility.cs" id="1_vu3oa"]
[node name="DoubleJump" type="Node"]
script = ExtResource("1_vu3oa")
metadata/_custom_type_script = "uid://xc0j26e88np7"

View File

@@ -0,0 +1,7 @@
[gd_scene load_steps=2 format=3 uid="uid://cdeh7wfc62fr4"]
[ext_resource type="Script" uid="uid://5fyepa666cc8" path="res://scripts/components/BrickArmorSkillComponent.cs" id="1_i7tox"]
[node name="BrickArmorSkillComponent" type="Node"]
script = ExtResource("1_i7tox")
metadata/_custom_type_script = "uid://5fyepa666cc8"

View File

@@ -0,0 +1,9 @@
[gd_scene load_steps=3 format=3 uid="uid://blwk5qduvdnxv"]
[ext_resource type="Script" uid="uid://dbiu2qrr8sprx" path="res://scripts/components/BrickShieldSkillComponent.cs" id="1_gjjt4"]
[ext_resource type="PackedScene" uid="uid://c6rgh0qn4jqlc" path="res://objects/items/shield.tscn" id="2_wjvuq"]
[node name="BrickShieldSkillComponent" type="Node"]
script = ExtResource("1_gjjt4")
ShieldScene = ExtResource("2_wjvuq")
metadata/_custom_type_script = "uid://dbiu2qrr8sprx"

View File

@@ -0,0 +1,9 @@
[gd_scene load_steps=3 format=3 uid="uid://dwaxbojb44a6l"]
[ext_resource type="Script" uid="uid://c61jxwtgiuqsy" path="res://scripts/components/DoubleJumpSkillComponent.cs" id="1_d8v8j"]
[ext_resource type="PackedScene" uid="uid://bktuhojquwesl" path="res://objects/movement_abilities/double_jump.tscn" id="2_romvo"]
[node name="DoubleJumpSkill" type="Node"]
script = ExtResource("1_d8v8j")
_doubleJumpAbilityScene = ExtResource("2_romvo")
metadata/_custom_type_script = "uid://c61jxwtgiuqsy"

View File

@@ -0,0 +1,9 @@
[gd_scene load_steps=3 format=3 uid="uid://lu3wvpqefekn"]
[ext_resource type="Script" uid="uid://3sclg5kdjg13" path="res://scripts/components/GroundPoundSkillComponent.cs" id="1_gx4wb"]
[ext_resource type="PackedScene" uid="uid://d0074by8ith81" path="res://objects/fxs/shockwave.tscn" id="2_3vdwu"]
[node name="GroundPoundSkillComponent" type="Node"]
script = ExtResource("1_gx4wb")
ShockwaveScene = ExtResource("2_3vdwu")
metadata/_custom_type_script = "uid://3sclg5kdjg13"

View File

@@ -0,0 +1,8 @@
[gd_scene load_steps=2 format=3 uid="uid://dtxkjif7prm70"]
[ext_resource type="Script" uid="uid://dl7vthhurirwc" path="res://scripts/components/XRayVisionSkillComponent.cs" id="1_ebn6n"]
[node name="XRayVisionSkillComponent" type="Node"]
script = ExtResource("1_ebn6n")
SecretLayer = 2
metadata/_custom_type_script = "uid://dl7vthhurirwc"

View File

@@ -1,4 +1,4 @@
[gd_scene load_steps=8 format=3 uid="uid://bi6v7u17vg1ww"]
[gd_scene load_steps=13 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"]
@@ -7,7 +7,12 @@
[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"]
[ext_resource type="Resource" uid="uid://bxsgq8703qx4u" path="res://resources/skills/double_jump.tres" id="8_87da4"]
[ext_resource type="Resource" uid="uid://cseilsspimw1n" path="res://resources/skills/ground_pound_skill.tres" id="9_77gav"]
[ext_resource type="Resource" uid="uid://c5dj06l86winx" path="res://resources/skills/xray_vision.tres" id="10_gib8v"]
[ext_resource type="Resource" uid="uid://d12defdtmlk0u" path="res://resources/skills/brick_shield.tres" id="11_6wy8o"]
[ext_resource type="Resource" uid="uid://dghnl301o1aiy" path="res://resources/skills/brick_armor.tres" id="12_gib8v"]
[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")])
AvailableSkills = Array[ExtResource("2_87da4")]([ExtResource("3_shjvi"), ExtResource("4_53vnv"), ExtResource("5_77gav"), ExtResource("6_gib8v"), ExtResource("7_6wy8o"), ExtResource("8_87da4"), ExtResource("9_77gav"), ExtResource("10_gib8v"), ExtResource("11_6wy8o"), ExtResource("12_gib8v")])

View File

@@ -193,12 +193,14 @@ locale/translations=PackedStringArray("res://translations.en.translation", "res:
[layer_names]
2d_render/layer_2="SECRET"
2d_physics/layer_1="Terrain"
2d_physics/layer_2="Collectible Entities"
2d_physics/layer_3="Player"
2d_physics/layer_4="Enemy"
2d_physics/layer_5="player projectiles"
2d_physics/layer_6="Environment"
2d_physics/layer_7="Enemy Projectiles"
[physics]

View File

@@ -0,0 +1,25 @@
[gd_resource type="Resource" script_class="SkillData" load_steps=5 format=3 uid="uid://dghnl301o1aiy"]
[ext_resource type="PackedScene" uid="uid://cdeh7wfc62fr4" path="res://objects/player_skills/brick_armor_skill_component.tscn" id="1_aqcna"]
[ext_resource type="Script" uid="uid://d4crrfmbgxnqf" path="res://scripts/Resources/SkillData.cs" id="1_unqwr"]
[ext_resource type="Script" uid="uid://dwb0e05pewcsn" path="res://scripts/Resources/SkillUpgrade.cs" id="2_kqsqd"]
[sub_resource type="Resource" id="Resource_xwv1u"]
script = ExtResource("2_kqsqd")
Cost = 120
Description = ""
Properties = Dictionary[String, Variant]({
"health_bonus": 1.0
})
metadata/_custom_type_script = "uid://dwb0e05pewcsn"
[resource]
script = ExtResource("1_unqwr")
Name = "BRICK_ARMOR"
Description = "BRICK_ARMOR_DESCRIPTION"
IsActive = false
Level = 1
Type = 1
Node = ExtResource("1_aqcna")
Upgrades = [SubResource("Resource_xwv1u"), SubResource("Resource_xwv1u")]
metadata/_custom_type_script = "uid://d4crrfmbgxnqf"

View File

@@ -0,0 +1,34 @@
[gd_resource type="Resource" script_class="SkillData" load_steps=6 format=3 uid="uid://d12defdtmlk0u"]
[ext_resource type="Script" uid="uid://d4crrfmbgxnqf" path="res://scripts/Resources/SkillData.cs" id="1_m360g"]
[ext_resource type="PackedScene" uid="uid://blwk5qduvdnxv" path="res://objects/player_skills/brick_shield_skill_component.tscn" id="1_xjknp"]
[ext_resource type="Script" uid="uid://dwb0e05pewcsn" path="res://scripts/Resources/SkillUpgrade.cs" id="2_lr0w4"]
[sub_resource type="Resource" id="Resource_mu2sy"]
script = ExtResource("2_lr0w4")
Cost = 100
Description = ""
Properties = Dictionary[String, Variant]({
"health": 0.25
})
metadata/_custom_type_script = "uid://dwb0e05pewcsn"
[sub_resource type="Resource" id="Resource_5ab4a"]
script = ExtResource("2_lr0w4")
Cost = 150
Description = ""
Properties = Dictionary[String, Variant]({
"health": 0.5
})
metadata/_custom_type_script = "uid://dwb0e05pewcsn"
[resource]
script = ExtResource("1_m360g")
Name = "BRICK_SHIELD"
Description = "BRICK_SHIELD_DESCRIPTION"
IsActive = false
Level = 1
Type = 2
Node = ExtResource("1_xjknp")
Upgrades = [SubResource("Resource_mu2sy"), SubResource("Resource_5ab4a")]
metadata/_custom_type_script = "uid://d4crrfmbgxnqf"

View File

@@ -0,0 +1,23 @@
[gd_resource type="Resource" script_class="SkillData" load_steps=5 format=3 uid="uid://bxsgq8703qx4u"]
[ext_resource type="Script" uid="uid://d4crrfmbgxnqf" path="res://scripts/Resources/SkillData.cs" id="1_p5qvt"]
[ext_resource type="PackedScene" uid="uid://dwaxbojb44a6l" path="res://objects/player_skills/double_jump_skill.tscn" id="1_t7o84"]
[ext_resource type="Script" uid="uid://dwb0e05pewcsn" path="res://scripts/Resources/SkillUpgrade.cs" id="2_kywbf"]
[sub_resource type="Resource" id="Resource_0fn2n"]
script = ExtResource("2_kywbf")
Cost = 80
Description = ""
Properties = Dictionary[String, Variant]({})
metadata/_custom_type_script = "uid://dwb0e05pewcsn"
[resource]
script = ExtResource("1_p5qvt")
Name = "DOUBLE_JUMP"
Description = "DOUBLE_JUMP_DESCRIPTION"
IsActive = false
Level = 1
Type = 2
Node = ExtResource("1_t7o84")
Upgrades = [SubResource("Resource_0fn2n")]
metadata/_custom_type_script = "uid://d4crrfmbgxnqf"

View File

@@ -0,0 +1,23 @@
[gd_resource type="Resource" script_class="SkillData" load_steps=5 format=3 uid="uid://cseilsspimw1n"]
[ext_resource type="PackedScene" uid="uid://lu3wvpqefekn" path="res://objects/player_skills/ground_pound_skill_component.tscn" id="1_auljr"]
[ext_resource type="Script" uid="uid://d4crrfmbgxnqf" path="res://scripts/Resources/SkillData.cs" id="1_i1qac"]
[ext_resource type="Script" uid="uid://dwb0e05pewcsn" path="res://scripts/Resources/SkillUpgrade.cs" id="2_tkhf7"]
[sub_resource type="Resource" id="Resource_upxa7"]
script = ExtResource("2_tkhf7")
Cost = 300
Description = ""
Properties = Dictionary[String, Variant]({})
metadata/_custom_type_script = "uid://dwb0e05pewcsn"
[resource]
script = ExtResource("1_i1qac")
Name = "GROUND_POUND_SKILL"
Description = "GROUND_POUND_SKILL_DESCRIPTION"
IsActive = false
Level = 1
Type = 2
Node = ExtResource("1_auljr")
Upgrades = [SubResource("Resource_upxa7")]
metadata/_custom_type_script = "uid://d4crrfmbgxnqf"

View File

@@ -0,0 +1,34 @@
[gd_resource type="Resource" script_class="SkillData" load_steps=6 format=3 uid="uid://c5dj06l86winx"]
[ext_resource type="PackedScene" uid="uid://dtxkjif7prm70" path="res://objects/player_skills/x_ray_vision_skill_component.tscn" id="1_ax2d8"]
[ext_resource type="Script" uid="uid://d4crrfmbgxnqf" path="res://scripts/Resources/SkillData.cs" id="1_g8qe3"]
[ext_resource type="Script" uid="uid://dwb0e05pewcsn" path="res://scripts/Resources/SkillUpgrade.cs" id="2_o726x"]
[sub_resource type="Resource" id="Resource_72ltj"]
script = ExtResource("2_o726x")
Cost = 200
Description = ""
Properties = Dictionary[String, Variant]({
"duration": 5.0
})
metadata/_custom_type_script = "uid://dwb0e05pewcsn"
[sub_resource type="Resource" id="Resource_2kdfi"]
script = ExtResource("2_o726x")
Cost = 275
Description = ""
Properties = Dictionary[String, Variant]({
"duration": 10.0
})
metadata/_custom_type_script = "uid://dwb0e05pewcsn"
[resource]
script = ExtResource("1_g8qe3")
Name = "XRAY_VISION"
Description = "XRAY_VISION_DESCRIPTION"
IsActive = false
Level = 1
Type = 1
Node = ExtResource("1_ax2d8")
Upgrades = [SubResource("Resource_72ltj"), SubResource("Resource_2kdfi")]
metadata/_custom_type_script = "uid://d4crrfmbgxnqf"

View File

@@ -59,7 +59,7 @@ ease = 2
[node name="Brick Player" parent="." instance=ExtResource("1_wcma7")]
z_index = 1
[node name="HitParticles" parent="Brick Player" index="26"]
[node name="HitParticles" parent="Brick Player" index="25"]
process_material = SubResource("ParticleProcessMaterial_lgb3u")
[node name="WorldEnvironment" parent="." instance=ExtResource("2_ot3dy")]

View File

@@ -4,6 +4,7 @@ using Godot.Collections;
namespace Mr.BrickAdventures.scripts.Resources;
[GlobalClass]
public partial class SkillData : Resource
{
[Export] public string Name { get; set; } = "New Skill";

View File

@@ -19,12 +19,17 @@ public partial class Marketplace : Control
[Export] public PackedScene SkillButtonScene { get; set; }
private GameManager _gameManager;
private SkillManager _skillManager;
private readonly List<Button> _unlockButtons = [];
private readonly List<SkillButton> _skillButtons = [];
public override void _Ready()
{
_gameManager = GetNode<GameManager>("/root/GameManager");
_skillManager = GetNode<SkillManager>("/root/SkillManager");
_skillManager.SkillRemoved += OnSkillRemoved;
Skills = _skillManager.AvailableSkills;
var skillsToUnlock = new List<SkillData>();
@@ -137,4 +142,22 @@ public partial class Marketplace : Control
btn.Deactivate();
}
}
private void OnSkillRemoved(SkillData skill)
{
SkillButton buttonToRemove = null;
foreach (var button in _skillButtons)
{
if (button.Data == skill)
{
buttonToRemove = button;
break;
}
}
if (buttonToRemove != null)
{
_skillButtons.Remove(buttonToRemove);
buttonToRemove.QueueFree();
}
}
}

View File

@@ -14,6 +14,7 @@ public partial class MarketplaceButton : Button
private GameManager _gameManager;
private SkillUnlockerComponent _skillUnlockerComponent;
private SkillManager _skillManager;
public override void _Ready()
{
@@ -27,6 +28,9 @@ public partial class MarketplaceButton : Button
_skillUnlockerComponent.SkillUnlocked += OnSkillStateChanged;
}
_skillManager = GetNode<SkillManager>("/root/SkillManager");
_skillManager.SkillRemoved += OnSkillStateChanged;
UpdateButtonState();
}

View File

@@ -0,0 +1,48 @@
using Godot;
using Mr.BrickAdventures.scripts.interfaces;
using Mr.BrickAdventures.scripts.Resources;
namespace Mr.BrickAdventures.scripts.components;
[GlobalClass]
public partial class BrickArmorSkillComponent : Node, ISkill
{
private HealthComponent _healthComponent;
private SkillData _skillData;
private float _armorBonus = 0;
public void Initialize(Node owner, SkillData data)
{
if (owner is not PlayerController player) return;
_healthComponent = player.GetNode<HealthComponent>("HealthComponent");
_skillData = data;
}
public void Activate()
{
if (_healthComponent == null || _skillData == null) return;
ApplyUpgrade(_skillData.Upgrades[_skillData.Level - 1]);
}
public void Deactivate()
{
if (_healthComponent == null) return;
_healthComponent.MaxHealth -= _armorBonus;
if (_healthComponent.Health > _healthComponent.MaxHealth)
{
_healthComponent.SetHealth(_healthComponent.MaxHealth);
}
_armorBonus = 0;
}
public void ApplyUpgrade(SkillUpgrade upgrade)
{
if (_healthComponent == null || upgrade == null) return;
_healthComponent.MaxHealth -= _armorBonus;
_armorBonus = (float)upgrade.Properties["health_bonus"];
_healthComponent.MaxHealth += _armorBonus;
_healthComponent.IncreaseHealth(_armorBonus);
}
}

View File

@@ -0,0 +1 @@
uid://5fyepa666cc8

View File

@@ -0,0 +1,72 @@
using Godot;
using Mr.BrickAdventures.Autoloads;
using Mr.BrickAdventures.scripts.interfaces;
using Mr.BrickAdventures.scripts.Resources;
namespace Mr.BrickAdventures.scripts.components;
[GlobalClass]
public partial class BrickShieldSkillComponent : Node, ISkill
{
[Export] public PackedScene ShieldScene { get; set; }
private PlayerController _player;
private Node2D _shieldInstance;
private SkillData _skillData;
private GameManager _gameManager;
private SkillManager _skillManager;
private HealthComponent _shieldHealth;
public override void _Ready()
{
_gameManager = GetNode<GameManager>("/root/GameManager");
_skillManager = GetNode<SkillManager>("/root/SkillManager");
}
public void Initialize(Node owner, SkillData data)
{
_player = owner as PlayerController;
_skillData = data;
}
public void Activate()
{
if (_player == null || ShieldScene == null || _shieldInstance != null) return;
_shieldInstance = ShieldScene.Instantiate<Node2D>();
_player.AddChild(_shieldInstance);
_shieldInstance.Position = Vector2.Zero;
_shieldInstance.TreeExiting += OnShieldDestroyed;
_shieldHealth = _shieldInstance.GetNode<HealthComponent>("HealthComponent");
}
public void Deactivate()
{
if (_shieldInstance != null && IsInstanceValid(_shieldInstance))
{
_shieldInstance.TreeExiting -= OnShieldDestroyed;
_shieldInstance.QueueFree();
}
_shieldInstance = null;
}
public void ApplyUpgrade(SkillUpgrade upgrade)
{
upgrade.Properties.TryGetValue("shield_health", out var newHealth);
if (_shieldHealth != null)
{
_shieldHealth.Health = (float)newHealth;
_shieldHealth.MaxHealth = (float)newHealth;
}
}
private void OnShieldDestroyed()
{
if (_gameManager != null && _skillData != null && _skillManager != null)
{
_gameManager.RemoveSkill(_skillData.Name);
_skillManager.RemoveSkill(_skillData.Name);
}
_shieldInstance = null;
}
}

View File

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

View File

@@ -4,6 +4,7 @@ using Mr.BrickAdventures.scripts.Resources;
namespace Mr.BrickAdventures.scripts.components;
[GlobalClass]
public partial class BrickThrowComponent : Node, ISkill
{
[Export] public PackedScene BrickScene { get; set; }

View File

@@ -2,6 +2,7 @@ using Godot;
namespace Mr.BrickAdventures.scripts.components;
[GlobalClass]
public partial class BulletComponent : Node
{
[Export] public Area2D Area { get; set; }

View File

@@ -3,6 +3,7 @@ using Godot;
namespace Mr.BrickAdventures.scripts.components;
[GlobalClass]
public partial class CageComponent : Node
{
[Export] public LeverComponent Lever { get; set; }

View File

@@ -2,6 +2,7 @@ using Godot;
namespace Mr.BrickAdventures.scripts.components;
[GlobalClass]
public partial class CanBeLaunchedComponent : Node
{

View File

@@ -2,6 +2,7 @@ using Godot;
namespace Mr.BrickAdventures.scripts.components;
[GlobalClass]
public partial class CanPickUpComponent : Node
{

View File

@@ -2,6 +2,7 @@ using Godot;
namespace Mr.BrickAdventures.scripts.components;
[GlobalClass]
public partial class CannotStompComponent : Node
{

View File

@@ -3,6 +3,7 @@ using PhantomCamera;
namespace Mr.BrickAdventures.scripts.components;
[GlobalClass]
public partial class ChaseLevelComponent : Node
{
[Export] public float ChaseSpeed { get; set; } = 200.0f;

View File

@@ -2,6 +2,7 @@ using Godot;
namespace Mr.BrickAdventures.scripts.components;
[GlobalClass]
public partial class CleanupComponent : Node
{
public void CleanUp()

View File

@@ -3,6 +3,7 @@ using Godot;
namespace Mr.BrickAdventures.scripts.components;
[GlobalClass]
public partial class CollapsableComponent : Node
{
[Export] public Timer ToCollapseTimer { get; set; }

View File

@@ -4,6 +4,7 @@ using Mr.BrickAdventures.scripts.Resources;
namespace Mr.BrickAdventures.scripts.components;
[GlobalClass]
public partial class CollectableComponent : Node
{
private bool _hasFadeAway = false;

View File

@@ -3,6 +3,7 @@ using Mr.BrickAdventures.scripts.Resources;
namespace Mr.BrickAdventures.scripts.components;
[GlobalClass]
public partial class DamageComponent : Node
{
[Export] public float Damage { get; set; } = 0.25f;

View File

@@ -2,6 +2,7 @@ using Godot;
namespace Mr.BrickAdventures.scripts.components;
[GlobalClass]
public partial class DestroyableComponent : Node2D
{
[Export] public HealthComponent Health { get; set; }

View File

@@ -0,0 +1,45 @@
using System.Linq;
using Godot;
using Mr.BrickAdventures.scripts.interfaces;
using Mr.BrickAdventures.scripts.Resources;
namespace Mr.BrickAdventures.scripts.components;
[GlobalClass]
public partial class DoubleJumpSkillComponent : Node, ISkill
{
[Export] private PackedScene _doubleJumpAbilityScene;
private PlayerController _playerController;
public void Initialize(Node owner, SkillData data)
{
_playerController = owner as PlayerController;
if (_playerController == null)
{
GD.PrintErr("DoubleJumpSkillComponent must be a child of a PlayerController.");
}
}
public void Activate()
{
if (_playerController == null) return;
var hasAbility = _playerController.GetActiveAbilities().Any(ability => ability is DoubleJumpAbility);
if (!hasAbility)
{
var abilityInstance = _doubleJumpAbilityScene.Instantiate<DoubleJumpAbility>();
_playerController.AddAbility(abilityInstance);
}
}
public void Deactivate()
{
_playerController?.RemoveAbility<DoubleJumpAbility>();
}
public void ApplyUpgrade(SkillUpgrade upgrade)
{
}
}

View File

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

View File

@@ -3,6 +3,7 @@ using Mr.BrickAdventures.scripts.Resources;
namespace Mr.BrickAdventures.scripts.components;
[GlobalClass]
public partial class EffectInflictorComponent : Node
{
[Export] public DamageComponent Damage { get; set; }

View File

@@ -3,6 +3,7 @@ using Godot;
namespace Mr.BrickAdventures.scripts.components;
[GlobalClass]
public partial class EnemyDeathComponent : Node
{
[Export] public float TweenDuration { get; set; } = 0.5f;

View File

@@ -4,6 +4,7 @@ using Mr.BrickAdventures.scripts.interfaces;
namespace Mr.BrickAdventures.scripts.components;
[GlobalClass]
public partial class ExitDoorComponent : Area2D, IUnlockable
{
[Export] public bool Locked { get; set; } = true;

View File

@@ -2,6 +2,7 @@ using Godot;
namespace Mr.BrickAdventures.scripts.components;
[GlobalClass]
public partial class ExplosiveComponent : Node2D
{
[Export] public DamageComponent Damage { get; set; }

View File

@@ -3,6 +3,7 @@ using Godot;
namespace Mr.BrickAdventures.scripts.components;
[GlobalClass]
public partial class FadeAwayComponent : Node
{
[Export] public Sprite2D Sprite { get; set; }

View File

@@ -3,6 +3,7 @@ using Mr.BrickAdventures.scripts.Resources;
namespace Mr.BrickAdventures.scripts.components;
[GlobalClass]
public partial class FireEffectComponent : Node
{
[Export] public HealthComponent Health { get; set; }

View File

@@ -2,6 +2,7 @@ using Godot;
namespace Mr.BrickAdventures.scripts.components;
[GlobalClass]
public partial class FlashingComponent : Node
{
[Export] public Node2D Sprite { get; set; }

View File

@@ -2,6 +2,7 @@ using Godot;
namespace Mr.BrickAdventures.scripts.components;
[GlobalClass]
public partial class FlipComponent : Node2D
{
[Export] public Sprite2D LeftEye { get; set; }

View File

@@ -2,6 +2,7 @@ using Godot;
namespace Mr.BrickAdventures.scripts.components;
[GlobalClass]
public partial class GravityMotionComponent : Node2D
{
[Export] public CharacterBody2D Body { get; set; }

View File

@@ -0,0 +1,66 @@
using Godot;
using Mr.BrickAdventures.scripts.interfaces;
using Mr.BrickAdventures.scripts.Resources;
namespace Mr.BrickAdventures.scripts.components;
[GlobalClass]
public partial class GroundPoundSkillComponent : Node, ISkill
{
[Export] public float PoundForce { get; set; } = 1200f;
[Export] public PackedScene ShockwaveScene { get; set; }
private PlayerController _player;
private PlayerInputHandler _input;
private bool _isPounding = false;
public void Initialize(Node owner, SkillData data)
{
_player = owner as PlayerController;
if (_player != null)
{
_input = _player.GetNode<PlayerInputHandler>("PlayerInputHandler");
}
}
public override void _PhysicsProcess(double delta)
{
if (_player == null || _input == null)
{
return;
}
// Check if we just landed from a ground pound to create the shockwave.
if (_isPounding && _player.IsOnFloor())
{
_isPounding = false;
if (ShockwaveScene != null)
{
var shockwave = ShockwaveScene.Instantiate<Node2D>();
_player.GetParent()?.AddChild(shockwave);
shockwave.GlobalPosition = _player.GlobalPosition;
}
}
// Check to initiate a ground pound. The player must be in the air.
if (_input.DownHeld && !_player.IsOnFloor() && !_isPounding)
{
// Apply a strong downward force, zeroing out horizontal movement.
_player.Velocity = new Vector2(0, PoundForce);
_isPounding = true;
}
}
public void Activate()
{
SetPhysicsProcess(true);
}
public void Deactivate()
{
SetPhysicsProcess(false);
_isPounding = false;
}
public void ApplyUpgrade(SkillUpgrade upgrade) { }
}

View File

@@ -0,0 +1 @@
uid://3sclg5kdjg13

View File

@@ -3,6 +3,7 @@ using Mr.BrickAdventures.scripts.Resources;
namespace Mr.BrickAdventures.scripts.components;
[GlobalClass]
public partial class HealComponent : Node
{
[Export] public GpuParticles2D HealFx { get; set; }

View File

@@ -4,6 +4,7 @@ using Mr.BrickAdventures.Autoloads;
namespace Mr.BrickAdventures.scripts.components;
[GlobalClass]
public partial class HealthComponent : Node2D
{
[Export] public float Health { get; set; } = 1.0f;

View File

@@ -2,6 +2,7 @@ using Godot;
namespace Mr.BrickAdventures.scripts.components;
[GlobalClass]
public partial class HitComponent : Node
{
[Export] public Sprite2D Sprite { get; set; }

View File

@@ -2,6 +2,7 @@ using Godot;
namespace Mr.BrickAdventures.scripts.components;
[GlobalClass]
public partial class HomingMissileMotionComponent : Node
{
[Export] public LaunchComponent Launch { get; set; }

View File

@@ -4,6 +4,7 @@ using Mr.BrickAdventures.scripts.Resources;
namespace Mr.BrickAdventures.scripts.components;
[GlobalClass]
public partial class IceEffectComponent : Node
{
[Export] public Array<Node> ComponentsToDisable { get; set; } = [];

View File

@@ -2,6 +2,7 @@ using Godot;
namespace Mr.BrickAdventures.scripts.components;
[GlobalClass]
public partial class InvulnerabilityComponent : Node
{
[Export] public float Duration { get; set; } = 1f;

View File

@@ -3,6 +3,7 @@ using Godot;
namespace Mr.BrickAdventures.scripts.components;
[GlobalClass]
public partial class JumpPadComponent : Node
{
[Export] public float JumpForce { get; set; } = 10f;

View File

@@ -2,6 +2,7 @@ using Godot;
namespace Mr.BrickAdventures.scripts.components;
[GlobalClass]
public partial class KillPlayerOutOfScreenComponent : Node
{
[Export] public VisibleOnScreenNotifier2D ScreenNotifier { get; set; }

View File

@@ -2,6 +2,7 @@ using Godot;
namespace Mr.BrickAdventures.scripts.components;
[GlobalClass]
public partial class KnockbackComponent : Node
{
[Export] public CharacterBody2D Body { get; set; }

View File

@@ -2,6 +2,7 @@ using Godot;
namespace Mr.BrickAdventures.scripts.components;
[GlobalClass]
public partial class LaunchComponent : Node2D
{
[Export] public Vector2 InitialDirection { get; set; } = Vector2.Right;

View File

@@ -3,6 +3,7 @@ using Godot;
namespace Mr.BrickAdventures.scripts.components;
[GlobalClass]
public partial class LeverComponent : Node
{
[Export] public Area2D Area { get; set; }

View File

@@ -2,6 +2,7 @@ using Godot;
namespace Mr.BrickAdventures.scripts.components;
[GlobalClass]
public partial class LifetimeComponent : Node
{
[Export] public float LifeTime { get; set; } = 5.0f;

View File

@@ -6,6 +6,7 @@ using Mr.BrickAdventures.scripts.Resources;
namespace Mr.BrickAdventures.scripts.components;
[GlobalClass]
public partial class MagneticSkillComponent : Node, ISkill
{
[Export] public Area2D MagneticArea { get; set; }

View File

@@ -0,0 +1,46 @@
using Godot;
namespace Mr.BrickAdventures.scripts.components;
[GlobalClass]
public partial class DoubleJumpAbility : MovementAbility
{
private bool _hasDoubleJumped = false;
private float _jumpVelocity;
public override void Initialize(PlayerController controller)
{
base.Initialize(controller);
foreach (var ability in _controller.GetActiveAbilities())
{
if (ability is VariableJumpAbility jumpAbility)
{
_jumpVelocity = (2.0f * jumpAbility.JumpHeight) / jumpAbility.JumpTimeToPeak * -1.0f;
break;
}
}
if (_jumpVelocity == 0)
{
_jumpVelocity = -400.0f;
}
}
public override Vector2 ProcessMovement(Vector2 velocity, double delta)
{
if (_body.IsOnFloor())
{
_hasDoubleJumped = false;
}
if (_input.JumpPressed && !_body.IsOnFloor() && !_hasDoubleJumped)
{
velocity.Y = _jumpVelocity;
_controller.EmitSignal(PlayerController.SignalName.JumpInitiated);
_hasDoubleJumped = true;
}
return velocity;
}
}

View File

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

View File

@@ -2,6 +2,7 @@ using Godot;
namespace Mr.BrickAdventures.scripts.components;
[GlobalClass]
public partial class OutOfScreenComponent : Node
{
[Export] public VisibleOnScreenNotifier2D VisibilityNotifier { get; set; }

View File

@@ -2,6 +2,7 @@ using Godot;
namespace Mr.BrickAdventures.scripts.components;
[GlobalClass]
public partial class PeriodicShootingComponent : Node
{
[Export] public PackedScene BulletScene { get; set; }

View File

@@ -3,6 +3,7 @@ using Mr.BrickAdventures.Autoloads;
namespace Mr.BrickAdventures.scripts.components;
[GlobalClass]
public partial class PlayerDeathComponent : Node2D
{
[Export] public AudioStreamPlayer2D DeathSfx { get; set; }

View File

@@ -10,6 +10,7 @@ public class ProjectileInitParams
public float PowerMultiplier { get; set; } = 1f;
}
[GlobalClass]
public partial class ProjectileInitComponent : Node
{
[Export] public LaunchComponent LaunchComponent { get; set; }

View File

@@ -3,6 +3,7 @@ using Mr.BrickAdventures.scripts.Resources;
namespace Mr.BrickAdventures.scripts.components;
[GlobalClass]
public partial class RequirementComponent : Node
{
[Export] public CollectableType RequirementType { get; set; }

View File

@@ -4,6 +4,7 @@ using Mr.BrickAdventures.scripts.Resources;
namespace Mr.BrickAdventures.scripts.components;
[GlobalClass]
public partial class ScoreComponent : Node
{
private GameManager _gameManager;

View File

@@ -3,6 +3,7 @@ using Godot;
namespace Mr.BrickAdventures.scripts.components;
[GlobalClass]
public partial class ShipShooterComponent : Node
{
[Export] public PackedScene BulletScene { get; set; }

View File

@@ -2,6 +2,7 @@ using Godot;
namespace Mr.BrickAdventures.scripts.components;
[GlobalClass]
public partial class SideToSideMovementComponent : Node
{
[Export] public Sprite2D Sprite { get; set; }

View File

@@ -6,6 +6,7 @@ using Mr.BrickAdventures.scripts.Resources;
namespace Mr.BrickAdventures.scripts.components;
[GlobalClass]
public partial class SkillUnlockerComponent : Node
{
public SkillManager SkillManager { get; private set; }

View File

@@ -2,6 +2,7 @@ using Godot;
namespace Mr.BrickAdventures.scripts.components;
[GlobalClass]
public partial class SpaceshipEnterComponent : Area2D
{
[Signal] public delegate void SpaceshipEnteredEventHandler();

View File

@@ -2,6 +2,7 @@ using Godot;
namespace Mr.BrickAdventures.scripts.components;
[GlobalClass]
public partial class SpaceshipExitComponent : Area2D
{
[Signal] public delegate void SpaceshipExitEventHandler();

View File

@@ -2,6 +2,7 @@ using Godot;
namespace Mr.BrickAdventures.scripts.components;
[GlobalClass]
public partial class SpinComponent : Node
{
[Export] public float SpinSpeed { get; set; } = 8f;

View File

@@ -11,6 +11,7 @@ public partial class StatusEffect : GodotObject
public Timer Timer { get; set; }
}
[GlobalClass]
public partial class StatusEffectComponent : Node
{
private List<StatusEffect> _activeEffects = [];

View File

@@ -2,6 +2,7 @@ using Godot;
namespace Mr.BrickAdventures.scripts.components;
[GlobalClass]
public partial class StompDamageComponent : Node
{
[Export] public float Damage { get; set; } = 0.25f;

View File

@@ -2,6 +2,7 @@ using Godot;
namespace Mr.BrickAdventures.scripts.components;
[GlobalClass]
public partial class StraightMotionComponent : Node
{
[Export] public LaunchComponent LaunchComponent { get; set; }

View File

@@ -5,6 +5,7 @@ using Godot;
namespace Mr.BrickAdventures.scripts.components;
[GlobalClass]
public partial class TerrainHitFx : Node
{
private List<GpuParticles2D> _gpuParticles = [];

View File

@@ -2,6 +2,7 @@ using Godot;
namespace Mr.BrickAdventures.scripts.components;
[GlobalClass]
public partial class TooltipComponent : Area2D
{
[Export] public Control UiRoot { get; set; }

View File

@@ -3,6 +3,7 @@ using Godot;
namespace Mr.BrickAdventures.scripts.components;
[GlobalClass]
public partial class TrailComponent : Line2D
{
[Export] public int MaxPoints { get; set; } = 100;

View File

@@ -2,6 +2,7 @@ using Godot;
namespace Mr.BrickAdventures.scripts.components;
[GlobalClass]
public partial class TriggerLeverComponent : Node
{

View File

@@ -4,6 +4,7 @@ using Mr.BrickAdventures.scripts.Resources;
namespace Mr.BrickAdventures.scripts.components;
[GlobalClass]
public partial class UnlockOnRequirementComponent : Node
{
[Export] public RequirementComponent RequirementComponent { get; set; }

View File

@@ -0,0 +1,51 @@
using Godot;
using Mr.BrickAdventures.scripts.interfaces;
using Mr.BrickAdventures.scripts.Resources;
namespace Mr.BrickAdventures.scripts.components;
[GlobalClass]
public partial class XRayVisionSkillComponent : Node, ISkill
{
[Export(PropertyHint.Layers2DRender)] public uint SecretLayer { get; set; }
[Export] public float Duration { get; set; } = 5.0f;
private Camera2D _camera;
private Viewport _viewport;
private uint _originalVisibilityLayer;
private Timer _timer;
public void Initialize(Node owner, SkillData data)
{
_viewport = GetViewport();
_camera = GetViewport().GetCamera2D();
_timer = new Timer { OneShot = true };
AddChild(_timer);
_timer.Timeout += Deactivate;
}
public void Activate()
{
if (_camera == null) return;
_originalVisibilityLayer = _camera.VisibilityLayer;
_camera.VisibilityLayer |= SecretLayer;
_timer.Start(Duration);
}
public void Deactivate()
{
if (_camera != null)
{
_camera.VisibilityLayer = _originalVisibilityLayer;
}
}
public void ApplyUpgrade(SkillUpgrade upgrade)
{
if (upgrade.Properties.TryGetValue("duration", out var newDuration))
{
Duration = (float)newDuration;
}
}
}

View File

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