Compare commits

..

2 Commits

Author SHA1 Message Date
b9a1888bfc Add implementation for box item 2026-02-04 02:11:00 -08:00
52dc8fb9e4 Box item implementation 2026-02-04 01:49:17 -08:00
23 changed files with 422 additions and 202 deletions

View File

@@ -4,5 +4,21 @@ public enum ItemTag
{ {
None, None,
BreaksOnChange, BreaksOnChange,
MysteryItem MysteryItem,
} DamagesPlayer,
ContainsRestorative,
ContainsWeapon,
ContainsArmor,
ContainsBox,
RandomSpell,
ContainsAccessory,
DropTo1HPAndGainRareItem,
TradeOneRandomItem,
TradeAllRandomItems,
ContainsUnobtainedItem,
ContainsBasicItem,
RestrictUnequip,
UnequipAllItems,
EjectAllItems,
UseAllItems
}

View File

@@ -44,6 +44,8 @@ public interface IPlayer : IKillable, ICharacterBody3D
public void SetHealthTimerStatus(bool isActive); public void SetHealthTimerStatus(bool isActive);
public bool CanEquipState { get; set; }
public event Action PlayerDied; public event Action PlayerDied;
public delegate InventoryItem RerollItem(InventoryItem item); public delegate InventoryItem RerollItem(InventoryItem item);
} }

View File

