diff options
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) { |
