Fix dying loop, add death counter, add die button to debug

This commit is contained in:
2026-01-20 21:18:10 -08:00
parent 670f8baabf
commit a1f67c3d71
16 changed files with 390 additions and 294 deletions

View File

@@ -8,7 +8,7 @@ public partial class GameState
public partial record State public partial record State
{ {
[Meta, LogicBlock(typeof(State), Diagram = true)] [Meta, LogicBlock(typeof(State), Diagram = true)]
public partial record DebugMenu : State, IGet<Input.DebugButtonPressed> public partial record DebugMenu : InGame, IGet<Input.DebugButtonPressed>
{ {
public Transition On(in Input.DebugButtonPressed input) public Transition On(in Input.DebugButtonPressed input)
{ {

View File

@@ -6,6 +6,9 @@ namespace Zennysoft.Ma.Adapter;
[Meta, Id("quest_data")] [Meta, Id("quest_data")]
public partial record QuestData public partial record QuestData
{ {
[Save("death_count")]
public int DeathCount { get; set; } = 0;
[Save("quest_data_1")] [Save("quest_data_1")]
public bool QuestMarker1 { get; set; } = false; public bool QuestMarker1 { get; set; } = false;
} }

View File

@@ -1,4 +1,4 @@
<Project Sdk="Godot.NET.Sdk/4.4.1"> <Project Sdk="Godot.NET.Sdk/4.4.0">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<EnableDynamicLoading>true</EnableDynamicLoading> <EnableDynamicLoading>true</EnableDynamicLoading>

View File

@@ -1,38 +0,0 @@
<Project Sdk="Godot.NET.Sdk/4.4.0">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<EnableDynamicLoading>true</EnableDynamicLoading>
<WarningsAsErrors>CS9057</WarningsAsErrors>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Chickensoft.AutoInject" Version="2.5.0" />
<PackageReference Include="Chickensoft.GodotNodeInterfaces" Version="2.4.0" />
<PackageReference Include="Chickensoft.Introspection" Version="2.2.0" />
<PackageReference Include="Chickensoft.Introspection.Generator" Version="2.2.0" />
<PackageReference Include="Chickensoft.LogicBlocks" Version="5.16.0" />
<PackageReference Include="Chickensoft.LogicBlocks.DiagramGenerator" Version="5.16.0" />
<PackageReference Include="Chickensoft.SaveFileBuilder" Version="1.1.0" />
<PackageReference Include="Chickensoft.Serialization.Godot" Version="0.7.6" />
<PackageReference Include="GodotSharp.SourceGenerators" Version="2.6.0-250131-2115.Release" />
<PackageReference Include="SimpleInjector" Version="5.5.0" />
<PackageReference Include="SSH.NET" Version="2024.2.0" />
<PackageReference Include="System.IO.Abstractions" Version="22.0.11" />
<PackageReference Include="Zeroconf" Version="3.7.16" />
</ItemGroup>
<ItemGroup>
<None Include=".editorconfig" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Zennysoft.Game.Godot.Implementation\Zennysoft.Game.Implementation.csproj" />
<ProjectReference Include="..\Zennysoft.Game.Ma.Implementation\Zennysoft.Ma.Adapter.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Update="Godot.SourceGenerators" Version="4.4.0-dev.2" />
</ItemGroup>
<ItemGroup>
<PackageReference Update="GodotSharp" Version="4.4.0-dev.2" />
</ItemGroup>
<ItemGroup>
<PackageReference Update="GodotSharpEditor" Version="4.4.0-dev.2" />
</ItemGroup>
</Project>

View File

@@ -99,6 +99,7 @@ public partial class Game : Node3D, IGame
}, },
QuestData = new QuestData() QuestData = new QuestData()
{ {
DeathCount = QuestData.DeathCount,
QuestMarker1 = QuestData.QuestMarker1 QuestMarker1 = QuestData.QuestMarker1
} }
}; };
@@ -145,6 +146,8 @@ public partial class Game : Node3D, IGame
public async void OnResolved() public async void OnResolved()
{ {
LoadExistingGame();
await InitializeGame(); await InitializeGame();
GameState.Set(GameRepo); GameState.Set(GameRepo);
@@ -256,8 +259,10 @@ public partial class Game : Node3D, IGame
public IDungeonFloor CurrentFloor => _map.CurrentFloor; public IDungeonFloor CurrentFloor => _map.CurrentFloor;
public void GameOver() public async void GameOver()
{ {
QuestData.DeathCount++;
await Save();
_player.Deactivate(); _player.Deactivate();
GameState.Input(new GameState.Input.GameOver()); GameState.Input(new GameState.Input.GameOver());
} }
@@ -363,8 +368,8 @@ public partial class Game : Node3D, IGame
}) })
.Handle((in GameState.Output.GameOver _) => .Handle((in GameState.Output.GameOver _) =>
{ {
//GameRepo.Pause(); GameRepo.Pause();
//DeathMenu.FadeIn(); GameOverMenu.FadeIn();
}); });
} }

View File

