diff --git a/Zennysoft.Game.Ma.Implementation/Components/IAttackComponent.cs b/Zennysoft.Game.Ma.Implementation/Components/IAttackComponent.cs index 2cac061d..abda2db5 100644 --- a/Zennysoft.Game.Ma.Implementation/Components/IAttackComponent.cs +++ b/Zennysoft.Game.Ma.Implementation/Components/IAttackComponent.cs @@ -2,7 +2,7 @@ namespace Zennysoft.Ma.Adapter; -public interface IAttackComponent +public interface IAttackComponent : IEntityComponent { public IAutoProp CurrentAttack { get; } diff --git a/Zennysoft.Game.Ma.Implementation/Components/IDefenseComponent.cs b/Zennysoft.Game.Ma.Implementation/Components/IDefenseComponent.cs index cdeb4ef0..46875a36 100644 --- a/Zennysoft.Game.Ma.Implementation/Components/IDefenseComponent.cs +++ b/Zennysoft.Game.Ma.Implementation/Components/IDefenseComponent.cs @@ -2,7 +2,7 @@ namespace Zennysoft.Ma.Adapter; -public interface IDefenseComponent +public interface IDefenseComponent : IEntityComponent { public IAutoProp CurrentDefense { get; } diff --git a/Zennysoft.Game.Ma.Implementation/Components/IEntityComponent.cs b/Zennysoft.Game.Ma.Implementation/Components/IEntityComponent.cs new file mode 100644 index 00000000..4358f547 --- /dev/null +++ b/Zennysoft.Game.Ma.Implementation/Components/IEntityComponent.cs @@ -0,0 +1,6 @@ +namespace Zennysoft.Ma.Adapter; + +public interface IEntityComponent +{ + public void Reset(); +} diff --git a/Zennysoft.Game.Ma.Implementation/Components/IEquipmentComponent.cs b/Zennysoft.Game.Ma.Implementation/Components/IEquipmentComponent.cs index 89c0f807..fbdae434 100644 --- a/Zennysoft.Game.Ma.Implementation/Components/IEquipmentComponent.cs +++ b/Zennysoft.Game.Ma.Implementation/Components/IEquipmentComponent.cs @@ -2,7 +2,7 @@ using Zennysoft.Ma.Adapter.Entity; namespace Zennysoft.Ma.Adapter; -public interface IEquipmentComponent +public interface IEquipmentComponent : IEntityComponent { public IAutoProp EquippedWeapon { get; } diff --git a/Zennysoft.Game.Ma.Implementation/Components/IExperiencePointsComponent.cs b/Zennysoft.Game.Ma.Implementation/Components/IExperiencePointsComponent.cs index 9e6d5c5e..8b43b82a 100644 --- a/Zennysoft.Game.Ma.Implementation/Components/IExperiencePointsComponent.cs +++ b/Zennysoft.Game.Ma.Implementation/Components/IExperiencePointsComponent.cs @@ -2,7 +2,7 @@ namespace Zennysoft.Ma.Adapter; -public interface IExperiencePointsComponent +public interface IExperiencePointsComponent : IEntityComponent { public IAutoProp CurrentExp { get; } diff --git a/Zennysoft.Game.Ma.Implementation/Components/IHealthComponent.cs b/Zennysoft.Game.Ma.Implementation/Components/IHealthComponent.cs index b202ad2b..ecc9aeca 100644 --- a/Zennysoft.Game.Ma.Implementation/Components/IHealthComponent.cs +++ b/Zennysoft.Game.Ma.Implementation/Components/IHealthComponent.cs @@ -2,7 +2,7 @@ namespace Zennysoft.Ma.Adapter; -public interface IHealthComponent +public interface IHealthComponent : IEntityComponent { public IAutoProp CurrentHP { get; } @@ -17,7 +17,9 @@ public interface IHealthComponent public void Damage(int damageAmount); - public void SetHealth(int health); + public void SetCurrentHealth(int health); + + public void SetMaximumHealth(int health); public void RaiseMaximumHP(int raiseAmount); -} +} \ No newline at end of file diff --git a/Zennysoft.Game.Ma.Implementation/Components/LuckComponent.cs b/Zennysoft.Game.Ma.Implementation/Components/LuckComponent.cs index 7b43309b..230f19b6 100644 --- a/Zennysoft.Game.Ma.Implementation/Components/LuckComponent.cs +++ b/Zennysoft.Game.Ma.Implementation/Components/LuckComponent.cs @@ -2,7 +2,7 @@ namespace Zennysoft.Ma.Adapter; -public interface ILuckComponent +public interface ILuckComponent : IEntityComponent { public IAutoProp Luck { get; } diff --git a/Zennysoft.Game.Ma.Implementation/Components/VTComponent.cs b/Zennysoft.Game.Ma.Implementation/Components/VTComponent.cs index d37efb70..76e9bfcd 100644 --- a/Zennysoft.Game.Ma.Implementation/Components/VTComponent.cs +++ b/Zennysoft.Game.Ma.Implementation/Components/VTComponent.cs @@ -2,7 +2,7 @@ namespace Zennysoft.Ma.Adapter; -public interface IVTComponent +public interface IVTComponent : IEntityComponent { public IAutoProp CurrentVT { get; } diff --git a/Zennysoft.Game.Ma.Implementation/Game/state/GameState.Input.cs b/Zennysoft.Game.Ma.Implementation/Game/state/GameState.Input.cs index febc8928..bce07db5 100644 --- a/Zennysoft.Game.Ma.Implementation/Game/state/GameState.Input.cs +++ b/Zennysoft.Game.Ma.Implementation/Game/state/GameState.Input.cs @@ -8,10 +8,6 @@ public partial class GameState public readonly record struct LoadGame; - public readonly record struct ContinueGame; - - public readonly record struct ReturnToMainMenu; - public readonly record struct LoadNextFloor; public readonly record struct InventoryButtonPressed; diff --git a/Zennysoft.Game.Ma.Implementation/Game/state/gamestates/GameState.State.AskForTeleportScreen.cs b/Zennysoft.Game.Ma.Implementation/Game/state/gamestates/GameState.State.AskForTeleportScreen.cs index db063f05..142c0663 100644 --- a/Zennysoft.Game.Ma.Implementation/Game/state/gamestates/GameState.State.AskForTeleportScreen.cs +++ b/Zennysoft.Game.Ma.Implementation/Game/state/gamestates/GameState.State.AskForTeleportScreen.cs @@ -16,11 +16,6 @@ public partial class GameState OnAttach(() => Get().Pause()); } - public Transition On(in Input.ReturnToMainMenu input) - { - return To(); - } - public Transition On(in Input.UseTeleport input) { Output(new Output.OpenFloorExitScreen()); diff --git a/Zennysoft.Game.Ma.Implementation/Game/state/gamestates/GameState.State.FloorExitScreen.cs b/Zennysoft.Game.Ma.Implementation/Game/state/gamestates/GameState.State.FloorExitScreen.cs index 6c045c37..6ff8c52c 100644 --- a/Zennysoft.Game.Ma.Implementation/Game/state/gamestates/GameState.State.FloorExitScreen.cs +++ b/Zennysoft.Game.Ma.Implementation/Game/state/gamestates/GameState.State.FloorExitScreen.cs @@ -8,7 +8,7 @@ public partial class GameState public partial record State { [Meta, LogicBlock(typeof(State), Diagram = true)] - public partial record FloorExitScreen : State, IGet, IGet + public partial record FloorExitScreen : State, IGet { public FloorExitScreen() { @@ -20,11 +20,6 @@ public partial class GameState Output(new Output.LoadNextFloor()); return To(); } - - public Transition On(in Input.ReturnToMainMenu input) - { - return To(); - } } } } diff --git a/Zennysoft.Game.Ma.Implementation/Game/state/gamestates/GameState.State.GameOver.cs b/Zennysoft.Game.Ma.Implementation/Game/state/gamestates/GameState.State.GameOver.cs index 06ab1ac6..2ae83f95 100644 --- a/Zennysoft.Game.Ma.Implementation/Game/state/gamestates/GameState.State.GameOver.cs +++ b/Zennysoft.Game.Ma.Implementation/Game/state/gamestates/GameState.State.GameOver.cs @@ -8,18 +8,13 @@ public partial class GameState public partial record State { [Meta, LogicBlock(typeof(State), Diagram = true)] - public partial record GameOver : State, IGet, IGet + public partial record GameOver : State, IGet { - public Transition On(in Input.ContinueGame input) + public Transition On(in Input.NewGame input) { Output(new Output.InitializeGame()); return To(); } - - public Transition On(in Input.ReturnToMainMenu input) - { - return To(); - } } } } diff --git a/Zennysoft.Game.Ma.Implementation/Game/state/gamestates/GameState.State.MainMenu..cs b/Zennysoft.Game.Ma.Implementation/Game/state/gamestates/GameState.State.MainMenu..cs deleted file mode 100644 index 2ca3b02d..00000000 --- a/Zennysoft.Game.Ma.Implementation/Game/state/gamestates/GameState.State.MainMenu..cs +++ /dev/null @@ -1,34 +0,0 @@ -using Chickensoft.Introspection; -using Chickensoft.LogicBlocks; - -namespace Zennysoft.Ma.Adapter; - -public partial class GameState -{ - public partial record State - { - [Meta, LogicBlock(typeof(State), Diagram = true)] - public partial record MainMenu : State, IGet, IGet, IGet - { - public Transition On(in Input.NewGame input) - { - Output(new Output.InitializeGame()); - return To(); - } - - public Transition On(in Input.ContinueGame input) - { - Output(new Output.InitializeGame()); - Output(new Output.LoadGameFromFile()); - return To(); - } - - public Transition On(in Input.LoadGame input) - { - Output(new Output.InitializeGame()); - Output(new Output.LoadGameFromFile()); - return To(); - } - } - } -} diff --git a/Zennysoft.Game.Ma.Implementation/Item/IDroppedItem.cs b/Zennysoft.Game.Ma.Implementation/Item/IDroppedItem.cs new file mode 100644 index 00000000..451d4450 --- /dev/null +++ b/Zennysoft.Game.Ma.Implementation/Item/IDroppedItem.cs @@ -0,0 +1,9 @@ +namespace Zennysoft.Ma.Adapter +{ + public interface IDroppedItem + { + void RescueItem(); + + public InventoryItem Item { get; } + } +} diff --git a/Zennysoft.Game.Ma.Implementation/Item/IInventory.cs b/Zennysoft.Game.Ma.Implementation/Item/IInventory.cs index 0c6b106a..e55ab2c6 100644 --- a/Zennysoft.Game.Ma.Implementation/Item/IInventory.cs +++ b/Zennysoft.Game.Ma.Implementation/Item/IInventory.cs @@ -1,9 +1,9 @@ -using Zennysoft.Game.Implementation; - -namespace Zennysoft.Ma.Adapter; +namespace Zennysoft.Ma.Adapter; public interface IInventory { + public bool PickUpItem(InventoryItem item); + public List Items { get; } public bool TryAdd(InventoryItem inventoryItem); @@ -13,4 +13,6 @@ public interface IInventory public void Remove(InventoryItem inventoryItem); public void Sort(EquipableItem currentWeapon, EquipableItem currentArmor, EquipableItem currentAccessory); + + public event Action BroadcastMessage; } diff --git a/Zennysoft.Game.Ma.Implementation/Item/IThrownItem.cs b/Zennysoft.Game.Ma.Implementation/Item/IThrownItem.cs new file mode 100644 index 00000000..18181b2c --- /dev/null +++ b/Zennysoft.Game.Ma.Implementation/Item/IThrownItem.cs @@ -0,0 +1,6 @@ +namespace Zennysoft.Ma.Adapter; + +public interface IThrownItem +{ + public InventoryItem ItemThatIsThrown { get; set; } +} diff --git a/Zennysoft.Game.Ma.Implementation/Player/IPlayer.cs b/Zennysoft.Game.Ma.Implementation/Player/IPlayer.cs index d88544fa..9af74e8f 100644 --- a/Zennysoft.Game.Ma.Implementation/Player/IPlayer.cs +++ b/Zennysoft.Game.Ma.Implementation/Player/IPlayer.cs @@ -6,6 +6,8 @@ namespace Zennysoft.Ma.Adapter; public interface IPlayer : IKillable, ICharacterBody3D { + public void ResetPlayerData(); + public void Activate(); public void Deactivate(); @@ -18,6 +20,10 @@ public interface IPlayer : IKillable, ICharacterBody3D public void TeleportPlayer(Transform3D newTransform); + public void Equip(EquipableItem equipable); + + public void Unequip(EquipableItem equipable); + public IInventory Inventory { get; } public IHealthComponent HealthComponent { get; } @@ -33,4 +39,7 @@ public interface IPlayer : IKillable, ICharacterBody3D public ILuckComponent LuckComponent { get; } public IEquipmentComponent EquipmentComponent { get; } + + public event Action PlayerDied; + public delegate InventoryItem RerollItem(InventoryItem item); } diff --git a/Zennysoft.Game.Ma/src/Components/AttackComponent.cs b/Zennysoft.Game.Ma/src/Components/AttackComponent.cs index 9a5a9070..5909c06f 100644 --- a/Zennysoft.Game.Ma/src/Components/AttackComponent.cs +++ b/Zennysoft.Game.Ma/src/Components/AttackComponent.cs @@ -10,21 +10,23 @@ public class AttackComponent : IAttackComponent public IAutoProp MaximumAttack => _maximumAttack; - public IAutoProp BonusAttack => _bonusAttack; - - public int TotalAttack => CurrentAttack.Value + BonusAttack.Value; - private readonly AutoProp _currentAttack; private readonly AutoProp _maximumAttack; - private readonly AutoProp _bonusAttack; + private readonly int _initialValue; public AttackComponent(int attackValue) { _maximumAttack = new AutoProp(attackValue); _currentAttack = new AutoProp(attackValue); - _bonusAttack = new AutoProp(0); + _initialValue = attackValue; + } + + public void Reset() + { + _maximumAttack.OnNext(_initialValue); + _currentAttack.OnNext(_initialValue); } public void Restore(int restoreAmount) @@ -50,14 +52,4 @@ public class AttackComponent : IAttackComponent _maximumAttack.OnNext(raiseAmount); Restore(raiseAmount); } - - public void RaiseBonusAttack(int raiseAmount) - { - _bonusAttack.OnNext(_bonusAttack.Value + raiseAmount); - } - - public void ResetBonusAttack() - { - _bonusAttack.OnNext(0); - } } diff --git a/Zennysoft.Game.Ma/src/Components/DefenseComponent.cs b/Zennysoft.Game.Ma/src/Components/DefenseComponent.cs index 094e0660..a2c524b6 100644 --- a/Zennysoft.Game.Ma/src/Components/DefenseComponent.cs +++ b/Zennysoft.Game.Ma/src/Components/DefenseComponent.cs @@ -14,10 +14,19 @@ public class DefenseComponent : IDefenseComponent private readonly AutoProp _maximumDefense; + private readonly int _initialValue; + public DefenseComponent(int defenseValue) { _maximumDefense = new AutoProp(defenseValue); _currentDefense = new AutoProp(defenseValue); + _initialValue = defenseValue; + } + + public void Reset() + { + _maximumDefense.OnNext(_initialValue); + _currentDefense.OnNext(_initialValue); } public void Restore(int restoreAmount) diff --git a/Zennysoft.Game.Ma/src/Components/EquipmentComponent.cs b/Zennysoft.Game.Ma/src/Components/EquipmentComponent.cs index 9b58b694..f1bfd4d2 100644 --- a/Zennysoft.Game.Ma/src/Components/EquipmentComponent.cs +++ b/Zennysoft.Game.Ma/src/Components/EquipmentComponent.cs @@ -36,6 +36,13 @@ public class EquipmentComponent : IEquipmentComponent _equippedAccessory = new AutoProp(new Accessory()); } + public void Reset() + { + _equippedWeapon.OnNext(new Weapon()); + _equippedArmor.OnNext(new Armor()); + _equippedAccessory.OnNext(new Accessory()); + } + public void Equip(EquipableItem equipable) { if (equipable is Weapon weapon) diff --git a/Zennysoft.Game.Ma/src/Components/ExperiencePointsComponent.cs b/Zennysoft.Game.Ma/src/Components/ExperiencePointsComponent.cs index 9cf65c2f..cf0a41c6 100644 --- a/Zennysoft.Game.Ma/src/Components/ExperiencePointsComponent.cs +++ b/Zennysoft.Game.Ma/src/Components/ExperiencePointsComponent.cs @@ -27,10 +27,19 @@ public class ExperiencePointsComponent : IExperiencePointsComponent var firstLevelExpRequirement = ExpToNextLevelCalculation(1); _expToNextLevel = new AutoProp(firstLevelExpRequirement); _currentExp = new AutoProp(0); - _expGainRate = new AutoProp(1.0); + _expGainRate = new AutoProp(1); _level = new AutoProp(1); } + public void Reset() + { + _currentExp.OnNext(0); + _expGainRate.OnNext(1); + _level.OnNext(1); + var firstLevelExpRequirement = ExpToNextLevelCalculation(1); + _expToNextLevel.OnNext(firstLevelExpRequirement); + } + public void Gain(int baseExpGain) { var modifiedExpGain = baseExpGain * _expGainRate.Value; diff --git a/Zennysoft.Game.Ma/src/Components/HealthComponent.cs b/Zennysoft.Game.Ma/src/Components/HealthComponent.cs index 3098a0ea..6a5d7183 100644 --- a/Zennysoft.Game.Ma/src/Components/HealthComponent.cs +++ b/Zennysoft.Game.Ma/src/Components/HealthComponent.cs @@ -19,10 +19,19 @@ public class HealthComponent : IHealthComponent public bool AtFullHealth => CurrentHP.Value == MaximumHP.Value; + private readonly int _initialValue; + public HealthComponent(int initialHP) { _maximumHP = new AutoProp(initialHP); _currentHP = new AutoProp(initialHP); + _initialValue = initialHP; + } + + public void Reset() + { + _maximumHP.OnNext(_initialValue); + _currentHP.OnNext(_initialValue); } public void Heal(int healAmount) @@ -42,12 +51,17 @@ public class HealthComponent : IHealthComponent DamageTaken?.Invoke(); } - public void SetHealth(int health) + public void SetCurrentHealth(int health) { var cappedAmount = Math.Min(health, _maximumHP.Value); _currentHP.OnNext(cappedAmount); } + public void SetMaximumHealth(int health) + { + _maximumHP.OnNext(health); + } + public void RaiseMaximumHP(int raiseAmount) { _maximumHP.OnNext(raiseAmount); diff --git a/Zennysoft.Game.Ma/src/Components/LuckComponent.cs b/Zennysoft.Game.Ma/src/Components/LuckComponent.cs index 41b9a499..bc4792d1 100644 --- a/Zennysoft.Game.Ma/src/Components/LuckComponent.cs +++ b/Zennysoft.Game.Ma/src/Components/LuckComponent.cs @@ -8,10 +8,17 @@ public class LuckComponent : ILuckComponent public IAutoProp Luck => _luck; private AutoProp _luck; + private readonly int _initialValue; public LuckComponent(int initialLuck) { _luck = new AutoProp(initialLuck); + _initialValue = initialLuck; + } + + public void Reset() + { + _luck.OnNext(_initialValue); } public void IncreaseLuck(int value) => _luck.OnNext(_luck.Value + value); diff --git a/Zennysoft.Game.Ma/src/Components/VTComponent.cs b/Zennysoft.Game.Ma/src/Components/VTComponent.cs index 943c9299..fa9c137d 100644 --- a/Zennysoft.Game.Ma/src/Components/VTComponent.cs +++ b/Zennysoft.Game.Ma/src/Components/VTComponent.cs @@ -14,12 +14,21 @@ public class VTComponent : IVTComponent private readonly AutoProp _maximumVT; + private readonly int _initialValue; + public bool AtFullVT => CurrentVT.Value == MaximumVT.Value; public VTComponent(int initialVT) { _maximumVT = new AutoProp(initialVT); _currentVT = new AutoProp(initialVT); + _initialValue = initialVT; + } + + public void Reset() + { + _maximumVT.OnNext(_initialValue); + _currentVT.OnNext(_initialValue); } public void Restore(int restoreAmount) diff --git a/Zennysoft.Game.Ma/src/enemy/behaviors/FollowBehavior.cs b/Zennysoft.Game.Ma/src/enemy/behaviors/FollowBehavior.cs index 9d645d9a..960302bb 100644 --- a/Zennysoft.Game.Ma/src/enemy/behaviors/FollowBehavior.cs +++ b/Zennysoft.Game.Ma/src/enemy/behaviors/FollowBehavior.cs @@ -63,5 +63,6 @@ public partial class FollowBehavior : Node3D, IBehavior { _thinkTimer.Stop(); _thinkTimer.Timeout -= OnTimeout; + _thinkTimer.Dispose(); } } diff --git a/Zennysoft.Game.Ma/src/enemy/enemy_types/07. chinthe/ChintheModelView.tscn b/Zennysoft.Game.Ma/src/enemy/enemy_types/07. chinthe/ChintheModelView.tscn index 7df79e34..46450c4b 100644 --- a/Zennysoft.Game.Ma/src/enemy/enemy_types/07. chinthe/ChintheModelView.tscn +++ b/Zennysoft.Game.Ma/src/enemy/enemy_types/07. chinthe/ChintheModelView.tscn @@ -2707,236 +2707,6 @@ tracks/1/keys = { "values": [0, 10] } -[sub_resource type="Animation" id="Animation_6dej3"] -resource_name = "teleport" -length = 0.833341 -step = 0.0833333 -tracks/0/type = "value" -tracks/0/imported = false -tracks/0/enabled = true -tracks/0/path = NodePath("Sprite3D/SubViewportContainer/SubViewport/AnimatedSprite:animation") -tracks/0/interp = 1 -tracks/0/loop_wrap = true -tracks/0/keys = { -"times": PackedFloat32Array(0), -"transitions": PackedFloat32Array(1), -"update": 1, -"values": [&"teleport"] -} -tracks/1/type = "value" -tracks/1/imported = false -tracks/1/enabled = true -tracks/1/path = NodePath("Sprite3D/SubViewportContainer/SubViewport/AnimatedSprite:frame") -tracks/1/interp = 1 -tracks/1/loop_wrap = true -tracks/1/keys = { -"times": PackedFloat32Array(0, 0.833333), -"transitions": PackedFloat32Array(1, 1), -"update": 0, -"values": [0, 10] -} -tracks/2/type = "value" -tracks/2/imported = false -tracks/2/enabled = true -tracks/2/path = NodePath("Sprite3D:scale:x") -tracks/2/interp = 1 -tracks/2/loop_wrap = true -tracks/2/keys = { -"times": PackedFloat32Array(0, 0.583333, 0.666667, 0.75), -"transitions": PackedFloat32Array(1, 1, 1, 1), -"update": 0, -"values": [1.5, Vector3(0, -8.54, 0), Vector3(0, 14.05, 0), Vector3(0, -13.51, 0)] -} -tracks/3/type = "value" -tracks/3/imported = false -tracks/3/enabled = true -tracks/3/path = NodePath("Sprite3D:position") -tracks/3/interp = 1 -tracks/3/loop_wrap = true -tracks/3/keys = { -"times": PackedFloat32Array(0), -"transitions": PackedFloat32Array(1), -"update": 0, -"values": [Vector3(0, 0, 0)] -} -tracks/4/type = "value" -tracks/4/imported = false -tracks/4/enabled = true -tracks/4/path = NodePath("Sprite3D:scale") -tracks/4/interp = 1 -tracks/4/loop_wrap = true -tracks/4/keys = { -"times": PackedFloat32Array(0.25, 0.416667, 0.583333, 0.75, 0.833333), -"transitions": PackedFloat32Array(1, 1, 1, 1, 1), -"update": 0, -"values": [Vector3(1.5, 1.5, 1.5), Vector3(1.5, -4.765, 1.5), Vector3(7.31, 0.66, 1.5), Vector3(0.397, 2.422, 1.5), Vector3(1.005, 0.005, 1.5)] -} -tracks/5/type = "value" -tracks/5/imported = false -tracks/5/enabled = true -tracks/5/path = NodePath("Sprite3D:modulate") -tracks/5/interp = 1 -tracks/5/loop_wrap = true -tracks/5/keys = { -"times": PackedFloat32Array(0, 0.25, 0.416667, 0.583333, 0.75, 0.833333), -"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1), -"update": 0, -"values": [Color(1, 1, 1, 1), Color(0, 0.291333, 0.92, 0.705882), Color(1, 0, 0, 0.917647), Color(0.3625, 1, 0.15, 0.552941), Color(0.685, 0.3, 1, 0.839216), Color(1, 1, 1, 1)] -} -tracks/6/type = "value" -tracks/6/imported = false -tracks/6/enabled = true -tracks/6/path = NodePath("GPUParticles3D:emitting") -tracks/6/interp = 1 -tracks/6/loop_wrap = true -tracks/6/keys = { -"times": PackedFloat32Array(0, 0.583333, 0.666667), -"transitions": PackedFloat32Array(1, 1, 1), -"update": 1, -"values": [false, false, true] -} - -[sub_resource type="Animation" id="Animation_3sdh3"] -resource_name = "teleport in" -step = 0.0833333 -tracks/0/type = "value" -tracks/0/imported = false -tracks/0/enabled = true -tracks/0/path = NodePath("Sprite3D/SubViewportContainer/SubViewport/AnimatedSprite:frame") -tracks/0/interp = 1 -tracks/0/loop_wrap = true -tracks/0/keys = { -"times": PackedFloat32Array(0, 0.666667), -"transitions": PackedFloat32Array(1, 1), -"update": 0, -"values": [0, 10] -} -tracks/1/type = "value" -tracks/1/imported = false -tracks/1/enabled = true -tracks/1/path = NodePath("Sprite3D:transparency") -tracks/1/interp = 1 -tracks/1/loop_wrap = true -tracks/1/keys = { -"times": PackedFloat32Array(0, 0.416667), -"transitions": PackedFloat32Array(1, 1), -"update": 0, -"values": [1.0, 0.0] -} -tracks/2/type = "value" -tracks/2/imported = false -tracks/2/enabled = true -tracks/2/path = NodePath("Sprite3D:scale:x") -tracks/2/interp = 1 -tracks/2/loop_wrap = true -tracks/2/keys = { -"times": PackedFloat32Array(0, 0.416667, 0.5, 0.583333), -"transitions": PackedFloat32Array(1, 1, 1, 1), -"update": 0, -"values": [1.5, Vector3(0, -8.54, 0), Vector3(0, 14.05, 0), Vector3(0, -13.51, 0)] -} -tracks/3/type = "value" -tracks/3/imported = false -tracks/3/enabled = true -tracks/3/path = NodePath("Sprite3D:position") -tracks/3/interp = 1 -tracks/3/loop_wrap = true -tracks/3/keys = { -"times": PackedFloat32Array(0), -"transitions": PackedFloat32Array(1), -"update": 0, -"values": [Vector3(0, 0, 0)] -} -tracks/4/type = "value" -tracks/4/imported = false -tracks/4/enabled = true -tracks/4/path = NodePath("Sprite3D:scale") -tracks/4/interp = 1 -tracks/4/loop_wrap = true -tracks/4/keys = { -"times": PackedFloat32Array(0, 0.0833333, 0.166667, 0.25, 0.416667, 0.583333, 0.666667), -"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1, 1), -"update": 0, -"values": [Vector3(1.005, 0.005, 1.5), Vector3(0.255, -5.205, 1.5), Vector3(0.313, -0.617, 1.5), Vector3(6.281, -0.15, 1.5), Vector3(0.723, 1.868, 1.5), Vector3(3.44, -0.22, 1.5), Vector3(1.5, 1.5, 1.5)] -} -tracks/5/type = "value" -tracks/5/imported = false -tracks/5/enabled = true -tracks/5/path = NodePath("Sprite3D:modulate") -tracks/5/interp = 1 -tracks/5/loop_wrap = true -tracks/5/keys = { -"times": PackedFloat32Array(0.333333, 0.416667, 0.583333, 0.666667), -"transitions": PackedFloat32Array(1, 1, 1, 1), -"update": 0, -"values": [Color(1, 1, 1, 1), Color(0.3625, 1, 0.15, 0.552941), Color(0.685, 0.3, 1, 0.839216), Color(1, 1, 1, 1)] -} -tracks/6/type = "value" -tracks/6/imported = false -tracks/6/enabled = true -tracks/6/path = NodePath("Sprite3D/SubViewportContainer/SubViewport/AnimatedSprite:modulate") -tracks/6/interp = 1 -tracks/6/loop_wrap = true -tracks/6/keys = { -"times": PackedFloat32Array(0, 0.5, 0.666667), -"transitions": PackedFloat32Array(1, 1, 1), -"update": 0, -"values": [Color(1, 1, 1, 1), Color(100, 100, 100, 1), Color(1, 1, 1, 1)] -} - -[sub_resource type="Animation" id="Animation_jbhro"] -resource_name = "stop_walk_front" -length = 1.41668 -step = 0.0833333 -tracks/0/type = "value" -tracks/0/imported = false -tracks/0/enabled = true -tracks/0/path = NodePath("Sprite3D/SubViewportContainer/SubViewport/AnimatedSprite:animation") -tracks/0/interp = 1 -tracks/0/loop_wrap = true -tracks/0/keys = { -"times": PackedFloat32Array(0), -"transitions": PackedFloat32Array(1), -"update": 1, -"values": [&"idle_front_walk"] -} -tracks/1/type = "value" -tracks/1/imported = false -tracks/1/enabled = true -tracks/1/path = NodePath("Sprite3D/SubViewportContainer/SubViewport/AnimatedSprite:frame") -tracks/1/interp = 1 -tracks/1/loop_wrap = true -tracks/1/keys = { -"times": PackedFloat32Array(0, 1.41667), -"transitions": PackedFloat32Array(1, 1), -"update": 0, -"values": [0, 17] -} -tracks/2/type = "value" -tracks/2/imported = false -tracks/2/enabled = true -tracks/2/path = NodePath("Sprite3D:position") -tracks/2/interp = 1 -tracks/2/loop_wrap = true -tracks/2/keys = { -"times": PackedFloat32Array(0, 0.166667, 0.416667), -"transitions": PackedFloat32Array(1, 5.46418, 1), -"update": 0, -"values": [Vector3(0, 0, 0), Vector3(0, 1.5, 0), Vector3(0, 0, 0)] -} -tracks/3/type = "value" -tracks/3/imported = false -tracks/3/enabled = true -tracks/3/path = NodePath(".:CanMove") -tracks/3/interp = 1 -tracks/3/loop_wrap = true -tracks/3/keys = { -"times": PackedFloat32Array(0, 0.0833333, 0.416667), -"transitions": PackedFloat32Array(1, 1, 1), -"update": 1, -"values": [false, true, false] -} - [sub_resource type="Animation" id="Animation_keq07"] resource_name = "stop_back_walk" length = 1.41668 @@ -3120,6 +2890,236 @@ tracks/4/keys = { "values": [false, true, false] } +[sub_resource type="Animation" id="Animation_jbhro"] +resource_name = "stop_walk_front" +length = 1.41668 +step = 0.0833333 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("Sprite3D/SubViewportContainer/SubViewport/AnimatedSprite:animation") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 1, +"values": [&"idle_front_walk"] +} +tracks/1/type = "value" +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/path = NodePath("Sprite3D/SubViewportContainer/SubViewport/AnimatedSprite:frame") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/keys = { +"times": PackedFloat32Array(0, 1.41667), +"transitions": PackedFloat32Array(1, 1), +"update": 0, +"values": [0, 17] +} +tracks/2/type = "value" +tracks/2/imported = false +tracks/2/enabled = true +tracks/2/path = NodePath("Sprite3D:position") +tracks/2/interp = 1 +tracks/2/loop_wrap = true +tracks/2/keys = { +"times": PackedFloat32Array(0, 0.166667, 0.416667), +"transitions": PackedFloat32Array(1, 5.46418, 1), +"update": 0, +"values": [Vector3(0, 0, 0), Vector3(0, 1.5, 0), Vector3(0, 0, 0)] +} +tracks/3/type = "value" +tracks/3/imported = false +tracks/3/enabled = true +tracks/3/path = NodePath(".:CanMove") +tracks/3/interp = 1 +tracks/3/loop_wrap = true +tracks/3/keys = { +"times": PackedFloat32Array(0, 0.0833333, 0.416667), +"transitions": PackedFloat32Array(1, 1, 1), +"update": 1, +"values": [false, true, false] +} + +[sub_resource type="Animation" id="Animation_6dej3"] +resource_name = "teleport" +length = 0.833341 +step = 0.0833333 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("Sprite3D/SubViewportContainer/SubViewport/AnimatedSprite:animation") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 1, +"values": [&"teleport"] +} +tracks/1/type = "value" +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/path = NodePath("Sprite3D/SubViewportContainer/SubViewport/AnimatedSprite:frame") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/keys = { +"times": PackedFloat32Array(0, 0.833333), +"transitions": PackedFloat32Array(1, 1), +"update": 0, +"values": [0, 10] +} +tracks/2/type = "value" +tracks/2/imported = false +tracks/2/enabled = true +tracks/2/path = NodePath("Sprite3D:scale:x") +tracks/2/interp = 1 +tracks/2/loop_wrap = true +tracks/2/keys = { +"times": PackedFloat32Array(0, 0.583333, 0.666667, 0.75), +"transitions": PackedFloat32Array(1, 1, 1, 1), +"update": 0, +"values": [1.5, Vector3(0, -8.54, 0), Vector3(0, 14.05, 0), Vector3(0, -13.51, 0)] +} +tracks/3/type = "value" +tracks/3/imported = false +tracks/3/enabled = true +tracks/3/path = NodePath("Sprite3D:position") +tracks/3/interp = 1 +tracks/3/loop_wrap = true +tracks/3/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [Vector3(0, 0, 0)] +} +tracks/4/type = "value" +tracks/4/imported = false +tracks/4/enabled = true +tracks/4/path = NodePath("Sprite3D:scale") +tracks/4/interp = 1 +tracks/4/loop_wrap = true +tracks/4/keys = { +"times": PackedFloat32Array(0.25, 0.416667, 0.583333, 0.75, 0.833333), +"transitions": PackedFloat32Array(1, 1, 1, 1, 1), +"update": 0, +"values": [Vector3(1.5, 1.5, 1.5), Vector3(1.5, -4.765, 1.5), Vector3(7.31, 0.66, 1.5), Vector3(0.397, 2.422, 1.5), Vector3(1.005, 0.005, 1.5)] +} +tracks/5/type = "value" +tracks/5/imported = false +tracks/5/enabled = true +tracks/5/path = NodePath("Sprite3D:modulate") +tracks/5/interp = 1 +tracks/5/loop_wrap = true +tracks/5/keys = { +"times": PackedFloat32Array(0, 0.25, 0.416667, 0.583333, 0.75, 0.833333), +"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1), +"update": 0, +"values": [Color(1, 1, 1, 1), Color(0, 0.291333, 0.92, 0.705882), Color(1, 0, 0, 0.917647), Color(0.3625, 1, 0.15, 0.552941), Color(0.685, 0.3, 1, 0.839216), Color(1, 1, 1, 1)] +} +tracks/6/type = "value" +tracks/6/imported = false +tracks/6/enabled = true +tracks/6/path = NodePath("GPUParticles3D:emitting") +tracks/6/interp = 1 +tracks/6/loop_wrap = true +tracks/6/keys = { +"times": PackedFloat32Array(0, 0.583333, 0.666667), +"transitions": PackedFloat32Array(1, 1, 1), +"update": 1, +"values": [false, false, true] +} + +[sub_resource type="Animation" id="Animation_3sdh3"] +resource_name = "teleport in" +step = 0.0833333 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("Sprite3D/SubViewportContainer/SubViewport/AnimatedSprite:frame") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0, 0.666667), +"transitions": PackedFloat32Array(1, 1), +"update": 0, +"values": [0, 10] +} +tracks/1/type = "value" +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/path = NodePath("Sprite3D:transparency") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/keys = { +"times": PackedFloat32Array(0, 0.416667), +"transitions": PackedFloat32Array(1, 1), +"update": 0, +"values": [1.0, 0.0] +} +tracks/2/type = "value" +tracks/2/imported = false +tracks/2/enabled = true +tracks/2/path = NodePath("Sprite3D:scale:x") +tracks/2/interp = 1 +tracks/2/loop_wrap = true +tracks/2/keys = { +"times": PackedFloat32Array(0, 0.416667, 0.5, 0.583333), +"transitions": PackedFloat32Array(1, 1, 1, 1), +"update": 0, +"values": [1.5, Vector3(0, -8.54, 0), Vector3(0, 14.05, 0), Vector3(0, -13.51, 0)] +} +tracks/3/type = "value" +tracks/3/imported = false +tracks/3/enabled = true +tracks/3/path = NodePath("Sprite3D:position") +tracks/3/interp = 1 +tracks/3/loop_wrap = true +tracks/3/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [Vector3(0, 0, 0)] +} +tracks/4/type = "value" +tracks/4/imported = false +tracks/4/enabled = true +tracks/4/path = NodePath("Sprite3D:scale") +tracks/4/interp = 1 +tracks/4/loop_wrap = true +tracks/4/keys = { +"times": PackedFloat32Array(0, 0.0833333, 0.166667, 0.25, 0.416667, 0.583333, 0.666667), +"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1, 1), +"update": 0, +"values": [Vector3(1.005, 0.005, 1.5), Vector3(0.255, -5.205, 1.5), Vector3(0.313, -0.617, 1.5), Vector3(6.281, -0.15, 1.5), Vector3(0.723, 1.868, 1.5), Vector3(3.44, -0.22, 1.5), Vector3(1.5, 1.5, 1.5)] +} +tracks/5/type = "value" +tracks/5/imported = false +tracks/5/enabled = true +tracks/5/path = NodePath("Sprite3D:modulate") +tracks/5/interp = 1 +tracks/5/loop_wrap = true +tracks/5/keys = { +"times": PackedFloat32Array(0.333333, 0.416667, 0.583333, 0.666667), +"transitions": PackedFloat32Array(1, 1, 1, 1), +"update": 0, +"values": [Color(1, 1, 1, 1), Color(0.3625, 1, 0.15, 0.552941), Color(0.685, 0.3, 1, 0.839216), Color(1, 1, 1, 1)] +} +tracks/6/type = "value" +tracks/6/imported = false +tracks/6/enabled = true +tracks/6/path = NodePath("Sprite3D/SubViewportContainer/SubViewport/AnimatedSprite:modulate") +tracks/6/interp = 1 +tracks/6/loop_wrap = true +tracks/6/keys = { +"times": PackedFloat32Array(0, 0.5, 0.666667), +"transitions": PackedFloat32Array(1, 1, 1), +"update": 0, +"values": [Color(1, 1, 1, 1), Color(100, 100, 100, 1), Color(1, 1, 1, 1)] +} + [sub_resource type="AnimationLibrary" id="AnimationLibrary_46p8q"] _data = { &"RESET": SubResource("Animation_46p8q"), diff --git a/Zennysoft.Game.Ma/src/game/Game.cs b/Zennysoft.Game.Ma/src/game/Game.cs index 7c349c66..83c72b9c 100644 --- a/Zennysoft.Game.Ma/src/game/Game.cs +++ b/Zennysoft.Game.Ma/src/game/Game.cs @@ -60,38 +60,29 @@ public partial class Game : Node3D, IGame public RescuedItemDatabase RescuedItems { get; set; } = default!; + public ItemDatabase ItemDatabase { get; private set; } + public QuestData QuestData { get; private set; } private EffectService _effectService; + private ItemReroller _itemReroller; private IInstantiator _instantiator; - private Player _player; - private Map _map; + private IPlayer _player; + private IMap _map; public Game() - { - QuestData = new QuestData(); - } - - public void Setup() { _container = new SimpleInjector.Container(); Module.Bootstrap(_container); - _instantiator = new Instantiator(GetTree()); - _player = _instantiator.LoadAndInstantiate("res://src/player/Player.tscn"); - PauseContainer.AddChild(_player); - - _map = _instantiator.LoadAndInstantiate("res://src/map/Map.tscn"); - PauseContainer.AddChild(_map); - GameRepo = _container.GetInstance(); GameState = _container.GetInstance(); - GameState.Set(GameRepo); - GameState.Set(_player); - GameState.Set(_map); - GameState.Set(InGameUI); + + QuestData = new QuestData(); RescuedItems = new RescuedItemDatabase(); + ItemDatabase = ItemDatabase.Instance; + _itemReroller = new ItemReroller(ItemDatabase); GameChunk = new SaveChunk( (chunk) => @@ -111,15 +102,12 @@ public partial class Game : Node3D, IGame }, onLoad: (chunk, data) => - { - RescuedItems = data.RescuedItems; - QuestData = data.QuestData; - } + { + RescuedItems = data.RescuedItems; + QuestData = data.QuestData; + } ); - } - public void OnResolved() - { var saveFileManager = _container.GetInstance(); SaveFile = new SaveFile( root: GameChunk, @@ -139,14 +127,129 @@ public partial class Game : Node3D, IGame return null; } ); + } + + public void Setup() + { + _instantiator = new Instantiator(GetTree()); + _player = _instantiator.LoadAndInstantiate("res://src/player/Player.tscn"); + _map = _instantiator.LoadAndInstantiate("res://src/map/Map.tscn"); + PauseContainer.AddChild((Player)_player); + PauseContainer.AddChild((Map)_map); + } + + public async void OnResolved() + { + await InitializeGame(); + + GameState.Set(GameRepo); + GameState.Set(_player); + GameState.Set(_map); + GameState.Set(InGameUI); + GameRepo.Resume(); + + InGameUI.Show(); + HandleGameLogic(); + GameState.Start(); + this.Provide(); + + InGameUI.UseTeleportPrompt.TeleportToNextFloor += UseTeleportPrompt_TeleportToNextFloor; + InGameUI.UseTeleportPrompt.CloseTeleportPrompt += UseTeleportPrompt_CloseTeleportPrompt; + FloorClearMenu.GoToNextFloor += FloorClearMenu_GoToNextFloor; + FloorClearMenu.Exit += FloorClearMenu_Exit; + FloorClearMenu.TransitionCompleted += FloorClearMenu_TransitionCompleted; + + GameRepo.RestorativePickedUp += GameEventDepot_RestorativePickedUp; + + _player.PlayerDied += GameOver; + DeathMenu.NewGame += OnNewGame; + DeathMenu.QuitGame += OnQuit; + + GameRepo.IsPaused.Sync += IsPaused_Sync; + InGameUI.PlayerInfoUI.Activate(); + + _map.SpawnPointCreated += MovePlayer; + } + + public void LoadExistingGame() => SaveFile.Load().ContinueWith((_) => CallDeferred(nameof(FinishedLoadingSaveFile))); + + public async Task InitializeGame() + { + _player.ResetPlayerData(); + _map.InitializeMapData(); + _effectService = new EffectService(this, _player, _map); + _player.Activate(); + await _map.LoadFloor(); + } + + public async Task Save() => await SaveFile.Save(); + + public void FloorExitReached() => GameState.Input(new GameState.Input.FloorExitEntered()); + + public async Task UseItem(InventoryItem item) + { + if (item.ItemTag == ItemTag.MysteryItem) + item = _itemReroller.RerollItem(item, _player.Inventory); + + switch (item) + { + case ConsumableItem consumableItem: + EnactConsumableItemEffects(consumableItem); + break; + case EffectItem effectItem: + EnactEffectItemEffects(effectItem); + break; + case ThrowableItem throwableItem: + EnactThrowableItemEffects(throwableItem); + break; + } + + await ToSignal(GetTree().CreateTimer(0.3f), "timeout"); + + RemoveItemOrSubtractFromItemCount(item); + } + + public void DropItem(InventoryItem item) + { + var droppedScene = GD.Load("res://src/items/dropped/DroppedItem.tscn"); + var dropped = droppedScene.Instantiate(); + dropped.Item = item; + AddChild(dropped); + dropped.Drop(); + } + + public void ThrowItem(InventoryItem item) + { + var thrownScene = GD.Load("res://src/items/thrown/ThrownItem.tscn"); + var thrown = thrownScene.Instantiate(); + thrown.ItemThatIsThrown = item; + AddChild(thrown); + thrown.Position += new Vector3(0, 1.5f, 0); + thrown.Throw(_effectService); + } + + public IDungeonFloor CurrentFloor => _map.CurrentFloor; + + public void GameOver() + { + _player.Deactivate(); + GameState.Input(new GameState.Input.GameOver()); + } + + public override void _Input(InputEvent @event) + { + if (@event.IsActionPressed(GameInputs.Debug)) + GameState.Input(new GameState.Input.DebugButtonPressed()); + } + + private void HandleGameLogic() + { GameBinding = GameState.Bind(); GameBinding .Handle((in GameState.Output.InitializeGame _) => - { - }) - .Handle((in GameState.Output.LoadGameFromFile _) => { LoadExistingGame(); + InitializeGame(); }) .Handle((in GameState.Output.OpenPauseScreen _) => { @@ -227,146 +330,17 @@ public partial class Game : Node3D, IGame GameRepo.Pause(); DeathMenu.FadeIn(); }); - - GameState.Start(); - this.Provide(); - InGameUI.UseTeleportPrompt.TeleportToNextFloor += UseTeleportPrompt_TeleportToNextFloor; - InGameUI.UseTeleportPrompt.CloseTeleportPrompt += UseTeleportPrompt_CloseTeleportPrompt; - FloorClearMenu.GoToNextFloor += FloorClearMenu_GoToNextFloor; - FloorClearMenu.SaveAndExit += FloorClearMenu_SaveAndExit; - FloorClearMenu.TransitionCompleted += FloorClearMenu_TransitionCompleted; - - GameRepo.RestorativePickedUp += GameEventDepot_RestorativePickedUp; - - DeathMenu.NewGame += OnContinueGame; - DeathMenu.QuitGame += OnQuit; - - GameRepo.IsPaused.Sync += IsPaused_Sync; - - _effectService = new EffectService(this, _player, _map); } -#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed - public void OnReady() - { - InitializeGame(); - SaveFile.Load(); - _map.LoadFloor(); - GameRepo.Resume(); - InGameUI.Show(); - InGameUI.PlayerInfoUI.Activate(); - _player.Activate(); - } -#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed - - private void FloorClearMenu_SaveAndExit() + private void FloorClearMenu_Exit() { _player.Deactivate(); - GameState.Input(new GameState.Input.ReturnToMainMenu()); + _map.ClearMap(); InGameUI.Hide(); } private void FloorClearMenu_GoToNextFloor() => GameState.Input(new GameState.Input.LoadNextFloor()); - public void LoadExistingGame() => SaveFile.Load().ContinueWith((_) => CallDeferred(nameof(FinishedLoadingSaveFile))); - - public void InitializeGame() - { - _map.InitializeMapData(); - } - - public async Task Save() => await SaveFile.Save(); - - public void FloorExitReached() - { - GameState.Input(new GameState.Input.FloorExitEntered()); - } - - public async Task UseItem(InventoryItem item) - { - if (item.ItemTag == ItemTag.MysteryItem) - item = RerollItem(item); - - switch (item) - { - case ConsumableItem consumableItem: - EnactConsumableItemEffects(consumableItem); - break; - case EffectItem effectItem: - EnactEffectItemEffects(effectItem); - break; - case ThrowableItem throwableItem: - EnactThrowableItemEffects(throwableItem); - break; - } - - await ToSignal(GetTree().CreateTimer(0.3f), "timeout"); - - RemoveItemOrSubtractFromItemCount(item); - } - - public void DropItem(InventoryItem item) - { - var droppedScene = GD.Load("res://src/items/dropped/DroppedItem.tscn"); - var dropped = droppedScene.Instantiate(); - dropped.Item = item; - AddChild(dropped); - dropped.Drop(); - } - - public void ThrowItem(InventoryItem item) - { - var thrownScene = GD.Load("res://src/items/thrown/ThrownItem.tscn"); - var thrown = thrownScene.Instantiate(); - thrown.ItemThatIsThrown = item; - AddChild(thrown); - thrown.Position += new Vector3(0, 1.5f, 0); - thrown.Throw(_effectService); - } - - public IDungeonFloor CurrentFloor => _map.CurrentFloor; - - public InventoryItem RerollItem(InventoryItem itemToReroll, bool insertIntoInventory = true) - { - var itemDb = new ItemDatabase(); - - var currentIndex = _player.Inventory.Items.IndexOf(itemToReroll); - - if (insertIntoInventory) - _player.Inventory.Remove(itemToReroll); - - InventoryItem rolledItem = null; - - if (itemToReroll is Weapon weapon) - rolledItem = itemDb.PickItem(weapon); - if (itemToReroll is Armor armor) - rolledItem = itemDb.PickItem(armor); - if (itemToReroll is Accessory accessory) - rolledItem = itemDb.PickItem(accessory); - if (itemToReroll is ThrowableItem throwableItem) - rolledItem = itemDb.PickItem(throwableItem); - if (itemToReroll is EffectItem effectItem) - rolledItem = itemDb.PickItem(effectItem); - if (itemToReroll is ConsumableItem consumableItem) - rolledItem = itemDb.PickItem(consumableItem); - - if (insertIntoInventory) - _player.Inventory.TryInsert(rolledItem, currentIndex); - - return rolledItem; - } - - public void GameOver() - { - GameState.Input(new GameState.Input.GameOver()); - } - - public override void _Input(InputEvent @event) - { - if (@event.IsActionPressed(GameInputs.Debug)) - GameState.Input(new GameState.Input.DebugButtonPressed()); - } - private void DropRestorative(Vector3 vector) { var restorativeScene = GD.Load("res://src/items/restorative/Restorative.tscn"); @@ -490,36 +464,28 @@ public partial class Game : Node3D, IGame GameRepo.RemoveItemFromInventory(item); } + private void MovePlayer(Transform3D spawnPoint) => _player.TeleportPlayer(spawnPoint); + private void OnNewGame() { + SaveFile.Load(); GameState.Input(new GameState.Input.NewGame()); + GameRepo.Resume(); } - private void OnContinueGame() - { - GameState.Input(new GameState.Input.ContinueGame()); - } - - private void OnLoadGame() - { - GameState.Input(new GameState.Input.LoadGame()); - } - - private void OnQuit() - { - } + private void OnQuit() => GetTree().Root.QueueFree(); public void OnExitTree() { InGameUI.UseTeleportPrompt.TeleportToNextFloor -= UseTeleportPrompt_TeleportToNextFloor; InGameUI.UseTeleportPrompt.CloseTeleportPrompt -= UseTeleportPrompt_CloseTeleportPrompt; FloorClearMenu.GoToNextFloor -= FloorClearMenu_GoToNextFloor; - FloorClearMenu.SaveAndExit -= FloorClearMenu_SaveAndExit; + FloorClearMenu.Exit -= FloorClearMenu_Exit; FloorClearMenu.TransitionCompleted -= FloorClearMenu_TransitionCompleted; GameRepo.RestorativePickedUp -= GameEventDepot_RestorativePickedUp; - DeathMenu.NewGame -= OnContinueGame; + DeathMenu.NewGame -= OnNewGame; DeathMenu.QuitGame -= OnQuit; GameRepo.IsPaused.Sync -= IsPaused_Sync; diff --git a/Zennysoft.Game.Ma/src/game/IGame.cs b/Zennysoft.Game.Ma/src/game/IGame.cs index 81a8717e..607637b5 100644 --- a/Zennysoft.Game.Ma/src/game/IGame.cs +++ b/Zennysoft.Game.Ma/src/game/IGame.cs @@ -25,8 +25,6 @@ public interface IGame : IProvide, IProvide, IProvide public void FloorExitReached(); - public InventoryItem RerollItem(InventoryItem itemToReroll, bool insertIntoInventory = true); - public void GameOver(); public Task Save(); diff --git a/Zennysoft.Game.Ma/src/item_rescue/ItemRescue.cs b/Zennysoft.Game.Ma/src/item_rescue/ItemRescue.cs index 502e2f3d..a0a5133c 100644 --- a/Zennysoft.Game.Ma/src/item_rescue/ItemRescue.cs +++ b/Zennysoft.Game.Ma/src/item_rescue/ItemRescue.cs @@ -1,6 +1,7 @@ using Chickensoft.AutoInject; using Chickensoft.Introspection; using Godot; +using Zennysoft.Ma.Adapter; namespace Zennysoft.Game.Ma; diff --git a/Zennysoft.Game.Ma/src/items/EffectService.cs b/Zennysoft.Game.Ma/src/items/EffectService.cs index c8764a78..81cc11a5 100644 --- a/Zennysoft.Game.Ma/src/items/EffectService.cs +++ b/Zennysoft.Game.Ma/src/items/EffectService.cs @@ -91,8 +91,8 @@ public class EffectService if (currentRoom is not MonsterRoom) return; - currentRoom.EnemiesInRoom.ForEach(e => e.HealthComponent.SetHealth(e.HealthComponent.MaximumHP.Value)); - _player.HealthComponent.SetHealth(_player.HealthComponent.MaximumHP.Value); + currentRoom.EnemiesInRoom.ForEach(e => e.HealthComponent.SetCurrentHealth(e.HealthComponent.MaximumHP.Value)); + _player.HealthComponent.SetCurrentHealth(_player.HealthComponent.MaximumHP.Value); } public void AbsorbHPFromAllEnemiesInRoom() @@ -134,7 +134,7 @@ public class EffectService var oldHp = _player.HealthComponent.CurrentHP.Value; var oldVt = _player.VTComponent.CurrentVT.Value; - _player.HealthComponent.SetHealth(oldVt); + _player.HealthComponent.SetCurrentHealth(oldVt); _player.VTComponent.SetVT(oldHp); } diff --git a/Zennysoft.Game.Ma/src/items/Inventory.cs b/Zennysoft.Game.Ma/src/items/Inventory.cs index 4898d722..9e8ee4ff 100644 --- a/Zennysoft.Game.Ma/src/items/Inventory.cs +++ b/Zennysoft.Game.Ma/src/items/Inventory.cs @@ -2,6 +2,7 @@ using Chickensoft.Introspection; using Chickensoft.Serialization; using Godot; +using System; using System.Collections.Generic; using System.Linq; using Zennysoft.Game.Abstractions; @@ -17,6 +18,8 @@ public partial class Inventory : Node, IInventory // TODO: Constants class with export private const int _maxInventorySize = 20; + public event Action BroadcastMessage; + public Inventory() { Items = []; @@ -25,6 +28,20 @@ public partial class Inventory : Node, IInventory [Save("inventory_items")] public List Items { get; private set; } + public bool PickUpItem(InventoryItem item) + { + var isAdded = TryAdd(item); + if (isAdded) + { + BroadcastMessage?.Invoke($"{item.ItemName} picked up."); + item.QueueFree(); + } + else + BroadcastMessage?.Invoke($"Could not pick up {item.ItemName}."); + + return isAdded; + } + public bool TryAdd(InventoryItem inventoryItem) { if (Items.Count >= _maxInventorySize) diff --git a/Zennysoft.Game.Ma/src/items/ItemDatabase.cs b/Zennysoft.Game.Ma/src/items/ItemDatabase.cs index 2d3826cc..3ef1da75 100644 --- a/Zennysoft.Game.Ma/src/items/ItemDatabase.cs +++ b/Zennysoft.Game.Ma/src/items/ItemDatabase.cs @@ -1,4 +1,5 @@ using Godot; +using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; @@ -6,11 +7,16 @@ using Zennysoft.Ma.Adapter; namespace Zennysoft.Game.Ma; -public partial class ItemDatabase : Node +public class ItemDatabase { + private static readonly Lazy lazy = + new Lazy(() => new ItemDatabase()); + + public static ItemDatabase Instance { get { return lazy.Value; } } + public ImmutableList Items { get; set; } - public InventoryItem PickItem(T itemToExclude = null) + public T PickItem(T itemToExclude = null) where T : InventoryItem { var rng = new RandomNumberGenerator(); @@ -27,10 +33,10 @@ public partial class ItemDatabase : Node if (selectedItem is ThrowableItem throwableItem) throwableItem.SetCount(rng.RandiRange(throwableItem.Stats.MinimumCount, throwableItem.Stats.MaximumCount)); - return selectedItem; + return (T)selectedItem; } - public ItemDatabase() + private ItemDatabase() { var database = new List(); var armorResources = DirAccess.GetFilesAt("res://src/items/armor/resources/"); diff --git a/Zennysoft.Game.Ma/src/items/ItemReroller.cs b/Zennysoft.Game.Ma/src/items/ItemReroller.cs new file mode 100644 index 00000000..dacb4b34 --- /dev/null +++ b/Zennysoft.Game.Ma/src/items/ItemReroller.cs @@ -0,0 +1,36 @@ +using Zennysoft.Ma.Adapter; + +namespace Zennysoft.Game.Ma; + +public class ItemReroller +{ + private readonly ItemDatabase _database; + + public ItemReroller(ItemDatabase database) + { + _database = database; + } + + public T RerollItem(T itemToReroll, IInventory inventory, bool insertIntoInventory = true) + where T : InventoryItem + { + var currentIndex = inventory.Items.IndexOf(itemToReroll); + + if (insertIntoInventory) + inventory.Remove(itemToReroll); + + var rolledItem = RerollItemInternal((dynamic)itemToReroll); + + if (insertIntoInventory) + inventory.TryInsert(rolledItem, currentIndex); + + return rolledItem; + } + + private Weapon RerollItemInternal(Weapon itemToReroll) => _database.PickItem(itemToReroll); + private Armor RerollItemInternal(Armor itemToReroll) => _database.PickItem(itemToReroll); + private Accessory RerollItemInternal(Accessory itemToReroll) => _database.PickItem(itemToReroll); + private ConsumableItem RerollItemInternal(ConsumableItem itemToReroll) => _database.PickItem(itemToReroll); + private ThrowableItem RerollItemInternal(ThrowableItem itemToReroll) => _database.PickItem(itemToReroll); + private EffectItem RerollItemInternal(EffectItem itemToReroll) => _database.PickItem(itemToReroll); +} diff --git a/Zennysoft.Game.Ma/src/items/dropped/DroppedItem.cs b/Zennysoft.Game.Ma/src/items/dropped/DroppedItem.cs index af41c4e0..d6f624d1 100644 --- a/Zennysoft.Game.Ma/src/items/dropped/DroppedItem.cs +++ b/Zennysoft.Game.Ma/src/items/dropped/DroppedItem.cs @@ -1,17 +1,10 @@ using Chickensoft.AutoInject; -using Chickensoft.GodotNodeInterfaces; using Chickensoft.Introspection; using Godot; -using Zennysoft.Game.Implementation; using Zennysoft.Ma.Adapter; namespace Zennysoft.Game.Ma; -public interface IDroppedItem : IRigidBody3D -{ - void RescueItem(); -} - [Meta(typeof(IAutoNode))] public partial class DroppedItem : RigidBody3D, IDroppedItem { diff --git a/Zennysoft.Game.Ma/src/items/thrown/ThrownItem.cs b/Zennysoft.Game.Ma/src/items/thrown/ThrownItem.cs index b5ee21f9..0f539c57 100644 --- a/Zennysoft.Game.Ma/src/items/thrown/ThrownItem.cs +++ b/Zennysoft.Game.Ma/src/items/thrown/ThrownItem.cs @@ -7,7 +7,7 @@ using Zennysoft.Ma.Adapter.Entity; namespace Zennysoft.Game.Ma; [Meta(typeof(IAutoNode))] -public partial class ThrownItem : RigidBody3D +public partial class ThrownItem : RigidBody3D, IThrownItem { public override void _Notification(int what) => this.Notify(what); @@ -15,9 +15,10 @@ public partial class ThrownItem : RigidBody3D [Dependency] public IGame Game => this.DependOn(); - public InventoryItem ItemThatIsThrown; + public InventoryItem ItemThatIsThrown { get; set; } private EffectService _effectService; + private ItemReroller _itemReroller; [Node] public Sprite2D Sprite { get; set; } = default!; @@ -31,7 +32,7 @@ public partial class ThrownItem : RigidBody3D Sprite.Texture = ItemThatIsThrown.GetTexture(); AddCollisionExceptionWith((Node)Player); Collision.SetCollisionLayerValue(3, false); - + _itemReroller = new ItemReroller(ItemDatabase.Instance); } private void Collision_AreaEntered(Area3D area) @@ -102,14 +103,14 @@ public partial class ThrownItem : RigidBody3D private void CalculateEffect(IEnemy enemy) { if (ItemThatIsThrown.ItemTag == ItemTag.MysteryItem) - ItemThatIsThrown = Game.RerollItem(ItemThatIsThrown, false); + ItemThatIsThrown = _itemReroller.RerollItem(ItemThatIsThrown, Player.Inventory, false); if (ItemThatIsThrown is ThrowableItem throwableItem) { switch (throwableItem.ThrowableItemTag) { case ThrowableItemTag.LowerTargetTo1HP: - enemy.HealthComponent.SetHealth(1); + enemy.HealthComponent.SetCurrentHealth(1); break; case ThrowableItemTag.TeleportToRandomLocation: _effectService.TeleportToRandomRoom(enemy); diff --git a/Zennysoft.Game.Ma/src/map/IMap.cs b/Zennysoft.Game.Ma/src/map/IMap.cs index 401d5598..064ac9c8 100644 --- a/Zennysoft.Game.Ma/src/map/IMap.cs +++ b/Zennysoft.Game.Ma/src/map/IMap.cs @@ -1,6 +1,7 @@ using Chickensoft.Collections; using Chickensoft.GodotNodeInterfaces; using Godot; +using System; using System.Threading.Tasks; namespace Zennysoft.Game.Ma; @@ -11,6 +12,8 @@ public interface IMap : INode3D Task LoadFloor(string sceneName); + void ClearMap(); + IDungeonFloor CurrentFloor { get; } Transform3D GetPlayerSpawnPosition(); @@ -20,4 +23,6 @@ public interface IMap : INode3D void InitializeMapData(); public AutoProp CurrentFloorNumber { get; } + + public event Action SpawnPointCreated; } diff --git a/Zennysoft.Game.Ma/src/map/Map.cs b/Zennysoft.Game.Ma/src/map/Map.cs index 856f7ef1..c054d7a6 100644 --- a/Zennysoft.Game.Ma/src/map/Map.cs +++ b/Zennysoft.Game.Ma/src/map/Map.cs @@ -1,12 +1,10 @@ using Chickensoft.AutoInject; using Chickensoft.Collections; using Chickensoft.Introspection; -using Chickensoft.SaveFileBuilder; using Godot; -using Godot.Collections; +using System; using System.Linq; using System.Threading.Tasks; -using Zennysoft.Ma.Adapter; namespace Zennysoft.Game.Ma; @@ -18,9 +16,6 @@ public partial class Map : Node3D, IMap [Dependency] public IGame Game => this.DependOn(); - [Dependency] - public IPlayer Player => this.DependOn(); - [Node] public Node MapOrder { get; set; } = default!; @@ -33,10 +28,11 @@ public partial class Map : Node3D, IMap private readonly string _floorFilePath = @"res://src/map/dungeon/floors/"; + public event Action SpawnPointCreated; + public void OnResolved() { this.Provide(); - InitializeMapData(); } @@ -66,13 +62,20 @@ public partial class Map : Node3D, IMap public async Task LoadFloor(string sceneName) { AnimationPlayer.CallDeferred(AnimationPlayer.MethodName.Play, "fade_out"); - ClearCurrentMap(); + ClearMap(); var newFloor = await LoadNewFloor(sceneName); AddChild(newFloor); InitializeFloor(newFloor); AnimationPlayer.CallDeferred(AnimationPlayer.MethodName.Play, ("fade_in")); } + public void ClearMap() + { + AnimationPlayer.CallDeferred(AnimationPlayer.MethodName.Play, "fade_out"); + CurrentFloor?.CallDeferred(MethodName.QueueFree, []); + SpawnPointCreated?.Invoke(new Transform3D(Basis.Identity, new Vector3(-999, -999, -999))); + } + private void InitializeFloor(Node newFloor) { CurrentFloor = (IDungeonFloor)newFloor; @@ -92,16 +95,10 @@ public partial class Map : Node3D, IMap return result; } - private void ClearCurrentMap() - { - CurrentFloor?.CallDeferred(MethodName.QueueFree, []); - Player.TeleportPlayer(new Transform3D(Basis.Identity, new Vector3(-999, -999, -999))); - } - private void SetupDungeonFloor() { CurrentFloor.InitializeDungeon(); var transform = GetPlayerSpawnPosition(); - Player.TeleportPlayer(transform); + SpawnPointCreated?.Invoke(transform); } } diff --git a/Zennysoft.Game.Ma/src/map/dungeon/code/MonsterRoom.cs b/Zennysoft.Game.Ma/src/map/dungeon/code/MonsterRoom.cs index 78bbfda4..98863aca 100644 --- a/Zennysoft.Game.Ma/src/map/dungeon/code/MonsterRoom.cs +++ b/Zennysoft.Game.Ma/src/map/dungeon/code/MonsterRoom.cs @@ -56,7 +56,7 @@ public partial class MonsterRoom : DungeonRoom rng.Randomize(); var numberOfItemsToSpawn = rng.RandiRange(1, itemSpawnPoints.Count); itemSpawnPoints.Shuffle(); - var database = new ItemDatabase(); + var database = ItemDatabase.Instance; foreach (var spawnPoint in itemSpawnPoints.Cast()) { if (numberOfItemsToSpawn <= 0) diff --git a/Zennysoft.Game.Ma/src/player/Player.cs b/Zennysoft.Game.Ma/src/player/Player.cs index 0f12813c..27133d95 100644 --- a/Zennysoft.Game.Ma/src/player/Player.cs +++ b/Zennysoft.Game.Ma/src/player/Player.cs @@ -1,23 +1,23 @@ using Chickensoft.AutoInject; using Chickensoft.GodotNodeInterfaces; using Chickensoft.Introspection; -using Chickensoft.SaveFileBuilder; using Godot; using SimpleInjector; +using System; using Zennysoft.Ma.Adapter; using Zennysoft.Ma.Adapter.Entity; namespace Zennysoft.Game.Ma; [Meta(typeof(IAutoNode))] -public partial class Player : CharacterBody3D, IPlayer +public partial class Player : CharacterBody3D, IPlayer, IProvide { #region Dependency Injection public override void _Notification(int what) => this.Notify(what); - private PlayerLogic.IBinding PlayerBinding { get; set; } = default!; + IPlayer IProvide.Value() => this; - [Dependency] private IGameRepo _gameRepo => this.DependOn(() => new GameRepo()); + private PlayerLogic.IBinding PlayerBinding { get; set; } = default!; #endregion public IHealthComponent HealthComponent { get; private set; } @@ -40,16 +40,12 @@ public partial class Player : CharacterBody3D, IPlayer public IInventory Inventory { get; private set; } = default!; + public event Action PlayerDied; + private PlayerLogic.Settings Settings { get; set; } = default!; private IPlayerLogic PlayerLogic { get; set; } = default!; - - #region Dependencies - [Dependency] - public IGame Game => this.DependOn(); - #endregion - #region Exports [ExportGroup("Movement")] [Export(PropertyHint.Range, "0, 100, 0.1")] @@ -99,9 +95,17 @@ public partial class Player : CharacterBody3D, IPlayer private float _knockbackStrength = 0.0f; private Vector3 _knockbackDirection = Vector3.Zero; - #region Initialization - public Player() + private ItemReroller _itemReroller; + + public void Initialize() { + var container = new SimpleInjector.Container(); + container.Register(Lifestyle.Singleton); + + PlayerLogic = container.GetInstance(); + PlayerLogic.Set(this as IPlayer); + PlayerLogic.Set(Settings); + Inventory = new Inventory(); HealthComponent = new HealthComponent(InitialHP); VTComponent = new VTComponent(InitialVT); @@ -110,21 +114,9 @@ public partial class Player : CharacterBody3D, IPlayer ExperiencePointsComponent = new ExperiencePointsComponent(); LuckComponent = new LuckComponent(InitialLuck); EquipmentComponent = new EquipmentComponent(); - } - public void Setup() - { - var container = new SimpleInjector.Container(); - container.Register(Lifestyle.Singleton); + _itemReroller = new ItemReroller(ItemDatabase.Instance); - PlayerLogic = container.GetInstance(); - PlayerLogic.Set(this as IPlayer); - PlayerLogic.Set(Settings); - PlayerLogic.Set(_gameRepo); - } - - public void OnResolved() - { Settings = new PlayerLogic.Settings() { RotationSpeed = RotationSpeed, MoveSpeed = MoveSpeed, Acceleration = Acceleration }; PlayerBinding = PlayerLogic.Bind(); @@ -142,6 +134,23 @@ public partial class Player : CharacterBody3D, IPlayer this.Provide(); } + public void ResetPlayerData() + { + foreach (var item in Inventory.Items) + Inventory.Remove(item); + + HealthComponent.Reset(); + VTComponent.Reset(); + AttackComponent.Reset(); + DefenseComponent.Reset(); + ExperiencePointsComponent.Reset(); + LuckComponent.Reset(); + EquipmentComponent.Reset(); + + HealthTimer.Timeout += OnHealthTimerTimeout; + } + + #region Initialization public void OnReady() { Hitbox.AreaEntered += Hitbox_AreaEntered; @@ -149,7 +158,6 @@ public partial class Player : CharacterBody3D, IPlayer SwordSlashAnimation.Position = GetViewport().GetVisibleRect().Size / 2; HealthComponent.HealthReachedZero += Die; HealthTimer.WaitTime = _healthTimerWaitTime; - HealthTimer.Timeout += OnHealthTimerTimeout; SetProcessInput(false); SetPhysicsProcess(false); } @@ -210,7 +218,7 @@ public partial class Player : CharacterBody3D, IPlayer SwordSlashAnimation.Stop(); SetProcessInput(false); SetPhysicsProcess(false); - Game.GameOver(); + PlayerDied?.Invoke(); } public override void _Input(InputEvent @event) @@ -233,7 +241,7 @@ public partial class Player : CharacterBody3D, IPlayer { if (equipable.ItemTag == ItemTag.MysteryItem) { - var rerolledItem = Game.RerollItem(equipable) as EquipableItem; + var rerolledItem = _itemReroller.RerollItem(equipable, Inventory); Equip(rerolledItem); return; } @@ -269,7 +277,6 @@ public partial class Player : CharacterBody3D, IPlayer if (PlayerIsHittingGeometry()) { AnimationPlayer.Play("hit_wall"); - _gameRepo.OnPlayerAttackedWall(); } else { @@ -291,7 +298,6 @@ public partial class Player : CharacterBody3D, IPlayer var attackSpeed = ((Weapon)EquipmentComponent.EquippedWeapon.Value).AttackSpeed; AnimationPlayer.SetSpeedScale((float)attackSpeed); AnimationPlayer.Play("attack"); - _gameRepo.OnPlayerAttack(); } private void OnExitTree() @@ -370,40 +376,25 @@ public partial class Player : CharacterBody3D, IPlayer { if (area.GetParent() is InventoryItem inventoryItem) { - var isAdded = Inventory.TryAdd(inventoryItem); + var isAdded = Inventory.PickUpItem(inventoryItem); if (isAdded) - { - _gameRepo.AnnounceMessageOnMainScreen($"{inventoryItem.ItemName} picked up."); inventoryItem.QueueFree(); - } - else - _gameRepo.AnnounceMessageOnMainScreen($"Could not pick up {inventoryItem.ItemName}."); } if (area.GetParent() is DroppedItem droppedItem) { - var isAdded = Inventory.TryAdd(droppedItem.Item); + var isAdded = Inventory.PickUpItem(droppedItem.Item); if (isAdded) - { - _gameRepo.AnnounceMessageOnMainScreen($"{droppedItem.Item.ItemName} picked up."); droppedItem.QueueFree(); - } - else - _gameRepo.AnnounceMessageOnMainScreen($"Could not pick up {droppedItem.Item.ItemName}."); } if (area.GetParent() is ThrownItem thrownItem) { - var isAdded = Inventory.TryAdd(thrownItem.ItemThatIsThrown); + var isAdded = Inventory.PickUpItem(thrownItem.ItemThatIsThrown); if (isAdded) - { - _gameRepo.AnnounceMessageOnMainScreen($"{thrownItem.ItemThatIsThrown.ItemName} picked up."); thrownItem.QueueFree(); - } - else - _gameRepo.AnnounceMessageOnMainScreen($"Could not pick up {thrownItem.ItemThatIsThrown.ItemName}."); } if (area.GetParent() is Restorative restorative) { - _gameRepo.OnRestorativePickedUp(restorative); + //_gameRepo.OnRestorativePickedUp(restorative); restorative.QueueFree(); } } diff --git a/Zennysoft.Game.Ma/src/quest/QuestTest.cs b/Zennysoft.Game.Ma/src/quest/QuestTest.cs index b03ef82c..fc1e60fc 100644 --- a/Zennysoft.Game.Ma/src/quest/QuestTest.cs +++ b/Zennysoft.Game.Ma/src/quest/QuestTest.cs @@ -20,5 +20,6 @@ public partial class QuestTest : Area3D private void QuestTest_AreaEntered(Area3D area) { Game.QuestData.QuestMarker1 = true; + QueueFree(); } } diff --git a/Zennysoft.Game.Ma/src/ui/death_menu/DeathMenu.cs b/Zennysoft.Game.Ma/src/ui/death_menu/DeathMenu.cs index 1827d211..720ff8e9 100644 --- a/Zennysoft.Game.Ma/src/ui/death_menu/DeathMenu.cs +++ b/Zennysoft.Game.Ma/src/ui/death_menu/DeathMenu.cs @@ -2,7 +2,6 @@ using Chickensoft.AutoInject; using Chickensoft.GodotNodeInterfaces; using Chickensoft.Introspection; using Godot; -using Zennysoft.Ma.Adapter; namespace Zennysoft.Game.Ma; diff --git a/Zennysoft.Game.Ma/src/ui/floor_clear/FloorClearMenu.cs b/Zennysoft.Game.Ma/src/ui/floor_clear/FloorClearMenu.cs index 5f9e1889..4cfefd1d 100644 --- a/Zennysoft.Game.Ma/src/ui/floor_clear/FloorClearMenu.cs +++ b/Zennysoft.Game.Ma/src/ui/floor_clear/FloorClearMenu.cs @@ -9,7 +9,7 @@ public interface IFloorClearMenu : IControl { event FloorClearMenu.GoToNextFloorEventHandler GoToNextFloor; - event FloorClearMenu.SaveAndExitEventHandler SaveAndExit; + event FloorClearMenu.ExitEventHandler Exit; event FloorClearMenu.TransitionCompletedEventHandler TransitionCompleted; @@ -27,7 +27,7 @@ public partial class FloorClearMenu : Control, IFloorClearMenu [Node] public Button ContinueButton { get; set; } = default!; - [Node] public Button SaveAndExitButton { get; set; } = default!; + [Node] public Button ExitButton { get; set; } = default!; public void FadeIn() => AnimationPlayer.Play("fade_in"); @@ -38,27 +38,27 @@ public partial class FloorClearMenu : Control, IFloorClearMenu [Signal] public delegate void GoToNextFloorEventHandler(); [Signal] - public delegate void SaveAndExitEventHandler(); + public delegate void ExitEventHandler(); public void OnResolved() { AnimationPlayer.AnimationFinished += AnimationPlayer_AnimationFinished; ContinueButton.Pressed += ContinueButton_Pressed; - SaveAndExitButton.Pressed += SaveAndExitButton_Pressed; + ExitButton.Pressed += ExitButton_Pressed; } - private void SaveAndExitButton_Pressed() + private void ExitButton_Pressed() { ContinueButton.Disabled = true; - SaveAndExitButton.Disabled = true; + ExitButton.Disabled = true; FadeOut(); - EmitSignal(SignalName.SaveAndExit); + EmitSignal(SignalName.Exit); } private void ContinueButton_Pressed() { ContinueButton.Disabled = true; - SaveAndExitButton.Disabled = true; + ExitButton.Disabled = true; EmitSignal(SignalName.GoToNextFloor); } @@ -67,7 +67,7 @@ public partial class FloorClearMenu : Control, IFloorClearMenu if (animName == "fade_in") { ContinueButton.Disabled = false; - SaveAndExitButton.Disabled = false; + ExitButton.Disabled = false; ContinueButton.CallDeferred(MethodName.GrabFocus); } if (animName == "fade_out") diff --git a/Zennysoft.Game.Ma/src/ui/floor_clear/FloorClearMenu.tscn b/Zennysoft.Game.Ma/src/ui/floor_clear/FloorClearMenu.tscn index 071f5fda..a59109c1 100644 --- a/Zennysoft.Game.Ma/src/ui/floor_clear/FloorClearMenu.tscn +++ b/Zennysoft.Game.Ma/src/ui/floor_clear/FloorClearMenu.tscn @@ -109,7 +109,7 @@ layout_mode = 2 focus_neighbor_left = NodePath(".") focus_neighbor_top = NodePath(".") focus_neighbor_right = NodePath(".") -focus_neighbor_bottom = NodePath("../SaveAndExitButton") +focus_neighbor_bottom = NodePath("../ExitButton") theme_override_colors/font_color = Color(0.737255, 0.705882, 0.690196, 1) theme_override_colors/font_focus_color = Color(1, 0.94902, 0, 1) theme_override_fonts/font = ExtResource("2_xk0dh") @@ -120,7 +120,7 @@ button_mask = 0 text = "Continue" flat = true -[node name="SaveAndExitButton" type="Button" parent="CenterContainer/VBoxContainer"] +[node name="ExitButton" type="Button" parent="CenterContainer/VBoxContainer"] unique_name_in_owner = true custom_minimum_size = Vector2(200, 50) layout_mode = 2 @@ -135,5 +135,5 @@ theme_override_font_sizes/font_size = 36 theme_override_styles/focus = SubResource("StyleBoxEmpty_cyd1c") theme_override_styles/normal = SubResource("StyleBoxEmpty_4bdva") button_mask = 0 -text = "Save and Exit" +text = "Exit Tower" flat = true diff --git a/Zennysoft.Game.Ma/src/ui/inventory_menu/InventoryMenu.cs b/Zennysoft.Game.Ma/src/ui/inventory_menu/InventoryMenu.cs index cac11b3e..4d4d29a6 100644 --- a/Zennysoft.Game.Ma/src/ui/inventory_menu/InventoryMenu.cs +++ b/Zennysoft.Game.Ma/src/ui/inventory_menu/InventoryMenu.cs @@ -28,8 +28,6 @@ public partial class InventoryMenu : Control, IInventoryMenu [Dependency] public IPlayer Player => this.DependOn(); - [Dependency] public IMap _map => this.DependOn(); - private InventoryPageNumber _currentPageNumber = InventoryPageNumber.FirstPage; private string ITEM_SLOT_SCENE = "res://src/ui/inventory_menu/ItemSlot.tscn"; @@ -62,11 +60,24 @@ public partial class InventoryMenu : Control, IInventoryMenu [Node] public AnimationPlayer AnimationPlayer { get; set; } = default!; #endregion - public void OnReady() + public InventoryMenu() + { + SetProcessInput(false); + SetProcess(false); + } + + public void OnResolved() { UseButton.Pressed += UseButtonPressed; ThrowButton.Pressed += ThrowButtonPressed; DropButton.Pressed += DropButtonPressed; + Player.AttackComponent.CurrentAttack.Sync += AttackSync; + Player.AttackComponent.MaximumAttack.Sync += AttackSync; + Player.EquipmentComponent.EquippedWeapon.Sync += BonusSync; + Player.EquipmentComponent.EquippedArmor.Sync += BonusSync; + Player.EquipmentComponent.EquippedAccessory.Sync += BonusSync; + Player.DefenseComponent.CurrentDefense.Sync += DefenseSync; + Player.DefenseComponent.MaximumDefense.Sync += DefenseSync; } public void OnExitTree() @@ -80,18 +91,6 @@ public partial class InventoryMenu : Control, IInventoryMenu Player.DefenseComponent.MaximumDefense.Sync -= DefenseSync; } - public void OnResolved() - { - SetProcessInput(false); - Player.AttackComponent.CurrentAttack.Sync += AttackSync; - Player.AttackComponent.MaximumAttack.Sync += AttackSync; - Player.EquipmentComponent.EquippedWeapon.Sync += BonusSync; - Player.EquipmentComponent.EquippedArmor.Sync += BonusSync; - Player.EquipmentComponent.EquippedAccessory.Sync += BonusSync; - Player.DefenseComponent.CurrentDefense.Sync += DefenseSync; - Player.DefenseComponent.MaximumDefense.Sync += DefenseSync; - } - public async Task DisplayMessage(string message) { SetProcessInput(false); @@ -125,8 +124,6 @@ public partial class InventoryMenu : Control, IInventoryMenu #pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed public override void _Input(InputEvent @event) { - var inventory = Player.Inventory; - if (@event.IsActionPressed(GameInputs.UiCancel)) { if (UseButton.HasFocus() || DropButton.HasFocus() || ThrowButton.HasFocus()) @@ -145,8 +142,12 @@ public partial class InventoryMenu : Control, IInventoryMenu if (ItemSlots.Length == 0 || UseButton.HasFocus() || DropButton.HasFocus() || ThrowButton.HasFocus()) return; - if (@event.IsActionPressed(GameInputs.UiRight) && _currentPageNumber == InventoryPageNumber.FirstPage && inventory.Items.Count > _itemsPerPage) - ChangeInventoryPage(InventoryPageNumber.SecondPage); + if (@event.IsActionPressed(GameInputs.UiRight) && _currentPageNumber == InventoryPageNumber.FirstPage) + { + var inventory = Player.Inventory; + if (inventory.Items.Count > _itemsPerPage) + ChangeInventoryPage(InventoryPageNumber.SecondPage); + } if (@event.IsActionPressed(GameInputs.UiLeft) && _currentPageNumber == InventoryPageNumber.SecondPage) ChangeInventoryPage(InventoryPageNumber.FirstPage); @@ -186,6 +187,7 @@ public partial class InventoryMenu : Control, IInventoryMenu if (@event.IsActionPressed(GameInputs.InventorySort)) { + var inventory = Player.Inventory; inventory.Sort(Player.EquipmentComponent.EquippedWeapon.Value, Player.EquipmentComponent.EquippedArmor.Value, Player.EquipmentComponent.EquippedAccessory.Value); if (_currentIndex > inventory.Items.Count - 1) _currentIndex = inventory.Items.Count - 1; @@ -357,7 +359,7 @@ public partial class InventoryMenu : Control, IInventoryMenu else { ItemEffectLabel.Text = $"{equippableItem.GetType().Name} equipped."; - Player.EquipmentComponent.Equip(equippableItem); + Player.Equip(equippableItem); itemSlot.SetEquippedSelectedItemStyle(); } diff --git a/Zennysoft.Game.Ma/src/ui/pause_menu/PauseDebugMenu.cs b/Zennysoft.Game.Ma/src/ui/pause_menu/PauseDebugMenu.cs index b4f75f14..ac01f09d 100644 --- a/Zennysoft.Game.Ma/src/ui/pause_menu/PauseDebugMenu.cs +++ b/Zennysoft.Game.Ma/src/ui/pause_menu/PauseDebugMenu.cs @@ -38,7 +38,7 @@ public partial class PauseDebugMenu : Control, IDebugMenu { LoadNextFloorButton.Pressed += LoadNextFloorButton_Pressed; - _itemDatabase = new ItemDatabase(); + _itemDatabase = ItemDatabase.Instance; _spawnableItems = _itemDatabase.Items; _spawnableEnemies = diff --git a/Zennysoft.Game.Ma/src/utils/SceneLoader.cs b/Zennysoft.Game.Ma/src/utils/SceneLoader.cs index 765211cd..25444257 100644 --- a/Zennysoft.Game.Ma/src/utils/SceneLoader.cs +++ b/Zennysoft.Game.Ma/src/utils/SceneLoader.cs @@ -18,6 +18,7 @@ public partial class SceneLoader : Node ResourceLoader.LoadThreadedRequest(sceneToLoad); _sceneToLoad = sceneToLoad; _loading = true; + SetProcess(true); } private void LoadScene()