diff --git a/Globals/Scribe.cs b/Globals/Scribe.cs index b1b9884a..249f4556 100644 --- a/Globals/Scribe.cs +++ b/Globals/Scribe.cs @@ -45,5 +45,19 @@ public partial class Scribe : Node ), } ), + new RelicTemplate( + "Dummy Item", + new RelicEffect[] + { + new RelicEffect( + BattleEffectTrigger.NotePlaced, + 100, + (director, val) => + { + director.Player.Heal(val); + } + ), + } + ), }; } diff --git a/Reward.cs b/Reward.cs new file mode 100644 index 00000000..07c61a2c --- /dev/null +++ b/Reward.cs @@ -0,0 +1,66 @@ +using System; +using System.Linq; +using Godot; + +//it's very messy, feel free to clean up as much as necessary + +public static class Reward +{ + private static readonly Random _rng = new Random(); + + public static void GiveRandomRelic(PlayerStats player) + { + RelicTemplate newRelic = GetRandomRelic(player.CurRelics); + + if (newRelic != null) + { + AddRelic(player, newRelic); + GD.Print("Relic added: " + newRelic.Name); + } + else + { + GD.Print("No new relic to collect"); + } + } + + public static RelicTemplate GetRandomRelic(RelicTemplate[] ownedRelics) + { + var availableRelics = Scribe + .RelicDictionary.Where(r => !ownedRelics.Any(o => o.Name == r.Name)) + .ToArray(); + + if (availableRelics.Length == 0) + { + return null; // No new relics available + } + + int index = _rng.Next(availableRelics.Length); + return availableRelics[index].Clone(); + } + + public static void AddRelic(PlayerStats player, RelicTemplate relic) + { + if (player.CurRelics.Any(r => r.Name == relic.Name)) + { + GD.Print("Relic already in inventory: " + relic.Name); + return; + } + player.CurRelics = player.CurRelics.Append(relic).ToArray(); + GD.Print("Adding relic: " + relic.Name); + } + + public static RelicTemplate[] GetMultipleRelics(RelicTemplate[] ownedRelics, int count) + { + var availableRelics = Scribe + .RelicDictionary.Where(r => !ownedRelics.Any(o => o.Name == r.Name)) + .ToArray(); + if (availableRelics.Length == 0) + return new RelicTemplate[0]; + + return availableRelics + .OrderBy(_ => _rng.Next()) + .Take(count) + .Select(r => r.Clone()) + .ToArray(); + } +} diff --git a/RewardSelect.cs b/RewardSelect.cs new file mode 100644 index 00000000..ec2de7b9 --- /dev/null +++ b/RewardSelect.cs @@ -0,0 +1,41 @@ +using System; +using System.Linq; +using Godot; + +public partial class RewardSelect : CanvasLayer +{ + [Export] + public VBoxContainer ButtonContainer; + + private PlayerStats _player; + private RelicTemplate[] _choices; + + public void Initialize(PlayerStats player) + { + _player = player; + GenerateRelicChoices(); + } + + private void GenerateRelicChoices() + { + //should probably change this so that the amount of relics offered can be changed when BD calls it + //i.e less options when killing trash mobs/basic/weak enemies + _choices = Reward.GetMultipleRelics(_player.CurRelics, 3); + + foreach (var relic in _choices) + { + var button = new Button(); + button.Text = relic.Name; + button.Pressed += () => OnRelicSelected(relic); + ButtonContainer.AddChild(button); + } + } + + private void OnRelicSelected(RelicTemplate choiceRelic) + { + Reward.AddRelic(_player, choiceRelic); + GD.Print("Relic selected: " + choiceRelic.Name); + + QueueFree(); + } +} diff --git a/RewardSelectionUI.tscn b/RewardSelectionUI.tscn new file mode 100644 index 00000000..a514446a --- /dev/null +++ b/RewardSelectionUI.tscn @@ -0,0 +1,18 @@ +[gd_scene load_steps=2 format=3 uid="uid://c6icx2yriud6y"] + +[ext_resource type="Script" path="res://RewardSelect.cs" id="1_ts2x3"] + +[node name="CanvasLayer" type="CanvasLayer" node_paths=PackedStringArray("ButtonContainer")] +script = ExtResource("1_ts2x3") +ButtonContainer = NodePath("PanelContainer/VBoxContainer") + +[node name="PanelContainer" type="PanelContainer" parent="."] +offset_left = 34.0 +offset_top = 67.0 +offset_right = 600.0 +offset_bottom = 264.0 + +[node name="VBoxContainer" type="VBoxContainer" parent="PanelContainer"] +layout_mode = 2 + +[node name="RewardSelect" type="Node2D" parent="."] diff --git a/scenes/BattleDirector/scripts/BattleDirector.cs b/scenes/BattleDirector/scripts/BattleDirector.cs index 7cc0f3ca..89412268 100644 --- a/scenes/BattleDirector/scripts/BattleDirector.cs +++ b/scenes/BattleDirector/scripts/BattleDirector.cs @@ -32,6 +32,9 @@ public partial class BattleDirector : Node2D private SongData _curSong; + private bool battleLost = false; + private bool battleWon = false; + #endregion #region Note Handling @@ -116,6 +119,12 @@ private void Begin() public override void _Process(double delta) { + //check if either one is dead until one is true, feel free to remove if we have a more efficent way of checking + //alternatively, stop the other process since the battle is over + if (!battleLost || !battleWon) + { + CheckBattleStatus(); + } TimeKeeper.CurrentTime = Audio.GetPlaybackPosition(); CD.CheckMiss(); } @@ -125,6 +134,15 @@ public override void _Process(double delta) public override void _UnhandledInput(InputEvent @event) { + //this one is for calling a debug key to insta-kill the enemy + if (@event is InputEventKey eventKey && eventKey.Pressed && !eventKey.Echo) + { + if (eventKey.Keycode == Key.Key0) + { + DebugKillEnemy(); + } + } + if (@event.IsActionPressed("Pause")) { var pauseMenu = GD.Load("res://scenes/UI/Pause.tscn"); @@ -209,4 +227,48 @@ private void EventizeRelics() } } #endregion + + + private void CheckBattleStatus() + { + if (battleLost || battleWon) + return; + + if (Player.GetCurrentHealth() <= 0) + { + GD.Print("Player is Dead"); + battleLost = true; + return; + } + + //will have to adjust this to account for when we have multiple enemies at once + if (Enemy.GetCurrentHealth() <= 0) + { + GD.Print("Enemy is dead"); + battleWon = true; + + //below, old method that just adds a random relic to the inventory + //Reward.GiveRandomRelic(Player.Stats); + //EventizeRelics(); //literally just here to force the ui to update and see if it was added, remove with the proper ui update + //probably won't even need it since we'll be loading to seperate scene anyways + + //new method that allows player to choose a relic + ShowRewardSelection(); + + return; + } + } + + private void DebugKillEnemy() + { + Enemy.TakeDamage(1000); + } + + private void ShowRewardSelection() + { + var rewardUI = GD.Load("res://RewardSelectionUI.tscn") + .Instantiate(); + AddChild(rewardUI); + rewardUI.Initialize(Player.Stats); + } } diff --git a/scenes/Puppets/scripts/PlayerStats.cs b/scenes/Puppets/scripts/PlayerStats.cs index c788ff59..b8fc20cf 100644 --- a/scenes/Puppets/scripts/PlayerStats.cs +++ b/scenes/Puppets/scripts/PlayerStats.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using Godot; public partial class PlayerStats : Resource diff --git a/scenes/Puppets/scripts/PuppetTemplate.cs b/scenes/Puppets/scripts/PuppetTemplate.cs index 249638a9..28b40e73 100644 --- a/scenes/Puppets/scripts/PuppetTemplate.cs +++ b/scenes/Puppets/scripts/PuppetTemplate.cs @@ -36,11 +36,16 @@ public void Init(Texture2D texture, string name) public void TakeDamage(int amount) { - _healthBar.ChangeHP(-amount); + _currentHealth = _healthBar.ChangeHP(-amount); } public void Heal(int amount) { _healthBar.ChangeHP(amount); } + + public int GetCurrentHealth() + { + return _currentHealth; + } }