summaryrefslogtreecommitdiff
path: root/scripts/Entities/Items
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 /scripts/Entities/Items
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.
Diffstat (limited to 'scripts/Entities/Items')
-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
27 files changed, 133 insertions, 238 deletions
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