@@ -69,7 +69,6 @@ public partial class Game : Node3D, IGame
public QuestData QuestData { get; private set; } public QuestData QuestData { get; private set; }
private EffectService _effectService; private EffectService _effectService;
private ItemReroller _itemReroller;
private IInstantiator _instantiator; private IInstantiator _instantiator;
private IPlayer _player; private IPlayer _player;
@@ -88,7 +87,6 @@ public partial class Game : Node3D, IGame
QuestData = new QuestData(); QuestData = new QuestData();
RescuedItems = new RescuedItemDatabase(); RescuedItems = new RescuedItemDatabase();
ItemDatabase = ItemDatabase.Instance; ItemDatabase = ItemDatabase.Instance;
_itemReroller = new ItemReroller(ItemDatabase);
GameChunk = new SaveChunk<GameData>( GameChunk = new SaveChunk<GameData>(
(chunk) => (chunk) =>
@@ -212,10 +210,13 @@ public partial class Game : Node3D, IGame
public async Task UseItem(InventoryItem item) public async Task UseItem(InventoryItem item)
{ {
if (item.ItemTag == ItemTag.MysteryItem) if (item.ItemTag == ItemTag.MysteryItem)
item = _itemReroller.RerollItem(item, _player.Inventory); _effectService.RerollItem(item);
switch (item) switch (item)
{ {
case BoxItem boxItem:
EnactBoxItemEffects(boxItem);
break;
case ConsumableItem consumableItem: case ConsumableItem consumableItem:
EnactConsumableItemEffects(consumableItem); EnactConsumableItemEffects(consumableItem);
break; break;
@@ -428,6 +429,16 @@ public partial class Game : Node3D, IGame
private void FinishedLoadingSaveFile() => EmitSignal(SignalName.SaveFileLoaded); private void FinishedLoadingSaveFile() => EmitSignal(SignalName.SaveFileLoaded);
private void EnactBoxItemEffects(BoxItem boxItem)
{
switch (boxItem.ItemTag)
{
case ItemTag.DamagesPlayer:
_effectService.DamagesPlayer(boxItem.Stats.DamageToPlayer);
break;
}
}
private void EnactConsumableItemEffects(ConsumableItem consumableItem) private void EnactConsumableItemEffects(ConsumableItem consumableItem)
{ {
if (_player.HealthComponent.AtFullHealth && consumableItem.RaiseHPAmount > 0) if (_player.HealthComponent.AtFullHealth && consumableItem.RaiseHPAmount > 0)
@@ -519,7 +530,7 @@ public partial class Game : Node3D, IGame
_effectService.ChangeAffinity(throwableItem); _effectService.ChangeAffinity(throwableItem);
break; break;
case ThrowableItemTag.WarpToExitIfFound: case ThrowableItemTag.WarpToExitIfFound:
_effectService.WarpToExit(_player); _effectService.WarpToExit();
GameRepo.CloseInventory(); GameRepo.CloseInventory();
break; break;
} }

View File

@@ -226,13 +226,90 @@ public class EffectService
throwableItem.SetCount(throwableItem.Count + 1); throwableItem.SetCount(throwableItem.Count + 1);
} }
public void WarpToExit(IPlayer player) public void WarpToExit()
{ {
var exitRoom = _game.CurrentFloor.Rooms.OfType<ExitRoom>().Single(); var exitRoom = _game.CurrentFloor.Rooms.OfType<ExitRoom>().Single();
if (exitRoom.PlayerDiscoveredRoom) if (exitRoom.PlayerDiscoveredRoom)
{ {
SfxDatabase.Instance.Play(SoundEffect.TeleportToExit); SfxDatabase.Instance.Play(SoundEffect.TeleportToExit);
player.TeleportPlayer((exitRoom.PlayerSpawn.Rotation, exitRoom.PlayerSpawn.Position)); _player.TeleportPlayer((exitRoom.PlayerSpawn.Rotation, exitRoom.PlayerSpawn.Position));
} }
} }
public void DamagesPlayer(int damage)
{
_player.TakeDamage(new AttackData(damage, ElementType.None, true, true));
}
public void RerollItem(InventoryItem itemToReroll)
{
var itemReroller = new ItemReroller(ItemDatabase.Instance);
itemReroller.RerollItem(itemToReroll, _player.Inventory);
}
public void GetRandomItemOfType<T>(T itemToExclude = null)
where T : InventoryItem
{
_player.Inventory.TryAdd(ItemDatabase.Instance.PickItem(itemToExclude));
}
public void RandomSpell()
{
throw new NotImplementedException("Spells not implemented yet.");
}
public void DropTo1HPAndGainRareItem<T>()
where T : InventoryItem
{
_player.HealthComponent.SetCurrentHealth(1);
_player.Inventory.TryAdd(ItemDatabase.Instance.PickRareItem<T>());
}
public void TradeRandomItem(BoxItem box)
{
if (_player.Inventory.Items.Count == 1)
return;
var tradableItems = _player.Inventory.Items.Where(x => x != box).ToList();
var rng = new RandomNumberGenerator();
rng.Randomize();
var randomIndex = rng.RandiRange(0, _player.Inventory.Items.Count - 1);
var randomItem = tradableItems[randomIndex];
if (randomItem is EquipableItem equipableItem)
{
if (_player.EquipmentComponent.IsItemEquipped(equipableItem))
_player.Unequip(equipableItem);
}
_player.Inventory.Remove(randomItem);
GetRandomItemOfType<InventoryItem>(box);
}
public void TradeAllRandomItems(BoxItem box)
{
var tradableItems = _player.Inventory.Items.Where(x => x != box);
foreach (var item in tradableItems)
TradeRandomItem(box);
}
public void GetUnobtainedItem()
{
var pickableItems = ItemDatabase.Instance.Items.Except(_player.Inventory.Items).ToList();
var rng = new RandomNumberGenerator();
rng.Randomize();
var randomIndex = rng.RandiRange(0, pickableItems.Count - 1);
var selectedItem = pickableItems[randomIndex];
if (selectedItem is ThrowableItem throwableItem)
throwableItem.SetCount(rng.RandiRange(throwableItem.Stats.MinimumCount, throwableItem.Stats.MaximumCount));
_player.Inventory.TryAdd(selectedItem);
}
public void GetBasicItem<T>()
where T : InventoryItem
{
_player.Inventory.TryAdd(ItemDatabase.Instance.PickBasicItem<T>());
}
} }

View File

@@ -18,12 +18,31 @@ public class ItemDatabase
public T PickItem<T>(T itemToExclude = null) public T PickItem<T>(T itemToExclude = null)
where T : InventoryItem where T : InventoryItem
{
var itemsToSelectFrom = Items;
return PickItemInternal(itemsToSelectFrom, itemToExclude);
}
public T PickRareItem<T>(T itemToExclude = null)
where T : InventoryItem
{
var getRareItems = Items.Where(x => x.SpawnRate < 0.1f);
return PickItemInternal(getRareItems, itemToExclude);
}
public T PickBasicItem<T>(T itemToExclude = null)
where T : InventoryItem
{
var getBasicItems = Items.Where(x => x.SpawnRate > 0.5f);
return PickItemInternal(getBasicItems, itemToExclude);
}
private T PickItemInternal<T>(IEnumerable<InventoryItem> itemsToSelectFrom, T itemToExclude = null)
where T : InventoryItem
{ {
var rng = new RandomNumberGenerator(); var rng = new RandomNumberGenerator();
rng.Randomize(); rng.Randomize();
var itemsToSelectFrom = Items;
if (itemToExclude is not null) if (itemToExclude is not null)
itemsToSelectFrom = [.. itemsToSelectFrom.OfType<T>().Where(x => x.ItemName != itemToExclude.ItemName)]; itemsToSelectFrom = [.. itemsToSelectFrom.OfType<T>().Where(x => x.ItemName != itemToExclude.ItemName)];

View File

@@ -27,6 +27,21 @@ public class ItemReroller
return rolledItem; return rolledItem;
} }
public InventoryItem RerollItemToAny(InventoryItem itemToReroll, IInventory inventory, bool insertIntoInventory = true)
{
var currentIndex = inventory.Items.IndexOf(itemToReroll);
if (insertIntoInventory)
inventory.Remove(itemToReroll);
var rolledItem = _database.PickItem(itemToReroll);
if (insertIntoInventory)
inventory.TryInsert(rolledItem, currentIndex);
return rolledItem;
}
private Weapon RerollItemInternal(Weapon itemToReroll) => _database.PickItem(itemToReroll); private Weapon RerollItemInternal(Weapon itemToReroll) => _database.PickItem(itemToReroll);
private Armor RerollItemInternal(Armor itemToReroll) => _database.PickItem(itemToReroll); private Armor RerollItemInternal(Armor itemToReroll) => _database.PickItem(itemToReroll);
private Accessory RerollItemInternal(Accessory itemToReroll) => _database.PickItem(itemToReroll); private Accessory RerollItemInternal(Accessory itemToReroll) => _database.PickItem(itemToReroll);

View File

@@ -0,0 +1,12 @@
using Chickensoft.Introspection;
using Godot;
namespace Zennysoft.Game.Ma;
[GlobalClass]
[Meta, Id("box_item_stat_type")]
public partial class BoxItemStats : InventoryItemStats
{
[Export]
public int DamageToPlayer { get; set; } = 10;
}

View File

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

View File

@@ -4,12 +4,12 @@ importer="scene"
importer_version=1 importer_version=1
type="PackedScene" type="PackedScene"
uid="uid://dkpgrhj14phdd" uid="uid://dkpgrhj14phdd"
path="res://.godot/imported/plastique.glb-38f4438846eaa3d64b225272714c5d02.scn" path="res://.godot/imported/plastique.glb-5845ad959844e1ca0c9791ff0287bc66.scn"
[deps] [deps]
source_file="res://src/items/assetts/plastique.glb" source_file="res://src/items/assets/plastique.glb"
dest_files=["res://.godot/imported/plastique.glb-38f4438846eaa3d64b225272714c5d02.scn"] dest_files=["res://.godot/imported/plastique.glb-5845ad959844e1ca0c9791ff0287bc66.scn"]
[params] [params]

View File

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@@ -3,7 +3,7 @@
importer="texture" importer="texture"
type="CompressedTexture2D" type="CompressedTexture2D"
uid="uid://dkqs4x4pi18on" uid="uid://dkqs4x4pi18on"
path="res://.godot/imported/plastique_plastique.png-3ad121f0468f0ec1d61934d8a0e41cb7.ctex" path="res://.godot/imported/plastique_plastique.png-06bcea5737da44088a0bd794735523f0.ctex"
metadata={ metadata={
"vram_texture": false "vram_texture": false
} }
@@ -13,8 +13,8 @@ generator_parameters={
[deps] [deps]
source_file="res://src/items/assetts/plastique_plastique.png" source_file="res://src/items/assets/plastique_plastique.png"
dest_files=["res://.godot/imported/plastique_plastique.png-3ad121f0468f0ec1d61934d8a0e41cb7.ctex"] dest_files=["res://.godot/imported/plastique_plastique.png-06bcea5737da44088a0bd794735523f0.ctex"]
[params] [params]

View File

@@ -0,0 +1,37 @@
using Chickensoft.AutoInject;
using Chickensoft.Introspection;
using Chickensoft.Serialization;
using Godot;
using Zennysoft.Game.Ma;
using Zennysoft.Ma.Adapter;
[Meta(typeof(IAutoNode)), Id("box_item")]
public partial class BoxItem : InventoryItem
{
public override void _Notification(int what) => this.Notify(what);
[Node] private Sprite3D _sprite { get; set; }
[Export]
[Save("box_stats")]
public BoxItemStats Stats { get; set; } = new BoxItemStats();
public override string ItemName => Stats.Name;
public override string Description => Stats.Description;
public override float SpawnRate => Stats.SpawnRate;
public override int ThrowDamage => Stats.ThrowDamage;
public override float ThrowSpeed => Stats.ThrowSpeed;
public override ItemTag ItemTag => Stats.ItemTag;
public override Texture2D GetTexture() => Stats.Texture;
public void OnReady()
{
_sprite.Texture = Stats.Texture;
}
}

View File

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

View File

@@ -1,6 +1,6 @@
[gd_scene load_steps=5 format=3 uid="uid://bguomljidwgto"] [gd_scene load_steps=5 format=3 uid="uid://bguomljidwgto"]
[ext_resource type="Script" path="res://src/items/box/BoxItem.cs" id="1_holk0"] [ext_resource type="Script" uid="uid://cqqqj4hgywst4" path="res://src/items/box/BoxItem.cs" id="1_holk0"]
[ext_resource type="Texture2D" uid="uid://bg47n2tmintm0" path="res://src/items/consumable/textures/past self remnant.PNG" id="2_holk0"] [ext_resource type="Texture2D" uid="uid://bg47n2tmintm0" path="res://src/items/consumable/textures/past self remnant.PNG" id="2_holk0"]
[sub_resource type="CylinderShape3D" id="CylinderShape3D_x6u08"] [sub_resource type="CylinderShape3D" id="CylinderShape3D_x6u08"]
@@ -17,7 +17,6 @@ axis_lock_angular_x = true
axis_lock_angular_y = true axis_lock_angular_y = true
axis_lock_angular_z = true axis_lock_angular_z = true
script = ExtResource("1_holk0") script = ExtResource("1_holk0")
Stats = null
[node name="CollisionShape3D" type="CollisionShape3D" parent="."] [node name="CollisionShape3D" type="CollisionShape3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.00908482, 0) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.00908482, 0)

View File

@@ -0,0 +1,25 @@
[gd_resource type="Resource" script_class="BoxItemStats" load_steps=3 format=3 uid="uid://cgkorwblwr12t"]
[ext_resource type="Texture2D" uid="uid://bg47n2tmintm0" path="res://src/items/consumable/textures/past self remnant.PNG" id="1_650jj"]
[ext_resource type="Script" uid="uid://vuavr681au06" path="res://src/items/accessory/BoxItemStats.cs" id="1_i336w"]
[resource]
script = ExtResource("1_i336w")
Name = "Empty Promise"
Description = "An empty box."
SpawnRate = 0.5
BonusAttack = 0
BonusDefense = 0
BonusLuck = 0.05
BonusHP = 0
BonusVT = 0
AeolicResistance = 0
TelluricResistance = 0
HydricResistance = 0
IgneousResistance = 0
FerrumResistance = 0
ThrowSpeed = 12.0
ThrowDamage = 5
ItemTag = 0
Texture = ExtResource("1_650jj")
metadata/_custom_type_script = "uid://vuavr681au06"

View File

@@ -2,7 +2,7 @@
[ext_resource type="Script" uid="uid://da8mhruqpgh6r" path="res://src/items/misc/SetItem.cs" id="1_m8dyi"] [ext_resource type="Script" uid="uid://da8mhruqpgh6r" path="res://src/items/misc/SetItem.cs" id="1_m8dyi"]
[ext_resource type="AudioStream" uid="uid://bjcersd5id8ee" path="res://src/audio/sfx/ITEM_PLASTIQUETIMER.ogg" id="2_kgxna"] [ext_resource type="AudioStream" uid="uid://bjcersd5id8ee" path="res://src/audio/sfx/ITEM_PLASTIQUETIMER.ogg" id="2_kgxna"]
[ext_resource type="Texture2D" uid="uid://dkqs4x4pi18on" path="res://src/items/assetts/plastique_plastique.png" id="2_m8dyi"] [ext_resource type="Texture2D" uid="uid://dkqs4x4pi18on" path="res://src/items/assets/plastique_plastique.png" id="2_m8dyi"]
[sub_resource type="Animation" id="Animation_eat5q"] [sub_resource type="Animation" id="Animation_eat5q"]
length = 0.001 length = 0.001

View File

@@ -1,9 +1,7 @@
using Chickensoft.AutoInject; using Chickensoft.AutoInject;
using Chickensoft.GodotNodeInterfaces;
using Chickensoft.Introspection; using Chickensoft.Introspection;
using Chickensoft.Serialization; using Chickensoft.Serialization;
using Godot; using Godot;
using System;
using Zennysoft.Ma.Adapter; using Zennysoft.Ma.Adapter;
using Zennysoft.Ma.Adapter.Entity; using Zennysoft.Ma.Adapter.Entity;

View File

@@ -1,8 +1,9 @@
[gd_scene load_steps=18 format=3 uid="uid://dl6h1djc27ddl"] [gd_scene load_steps=19 format=3 uid="uid://dl6h1djc27ddl"]
[ext_resource type="Script" uid="uid://c1nhqlem1ew3m" path="res://src/map/dungeon/code/Altar.cs" id="1_5jip8"] [ext_resource type="Script" uid="uid://c1nhqlem1ew3m" path="res://src/map/dungeon/code/Altar.cs" id="1_5jip8"]
[ext_resource type="Resource" uid="uid://bqnfw6r4085yv" path="res://src/dialog/Altar.dialogue" id="2_7xfp0"] [ext_resource type="Resource" uid="uid://bqnfw6r4085yv" path="res://src/dialog/Altar.dialogue" id="2_7xfp0"]
[ext_resource type="PackedScene" uid="uid://co0fmuno2pjc7" path="res://src/map/dungeon/models/Special Floors & Rooms/Altar/02_ALTAR_FLOOR_ZER0_VER.1.glb" id="2_xpi6o"] [ext_resource type="PackedScene" uid="uid://co0fmuno2pjc7" path="res://src/map/dungeon/models/Special Floors & Rooms/Altar/02_ALTAR_FLOOR_ZER0_VER.1.glb" id="2_xpi6o"]
[ext_resource type="PackedScene" uid="uid://bdygmhgk4k0qh" path="res://src/items/box/BoxItem.tscn" id="6_rrmfo"]
[ext_resource type="Shader" uid="uid://c4a68uhm5o2h4" path="res://src/map/map shaders/Altar Sky Environment.gdshader" id="27_lb4gb"] [ext_resource type="Shader" uid="uid://c4a68uhm5o2h4" path="res://src/map/map shaders/Altar Sky Environment.gdshader" id="27_lb4gb"]
[ext_resource type="AudioStream" uid="uid://c4ud110da8efp" path="res://src/audio/AMB/amb_wind_loop_altar.wav" id="28_je2oh"] [ext_resource type="AudioStream" uid="uid://c4ud110da8efp" path="res://src/audio/AMB/amb_wind_loop_altar.wav" id="28_je2oh"]
@@ -212,3 +213,5 @@ collision_mask = 64
[node name="CollisionShape3D" type="CollisionShape3D" parent="NoExitArea"] [node name="CollisionShape3D" type="CollisionShape3D" parent="NoExitArea"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 72.5243, -2.06593, -2.02953) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 72.5243, -2.06593, -2.02953)
shape = SubResource("BoxShape3D_tp2pi") shape = SubResource("BoxShape3D_tp2pi")
[node name="Box Item" parent="." instance=ExtResource("6_rrmfo")]

View File

@@ -94,6 +94,7 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<IPlayer>
#endregion #endregion
public bool CanEquipState { get; set; } = true;
private bool flipAttack = false; private bool flipAttack = false;

View File

@@ -411,7 +411,7 @@ tracks/0/loop_wrap = true
tracks/0/keys = { tracks/0/keys = {
"times": PackedFloat32Array(0), "times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1), "transitions": PackedFloat32Array(1),
"update": 0, "update": 1,
"values": [&"default"] "values": [&"default"]
} }
tracks/1/type = "value" tracks/1/type = "value"

View File

@@ -62,144 +62,144 @@ public partial class InventoryMenu : Control, IInventoryMenu
public override void _EnterTree() public override void _EnterTree()
{ {
SetProcessInput(false); SetProcessInput(false);
SetProcessUnhandledInput(false);
} }
public void OnResolved() public void OnResolved()
{ {
ItemSlots = [ItemSlot1, ItemSlot2, ItemSlot3, ItemSlot4, ItemSlot5, ItemSlot6, ItemSlot7, ItemSlot8, ItemSlot9, ItemSlot10, ItemSlot11, ItemSlot12, ItemSlot13, ItemSlot14, ItemSlot15, ItemSlot16, ItemSlot17, ItemSlot18, ItemSlot19, ItemSlot20]; ItemSlots = [ItemSlot1, ItemSlot2, ItemSlot3, ItemSlot4, ItemSlot5, ItemSlot6, ItemSlot7, ItemSlot8, ItemSlot9, ItemSlot10, ItemSlot11, ItemSlot12, ItemSlot13, ItemSlot14, ItemSlot15, ItemSlot16, ItemSlot17, ItemSlot18, ItemSlot19, ItemSlot20];
_currentlySelectedItem = ItemSlot1; _currentlySelectedItem = ItemSlot1;
foreach (var item in ItemSlots) foreach (var item in ItemSlots)
{ {
item.ItemPressed += Item_Pressed; item.ItemPressed += Item_Pressed;
item.ItemEnterFocus += Item_FocusEntered; item.ItemEnterFocus += Item_FocusEntered;
item.ItemExitFocus += Item_ItemExitFocus; item.ItemExitFocus += Item_ItemExitFocus;
} }
_player.AttackComponent.CurrentAttack.Sync += Attack_Sync; _player.AttackComponent.CurrentAttack.Sync += Attack_Sync;
_player.AttackComponent.MaximumAttack.Sync += Attack_Sync; _player.AttackComponent.MaximumAttack.Sync += Attack_Sync;
_player.DefenseComponent.CurrentDefense.Sync += Defense_Sync; _player.DefenseComponent.CurrentDefense.Sync += Defense_Sync;
_player.DefenseComponent.MaximumDefense.Sync += Defense_Sync; _player.DefenseComponent.MaximumDefense.Sync += Defense_Sync;
_player.EquipmentComponent.EquipmentChanged += EquipmentComponent_EquipmentChanged; _player.EquipmentComponent.EquipmentChanged += EquipmentComponent_EquipmentChanged;
_player.Inventory.InventoryChanged += Inventory_InventoryChanged; _player.Inventory.InventoryChanged += Inventory_InventoryChanged;
UseButton.Pressed += UseButtonPressed; UseButton.Pressed += UseButtonPressed;
ThrowButton.Pressed += ThrowButtonPressed; ThrowButton.Pressed += ThrowButtonPressed;
DropButton.Pressed += DropButtonPressed; DropButton.Pressed += DropButtonPressed;
UseButton.FocusEntered += ActionButtonFocusChanged; UseButton.FocusEntered += ActionButtonFocusChanged;
ThrowButton.FocusEntered += ActionButtonFocusChanged; ThrowButton.FocusEntered += ActionButtonFocusChanged;
DropButton.FocusEntered += ActionButtonFocusChanged; DropButton.FocusEntered += ActionButtonFocusChanged;
VisibilityChanged += InventoryMenu_VisibilityChanged; VisibilityChanged += InventoryMenu_VisibilityChanged;
} }
private void ActionButtonFocusChanged() private void ActionButtonFocusChanged()
{ {
if (!_enableMenuSound) if (!_enableMenuSound)
SfxDatabase.Instance.Play(SoundEffect.MoveUI); SfxDatabase.Instance.Play(SoundEffect.MoveUI);
} }
public override void _UnhandledInput(InputEvent @event) public override void _UnhandledInput(InputEvent @event)
{ {
if (!Visible) if ((!Input.IsActionJustPressed(GameInputs.UiUp) && Input.IsActionPressed(GameInputs.UiUp)) || (!Input.IsActionJustPressed(GameInputs.UiDown) && Input.IsActionPressed(GameInputs.UiDown)))
return; AcceptEvent();
if ((!Input.IsActionJustPressed(GameInputs.UiUp) && Input.IsActionPressed(GameInputs.UiUp)) || (!Input.IsActionJustPressed(GameInputs.UiDown) && Input.IsActionPressed(GameInputs.UiDown))) if (Input.IsActionJustPressed(GameInputs.UiCancel) && (UseItemPrompt.Visible))
AcceptEvent(); {
SfxDatabase.Instance.Play(SoundEffect.CancelUI);
AcceptEvent();
HideUserActionPrompt();
}
else if (Input.IsActionJustPressed(GameInputs.UiCancel))
{
SfxDatabase.Instance.Play(SoundEffect.CancelUI);
AcceptEvent();
_gameRepo.CloseInventory();
}
if (Input.IsActionJustPressed(GameInputs.UiCancel) && (UseButton.HasFocus() || DropButton.HasFocus() || ThrowButton.HasFocus())) if (Input.IsActionJustPressed(GameInputs.InventorySort))
{ {
SfxDatabase.Instance.Play(SoundEffect.CancelUI); var isChanged = _player.Inventory.Sort(_player.EquipmentComponent.EquippedWeapon.Value, _player.EquipmentComponent.EquippedArmor.Value, _player.EquipmentComponent.EquippedAccessory.Value);
AcceptEvent(); if (!isChanged)
HideUserActionPrompt(); return;
}
else if (Input.IsActionJustPressed(GameInputs.UiCancel))
{
SfxDatabase.Instance.Play(SoundEffect.CancelUI);
AcceptEvent();
_gameRepo.CloseInventory();
}
if (Input.IsActionJustPressed(GameInputs.InventorySort)) SfxDatabase.Instance.Play(SoundEffect.SortInventory);
{ Inventory_InventoryChanged();
var isChanged = _player.Inventory.Sort(_player.EquipmentComponent.EquippedWeapon.Value, _player.EquipmentComponent.EquippedArmor.Value, _player.EquipmentComponent.EquippedAccessory.Value); foreach (var slot in ItemSlots)
if (!isChanged) slot.SetItemStyle();
return; Item_ItemExitFocus(_currentlySelectedItem);
_currentlySelectedItem = ItemSlot1;
SfxDatabase.Instance.Play(SoundEffect.SortInventory); _currentlySelectedItem.GrabFocus();
Inventory_InventoryChanged(); }
foreach (var slot in ItemSlots)
slot.SetItemStyle();
Item_ItemExitFocus(_currentlySelectedItem);
_currentlySelectedItem = ItemSlot1;
_currentlySelectedItem.GrabFocus();
}
} }
private void InventoryMenu_VisibilityChanged() private void InventoryMenu_VisibilityChanged()
{ {
if (Visible) if (Visible)
{ {
SfxDatabase.Instance.Play(SoundEffect.OpenInventory); SetProcessUnhandledInput(true);
_currentlySelectedItem.GrabFocus(); SfxDatabase.Instance.Play(SoundEffect.OpenInventory);
_enableMenuSound = true; _currentlySelectedItem.GrabFocus();
} _enableMenuSound = true;
else }
{ else
SfxDatabase.Instance.Play(SoundEffect.CancelUI); {
_enableMenuSound = false; SetProcessUnhandledInput(false);
} SfxDatabase.Instance.Play(SoundEffect.CancelUI);
_enableMenuSound = false;
}
} }
private void Item_ItemExitFocus(IItemSlot itemSlot) private void Item_ItemExitFocus(IItemSlot itemSlot)
{ {
ItemDescriptionTitle.Text = string.Empty; ItemDescriptionTitle.Text = string.Empty;
ItemEffectLabel.Text = string.Empty; ItemEffectLabel.Text = string.Empty;
itemSlot.IsSelected = false; itemSlot.IsSelected = false;
itemSlot.SetItemStyle(); itemSlot.SetItemStyle();
} }
private void Item_FocusEntered(IItemSlot itemSlot) private void Item_FocusEntered(IItemSlot itemSlot)
{ {
if (itemSlot.Item.Value == null) if (itemSlot.Item.Value == null)
return; return;
if (_enableMenuSound) if (_enableMenuSound)
SfxDatabase.Instance.Play(SoundEffect.MoveUI); SfxDatabase.Instance.Play(SoundEffect.MoveUI);
ItemDescriptionTitle.Text = $"{itemSlot.Item.Value.ItemName}"; ItemDescriptionTitle.Text = $"{itemSlot.Item.Value.ItemName}";
ItemEffectLabel.Text = $"{itemSlot.Item.Value.Description}"; ItemEffectLabel.Text = $"{itemSlot.Item.Value.Description}";
_currentlySelectedItem = itemSlot; _currentlySelectedItem = itemSlot;
itemSlot.IsSelected = true; itemSlot.IsSelected = true;
itemSlot.SetItemStyle(); itemSlot.SetItemStyle();
AcceptEvent(); AcceptEvent();
} }
private void Item_Pressed(InventoryItem item) => DisplayUserActionPrompt(item); private void Item_Pressed(InventoryItem item) => DisplayUserActionPrompt(item);
private async void Inventory_InventoryChanged() private async void Inventory_InventoryChanged()
{ {
foreach (var slot in ItemSlots) foreach (var slot in ItemSlots)
{ {
slot.Visible = false; slot.Visible = false;
slot.SetItemStyle(); slot.SetItemStyle();
} }
var itemsToDisplay = _player.Inventory.Items; var itemsToDisplay = _player.Inventory.Items;
for (var i = 0; i < itemsToDisplay.Count; i++) for (var i = 0; i < itemsToDisplay.Count; i++)
{ {
ItemSlots[i].Item.OnNext(itemsToDisplay[i]); ItemSlots[i].Item.OnNext(itemsToDisplay[i]);
ItemSlots[i].Visible = true; ItemSlots[i].Visible = true;
} }
if (!_player.Inventory.Items.Contains(_currentlySelectedItem.Item.Value)) if (!_player.Inventory.Items.Contains(_currentlySelectedItem.Item.Value))
{ {
_currentlySelectedItem.Item.OnNext(null); _currentlySelectedItem.Item.OnNext(null);
var elementToSelect = Mathf.Max(0, ItemSlots.IndexOf(_currentlySelectedItem) - 1); var elementToSelect = Mathf.Max(0, ItemSlots.IndexOf(_currentlySelectedItem) - 1);
_currentlySelectedItem = ItemSlots.ElementAt(elementToSelect); _currentlySelectedItem = ItemSlots.ElementAt(elementToSelect);
_currentlySelectedItem.GrabFocus(); _currentlySelectedItem.GrabFocus();
} }
} }
private void Attack_Sync(int obj) => ATKValue.Text = $"{_player.AttackComponent.CurrentAttack.Value}/{_player.AttackComponent.MaximumAttack.Value}"; private void Attack_Sync(int obj) => ATKValue.Text = $"{_player.AttackComponent.CurrentAttack.Value}/{_player.AttackComponent.MaximumAttack.Value}";
@@ -207,125 +207,128 @@ public partial class InventoryMenu : Control, IInventoryMenu
private void EquipmentComponent_EquipmentChanged(EquipableItem equipableItem) private void EquipmentComponent_EquipmentChanged(EquipableItem equipableItem)
{ {
ATKBonusLabel.Text = $"{_player.EquipmentComponent.BonusAttack:+0;-#;\\.\\.\\.}"; ATKBonusLabel.Text = $"{_player.EquipmentComponent.BonusAttack:+0;-#;\\.\\.\\.}";
DEFBonusLabel.Text = $"{_player.EquipmentComponent.BonusDefense:+0;-#;\\.\\.\\.}"; DEFBonusLabel.Text = $"{_player.EquipmentComponent.BonusDefense:+0;-#;\\.\\.\\.}";
} }
private async void UseButtonPressed() private async void UseButtonPressed()
{ {
UseButton.Disabled = true; UseButton.Disabled = true;
if (_currentlySelectedItem.Item.Value is EquipableItem equipable) if (_currentlySelectedItem.Item.Value is EquipableItem equipable)
await EquipOrUnequipItem(equipable); await EquipOrUnequipItem(equipable);
else if (_currentlySelectedItem.Item.Value is Plastique plastique) else if (_currentlySelectedItem.Item.Value is Plastique plastique)
SetItem(); SetItem();
else else
await _game.UseItem(_currentlySelectedItem.Item.Value); await _game.UseItem(_currentlySelectedItem.Item.Value);
UseButton.Disabled = false; UseButton.Disabled = false;
HideUserActionPrompt(); HideUserActionPrompt();
await ShowInventoryInfo(); await ShowInventoryInfo();
await ToSignal(GetTree().CreateTimer(1f), "timeout"); await ToSignal(GetTree().CreateTimer(1f), "timeout");
} }
private async void SetItem() private async void SetItem()
{ {
_game.SetItem(_currentlySelectedItem.Item.Value); _game.SetItem(_currentlySelectedItem.Item.Value);
_player.Inventory.Remove(_currentlySelectedItem.Item.Value); _player.Inventory.Remove(_currentlySelectedItem.Item.Value);
HideUserActionPrompt(); HideUserActionPrompt();
await ShowInventoryInfo(); await ShowInventoryInfo();
_gameRepo.CloseInventory(); _gameRepo.CloseInventory();
} }
private async void ThrowButtonPressed() private async void ThrowButtonPressed()
{ {
_game.ThrowItem(_currentlySelectedItem.Item.Value); _game.ThrowItem(_currentlySelectedItem.Item.Value);
_player.Inventory.Remove(_currentlySelectedItem.Item.Value); _player.Inventory.Remove(_currentlySelectedItem.Item.Value);
HideUserActionPrompt(); HideUserActionPrompt();
await ShowInventoryInfo(); await ShowInventoryInfo();
_gameRepo.CloseInventory(); _gameRepo.CloseInventory();
} }
private async void DropButtonPressed() private async void DropButtonPressed()
{ {
_game.DropItem(_currentlySelectedItem.Item.Value); _game.DropItem(_currentlySelectedItem.Item.Value);
_player.Inventory.Remove(_currentlySelectedItem.Item.Value); _player.Inventory.Remove(_currentlySelectedItem.Item.Value);
HideUserActionPrompt(); HideUserActionPrompt();
await ShowInventoryInfo(); await ShowInventoryInfo();
} }
private void DisplayUserActionPrompt(InventoryItem item) private void DisplayUserActionPrompt(InventoryItem item)
{ {
SfxDatabase.Instance.Play(SoundEffect.SelectUI); SfxDatabase.Instance.Play(SoundEffect.SelectUI);
ItemDescriptionTitle.Hide(); ItemDescriptionTitle.Hide();
ItemEffectLabel.Hide(); ItemEffectLabel.Hide();
UseItemPrompt.Show(); UseItemPrompt.Show();
UseButton.Show(); UseButton.Show();
ThrowButton.Show(); ThrowButton.Show();
DropButton.Show(); DropButton.Show();
if (item is EquipableItem equipable) if (item is EquipableItem equipable)
{ {
var isItemEquipped = _player.EquipmentComponent.IsItemEquipped(equipable); var isItemEquipped = _player.EquipmentComponent.IsItemEquipped(equipable);
UseButton.Text = isItemEquipped ? "Unequip" : "Equip"; UseButton.Text = isItemEquipped ? "Unequip" : "Equip";
ThrowButton.Disabled = isItemEquipped; ThrowButton.Disabled = isItemEquipped;
ThrowButton.FocusMode = isItemEquipped ? FocusModeEnum.None : FocusModeEnum.All; ThrowButton.FocusMode = isItemEquipped ? FocusModeEnum.None : FocusModeEnum.All;
DropButton.Disabled = isItemEquipped; DropButton.Disabled = isItemEquipped;
DropButton.FocusMode = isItemEquipped ? FocusModeEnum.None : FocusModeEnum.All; DropButton.FocusMode = isItemEquipped ? FocusModeEnum.None : FocusModeEnum.All;
}
else if (item is Plastique plastique)
{
UseButton.Text = "Set";
}
else
{
UseButton.Text = "Use";
}
UseButton.GrabFocus(); UseButton.GrabFocus();
_enableMenuSound = false;
if (!_player.CanEquipState && isItemEquipped)
UseButton.Disabled = true;
}
else if (item is Plastique plastique)
{
UseButton.Text = "Set";
}
else
{
UseButton.Text = "Use";
}
_enableMenuSound = false;
} }
private void HideUserActionPrompt() private void HideUserActionPrompt()
{ {
UseItemPrompt.Hide(); UseItemPrompt.Hide();
UseButton.Hide(); UseButton.Hide();
ThrowButton.Hide(); ThrowButton.Hide();
DropButton.Hide(); DropButton.Hide();
UseButton.ReleaseFocus(); UseButton.ReleaseFocus();
ThrowButton.ReleaseFocus(); ThrowButton.ReleaseFocus();
DropButton.ReleaseFocus(); DropButton.ReleaseFocus();
_currentlySelectedItem.GrabFocus(); _currentlySelectedItem.GrabFocus();
_enableMenuSound = true; _enableMenuSound = true;
} }
private async Task EquipOrUnequipItem(EquipableItem equipable) private async Task EquipOrUnequipItem(EquipableItem equipable)
{ {
if (_player.EquipmentComponent.IsItemEquipped(equipable)) if (_player.EquipmentComponent.IsItemEquipped(equipable))
{ {
SfxDatabase.Instance.Play(SoundEffect.Unequip); SfxDatabase.Instance.Play(SoundEffect.Unequip);
ItemEffectLabel.Text = $"{equipable.GetType().Name} unequipped."; ItemEffectLabel.Text = $"{equipable.GetType().Name} unequipped.";
_player.Unequip(equipable); _player.Unequip(equipable);
} }
else else
{ {
SfxDatabase.Instance.Play(SoundEffect.Equip); SfxDatabase.Instance.Play(SoundEffect.Equip);
var itemSlot = _currentlySelectedItem; var itemSlot = _currentlySelectedItem;
ItemEffectLabel.Text = $"{equipable.GetType().Name} equipped."; ItemEffectLabel.Text = $"{equipable.GetType().Name} equipped.";
_player.Equip(equipable); _player.Equip(equipable);
_currentlySelectedItem = itemSlot; _currentlySelectedItem = itemSlot;
} }
} }
private async Task ShowInventoryInfo() private async Task ShowInventoryInfo()
{ {
ItemDescriptionTitle.Show(); ItemDescriptionTitle.Show();
ItemEffectLabel.Show(); ItemEffectLabel.Show();
} }
private enum InventoryPageNumber private enum InventoryPageNumber
{ {
FirstPage, FirstPage,
SecondPage SecondPage
} }
} }

View File

@@ -101,7 +101,7 @@ public partial class PauseDebugMenu : Control, IDebugMenu
{ {
var enemyToSpawn = _spawnableEnemies.ElementAt((int)index); var enemyToSpawn = _spawnableEnemies.ElementAt((int)index);
var loadedEnemy = GD.Load<PackedScene>(enemyToSpawn).Instantiate<Enemy>(); var loadedEnemy = GD.Load<PackedScene>(enemyToSpawn).Instantiate<Enemy>();
AddChild(loadedEnemy); _game.AddChild(loadedEnemy);
loadedEnemy.GlobalPosition = new Vector3(_player.GlobalPosition.X, _player.GlobalPosition.Y + 1, _player.GlobalPosition.Z) + (-_player.GlobalBasis.Z * 2); loadedEnemy.GlobalPosition = new Vector3(_player.GlobalPosition.X, _player.GlobalPosition.Y + 1, _player.GlobalPosition.Z) + (-_player.GlobalBasis.Z * 2);
} }
@@ -109,7 +109,7 @@ public partial class PauseDebugMenu : Control, IDebugMenu
{ {
var itemToSpawn = _spawnableItems.ElementAt((int)index); var itemToSpawn = _spawnableItems.ElementAt((int)index);
var duplicated = itemToSpawn.Duplicate((int)DuplicateFlags.UseInstantiation) as Node3D; var duplicated = itemToSpawn.Duplicate((int)DuplicateFlags.UseInstantiation) as Node3D;
AddChild(duplicated); _game.AddChild(duplicated);
duplicated.GlobalPosition = new Vector3(_player.GlobalPosition.X, _player.GlobalPosition.Y + 1, _player.GlobalPosition.Z) + (-_player.GlobalBasis.Z * 2); duplicated.GlobalPosition = new Vector3(_player.GlobalPosition.X, _player.GlobalPosition.Y + 1, _player.GlobalPosition.Z) + (-_player.GlobalBasis.Z * 2);
} }