@@ -1,9 +1,8 @@
[gd_scene load_steps=7 format=3 uid="uid://33ek675mfb5n"] [gd_scene load_steps=6 format=3 uid="uid://33ek675mfb5n"]
[ext_resource type="Script" uid="uid://chftlu4proh3d" path="res://src/game/Game.cs" id="1_ytcii"] [ext_resource type="Script" uid="uid://chftlu4proh3d" path="res://src/game/Game.cs" id="1_ytcii"]
[ext_resource type="PackedScene" uid="uid://b1muxus5qdbeu" path="res://src/ui/in_game_ui/InGameUI.tscn" id="5_lxtnp"] [ext_resource type="PackedScene" uid="uid://b1muxus5qdbeu" path="res://src/ui/in_game_ui/InGameUI.tscn" id="5_lxtnp"]
[ext_resource type="PackedScene" uid="uid://cgwiwufvxvfs4" path="res://src/ui/load_next_level/LoadNextLevel.tscn" id="7_yw8km"] [ext_resource type="PackedScene" uid="uid://cgwiwufvxvfs4" path="res://src/ui/load_next_level/LoadNextLevel.tscn" id="7_yw8km"]
[ext_resource type="Script" uid="uid://cbal5oeaha4nx" path="res://src/ui/pause_menu/PauseMenu.cs" id="11_5ng8c"]
[ext_resource type="PackedScene" uid="uid://dbtfgrtgpr4qg" path="res://src/ui/game_over/GameOverMenu.tscn" id="11_wypid"] [ext_resource type="PackedScene" uid="uid://dbtfgrtgpr4qg" path="res://src/ui/game_over/GameOverMenu.tscn" id="11_wypid"]
[ext_resource type="PackedScene" uid="uid://blbqgw3wosc1w" path="res://src/ui/pause_menu/PauseMenu.tscn" id="12_yev8k"] [ext_resource type="PackedScene" uid="uid://blbqgw3wosc1w" path="res://src/ui/pause_menu/PauseMenu.tscn" id="12_yev8k"]
@@ -45,4 +44,3 @@ unique_name_in_owner = true
[node name="PauseMenu" parent="." instance=ExtResource("12_yev8k")] [node name="PauseMenu" parent="." instance=ExtResource("12_yev8k")]
unique_name_in_owner = true unique_name_in_owner = true
visible = false visible = false
script = ExtResource("11_5ng8c")

View File

@@ -53,4 +53,6 @@ public partial class RescuedItems : Node3D
Game.RescuedItems.Items.Clear(); Game.RescuedItems.Items.Clear();
} }
public override void _ExitTree() => base._ExitTree();
} }

View File

