summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'scripts')
-rw-r--r--scripts/entities/Entity.cs34
-rw-r--r--scripts/entities/EntityDefinition.cs7
-rw-r--r--scripts/entities/actions/Action.cs3
-rw-r--r--scripts/entities/actions/ItemAction.cs15
-rw-r--r--scripts/entities/actions/ItemAction.cs.uid1
-rw-r--r--scripts/entities/actors/Actor.cs4
-rw-r--r--scripts/entities/items/ConsumableItem.cs31
-rw-r--r--scripts/entities/items/ConsumableItem.cs.uid1
-rw-r--r--scripts/entities/items/ConsumableItemDefinition.cs7
-rw-r--r--scripts/entities/items/ConsumableItemDefinition.cs.uid1
-rw-r--r--scripts/entities/items/HealingConsumable.cs27
-rw-r--r--scripts/entities/items/HealingConsumable.cs.uid1
-rw-r--r--scripts/entities/items/HealingConsumableDefinition.cs11
-rw-r--r--scripts/entities/items/HealingConsumableDefinition.cs.uid1
-rw-r--r--scripts/map/DungeonGenerator.cs45
-rw-r--r--scripts/map/Map.cs12
16 files changed, 183 insertions, 18 deletions
diff --git a/scripts/entities/Entity.cs b/scripts/entities/Entity.cs
index fb83f90..85a3156 100644
--- a/scripts/entities/Entity.cs
+++ b/scripts/entities/Entity.cs
@@ -1,16 +1,42 @@
using Godot;
-public partial class Entity : Sprite2D {
+/// <summary>
+/// Defino aqui que o jogo irá desenhar
+/// atores em cima de itens e itens acima de corpos.
+/// </summary>
+public enum EntityType
+{
+ CORPSE,
+ ITEM,
+ ACTOR
+};
+
+/// <summary>
+/// Classe para elementos móveis que o jogador pode interagir.
+/// </summary>
+public abstract partial class Entity : Sprite2D {
/// <summary>
/// A definição da entidade possui caracterísitcas padrões que definem
/// a entidade em questão.
/// </summary>
private EntityDefinition definition;
+ private EntityType type;
/// <summary>
- /// É conveniente ter acesso ao mapa dentro da entidade. Isto porque ela existe dentro
- /// do mapa, então é necessário ter acesso à algumas informações.
+ /// Usado para definir a camada da entidade no mapa.
/// </summary>
+ public EntityType Type {
+ get => type;
+ set {
+ type = value;
+ ZIndex = (int) type;
+ }
+ }
+
+ /// <summary>
+ /// É conveniente ter acesso ao mapa dentro da entidade. Isto porque ela existe dentro
+ /// do mapa, então é necessário ter acesso à algumas informações.
+ /// </summary>
public MapData Map_Data { get; set; }
private Vector2I gridPosition = Vector2I.Zero;
@@ -76,7 +102,7 @@ public partial class Entity : Sprite2D {
this.definition = definition;
BlocksMovement = definition.blocksMovement;
DisplayName = definition.name;
- ZIndex = 1;
+ Type = definition.Type;
Texture = definition.texture;
}
} \ No newline at end of file
diff --git a/scripts/entities/EntityDefinition.cs b/scripts/entities/EntityDefinition.cs
index 19693db..ba7236a 100644
--- a/scripts/entities/EntityDefinition.cs
+++ b/scripts/entities/EntityDefinition.cs
@@ -2,15 +2,18 @@ using Godot;
[GlobalClass]
public partial class EntityDefinition : Resource{
- [ExportCategory("Visuals")]
+ [ExportCategory("Entity Visuals")]
// Nome da entidade.
[Export]
public string name = "unnamed";
// Seu sprite.
[Export]
public Texture2D texture;
+ // A camada da entidade.
+ [Export]
+ public EntityType Type;
- [ExportCategory("Mechanics")]
+ [ExportCategory("Entity Mechanics")]
// Se a entidade bloqueia movimento.
[Export]
public bool blocksMovement = true;
diff --git a/scripts/entities/actions/Action.cs b/scripts/entities/actions/Action.cs
index 3f15105..9dab5a4 100644
--- a/scripts/entities/actions/Action.cs
+++ b/scripts/entities/actions/Action.cs
@@ -10,8 +10,9 @@ public abstract partial class Action : RefCounted {
/// O ator que realiza a ação.
/// </summary>
protected Actor actor;
+ public Actor ThisActor { get => actor; }
- // O custo da ação.
+ // O custo da ação.
protected int cost;
public Action(Actor actor) {
diff --git a/scripts/entities/actions/ItemAction.cs b/scripts/entities/actions/ItemAction.cs
new file mode 100644
index 0000000..54ff207
--- /dev/null
+++ b/scripts/entities/actions/ItemAction.cs
@@ -0,0 +1,15 @@
+using Godot;
+
+public partial class ItemAction : Action
+{
+ private ConsumableItem item;
+ public ItemAction(Actor actor, ConsumableItem item) : base(actor)
+ {
+ this.item = item;
+ }
+
+ public override bool Perform()
+ {
+ return item.Activate(this);
+ }
+} \ No newline at end of file
diff --git a/scripts/entities/actions/ItemAction.cs.uid b/scripts/entities/actions/ItemAction.cs.uid
new file mode 100644
index 0000000..c8c8e23
--- /dev/null
+++ b/scripts/entities/actions/ItemAction.cs.uid
@@ -0,0 +1 @@
+uid://f7ep4u4fwsyl
diff --git a/scripts/entities/actors/Actor.cs b/scripts/entities/actors/Actor.cs
index dc8ba53..1717cfa 100644
--- a/scripts/entities/actors/Actor.cs
+++ b/scripts/entities/actors/Actor.cs
@@ -156,7 +156,7 @@ public partial class Actor : Entity
base.SetDefinition(definition);
this.definition = definition;
- ZIndex = 1;
+ Type = definition.Type;
MaxHp = definition.Hp;
Hp = definition.Hp;
@@ -207,7 +207,7 @@ public partial class Actor : Entity
Texture = definition.deathTexture;
BlocksMovement = false;
- ZIndex = 0;
+ Type = EntityType.CORPSE;
DisplayName= $"Restos mortais de {DisplayName}";
Map_Data.UnregisterBlockingEntity(this);
EmitSignal(SignalName.Died);
diff --git a/scripts/entities/items/ConsumableItem.cs b/scripts/entities/items/ConsumableItem.cs
new file mode 100644
index 0000000..8c862da
--- /dev/null
+++ b/scripts/entities/items/ConsumableItem.cs
@@ -0,0 +1,31 @@
+using Godot;
+
+/// <summary>
+/// Classe para itens consumíveis.
+/// Itens consumíveis são itens de uso limitado.
+/// </summary>
+public abstract partial class ConsumableItem : Entity
+{
+ public ConsumableItem(Vector2I initialPosition, MapData map, EntityDefinition definition) : base(initialPosition, map, definition)
+ {
+ }
+
+ /// <summary>
+ /// Gera uma ação onde o ator consome o item.
+ /// </summary>
+ /// <param name="consumer"></param>
+ /// <returns></returns>
+ public Action GetAction(Actor consumer)
+ {
+ return new ItemAction(consumer, this);
+ }
+
+ /// <summary>
+ /// Ativa a função deste item.
+ /// Este método é chamado pela ação gerada por ele mesmo.
+ /// Este método permite definir condições para a sua ativação.
+ /// </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);
+} \ No newline at end of file
diff --git a/scripts/entities/items/ConsumableItem.cs.uid b/scripts/entities/items/ConsumableItem.cs.uid
new file mode 100644
index 0000000..e6c452a
--- /dev/null
+++ b/scripts/entities/items/ConsumableItem.cs.uid
@@ -0,0 +1 @@
+uid://hpppt5k743x
diff --git a/scripts/entities/items/ConsumableItemDefinition.cs b/scripts/entities/items/ConsumableItemDefinition.cs
new file mode 100644
index 0000000..74340d2
--- /dev/null
+++ b/scripts/entities/items/ConsumableItemDefinition.cs
@@ -0,0 +1,7 @@
+using Godot;
+
+/// <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
new file mode 100644
index 0000000..9ddc0f6
--- /dev/null
+++ b/scripts/entities/items/ConsumableItemDefinition.cs.uid
@@ -0,0 +1 @@
+uid://dpdju2ucehsb0
diff --git a/scripts/entities/items/HealingConsumable.cs b/scripts/entities/items/HealingConsumable.cs
new file mode 100644
index 0000000..3d8df51
--- /dev/null
+++ b/scripts/entities/items/HealingConsumable.cs
@@ -0,0 +1,27 @@
+using Godot;
+
+public partial class HealingConsumable : ConsumableItem
+{
+ private HealingConsumableDefinition definition;
+ public float HealingPercentage { get; private set; }
+ public HealingConsumable(Vector2I initialPosition, MapData map, HealingConsumableDefinition definition) : base(initialPosition, map, definition)
+ {
+ this.definition = definition;
+ HealingPercentage = definition.healingPercentage;
+ }
+
+ public override bool Activate(ItemAction action)
+ {
+ Actor consumer = action.ThisActor;
+ 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");
+ return true;
+ }
+} \ No newline at end of file
diff --git a/scripts/entities/items/HealingConsumable.cs.uid b/scripts/entities/items/HealingConsumable.cs.uid
new file mode 100644
index 0000000..8f8f942
--- /dev/null
+++ b/scripts/entities/items/HealingConsumable.cs.uid
@@ -0,0 +1 @@
+uid://ct20rmjhaukge
diff --git a/scripts/entities/items/HealingConsumableDefinition.cs b/scripts/entities/items/HealingConsumableDefinition.cs
new file mode 100644
index 0000000..2562e9e
--- /dev/null
+++ b/scripts/entities/items/HealingConsumableDefinition.cs
@@ -0,0 +1,11 @@
+using Godot;
+
+[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
new file mode 100644
index 0000000..2fd311d
--- /dev/null
+++ b/scripts/entities/items/HealingConsumableDefinition.cs.uid
@@ -0,0 +1 @@
+uid://b3qy4gtjfci14
diff --git a/scripts/map/DungeonGenerator.cs b/scripts/map/DungeonGenerator.cs
index f016dd2..cb89508 100644
--- a/scripts/map/DungeonGenerator.cs
+++ b/scripts/map/DungeonGenerator.cs
@@ -12,12 +12,16 @@ public partial class DungeonGenerator : Node
private static readonly Godot.Collections.Array<EnemyDefinition> enemies = [
GD.Load<EnemyDefinition>("res://assets/definitions/actor/Skeleton.tres"),
GD.Load<EnemyDefinition>("res://assets/definitions/actor/morcegao.tres"),
- GD.Load<EnemyDefinition>("res://assets/definitions/actor/Shadow.tres")
+ 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")
];
/// <summary>
- /// Dimensões do mapa a ser criado.
- /// </summary>
+ /// Dimensões do mapa a ser criado.
+ /// </summary>
[ExportCategory("Dimension")]
[Export]
private int width = 80;
@@ -52,6 +56,13 @@ public partial class DungeonGenerator : Node
[Export]
private int maxMonsterPerRoom = 2;
+ /// <summary>
+ /// Quantidade máxima de itens por sala.
+ /// </summary>
+ [ExportCategory("Loot RNG")]
+ [Export]
+ private int maxItemsPerRoom = 2;
+
public override void _Ready()
{
base._Ready();
@@ -149,6 +160,8 @@ public partial class DungeonGenerator : Node
private void PlaceEntities(MapData data, Rect2I room) {
// Define quantos monstros serão colocados na sala
int monsterAmount = rng.RandiRange(0, maxMonsterPerRoom);
+ // Define quantos itens serão colocados na sala.
+ int itemAmount = rng.RandiRange(0, maxItemsPerRoom);
for (int i = 0; i < monsterAmount; i++) {
// Escolhe um lugar aleatório na sala.
@@ -173,6 +186,32 @@ public partial class DungeonGenerator : Node
data.InsertEntity(enemy);
}
}
+
+ for (int i = 0; i < itemAmount; i++) {
+ // Escolhe um lugar aleatório na sala.
+ Vector2I position = new(
+ rng.RandiRange(room.Position.X, room.End.X - 1),
+ rng.RandiRange(room.Position.Y, room.End.Y - 1)
+ );
+
+ // Só podemos colocar um ator por ponto no espaço.
+ bool canPlace = true;
+ foreach (Entity entity in data.Entities) {
+ if (entity.GridPosition == position) {
+ canPlace = false;
+ break;
+ }
+ }
+
+ // 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);
+ }
+ }
+ }
}
/// <summary>
diff --git a/scripts/map/Map.cs b/scripts/map/Map.cs
index c14880a..f4f0783 100644
--- a/scripts/map/Map.cs
+++ b/scripts/map/Map.cs
@@ -46,11 +46,11 @@ public partial class Map : Node2D
}
/// <summary>
- /// Coloca todos os tiles do mapa no mundo do jogo.
+ /// Coloca todas as entidades do mapa no mundo do jogo.
/// </summary>
private void PlaceEntities() {
- foreach (Actor actor in Map_Data.Entities) {
- entitiesNode.AddChild(actor);
+ foreach (Entity entity in Map_Data.Entities) {
+ entitiesNode.AddChild(entity);
}
}
@@ -72,9 +72,9 @@ public partial class Map : Node2D
/// <param name="pos">Centro de visão, normalmente é a posição do jogador.</param>
public void UpdateFOV(Vector2I pos) {
fieldOfView.UpdateFOV(Map_Data, pos, fovRadius);
- // Esconde ou revela atores com base no campo de visão.
- foreach (Actor actor in Map_Data.Entities) {
- actor.Visible = Map_Data.GetTile(actor.GridPosition).IsInView;
+ // Esconde ou revela entidades com base no campo de visão.
+ foreach (Entity entity in Map_Data.Entities) {
+ entity.Visible = Map_Data.GetTile(entity.GridPosition).IsInView;
}
}
}