diff --git a/src/game/Game.cs b/src/game/Game.cs index ebb8083b..4764d586 100644 --- a/src/game/Game.cs +++ b/src/game/Game.cs @@ -8,6 +8,7 @@ using Godot; public interface IGame : IProvide, IProvide, INode3D { + event Game.StatRaisedAlertEventHandler StatRaisedAlert; } [Meta(typeof(IAutoNode))] @@ -27,6 +28,9 @@ public partial class Game : Node3D, IGame public GameLogic.IBinding GameBinding { get; set; } = default!; + [Signal] + public delegate void StatRaisedAlertEventHandler(string statRaisedAlert); + [Dependency] public IAppRepo AppRepo => this.DependOn(); #region Nodes @@ -121,6 +125,30 @@ public partial class Game : Node3D, IGame Map.DungeonFinishedGenerating += Map_DungeonFinishedGenerating; InGameUI.InventoryMenu.ClosedMenu += InventoryMenu_CloseInventory; GameRepo.PlayerData.Inventory.InventoryAtCapacity += PlayerInventory_InventoryAtCapacity; + GameRepo.PlayerData.Inventory.RaiseStatRequest += Inventory_RaiseStatRequest; + } + + private void Inventory_RaiseStatRequest(ConsumableItemStats consumableItemStats) + { + if (consumableItemStats.RaiseHPAmount > 0 && GameRepo.PlayerData.CurrentHP.Value.Equals(GameRepo.PlayerData.MaximumHP.Value)) + RaiseHP(consumableItemStats.RaiseHPAmount); + else if (consumableItemStats.HealHPAmount > 0) + HealHP(consumableItemStats.HealHPAmount); + + if (consumableItemStats.RaiseVTAmount > 0 && GameRepo.PlayerData.CurrentVT.Value.Equals(GameRepo.PlayerData.MaximumVT.Value)) + RaiseVT(consumableItemStats.RaiseVTAmount); + else if (consumableItemStats.HealVTAmount > 0) + HealVT(consumableItemStats.HealVTAmount); + } + + private void RaiseHP(int amountToRaise) + { + if (GameRepo.PlayerData.CurrentHP == GameRepo.PlayerData.MaximumHP) + { + GameRepo.PlayerData.SetMaximumHP(GameRepo.PlayerData.MaximumHP.Value + amountToRaise); + GameRepo.PlayerData.SetCurrentHP(GameRepo.PlayerData.MaximumHP.Value); + EmitSignal(SignalName.StatRaisedAlert, $"{amountToRaise} Maximum HP Up."); + } } public void ToggleInventory() @@ -161,5 +189,27 @@ public partial class Game : Node3D, IGame GetTree().Paused = isPaused; } + private void HealHP(int amountToRaise) + { + GameRepo.PlayerData.SetCurrentHP(GameRepo.PlayerData.CurrentHP.Value + amountToRaise); + EmitSignal(SignalName.StatRaisedAlert, $"{amountToRaise}HP Up."); + } + + private void RaiseVT(int amountToRaise) + { + if (GameRepo.PlayerData.CurrentVT == GameRepo.PlayerData.MaximumVT) + { + GameRepo.PlayerData.SetMaximumVT(GameRepo.PlayerData.MaximumVT.Value + amountToRaise); + GameRepo.PlayerData.SetCurrentVT(GameRepo.PlayerData.MaximumVT.Value); + EmitSignal(SignalName.StatRaisedAlert, $"{amountToRaise} Maximum VT Up."); + } + } + + private void HealVT(int amountToRaise) + { + GameRepo.PlayerData.SetCurrentVT(GameRepo.PlayerData.CurrentVT.Value + amountToRaise); + EmitSignal(SignalName.StatRaisedAlert, $"{amountToRaise}VT Up."); + } + public void OnStart() => GameLogic.Input(new GameLogic.Input.StartGame()); } diff --git a/src/inventory_menu/InventoryMenu.cs b/src/inventory_menu/InventoryMenu.cs index 37e91ff1..cfd550d8 100644 --- a/src/inventory_menu/InventoryMenu.cs +++ b/src/inventory_menu/InventoryMenu.cs @@ -4,6 +4,7 @@ using Chickensoft.Introspection; using GameJamDungeon; using Godot; using System.Linq; +using System.Threading; using System.Threading.Tasks; public interface IInventoryMenu : IControl @@ -21,6 +22,9 @@ public partial class InventoryMenu : Control, IInventoryMenu [Dependency] public IGameRepo GameRepo => this.DependOn(); + [Dependency] + public IGame Game => this.DependOn(); + [Signal] public delegate void ClosedMenuEventHandler(); @@ -59,6 +63,8 @@ public partial class InventoryMenu : Control, IInventoryMenu [Node] public Button UseButton { get; set; } = default!; [Node] public Button ThrowButton { get; set; } = default!; [Node] public Button DropButton { get; set; } = default!; + + [Node] public AnimationPlayer AnimationPlayer { get; set; } = default!; #endregion public void OnReady() @@ -84,6 +90,29 @@ public partial class InventoryMenu : Control, IInventoryMenu GameRepo.PlayerData.Inventory.EquippedWeapon.Sync += EquippedWeapon_Sync; GameRepo.PlayerData.Inventory.EquippedArmor.Sync += EquippedArmor_Sync; GameRepo.PlayerData.Inventory.EquippedAccessory.Sync += EquippedAccessory_Sync; + + Game.StatRaisedAlert += Game_StatRaisedAlert; + + AnimationPlayer.AnimationFinished += AnimationPlayer_AnimationFinished; + } + + private async void AnimationPlayer_AnimationFinished(StringName animName) + { + if (animName == "status_up") + { + if (_currentIndex >= ItemSlots.Length - 1) + _currentIndex--; + if (_currentIndex <= 0) + _currentIndex = 0; + await RedrawInventory(); + await ShowInventoryInfo(); + } + } + + private async void Game_StatRaisedAlert(string statRaisedAlert) + { + ItemEffectLabel.Text = statRaisedAlert; + AnimationPlayer.Play("status_up"); } private void EquippedAccessory_Sync(Accessory obj) @@ -129,7 +158,6 @@ public partial class InventoryMenu : Control, IInventoryMenu public async Task RedrawInventory() { - await HideUserActionPrompt(); await ClearItems(); PopulateInventory(); PopulatePlayerInfo(); @@ -182,8 +210,6 @@ public partial class InventoryMenu : Control, IInventoryMenu { foreach (var item in ItemSlots) ItemsPage.RemoveChildEx(item); - - await HideUserActionPrompt(); } private void PopulatePlayerInfo() @@ -228,14 +254,18 @@ public partial class InventoryMenu : Control, IInventoryMenu private async Task HideUserActionPrompt() { - ItemDescriptionTitle.Show(); - ItemEffectLabel.Show(); UseItemPrompt.Hide(); UseButton.Hide(); ThrowButton.Hide(); DropButton.Hide(); } + private async Task ShowInventoryInfo() + { + ItemDescriptionTitle.Show(); + ItemEffectLabel.Show(); + } + private async Task ChangeInventoryPage(InventoryPageNumber pageToChangeTo) { await ClearItems(); @@ -311,12 +341,14 @@ public partial class InventoryMenu : Control, IInventoryMenu if (GameRepo.PlayerData.Inventory.IsEquipped(equipableItem)) { GameRepo.PlayerData.Inventory.Unequip(equipableItem); + AnimationPlayer.Play("status_up"); itemSlot.SetSelectedItemStyle(); } else { GameRepo.PlayerData.Inventory.Equip(equipableItem); itemSlot.SetEquippedSelectedItemStyle(); + AnimationPlayer.Play("status_up"); } } } @@ -328,17 +360,10 @@ public partial class InventoryMenu : Control, IInventoryMenu await EquipOrUnequipItem(); else if (currentItem is ConsumableItem consumable) { - consumable.Use(); - if (_currentIndex >= ItemSlots.Length - 1) - _currentIndex--; - if (_currentIndex <= 0) - _currentIndex = 0; - EmitSignal(SignalName.ClosedMenu); + GameRepo.PlayerData.Inventory.Use(consumable); } - // TODO: Replace with animation player (for visual effects/sound effects?) - await ToSignal(GetTree().CreateTimer(0.25f), "timeout"); - await RedrawInventory(); + await HideUserActionPrompt(); } private async void ThrowButtonPressed() @@ -350,7 +375,7 @@ public partial class InventoryMenu : Control, IInventoryMenu if (_currentIndex <= 0) _currentIndex = 0; EmitSignal(SignalName.ClosedMenu); - currentItem.Throw(); + GameRepo.PlayerData.Inventory.Throw(currentItem); } private async void DropButtonPressed() @@ -363,7 +388,7 @@ public partial class InventoryMenu : Control, IInventoryMenu _currentIndex = 0; EmitSignal(SignalName.ClosedMenu); - currentItem.Drop(); + GameRepo.PlayerData.Inventory.Drop(currentItem); } private enum InventoryPageNumber diff --git a/src/inventory_menu/InventoryMenu.tscn b/src/inventory_menu/InventoryMenu.tscn index 67b4fa54..65022b35 100644 --- a/src/inventory_menu/InventoryMenu.tscn +++ b/src/inventory_menu/InventoryMenu.tscn @@ -1,12 +1,12 @@ -[gd_scene load_steps=32 format=3 uid="uid://dlj8qdg1c5048"] +[gd_scene load_steps=35 format=3 uid="uid://dlj8qdg1c5048"] [ext_resource type="Script" path="res://src/inventory_menu/InventoryMenu.cs" id="1_l64wl"] [ext_resource type="Shader" path="res://src/inventory_menu/InventoryMenu.gdshader" id="2_0fvsh"] [ext_resource type="FontFile" uid="uid://cm8j5vcdop5x0" path="res://src/ui/fonts/Mrs-Eaves-OT-Roman_31443.ttf" id="3_lm4o1"] [ext_resource type="FontFile" uid="uid://cb41qqmxqurj8" path="res://src/ui/fonts/FT88-Bold.ttf" id="4_rg5yb"] [ext_resource type="FontFile" uid="uid://dit3vylt7hmmx" path="res://src/ui/fonts/FT88-Regular.ttf" id="5_2qnnx"] -[ext_resource type="LabelSettings" uid="uid://c4wbba5mo7qcp" path="res://src/ui/label_settings/MainTextFontItalicized.tres" id="6_q3oua"] [ext_resource type="LabelSettings" uid="uid://ca1q6yu8blwxf" path="res://src/ui/label_settings/InventoryMainTextBold.tres" id="6_tmdno"] +[ext_resource type="LabelSettings" uid="uid://cuuo43x72xcsc" path="res://src/ui/label_settings/MainTextBold.tres" id="7_vyrxm"] [ext_resource type="Theme" uid="uid://daxuhpmyxwxck" path="res://src/inventory_menu/InventoryDialogueSelectionStyle.tres" id="8_khyvo"] [sub_resource type="ShaderMaterial" id="ShaderMaterial_i55tv"] @@ -101,6 +101,67 @@ font = ExtResource("3_lm4o1") font_size = 80 font_color = Color(0.737255, 0.705882, 0.690196, 1) +[sub_resource type="Animation" id="Animation_7by7u"] +resource_name = "status_up" +length = 2.5 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("InventoryInfo/HBoxContainer/PlayerInfo/HBoxContainer/VBoxContainer/ItemEffectLabel:visible") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0, 2.5), +"transitions": PackedFloat32Array(1, 1), +"update": 1, +"values": [true, false] +} +tracks/1/type = "value" +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/path = NodePath("InventoryInfo/HBoxContainer/PlayerInfo/HBoxContainer/VBoxContainer/ItemEffectLabel:text") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/keys = { +"times": PackedFloat32Array(2.5), +"transitions": PackedFloat32Array(1), +"update": 1, +"values": [""] +} + +[sub_resource type="Animation" id="Animation_dg155"] +length = 0.001 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("InventoryInfo/HBoxContainer/PlayerInfo/HBoxContainer/VBoxContainer/ItemEffectLabel:visible") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 1, +"values": [true] +} +tracks/1/type = "value" +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/path = NodePath("InventoryInfo/HBoxContainer/PlayerInfo/HBoxContainer/VBoxContainer/ItemEffectLabel:text") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 1, +"values": [""] +} + +[sub_resource type="AnimationLibrary" id="AnimationLibrary_eivo2"] +_data = { +"RESET": SubResource("Animation_dg155"), +"status_up": SubResource("Animation_7by7u") +} + [node name="InventoryMenu" type="Control"] layout_mode = 3 anchors_preset = 15 @@ -349,12 +410,11 @@ unique_name_in_owner = true custom_minimum_size = Vector2(800, 100) layout_mode = 2 size_flags_horizontal = 0 -label_settings = ExtResource("6_q3oua") +label_settings = ExtResource("7_vyrxm") autowrap_mode = 2 [node name="UseItemPrompt" type="Label" parent="InventoryInfo/HBoxContainer/PlayerInfo/HBoxContainer/VBoxContainer"] unique_name_in_owner = true -visible = false custom_minimum_size = Vector2(800, 100) layout_mode = 2 size_flags_horizontal = 0 @@ -485,3 +545,9 @@ alignment = 1 [node name="ReferenceRect3" type="ReferenceRect" parent="InventoryInfo/HBoxContainer/ItemInfo/ItemsPage"] custom_minimum_size = Vector2(0, 14) layout_mode = 2 + +[node name="AnimationPlayer" type="AnimationPlayer" parent="."] +unique_name_in_owner = true +libraries = { +"": SubResource("AnimationLibrary_eivo2") +} diff --git a/src/items/Inventory.cs b/src/items/Inventory.cs index 12ac3e16..4ba28361 100644 --- a/src/items/Inventory.cs +++ b/src/items/Inventory.cs @@ -25,9 +25,17 @@ public interface IInventory : INode public bool IsEquipped(IEquipable equipable); + public void Use(IInventoryItem inventoryItem); + + public void Throw(IInventoryItem inventoryItem); + + public void Drop(IInventoryItem inventoryItem); + event Inventory.InventoryAtCapacityEventHandler InventoryAtCapacity; event Inventory.AccessoryUnequippedEventHandler AccessoryUnequipped; + + event Inventory.RaiseStatRequestEventHandler RaiseStatRequest; } public partial class Inventory : Node, IInventory @@ -39,6 +47,8 @@ public partial class Inventory : Node, IInventory public delegate void InventoryAtCapacityEventHandler(string rejectedItemName); [Signal] public delegate void AccessoryUnequippedEventHandler(AccessoryStats unequippedAccessory); + [Signal] + public delegate void RaiseStatRequestEventHandler(ConsumableItemStats consumableItemStats); public Inventory() { @@ -108,4 +118,23 @@ public partial class Inventory : Node, IInventory else throw new NotImplementedException("Item type is not supported."); } + + public void Use(IInventoryItem item) + { + if (item is ConsumableItem consumableItem) + { + EmitSignal(SignalName.RaiseStatRequest, consumableItem.ConsumableItemInfo); + Remove(consumableItem); + } + } + + public void Throw(IInventoryItem item) + { + Remove(item); + } + + public void Drop(IInventoryItem item) + { + Remove(item); + } } diff --git a/src/items/InventoryItem.cs b/src/items/InventoryItem.cs index f0014739..a3ae7157 100644 --- a/src/items/InventoryItem.cs +++ b/src/items/InventoryItem.cs @@ -9,9 +9,5 @@ namespace GameJamDungeon public IGameRepo GameRepo { get; } public InventoryItemStats Info { get; } - - public void Throw(); - - public void Drop(); } } diff --git a/src/items/consumable/ConsumableItem.cs b/src/items/consumable/ConsumableItem.cs index e93f230d..dea5fd22 100644 --- a/src/items/consumable/ConsumableItem.cs +++ b/src/items/consumable/ConsumableItem.cs @@ -3,7 +3,6 @@ using Chickensoft.Introspection; using GameJamDungeon; using Godot; using System; -using System.Linq; [Meta(typeof(IAutoNode))] public partial class ConsumableItem : Node3D, IInventoryItem @@ -29,58 +28,6 @@ public partial class ConsumableItem : Node3D, IInventoryItem Pickup.BodyEntered += OnEntered; } - public void Use() - { - if (ConsumableItemInfo.RaiseHPAmount != 0) - RaiseHP(); - if (ConsumableItemInfo.RaiseVTAmount != 0) - RaiseVT(); - if (ConsumableItemInfo.HealHPAmount != 0) - HealHP(); - if (ConsumableItemInfo.HealVTAmount != 0) - HealVT(); - - GameRepo.PlayerData.Inventory.Remove(this); - } - - private void RaiseHP() - { - if (GameRepo.PlayerData.CurrentHP == GameRepo.PlayerData.MaximumHP) - { - GameRepo.PlayerData.SetMaximumHP(GameRepo.PlayerData.MaximumHP.Value + ConsumableItemInfo.RaiseHPAmount); - GameRepo.PlayerData.SetCurrentHP(GameRepo.PlayerData.MaximumHP.Value); - } - } - - private void HealHP() - { - GameRepo.PlayerData.SetCurrentHP(GameRepo.PlayerData.CurrentHP.Value + ConsumableItemInfo.HealHPAmount); - } - - private void RaiseVT() - { - if (GameRepo.PlayerData.CurrentVT == GameRepo.PlayerData.MaximumVT) - { - GameRepo.PlayerData.SetMaximumVT(GameRepo.PlayerData.MaximumVT.Value + ConsumableItemInfo.RaiseVTAmount); - GameRepo.PlayerData.SetCurrentVT(GameRepo.PlayerData.MaximumVT.Value); - } - } - - private void HealVT() - { - GameRepo.PlayerData.SetCurrentVT(GameRepo.PlayerData.CurrentVT.Value + ConsumableItemInfo.HealVTAmount); - } - - public void Throw() - { - GameRepo.PlayerData.Inventory.Remove(this); - } - - public void Drop() - { - GameRepo.PlayerData.Inventory.Remove(this); - } - public void OnEntered(Node3D body) { var isAdded = GameRepo.PlayerData.Inventory.TryAdd(this); diff --git a/src/ui/label_settings/InventoryFullAlertLabelSetting.tres b/src/ui/label_settings/InventoryFullAlertLabelSetting.tres new file mode 100644 index 00000000..94b67aef --- /dev/null +++ b/src/ui/label_settings/InventoryFullAlertLabelSetting.tres @@ -0,0 +1,8 @@ +[gd_resource type="LabelSettings" load_steps=2 format=3 uid="uid://bqdq5r46uduvd"] + +[ext_resource type="FontFile" uid="uid://dit3vylt7hmmx" path="res://src/ui/fonts/FT88-Regular.ttf" id="1_gld51"] + +[resource] +font = ExtResource("1_gld51") +font_size = 24 +font_color = Color(0.737255, 0.705882, 0.690196, 1) diff --git a/src/ui/label_settings/MainTextFontItalicized.tres b/src/ui/label_settings/MainTextFontItalicized.tres index 382e8c3f..6fe3ff3a 100644 --- a/src/ui/label_settings/MainTextFontItalicized.tres +++ b/src/ui/label_settings/MainTextFontItalicized.tres @@ -5,3 +5,4 @@ [resource] font = ExtResource("1_ofouc") font_size = 36 +font_color = Color(1, 0.94902, 0, 1) diff --git a/src/ui/player_ui/PlayerInfoUI.cs b/src/ui/player_ui/PlayerInfoUI.cs index 2c469577..7d11b41b 100644 --- a/src/ui/player_ui/PlayerInfoUI.cs +++ b/src/ui/player_ui/PlayerInfoUI.cs @@ -32,7 +32,7 @@ public partial class PlayerInfoUI : Control, IPlayerInfoUI public void OnResolved() { - _labelSettings = GD.Load("res://src/ui/label_settings/MainTextRegular.tres"); + _labelSettings = GD.Load("res://src/ui/label_settings/InventoryFullAlertLabelSetting.tres"); GameRepo.PlayerData.CurrentHP.Sync += CurrentHP_Sync; GameRepo.PlayerData.MaximumHP.Sync += MaximumHP_Sync;