summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatheus <matheus.guedes.mg.m@gmail.com>2025-10-24 21:25:15 -0300
committerMatheus <matheus.guedes.mg.m@gmail.com>2025-10-24 21:25:15 -0300
commit639cd8cef403e9e66bf31e7888e786effac2b292 (patch)
treea1b3872a91ad599a71629d0d62c72125138c5c14
parent52c32a24044aa574c9e7bf7aa4e2499349cc36b2 (diff)
refactor: Sistema de itens reescrito
Em tese, este novo sistema é mais fácil de serializar. Descanse em paz pergaminhos, eu não quero reimplementá-los neste novo sistema.
-rw-r--r--assets/definitions/Items/mana_bolt_grimoire.tres25
-rw-r--r--assets/definitions/Items/mana_bolt_scroll.tres14
-rw-r--r--assets/definitions/Items/small_healing_potion.tres29
-rw-r--r--projeto-fantasia.csproj2
-rw-r--r--projeto-fantasia.csproj.old.17
-rw-r--r--scripts/Entities/Actions/DropAction.cs2
-rw-r--r--scripts/Entities/Actions/ItemAction.cs4
-rw-r--r--scripts/Entities/Actions/PickUpAction.cs6
-rw-r--r--scripts/Entities/Actors/Inventory.cs21
-rw-r--r--scripts/Entities/Entity.cs14
-rw-r--r--scripts/Entities/Items/ConsumableItem.cs.uid1
-rw-r--r--scripts/Entities/Items/ConsumableItemDefinition.cs9
-rw-r--r--scripts/Entities/Items/ConsumableItemDefinition.cs.uid1
-rw-r--r--scripts/Entities/Items/GrimoireConsumable.cs22
-rw-r--r--scripts/Entities/Items/GrimoireConsumable.cs.uid1
-rw-r--r--scripts/Entities/Items/GrimoireConsumableDefinition.cs11
-rw-r--r--scripts/Entities/Items/GrimoireConsumableDefinition.cs.uid1
-rw-r--r--scripts/Entities/Items/GrimoireItemActivation.cs19
-rw-r--r--scripts/Entities/Items/GrimoireItemActivation.cs.uid1
-rw-r--r--scripts/Entities/Items/HealingConsumable.cs30
-rw-r--r--scripts/Entities/Items/HealingConsumable.cs.uid1
-rw-r--r--scripts/Entities/Items/HealingConsumableDefinition.cs14
-rw-r--r--scripts/Entities/Items/HealingConsumableDefinition.cs.uid1
-rw-r--r--scripts/Entities/Items/Item.cs (renamed from scripts/Entities/Items/ConsumableItem.cs)37
-rw-r--r--scripts/Entities/Items/Item.cs.uid1
-rw-r--r--scripts/Entities/Items/ItemActivation.cs13
-rw-r--r--scripts/Entities/Items/ItemActivation.cs.uid1
-rw-r--r--scripts/Entities/Items/ItemEntity.cs25
-rw-r--r--scripts/Entities/Items/ItemEntity.cs.uid1
-rw-r--r--scripts/Entities/Items/ItemResource.cs22
-rw-r--r--scripts/Entities/Items/ItemResource.cs.uid1
-rw-r--r--scripts/Entities/Items/ScrollConsumable.cs125
-rw-r--r--scripts/Entities/Items/ScrollConsumable.cs.uid1
-rw-r--r--scripts/Entities/Items/ScrollConsumableDefinition.cs11
-rw-r--r--scripts/Entities/Items/ScrollConsumableDefinition.cs.uid1
-rw-r--r--scripts/Entities/Items/SpellEffectItemActivation.cs19
-rw-r--r--scripts/Entities/Items/SpellEffectItemActivation.cs.uid1
-rw-r--r--scripts/GUI/InventoryMenu.cs10
-rw-r--r--scripts/GUI/ItemMenuEntry.cs12
-rw-r--r--scripts/InputHandling/InventoryInputHandler.cs8
-rw-r--r--scripts/Magic/HealEffect.cs20
-rw-r--r--scripts/Magic/HealEffect.cs.uid1
-rw-r--r--scripts/Map/DungeonGenerator.cs28
-rw-r--r--scripts/Map/MapData.cs10
44 files changed, 256 insertions, 328 deletions
diff --git a/assets/definitions/Items/mana_bolt_grimoire.tres b/assets/definitions/Items/mana_bolt_grimoire.tres
index b134ea1..95918d5 100644
--- a/assets/definitions/Items/mana_bolt_grimoire.tres
+++ b/assets/definitions/Items/mana_bolt_grimoire.tres
@@ -1,14 +1,19 @@
-[gd_resource type="Resource" script_class="GrimoireConsumableDefinition" load_steps=4 format=3 uid="uid://coeyeuyren2vi"]
+[gd_resource type="Resource" script_class="ItemResource" load_steps=6 format=3 uid="uid://bpg2rb62r7aev"]
-[ext_resource type="Resource" uid="uid://boi8svlb0e8l" path="res://assets/definitions/spells/mana_bolt.tres" id="1_dnjm5"]
-[ext_resource type="Script" uid="uid://blkth0in1fp74" path="res://scripts/Entities/Items/GrimoireConsumableDefinition.cs" id="1_tv46f"]
-[ext_resource type="Texture2D" uid="uid://lgxlsnp626j8" path="res://assets/sprites/items/grimoire.png" id="3_degcq"]
+[ext_resource type="Script" uid="uid://bjheqia3q1u7m" path="res://scripts/Entities/Items/GrimoireItemActivation.cs" id="1_degcq"]
+[ext_resource type="Script" uid="uid://bybli1lduvm3n" path="res://scripts/Entities/Items/ItemResource.cs" id="1_tv46f"]
+[ext_resource type="Resource" uid="uid://boi8svlb0e8l" path="res://assets/definitions/spells/mana_bolt.tres" id="2_dtkc6"]
+[ext_resource type="Texture2D" uid="uid://lgxlsnp626j8" path="res://assets/sprites/items/grimoire.png" id="3_f5ce4"]
+
+[sub_resource type="Resource" id="Resource_4p7cf"]
+script = ExtResource("1_degcq")
+spell = ExtResource("2_dtkc6")
+metadata/_custom_type_script = "uid://bjheqia3q1u7m"
[resource]
script = ExtResource("1_tv46f")
-Spell = ExtResource("1_dnjm5")
-name = "Grimório de flecha de mana."
-texture = ExtResource("3_degcq")
-Type = 1
-blocksMovement = false
-metadata/_custom_type_script = "uid://blkth0in1fp74"
+DisplayName = "Grimório de mana bolt"
+Icon = ExtResource("3_f5ce4")
+Description = "O demiurgo usou as leis da matéria, moldou o mundo e aprisionou todas as centelhas no reino sensível."
+Activation = SubResource("Resource_4p7cf")
+metadata/_custom_type_script = "uid://bybli1lduvm3n"
diff --git a/assets/definitions/Items/mana_bolt_scroll.tres b/assets/definitions/Items/mana_bolt_scroll.tres
deleted file mode 100644
index 1b0dec8..0000000
--- a/assets/definitions/Items/mana_bolt_scroll.tres
+++ /dev/null
@@ -1,14 +0,0 @@
-[gd_resource type="Resource" script_class="ScrollConsumableDefinition" load_steps=4 format=3 uid="uid://xbjfp7d6qoyj"]
-
-[ext_resource type="Resource" uid="uid://boi8svlb0e8l" path="res://assets/definitions/spells/mana_bolt.tres" id="1_eaxr2"]
-[ext_resource type="Script" uid="uid://2lk5w2po81gy" path="res://scripts/Entities/Items/ScrollConsumableDefinition.cs" id="1_jtnuc"]
-[ext_resource type="Texture2D" uid="uid://b2rpvh57daol7" path="res://assets/sprites/items/scroll.png" id="3_eaxr2"]
-
-[resource]
-script = ExtResource("1_jtnuc")
-Spell = ExtResource("1_eaxr2")
-name = "Pergaminho de flecha de mana"
-texture = ExtResource("3_eaxr2")
-Type = 1
-blocksMovement = false
-metadata/_custom_type_script = "uid://2lk5w2po81gy"
diff --git a/assets/definitions/Items/small_healing_potion.tres b/assets/definitions/Items/small_healing_potion.tres
index 4a75d72..2c5d1c4 100644
--- a/assets/definitions/Items/small_healing_potion.tres
+++ b/assets/definitions/Items/small_healing_potion.tres
@@ -1,13 +1,24 @@
-[gd_resource type="Resource" script_class="HealingConsumableDefinition" load_steps=3 format=3 uid="uid://bm6yx6rwh8bds"]
+[gd_resource type="Resource" script_class="ItemResource" load_steps=7 format=3 uid="uid://bb2lhoglbafb4"]
-[ext_resource type="Script" uid="uid://b3qy4gtjfci14" path="res://scripts/Entities/Items/HealingConsumableDefinition.cs" id="1_4dl2g"]
-[ext_resource type="Texture2D" uid="uid://b7drpdbk4lggb" path="res://assets/sprites/items/small_health_potion.png" id="2_esrbk"]
+[ext_resource type="Script" uid="uid://bybli1lduvm3n" path="res://scripts/Entities/Items/ItemResource.cs" id="1_4dl2g"]
+[ext_resource type="Script" uid="uid://bslt4pbvwvsj1" path="res://scripts/Magic/HealEffect.cs" id="1_fmuec"]
+[ext_resource type="Script" uid="uid://b72fwkwul1wet" path="res://scripts/Entities/Items/SpellEffectItemActivation.cs" id="2_nd4hc"]
+[ext_resource type="Texture2D" uid="uid://b7drpdbk4lggb" path="res://assets/sprites/items/small_health_potion.png" id="3_e450c"]
+
+[sub_resource type="Resource" id="Resource_qjoe0"]
+script = ExtResource("1_fmuec")
+Healing = 4
+metadata/_custom_type_script = "uid://bslt4pbvwvsj1"
+
+[sub_resource type="Resource" id="Resource_72281"]
+script = ExtResource("2_nd4hc")
+effect = SubResource("Resource_qjoe0")
+metadata/_custom_type_script = "uid://b72fwkwul1wet"
[resource]
script = ExtResource("1_4dl2g")
-healingPercentage = 10.0
-name = "Poção de vida pequena"
-texture = ExtResource("2_esrbk")
-Type = 1
-blocksMovement = false
-metadata/_custom_type_script = "uid://b3qy4gtjfci14"
+DisplayName = "Poção de vida pequena"
+Icon = ExtResource("3_e450c")
+Description = "Recupera um pouco de vida lol"
+Activation = SubResource("Resource_72281")
+metadata/_custom_type_script = "uid://bybli1lduvm3n"
diff --git a/projeto-fantasia.csproj b/projeto-fantasia.csproj
index 2924733..3497dfc 100644
--- a/projeto-fantasia.csproj
+++ b/projeto-fantasia.csproj
@@ -1,4 +1,4 @@
-<Project Sdk="Godot.NET.Sdk/4.5.0">
+<Project Sdk="Godot.NET.Sdk/4.5.1">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<EnableDynamicLoading>true</EnableDynamicLoading>
diff --git a/projeto-fantasia.csproj.old.1 b/projeto-fantasia.csproj.old.1
new file mode 100644
index 0000000..2924733
--- /dev/null
+++ b/projeto-fantasia.csproj.old.1
@@ -0,0 +1,7 @@
+<Project Sdk="Godot.NET.Sdk/4.5.0">
+ <PropertyGroup>
+ <TargetFramework>net8.0</TargetFramework>
+ <EnableDynamicLoading>true</EnableDynamicLoading>
+ <RootNamespace>projetofantasia</RootNamespace>
+ </PropertyGroup>
+</Project> \ No newline at end of file
diff --git a/scripts/Entities/Actions/DropAction.cs b/scripts/Entities/Actions/DropAction.cs
index 51d4ce6..920c04c 100644
--- a/scripts/Entities/Actions/DropAction.cs
+++ b/scripts/Entities/Actions/DropAction.cs
@@ -5,7 +5,7 @@ namespace TheLegendOfGustav.Entities.Actions;
public partial class DropAction : ItemAction
{
- public DropAction(Player player, ConsumableItem item) : base(player, item)
+ public DropAction(Player player, Item item) : base(player, item)
{
}
diff --git a/scripts/Entities/Actions/ItemAction.cs b/scripts/Entities/Actions/ItemAction.cs
index a2ca1a2..a3197d4 100644
--- a/scripts/Entities/Actions/ItemAction.cs
+++ b/scripts/Entities/Actions/ItemAction.cs
@@ -5,9 +5,9 @@ namespace TheLegendOfGustav.Entities.Actions;
public partial class ItemAction : Action
{
- protected ConsumableItem item;
+ protected Item item;
- public ItemAction(Player player, ConsumableItem item) : base(player)
+ public ItemAction(Player player, Item item) : base(player)
{
this.item = item;
Player = player;
diff --git a/scripts/Entities/Actions/PickUpAction.cs b/scripts/Entities/Actions/PickUpAction.cs
index eaed01c..7676294 100644
--- a/scripts/Entities/Actions/PickUpAction.cs
+++ b/scripts/Entities/Actions/PickUpAction.cs
@@ -19,7 +19,7 @@ public partial class PickupAction : DirectionalAction
public override bool Perform()
{
- ConsumableItem item = MapData.GetFirstItemAtPosition(Destination);
+ ItemEntity item = MapData.GetFirstItemAtPosition(Destination);
if (item == null)
{
@@ -34,7 +34,9 @@ public partial class PickupAction : DirectionalAction
}
MapData.RemoveEntity(item);
- player.Inventory.Add(item);
+ player.Inventory.Add(item.Item);
+
+ item.QueueFree();
player.Energy -= cost;
return true;
diff --git a/scripts/Entities/Actors/Inventory.cs b/scripts/Entities/Actors/Inventory.cs
index 057316a..5ae61b4 100644
--- a/scripts/Entities/Actors/Inventory.cs
+++ b/scripts/Entities/Actors/Inventory.cs
@@ -9,7 +9,7 @@ public partial class Inventory(int capacity) : Node
{
private Player player;
public int Capacity { get; private set; } = capacity;
- public Godot.Collections.Array<ConsumableItem> Items { get; private set; } = [];
+ public Godot.Collections.Array<Item> Items { get; private set; } = [];
public override void _Ready()
{
@@ -17,29 +17,28 @@ public partial class Inventory(int capacity) : Node
player = GetParent<Player>();
}
- public void Drop(ConsumableItem item)
+ public void Drop(Item item)
{
Items.Remove(item);
MapData data = player.MapData;
-
- data.InsertEntity(item);
- data.EmitSignal(MapData.SignalName.EntityPlaced, item);
-
- item.MapData = data;
- item.GridPosition = player.GridPosition;
- MessageLogData.Instance.AddMessage($"Você descarta {item.DisplayName}.");
+ ItemEntity itemEnt = new(player.GridPosition, data, item);
+
+ data.InsertEntity(itemEnt);
+ data.EmitSignal(MapData.SignalName.EntityPlaced, itemEnt);
+
+ MessageLogData.Instance.AddMessage($"Você descarta {item.Definition.DisplayName}.");
}
- public void Add(ConsumableItem item)
+ public void Add(Item item)
{
if (Items.Count >= Capacity) return;
Items.Add(item);
}
- public void RemoveItem(ConsumableItem item)
+ public void RemoveItem(Item item)
{
Items.Remove(item);
}
diff --git a/scripts/Entities/Entity.cs b/scripts/Entities/Entity.cs
index c0e026d..b7dbcc2 100644
--- a/scripts/Entities/Entity.cs
+++ b/scripts/Entities/Entity.cs
@@ -40,6 +40,20 @@ public abstract partial class Entity : Sprite2D
SetDefinition(definition);
}
+
+ /// <summary>
+ /// Aqui eu confio que quem chamar este contrutor
+ /// chamará SetDefinition logo depois. Este construtor existe
+ /// porque tem um caso onde eu não tenho a definição logo de cara.
+ /// </summary>
+ /// <param name="initialPosition"></param>
+ /// <param name="map"></param>
+ public Entity(Vector2I initialPosition, MapData map)
+ {
+ GridPosition = initialPosition;
+ MapData = map;
+ Centered = false;
+ }
/// <summary>
/// Usado para definir a camada da entidade no mapa.
diff --git a/scripts/Entities/Items/ConsumableItem.cs.uid b/scripts/Entities/Items/ConsumableItem.cs.uid
deleted file mode 100644
index e6c452a..0000000
--- a/scripts/Entities/Items/ConsumableItem.cs.uid
+++ /dev/null
@@ -1 +0,0 @@
-uid://hpppt5k743x
diff --git a/scripts/Entities/Items/ConsumableItemDefinition.cs b/scripts/Entities/Items/ConsumableItemDefinition.cs
deleted file mode 100644
index 9cadc0b..0000000
--- a/scripts/Entities/Items/ConsumableItemDefinition.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-using Godot;
-
-namespace TheLegendOfGustav.Entities.Items;
-
-/// <summary>
-/// Esta classe só existe para agrupar seus descendentes.
-/// </summary>
-[GlobalClass]
-public abstract partial class ConsumableItemDefinition : EntityDefinition; \ No newline at end of file
diff --git a/scripts/Entities/Items/ConsumableItemDefinition.cs.uid b/scripts/Entities/Items/ConsumableItemDefinition.cs.uid
deleted file mode 100644
index 9ddc0f6..0000000
--- a/scripts/Entities/Items/ConsumableItemDefinition.cs.uid
+++ /dev/null
@@ -1 +0,0 @@
-uid://dpdju2ucehsb0
diff --git a/scripts/Entities/Items/GrimoireConsumable.cs b/scripts/Entities/Items/GrimoireConsumable.cs
deleted file mode 100644
index e5157a7..0000000
--- a/scripts/Entities/Items/GrimoireConsumable.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-using Godot;
-using TheLegendOfGustav.Entities.Actions;
-using TheLegendOfGustav.Entities.Actors;
-using TheLegendOfGustav.Magic;
-using TheLegendOfGustav.Map;
-
-namespace TheLegendOfGustav.Entities.Items;
-
-public partial class GrimoireConsumable(Vector2I initialPosition, MapData map, GrimoireConsumableDefinition definition) : ConsumableItem(initialPosition, map, definition)
-{
- private SpellResource spell = definition.Spell;
-
- public override bool Activate(ItemAction action)
- {
- Player consumer = action.Player;
-
- consumer.SpellBook.LearnSpell(spell);
-
- ConsumedBy(consumer);
- return true;
- }
-} \ No newline at end of file
diff --git a/scripts/Entities/Items/GrimoireConsumable.cs.uid b/scripts/Entities/Items/GrimoireConsumable.cs.uid
deleted file mode 100644
index 2d56832..0000000
--- a/scripts/Entities/Items/GrimoireConsumable.cs.uid
+++ /dev/null
@@ -1 +0,0 @@
-uid://cdk0yd56njql0
diff --git a/scripts/Entities/Items/GrimoireConsumableDefinition.cs b/scripts/Entities/Items/GrimoireConsumableDefinition.cs
deleted file mode 100644
index 4b041c1..0000000
--- a/scripts/Entities/Items/GrimoireConsumableDefinition.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-using Godot;
-using TheLegendOfGustav.Magic;
-
-namespace TheLegendOfGustav.Entities.Items;
-
-[GlobalClass]
-public partial class GrimoireConsumableDefinition : ConsumableItemDefinition
-{
- [Export]
- public SpellResource Spell { get; set; }
-} \ No newline at end of file
diff --git a/scripts/Entities/Items/GrimoireConsumableDefinition.cs.uid b/scripts/Entities/Items/GrimoireConsumableDefinition.cs.uid
deleted file mode 100644
index 97ad272..0000000
--- a/scripts/Entities/Items/GrimoireConsumableDefinition.cs.uid
+++ /dev/null
@@ -1 +0,0 @@
-uid://blkth0in1fp74
diff --git a/scripts/Entities/Items/GrimoireItemActivation.cs b/scripts/Entities/Items/GrimoireItemActivation.cs
new file mode 100644
index 0000000..34c136f
--- /dev/null
+++ b/scripts/Entities/Items/GrimoireItemActivation.cs
@@ -0,0 +1,19 @@
+using Godot;
+using TheLegendOfGustav.Entities.Actors;
+using TheLegendOfGustav.Magic;
+
+/// <summary>
+/// Aplica um efeito de feitiço ao usuário.
+/// </summary>
+[GlobalClass]
+public partial class GrimoireItemActivation : ItemActivation
+{
+ [Export]
+ SpellResource spell;
+
+ public override bool OnActivation(Player consumer)
+ {
+ consumer.SpellBook.LearnSpell(spell);
+ return true;
+ }
+} \ No newline at end of file
diff --git a/scripts/Entities/Items/GrimoireItemActivation.cs.uid b/scripts/Entities/Items/GrimoireItemActivation.cs.uid
new file mode 100644
index 0000000..1d3b1ae
--- /dev/null
+++ b/scripts/Entities/Items/GrimoireItemActivation.cs.uid
@@ -0,0 +1 @@
+uid://bjheqia3q1u7m
diff --git a/scripts/Entities/Items/HealingConsumable.cs b/scripts/Entities/Items/HealingConsumable.cs
deleted file mode 100644
index 85377d3..0000000
--- a/scripts/Entities/Items/HealingConsumable.cs
+++ /dev/null
@@ -1,30 +0,0 @@
-using Godot;
-using TheLegendOfGustav.Entities.Actors;
-using TheLegendOfGustav.Utils;
-using TheLegendOfGustav.Entities.Actions;
-using TheLegendOfGustav.Map;
-
-namespace TheLegendOfGustav.Entities.Items;
-
-public partial class HealingConsumable(Vector2I initialPosition, MapData map, HealingConsumableDefinition definition) : ConsumableItem(initialPosition, map, definition)
-{
- private HealingConsumableDefinition definition = definition;
- public float HealingPercentage { get; private set; } = definition.healingPercentage;
-
- public override bool Activate(ItemAction action)
- {
- Player consumer = action.Player;
- int intendedAmount = (int)(HealingPercentage / 100 * consumer.MaxHp);
- int recovered = consumer.Heal(intendedAmount);
-
- // Se não tinha o que curar, a ativação falhou.
- if (recovered == 0)
- {
- MessageLogData.Instance.AddMessage("Você já está saudável.");
- return false;
- }
- MessageLogData.Instance.AddMessage($"Você consome {DisplayName} e recupera {recovered} de HP");
- ConsumedBy(consumer);
- return true;
- }
-} \ No newline at end of file
diff --git a/scripts/Entities/Items/HealingConsumable.cs.uid b/scripts/Entities/Items/HealingConsumable.cs.uid
deleted file mode 100644
index 8f8f942..0000000
--- a/scripts/Entities/Items/HealingConsumable.cs.uid
+++ /dev/null
@@ -1 +0,0 @@
-uid://ct20rmjhaukge
diff --git a/scripts/Entities/Items/HealingConsumableDefinition.cs b/scripts/Entities/Items/HealingConsumableDefinition.cs
deleted file mode 100644
index d0e5850..0000000
--- a/scripts/Entities/Items/HealingConsumableDefinition.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-using Godot;
-
-namespace TheLegendOfGustav.Entities.Items;
-
-[GlobalClass]
-public partial class HealingConsumableDefinition : ConsumableItemDefinition
-{
- ///<summary>
- /// Porcentagem da vida do ator para restaurar.
- ///</summary>
- [ExportCategory("Item Mechanics")]
- [Export]
- public float healingPercentage = 10;
-} \ No newline at end of file
diff --git a/scripts/Entities/Items/HealingConsumableDefinition.cs.uid b/scripts/Entities/Items/HealingConsumableDefinition.cs.uid
deleted file mode 100644
index 2fd311d..0000000
--- a/scripts/Entities/Items/HealingConsumableDefinition.cs.uid
+++ /dev/null
@@ -1 +0,0 @@
-uid://b3qy4gtjfci14
diff --git a/scripts/Entities/Items/ConsumableItem.cs b/scripts/Entities/Items/Item.cs
index b672b7d..0eeffd8 100644
--- a/scripts/Entities/Items/ConsumableItem.cs
+++ b/scripts/Entities/Items/Item.cs
@@ -1,17 +1,22 @@
+using System.Reflection.Metadata;
using Godot;
using TheLegendOfGustav.Entities.Actions;
using TheLegendOfGustav.Entities.Actors;
-using TheLegendOfGustav.Map;
namespace TheLegendOfGustav.Entities.Items;
-/// <summary>
-/// Classe para itens consumíveis.
-/// Itens consumíveis são itens de uso limitado.
-/// </summary>
-public abstract partial class ConsumableItem(Vector2I initialPosition, MapData map, ConsumableItemDefinition definition) : Entity(initialPosition, map, definition)
+public partial class Item : RefCounted
{
+ public Item(ItemResource definition)
+ {
+ Definition = definition;
+ Uses = Definition.MaxUses;
+ }
+
+ public ItemResource Definition { get; private set; }
+ public int Uses { get; set; }
+
/// <summary>
/// Gera uma ação onde o ator consome o item.
/// </summary>
@@ -29,12 +34,28 @@ public abstract partial class ConsumableItem(Vector2I initialPosition, MapData m
/// </summary>
/// <param name="action">Ação gerada pelo item.</param>
/// <returns>Se a ação foi realizada ou não.</returns>
- public abstract bool Activate(ItemAction action);
+ public bool Activate(ItemAction action)
+ {
+ if (Uses != 0)
+ {
+ bool ret = Definition.Activation.OnActivation(action.Player);
+
+ if (ret && Uses > 0)
+ {
+ Uses--;
+ }
+
+ return ret;
+ }
+ else
+ {
+ return false;
+ }
+ }
public virtual void ConsumedBy(Player consumer)
{
Inventory inventory = consumer.Inventory;
inventory.RemoveItem(this);
- QueueFree();
}
} \ No newline at end of file
diff --git a/scripts/Entities/Items/Item.cs.uid b/scripts/Entities/Items/Item.cs.uid
new file mode 100644
index 0000000..23e7a9d
--- /dev/null
+++ b/scripts/Entities/Items/Item.cs.uid
@@ -0,0 +1 @@
+uid://c3e6awwrjyfnj
diff --git a/scripts/Entities/Items/ItemActivation.cs b/scripts/Entities/Items/ItemActivation.cs
new file mode 100644
index 0000000..110beea
--- /dev/null
+++ b/scripts/Entities/Items/ItemActivation.cs
@@ -0,0 +1,13 @@
+using Godot;
+using TheLegendOfGustav.Entities.Actors;
+
+/// <summary>
+/// Isto é um pedido de ajuda. Estou gritando ao vazio e o vazio permanece em silêncio.
+/// Eu quero que itens tenham efeitos arbitrários e quero que sejam fáceis de serializar.
+/// Este é a única forma que encontrei para tornar isto possível.
+/// </summary>
+[GlobalClass]
+public abstract partial class ItemActivation : Resource
+{
+ public abstract bool OnActivation(Player consumer);
+} \ No newline at end of file
diff --git a/scripts/Entities/Items/ItemActivation.cs.uid b/scripts/Entities/Items/ItemActivation.cs.uid
new file mode 100644
index 0000000..7e738cb
--- /dev/null
+++ b/scripts/Entities/Items/ItemActivation.cs.uid
@@ -0,0 +1 @@
+uid://pfp13pyai3th
diff --git a/scripts/Entities/Items/ItemEntity.cs b/scripts/Entities/Items/ItemEntity.cs
new file mode 100644
index 0000000..e646e40
--- /dev/null
+++ b/scripts/Entities/Items/ItemEntity.cs
@@ -0,0 +1,25 @@
+using Godot;
+using TheLegendOfGustav.Entities;
+using TheLegendOfGustav.Map;
+
+namespace TheLegendOfGustav.Entities.Items;
+
+public partial class ItemEntity : Entity
+{
+ public Item Item { get; private set; }
+
+ public ItemEntity(Vector2I initialPosition, MapData map, Item item) : base(initialPosition, map)
+ {
+ Item = item;
+ // Eu quero muito reescrever o jogo do zero, mas não tenho tempo :(
+ EntityDefinition sad = new()
+ {
+ blocksMovement = true,
+ name = item.Definition.DisplayName,
+ texture = item.Definition.Icon,
+ Type = EntityType.ITEM,
+ };
+
+ SetDefinition(sad);
+ }
+} \ No newline at end of file
diff --git a/scripts/Entities/Items/ItemEntity.cs.uid b/scripts/Entities/Items/ItemEntity.cs.uid
new file mode 100644
index 0000000..dc7bb78
--- /dev/null
+++ b/scripts/Entities/Items/ItemEntity.cs.uid
@@ -0,0 +1 @@
+uid://c72n26da2uu2e
diff --git a/scripts/Entities/Items/ItemResource.cs b/scripts/Entities/Items/ItemResource.cs
new file mode 100644
index 0000000..47ea64d
--- /dev/null
+++ b/scripts/Entities/Items/ItemResource.cs
@@ -0,0 +1,22 @@
+using Godot;
+
+namespace TheLegendOfGustav.Entities.Items;
+
+/// <summary>
+/// Esta classe só existe para agrupar seus descendentes.
+/// </summary>
+[GlobalClass]
+public partial class ItemResource : Resource
+{
+ [Export]
+ public string DisplayName { get; set; } = "Unnamed item";
+ [Export]
+ public Texture2D Icon { get; set; }
+ [Export]
+ public int MaxUses { get; set; } = 1;
+ [Export]
+ public string Description { get; set; } = "";
+
+ [Export]
+ public ItemActivation Activation { get; set; }
+} \ No newline at end of file
diff --git a/scripts/Entities/Items/ItemResource.cs.uid b/scripts/Entities/Items/ItemResource.cs.uid
new file mode 100644
index 0000000..d5c53a0
--- /dev/null
+++ b/scripts/Entities/Items/ItemResource.cs.uid
@@ -0,0 +1 @@
+uid://bybli1lduvm3n
diff --git a/scripts/Entities/Items/ScrollConsumable.cs b/scripts/Entities/Items/ScrollConsumable.cs
deleted file mode 100644
index 2869deb..0000000
--- a/scripts/Entities/Items/ScrollConsumable.cs
+++ /dev/null
@@ -1,125 +0,0 @@
-using Godot;
-using TheLegendOfGustav.Entities.Actions;
-using TheLegendOfGustav.Entities.Actors;
-using TheLegendOfGustav.InputHandling;
-using TheLegendOfGustav.Magic;
-using TheLegendOfGustav.Map;
-using TheLegendOfGustav.Utils;
-
-namespace TheLegendOfGustav.Entities.Items;
-
-/// <summary>
-/// Um pergaminho é um item consumível que joga exatamente um feitiço.
-/// Feitiços de pergaminhos são gratuitos e não possuem restrições.
-/// </summary>
-/// <param name="initialPosition">Posição que o item será colocado no mapa.</param>
-/// <param name="map">Mapa que o item será colocado.</param>
-/// <param name="definition">Definição do item.</param>
-public partial class ScrollConsumable(Vector2I initialPosition, MapData map, ScrollConsumableDefinition definition) : ConsumableItem(initialPosition, map, definition)
-{
- /// <summary>
- /// O pergaminho só pode ser usado uma única vez.
- /// Alguns feitiços precisam de um alvo, o que significa que
- /// o pergaminho não pode se auto-destruir enquanto o jogador não
- /// escolher uma posição válida.
- ///
- /// Esta variável garante que seja impossível de usar o pergaminho enquanto o jogador
- /// escolhe um alvo.
- /// </summary>
- private bool awaitingTermination = false;
-
- private ScrollConsumableDefinition definition = definition;
-
- /// <summary>
- /// O godot exige que desconectemos sinais customizados antes de
- /// apagar nós.
- ///
- /// Esta variável guarda a expressão lambda que usamos no sinal PlayerSpellCast
- /// para ser desconectado em ConsumedBy.
- /// </summary>
- private SignalBus.PlayerSpellCastEventHandler bindSignal = null;
-
- public SpellResource Spell { get; private set; } = definition.Spell;
-
- public override bool Activate(ItemAction action)
- {
- if (awaitingTermination)
- {
- return false;
- }
- // Feitiços de pergaminhos são gratuitos.
- Spell.Cost = 0;
-
- Player consumer = action.Player;
-
- // Alguns feitiços precisam de um alvo escolhido pelo jogador.
- // Não podemos esperar pelo jogador aqui, a função precisa retornar de forma síncrona.
- //
- // Então, se o feitiço precisar de um alvo, foi montada uma infraestrutura de sinais
- // para garantir que:
- // 1. O jogador possa escolher uma localização qualquer.
- // 2. Uma ação seja gerada com a posição escolhida e dentro de um inputHandler para entrar
- // no ciclo de turnos normalmente.
- // 3. O pergaminho seja destruído quando o feitiço for executado com sucesso.
- if (Spell.Type == SpellType.Ranged)
- {
- // Este delegate existe somente para que eu possa desconectar o sinal de quando o feitiço é executado.
- // A engine exige que desconectemos sinais customizados antes de apagar um nó.
- bindSignal = delegate (bool success) { OnPlayerChoseTarget(success, action.Player); };
-
- // Eu mando dois sinais aqui. um deles avisa para o input handler trocar para o estado de
- // escolher posição de feitiço e o outro informa este inputhandler o feitiço deste pergaminho.
- SignalBus.Instance.EmitSignal(SignalBus.SignalName.CommandInputHandler, (int)InputHandlers.CastSpell);
- SignalBus.Instance.EmitSignal(SignalBus.SignalName.PlayerSpellChooseLocation, Spell);
-
- // Eu também conecto nosso delegate declarado anteriormente para quando o feitiço for executado.
- SignalBus.Instance.PlayerSpellCast += bindSignal;
- awaitingTermination = true;
-
- return true;
- }
-
- return true;
- }
-
- public override void ConsumedBy(Player consumer)
- {
- // De novo, a engine exige que desconectemos o sinal antes de destruir o pergaminho.
- if (bindSignal != null)
- {
- SignalBus.Instance.PlayerSpellCast -= bindSignal;
- }
- base.ConsumedBy(consumer);
- }
-
- public override void _Notification(int what)
- {
- if (what == NotificationPredelete)
- {
- if (bindSignal != null)
- {
- SignalBus.Instance.PlayerSpellCast -= bindSignal;
- }
- }
- base._Notification(what);
- }
-
- /// <summary>
- /// Este método é executado quando o feitiço deste pergaminho for executado
- /// (depois do jogador escolher um alvo.)
- /// </summary>
- /// <param name="success">Se o feitiço for executado com sucesso.</param>
- /// <param name="consumer">Quem ativou o feitiço.</param>
- private void OnPlayerChoseTarget(bool success, Player consumer) {
- if (success)
- {
- ConsumedBy(consumer);
- }
- else
- {
- // Se o feitiço não for ativado com sucesso,
- // podemos reutilizar o pergaminho.
- awaitingTermination = false;
- }
- }
-} \ No newline at end of file
diff --git a/scripts/Entities/Items/ScrollConsumable.cs.uid b/scripts/Entities/Items/ScrollConsumable.cs.uid
deleted file mode 100644
index ba79f47..0000000
--- a/scripts/Entities/Items/ScrollConsumable.cs.uid
+++ /dev/null
@@ -1 +0,0 @@
-uid://dsp0ryh6fctv1
diff --git a/scripts/Entities/Items/ScrollConsumableDefinition.cs b/scripts/Entities/Items/ScrollConsumableDefinition.cs
deleted file mode 100644
index c9f50a5..0000000
--- a/scripts/Entities/Items/ScrollConsumableDefinition.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-using Godot;
-using TheLegendOfGustav.Magic;
-
-namespace TheLegendOfGustav.Entities.Items;
-
-[GlobalClass]
-public partial class ScrollConsumableDefinition : ConsumableItemDefinition
-{
- [Export]
- public SpellResource Spell { get; set; }
-} \ No newline at end of file
diff --git a/scripts/Entities/Items/ScrollConsumableDefinition.cs.uid b/scripts/Entities/Items/ScrollConsumableDefinition.cs.uid
deleted file mode 100644
index 8cadd79..0000000
--- a/scripts/Entities/Items/ScrollConsumableDefinition.cs.uid
+++ /dev/null
@@ -1 +0,0 @@
-uid://2lk5w2po81gy
diff --git a/scripts/Entities/Items/SpellEffectItemActivation.cs b/scripts/Entities/Items/SpellEffectItemActivation.cs
new file mode 100644
index 0000000..3b421c7
--- /dev/null
+++ b/scripts/Entities/Items/SpellEffectItemActivation.cs
@@ -0,0 +1,19 @@
+using Godot;
+using TheLegendOfGustav.Entities.Actors;
+using TheLegendOfGustav.Magic;
+
+/// <summary>
+/// Aplica um efeito de feitiço ao usuário.
+/// </summary>
+[GlobalClass]
+public partial class SpellEffectItemActivation : ItemActivation
+{
+ [Export]
+ SpellEffect effect;
+
+ public override bool OnActivation(Player consumer)
+ {
+ effect.Apply(consumer, consumer);
+ return true;
+ }
+} \ No newline at end of file
diff --git a/scripts/Entities/Items/SpellEffectItemActivation.cs.uid b/scripts/Entities/Items/SpellEffectItemActivation.cs.uid
new file mode 100644
index 0000000..91d3579
--- /dev/null
+++ b/scripts/Entities/Items/SpellEffectItemActivation.cs.uid
@@ -0,0 +1 @@
+uid://b72fwkwul1wet
diff --git a/scripts/GUI/InventoryMenu.cs b/scripts/GUI/InventoryMenu.cs
index dd8e133..7e264fa 100644
--- a/scripts/GUI/InventoryMenu.cs
+++ b/scripts/GUI/InventoryMenu.cs
@@ -11,9 +11,9 @@ public partial class InventoryMenu : CanvasLayer
private VBoxContainer itemsNode;
[Signal]
- public delegate void ItemSelectedEventHandler(ConsumableItem item);
+ public delegate void ItemSelectedEventHandler(Item item);
[Signal]
- public delegate void ItemDropEventHandler(ConsumableItem item);
+ public delegate void ItemDropEventHandler(Item item);
public override void _Ready()
{
@@ -23,12 +23,12 @@ public partial class InventoryMenu : CanvasLayer
Hide();
}
- public void OnActivate(ConsumableItem item)
+ public void OnActivate(Item item)
{
EmitSignal(SignalName.ItemSelected, item);
}
- public void OnDrop(ConsumableItem item)
+ public void OnDrop(Item item)
{
EmitSignal(SignalName.ItemDrop, item);
}
@@ -43,7 +43,7 @@ public partial class InventoryMenu : CanvasLayer
Show();
}
- private void RegisterItem(int index, ConsumableItem item)
+ private void RegisterItem(int index, Item item)
{
char? shortcut = null;
diff --git a/scripts/GUI/ItemMenuEntry.cs b/scripts/GUI/ItemMenuEntry.cs
index 6f18bd9..364c694 100644
--- a/scripts/GUI/ItemMenuEntry.cs
+++ b/scripts/GUI/ItemMenuEntry.cs
@@ -11,13 +11,13 @@ public partial class ItemMenuEntry : HBoxContainer
private Label nameLabel;
private Button activateBtn;
private Button dropBtn;
- private ConsumableItem item;
+ private Item item;
[Signal]
- public delegate void ActivateEventHandler(ConsumableItem Item);
+ public delegate void ActivateEventHandler(Item Item);
[Signal]
- public delegate void DropEventHandler(ConsumableItem Item);
+ public delegate void DropEventHandler(Item Item);
public override void _Ready()
{
@@ -32,10 +32,10 @@ public partial class ItemMenuEntry : HBoxContainer
dropBtn.Pressed += () => EmitSignal(SignalName.Drop, item);
}
- public void Initialize(ConsumableItem item, char? shortcut)
+ public void Initialize(Item item, char? shortcut)
{
this.item = item;
- nameLabel.Text = item.DisplayName;
+ nameLabel.Text = item.Definition.DisplayName;
if (shortcut != null)
{
shortcutLabel.Text = $"{shortcut}";
@@ -70,6 +70,6 @@ public partial class ItemMenuEntry : HBoxContainer
{
shortcutLabel.Text = "";
}
- icon.Texture = item.Texture;
+ icon.Texture = item.Definition.Icon;
}
}
diff --git a/scripts/InputHandling/InventoryInputHandler.cs b/scripts/InputHandling/InventoryInputHandler.cs
index 1eb7f3a..fef0df0 100644
--- a/scripts/InputHandling/InventoryInputHandler.cs
+++ b/scripts/InputHandling/InventoryInputHandler.cs
@@ -15,8 +15,8 @@ public partial class InventoryInputHandler : BaseInputHandler
private Map.Map map;
private InventoryMenu inventoryMenu;
- private ConsumableItem activationItem = null;
- private ConsumableItem dropItem = null;
+ private Item activationItem = null;
+ private Item dropItem = null;
public override void Enter()
{
@@ -63,12 +63,12 @@ public partial class InventoryInputHandler : BaseInputHandler
GetParent<InputHandler>().SetInputHandler(InputHandlers.MainGame);
}
- private void OnItemActivate(ConsumableItem item)
+ private void OnItemActivate(Item item)
{
activationItem = item;
}
- private void OnItemDrop(ConsumableItem item)
+ private void OnItemDrop(Item item)
{
dropItem = item;
}
diff --git a/scripts/Magic/HealEffect.cs b/scripts/Magic/HealEffect.cs
new file mode 100644
index 0000000..3e924c3
--- /dev/null
+++ b/scripts/Magic/HealEffect.cs
@@ -0,0 +1,20 @@
+using Godot;
+using TheLegendOfGustav.Entities.Actors;
+using TheLegendOfGustav.Utils;
+
+namespace TheLegendOfGustav.Magic;
+
+[GlobalClass]
+public partial class HealEffect : SpellEffect
+{
+ [Export]
+ public int Healing { get; set; }
+
+ public override void Apply(Actor caster, Actor target)
+ {
+ int prevHealth = target.Hp;
+ target.Hp += Healing;
+ int healingDealt = target.Hp - prevHealth;
+ MessageLogData.Instance.AddMessage($"{caster.DisplayName} restaurou {healingDealt} de HP de {target.DisplayName}");
+ }
+} \ No newline at end of file
diff --git a/scripts/Magic/HealEffect.cs.uid b/scripts/Magic/HealEffect.cs.uid
new file mode 100644
index 0000000..c35b31a
--- /dev/null
+++ b/scripts/Magic/HealEffect.cs.uid
@@ -0,0 +1 @@
+uid://bslt4pbvwvsj1
diff --git a/scripts/Map/DungeonGenerator.cs b/scripts/Map/DungeonGenerator.cs
index 7dee0b4..7e447b0 100644
--- a/scripts/Map/DungeonGenerator.cs
+++ b/scripts/Map/DungeonGenerator.cs
@@ -21,10 +21,9 @@ public partial class DungeonGenerator : Node
GD.Load<EnemyDefinition>("res://assets/definitions/actor/Shadow.tres"),
];
- private static readonly Godot.Collections.Array<ConsumableItemDefinition> items = [
- GD.Load<HealingConsumableDefinition>("res://assets/definitions/Items/small_healing_potion.tres"),
- GD.Load<ScrollConsumableDefinition>("res://assets/definitions/Items/mana_bolt_scroll.tres"),
- GD.Load<GrimoireConsumableDefinition>("res://assets/definitions/Items/mana_bolt_grimoire.tres")
+ private static readonly Godot.Collections.Array<ItemResource> items = [
+ GD.Load<ItemResource>("res://assets/definitions/Items/small_healing_potion.tres"),
+ GD.Load<ItemResource>("res://assets/definitions/Items/mana_bolt_grimoire.tres")
];
/// <summary>
@@ -275,7 +274,7 @@ public partial class DungeonGenerator : Node
rng.RandiRange(room.Position.Y, room.End.Y - 1)
);
- bool canPlace = true;
+ bool canPlace = items.Count > 0;
foreach (Entity entity in data.Entities)
{
if (entity.GridPosition == position)
@@ -288,21 +287,10 @@ public partial class DungeonGenerator : Node
// Se possível, criamos um inimigo aleatório na posição escolhida.
if (canPlace)
{
- ConsumableItemDefinition definition = items.PickRandom();
- if (definition is HealingConsumableDefinition hcDefinition)
- {
- HealingConsumable item = new(position, data, hcDefinition);
- data.InsertEntity(item);
- }
- else if (definition is ScrollConsumableDefinition scroll)
- {
- ScrollConsumable item = new(position, data, scroll);
- data.InsertEntity(item);
- } else if (definition is GrimoireConsumableDefinition grimoire)
- {
- GrimoireConsumable item = new(position, data, grimoire);
- data.InsertEntity(item);
- }
+ ItemResource itemRes = items.PickRandom();
+ Item item = new(itemRes);
+ ItemEntity itemEnt = new(position, data, item);
+ data.InsertEntity(itemEnt);
}
}
}
diff --git a/scripts/Map/MapData.cs b/scripts/Map/MapData.cs
index 699295e..49e4ca0 100644
--- a/scripts/Map/MapData.cs
+++ b/scripts/Map/MapData.cs
@@ -70,14 +70,14 @@ public partial class MapData : RefCounted
/// <summary>
/// Lista de todos os itens dentro do mapa.
/// </summary>
- public Godot.Collections.Array<ConsumableItem> Items
+ public Godot.Collections.Array<ItemEntity> Items
{
get
{
- Godot.Collections.Array<ConsumableItem> list = [];
+ Godot.Collections.Array<ItemEntity> list = [];
foreach (Entity entity in Entities)
{
- if (entity is ConsumableItem item)
+ if (entity is ItemEntity item)
{
list.Add(item);
}
@@ -207,9 +207,9 @@ public partial class MapData : RefCounted
/// </summary>
/// <param name="pos">Posição</param>
/// <returns>O primeiro item na posição, nulo se não houver.</returns>
- public ConsumableItem GetFirstItemAtPosition(Vector2I pos)
+ public ItemEntity GetFirstItemAtPosition(Vector2I pos)
{
- foreach (ConsumableItem item in Items)
+ foreach (ItemEntity item in Items)
{
if (item.GridPosition == pos)
{