From d84f7d17406f0f17571598aea9e43b3681c2282b Mon Sep 17 00:00:00 2001 From: Gabriel Kaszewski Date: Fri, 15 Aug 2025 00:45:57 +0200 Subject: [PATCH] Csharp rewrite (#4) * Implement BeamComponent in C# and enhance marketplace button functionality * Add core game components including ConfigFileHandler, GameManager, SaveSystem, and UIManager * cleanup * Add new components: CanPickUpComponent, CollapsableComponent, DestroyableComponent, EffectInflictorComponent, StatusEffectComponent, and StatusEffectDataResource * Add new components: EnemyDeathComponent, EnemyWaveTriggerComponent, and ExitDoorComponent * Add new components: ExplosiveComponent, FadeAwayComponent, FireEffectComponent, FlipComponent, GravityMotionComponent, LaunchComponent, and update PlatformMovement with LastDirection property * Add new components: HealComponent, HitComponent, HomingMissileMotionComponent, LeverComponent, and TriggerLeverComponent * Refactor GameManager session state handling and add new components: CanBeLaunchedComponent, IceEffectComponent, JumpPadComponent, KillPlayerOutOfScreenComponent, KnockbackComponent, LifetimeComponent, MagneticSkillComponent, OutOfScreenComponent, PeriodicShootingComponent, PlayerDeathComponent, ProgressiveDamageComponent, ProjectileComponent, ProjectileInitComponent, RequirementComponent, ScoreComponent, ShipMovementComponent, ShipShooterComponent, and SideToSideMovementComponent * Add new components: CannotStompComponent, SkillUnlockedComponent, SpaceshipEnterComponent, SpaceshipExitComponent, SpinComponent, StompDamageComponent, StraightMotionComponent, TerrainHitFx, TooltipComponent, TrailComponent, and UnlockOnRequirementComponent * Add new components: BrickThrowComponent, BulletComponent, CageComponent, ChaseLevelComponent, CleanupComponent, and ThrowInputResource classes; implement game saving and loading logic in SaveSystem * Add audio settings management and platform movement component * Add ChargeProgressBar, Credits, and GameOverScreen components for UI management * Add UID files for ConfigFileHandler, GameManager, SaveSystem, and UIManager components * Add README.md file with game description and features; include project license and contribution guidelines * Add Hud component for UI management; display health, coins, and lives * Add MainMenu and Marketplace components; implement game management and skill unlocking features * Add PauseMenu, SettingsMenu, and SkillButton components; enhance game management and UI functionality --- Autoloads/ConfigFileHandler.cs | 27 ++ Autoloads/ConfigFileHandler.cs.uid | 1 + Autoloads/GameManager.cs | 241 ++++++++++++++++++ Autoloads/GameManager.cs.uid | 1 + Autoloads/SaveSystem.cs | 61 +++++ Autoloads/SaveSystem.cs.uid | 1 + Autoloads/UIManager.cs | 65 +++++ Autoloads/UIManager.cs.uid | 1 + Mr. Brick Adventures.csproj | 143 +++++++++++ Mr. Brick Adventures.sln | 19 ++ Mr. Brick Adventures.sln.DotSettings.user | 6 + autoloads/ui_manager.gd | 2 +- project.godot | 2 +- scripts/Resources/ChargeThrowInputResource.cs | 70 +++++ .../Resources/ChargeThrowInputResource.cs.uid | 1 + scripts/Resources/CollectableResource.cs | 9 + scripts/Resources/CollectableResource.cs.uid | 1 + scripts/Resources/CollectableType.cs | 8 + scripts/Resources/CollectableType.cs.uid | 1 + scripts/Resources/SkillData.cs | 19 ++ scripts/Resources/SkillData.cs.uid | 1 + scripts/Resources/SkillType.cs | 8 + scripts/Resources/SkillType.cs.uid | 1 + scripts/Resources/StatusEffectDataResource.cs | 10 + .../Resources/StatusEffectDataResource.cs.uid | 1 + scripts/Resources/StatusEffectType.cs | 8 + scripts/Resources/StatusEffectType.cs.uid | 1 + scripts/Resources/TapThrowInputResource.cs | 20 ++ .../Resources/TapThrowInputResource.cs.uid | 1 + scripts/Resources/ThrowInputResource.cs | 24 ++ scripts/Resources/ThrowInputResource.cs.uid | 1 + scripts/Screenshot.cs | 15 ++ scripts/Screenshot.cs.uid | 1 + scripts/SkillManager.cs | 144 +++++++++++ scripts/SkillManager.cs.uid | 1 + scripts/UI/AudioSettings.cs | 102 ++++++++ scripts/UI/AudioSettings.cs.uid | 1 + scripts/UI/ChargeProgressBar.cs | 81 ++++++ scripts/UI/ChargeProgressBar.cs.uid | 1 + scripts/UI/Credits.cs | 23 ++ scripts/UI/Credits.cs.uid | 1 + scripts/UI/GameOverScreen.cs | 39 +++ scripts/UI/GameOverScreen.cs.uid | 1 + scripts/UI/Hud.cs | 43 ++++ scripts/UI/Hud.cs.uid | 1 + scripts/UI/MainMenu.cs | 67 +++++ scripts/UI/MainMenu.cs.uid | 1 + scripts/UI/Marketplace.cs | 142 +++++++++++ scripts/UI/Marketplace.cs.uid | 1 + scripts/UI/MarketplaceButton.cs | 62 +++++ scripts/UI/MarketplaceButton.cs.uid | 1 + scripts/UI/PauseMenu.cs | 67 +++++ scripts/UI/PauseMenu.cs.uid | 1 + scripts/UI/SettingsMenu.cs | 60 +++++ scripts/UI/SettingsMenu.cs.uid | 1 + scripts/UI/SkillButton.cs | 25 ++ scripts/UI/SkillButton.cs.uid | 1 + scripts/components/BeamComponent.cs | 109 ++++++++ scripts/components/BeamComponent.cs.uid | 1 + scripts/components/BrickThrowComponent.cs | 70 +++++ scripts/components/BrickThrowComponent.cs.uid | 1 + scripts/components/BulletComponent.cs | 45 ++++ scripts/components/BulletComponent.cs.uid | 1 + scripts/components/CageComponent.cs | 47 ++++ scripts/components/CageComponent.cs.uid | 1 + scripts/components/CanBeLaunchedComponent.cs | 8 + .../components/CanBeLaunchedComponent.cs.uid | 1 + scripts/components/CanPickUpComponent.cs | 8 + scripts/components/CanPickUpComponent.cs.uid | 1 + scripts/components/CannotStompComponent.cs | 8 + .../components/CannotStompComponent.cs.uid | 1 + scripts/components/ChaseLevelComponent.cs | 79 ++++++ scripts/components/ChaseLevelComponent.cs.uid | 1 + scripts/components/CleanupComponent.cs | 11 + scripts/components/CleanupComponent.cs.uid | 1 + scripts/components/CollapsableComponent.cs | 81 ++++++ .../components/CollapsableComponent.cs.uid | 1 + scripts/components/CollectableComponent.cs | 50 ++++ .../components/CollectableComponent.cs.uid | 1 + scripts/components/DamageComponent.cs | 105 ++++++++ scripts/components/DamageComponent.cs.uid | 1 + scripts/components/DestroyableComponent.cs | 35 +++ .../components/DestroyableComponent.cs.uid | 1 + .../components/EffectInflictorComponent.cs | 27 ++ .../EffectInflictorComponent.cs.uid | 1 + scripts/components/EnemyDeathComponent.cs | 42 +++ scripts/components/EnemyDeathComponent.cs.uid | 1 + .../components/EnemyWaveTriggerComponent.cs | 51 ++++ .../EnemyWaveTriggerComponent.cs.uid | 1 + scripts/components/ExitDoorComponent.cs | 52 ++++ scripts/components/ExitDoorComponent.cs.uid | 1 + scripts/components/ExplosiveComponent.cs | 81 ++++++ scripts/components/ExplosiveComponent.cs.uid | 1 + scripts/components/FadeAwayComponent.cs | 32 +++ scripts/components/FadeAwayComponent.cs.uid | 1 + scripts/components/FireEffectComponent.cs | 71 ++++++ scripts/components/FireEffectComponent.cs.uid | 1 + scripts/components/FlashingComponent.cs | 83 ++++++ scripts/components/FlashingComponent.cs.uid | 1 + scripts/components/FlipComponent.cs | 36 +++ scripts/components/FlipComponent.cs.uid | 1 + scripts/components/GravityMotionComponent.cs | 37 +++ .../components/GravityMotionComponent.cs.uid | 1 + scripts/components/HealComponent.cs | 48 ++++ scripts/components/HealComponent.cs.uid | 1 + scripts/components/HealthComponent.cs | 65 +++++ scripts/components/HealthComponent.cs.uid | 1 + scripts/components/HitComponent.cs | 75 ++++++ scripts/components/HitComponent.cs.uid | 1 + .../HomingMissileMotionComponent.cs | 64 +++++ .../HomingMissileMotionComponent.cs.uid | 1 + scripts/components/IceEffectComponent.cs | 70 +++++ scripts/components/IceEffectComponent.cs.uid | 1 + .../components/InvulnerabilityComponent.cs | 31 +++ .../InvulnerabilityComponent.cs.uid | 1 + scripts/components/JumpPadComponent.cs | 39 +++ scripts/components/JumpPadComponent.cs.uid | 1 + .../KillPlayerOutOfScreenComponent.cs | 21 ++ .../KillPlayerOutOfScreenComponent.cs.uid | 1 + scripts/components/KnockbackComponent.cs | 48 ++++ scripts/components/KnockbackComponent.cs.uid | 1 + scripts/components/LaunchComponent.cs | 24 ++ scripts/components/LaunchComponent.cs.uid | 1 + scripts/components/LeverComponent.cs | 66 +++++ scripts/components/LeverComponent.cs.uid | 1 + scripts/components/LifetimeComponent.cs | 27 ++ scripts/components/LifetimeComponent.cs.uid | 1 + scripts/components/MagneticSkillComponent.cs | 78 ++++++ .../components/MagneticSkillComponent.cs.uid | 1 + scripts/components/OutOfScreenComponent.cs | 18 ++ .../components/OutOfScreenComponent.cs.uid | 1 + .../components/PeriodicShootingComponent.cs | 71 ++++++ .../PeriodicShootingComponent.cs.uid | 1 + .../components/PlatformMovementComponent.cs | 171 +++++++++++++ .../PlatformMovementComponent.cs.uid | 1 + scripts/components/PlayerController.cs | 103 ++++++++ scripts/components/PlayerController.cs.uid | 1 + scripts/components/PlayerDeathComponent.cs | 36 +++ .../components/PlayerDeathComponent.cs.uid | 1 + .../components/ProgressiveDamageComponent.cs | 65 +++++ .../ProgressiveDamageComponent.cs.uid | 1 + scripts/components/ProjectileComponent.cs | 26 ++ scripts/components/ProjectileComponent.cs.uid | 1 + scripts/components/ProjectileInitComponent.cs | 37 +++ .../components/ProjectileInitComponent.cs.uid | 1 + scripts/components/RequirementComponent.cs | 44 ++++ .../components/RequirementComponent.cs.uid | 1 + scripts/components/ScoreComponent.cs | 42 +++ scripts/components/ScoreComponent.cs.uid | 1 + scripts/components/ShipMovementComponent.cs | 38 +++ .../components/ShipMovementComponent.cs.uid | 1 + scripts/components/ShipShooterComponent.cs | 59 +++++ .../components/ShipShooterComponent.cs.uid | 1 + .../components/SideToSideMovementComponent.cs | 117 +++++++++ .../SideToSideMovementComponent.cs.uid | 1 + scripts/components/SkillUnlockedComponent.cs | 70 +++++ .../components/SkillUnlockedComponent.cs.uid | 1 + scripts/components/SpaceshipEnterComponent.cs | 21 ++ .../components/SpaceshipEnterComponent.cs.uid | 1 + scripts/components/SpaceshipExitComponent.cs | 20 ++ .../components/SpaceshipExitComponent.cs.uid | 1 + scripts/components/SpinComponent.cs | 23 ++ scripts/components/SpinComponent.cs.uid | 1 + scripts/components/StatusEffectComponent.cs | 55 ++++ .../components/StatusEffectComponent.cs.uid | 1 + scripts/components/StompDamageComponent.cs | 43 ++++ .../components/StompDamageComponent.cs.uid | 1 + scripts/components/StraightMotionComponent.cs | 19 ++ .../components/StraightMotionComponent.cs.uid | 1 + scripts/components/TerrainHitFx.cs | 33 +++ scripts/components/TerrainHitFx.cs.uid | 1 + scripts/components/TooltipComponent.cs | 39 +++ scripts/components/TooltipComponent.cs.uid | 1 + scripts/components/TrailComponent.cs | 22 ++ scripts/components/TrailComponent.cs.uid | 1 + scripts/components/TriggerLeverComponent.cs | 8 + .../components/TriggerLeverComponent.cs.uid | 1 + .../UnlockOnRequirementComponent.cs | 25 ++ .../UnlockOnRequirementComponent.cs.uid | 1 + scripts/components/beam_component.gd | 2 +- scripts/components/platform_movement.gd.uid | 2 +- scripts/interfaces/IMovement.cs | 14 + scripts/interfaces/IMovement.cs.uid | 1 + scripts/interfaces/IThrowInput.cs | 10 + scripts/interfaces/IThrowInput.cs.uid | 1 + scripts/interfaces/IUnlockable.cs | 6 + scripts/interfaces/IUnlockable.cs.uid | 1 + scripts/ui/marketplace.gd | 27 +- 188 files changed, 4774 insertions(+), 18 deletions(-) create mode 100644 Autoloads/ConfigFileHandler.cs create mode 100644 Autoloads/ConfigFileHandler.cs.uid create mode 100644 Autoloads/GameManager.cs create mode 100644 Autoloads/GameManager.cs.uid create mode 100644 Autoloads/SaveSystem.cs create mode 100644 Autoloads/SaveSystem.cs.uid create mode 100644 Autoloads/UIManager.cs create mode 100644 Autoloads/UIManager.cs.uid create mode 100644 Mr. Brick Adventures.csproj create mode 100644 Mr. Brick Adventures.sln create mode 100644 Mr. Brick Adventures.sln.DotSettings.user create mode 100644 scripts/Resources/ChargeThrowInputResource.cs create mode 100644 scripts/Resources/ChargeThrowInputResource.cs.uid create mode 100644 scripts/Resources/CollectableResource.cs create mode 100644 scripts/Resources/CollectableResource.cs.uid create mode 100644 scripts/Resources/CollectableType.cs create mode 100644 scripts/Resources/CollectableType.cs.uid create mode 100644 scripts/Resources/SkillData.cs create mode 100644 scripts/Resources/SkillData.cs.uid create mode 100644 scripts/Resources/SkillType.cs create mode 100644 scripts/Resources/SkillType.cs.uid create mode 100644 scripts/Resources/StatusEffectDataResource.cs create mode 100644 scripts/Resources/StatusEffectDataResource.cs.uid create mode 100644 scripts/Resources/StatusEffectType.cs create mode 100644 scripts/Resources/StatusEffectType.cs.uid create mode 100644 scripts/Resources/TapThrowInputResource.cs create mode 100644 scripts/Resources/TapThrowInputResource.cs.uid create mode 100644 scripts/Resources/ThrowInputResource.cs create mode 100644 scripts/Resources/ThrowInputResource.cs.uid create mode 100644 scripts/Screenshot.cs create mode 100644 scripts/Screenshot.cs.uid create mode 100644 scripts/SkillManager.cs create mode 100644 scripts/SkillManager.cs.uid create mode 100644 scripts/UI/AudioSettings.cs create mode 100644 scripts/UI/AudioSettings.cs.uid create mode 100644 scripts/UI/ChargeProgressBar.cs create mode 100644 scripts/UI/ChargeProgressBar.cs.uid create mode 100644 scripts/UI/Credits.cs create mode 100644 scripts/UI/Credits.cs.uid create mode 100644 scripts/UI/GameOverScreen.cs create mode 100644 scripts/UI/GameOverScreen.cs.uid create mode 100644 scripts/UI/Hud.cs create mode 100644 scripts/UI/Hud.cs.uid create mode 100644 scripts/UI/MainMenu.cs create mode 100644 scripts/UI/MainMenu.cs.uid create mode 100644 scripts/UI/Marketplace.cs create mode 100644 scripts/UI/Marketplace.cs.uid create mode 100644 scripts/UI/MarketplaceButton.cs create mode 100644 scripts/UI/MarketplaceButton.cs.uid create mode 100644 scripts/UI/PauseMenu.cs create mode 100644 scripts/UI/PauseMenu.cs.uid create mode 100644 scripts/UI/SettingsMenu.cs create mode 100644 scripts/UI/SettingsMenu.cs.uid create mode 100644 scripts/UI/SkillButton.cs create mode 100644 scripts/UI/SkillButton.cs.uid create mode 100644 scripts/components/BeamComponent.cs create mode 100644 scripts/components/BeamComponent.cs.uid create mode 100644 scripts/components/BrickThrowComponent.cs create mode 100644 scripts/components/BrickThrowComponent.cs.uid create mode 100644 scripts/components/BulletComponent.cs create mode 100644 scripts/components/BulletComponent.cs.uid create mode 100644 scripts/components/CageComponent.cs create mode 100644 scripts/components/CageComponent.cs.uid create mode 100644 scripts/components/CanBeLaunchedComponent.cs create mode 100644 scripts/components/CanBeLaunchedComponent.cs.uid create mode 100644 scripts/components/CanPickUpComponent.cs create mode 100644 scripts/components/CanPickUpComponent.cs.uid create mode 100644 scripts/components/CannotStompComponent.cs create mode 100644 scripts/components/CannotStompComponent.cs.uid create mode 100644 scripts/components/ChaseLevelComponent.cs create mode 100644 scripts/components/ChaseLevelComponent.cs.uid create mode 100644 scripts/components/CleanupComponent.cs create mode 100644 scripts/components/CleanupComponent.cs.uid create mode 100644 scripts/components/CollapsableComponent.cs create mode 100644 scripts/components/CollapsableComponent.cs.uid create mode 100644 scripts/components/CollectableComponent.cs create mode 100644 scripts/components/CollectableComponent.cs.uid create mode 100644 scripts/components/DamageComponent.cs create mode 100644 scripts/components/DamageComponent.cs.uid create mode 100644 scripts/components/DestroyableComponent.cs create mode 100644 scripts/components/DestroyableComponent.cs.uid create mode 100644 scripts/components/EffectInflictorComponent.cs create mode 100644 scripts/components/EffectInflictorComponent.cs.uid create mode 100644 scripts/components/EnemyDeathComponent.cs create mode 100644 scripts/components/EnemyDeathComponent.cs.uid create mode 100644 scripts/components/EnemyWaveTriggerComponent.cs create mode 100644 scripts/components/EnemyWaveTriggerComponent.cs.uid create mode 100644 scripts/components/ExitDoorComponent.cs create mode 100644 scripts/components/ExitDoorComponent.cs.uid create mode 100644 scripts/components/ExplosiveComponent.cs create mode 100644 scripts/components/ExplosiveComponent.cs.uid create mode 100644 scripts/components/FadeAwayComponent.cs create mode 100644 scripts/components/FadeAwayComponent.cs.uid create mode 100644 scripts/components/FireEffectComponent.cs create mode 100644 scripts/components/FireEffectComponent.cs.uid create mode 100644 scripts/components/FlashingComponent.cs create mode 100644 scripts/components/FlashingComponent.cs.uid create mode 100644 scripts/components/FlipComponent.cs create mode 100644 scripts/components/FlipComponent.cs.uid create mode 100644 scripts/components/GravityMotionComponent.cs create mode 100644 scripts/components/GravityMotionComponent.cs.uid create mode 100644 scripts/components/HealComponent.cs create mode 100644 scripts/components/HealComponent.cs.uid create mode 100644 scripts/components/HealthComponent.cs create mode 100644 scripts/components/HealthComponent.cs.uid create mode 100644 scripts/components/HitComponent.cs create mode 100644 scripts/components/HitComponent.cs.uid create mode 100644 scripts/components/HomingMissileMotionComponent.cs create mode 100644 scripts/components/HomingMissileMotionComponent.cs.uid create mode 100644 scripts/components/IceEffectComponent.cs create mode 100644 scripts/components/IceEffectComponent.cs.uid create mode 100644 scripts/components/InvulnerabilityComponent.cs create mode 100644 scripts/components/InvulnerabilityComponent.cs.uid create mode 100644 scripts/components/JumpPadComponent.cs create mode 100644 scripts/components/JumpPadComponent.cs.uid create mode 100644 scripts/components/KillPlayerOutOfScreenComponent.cs create mode 100644 scripts/components/KillPlayerOutOfScreenComponent.cs.uid create mode 100644 scripts/components/KnockbackComponent.cs create mode 100644 scripts/components/KnockbackComponent.cs.uid create mode 100644 scripts/components/LaunchComponent.cs create mode 100644 scripts/components/LaunchComponent.cs.uid create mode 100644 scripts/components/LeverComponent.cs create mode 100644 scripts/components/LeverComponent.cs.uid create mode 100644 scripts/components/LifetimeComponent.cs create mode 100644 scripts/components/LifetimeComponent.cs.uid create mode 100644 scripts/components/MagneticSkillComponent.cs create mode 100644 scripts/components/MagneticSkillComponent.cs.uid create mode 100644 scripts/components/OutOfScreenComponent.cs create mode 100644 scripts/components/OutOfScreenComponent.cs.uid create mode 100644 scripts/components/PeriodicShootingComponent.cs create mode 100644 scripts/components/PeriodicShootingComponent.cs.uid create mode 100644 scripts/components/PlatformMovementComponent.cs create mode 100644 scripts/components/PlatformMovementComponent.cs.uid create mode 100644 scripts/components/PlayerController.cs create mode 100644 scripts/components/PlayerController.cs.uid create mode 100644 scripts/components/PlayerDeathComponent.cs create mode 100644 scripts/components/PlayerDeathComponent.cs.uid create mode 100644 scripts/components/ProgressiveDamageComponent.cs create mode 100644 scripts/components/ProgressiveDamageComponent.cs.uid create mode 100644 scripts/components/ProjectileComponent.cs create mode 100644 scripts/components/ProjectileComponent.cs.uid create mode 100644 scripts/components/ProjectileInitComponent.cs create mode 100644 scripts/components/ProjectileInitComponent.cs.uid create mode 100644 scripts/components/RequirementComponent.cs create mode 100644 scripts/components/RequirementComponent.cs.uid create mode 100644 scripts/components/ScoreComponent.cs create mode 100644 scripts/components/ScoreComponent.cs.uid create mode 100644 scripts/components/ShipMovementComponent.cs create mode 100644 scripts/components/ShipMovementComponent.cs.uid create mode 100644 scripts/components/ShipShooterComponent.cs create mode 100644 scripts/components/ShipShooterComponent.cs.uid create mode 100644 scripts/components/SideToSideMovementComponent.cs create mode 100644 scripts/components/SideToSideMovementComponent.cs.uid create mode 100644 scripts/components/SkillUnlockedComponent.cs create mode 100644 scripts/components/SkillUnlockedComponent.cs.uid create mode 100644 scripts/components/SpaceshipEnterComponent.cs create mode 100644 scripts/components/SpaceshipEnterComponent.cs.uid create mode 100644 scripts/components/SpaceshipExitComponent.cs create mode 100644 scripts/components/SpaceshipExitComponent.cs.uid create mode 100644 scripts/components/SpinComponent.cs create mode 100644 scripts/components/SpinComponent.cs.uid create mode 100644 scripts/components/StatusEffectComponent.cs create mode 100644 scripts/components/StatusEffectComponent.cs.uid create mode 100644 scripts/components/StompDamageComponent.cs create mode 100644 scripts/components/StompDamageComponent.cs.uid create mode 100644 scripts/components/StraightMotionComponent.cs create mode 100644 scripts/components/StraightMotionComponent.cs.uid create mode 100644 scripts/components/TerrainHitFx.cs create mode 100644 scripts/components/TerrainHitFx.cs.uid create mode 100644 scripts/components/TooltipComponent.cs create mode 100644 scripts/components/TooltipComponent.cs.uid create mode 100644 scripts/components/TrailComponent.cs create mode 100644 scripts/components/TrailComponent.cs.uid create mode 100644 scripts/components/TriggerLeverComponent.cs create mode 100644 scripts/components/TriggerLeverComponent.cs.uid create mode 100644 scripts/components/UnlockOnRequirementComponent.cs create mode 100644 scripts/components/UnlockOnRequirementComponent.cs.uid create mode 100644 scripts/interfaces/IMovement.cs create mode 100644 scripts/interfaces/IMovement.cs.uid create mode 100644 scripts/interfaces/IThrowInput.cs create mode 100644 scripts/interfaces/IThrowInput.cs.uid create mode 100644 scripts/interfaces/IUnlockable.cs create mode 100644 scripts/interfaces/IUnlockable.cs.uid diff --git a/Autoloads/ConfigFileHandler.cs b/Autoloads/ConfigFileHandler.cs new file mode 100644 index 0000000..67acdae --- /dev/null +++ b/Autoloads/ConfigFileHandler.cs @@ -0,0 +1,27 @@ +using Godot; + +namespace Mr.BrickAdventures.Autoloads; + +public partial class ConfigFileHandler : Node +{ + private ConfigFile _settingsConfig = new(); + public const string SettingsPath = "user://settings.ini"; + + public ConfigFile SettingsConfig => _settingsConfig; + + public override void _Ready() + { + if (!FileAccess.FileExists(SettingsPath)) + { + var err = _settingsConfig.Save(SettingsPath); + if (err != Error.Ok) + GD.PushError($"Failed to create settings file at {SettingsPath}: {err}"); + } + else + { + var err = _settingsConfig.Load(SettingsPath); + if (err != Error.Ok) + GD.PushError($"Failed to load settings file at {SettingsPath}: {err}"); + } + } +} \ No newline at end of file diff --git a/Autoloads/ConfigFileHandler.cs.uid b/Autoloads/ConfigFileHandler.cs.uid new file mode 100644 index 0000000..b8f877c --- /dev/null +++ b/Autoloads/ConfigFileHandler.cs.uid @@ -0,0 +1 @@ +uid://8cyvbeyd13cj diff --git a/Autoloads/GameManager.cs b/Autoloads/GameManager.cs new file mode 100644 index 0000000..ae81968 --- /dev/null +++ b/Autoloads/GameManager.cs @@ -0,0 +1,241 @@ +using System.Collections.Generic; +using System.Linq; +using Godot; +using Godot.Collections; +using Mr.BrickAdventures.scripts.components; +using Mr.BrickAdventures.scripts.Resources; + +namespace Mr.BrickAdventures.Autoloads; + +public partial class GameManager : Node +{ + [Export] public Array LevelScenes { get; set; } = new(); + + public PlayerController Player { get; set; } + + private List _sceneNodes = new(); + + public Dictionary PlayerState { get; set; } = new() + { + { "coins", 0 }, + { "lives", 3 }, + { "current_level", 0 }, + { "completed_levels", new Array() }, + { "unlocked_levels", new Array() {0}}, + { "unlocked_skills", new Array() } + }; + + public Dictionary CurrentSessionState { get; private set; } = new() + { + { "coins_collected", 0 }, + { "skills_unlocked", new Array() } + }; + + public override void _EnterTree() + { + GetTree().NodeAdded += OnNodeAdded; + GetTree().NodeRemoved += OnNodeRemoved; + } + + public override void _ExitTree() + { + GetTree().NodeAdded -= OnNodeAdded; + GetTree().NodeRemoved -= OnNodeRemoved; + _sceneNodes.Clear(); + } + + private void OnNodeAdded(Node node) + { + _sceneNodes.Add(node); + } + + private void OnNodeRemoved(Node node) + { + _sceneNodes.Remove(node); + } + + public void AddCoins(int amount) + { + PlayerState["coins"] = Mathf.Max(0, (int)PlayerState["coins"] + amount); + } + + public void SetCoins(int amount) => PlayerState["coins"] = Mathf.Max(0, amount); + + public int GetCoins() => (int)PlayerState["coins"] + (int)CurrentSessionState["coins_collected"]; + + public void RemoveCoins(int amount) + { + var sessionCoins = (int)CurrentSessionState["coins_collected"]; + if (amount <= sessionCoins) + { + CurrentSessionState["coins_collected"] = sessionCoins - amount; + } + else + { + var remaining = amount - sessionCoins; + CurrentSessionState["coins_collected"] = 0; + PlayerState["coins"] = Mathf.Max(0, (int)PlayerState["coins"] - remaining); + } + PlayerState["coins"] = Mathf.Max(0, (int)PlayerState["coins"]); + } + + public void AddLives(int amount) => PlayerState["lives"] = (int)PlayerState["lives"] + amount; + public void RemoveLives(int amount) => PlayerState["lives"] = (int)PlayerState["lives"] - amount; + public void SetLives(int amount) => PlayerState["lives"] = amount; + public int GetLives() => (int)PlayerState["lives"]; + + public bool IsSkillUnlocked(SkillData skill) + { + return ((Array)PlayerState["unlocked_skills"]).Contains(skill) + || ((Array)CurrentSessionState["skills_unlocked"]).Contains(skill); + } + + public void UnlockSkill(SkillData skill) + { + if (!IsSkillUnlocked(skill)) + ((Array)PlayerState["unlocked_skills"]).Add(skill); + } + + public void RemoveSkill(string skillName) + { + var arr = (Array)PlayerState["unlocked_skills"]; + foreach (SkillData s in arr) + { + if (s.Name != skillName) continue; + + arr.Remove(s); + break; + } + } + + public void UnlockSkills(Array skills) + { + foreach (var s in skills) + UnlockSkill(s); + } + + public void ResetPlayerState() + { + PlayerState = new Dictionary + { + { "coins", 0 }, + { "lives", 3 }, + { "current_level", 0 }, + { "completed_levels", new Array() }, + { "unlocked_levels", new Array() {0}}, + { "unlocked_skills", new Array() } + }; + } + + public void UnlockLevel(int levelIndex) + { + var unlocked = (Array)PlayerState["unlocked_levels"]; + if (!unlocked.Contains(levelIndex)) unlocked.Add(levelIndex); + } + + public void TryToGoToNextLevel() + { + var next = (int)PlayerState["current_level"] + 1; + var unlocked = (Array)PlayerState["unlocked_levels"]; + if (next < LevelScenes.Count && unlocked.Contains(next)) + { + PlayerState["current_level"] = next; + GetTree().ChangeSceneToPacked(LevelScenes[next]); + } + } + + public void MarkLevelComplete(int levelIndex) + { + UnlockLevel(levelIndex + 1); + var completed = (Array)PlayerState["completed_levels"]; + if (!completed.Contains(levelIndex)) completed.Add(levelIndex); + } + + public void ResetCurrentSessionState() + { + CurrentSessionState = new Dictionary + { + { "coins_collected", 0 }, + { "skills_unlocked", new Array() } + }; + } + + public void RestartGame() + { + ResetPlayerState(); + ResetCurrentSessionState(); + GetTree().ChangeSceneToPacked(LevelScenes[0]); + GetNode("/root/SaveSystem").SaveGame(); + } + + public void QuitGame() => GetTree().Quit(); + + public void PauseGame() => Engine.TimeScale = 0; + public void ResumeGame() => Engine.TimeScale = 1; + + public void StartNewGame() + { + ResetPlayerState(); + ResetCurrentSessionState(); + GetTree().ChangeSceneToPacked(LevelScenes[0]); + GetNode("/root/SaveSystem").SaveGame(); + } + + public void ContinueGame() + { + var save = GetNode("/root/SaveSystem"); + if (!save.LoadGame()) + { + GD.PrintErr("Failed to load game. Starting a new game instead."); + StartNewGame(); + return; + } + + var idx = (int)PlayerState["current_level"]; + if (idx < LevelScenes.Count) + GetTree().ChangeSceneToPacked(LevelScenes[idx]); + else + GD.PrintErr("No levels unlocked to continue."); + } + + public void OnLevelComplete() + { + var levelIndex = (int)PlayerState["current_level"]; + MarkLevelComplete(levelIndex); + AddCoins((int)CurrentSessionState["coins_collected"]); + foreach (var s in (Array)CurrentSessionState["skills_unlocked"]) + UnlockSkill((SkillData)s); + + ResetCurrentSessionState(); + TryToGoToNextLevel(); + GetNode("/root/SaveSystem").SaveGame(); + } + + public Array GetUnlockedSkills() + { + var unlocked = (Array)PlayerState["unlocked_skills"]; + var session = (Array)CurrentSessionState["skills_unlocked"]; + if (session!.Count == 0) return unlocked; + if (unlocked!.Count == 0) return session; + var joined = new Array(); + joined.AddRange(unlocked); + joined.AddRange(session); + return joined; + } + + public PlayerController GetPlayer() + { + if (Player != null) return Player; + + foreach (var node in _sceneNodes) + { + if (node is not PlayerController player) continue; + + Player = player; + return Player; + } + + GD.PrintErr("PlayerController not found in the scene tree."); + return null; + } +} \ No newline at end of file diff --git a/Autoloads/GameManager.cs.uid b/Autoloads/GameManager.cs.uid new file mode 100644 index 0000000..3fc829d --- /dev/null +++ b/Autoloads/GameManager.cs.uid @@ -0,0 +1 @@ +uid://c6eoi3ymefc0x diff --git a/Autoloads/SaveSystem.cs b/Autoloads/SaveSystem.cs new file mode 100644 index 0000000..d5ce18a --- /dev/null +++ b/Autoloads/SaveSystem.cs @@ -0,0 +1,61 @@ +using Godot; +using Godot.Collections; +using Mr.BrickAdventures.scripts.Resources; + +namespace Mr.BrickAdventures.Autoloads; + +public partial class SaveSystem : Node +{ + [Export] public string SavePath { get; set; } = "user://savegame.save"; + [Export] public int Version { get; set; } = 1; + + private GameManager _gameManager; + + public override void _Ready() + { + _gameManager = GetNode("/root/GameManager"); + } + + public void SaveGame() + { + var saveData = new Dictionary + { + { "player_state", _gameManager.PlayerState}, + { "version", Version} + }; + + using var file = FileAccess.Open(SavePath, FileAccess.ModeFlags.Write); + file.StoreVar(saveData); + GD.Print("Game state saved to: ", SavePath); + } + + public bool LoadGame() + { + if (!FileAccess.FileExists(SavePath)) + return false; + + using var file = FileAccess.Open(SavePath, FileAccess.ModeFlags.Read); + var saveDataObj = (Dictionary)file.GetVar(); + + if (saveDataObj.ContainsKey("version") && (int)saveDataObj["version"] != Version) + { + GD.Print($"Save file version mismatch. Expected: {Version}, Found: {saveDataObj["version"]}"); + return false; + } + + GD.Print("Game state loaded from: ", SavePath); + GD.Print("Player state: ", saveDataObj["player_state"]); + _gameManager.PlayerState = (Dictionary)saveDataObj["player_state"]; + + var skills = new Array(); + foreach (var skill in (Array)_gameManager.PlayerState["unlocked_skills"]) + { + skills.Add(skill); + } + + _gameManager.UnlockSkills(skills); + return true; + } + + public bool CheckSaveExists() => FileAccess.FileExists(SavePath); +} \ No newline at end of file diff --git a/Autoloads/SaveSystem.cs.uid b/Autoloads/SaveSystem.cs.uid new file mode 100644 index 0000000..a014aec --- /dev/null +++ b/Autoloads/SaveSystem.cs.uid @@ -0,0 +1 @@ +uid://bh20fqbyifidc diff --git a/Autoloads/UIManager.cs b/Autoloads/UIManager.cs new file mode 100644 index 0000000..cd576be --- /dev/null +++ b/Autoloads/UIManager.cs @@ -0,0 +1,65 @@ +using Godot; +using Godot.Collections; + +namespace Mr.BrickAdventures.Autoloads; + +public partial class UIManager : Node +{ + [Export] public Array UiStack { get; set; } = new(); + + [Signal] public delegate void ScreenPushedEventHandler(Control screen); + [Signal] public delegate void ScreenPoppedEventHandler(Control screen); + + public void PushScreen(Control screen) + { + if (screen == null) + { + GD.PushError($"Cannot push a null screen."); + return; + } + + UiStack.Add(screen); + screen.Show(); + screen.SetProcessInput(true); + screen.SetFocusMode(Control.FocusModeEnum.All); + screen.GrabFocus(); + EmitSignalScreenPushed(screen); + } + + public void PopScreen() + { + if (UiStack.Count == 0) + { + GD.PushError($"Cannot pop screen from an empty stack."); + return; + } + + var top = (Control)UiStack[^1]; + UiStack.RemoveAt(UiStack.Count - 1); + top.Hide(); + top.SetProcessInput(false); + EmitSignalScreenPopped(top); + top.AcceptEvent(); + + if (UiStack.Count > 0) ((Control)UiStack[^1]).GrabFocus(); + } + + public Control TopScreen() => UiStack.Count > 0 ? (Control)UiStack[^1] : null; + + public bool IsScreenOnTop(Control screen) => UiStack.Count > 0 && (Control)UiStack[^1] == screen; + + public bool IsVisibleOnStack(Control screen) => UiStack.Contains(screen) && screen.Visible; + + public void CloseAll() + { + while (UiStack.Count > 0) + PopScreen(); + } + + public static void HideAndDisable(Control screen) + { + screen.Hide(); + screen.SetProcessInput(false); + } + +} \ No newline at end of file diff --git a/Autoloads/UIManager.cs.uid b/Autoloads/UIManager.cs.uid new file mode 100644 index 0000000..c888e92 --- /dev/null +++ b/Autoloads/UIManager.cs.uid @@ -0,0 +1 @@ +uid://c3ldmnrwperr4 diff --git a/Mr. Brick Adventures.csproj b/Mr. Brick Adventures.csproj new file mode 100644 index 0000000..91104ef --- /dev/null +++ b/Mr. Brick Adventures.csproj @@ -0,0 +1,143 @@ + + + net8.0 + true + Mr.BrickAdventures + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Mr. Brick Adventures.sln b/Mr. Brick Adventures.sln new file mode 100644 index 0000000..7ef00af --- /dev/null +++ b/Mr. Brick Adventures.sln @@ -0,0 +1,19 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mr. Brick Adventures", "Mr. Brick Adventures.csproj", "{A1D482B9-207B-4D6C-A0A0-D9E6D1AE2356}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + ExportDebug|Any CPU = ExportDebug|Any CPU + ExportRelease|Any CPU = ExportRelease|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A1D482B9-207B-4D6C-A0A0-D9E6D1AE2356}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A1D482B9-207B-4D6C-A0A0-D9E6D1AE2356}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A1D482B9-207B-4D6C-A0A0-D9E6D1AE2356}.ExportDebug|Any CPU.ActiveCfg = ExportDebug|Any CPU + {A1D482B9-207B-4D6C-A0A0-D9E6D1AE2356}.ExportDebug|Any CPU.Build.0 = ExportDebug|Any CPU + {A1D482B9-207B-4D6C-A0A0-D9E6D1AE2356}.ExportRelease|Any CPU.ActiveCfg = ExportRelease|Any CPU + {A1D482B9-207B-4D6C-A0A0-D9E6D1AE2356}.ExportRelease|Any CPU.Build.0 = ExportRelease|Any CPU + EndGlobalSection +EndGlobal diff --git a/Mr. Brick Adventures.sln.DotSettings.user b/Mr. Brick Adventures.sln.DotSettings.user new file mode 100644 index 0000000..38db013 --- /dev/null +++ b/Mr. Brick Adventures.sln.DotSettings.user @@ -0,0 +1,6 @@ + + ForceIncluded + ForceIncluded + ForceIncluded + ForceIncluded + ForceIncluded \ No newline at end of file diff --git a/autoloads/ui_manager.gd b/autoloads/ui_manager.gd index 91e1171..a5c8914 100644 --- a/autoloads/ui_manager.gd +++ b/autoloads/ui_manager.gd @@ -51,4 +51,4 @@ func close_all() -> void: func hide_and_disable(screen: Control) -> void: screen.hide() - screen.set_process_input(false) \ No newline at end of file + screen.set_process_input(false) diff --git a/project.godot b/project.godot index 570baac..42f3f74 100644 --- a/project.godot +++ b/project.godot @@ -19,7 +19,7 @@ config/version="in-dev" run/main_scene="uid://cl00e2ocomk3m" config/use_custom_user_dir=true config/custom_user_dir_name="MrBrickAdventures" -config/features=PackedStringArray("4.4", "GL Compatibility") +config/features=PackedStringArray("4.4", "C#", "GL Compatibility") run/max_fps=180 boot_splash/bg_color=Color(0, 0, 0, 1) boot_splash/show_image=false diff --git a/scripts/Resources/ChargeThrowInputResource.cs b/scripts/Resources/ChargeThrowInputResource.cs new file mode 100644 index 0000000..a781748 --- /dev/null +++ b/scripts/Resources/ChargeThrowInputResource.cs @@ -0,0 +1,70 @@ +using Godot; + +namespace Mr.BrickAdventures.scripts.Resources; + +public partial class ChargeThrowInputResource : ThrowInputResource +{ + [Export] public float MinPower { get; set; } = 0.5f; + [Export] public float MaxPower { get; set; } = 2.0f; + [Export] public float MaxChargeTime { get; set; } = 2.0f; + [Export] public float MinChargeDuration { get; set; } = 0.1f; + + private bool _isCharging = false; + private float _chargeStartTime = 0f; + + [Signal] public delegate void ChargeStartedEventHandler(); + [Signal] public delegate void ChargeUpdatedEventHandler(float chargeRatio); + [Signal] public delegate void ChargeStoppedEventHandler(); + + public override void ProcessInput(InputEvent @event) + { + if (@event.IsActionPressed("attack")) + { + _isCharging = true; + _chargeStartTime = Time.GetTicksMsec() / 1000f; + EmitSignalChargeStarted(); + } + + if (@event.IsActionReleased("attack") && _isCharging) + { + var power = CalculatePower(); + _isCharging = false; + EmitSignalThrowRequested(power); + EmitSignalChargeStopped(); + } + } + + public override void Update(double delta) + { + if (!_isCharging) return; + + var t = Mathf.Clamp(GetChargeRatio(), MinPower, MaxPower); + EmitSignalChargeUpdated(t); + } + + public override bool SupportsCharging() + { + return true; + } + + private float CalculatePower() + { + var now = Time.GetTicksMsec() / 1000f; + var heldTime = now - _chargeStartTime; + if (heldTime < MinChargeDuration) + return MinPower; + + var t = Mathf.Clamp(heldTime / MaxChargeTime, 0f, 1f); + return Mathf.Lerp(MinPower, MaxPower, t); + } + + private float GetChargeRatio() + { + if (!_isCharging) return MinPower; + + var now = Time.GetTicksMsec() / 1000f; + var heldTime = now - _chargeStartTime; + var t = Mathf.Clamp(heldTime / MaxChargeTime, 0f, 1f); + return Mathf.Lerp(MinPower, MaxPower, t); + } +} \ No newline at end of file diff --git a/scripts/Resources/ChargeThrowInputResource.cs.uid b/scripts/Resources/ChargeThrowInputResource.cs.uid new file mode 100644 index 0000000..34c7c14 --- /dev/null +++ b/scripts/Resources/ChargeThrowInputResource.cs.uid @@ -0,0 +1 @@ +uid://dtpdh4jp51jis diff --git a/scripts/Resources/CollectableResource.cs b/scripts/Resources/CollectableResource.cs new file mode 100644 index 0000000..88b338b --- /dev/null +++ b/scripts/Resources/CollectableResource.cs @@ -0,0 +1,9 @@ +using Godot; + +namespace Mr.BrickAdventures.scripts.Resources; + +public partial class CollectableResource : Resource +{ + [Export] public Variant Amount { get; set; } = 0.0; + [Export] public CollectableType Type { get; set; } +} \ No newline at end of file diff --git a/scripts/Resources/CollectableResource.cs.uid b/scripts/Resources/CollectableResource.cs.uid new file mode 100644 index 0000000..314072f --- /dev/null +++ b/scripts/Resources/CollectableResource.cs.uid @@ -0,0 +1 @@ +uid://gptsgaw3agkf diff --git a/scripts/Resources/CollectableType.cs b/scripts/Resources/CollectableType.cs new file mode 100644 index 0000000..840b8b9 --- /dev/null +++ b/scripts/Resources/CollectableType.cs @@ -0,0 +1,8 @@ +namespace Mr.BrickAdventures.scripts.Resources; + +public enum CollectableType +{ + Coin, + Kid, + Health, +} \ No newline at end of file diff --git a/scripts/Resources/CollectableType.cs.uid b/scripts/Resources/CollectableType.cs.uid new file mode 100644 index 0000000..077048b --- /dev/null +++ b/scripts/Resources/CollectableType.cs.uid @@ -0,0 +1 @@ +uid://2ql8wj3vfeke diff --git a/scripts/Resources/SkillData.cs b/scripts/Resources/SkillData.cs new file mode 100644 index 0000000..a96a8b1 --- /dev/null +++ b/scripts/Resources/SkillData.cs @@ -0,0 +1,19 @@ +using System; +using Godot; +using Godot.Collections; + +namespace Mr.BrickAdventures.scripts.Resources; + +public partial class SkillData : Resource +{ + [Export] public string Name { get; set; } = "New Skill"; + [Export] public string Description { get; set; } = "New Skill"; + [Export] public Dictionary Config { get; set; } = new(); + [Export] public int Cost { get; set; } = 0; + [Export] public Texture2D Icon { get; set; } + [Export] public bool IsActive { get; set; } = false; + [Export] public int Level { get; set; } = 1; + [Export] public int MaxLevel { get; set; } = 1; + [Export] public SkillType Type { get; set; } = SkillType.Throw; + [Export] public PackedScene Node { get; set; } +} \ No newline at end of file diff --git a/scripts/Resources/SkillData.cs.uid b/scripts/Resources/SkillData.cs.uid new file mode 100644 index 0000000..7c3a3a1 --- /dev/null +++ b/scripts/Resources/SkillData.cs.uid @@ -0,0 +1 @@ +uid://d4crrfmbgxnqf diff --git a/scripts/Resources/SkillType.cs b/scripts/Resources/SkillType.cs new file mode 100644 index 0000000..ceb0b4d --- /dev/null +++ b/scripts/Resources/SkillType.cs @@ -0,0 +1,8 @@ +namespace Mr.BrickAdventures.scripts.Resources; + +public enum SkillType +{ + Attack, + Throw, + Misc, +} \ No newline at end of file diff --git a/scripts/Resources/SkillType.cs.uid b/scripts/Resources/SkillType.cs.uid new file mode 100644 index 0000000..d9acebb --- /dev/null +++ b/scripts/Resources/SkillType.cs.uid @@ -0,0 +1 @@ +uid://sma20qug2r0q diff --git a/scripts/Resources/StatusEffectDataResource.cs b/scripts/Resources/StatusEffectDataResource.cs new file mode 100644 index 0000000..3152115 --- /dev/null +++ b/scripts/Resources/StatusEffectDataResource.cs @@ -0,0 +1,10 @@ +using Godot; + +namespace Mr.BrickAdventures.scripts.Resources; + +public partial class StatusEffectDataResource : Resource +{ + [Export] public float Duration { get; set; } = 1f; + [Export] public float DamagePerSecond { get; set; } = 0.25f; + [Export] public StatusEffectType Type { get; set; } +} \ No newline at end of file diff --git a/scripts/Resources/StatusEffectDataResource.cs.uid b/scripts/Resources/StatusEffectDataResource.cs.uid new file mode 100644 index 0000000..f55ca07 --- /dev/null +++ b/scripts/Resources/StatusEffectDataResource.cs.uid @@ -0,0 +1 @@ +uid://pw0pu6gb21y2 diff --git a/scripts/Resources/StatusEffectType.cs b/scripts/Resources/StatusEffectType.cs new file mode 100644 index 0000000..7f61f98 --- /dev/null +++ b/scripts/Resources/StatusEffectType.cs @@ -0,0 +1,8 @@ +namespace Mr.BrickAdventures.scripts.Resources; + +public enum StatusEffectType +{ + None, + Fire, + Ice +} \ No newline at end of file diff --git a/scripts/Resources/StatusEffectType.cs.uid b/scripts/Resources/StatusEffectType.cs.uid new file mode 100644 index 0000000..711e14c --- /dev/null +++ b/scripts/Resources/StatusEffectType.cs.uid @@ -0,0 +1 @@ +uid://b0a7k7mse3l68 diff --git a/scripts/Resources/TapThrowInputResource.cs b/scripts/Resources/TapThrowInputResource.cs new file mode 100644 index 0000000..97079e8 --- /dev/null +++ b/scripts/Resources/TapThrowInputResource.cs @@ -0,0 +1,20 @@ +using Godot; +using Mr.BrickAdventures.scripts.interfaces; + +namespace Mr.BrickAdventures.scripts.Resources; + +public partial class TapThrowInputResource : ThrowInputResource +{ + public override void Update(double delta) + { + if (Input.IsActionPressed("attack")) + { + EmitSignalThrowRequested(1f); + } + } + + public override bool SupportsCharging() + { + return false; + } +} \ No newline at end of file diff --git a/scripts/Resources/TapThrowInputResource.cs.uid b/scripts/Resources/TapThrowInputResource.cs.uid new file mode 100644 index 0000000..ecd7ca2 --- /dev/null +++ b/scripts/Resources/TapThrowInputResource.cs.uid @@ -0,0 +1 @@ +uid://cx7ryqxemgs56 diff --git a/scripts/Resources/ThrowInputResource.cs b/scripts/Resources/ThrowInputResource.cs new file mode 100644 index 0000000..e7285e7 --- /dev/null +++ b/scripts/Resources/ThrowInputResource.cs @@ -0,0 +1,24 @@ +using Godot; +using Mr.BrickAdventures.scripts.interfaces; + +namespace Mr.BrickAdventures.scripts.Resources; + +public abstract partial class ThrowInputResource : Resource, IThrowInput +{ + [Signal] public delegate void ThrowRequestedEventHandler(float powerMultiplier = 1f); + + public virtual void ProcessInput(InputEvent @event) + { + throw new System.NotImplementedException(); + } + + public virtual void Update(double delta) + { + throw new System.NotImplementedException(); + } + + public virtual bool SupportsCharging() + { + throw new System.NotImplementedException(); + } +} \ No newline at end of file diff --git a/scripts/Resources/ThrowInputResource.cs.uid b/scripts/Resources/ThrowInputResource.cs.uid new file mode 100644 index 0000000..b051cca --- /dev/null +++ b/scripts/Resources/ThrowInputResource.cs.uid @@ -0,0 +1 @@ +uid://mnn5wy5cyr4m diff --git a/scripts/Screenshot.cs b/scripts/Screenshot.cs new file mode 100644 index 0000000..b389dd5 --- /dev/null +++ b/scripts/Screenshot.cs @@ -0,0 +1,15 @@ +using Godot; + +namespace Mr.BrickAdventures.scripts; + +public partial class Screenshot : Node +{ + public override void _Process(double delta) + { + if (!OS.IsDebugBuild() || !Input.IsActionJustPressed("screenshot")) return; + var img = GetViewport().GetTexture().GetImage(); + var id = OS.GetUniqueId() + "_" + Time.GetDatetimeStringFromSystem(); + var path = "user://screenshots/screenshot_" + id + ".png"; + img.SavePng(path); + } +} \ No newline at end of file diff --git a/scripts/Screenshot.cs.uid b/scripts/Screenshot.cs.uid new file mode 100644 index 0000000..4b7d34d --- /dev/null +++ b/scripts/Screenshot.cs.uid @@ -0,0 +1 @@ +uid://chrhjch4ymfvr diff --git a/scripts/SkillManager.cs b/scripts/SkillManager.cs new file mode 100644 index 0000000..ad53727 --- /dev/null +++ b/scripts/SkillManager.cs @@ -0,0 +1,144 @@ +using Godot; +using Godot.Collections; +using Mr.BrickAdventures.Autoloads; +using Mr.BrickAdventures.scripts.Resources; + +namespace Mr.BrickAdventures.scripts; + +public partial class SkillManager : Node +{ + private GameManager _gameManager; + [Export] public Array AvailableSkills { get; set; } = []; + + public Dictionary ActiveComponents { get; private set; } = new(); + + public override void _Ready() + { + _gameManager = GetNode("/root/GameManager"); + ApplyUnlockedSkills(); + } + + public void AddSkill(SkillData skillData) + { + if (ActiveComponents.ContainsKey(skillData.Name)) + return; + + if (skillData.Type == SkillType.Throw) + { + var unlocked = _gameManager.GetUnlockedSkills(); + foreach (var skill in unlocked) + { + SkillData data = null; + foreach (var s in AvailableSkills) + { + if (s == (SkillData)skill) + { + data = s; + break; + } + } + if (data != null && data.Type == SkillType.Throw) + RemoveSkill(data.Name); + } + } + + var instance = skillData.Node.Instantiate(); + foreach (var key in skillData.Config.Keys) + { + if (instance.HasMethod("get")) // rough presence check + { + var value = skillData.Config[key]; + var parent = GetParent(); + + if (value.VariantType == Variant.Type.NodePath) + { + var np = (NodePath)value; + if (parent.HasNode(np)) + value = parent.GetNode(np); + else if (instance.HasNode(np)) + value = instance.GetNode(np); + else + continue; + } + + // Set via property if exists + instance.Set(key, value); + } + } + + Owner.AddChild(instance); + ActiveComponents[skillData.Name] = instance; + } + + public void RemoveSkill(string skillName) + { + if (!ActiveComponents.TryGetValue(skillName, out var component)) + return; + + var inst = (Node)component; + if (IsInstanceValid(inst)) + inst.QueueFree(); + + var skills = _gameManager.GetUnlockedSkills(); + foreach (SkillData s in skills) + { + if (s.Name == skillName) + { + s.IsActive = false; + break; + } + } + ActiveComponents.Remove(skillName); + } + + public void ApplyUnlockedSkills() + { + foreach (var sd in AvailableSkills) + { + if (_gameManager.IsSkillUnlocked(sd)) + { + GD.Print("Applying skill: ", sd.Name); + CallDeferred(MethodName.AddSkill, sd); + } + else + { + RemoveSkill(sd.Name); + } + } + } + + public SkillData GetSkillByName(string skillName) + { + foreach (var sd in AvailableSkills) + if (sd.Name == skillName) return sd; + return null; + } + + public void ActivateSkill(SkillData skill) + { + if (!ActiveComponents.ContainsKey(skill.Name)) + { + AddSkill(skill); + skill.IsActive = true; + } + } + + public void DeactivateSkill(SkillData skill) + { + if (ActiveComponents.ContainsKey(skill.Name)) + { + RemoveSkill(skill.Name); + skill.IsActive = false; + } + } + + public void ToggleSkillActivation(SkillData skill) + { + if (skill == null) return; + + if (ActiveComponents.ContainsKey(skill.Name)) + DeactivateSkill(skill); + else + ActivateSkill(skill); + } +} \ No newline at end of file diff --git a/scripts/SkillManager.cs.uid b/scripts/SkillManager.cs.uid new file mode 100644 index 0000000..dc14de7 --- /dev/null +++ b/scripts/SkillManager.cs.uid @@ -0,0 +1 @@ +uid://di572axt0c3s8 diff --git a/scripts/UI/AudioSettings.cs b/scripts/UI/AudioSettings.cs new file mode 100644 index 0000000..0d605b3 --- /dev/null +++ b/scripts/UI/AudioSettings.cs @@ -0,0 +1,102 @@ +using Godot; +using Mr.BrickAdventures.Autoloads; + +namespace Mr.BrickAdventures.scripts.UI; + +public partial class AudioSettings : Node +{ + [Export] public Slider MasterVolumeSlider { get; set; } + [Export] public Slider MusicVolumeSlider { get; set; } + [Export] public Slider SfxVolumeSlider { get; set; } + [Export] public Control AudioSettingsControl { get; set; } + [Export] public float MuteThreshold { get; set; } = -20f; + + private UIManager _uiManager; + private ConfigFileHandler _configFileHandler; + + public override void _Ready() + { + _uiManager = GetNode("/root/UIManager"); + _configFileHandler = GetNode("/root/ConfigFileHandler"); + Initialize(); + MasterVolumeSlider.ValueChanged += OnMasterVolumeChanged; + MusicVolumeSlider.ValueChanged += OnMusicVolumeChanged; + SfxVolumeSlider.ValueChanged += OnSfxVolumeChanged; + } + + public override void _UnhandledInput(InputEvent @event) + { + if (!@event.IsActionReleased("ui_cancel")) return; + if (!_uiManager.IsScreenOnTop(AudioSettingsControl)) return; + + SaveSettings(); + _uiManager.PopScreen(); + } + + private void OnSfxVolumeChanged(double value) + { + AudioServer.SetBusVolumeDb(AudioServer.GetBusIndex("sfx"), (float)value); + HandleMute(AudioServer.GetBusIndex("sfx"), (float)value); + } + + private void OnMusicVolumeChanged(double value) + { + AudioServer.SetBusVolumeDb(AudioServer.GetBusIndex("music"), (float)value); + HandleMute(AudioServer.GetBusIndex("music"), (float)value); + } + + private void OnMasterVolumeChanged(double value) + { + AudioServer.SetBusVolumeDb(AudioServer.GetBusIndex("Master"), (float)value); + HandleMute(AudioServer.GetBusIndex("Master"), (float)value); + } + + private void Initialize() + { + var volumeDb = AudioServer.GetBusVolumeDb(AudioServer.GetBusIndex("Master")); + MasterVolumeSlider.Value = volumeDb; + MasterVolumeSlider.MinValue = MuteThreshold; + MasterVolumeSlider.MaxValue = 0f; + + var musicVolumeDb = AudioServer.GetBusVolumeDb(AudioServer.GetBusIndex("music")); + MusicVolumeSlider.Value = musicVolumeDb; + MusicVolumeSlider.MinValue = MuteThreshold; + MusicVolumeSlider.MaxValue = 0f; + + var sfxVolumeDb = AudioServer.GetBusVolumeDb(AudioServer.GetBusIndex("sfx")); + SfxVolumeSlider.Value = sfxVolumeDb; + SfxVolumeSlider.MinValue = MuteThreshold; + SfxVolumeSlider.MaxValue = 0f; + } + + private void HandleMute(int busIndex, float value) + { + AudioServer.SetBusMute(busIndex, value <= MuteThreshold); + } + + private void SaveSettings() + { + var settingsConfig = _configFileHandler.SettingsConfig; + settingsConfig.SetValue("audio_settings", "master_volume", MasterVolumeSlider.Value); + settingsConfig.SetValue("audio_settings", "music_volume", MusicVolumeSlider.Value); + settingsConfig.SetValue("audio_settings", "sfx_volume", SfxVolumeSlider.Value); + settingsConfig.SetValue("audio_settings", "mute_threshold", MuteThreshold); + settingsConfig.Save(ConfigFileHandler.SettingsPath); + } + + private void LoadSettings() + { + var settingsConfig = _configFileHandler.SettingsConfig; + if (!settingsConfig.HasSection("audio_settings")) return; + + var masterVolume = (float)settingsConfig.GetValue("audio_settings", "master_volume", MasterVolumeSlider.Value); + var musicVolume = (float)settingsConfig.GetValue("audio_settings", "music_volume", MusicVolumeSlider.Value); + var sfxVolume = (float)settingsConfig.GetValue("audio_settings", "sfx_volume", SfxVolumeSlider.Value); + var muteThreshold = (float)settingsConfig.GetValue("audio_settings", "mute_threshold", MuteThreshold); + + MasterVolumeSlider.Value = masterVolume; + MusicVolumeSlider.Value = musicVolume; + SfxVolumeSlider.Value = sfxVolume; + MuteThreshold = muteThreshold; + } +} \ No newline at end of file diff --git a/scripts/UI/AudioSettings.cs.uid b/scripts/UI/AudioSettings.cs.uid new file mode 100644 index 0000000..b819f88 --- /dev/null +++ b/scripts/UI/AudioSettings.cs.uid @@ -0,0 +1 @@ +uid://g61qqsymqfxd diff --git a/scripts/UI/ChargeProgressBar.cs b/scripts/UI/ChargeProgressBar.cs new file mode 100644 index 0000000..5e74caf --- /dev/null +++ b/scripts/UI/ChargeProgressBar.cs @@ -0,0 +1,81 @@ +using Godot; +using Mr.BrickAdventures.scripts.components; +using Mr.BrickAdventures.scripts.Resources; + +namespace Mr.BrickAdventures.scripts.UI; + +public partial class ChargeProgressBar : Node +{ + [Export] public ProgressBar ProgressBar { get; set; } + [Export] public BrickThrowComponent ThrowComponent { get; set; } + + private ChargeThrowInputResource _throwInput; + + public override void _Ready() + { + Owner.ChildEnteredTree += OnNodeEntered; + ProgressBar.Hide(); + SetupDependencies(); + } + + private void OnNodeEntered(Node node) + { + if (node is not BrickThrowComponent throwComponent || ThrowComponent != null) return; + ThrowComponent = throwComponent; + SetupDependencies(); + } + + private void SetupDependencies() + { + if (ThrowComponent.ThrowInputBehavior is ChargeThrowInputResource throwInput) + { + _throwInput = throwInput; + } + else + { + _throwInput = null; + } + + if (_throwInput == null) + { + return; + } + + if (!_throwInput.SupportsCharging()) + { + ProgressBar.Hide(); + return; + } + + SetupProgressBar(); + + _throwInput.ChargeStarted += OnChargeStarted; + _throwInput.ChargeStopped += OnChargeStopped; + _throwInput.ChargeUpdated += OnChargeUpdated; + } + + private void SetupProgressBar() + { + ProgressBar.MinValue = _throwInput.MinPower; + ProgressBar.MaxValue = _throwInput.MaxPower; + ProgressBar.Value = _throwInput.MinPower; + ProgressBar.Step = 0.01f; + ProgressBar.Hide(); + } + + private void OnChargeStarted() + { + ProgressBar.Show(); + } + + private void OnChargeStopped() + { + ProgressBar.Hide(); + } + + private void OnChargeUpdated(float chargeRatio) + { + ProgressBar.Value = chargeRatio; + ProgressBar.Show(); + } +} \ No newline at end of file diff --git a/scripts/UI/ChargeProgressBar.cs.uid b/scripts/UI/ChargeProgressBar.cs.uid new file mode 100644 index 0000000..9445c4f --- /dev/null +++ b/scripts/UI/ChargeProgressBar.cs.uid @@ -0,0 +1 @@ +uid://dev2q1228otm2 diff --git a/scripts/UI/Credits.cs b/scripts/UI/Credits.cs new file mode 100644 index 0000000..b0d2d0f --- /dev/null +++ b/scripts/UI/Credits.cs @@ -0,0 +1,23 @@ +using Godot; +using Mr.BrickAdventures.Autoloads; + +namespace Mr.BrickAdventures.scripts.UI; + +public partial class Credits : Control +{ + private UIManager _uiManager; + + public override void _Ready() + { + _uiManager = GetNode("/root/UIManager"); + } + + public override void _UnhandledInput(InputEvent @event) + { + if (!@event.IsActionPressed("ui_cancel")) return; + if (_uiManager != null && _uiManager.IsScreenOnTop(this)) + { + _uiManager.PopScreen(); + } + } +} \ No newline at end of file diff --git a/scripts/UI/Credits.cs.uid b/scripts/UI/Credits.cs.uid new file mode 100644 index 0000000..de4edcf --- /dev/null +++ b/scripts/UI/Credits.cs.uid @@ -0,0 +1 @@ +uid://daevj4uootmcw diff --git a/scripts/UI/GameOverScreen.cs b/scripts/UI/GameOverScreen.cs new file mode 100644 index 0000000..80e55b7 --- /dev/null +++ b/scripts/UI/GameOverScreen.cs @@ -0,0 +1,39 @@ +using Godot; +using Mr.BrickAdventures.Autoloads; + +namespace Mr.BrickAdventures.scripts.UI; + +public partial class GameOverScreen : Node +{ + [Export] public Control GameOverPanel { get; set; } + [Export] public Button RestartButton { get; set; } + [Export] public Button MainMenuButton { get; set; } + [Export] public PackedScene MainMenuScene { get; set; } + + private GameManager _gameManager; + + public override void _Ready() + { + _gameManager = GetNode("/root/GameManager"); + RestartButton.Pressed += OnRestartClicked; + MainMenuButton.Pressed += OnMainMenuClicked; + } + + private void OnMainMenuClicked() + { + _gameManager.ResetPlayerState(); + GetTree().ChangeSceneToPacked(MainMenuScene); + } + + private void OnRestartClicked() + { + _gameManager.RestartGame(); + } + + public void OnPlayerDeath() + { + if (_gameManager == null || _gameManager.GetLives() != 0) return; + + GameOverPanel.Show(); + } +} \ No newline at end of file diff --git a/scripts/UI/GameOverScreen.cs.uid b/scripts/UI/GameOverScreen.cs.uid new file mode 100644 index 0000000..43680fa --- /dev/null +++ b/scripts/UI/GameOverScreen.cs.uid @@ -0,0 +1 @@ +uid://u4qfsx4w72dv diff --git a/scripts/UI/Hud.cs b/scripts/UI/Hud.cs new file mode 100644 index 0000000..5939a8e --- /dev/null +++ b/scripts/UI/Hud.cs @@ -0,0 +1,43 @@ +using Godot; +using Mr.BrickAdventures.Autoloads; +using Mr.BrickAdventures.scripts.components; + +namespace Mr.BrickAdventures.scripts.UI; + +public partial class Hud : Node +{ + [Export] public HealthComponent Health { get; set; } + [Export] public Label CoinsLabel { get; set; } + [Export] public ProgressBar HealthBar { get; set; } + [Export] public Label LivesLabel { get; set; } + + private GameManager _gameManager; + + public override void _Ready() + { + _gameManager = GetNode("/root/GameManager"); + } + + public override void _Process(double delta) + { + SetHealthBar(); + SetLivesLabel(); + SetCoinsLabel(); + } + + private void SetCoinsLabel() + { + CoinsLabel.Text = Tr("COINS_LABEL") + ": " + _gameManager.GetCoins(); + } + + private void SetLivesLabel() + { + LivesLabel.Text = Tr("LIVES_LABEL") + ": " + _gameManager.GetLives(); + } + + private void SetHealthBar() + { + HealthBar.Value = Health.Health; + HealthBar.MaxValue = Health.MaxHealth; + } +} \ No newline at end of file diff --git a/scripts/UI/Hud.cs.uid b/scripts/UI/Hud.cs.uid new file mode 100644 index 0000000..15ddc0b --- /dev/null +++ b/scripts/UI/Hud.cs.uid @@ -0,0 +1 @@ +uid://wfj674u4486f diff --git a/scripts/UI/MainMenu.cs b/scripts/UI/MainMenu.cs new file mode 100644 index 0000000..b4b5de0 --- /dev/null +++ b/scripts/UI/MainMenu.cs @@ -0,0 +1,67 @@ +using Godot; +using Mr.BrickAdventures.Autoloads; + +namespace Mr.BrickAdventures.scripts.UI; + +public partial class MainMenu : Node +{ + [Export] public Control MainMenuControl { get; set; } + [Export] public Button NewGameButton { get; set; } + [Export] public Button ContinueButton { get; set; } + [Export] public Button SettingsButton { get; set; } + [Export] public Button CreditsButton { get; set; } + [Export] public Button ExitButton { get; set; } + [Export] public Label VersionLabel { get; set; } + [Export] public Control SettingsControl { get; set; } + [Export] public Control CreditsControl { get; set; } + + private SaveSystem _saveSystem; + private GameManager _gameManager; + private UIManager _uiManager; + + public override void _Ready() + { + _saveSystem = GetNode("/root/SaveSystem"); + _gameManager = GetNode("/root/GameManager"); + _uiManager = GetNode("/root/UIManager"); + + NewGameButton.Pressed += OnNewGamePressed; + ContinueButton.Pressed += OnContinuePressed; + SettingsButton.Pressed += OnSettingsPressed; + CreditsButton.Pressed += OnCreditsPressed; + ExitButton.Pressed += OnExitPressed; + + VersionLabel.Text = $"v. {ProjectSettings.GetSetting("application/config/version")}"; + ContinueButton.Disabled = !_saveSystem.CheckSaveExists(); + + if (_saveSystem.CheckSaveExists()) + ContinueButton.GrabFocus(); + else + NewGameButton.GrabFocus(); + } + + private void OnExitPressed() + { + _gameManager.QuitGame(); + } + + private void OnCreditsPressed() + { + _uiManager.PushScreen(CreditsControl); + } + + private void OnSettingsPressed() + { + _uiManager.PushScreen(SettingsControl); + } + + private void OnContinuePressed() + { + _gameManager.ContinueGame(); + } + + private void OnNewGamePressed() + { + _gameManager.StartNewGame(); + } +} \ No newline at end of file diff --git a/scripts/UI/MainMenu.cs.uid b/scripts/UI/MainMenu.cs.uid new file mode 100644 index 0000000..73f54b3 --- /dev/null +++ b/scripts/UI/MainMenu.cs.uid @@ -0,0 +1 @@ +uid://bna3ggr6n7ycr diff --git a/scripts/UI/Marketplace.cs b/scripts/UI/Marketplace.cs new file mode 100644 index 0000000..1fc580c --- /dev/null +++ b/scripts/UI/Marketplace.cs @@ -0,0 +1,142 @@ +using System.Collections.Generic; +using Godot; +using Godot.Collections; +using Mr.BrickAdventures.Autoloads; +using Mr.BrickAdventures.scripts.components; +using Mr.BrickAdventures.scripts.Resources; + +namespace Mr.BrickAdventures.scripts.UI; + +public partial class Marketplace : Node +{ + [Export] public Array Skills { get; set; } = []; + [Export] public GridContainer ToUnlockGrid { get; set; } + [Export] public GridContainer UnlockedGrid { get; set; } + [Export] public Font Font { get; set; } + [Export] public SkillUnlockedComponent SkillUnlockedComponent { get; set; } + [Export] public Array ComponentsToDisable { get; set; } = []; + [Export] public PackedScene MarketplaceButtonScene { get; set; } + [Export] public PackedScene SkillButtonScene { get; set; } + + private GameManager _gameManager; + private readonly List