@@ -76,15 +76,63 @@ libraries = {
[node name="MapOrder" type="Node" parent="."] [node name="MapOrder" type="Node" parent="."]
unique_name_in_owner = true unique_name_in_owner = true
[node name="Overworld" type="Node" parent="MapOrder"]
script = ExtResource("3_v14r0")
[node name="Altar" type="Node" parent="MapOrder"] [node name="Altar" type="Node" parent="MapOrder"]
script = ExtResource("3_v14r0") script = ExtResource("3_v14r0")
FloorName = 1 FloorName = 1
[node name="FirstFloor" type="Node" parent="MapOrder"] [node name="Floor01" type="Node" parent="MapOrder"]
script = ExtResource("2_00xd7") script = ExtResource("2_00xd7")
FolderName = "SetAFloors" FolderName = "Floor01"
FloorOdds = Array[float]([0.0, 1.0]) FloorOdds = Array[float]([0.0, 1.0])
Sproingy = 1.0 Sproingy = 1.0
[node name="Overworld" type="Node" parent="MapOrder"] [node name="Floor02" type="Node" parent="MapOrder"]
script = ExtResource("3_v14r0") script = ExtResource("2_00xd7")
FolderName = "Floor02"
FloorOdds = Array[float]([0.0, 1.0])
Sproingy = 1.0
[node name="Floor03" type="Node" parent="MapOrder"]
script = ExtResource("2_00xd7")
FolderName = "Floor03"
FloorOdds = Array[float]([0.0, 1.0])
Sproingy = 1.0
[node name="Floor04" type="Node" parent="MapOrder"]
script = ExtResource("2_00xd7")
FolderName = "Floor04"
FloorOdds = Array[float]([0.0, 1.0])
Sproingy = 1.0
[node name="Floor05" type="Node" parent="MapOrder"]
script = ExtResource("2_00xd7")
FolderName = "Floor05"
FloorOdds = Array[float]([0.0, 1.0])
Sproingy = 1.0
[node name="Floor06" type="Node" parent="MapOrder"]
script = ExtResource("2_00xd7")
FolderName = "Floor06"
FloorOdds = Array[float]([0.0, 1.0])
Sproingy = 1.0
[node name="Floor07" type="Node" parent="MapOrder"]
script = ExtResource("2_00xd7")
FolderName = "Floor07"
FloorOdds = Array[float]([0.0, 1.0])
Sproingy = 1.0
[node name="Floor08" type="Node" parent="MapOrder"]
script = ExtResource("2_00xd7")
FolderName = "Floor08"
FloorOdds = Array[float]([0.0, 1.0])
Sproingy = 1.0
[node name="Floor09" type="Node" parent="MapOrder"]
script = ExtResource("2_00xd7")
FolderName = "Floor09"
FloorOdds = Array[float]([0.0, 1.0])
Sproingy = 1.0

View File

@@ -18,8 +18,6 @@ public partial class Overworld : Node3D, IDungeonFloor
[Node] private Area3D Exit { get; set; } = default!; [Node] private Area3D Exit { get; set; } = default!;
[Node] private RescuedItems RescuedItems { get; set; } = default!;
[Node] private Area3D RestoreArea { get; set; } = default!; [Node] private Area3D RestoreArea { get; set; } = default!;
public ImmutableList<IDungeonRoom> Rooms => []; public ImmutableList<IDungeonRoom> Rooms => [];
@@ -32,7 +30,6 @@ public partial class Overworld : Node3D, IDungeonFloor
{ {
Show(); Show();
Exit.AreaEntered += Exit_AreaEntered; Exit.AreaEntered += Exit_AreaEntered;
RescuedItems.SpawnRescuedItems();
RestoreArea.AreaEntered += RestoreArea_AreaEntered; RestoreArea.AreaEntered += RestoreArea_AreaEntered;
RestoreArea.AreaExited += RestoreArea_AreaExited; RestoreArea.AreaExited += RestoreArea_AreaExited;
RestoreTimer = new Timer(); RestoreTimer = new Timer();

View File

@@ -1,10 +1,10 @@
[gd_scene load_steps=523 format=4 uid="uid://dvnc26rebk6o0"] [gd_scene load_steps=522 format=4 uid="uid://dvnc26rebk6o0"]
[ext_resource type="Script" uid="uid://cuhfkyh3d7noa" path="res://src/map/dungeon/code/Overworld.cs" id="1_5hmt3"] [ext_resource type="Script" uid="uid://cuhfkyh3d7noa" path="res://src/map/dungeon/code/Overworld.cs" id="1_5hmt3"]
[ext_resource type="Texture2D" uid="uid://co6h8vyi11sl2" path="res://src/map/overworld/Models/Overworld_CLOUD_RINGS_INNER_63.png" id="2_g6b7b"] [ext_resource type="Texture2D" uid="uid://co6h8vyi11sl2" path="res://src/map/overworld/Models/Overworld_CLOUD_RINGS_INNER_63.png" id="2_g6b7b"]
[ext_resource type="AudioStream" uid="uid://dqmsaok6fyhe7" path="res://src/audio/amb/amb_perlin.wav" id="2_wbbo3"] [ext_resource type="AudioStream" uid="uid://dqmsaok6fyhe7" path="res://src/audio/AMB/amb_perlin.wav" id="2_wbbo3"]
[ext_resource type="AudioStream" uid="uid://dl07vg00se7hd" path="res://src/audio/amb/amb_white_noise.wav" id="3_c2gp5"] [ext_resource type="AudioStream" uid="uid://dl07vg00se7hd" path="res://src/audio/AMB/amb_white_noise.wav" id="3_c2gp5"]
[ext_resource type="AudioStream" uid="uid://boypvgaweep8a" path="res://src/audio/amb/amb_beach.wav" id="3_pvi8n"] [ext_resource type="AudioStream" uid="uid://boypvgaweep8a" path="res://src/audio/AMB/amb_beach.wav" id="3_pvi8n"]
[ext_resource type="Texture2D" uid="uid://w33fr6exryiy" path="res://src/map/overworld/Models/Overworld_CLOUD_RINGS_INNER_37.png" id="3_uyygh"] [ext_resource type="Texture2D" uid="uid://w33fr6exryiy" path="res://src/map/overworld/Models/Overworld_CLOUD_RINGS_INNER_37.png" id="3_uyygh"]
[ext_resource type="Texture2D" uid="uid://dv10yaqvp3mub" path="res://src/map/overworld/Models/Overworld_CLOUD_RINGS_INNER_71.png" id="4_r8r3k"] [ext_resource type="Texture2D" uid="uid://dv10yaqvp3mub" path="res://src/map/overworld/Models/Overworld_CLOUD_RINGS_INNER_71.png" id="4_r8r3k"]
[ext_resource type="Shader" uid="uid://brhf7s3riyag5" path="res://src/map/map shaders/Metal.gdshader" id="5_d1qcb"] [ext_resource type="Shader" uid="uid://brhf7s3riyag5" path="res://src/map/map shaders/Metal.gdshader" id="5_d1qcb"]
@@ -104,7 +104,6 @@
[ext_resource type="PackedScene" uid="uid://clml6uw8csbw1" path="res://src/map/overworld/Models/Overworld Re-Scaled (Missing Distance Objects).glb" id="108_yksd7"] [ext_resource type="PackedScene" uid="uid://clml6uw8csbw1" path="res://src/map/overworld/Models/Overworld Re-Scaled (Missing Distance Objects).glb" id="108_yksd7"]
[ext_resource type="PackedScene" uid="uid://dld10xlpr8d17" path="res://src/map/assets/OW_gate.glb" id="109_8vsb2"] [ext_resource type="PackedScene" uid="uid://dld10xlpr8d17" path="res://src/map/assets/OW_gate.glb" id="109_8vsb2"]
[ext_resource type="PackedScene" uid="uid://dnomijv6j8s3" path="res://src/map/overworld/Models/Overworld COLLISION.glb" id="109_vbsj2"] [ext_resource type="PackedScene" uid="uid://dnomijv6j8s3" path="res://src/map/overworld/Models/Overworld COLLISION.glb" id="109_vbsj2"]
[ext_resource type="PackedScene" uid="uid://tc5kdfoggrng" path="res://src/item_rescue/RescuedItems.tscn" id="141_b6pah"]
[ext_resource type="Texture2D" uid="uid://bd3ad0jb6emg" path="res://src/vfx/World/GREEN_FLAME.png" id="141_fmewe"] [ext_resource type="Texture2D" uid="uid://bd3ad0jb6emg" path="res://src/vfx/World/GREEN_FLAME.png" id="141_fmewe"]
[ext_resource type="Texture2D" uid="uid://b7kj1pxt7wx1g" path="res://src/vfx/World/BLUE_FLAME.png" id="142_8vsb2"] [ext_resource type="Texture2D" uid="uid://b7kj1pxt7wx1g" path="res://src/vfx/World/BLUE_FLAME.png" id="142_8vsb2"]
[ext_resource type="Texture2D" uid="uid://tqkq5kaijq7f" path="res://src/vfx/World/REGULAR_FLAME.png" id="143_xuv6m"] [ext_resource type="Texture2D" uid="uid://tqkq5kaijq7f" path="res://src/vfx/World/REGULAR_FLAME.png" id="143_xuv6m"]
@@ -10671,10 +10670,6 @@ omni_range = 60.893
[node name="Item Transport" type="Node3D" parent="Node3D"] [node name="Item Transport" type="Node3D" parent="Node3D"]
[node name="RescuedItems" parent="Node3D/Item Transport" instance=ExtResource("141_b6pah")]
unique_name_in_owner = true
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -349.863, 9.41853, 131.703)
[node name="Flames" type="Node3D" parent="Node3D"] [node name="Flames" type="Node3D" parent="Node3D"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -384.577, -32.0995, 112.205) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -384.577, -32.0995, 112.205)

View File

@@ -2,7 +2,7 @@
importer="texture" importer="texture"
type="CompressedTexture2D" type="CompressedTexture2D"
uid="uid://rq7xhwirdq4k" uid="uid://d2b7x8y1t8h0c"
path="res://.godot/imported/A1-Longroom_brick_corridor_corrected.png-b1ea2c8e973447760ca54f5a871194df.ctex" path="res://.godot/imported/A1-Longroom_brick_corridor_corrected.png-b1ea2c8e973447760ca54f5a871194df.ctex"
metadata={ metadata={
"vram_texture": false "vram_texture": false

File diff suppressed because one or more lines are too long

View File

@@ -117,3 +117,25 @@ popup/item_14/id = 14
unique_name_in_owner = true unique_name_in_owner = true
layout_mode = 2 layout_mode = 2
text = "Load Next Floor" text = "Load Next Floor"
[node name="DieButton" type="Button" parent="MarginContainer/VBoxContainer/HBoxContainer/VFlowContainer"]
unique_name_in_owner = true
layout_mode = 2
text = "Die"
[node name="DeathCountLabel" type="Label" parent="."]
layout_mode = 0
offset_left = 58.0
offset_top = 657.0
offset_right = 160.0
offset_bottom = 680.0
text = "Death Count:"
[node name="DeathCount" type="Label" parent="."]
unique_name_in_owner = true
layout_mode = 0
offset_left = 165.0
offset_top = 658.0
offset_right = 205.0
offset_bottom = 681.0
text = "100"

View File

@@ -111,201 +111,203 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<IPlayer>
public void Initialize() public void Initialize()
{ {
var container = new SimpleInjector.Container(); var container = new SimpleInjector.Container();
container.Register<IPlayerLogic, PlayerLogic>(Lifestyle.Singleton); container.Register<IPlayerLogic, PlayerLogic>(Lifestyle.Singleton);
PlayerLogic = container.GetInstance<IPlayerLogic>(); PlayerLogic = container.GetInstance<IPlayerLogic>();
PlayerLogic.Set(this as IPlayer); PlayerLogic.Set(this as IPlayer);
PlayerLogic.Set(Settings); PlayerLogic.Set(Settings);
Inventory = new Inventory(); Inventory = new Inventory();
HealthComponent = new HealthComponent(InitialHP); HealthComponent = new HealthComponent(InitialHP);
VTComponent = new VTComponent(InitialVT); VTComponent = new VTComponent(InitialVT);
AttackComponent = new AttackComponent(InitialAttack); AttackComponent = new AttackComponent(InitialAttack);
DefenseComponent = new DefenseComponent(InitialDefense); DefenseComponent = new DefenseComponent(InitialDefense);
ExperiencePointsComponent = new ExperiencePointsComponent(); ExperiencePointsComponent = new ExperiencePointsComponent();
LuckComponent = new LuckComponent(InitialLuck); LuckComponent = new LuckComponent(InitialLuck);
EquipmentComponent = new EquipmentComponent(); EquipmentComponent = new EquipmentComponent();
_itemReroller = new ItemReroller(ItemDatabase.Instance); _itemReroller = new ItemReroller(ItemDatabase.Instance);
CameraAnimations.AnimationFinished += CameraAnimations_AnimationFinished; CameraAnimations.AnimationFinished += CameraAnimations_AnimationFinished;
Settings = new PlayerLogic.Settings() { RotationSpeed = RotationSpeed, MoveSpeed = MoveSpeed, Acceleration = Acceleration }; Settings = new PlayerLogic.Settings() { RotationSpeed = RotationSpeed, MoveSpeed = MoveSpeed, Acceleration = Acceleration };
PlayerBinding = PlayerLogic.Bind(); PlayerBinding = PlayerLogic.Bind();
PlayerBinding PlayerBinding
.Handle((in PlayerLogic.Output.ThrowItem output) => .Handle((in PlayerLogic.Output.ThrowItem output) =>
{ {
}) })
.Handle((in PlayerLogic.Output.Move output) => .Handle((in PlayerLogic.Output.Move output) =>
{ {
Move(output.delta); Move(output.delta);
}); });
PlayerLogic.Start(); PlayerLogic.Start();
this.Provide(); this.Provide();
} }
public void ResetPlayerData() public void ResetPlayerData()
{ {
foreach (var item in Inventory.Items) PlayerFXAnimations.Play("RESET");
Inventory.Remove(item);
HealthComponent.Reset(); foreach (var item in Inventory.Items)
VTComponent.Reset(); Inventory.Remove(item);
AttackComponent.Reset();
DefenseComponent.Reset();
ExperiencePointsComponent.Reset();
LuckComponent.Reset();
EquipmentComponent.Reset();
HealthTimer.Timeout += OnHealthTimerTimeout; HealthComponent.Reset();
VTComponent.Reset();
AttackComponent.Reset();
DefenseComponent.Reset();
ExperiencePointsComponent.Reset();
LuckComponent.Reset();
EquipmentComponent.Reset();
HealthTimer.Timeout += OnHealthTimerTimeout;
} }
#region Initialization #region Initialization
public void OnReady() public void OnReady()
{ {
Hitbox.AreaEntered += Hitbox_AreaEntered; Hitbox.AreaEntered += Hitbox_AreaEntered;
CollisionDetector.AreaEntered += CollisionDetector_AreaEntered; CollisionDetector.AreaEntered += CollisionDetector_AreaEntered;
HealthComponent.HealthReachedZero += Die; HealthComponent.HealthReachedZero += Die;
HealthTimer.WaitTime = _healthTimerWaitTime; PlayerFXAnimations.AnimationFinished += PlayerFXAnimations_AnimationFinished;
SetProcessInput(false); HealthTimer.WaitTime = _healthTimerWaitTime;
SetPhysicsProcess(false); SetProcessInput(false);
SetPhysicsProcess(false);
} }
#endregion #endregion
public void Activate() public void Activate()
{ {
SetProcessInput(true); SetProcessInput(true);
SetPhysicsProcess(true); SetPhysicsProcess(true);
SetHealthTimerStatus(HealthTimerIsActive); SetHealthTimerStatus(HealthTimerIsActive);
} }
public void Deactivate() public void Deactivate()
{ {
Velocity = Vector3.Zero; Velocity = Vector3.Zero;
SetProcessInput(false); SetProcessInput(false);
SetPhysicsProcess(false); SetPhysicsProcess(false);
SetHealthTimerStatus(false); SetHealthTimerStatus(false);
} }
public void LookUp() => CameraAnimations.Play("look_up"); public void LookUp() => CameraAnimations.Play("look_up");
public void SetHealthTimerStatus(bool isActive) public void SetHealthTimerStatus(bool isActive)
{ {
if (isActive) if (isActive)
HealthTimer.Start(); HealthTimer.Start();
else else
HealthTimer.Stop(); HealthTimer.Stop();
} }
public void TeleportPlayer(Transform3D newTransform) public void TeleportPlayer(Transform3D newTransform)
{ {
Transform = newTransform; Transform = newTransform;
} }
public void TakeDamage(AttackData damage) public void TakeDamage(AttackData damage)
{ {
_camera3D.AddShake(1.0f); _camera3D.AddShake(1.0f);
TakeDamageAnimationPlayer.Play("take_damage"); TakeDamageAnimationPlayer.Play("take_damage");
var damageReceived = DamageCalculator.CalculateDamage(damage, DefenseComponent.CurrentDefense.Value + EquipmentComponent.BonusDefense, EquipmentComponent.ElementalResistance); var damageReceived = DamageCalculator.CalculateDamage(damage, DefenseComponent.CurrentDefense.Value + EquipmentComponent.BonusDefense, EquipmentComponent.ElementalResistance);
HealthComponent.Damage(damageReceived); HealthComponent.Damage(damageReceived);
SfxDatabase.Instance.Play(SoundEffect.TakeDamage); SfxDatabase.Instance.Play(SoundEffect.TakeDamage);
} }
public void Knockback(float impulse) public void Knockback(float impulse)
{ {
_knockbackStrength = impulse; _knockbackStrength = impulse;
_knockbackDirection = GlobalBasis.Z.Normalized(); _knockbackDirection = GlobalBasis.Z.Normalized();
} }
public void LevelUp() public void LevelUp()
{ {
var rng = new RandomNumberGenerator(); var rng = new RandomNumberGenerator();
rng.Randomize(); rng.Randomize();
var hpIncrease = rng.RandiRange(3, 6); var hpIncrease = rng.RandiRange(3, 6);
HealthComponent.RaiseMaximumHP(hpIncrease); HealthComponent.RaiseMaximumHP(hpIncrease);
ExperiencePointsComponent.LevelUp(); ExperiencePointsComponent.LevelUp();
} }
public void Die() public void Die()
{ {
PlayerFXAnimations.Play("death"); PlayerFXAnimations.Play("death");
HealthTimer.WaitTime = _healthTimerWaitTime; HealthTimer.WaitTime = _healthTimerWaitTime;
HealthTimer.Timeout -= OnHealthTimerTimeout; HealthTimer.Timeout -= OnHealthTimerTimeout;
SetProcessInput(false); SetProcessInput(false);
SetPhysicsProcess(false); SetPhysicsProcess(false);
PlayerDied?.Invoke();
} }
public void Reset() public void Reset()
{ {
CameraAnimations.Play("RESET"); CameraAnimations.Play("RESET");
} }
public override void _Input(InputEvent @event) public override void _Input(InputEvent @event)
{ {
if (@event.IsActionPressed(GameInputs.Attack)) if (@event.IsActionPressed(GameInputs.Attack))
Attack(); Attack();
if (@event.IsActionPressed(GameInputs.Sprint)) if (@event.IsActionPressed(GameInputs.Sprint))
Settings.MoveSpeed *= 2; Settings.MoveSpeed *= 2;
if (@event.IsActionReleased(GameInputs.Sprint)) if (@event.IsActionReleased(GameInputs.Sprint))
Settings.MoveSpeed /= 2; Settings.MoveSpeed /= 2;
} }
public void PlayTestAnimation() public void PlayTestAnimation()
{ {
PlayerFXAnimations.Play("test_animation"); PlayerFXAnimations.Play("test_animation");
} }
public void OnPhysicsProcess(double delta) public void OnPhysicsProcess(double delta)
{ {
PlayerLogic.Input(new PlayerLogic.Input.PhysicsTick(delta)); PlayerLogic.Input(new PlayerLogic.Input.PhysicsTick(delta));
PlayerLogic.Input(new PlayerLogic.Input.Moved(GlobalPosition, GlobalTransform)); PlayerLogic.Input(new PlayerLogic.Input.Moved(GlobalPosition, GlobalTransform));
} }
public void Equip(EquipableItem equipable) public void Equip(EquipableItem equipable)
{ {
if (equipable.ItemTag == ItemTag.MysteryItem) if (equipable.ItemTag == ItemTag.MysteryItem)
{ {
var rerolledItem = _itemReroller.RerollItem(equipable, Inventory); var rerolledItem = _itemReroller.RerollItem(equipable, Inventory);
Equip(rerolledItem); Equip(rerolledItem);
return; return;
} }
HealthComponent.RaiseMaximumHP(equipable.BonusHP, false); HealthComponent.RaiseMaximumHP(equipable.BonusHP, false);
VTComponent.RaiseMaximumVT(equipable.BonusVT, false); VTComponent.RaiseMaximumVT(equipable.BonusVT, false);
EquipmentComponent.Equip(equipable); EquipmentComponent.Equip(equipable);
} }
public void Unequip(EquipableItem equipable) public void Unequip(EquipableItem equipable)
{ {
HealthComponent.SetMaximumHealth(HealthComponent.MaximumHP.Value - equipable.BonusHP); HealthComponent.SetMaximumHealth(HealthComponent.MaximumHP.Value - equipable.BonusHP);
VTComponent.SetMaximumVT(VTComponent.MaximumVT.Value - equipable.BonusVT); VTComponent.SetMaximumVT(VTComponent.MaximumVT.Value - equipable.BonusVT);
EquipmentComponent.Unequip(equipable); EquipmentComponent.Unequip(equipable);
} }
private void CameraAnimations_AnimationFinished(StringName animName) private void CameraAnimations_AnimationFinished(StringName animName)
{ {
PointUpFinished?.Invoke(); PointUpFinished?.Invoke();
} }
private static Vector3 GlobalInputVector private static Vector3 GlobalInputVector
{ {
get get
{ {
var rawInput = Input.GetVector(GameInputs.MoveLeft, GameInputs.MoveRight, GameInputs.MoveUp, GameInputs.MoveDown); var rawInput = Input.GetVector(GameInputs.MoveLeft, GameInputs.MoveRight, GameInputs.MoveUp, GameInputs.MoveDown);
var input = new Vector3 var input = new Vector3
{ {
X = rawInput.X, X = rawInput.X,
Z = rawInput.Y Z = rawInput.Y
}; };
return input with { Y = 0f }; return input with { Y = 0f };
} }
} }
private static float LeftStrafeInputVector => Input.GetActionStrength(GameInputs.StrafeLeft); private static float LeftStrafeInputVector => Input.GetActionStrength(GameInputs.StrafeLeft);
@@ -314,143 +316,149 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<IPlayer>
private void Attack() private void Attack()
{ {
if (PlayerIsHittingGeometry()) if (PlayerIsHittingGeometry())
AnimationPlayer.Play("hit_wall"); AnimationPlayer.Play("hit_wall");
else if (!AnimationPlayer.IsPlaying()) else if (!AnimationPlayer.IsPlaying())
PlayAttackAnimation(); PlayAttackAnimation();
} }
private void ThrowItem() private void ThrowItem()
{ {
var itemScene = GD.Load<PackedScene>("res://src/items/throwable/ThrowableItem.tscn"); var itemScene = GD.Load<PackedScene>("res://src/items/throwable/ThrowableItem.tscn");
var throwItem = itemScene.Instantiate<ThrowableItem>(); var throwItem = itemScene.Instantiate<ThrowableItem>();
GetTree().Root.AddChildEx(throwItem); GetTree().Root.AddChildEx(throwItem);
throwItem.GlobalPosition = CurrentPosition + new Vector3(0, 3.5f, 0); throwItem.GlobalPosition = CurrentPosition + new Vector3(0, 3.5f, 0);
throwItem.GlobalRotation = GlobalRotation; throwItem.GlobalRotation = GlobalRotation;
} }
private void PlayAttackAnimation() private void PlayAttackAnimation()
{ {
SfxDatabase.Instance.Play(((Weapon)EquipmentComponent.EquippedWeapon.Value).SoundEffect); SfxDatabase.Instance.Play(((Weapon)EquipmentComponent.EquippedWeapon.Value).SoundEffect);
var attackSpeed = ((Weapon)EquipmentComponent.EquippedWeapon.Value).AttackSpeed; var attackSpeed = ((Weapon)EquipmentComponent.EquippedWeapon.Value).AttackSpeed;
AnimationPlayer.SetSpeedScale((float)attackSpeed); AnimationPlayer.SetSpeedScale((float)attackSpeed);
AnimationPlayer.Play("attack"); AnimationPlayer.Play("attack");
}
private void PlayerFXAnimations_AnimationFinished(StringName animName)
{
if (animName == "death")
PlayerDied?.Invoke();
} }
private void OnExitTree() private void OnExitTree()
{ {
PlayerLogic.Stop(); PlayerLogic.Stop();
PlayerBinding.Dispose(); PlayerBinding.Dispose();
Hitbox.AreaEntered -= Hitbox_AreaEntered; Hitbox.AreaEntered -= Hitbox_AreaEntered;
CollisionDetector.AreaEntered -= CollisionDetector_AreaEntered; CollisionDetector.AreaEntered -= CollisionDetector_AreaEntered;
HealthComponent.HealthReachedZero -= Die; HealthComponent.HealthReachedZero -= Die;
HealthTimer.Timeout -= OnHealthTimerTimeout; HealthTimer.Timeout -= OnHealthTimerTimeout;
} }
private void Move(float delta) private void Move(float delta)
{ {
var rawInput = GlobalInputVector; var rawInput = GlobalInputVector;
var strafeLeftInput = LeftStrafeInputVector; var strafeLeftInput = LeftStrafeInputVector;
var strafeRightInput = RightStrafeInputVector; var strafeRightInput = RightStrafeInputVector;
var transform = Transform; var transform = Transform;
transform.Basis = new Basis(Vector3.Up, Settings.RotationSpeed * -rawInput.X * delta) * transform.Basis; transform.Basis = new Basis(Vector3.Up, Settings.RotationSpeed * -rawInput.X * delta) * transform.Basis;
var moveDirection = new Vector3(strafeRightInput - strafeLeftInput, 0, rawInput.Z).Normalized(); var moveDirection = new Vector3(strafeRightInput - strafeLeftInput, 0, rawInput.Z).Normalized();
var velocity = Basis * moveDirection * Settings.MoveSpeed * Settings.Acceleration; var velocity = Basis * moveDirection * Settings.MoveSpeed * Settings.Acceleration;
_knockbackStrength *= 0.9f; _knockbackStrength *= 0.9f;
Transform = Transform with { Basis = transform.Basis }; Transform = Transform with { Basis = transform.Basis };
Velocity = velocity + (_knockbackDirection * _knockbackStrength); Velocity = velocity + (_knockbackDirection * _knockbackStrength);
if (!WalkSFX.Playing && !Velocity.IsZeroApprox()) if (!WalkSFX.Playing && !Velocity.IsZeroApprox())
WalkSFX.Play(); WalkSFX.Play();
else if (Velocity.IsZeroApprox()) else if (Velocity.IsZeroApprox())
WalkSFX.Stop(); WalkSFX.Stop();
MoveAndSlide(); MoveAndSlide();
} }
private void OnPlayerPositionUpdated(Vector3 globalPosition) => GlobalPosition = globalPosition; private void OnPlayerPositionUpdated(Vector3 globalPosition) => GlobalPosition = globalPosition;
private void OnHealthTimerTimeout() private void OnHealthTimerTimeout()
{ {
if (VTComponent.CurrentVT.Value > 0) if (VTComponent.CurrentVT.Value > 0)
{ {
if (((Accessory)EquipmentComponent.EquippedAccessory.Value).AccessoryTag == AccessoryTag.HalfVTConsumption) if (((Accessory)EquipmentComponent.EquippedAccessory.Value).AccessoryTag == AccessoryTag.HalfVTConsumption)
_healthTimerActive = !_healthTimerActive; _healthTimerActive = !_healthTimerActive;
HealthComponent.Heal(1); HealthComponent.Heal(1);
if (_healthTimerActive) if (_healthTimerActive)
VTComponent.Reduce(1); VTComponent.Reduce(1);
} }
else else
HealthComponent.Damage(1); HealthComponent.Damage(1);
} }
private void Hitbox_AreaEntered(Area3D area) private void Hitbox_AreaEntered(Area3D area)
{ {
var target = area.GetOwner(); var target = area.GetOwner();
if (target is IEnemy enemy) if (target is IEnemy enemy)
HitEnemy(enemy); HitEnemy(enemy);
} }
private void HitEnemy(IEnemy enemy) private void HitEnemy(IEnemy enemy)
{ {
var ignoreElementalResistance = (EquipmentComponent.EquippedWeapon.Value as Weapon).WeaponTag == WeaponTag.IgnoreAffinity; var ignoreElementalResistance = (EquipmentComponent.EquippedWeapon.Value as Weapon).WeaponTag == WeaponTag.IgnoreAffinity;
var ignoreDefense = (EquipmentComponent.EquippedWeapon.Value as Weapon).WeaponTag == WeaponTag.IgnoreDefense; var ignoreDefense = (EquipmentComponent.EquippedWeapon.Value as Weapon).WeaponTag == WeaponTag.IgnoreDefense;
var isCriticalHit = BattleExtensions.IsCriticalHit(LuckComponent.Luck.Value + EquipmentComponent.BonusLuck); var isCriticalHit = BattleExtensions.IsCriticalHit(LuckComponent.Luck.Value + EquipmentComponent.BonusLuck);
var totalDamage = AttackComponent.CurrentAttack.Value + EquipmentComponent.BonusAttack; var totalDamage = AttackComponent.CurrentAttack.Value + EquipmentComponent.BonusAttack;
var element = (EquipmentComponent.EquippedWeapon.Value as Weapon).WeaponElement; var element = (EquipmentComponent.EquippedWeapon.Value as Weapon).WeaponElement;
if (isCriticalHit) if (isCriticalHit)
{ {
totalDamage += (int)(totalDamage * 0.5f); totalDamage += (int)(totalDamage * 0.5f);
SfxDatabase.Instance.Play(SoundEffect.Crit); SfxDatabase.Instance.Play(SoundEffect.Crit);
} }
var baseAttack = new AttackData(totalDamage, element, ignoreDefense, ignoreElementalResistance); var baseAttack = new AttackData(totalDamage, element, ignoreDefense, ignoreElementalResistance);
var damageDealt = DamageCalculator.CalculateDamage(baseAttack, enemy.DefenseComponent.CurrentDefense.Value, enemy.ElementalResistanceSet); var damageDealt = DamageCalculator.CalculateDamage(baseAttack, enemy.DefenseComponent.CurrentDefense.Value, enemy.ElementalResistanceSet);
enemy.HealthComponent.Damage(damageDealt); enemy.HealthComponent.Damage(damageDealt);
if (((Weapon)EquipmentComponent.EquippedWeapon.Value).WeaponTag == WeaponTag.Knockback && enemy is IKnockbackable knockbackable) if (((Weapon)EquipmentComponent.EquippedWeapon.Value).WeaponTag == WeaponTag.Knockback && enemy is IKnockbackable knockbackable)
knockbackable.Knockback(0.3f, -CurrentBasis.Z.Normalized()); knockbackable.Knockback(0.3f, -CurrentBasis.Z.Normalized());
if (((Weapon)EquipmentComponent.EquippedWeapon.Value).WeaponTag == WeaponTag.SelfDamage) if (((Weapon)EquipmentComponent.EquippedWeapon.Value).WeaponTag == WeaponTag.SelfDamage)
HealthComponent.Damage(5); HealthComponent.Damage(5);
} }
private void CollisionDetector_AreaEntered(Area3D area) private void CollisionDetector_AreaEntered(Area3D area)
{ {
if (area.GetParent() is InventoryItem inventoryItem) if (area.GetParent() is InventoryItem inventoryItem)
{ {
var isAdded = Inventory.PickUpItem(inventoryItem); var isAdded = Inventory.PickUpItem(inventoryItem);
if (isAdded) if (isAdded)
inventoryItem.QueueFree(); inventoryItem.QueueFree();
} }
if (area.GetParent() is DroppedItem droppedItem) if (area.GetParent() is DroppedItem droppedItem)
{ {
var isAdded = Inventory.PickUpItem(droppedItem.Item); var isAdded = Inventory.PickUpItem(droppedItem.Item);
if (isAdded) if (isAdded)
droppedItem.QueueFree(); droppedItem.QueueFree();
} }
if (area.GetParent() is ThrownItem thrownItem) if (area.GetParent() is ThrownItem thrownItem)
{ {
var isAdded = Inventory.PickUpItem(thrownItem.ItemThatIsThrown); var isAdded = Inventory.PickUpItem(thrownItem.ItemThatIsThrown);
if (isAdded) if (isAdded)
thrownItem.QueueFree(); thrownItem.QueueFree();
} }
if (area.GetParent() is Restorative restorative) if (area.GetParent() is Restorative restorative)
{ {
restorative.QueueFree(); restorative.QueueFree();
} }
} }
private bool PlayerIsHittingGeometry() private bool PlayerIsHittingGeometry()
{ {
var collisions = WallCheck.GetCollidingBodies(); var collisions = WallCheck.GetCollidingBodies();
return collisions.Count > 0; return collisions.Count > 0;
} }
private void WallCheck_BodyEntered(Node body) private void WallCheck_BodyEntered(Node body)
{ {
GD.Print("Hit wall"); GD.Print("Hit wall");
AnimationPlayer.Stop(); AnimationPlayer.Stop();
} }
} }

View File

@@ -2847,6 +2847,9 @@ animations = [{
}, { }, {
"duration": 1.0, "duration": 1.0,
"texture": SubResource("AtlasTexture_ywo1c") "texture": SubResource("AtlasTexture_ywo1c")
}, {
"duration": 1.0,
"texture": null
}], }],
"loop": false, "loop": false,
"name": &"default", "name": &"default",
@@ -8002,6 +8005,9 @@ animations = [{
}, { }, {
"duration": 1.0, "duration": 1.0,
"texture": SubResource("AtlasTexture_d4xbt") "texture": SubResource("AtlasTexture_d4xbt")
}, {
"duration": 1.0,
"texture": null
}], }],
"loop": false, "loop": false,
"name": &"default", "name": &"default",
@@ -12585,7 +12591,7 @@ frame_progress = 1.0
[node name="Crit Marker" type="AnimatedSprite2D" parent="ScreenFX/SubViewportContainer/SubViewport"] [node name="Crit Marker" type="AnimatedSprite2D" parent="ScreenFX/SubViewportContainer/SubViewport"]
position = Vector2(730, 531) position = Vector2(730, 531)
sprite_frames = SubResource("SpriteFrames_gtij5") sprite_frames = SubResource("SpriteFrames_gtij5")
frame = 31 frame = 32
frame_progress = 1.0 frame_progress = 1.0
speed_scale = 2.0 speed_scale = 2.0

