summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatheus <matheus.guedes.mg.m@gmail.com>2025-11-09 20:16:40 -0300
committerMatheus <matheus.guedes.mg.m@gmail.com>2025-11-09 20:16:50 -0300
commitc4f5404211ef654944d5615e9055c714441f8234 (patch)
treee1ff13c28c44deb9b3f9e4ac9a3ef8c5656769d4
parent3840e41432593855f53013962f42da553264baeb (diff)
desgosto
Este commit marca minha desistência oficial do projeto. Minha preocupação em seguir um tutorial, adicionando minhas próprias features sem se importar com o design da aplicação como um todo resultou em um código maior que o necessário e difícil de manter. Toda vez que eu me forço a trabalhar no jogo, me sinto extremamente desmotivado e enojado. Os próximos commits serão para terminar o jogo para a apresentação. Eu planejo fazer um novo roguelike durante minhas férias da faculade, sem prazos, sem a limitação de usar todos os pilares da programação orientada a objetos e com planejamento minimamente decente. O projeto como um todo não foi um desperdício de tempo. Não só me ensinou o que não fazer, como também será um ótimo alimento para o copilot e outros LLMs. - Matheus Ferreira Guedes.
-rw-r--r--assets/definitions/Items/uohhh.tres21
-rw-r--r--assets/definitions/actor/Player.tres2
-rw-r--r--project.godot1
-rw-r--r--scripts/Entities/Actions/EscapeAction.cs76
-rw-r--r--scripts/Entities/Actors/Actor.cs6
-rw-r--r--scripts/Game.cs2
-rw-r--r--scripts/GameManager.cs2
-rw-r--r--scripts/InputHandling/MainGameInputHandler.cs2
-rw-r--r--scripts/Map/DungeonGenerator.cs62
-rw-r--r--scripts/Utils/Stats.cs52
-rw-r--r--scripts/Utils/Stats.cs.uid1
11 files changed, 207 insertions, 20 deletions
diff --git a/assets/definitions/Items/uohhh.tres b/assets/definitions/Items/uohhh.tres
new file mode 100644
index 0000000..c48c07a
--- /dev/null
+++ b/assets/definitions/Items/uohhh.tres
@@ -0,0 +1,21 @@
+[gd_resource type="Resource" script_class="ItemResource" load_steps=6 format=3 uid="uid://otklq7k1tb45"]
+
+[ext_resource type="Script" uid="uid://bybli1lduvm3n" path="res://scripts/Entities/Items/ItemResource.cs" id="1_6qucm"]
+[ext_resource type="Script" uid="uid://bslt4pbvwvsj1" path="res://scripts/Magic/HealEffect.cs" id="1_uvkms"]
+[ext_resource type="Script" uid="uid://b72fwkwul1wet" path="res://scripts/Entities/Items/SpellEffectItemActivation.cs" id="2_i5wwe"]
+
+[sub_resource type="Resource" id="Resource_idx7p"]
+script = ExtResource("1_uvkms")
+Healing = 89
+metadata/_custom_type_script = "uid://bslt4pbvwvsj1"
+
+[sub_resource type="Resource" id="Resource_v7ab0"]
+script = ExtResource("2_i5wwe")
+effect = SubResource("Resource_idx7p")
+metadata/_custom_type_script = "uid://b72fwkwul1wet"
+
+[resource]
+script = ExtResource("1_6qucm")
+DisplayName = "ojo"
+Activation = SubResource("Resource_v7ab0")
+metadata/_custom_type_script = "uid://bybli1lduvm3n"
diff --git a/assets/definitions/actor/Player.tres b/assets/definitions/actor/Player.tres
index 8a4e2c1..58062c3 100644
--- a/assets/definitions/actor/Player.tres
+++ b/assets/definitions/actor/Player.tres
@@ -11,7 +11,7 @@ deathTexture = ExtResource("1_m72ac")
Hp = 36
Mp = 12
Atk = 8
-Def = 10
+Def = 3
Men = 3
name = "Jogador"
texture = ExtResource("3_m72ac")
diff --git a/project.godot b/project.godot
index 5ee82d7..1cd62bd 100644
--- a/project.godot
+++ b/project.godot
@@ -20,6 +20,7 @@ config/icon="res://icon.svg"
signalBus="*res://scripts/Utils/SignalBus.cs"
MessageLogData="*res://scripts/Utils/MessageLogData.cs"
+Stats="*res://scripts/Utils/Stats.cs"
[display]
diff --git a/scripts/Entities/Actions/EscapeAction.cs b/scripts/Entities/Actions/EscapeAction.cs
index f0b1ed5..1b3aae2 100644
--- a/scripts/Entities/Actions/EscapeAction.cs
+++ b/scripts/Entities/Actions/EscapeAction.cs
@@ -1,13 +1,85 @@
+using System;
+using Godot;
+using Godot.Collections;
+using Microsoft.VisualBasic;
using TheLegendOfGustav.Entities.Actors;
using TheLegendOfGustav.Utils;
namespace TheLegendOfGustav.Entities.Actions;
-public partial class EscapeAction(Actor actor) : Action(actor)
+public partial class EscapeAction(Actor actor, bool should_save = false) : Action(actor)
{
+ private bool should_save = should_save;
public override bool Perform()
{
- Actor.MapData.SaveGame();
+ if (should_save) {
+ Actor.MapData.SaveGame();
+ } else {
+ // game over
+ bool hasLeaderboardFile = FileAccess.FileExists("user://placar.json");
+ if (hasLeaderboardFile) {
+ using var leaderboardFile = FileAccess.Open("user://placar.json", FileAccess.ModeFlags.ReadWrite);
+ string boardString = leaderboardFile.GetLine();
+
+ Dictionary<string, Variant> leaderBoardData;
+
+ try {
+ var parseResult = Json.ParseString(boardString);
+ if (parseResult.VariantType == Variant.Type.Nil) {
+ throw new Exception();
+ }
+ leaderBoardData = (Dictionary<string, Variant>)parseResult;
+ } catch (Exception)
+ {
+ leaderboardFile.Resize(0);
+ leaderboardFile.Seek(0);
+
+ leaderBoardData = new()
+ {
+ {"placar", new Array<Dictionary<string, Variant>>() {Stats.Instance.Serialize()}}
+ };
+ boardString = Json.Stringify(leaderBoardData);
+
+ leaderboardFile.StoreLine(boardString);
+
+ SignalBus.Instance.EmitSignal(SignalBus.SignalName.EscapeRequested);
+ return false;
+ }
+
+ Array<Dictionary<string, Variant>> players = (Array<Dictionary<string, Variant>>)leaderBoardData["placar"];
+
+ players.Add(Stats.Instance.Serialize());
+
+ for (int i = 0; i < players.Count; i++) {
+ for (int j = 0; j < players.Count - 1 - i; j++) {
+ if ((int)players[j]["andar_mais_fundo"] < (int)players[j + 1]["andar_mais_fundo"]) {
+ Dictionary<string, Variant> tmp = players[j];
+ players[j] = players[j + 1];
+ players[j + 1] = tmp;
+ }
+ }
+ }
+
+ if (players.Count > 10) {
+ players = players.GetSliceRange(0, 10);
+ }
+
+ leaderBoardData["placar"] = players;
+
+ leaderboardFile.Resize(0);
+ leaderboardFile.Seek(0);
+ leaderboardFile.StoreLine(Json.Stringify(leaderBoardData));
+ } else {
+ using var leaderboardFile = FileAccess.Open("user://placar.json", FileAccess.ModeFlags.Write);
+ Dictionary<string, Variant> leaderBoardData = new()
+ {
+ {"placar", new Array<Dictionary<string, Variant>>() {Stats.Instance.Serialize()}}
+ };
+ string boardString = Json.Stringify(leaderBoardData);
+
+ leaderboardFile.StoreLine(boardString);
+ }
+ }
SignalBus.Instance.EmitSignal(SignalBus.SignalName.EscapeRequested);
return false;
}
diff --git a/scripts/Entities/Actors/Actor.cs b/scripts/Entities/Actors/Actor.cs
index c68cc2b..e6b8867 100644
--- a/scripts/Entities/Actors/Actor.cs
+++ b/scripts/Entities/Actors/Actor.cs
@@ -101,6 +101,9 @@ public partial class Actor : Entity, ISaveable
get => hp;
set
{
+ if (MapData != null && MapData.Player == this && hp > value) {
+ Stats.Instance.DamageTaken += (hp - value);
+ }
// Esta propriedade impede que o HP seja maior que o máximo.
hp = int.Clamp(value, 0, MaxHp);
EmitSignal(SignalName.HealthChanged, Hp, MaxHp);
@@ -280,6 +283,9 @@ public partial class Actor : Entity, ISaveable
else
{
deathMessage = $"{DisplayName} morreu!";
+ if (!inLoading) {
+ Stats.Instance.EnemiesKilled++;
+ }
}
diff --git a/scripts/Game.cs b/scripts/Game.cs
index e55b937..cc86928 100644
--- a/scripts/Game.cs
+++ b/scripts/Game.cs
@@ -90,6 +90,8 @@ public partial class Game : Node
player.AddChild(camera);
+ Stats.Instance.PlayerName = player.DisplayName;
+
if (!map.LoadGame(player))
{
return false;
diff --git a/scripts/GameManager.cs b/scripts/GameManager.cs
index 5898744..df93954 100644
--- a/scripts/GameManager.cs
+++ b/scripts/GameManager.cs
@@ -42,6 +42,7 @@ public partial class GameManager : Node
private void LoadMainMenu()
{
MainMenu menu = (MainMenu)SwitchToScene(mainMenuScene);
+ Stats.Instance.Clear();
menu.GameRequest += OnGameRequest;
}
@@ -72,6 +73,7 @@ public partial class GameManager : Node
private void OnNameSelect(string name)
{
+ Stats.Instance.PlayerName = name;
NewGame(name);
}
diff --git a/scripts/InputHandling/MainGameInputHandler.cs b/scripts/InputHandling/MainGameInputHandler.cs
index a18bd73..d1b5818 100644
--- a/scripts/InputHandling/MainGameInputHandler.cs
+++ b/scripts/InputHandling/MainGameInputHandler.cs
@@ -60,7 +60,7 @@ public partial class MainGameInputHandler : BaseInputHandler
if (Input.IsActionJustPressed("quit"))
{
- action = new EscapeAction(player);
+ action = new EscapeAction(player, true);
}
if (Input.IsActionJustPressed("descend"))
diff --git a/scripts/Map/DungeonGenerator.cs b/scripts/Map/DungeonGenerator.cs
index 779675f..7f57353 100644
--- a/scripts/Map/DungeonGenerator.cs
+++ b/scripts/Map/DungeonGenerator.cs
@@ -3,6 +3,9 @@ using TheLegendOfGustav.Entities.Actors;
using TheLegendOfGustav.Entities;
using TheLegendOfGustav.Entities.Items;
using System;
+using Godot.Collections;
+using System.Diagnostics.Metrics;
+using System.Numerics;
namespace TheLegendOfGustav.Map;
@@ -14,6 +17,27 @@ public partial class DungeonGenerator : Node
{
#region Fields
/// <summary>
+ /// Chave: Andar mínimo
+ /// Valor: Número de máximo de monstros por sala
+ /// </summary>
+ private static readonly Dictionary<int, int> maxMonstersByFloor = new()
+ {
+ {1, 2},
+ {4, 3},
+ {6, 4},
+ {10, 8}
+ };
+ /// <summary>
+ /// Chave: Andar mínimo
+ /// Valor: Número de máximo de itens por sala
+ /// </summary>
+ private static readonly Dictionary<int, int> maxItemsByFloor = new()
+ {
+ {1, 1},
+ {4, 2},
+ {6, 3},
+ };
+ /// <summary>
/// Coleção de todos os inimigos que o gerador tem acesso.
/// </summary>
private static readonly Godot.Collections.Array<EnemyDefinition> enemies = [
@@ -47,24 +71,30 @@ public partial class DungeonGenerator : Node
/// </summary>
[ExportCategory("RNG")]
private RandomNumberGenerator rng = new();
-
- /// <summary>
- /// Quantidade máxima de inimigos por sala.
- /// </summary>
- [ExportCategory("Monster RNG")]
- [Export]
- private int maxMonstersPerRoom = 2;
-
- /// <summary>
- /// Quantidade máxima de itens por sala.
- /// </summary>
- [ExportCategory("Loot RNG")]
- [Export]
- private int maxItemsPerRoom = 2;
#endregion
#region Methods
+ private int GetMaxIValueForFloor(Dictionary<int, int> valueTable, int currentFloor) {
+ int currentValue = 0;
+
+ int? key = null;
+
+ foreach (int theKey in valueTable.Keys) {
+ if (theKey > currentFloor) {
+ break;
+ } else {
+ key = theKey;
+ }
+ }
+
+ if (key.HasValue) {
+ currentValue = valueTable[key.Value];
+ }
+
+ return currentValue;
+ }
+
/// <summary>
/// Gera um andar da masmorra.
/// Inimigos são colocados conforme configurações.
@@ -229,9 +259,9 @@ 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, maxMonstersPerRoom);
+ int monsterAmount = rng.RandiRange(0, GetMaxIValueForFloor(maxMonstersByFloor, data.CurrentFloor));
// Define quantos itens serão colocados na sala.
- int itemAmount = rng.RandiRange(0, maxItemsPerRoom);
+ int itemAmount = rng.RandiRange(0, GetMaxIValueForFloor(maxItemsByFloor, data.CurrentFloor));
for (int i = 0; i < monsterAmount; i++)
{
diff --git a/scripts/Utils/Stats.cs b/scripts/Utils/Stats.cs
new file mode 100644
index 0000000..d3c4aa3
--- /dev/null
+++ b/scripts/Utils/Stats.cs
@@ -0,0 +1,52 @@
+using Godot;
+using Godot.Collections;
+using TheLegendOfGustav.Utils;
+
+namespace TheLegendOfGustav.Utils;
+
+public partial class Stats : Node
+{
+ public static Stats Instance { get; set; }
+
+ public string PlayerName { get; set; }
+ public int MaxFloor { get; set; } = 0;
+
+ public int EnemiesKilled { get; set; } = 0;
+
+ public int DamageTaken { get; set; } = 0;
+
+ public override void _Ready()
+ {
+ base._Ready();
+ Instance = this;
+
+ SignalBus.Instance.DungeonFloorChanged += OnFloorChange;
+ }
+
+ public void Clear()
+ {
+ PlayerName = "";
+ MaxFloor = 0;
+ EnemiesKilled = 0;
+ DamageTaken = 0;
+ }
+
+ void OnFloorChange(int floor)
+ {
+ if (floor > MaxFloor)
+ {
+ MaxFloor = floor;
+ }
+ }
+
+ public Dictionary<string, Variant> Serialize()
+ {
+ return new()
+ {
+ {"jogador", PlayerName},
+ {"andar_mais_fundo", MaxFloor},
+ {"inimigos_mortos", EnemiesKilled},
+ {"dano_tomado", DamageTaken}
+ };
+ }
+} \ No newline at end of file
diff --git a/scripts/Utils/Stats.cs.uid b/scripts/Utils/Stats.cs.uid
new file mode 100644
index 0000000..a93778d
--- /dev/null
+++ b/scripts/Utils/Stats.cs.uid
@@ -0,0 +1 @@
+uid://eg7t08o6wpxb