Add more interactive effects to inventory menu

This commit is contained in:
2024-09-10 19:40:19 -07:00
parent 081bde1d9a
commit d854f159b4
21 changed files with 279 additions and 112 deletions

View File

@@ -7,10 +7,10 @@ using DialogueManagerRuntime;
using Godot; using Godot;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks;
public interface IGame : IProvide<IGameRepo>, INode3D public interface IGame : IProvide<IGameRepo>, IProvide<IGame>, INode3D
{ {
public void ToggleInventory();
} }
[Meta(typeof(IAutoNode))] [Meta(typeof(IAutoNode))]
@@ -20,6 +20,8 @@ public partial class Game : Node3D, IGame
IGameRepo IProvide<IGameRepo>.Value() => GameRepo; IGameRepo IProvide<IGameRepo>.Value() => GameRepo;
IGame IProvide<IGame>.Value() => this;
public IInstantiator Instantiator { get; set; } = default!; public IInstantiator Instantiator { get; set; } = default!;
public IGameLogic GameLogic { get; set; } = default!; public IGameLogic GameLogic { get; set; } = default!;
@@ -116,6 +118,11 @@ public partial class Game : Node3D, IGame
this.Provide(); this.Provide();
} }
public void ToggleInventory()
{
GameLogic.Input(new GameLogic.Input.InventoryMenuToggle());
}
private void AnimationPlayer_AnimationStarted(StringName animName) private void AnimationPlayer_AnimationStarted(StringName animName)
{ {
var newFloor = Floors.ElementAt(GameRepo.CurrentFloor + 1); var newFloor = Floors.ElementAt(GameRepo.CurrentFloor + 1);
@@ -130,21 +137,21 @@ public partial class Game : Node3D, IGame
GameRepo.CurrentFloor++; GameRepo.CurrentFloor++;
} }
public override void _Process(double delta) public override void _UnhandledInput(InputEvent @event)
{ {
if (Input.IsActionJustPressed(GameInputs.Inventory)) if (@event.IsActionPressed(GameInputs.Inventory))
{ {
GD.Print("Inventory button pressed"); GD.Print("Inventory button pressed");
GameLogic.Input(new GameLogic.Input.InventoryMenuButtonPressed()); GameLogic.Input(new GameLogic.Input.InventoryMenuToggle());
} }
if (Input.IsActionJustPressed(GameInputs.MiniMap)) if (@event.IsActionPressed(GameInputs.MiniMap))
{ {
GD.Print("MiniMap button pressed"); GD.Print("MiniMap button pressed");
GameLogic.Input(new GameLogic.Input.MiniMapButtonPressed()); GameLogic.Input(new GameLogic.Input.MiniMapButtonPressed());
} }
if (Input.IsActionJustReleased(GameInputs.MiniMap)) if (@event.IsActionReleased(GameInputs.MiniMap))
{ {
GD.Print("MiniMap button released"); GD.Print("MiniMap button released");
GameLogic.Input(new GameLogic.Input.MiniMapButtonReleased()); GameLogic.Input(new GameLogic.Input.MiniMapButtonReleased());

View File

@@ -8,7 +8,7 @@
public readonly record struct Initialize; public readonly record struct Initialize;
public readonly record struct InventoryMenuButtonPressed; public readonly record struct InventoryMenuToggle;
public readonly record struct MiniMapButtonPressed; public readonly record struct MiniMapButtonPressed;

View File

@@ -8,14 +8,14 @@ namespace GameJamDungeon
public partial record State public partial record State
{ {
[Meta] [Meta]
public partial record InventoryOpened : State, IGet<Input.InventoryMenuButtonPressed> public partial record InventoryOpened : State, IGet<Input.InventoryMenuToggle>
{ {
public InventoryOpened() public InventoryOpened()
{ {
this.OnEnter(() => { Get<IGameRepo>().Pause(); Output(new Output.SetInventoryMode(Get<IGameRepo>().InventoryItems.Value)); }); this.OnEnter(() => { Get<IGameRepo>().Pause(); Output(new Output.SetInventoryMode(Get<IGameRepo>().InventoryItems.Value)); });
this.OnExit(() => { Get<IGameRepo>().Resume(); Output(new Output.HideInventory()); }); this.OnExit(() => { Get<IGameRepo>().Resume(); Output(new Output.HideInventory()); });
} }
public Transition On(in Input.InventoryMenuButtonPressed input) => To<Playing>(); public Transition On(in Input.InventoryMenuToggle input) => To<Playing>();
} }
} }
} }

View File

@@ -8,7 +8,7 @@ namespace GameJamDungeon
public partial record State public partial record State
{ {
[Meta] [Meta]
public partial record Paused : State, IGet<Input.InventoryMenuButtonPressed>, IGet<Input.MiniMapButtonReleased> public partial record Paused : State, IGet<Input.InventoryMenuToggle>, IGet<Input.MiniMapButtonReleased>
{ {
public Paused() public Paused()
{ {
@@ -17,7 +17,7 @@ namespace GameJamDungeon
} }
public virtual Transition On(in Input.InventoryMenuButtonPressed input) => To<Playing>(); public virtual Transition On(in Input.InventoryMenuToggle input) => To<Playing>();
public virtual Transition On(in Input.MiniMapButtonReleased input) => To<Playing>(); public virtual Transition On(in Input.MiniMapButtonReleased input) => To<Playing>();
} }

View File

@@ -8,7 +8,7 @@ namespace GameJamDungeon
public partial record State public partial record State
{ {
[Meta] [Meta]
public partial record Playing : State, IGet<Input.InventoryMenuButtonPressed>, IGet<Input.MiniMapButtonPressed>, IGet<Input.GameOver>, IGet<Input.LoadNextFloor> public partial record Playing : State, IGet<Input.InventoryMenuToggle>, IGet<Input.MiniMapButtonPressed>, IGet<Input.GameOver>, IGet<Input.LoadNextFloor>
{ {
public Playing() public Playing()
{ {
@@ -20,7 +20,7 @@ namespace GameJamDungeon
public void OnEnded() => Input(new Input.GameOver()); public void OnEnded() => Input(new Input.GameOver());
public Transition On(in Input.InventoryMenuButtonPressed input) => To<InventoryOpened>(); public Transition On(in Input.InventoryMenuToggle input) => To<InventoryOpened>();
public Transition On(in Input.MiniMapButtonPressed input) => To<MinimapOpen>(); public Transition On(in Input.MiniMapButtonPressed input) => To<MinimapOpen>();

View File

@@ -4,6 +4,7 @@ using Chickensoft.Introspection;
using GameJamDungeon; using GameJamDungeon;
using Godot; using Godot;
using System.Linq; using System.Linq;
using System.Threading.Tasks;
public interface IInventoryMenu : IControl public interface IInventoryMenu : IControl
{ {
@@ -20,6 +21,9 @@ public partial class InventoryMenu : Control, IInventoryMenu
[Dependency] [Dependency]
public IGameRepo GameRepo => this.DependOn<IGameRepo>(); public IGameRepo GameRepo => this.DependOn<IGameRepo>();
[Dependency]
public IGame Game => this.DependOn<IGame>();
// Player Info // Player Info
[Node] public Label FloorLabel { get; set; } = default!; [Node] public Label FloorLabel { get; set; } = default!;
[Node] public Label CurrentLevelLabel { get; set; } = default!; [Node] public Label CurrentLevelLabel { get; set; } = default!;
@@ -43,12 +47,14 @@ public partial class InventoryMenu : Control, IInventoryMenu
// User Prompt Menu // User Prompt Menu
[Node] public Label UseItemPrompt { get; set; } = default!; [Node] public Label UseItemPrompt { get; set; } = default!;
[Node] public Button UseButton { get; set; } = default!; [Node] public Button UseButton { get; set; } = default!;
[Node] public Button EquipButton { get; set; } = default!; [Node] public Button ThrowButton { get; set; } = default!;
[Node] public Button DropButton { get; set; } = default!; [Node] public Button DropButton { get; set; } = default!;
public void OnReady() public void OnReady()
{ {
EquipButton.Pressed += EquipButtonPressed; UseButton.Pressed += UseButtonPressed;
ThrowButton.Pressed += ThrowButtonPressed;
DropButton.Pressed += DropButtonPressed;
} }
private InventoryPageNumber _currentPageNumber = InventoryPageNumber.FirstPage; private InventoryPageNumber _currentPageNumber = InventoryPageNumber.FirstPage;
@@ -127,30 +133,27 @@ public partial class InventoryMenu : Control, IInventoryMenu
var inventory = GameRepo.InventoryItems.Value; var inventory = GameRepo.InventoryItems.Value;
if (Input.IsActionJustPressed(GameInputs.UiRight) && _currentPageNumber == InventoryPageNumber.FirstPage && inventory.Count > _itemsPerPage) if (@event.IsActionPressed(GameInputs.UiRight) && _currentPageNumber == InventoryPageNumber.FirstPage && inventory.Count > _itemsPerPage)
ChangeInventoryPage(InventoryPageNumber.SecondPage); ChangeInventoryPage(InventoryPageNumber.SecondPage);
if (Input.IsActionJustPressed(GameInputs.UiLeft) && _currentPageNumber == InventoryPageNumber.SecondPage) if (@event.IsActionPressed(GameInputs.UiLeft) && _currentPageNumber == InventoryPageNumber.SecondPage)
ChangeInventoryPage(InventoryPageNumber.FirstPage); ChangeInventoryPage(InventoryPageNumber.FirstPage);
if (Input.IsActionJustPressed(GameInputs.UiDown)) if (@event.IsActionPressed(GameInputs.UiDown))
{ {
SetToUnselectedStyle(ItemSlots.ElementAt(_currentIndex)); SetToUnselectedStyle(ItemSlots.ElementAt(_currentIndex));
_currentIndex = new[] { _currentIndex + 1, _itemsPerPage - 1, ItemSlots.Length - 1 }.Min(); _currentIndex = new[] { _currentIndex + 1, _itemsPerPage - 1, ItemSlots.Length - 1 }.Min();
SetToSelectedStyle(ItemSlots.ElementAt(_currentIndex)); SetToSelectedStyle(ItemSlots.ElementAt(_currentIndex));
} }
if (Input.IsActionJustPressed(GameInputs.UiUp)) if (@event.IsActionPressed(GameInputs.UiUp))
{ {
if (ItemSlots.Length == 0)
return;
SetToUnselectedStyle(ItemSlots.ElementAt(_currentIndex)); SetToUnselectedStyle(ItemSlots.ElementAt(_currentIndex));
_currentIndex = new[] { _currentIndex - 1, 0 }.Max(); _currentIndex = new[] { _currentIndex - 1, 0 }.Max();
SetToSelectedStyle(ItemSlots.ElementAt(_currentIndex)); SetToSelectedStyle(ItemSlots.ElementAt(_currentIndex));
} }
if (Input.IsActionJustPressed(GameInputs.UiAccept)) if (@event.IsActionPressed(GameInputs.UiAccept))
{ {
if (ItemSlots.Length == 0 || GetViewport().GuiGetFocusOwner() is Button) if (ItemSlots.Length == 0 || GetViewport().GuiGetFocusOwner() is Button)
return; return;
@@ -164,42 +167,42 @@ public partial class InventoryMenu : Control, IInventoryMenu
ItemEffectLabel.Hide(); ItemEffectLabel.Hide();
UseItemPrompt.Show(); UseItemPrompt.Show();
UseButton.Show(); UseButton.Show();
EquipButton.Show(); ThrowButton.Show();
EquipButton.Disabled = false;
DropButton.Show(); DropButton.Show();
var currentItem = ItemSlots.ElementAt(_currentIndex).Item; var currentItem = ItemSlots.ElementAt(_currentIndex).Item;
if (currentItem is IEquipable equipable) if (currentItem is IEquipable equipable)
{ {
EquipButton.Disabled = false; var isEquipped = GameRepo.IsItemEquipped(equipable);
EquipButton.FocusMode = FocusModeEnum.All; UseButton.Text = isEquipped ? "Unequip" : "Equip";
EquipButton.Text = GameRepo.IsItemEquipped(equipable) ? "Unequip" : "Equip"; ThrowButton.Disabled = isEquipped ? true : false;
ThrowButton.FocusMode = isEquipped ? FocusModeEnum.None : FocusModeEnum.All;
DropButton.Disabled = isEquipped ? true : false;
DropButton.FocusMode = isEquipped ? FocusModeEnum.None : FocusModeEnum.All;
} }
else else
{ {
EquipButton.Disabled = true; UseButton.Text = "Use";
EquipButton.FocusMode = FocusModeEnum.None;
} }
UseButton.Text = currentItem is ThrowableItem ? "Throw" : "Use";
UseButton.GrabFocus(); UseButton.GrabFocus();
} }
private void HideUserActionPrompt() private async Task HideUserActionPrompt()
{ {
ItemDescriptionTitle.Show(); ItemDescriptionTitle.Show();
ItemEffectLabel.Show(); ItemEffectLabel.Show();
UseItemPrompt.Hide(); UseItemPrompt.Hide();
UseButton.Hide(); UseButton.Hide();
EquipButton.Hide(); ThrowButton.Hide();
DropButton.Hide(); DropButton.Hide();
} }
private void ChangeInventoryPage(InventoryPageNumber pageToChangeTo) private async void ChangeInventoryPage(InventoryPageNumber pageToChangeTo)
{ {
ClearItems(); ClearItems();
await ToSignal(GetTree().CreateTimer(0.1f), "timeout");
_currentIndex = 0; _currentIndex = 0;
_currentPageNumber = pageToChangeTo; _currentPageNumber = pageToChangeTo;
PopulateItems(); PopulateItems();
@@ -246,15 +249,17 @@ public partial class InventoryMenu : Control, IInventoryMenu
} }
} }
private void SetToUnselectedStyle(IItemSlot itemSlot) private async void SetToUnselectedStyle(IItemSlot itemSlot)
{ {
await ToSignal(GetTree().CreateTimer(0.1f), "timeout");
itemSlot.SetItemStyle(); itemSlot.SetItemStyle();
if (itemSlot.Item is IEquipable equipable && GameRepo.IsItemEquipped(equipable)) if (itemSlot.Item is IEquipable equipable && GameRepo.IsItemEquipped(equipable))
itemSlot.SetEquippedItemStyle(); itemSlot.SetEquippedItemStyle();
} }
private void SetToSelectedStyle(IItemSlot itemSlot) private async void SetToSelectedStyle(IItemSlot itemSlot)
{ {
await ToSignal(GetTree().CreateTimer(0.1f), "timeout");
itemSlot.SetSelectedItemStyle(); itemSlot.SetSelectedItemStyle();
if (itemSlot.Item is IEquipable newEquipable && GameRepo.IsItemEquipped(newEquipable)) if (itemSlot.Item is IEquipable newEquipable && GameRepo.IsItemEquipped(newEquipable))
itemSlot.SetEquippedSelectedItemStyle(); itemSlot.SetEquippedSelectedItemStyle();
@@ -262,9 +267,10 @@ public partial class InventoryMenu : Control, IInventoryMenu
ItemEffectLabel.Text = $"{itemSlot.Item.Info.Description}"; ItemEffectLabel.Text = $"{itemSlot.Item.Info.Description}";
} }
private void EquipOrUnequipItem() private async void EquipOrUnequipItem()
{ {
var itemSlot = ItemSlots[_currentIndex]; var itemSlot = ItemSlots[_currentIndex];
await ToSignal(GetTree().CreateTimer(0.2f), "timeout");
if (itemSlot.Item is IEquipable equipableItem) if (itemSlot.Item is IEquipable equipableItem)
{ {
if (GameRepo.IsItemEquipped(equipableItem)) if (GameRepo.IsItemEquipped(equipableItem))
@@ -300,10 +306,43 @@ public partial class InventoryMenu : Control, IInventoryMenu
VTValue.Text = $"{currentVT}/{maxVT}"; VTValue.Text = $"{currentVT}/{maxVT}";
} }
private void EquipButtonPressed() private async void UseButtonPressed()
{ {
var currentItem = ItemSlots[_currentIndex].Item;
if (currentItem is IEquipable)
EquipOrUnequipItem(); EquipOrUnequipItem();
HideUserActionPrompt(); if (currentItem is ConsumableItem consumable)
consumable.Use();
// TODO: Replace with animation player (for visual effects/sound effects?)
await ToSignal(GetTree().CreateTimer(0.25f), "timeout");
await HideUserActionPrompt();
PopulatePlayerInfo();
}
private async void ThrowButtonPressed()
{
var currentItem = ItemSlots[_currentIndex].Item;
if (_currentIndex >= ItemSlots.Length - 1)
_currentIndex--;
if (_currentIndex <= 0)
_currentIndex = 0;
Game.ToggleInventory();
currentItem.Throw();
}
private async void DropButtonPressed()
{
var currentItem = ItemSlots[_currentIndex].Item;
if (_currentIndex >= ItemSlots.Length - 1)
_currentIndex--;
if (_currentIndex <= 0)
_currentIndex = 0;
Game.ToggleInventory();
currentItem.Drop();
} }
private enum InventoryPageNumber private enum InventoryPageNumber

View File

@@ -73,16 +73,16 @@ font_color = Color(0.737255, 0.705882, 0.690196, 1)
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_0kb6l"] [sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_0kb6l"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_ascpt"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_abpb1"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_545ij"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_fu7o2"] [sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_fu7o2"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_nkvce"] [sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_nkvce"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_545ij"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_ascpt"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_abpb1"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_omlgh"] [sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_omlgh"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_uerb4"] [sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_uerb4"]
@@ -373,31 +373,15 @@ autowrap_mode = 2
[node name="UseButton" type="Button" parent="InventoryInfo/HBoxContainer/PlayerInfo/HBoxContainer/VBoxContainer"] [node name="UseButton" type="Button" parent="InventoryInfo/HBoxContainer/PlayerInfo/HBoxContainer/VBoxContainer"]
unique_name_in_owner = true unique_name_in_owner = true
visible = false
custom_minimum_size = Vector2(200, 0) custom_minimum_size = Vector2(200, 0)
layout_mode = 2 layout_mode = 2
size_flags_horizontal = 0 size_flags_horizontal = 0
size_flags_vertical = 0 size_flags_vertical = 0
focus_neighbor_top = NodePath("../DropButton") focus_neighbor_left = NodePath(".")
focus_neighbor_bottom = NodePath("../EquipButton") focus_neighbor_top = NodePath(".")
theme = ExtResource("8_khyvo") focus_neighbor_right = NodePath(".")
theme_override_colors/font_disabled_color = Color(0.137255, 0.121569, 0.12549, 1) focus_neighbor_bottom = NodePath("../ThrowButton")
theme_override_colors/font_pressed_color = Color(0.137255, 0.121569, 0.12549, 1)
theme_override_colors/font_focus_color = Color(1, 0.94902, 0, 1)
theme_override_colors/font_color = Color(0.737255, 0.705882, 0.690196, 1)
theme_override_styles/focus = SubResource("StyleBoxEmpty_0kb6l")
theme_override_styles/disabled = SubResource("StyleBoxEmpty_ascpt")
theme_override_styles/pressed = SubResource("StyleBoxEmpty_abpb1")
theme_override_styles/normal = SubResource("StyleBoxEmpty_545ij")
button_mask = 0
text = "Use"
alignment = 0
[node name="EquipButton" type="Button" parent="InventoryInfo/HBoxContainer/PlayerInfo/HBoxContainer/VBoxContainer"]
unique_name_in_owner = true
custom_minimum_size = Vector2(200, 0)
layout_mode = 2
size_flags_horizontal = 0
size_flags_vertical = 0
theme = ExtResource("8_khyvo") theme = ExtResource("8_khyvo")
theme_override_colors/font_disabled_color = Color(0.137255, 0.121569, 0.12549, 1) theme_override_colors/font_disabled_color = Color(0.137255, 0.121569, 0.12549, 1)
theme_override_colors/font_pressed_color = Color(0.137255, 0.121569, 0.12549, 1) theme_override_colors/font_pressed_color = Color(0.137255, 0.121569, 0.12549, 1)
@@ -408,17 +392,44 @@ theme_override_styles/disabled = SubResource("StyleBoxEmpty_fu7o2")
theme_override_styles/pressed = SubResource("StyleBoxEmpty_nkvce") theme_override_styles/pressed = SubResource("StyleBoxEmpty_nkvce")
theme_override_styles/normal = SubResource("StyleBoxEmpty_545ij") theme_override_styles/normal = SubResource("StyleBoxEmpty_545ij")
button_mask = 0 button_mask = 0
text = "Equip" text = "Use"
alignment = 0 alignment = 0
[node name="DropButton" type="Button" parent="InventoryInfo/HBoxContainer/PlayerInfo/HBoxContainer/VBoxContainer"] [node name="ThrowButton" type="Button" parent="InventoryInfo/HBoxContainer/PlayerInfo/HBoxContainer/VBoxContainer"]
unique_name_in_owner = true unique_name_in_owner = true
visible = false
custom_minimum_size = Vector2(200, 0) custom_minimum_size = Vector2(200, 0)
layout_mode = 2 layout_mode = 2
size_flags_horizontal = 0 size_flags_horizontal = 0
size_flags_vertical = 0 size_flags_vertical = 0
focus_neighbor_top = NodePath("../EquipButton") focus_neighbor_left = NodePath(".")
focus_neighbor_bottom = NodePath("../UseButton") focus_neighbor_top = NodePath("../UseButton")
focus_neighbor_right = NodePath(".")
focus_neighbor_bottom = NodePath("../DropButton")
theme = ExtResource("8_khyvo")
theme_override_colors/font_disabled_color = Color(0.137255, 0.121569, 0.12549, 1)
theme_override_colors/font_pressed_color = Color(0.137255, 0.121569, 0.12549, 1)
theme_override_colors/font_focus_color = Color(1, 0.94902, 0, 1)
theme_override_colors/font_color = Color(0.737255, 0.705882, 0.690196, 1)
theme_override_styles/focus = SubResource("StyleBoxEmpty_0kb6l")
theme_override_styles/disabled = SubResource("StyleBoxEmpty_ascpt")
theme_override_styles/pressed = SubResource("StyleBoxEmpty_abpb1")
theme_override_styles/normal = SubResource("StyleBoxEmpty_545ij")
button_mask = 0
text = "Throw"
alignment = 0
[node name="DropButton" type="Button" parent="InventoryInfo/HBoxContainer/PlayerInfo/HBoxContainer/VBoxContainer"]
unique_name_in_owner = true
visible = false
custom_minimum_size = Vector2(200, 0)
layout_mode = 2
size_flags_horizontal = 0
size_flags_vertical = 0
focus_neighbor_left = NodePath(".")
focus_neighbor_top = NodePath("../ThrowButton")
focus_neighbor_right = NodePath(".")
focus_neighbor_bottom = NodePath(".")
theme = ExtResource("8_khyvo") theme = ExtResource("8_khyvo")
theme_override_colors/font_disabled_color = Color(0.137255, 0.121569, 0.12549, 1) theme_override_colors/font_disabled_color = Color(0.137255, 0.121569, 0.12549, 1)
theme_override_colors/font_pressed_color = Color(0.137255, 0.121569, 0.12549, 1) theme_override_colors/font_pressed_color = Color(0.137255, 0.121569, 0.12549, 1)
@@ -436,30 +447,30 @@ alignment = 0
layout_mode = 2 layout_mode = 2
theme_override_constants/separation = 20 theme_override_constants/separation = 20
[node name="HBoxContainer" type="HBoxContainer" parent="InventoryInfo/HBoxContainer/ItemInfo"] [node name="CenterContainer" type="CenterContainer" parent="InventoryInfo/HBoxContainer/ItemInfo"]
custom_minimum_size = Vector2(800, 0) custom_minimum_size = Vector2(800, 0)
layout_mode = 2 layout_mode = 2
size_flags_horizontal = 4 size_flags_horizontal = 4
[node name="BackArrow" type="Label" parent="InventoryInfo/HBoxContainer/ItemInfo/HBoxContainer"] [node name="BackArrow" type="Label" parent="InventoryInfo/HBoxContainer/ItemInfo/CenterContainer"]
unique_name_in_owner = true unique_name_in_owner = true
custom_minimum_size = Vector2(100, 100) custom_minimum_size = Vector2(800, 0)
layout_mode = 2 layout_mode = 2
text = "◄" text = "◄"
label_settings = SubResource("LabelSettings_x4aj3") label_settings = SubResource("LabelSettings_x4aj3")
horizontal_alignment = 2
[node name="ItemsTitle" type="Label" parent="InventoryInfo/HBoxContainer/ItemInfo/HBoxContainer"] [node name="ItemsTitle" type="Label" parent="InventoryInfo/HBoxContainer/ItemInfo/CenterContainer"]
custom_minimum_size = Vector2(600, 0) custom_minimum_size = Vector2(450, 0)
layout_mode = 2 layout_mode = 2
size_flags_horizontal = 4
text = " ITEMS" text = " ITEMS"
label_settings = SubResource("LabelSettings_31kc7") label_settings = SubResource("LabelSettings_31kc7")
horizontal_alignment = 1 horizontal_alignment = 1
vertical_alignment = 1 vertical_alignment = 1
[node name="ForwardArrow" type="Label" parent="InventoryInfo/HBoxContainer/ItemInfo/HBoxContainer"] [node name="ForwardArrow" type="Label" parent="InventoryInfo/HBoxContainer/ItemInfo/CenterContainer"]
unique_name_in_owner = true unique_name_in_owner = true
custom_minimum_size = Vector2(100, 100) custom_minimum_size = Vector2(800, 100)
layout_mode = 2 layout_mode = 2
text = "►" text = "►"
label_settings = SubResource("LabelSettings_x4aj3") label_settings = SubResource("LabelSettings_x4aj3")

View File

@@ -11,5 +11,9 @@ namespace GameJamDungeon
public IGameRepo GameRepo { get; } public IGameRepo GameRepo { get; }
public InventoryItemInfo Info { get; } public InventoryItemInfo Info { get; }
public void Throw();
public void Drop();
} }
} }

View File

@@ -30,6 +30,16 @@ public partial class Accessory : Node3D, IInventoryItem, IEquipable
Pickup.BodyEntered += OnEntered; Pickup.BodyEntered += OnEntered;
} }
public void Throw()
{
GameRepo.InventoryItems.Value.Remove(this);
}
public void Drop()
{
GameRepo.InventoryItems.Value.Remove(this);
}
public void OnEntered(Node3D body) public void OnEntered(Node3D body)
{ {
if (GameRepo.InventoryItems.Value.Count() >= GameRepo.MaxItemSize) if (GameRepo.InventoryItems.Value.Count() >= GameRepo.MaxItemSize)

View File

@@ -30,6 +30,16 @@ public partial class Armor : Node3D, IInventoryItem, IEquipable
Pickup.BodyEntered += OnEntered; Pickup.BodyEntered += OnEntered;
} }
public void Throw()
{
GameRepo.InventoryItems.Value.Remove(this);
}
public void Drop()
{
GameRepo.InventoryItems.Value.Remove(this);
}
public void OnEntered(Node3D body) public void OnEntered(Node3D body)
{ {
if (GameRepo.InventoryItems.Value.Count() >= GameRepo.MaxItemSize) if (GameRepo.InventoryItems.Value.Count() >= GameRepo.MaxItemSize)

View File

@@ -29,6 +29,56 @@ public partial class ConsumableItem : Node3D, IInventoryItem
Pickup.BodyEntered += OnEntered; 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();
}
private void RaiseHP()
{
if (GameRepo.PlayerStatInfo.Value.CurrentHP == GameRepo.PlayerStatInfo.Value.MaximumHP)
{
GameRepo.PlayerStatInfo.Value.MaximumHP += ConsumableItemInfo.RaiseHPAmount;
GameRepo.PlayerStatInfo.Value.CurrentHP = GameRepo.PlayerStatInfo.Value.MaximumHP;
}
}
private void HealHP()
{
GameRepo.PlayerStatInfo.Value.CurrentHP += ConsumableItemInfo.HealHPAmount;
}
private void RaiseVT()
{
if (GameRepo.PlayerStatInfo.Value.CurrentVT == GameRepo.PlayerStatInfo.Value.MaximumVT)
{
GameRepo.PlayerStatInfo.Value.MaximumVT += ConsumableItemInfo.RaiseVTAmount;
GameRepo.PlayerStatInfo.Value.CurrentVT = GameRepo.PlayerStatInfo.Value.MaximumVT;
}
}
private void HealVT()
{
GameRepo.PlayerStatInfo.Value.CurrentVT += ConsumableItemInfo.HealVTAmount;
}
public void Throw()
{
GameRepo.InventoryItems.Value.Remove(this);
}
public void Drop()
{
GameRepo.InventoryItems.Value.Remove(this);
}
public void OnEntered(Node3D body) public void OnEntered(Node3D body)
{ {
if (GameRepo.InventoryItems.Value.Count() >= GameRepo.MaxItemSize) if (GameRepo.InventoryItems.Value.Count() >= GameRepo.MaxItemSize)

View File

@@ -5,4 +5,15 @@ namespace GameJamDungeon;
[GlobalClass] [GlobalClass]
public partial class ConsumableItemInfo : InventoryItemInfo public partial class ConsumableItemInfo : InventoryItemInfo
{ {
[Export]
public int HealHPAmount { get; set; } = 0;
[Export]
public int RaiseHPAmount { get; set; } = 0;
[Export]
public int HealVTAmount { get; set; } = 0;
[Export]
public int RaiseVTAmount { get; set; } = 0;
} }

View File

@@ -5,7 +5,10 @@
[resource] [resource]
script = ExtResource("1_f8ogj") script = ExtResource("1_f8ogj")
HealVTAmount = 30
RaiseVTAmount = 10
Name = "Stelo Fragment" Name = "Stelo Fragment"
Description = "A small gathered piece of the former heavens. Description = "A small gathered piece of the former heavens.
Restores 30 VT. If VT full, raises MAX VT by 10." Restores 30 VT. If VT full, raises MAX VT by 10."
Texture = ExtResource("1_ic5xm") Texture = ExtResource("1_ic5xm")
SpawnRate = 0.5

View File

@@ -35,6 +35,16 @@ public partial class ThrowableItem : Node3D, IInventoryItem
Pickup.BodyEntered += OnEntered; Pickup.BodyEntered += OnEntered;
} }
public void Throw()
{
GameRepo.InventoryItems.Value.Remove(this);
}
public void Drop()
{
GameRepo.InventoryItems.Value.Remove(this);
}
public void OnEntered(Node3D body) public void OnEntered(Node3D body)
{ {
if (GameRepo.InventoryItems.Value.Count() >= GameRepo.MaxItemSize) if (GameRepo.InventoryItems.Value.Count() >= GameRepo.MaxItemSize)

View File

@@ -29,6 +29,16 @@ public partial class Weapon : Node3D, IInventoryItem, IEquipable
Pickup.BodyEntered += OnEntered; Pickup.BodyEntered += OnEntered;
} }
public void Throw()
{
GameRepo.InventoryItems.Value.Remove(this);
}
public void Drop()
{
GameRepo.InventoryItems.Value.Remove(this);
}
public void OnEntered(Node3D body) public void OnEntered(Node3D body)
{ {
if (GameRepo.InventoryItems.Value.Count() >= GameRepo.MaxItemSize) if (GameRepo.InventoryItems.Value.Count() >= GameRepo.MaxItemSize)

View File

@@ -45,7 +45,7 @@ public partial class Menu : Control, IMenu
public override void _UnhandledInput(InputEvent @event) public override void _UnhandledInput(InputEvent @event)
{ {
if (Input.IsActionJustPressed(GameInputs.Attack)) if (@event.IsActionPressed(GameInputs.Attack))
OnNewGamePressed(); OnNewGamePressed();
} }
} }

View File

@@ -52,7 +52,7 @@ public partial class Npc : Node3D
public override void _UnhandledInput(InputEvent @event) public override void _UnhandledInput(InputEvent @event)
{ {
if (Input.IsActionJustPressed(GameInputs.Throw) && _isInDialogueZone) if (@event.IsActionPressed(GameInputs.Throw) && _isInDialogueZone)
{ {
if (_isIntroductionComplete) if (_isIntroductionComplete)
DialogueController.ShowDialogue(Dialogue, "general"); DialogueController.ShowDialogue(Dialogue, "general");

View File

@@ -84,7 +84,7 @@ namespace GameJamDungeon
public void Setup() public void Setup()
{ {
Settings = new PlayerLogic.Settings(RotationSpeed, MoveSpeed); Settings = new PlayerLogic.Settings() { RotationSpeed = RotationSpeed, MoveSpeed = MoveSpeed };
PlayerLogic = new PlayerLogic(); PlayerLogic = new PlayerLogic();
PlayerLogic.Set(this as IPlayer); PlayerLogic.Set(this as IPlayer);
@@ -136,8 +136,13 @@ namespace GameJamDungeon
public override void _UnhandledInput(InputEvent @event) public override void _UnhandledInput(InputEvent @event)
{ {
if (Input.IsActionJustPressed(GameInputs.Attack)) if (@event.IsActionPressed(GameInputs.Attack))
PlayerLogic.Input(new PlayerLogic.Input.Attack()); PlayerLogic.Input(new PlayerLogic.Input.Attack());
if (@event.IsActionPressed(GameInputs.Sprint))
Settings.MoveSpeed *= 4;
if (@event.IsActionReleased(GameInputs.Sprint))
Settings.MoveSpeed /= 4;
} }
private void OnEnemyHitBoxEntered(Area3D area) private void OnEnemyHitBoxEntered(Area3D area)

View File

@@ -7,13 +7,13 @@ namespace GameJamDungeon
public partial class PlayerStatInfo : Resource, ICharacterStats public partial class PlayerStatInfo : Resource, ICharacterStats
{ {
[Export] [Export]
public double CurrentHP { get => _currentHP.Value; set => _currentHP.OnNext(value); } public double CurrentHP { get => _currentHP.Value; set => _currentHP.OnNext(Mathf.Min(MaximumHP, value)); }
[Export] [Export]
public double MaximumHP { get => _maximumHP.Value; set => _maximumHP.OnNext(value); } public double MaximumHP { get => _maximumHP.Value; set => _maximumHP.OnNext(value); }
[Export] [Export]
public int CurrentVT { get => _currentVT.Value; set => _currentVT.OnNext(value); } public int CurrentVT { get => _currentVT.Value; set => _currentVT.OnNext(Mathf.Min(MaximumVT, value)); }
[Export] [Export]
public int MaximumVT { get => _maximumVT.Value; set => _maximumVT.OnNext(value); } public int MaximumVT { get => _maximumVT.Value; set => _maximumVT.OnNext(value); }
@@ -29,13 +29,13 @@ namespace GameJamDungeon
public int EXPToNextLevel { get => _expToNextLevel.Value; set => _expToNextLevel.OnNext(value); } public int EXPToNextLevel { get => _expToNextLevel.Value; set => _expToNextLevel.OnNext(value); }
[Export] [Export]
public int CurrentAttack { get => _currentAttack.Value; set => _currentAttack.OnNext(value); } public int CurrentAttack { get => _currentAttack.Value; set => _currentAttack.OnNext(Mathf.Min(MaxAttack, value)); }
[Export] [Export]
public int MaxAttack { get => _maxAttack.Value; set => _maxAttack.OnNext(value); } public int MaxAttack { get => _maxAttack.Value; set => _maxAttack.OnNext(value); }
[Export] [Export]
public int CurrentDefense { get => _currentDefense.Value; set => _currentDefense.OnNext(value); } public int CurrentDefense { get => _currentDefense.Value; set => _currentDefense.OnNext(Mathf.Min(CurrentDefense, value)); }
[Export] [Export]
public int MaxDefense { get => _maxDefense.Value; set => _maxDefense.OnNext(value); } public int MaxDefense { get => _maxDefense.Value; set => _maxDefense.OnNext(value); }
@@ -49,25 +49,25 @@ namespace GameJamDungeon
public double Luck { get => _luck.Value; set => _luck.OnNext(value); } public double Luck { get => _luck.Value; set => _luck.OnNext(value); }
// AutoProp backing data // AutoProp backing data
private readonly AutoProp<double> _currentHP = new AutoProp<double>(0); private readonly AutoProp<double> _currentHP = new AutoProp<double>(double.MaxValue);
private readonly AutoProp<double> _maximumHP = new AutoProp<double>(0); private readonly AutoProp<double> _maximumHP = new AutoProp<double>(double.MaxValue);
private readonly AutoProp<int> _currentVT = new AutoProp<int>(0); private readonly AutoProp<int> _currentVT = new AutoProp<int>(int.MaxValue);
private readonly AutoProp<int> _maximumVT = new AutoProp<int>(0); private readonly AutoProp<int> _maximumVT = new AutoProp<int>(int.MaxValue);
private readonly AutoProp<int> _currentExp = new AutoProp<int>(0); private readonly AutoProp<int> _currentExp = new AutoProp<int>(int.MaxValue);
private readonly AutoProp<int> _expToNextLevel = new AutoProp<int>(0); private readonly AutoProp<int> _expToNextLevel = new AutoProp<int>(int.MaxValue);
private readonly AutoProp<int> _currentLevel = new AutoProp<int>(0); private readonly AutoProp<int> _currentLevel = new AutoProp<int>(int.MaxValue);
private readonly AutoProp<int> _currentAttack = new AutoProp<int>(0); private readonly AutoProp<int> _currentAttack = new AutoProp<int>(int.MaxValue);
private readonly AutoProp<int> _currentDefense = new AutoProp<int>(0); private readonly AutoProp<int> _currentDefense = new AutoProp<int>(int.MaxValue);
private readonly AutoProp<int> _maxAttack = new AutoProp<int>(0); private readonly AutoProp<int> _maxAttack = new AutoProp<int>(int.MaxValue);
private readonly AutoProp<int> _maxDefense = new AutoProp<int>(0); private readonly AutoProp<int> _maxDefense = new AutoProp<int>(int.MaxValue);
private readonly AutoProp<int> _bonusAttack = new AutoProp<int>(0); private readonly AutoProp<int> _bonusAttack = new AutoProp<int>(int.MaxValue);
private readonly AutoProp<int> _bonusDefense = new AutoProp<int>(0); private readonly AutoProp<int> _bonusDefense = new AutoProp<int>(int.MaxValue);
private readonly AutoProp<double> _luck = new AutoProp<double>(0.0); private readonly AutoProp<double> _luck = new AutoProp<double>(double.MaxValue);
} }
} }

View File

@@ -2,8 +2,11 @@
{ {
public partial class PlayerLogic public partial class PlayerLogic
{ {
public record Settings( public record Settings
float RotationSpeed, {
float MoveSpeed); public float MoveSpeed { get; set; }
public float RotationSpeed { get; set; }
}
} }
} }

View File

@@ -23,12 +23,6 @@ namespace GameJamDungeon
transform.Basis = new Basis(Vector3.Up, settings.RotationSpeed * -rawInput.X) * transform.Basis; transform.Basis = new Basis(Vector3.Up, settings.RotationSpeed * -rawInput.X) * transform.Basis;
var velocity = player.Basis * new Vector3(strafeRightInput - strafeLeftInput, 0, rawInput.Z) * settings.MoveSpeed; var velocity = player.Basis * new Vector3(strafeRightInput - strafeLeftInput, 0, rawInput.Z) * settings.MoveSpeed;
if (Godot.Input.IsActionPressed(GameInputs.Sprint))
velocity *= 3;
if (Godot.Input.IsActionJustPressed(GameInputs.Throw))
Output(new Output.ThrowItem());
Output(new Output.MovementComputed(transform.Basis, velocity)); Output(new Output.MovementComputed(transform.Basis, velocity));
return ToSelf(); return ToSelf();