View File

@@ -12,6 +12,8 @@ public partial class PauseDebugMenu : Control, IDebugMenu
{ {
public override void _Notification(int what) => this.Notify(what); public override void _Notification(int what) => this.Notify(what);
[Dependency] private IGame _game => this.DependOn<IGame>();
[Dependency] private IMap _map => this.DependOn<IMap>(() => new Map()); [Dependency] private IMap _map => this.DependOn<IMap>(() => new Map());
[Dependency] private IPlayer _player => this.DependOn<IPlayer>(); [Dependency] private IPlayer _player => this.DependOn<IPlayer>();
@@ -24,6 +26,10 @@ public partial class PauseDebugMenu : Control, IDebugMenu
[Node] public Button LoadNextFloorButton { get; set; } = default!; [Node] public Button LoadNextFloorButton { get; set; } = default!;
[Node] public Button DieButton { get; set; } = default!;
[Node] public Label DeathCount { get; set; } = default!;
private readonly string _floorFilePath = @"res://src/map/dungeon/floors/"; private readonly string _floorFilePath = @"res://src/map/dungeon/floors/";
private readonly string _enemyFilePath = @"res://src/enemy/enemy_types"; private readonly string _enemyFilePath = @"res://src/enemy/enemy_types";
@@ -35,6 +41,8 @@ public partial class PauseDebugMenu : Control, IDebugMenu
public override void _Ready() public override void _Ready()
{ {
LoadNextFloorButton.Pressed += LoadNextFloorButton_Pressed; LoadNextFloorButton.Pressed += LoadNextFloorButton_Pressed;
DieButton.Pressed += DieButton_Pressed;
VisibilityChanged += PauseDebugMenu_VisibilityChanged;
_itemDatabase = ItemDatabase.Instance; _itemDatabase = ItemDatabase.Instance;
_spawnableItems = _itemDatabase.Items; _spawnableItems = _itemDatabase.Items;
@@ -79,6 +87,10 @@ public partial class PauseDebugMenu : Control, IDebugMenu
SpawnEnemyDropDown.ItemSelected += SpawnEnemyDropDown_ItemSelected; SpawnEnemyDropDown.ItemSelected += SpawnEnemyDropDown_ItemSelected;
} }
private void DieButton_Pressed() => _player.Die();
private void PauseDebugMenu_VisibilityChanged() => DeathCount.Text = _game.QuestData.DeathCount.ToString("D2");
private void FloorSelectDropDown_ItemSelected(long index) private void FloorSelectDropDown_ItemSelected(long index)
{ {
var sceneName = FloorSelectDropDown.GetItemText((int)index); var sceneName = FloorSelectDropDown.GetItemText((int)index);