Rework game over logic and game initialization
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace Zennysoft.Ma.Adapter;
|
||||
|
||||
public interface IAttackComponent
|
||||
public interface IAttackComponent : IEntityComponent
|
||||
{
|
||||
public IAutoProp<int> CurrentAttack { get; }
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace Zennysoft.Ma.Adapter;
|
||||
|
||||
public interface IDefenseComponent
|
||||
public interface IDefenseComponent : IEntityComponent
|
||||
{
|
||||
public IAutoProp<int> CurrentDefense { get; }
|
||||
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Zennysoft.Ma.Adapter;
|
||||
|
||||
public interface IEntityComponent
|
||||
{
|
||||
public void Reset();
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
using Zennysoft.Ma.Adapter.Entity;
|
||||
|
||||
namespace Zennysoft.Ma.Adapter;
|
||||
public interface IEquipmentComponent
|
||||
public interface IEquipmentComponent : IEntityComponent
|
||||
{
|
||||
public IAutoProp<EquipableItem> EquippedWeapon { get; }
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace Zennysoft.Ma.Adapter;
|
||||
|
||||
public interface IExperiencePointsComponent
|
||||
public interface IExperiencePointsComponent : IEntityComponent
|
||||
{
|
||||
public IAutoProp<int> CurrentExp { get; }
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace Zennysoft.Ma.Adapter;
|
||||
|
||||
public interface IHealthComponent
|
||||
public interface IHealthComponent : IEntityComponent
|
||||
{
|
||||
public IAutoProp<int> 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);
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace Zennysoft.Ma.Adapter;
|
||||
|
||||
public interface ILuckComponent
|
||||
public interface ILuckComponent : IEntityComponent
|
||||
{
|
||||
public IAutoProp<int> Luck { get; }
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace Zennysoft.Ma.Adapter;
|
||||
|
||||
public interface IVTComponent
|
||||
public interface IVTComponent : IEntityComponent
|
||||
{
|
||||
public IAutoProp<int> CurrentVT { get; }
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -16,11 +16,6 @@ public partial class GameState
|
||||
OnAttach(() => Get<IGameRepo>().Pause());
|
||||
}
|
||||
|
||||
public Transition On(in Input.ReturnToMainMenu input)
|
||||
{
|
||||
return To<MainMenu>();
|
||||
}
|
||||
|
||||
public Transition On(in Input.UseTeleport input)
|
||||
{
|
||||
Output(new Output.OpenFloorExitScreen());
|
||||
|
||||
@@ -8,7 +8,7 @@ public partial class GameState
|
||||
public partial record State
|
||||
{
|
||||
[Meta, LogicBlock(typeof(State), Diagram = true)]
|
||||
public partial record FloorExitScreen : State, IGet<Input.LoadNextFloor>, IGet<Input.ReturnToMainMenu>
|
||||
public partial record FloorExitScreen : State, IGet<Input.LoadNextFloor>
|
||||
{
|
||||
public FloorExitScreen()
|
||||
{
|
||||
@@ -20,11 +20,6 @@ public partial class GameState
|
||||
Output(new Output.LoadNextFloor());
|
||||
return To<InGame>();
|
||||
}
|
||||
|
||||
public Transition On(in Input.ReturnToMainMenu input)
|
||||
{
|
||||
return To<MainMenu>();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,18 +8,13 @@ public partial class GameState
|
||||
public partial record State
|
||||
{
|
||||
[Meta, LogicBlock(typeof(State), Diagram = true)]
|
||||
public partial record GameOver : State, IGet<Input.ContinueGame>, IGet<Input.ReturnToMainMenu>
|
||||
public partial record GameOver : State, IGet<Input.NewGame>
|
||||
{
|
||||
public Transition On(in Input.ContinueGame input)
|
||||
public Transition On(in Input.NewGame input)
|
||||
{
|
||||
Output(new Output.InitializeGame());
|
||||
return To<InGame>();
|
||||
}
|
||||
|
||||
public Transition On(in Input.ReturnToMainMenu input)
|
||||
{
|
||||
return To<MainMenu>();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<Input.NewGame>, IGet<Input.ContinueGame>, IGet<Input.LoadGame>
|
||||
{
|
||||
public Transition On(in Input.NewGame input)
|
||||
{
|
||||
Output(new Output.InitializeGame());
|
||||
return To<InGame>();
|
||||
}
|
||||
|
||||
public Transition On(in Input.ContinueGame input)
|
||||
{
|
||||
Output(new Output.InitializeGame());
|
||||
Output(new Output.LoadGameFromFile());
|
||||
return To<InGame>();
|
||||
}
|
||||
|
||||
public Transition On(in Input.LoadGame input)
|
||||
{
|
||||
Output(new Output.InitializeGame());
|
||||
Output(new Output.LoadGameFromFile());
|
||||
return To<InGame>();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
9
Zennysoft.Game.Ma.Implementation/Item/IDroppedItem.cs
Normal file
9
Zennysoft.Game.Ma.Implementation/Item/IDroppedItem.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
namespace Zennysoft.Ma.Adapter
|
||||
{
|
||||
public interface IDroppedItem
|
||||
{
|
||||
void RescueItem();
|
||||
|
||||
public InventoryItem Item { get; }
|
||||
}
|
||||
}
|
||||
@@ -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<InventoryItem> 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<string> BroadcastMessage;
|
||||
}
|
||||
|
||||
6
Zennysoft.Game.Ma.Implementation/Item/IThrownItem.cs
Normal file
6
Zennysoft.Game.Ma.Implementation/Item/IThrownItem.cs
Normal file
@@ -0,0 +1,6 @@
|
||||
namespace Zennysoft.Ma.Adapter;
|
||||
|
||||
public interface IThrownItem
|
||||
{
|
||||
public InventoryItem ItemThatIsThrown { get; set; }
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -10,21 +10,23 @@ public class AttackComponent : IAttackComponent
|
||||
|
||||
public IAutoProp<int> MaximumAttack => _maximumAttack;
|
||||
|
||||
public IAutoProp<int> BonusAttack => _bonusAttack;
|
||||
|
||||
public int TotalAttack => CurrentAttack.Value + BonusAttack.Value;
|
||||
|
||||
private readonly AutoProp<int> _currentAttack;
|
||||
|
||||
private readonly AutoProp<int> _maximumAttack;
|
||||
|
||||
private readonly AutoProp<int> _bonusAttack;
|
||||
private readonly int _initialValue;
|
||||
|
||||
public AttackComponent(int attackValue)
|
||||
{
|
||||
_maximumAttack = new AutoProp<int>(attackValue);
|
||||
_currentAttack = new AutoProp<int>(attackValue);
|
||||
_bonusAttack = new AutoProp<int>(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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,10 +14,19 @@ public class DefenseComponent : IDefenseComponent
|
||||
|
||||
private readonly AutoProp<int> _maximumDefense;
|
||||
|
||||
private readonly int _initialValue;
|
||||
|
||||
public DefenseComponent(int defenseValue)
|
||||
{
|
||||
_maximumDefense = new AutoProp<int>(defenseValue);
|
||||
_currentDefense = new AutoProp<int>(defenseValue);
|
||||
_initialValue = defenseValue;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
_maximumDefense.OnNext(_initialValue);
|
||||
_currentDefense.OnNext(_initialValue);
|
||||
}
|
||||
|
||||
public void Restore(int restoreAmount)
|
||||
|
||||
@@ -36,6 +36,13 @@ public class EquipmentComponent : IEquipmentComponent
|
||||
_equippedAccessory = new AutoProp<EquipableItem>(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)
|
||||
|
||||
@@ -27,10 +27,19 @@ public class ExperiencePointsComponent : IExperiencePointsComponent
|
||||
var firstLevelExpRequirement = ExpToNextLevelCalculation(1);
|
||||
_expToNextLevel = new AutoProp<int>(firstLevelExpRequirement);
|
||||
_currentExp = new AutoProp<int>(0);
|
||||
_expGainRate = new AutoProp<double>(1.0);
|
||||
_expGainRate = new AutoProp<double>(1);
|
||||
_level = new AutoProp<int>(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;
|
||||
|
||||
@@ -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<int>(initialHP);
|
||||
_currentHP = new AutoProp<int>(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);
|
||||
|
||||
@@ -8,10 +8,17 @@ public class LuckComponent : ILuckComponent
|
||||
public IAutoProp<int> Luck => _luck;
|
||||
|
||||
private AutoProp<int> _luck;
|
||||
private readonly int _initialValue;
|
||||
|
||||
public LuckComponent(int initialLuck)
|
||||
{
|
||||
_luck = new AutoProp<int>(initialLuck);
|
||||
_initialValue = initialLuck;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
_luck.OnNext(_initialValue);
|
||||
}
|
||||
|
||||
public void IncreaseLuck(int value) => _luck.OnNext(_luck.Value + value);
|
||||
|
||||
@@ -14,12 +14,21 @@ public class VTComponent : IVTComponent
|
||||
|
||||
private readonly AutoProp<int> _maximumVT;
|
||||
|
||||
private readonly int _initialValue;
|
||||
|
||||
public bool AtFullVT => CurrentVT.Value == MaximumVT.Value;
|
||||
|
||||
public VTComponent(int initialVT)
|
||||
{
|
||||
_maximumVT = new AutoProp<int>(initialVT);
|
||||
_currentVT = new AutoProp<int>(initialVT);
|
||||
_initialValue = initialVT;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
_maximumVT.OnNext(_initialValue);
|
||||
_currentVT.OnNext(_initialValue);
|
||||
}
|
||||
|
||||
public void Restore(int restoreAmount)
|
||||
|
||||
@@ -63,5 +63,6 @@ public partial class FollowBehavior : Node3D, IBehavior
|
||||
{
|
||||
_thinkTimer.Stop();
|
||||
_thinkTimer.Timeout -= OnTimeout;
|
||||
_thinkTimer.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"),
|
||||
|
||||
@@ -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<Player>("res://src/player/Player.tscn");
|
||||
PauseContainer.AddChild(_player);
|
||||
|
||||
_map = _instantiator.LoadAndInstantiate<Map>("res://src/map/Map.tscn");
|
||||
PauseContainer.AddChild(_map);
|
||||
|
||||
GameRepo = _container.GetInstance<IGameRepo>();
|
||||
GameState = _container.GetInstance<IGameState>();
|
||||
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<GameData>(
|
||||
(chunk) =>
|
||||
@@ -116,10 +107,7 @@ public partial class Game : Node3D, IGame
|
||||
QuestData = data.QuestData;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public void OnResolved()
|
||||
{
|
||||
var saveFileManager = _container.GetInstance<IMaSaveFileManager>();
|
||||
SaveFile = new SaveFile<GameData>(
|
||||
root: GameChunk,
|
||||
@@ -139,14 +127,129 @@ public partial class Game : Node3D, IGame
|
||||
return null;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public void Setup()
|
||||
{
|
||||
_instantiator = new Instantiator(GetTree());
|
||||
_player = _instantiator.LoadAndInstantiate<Player>("res://src/player/Player.tscn");
|
||||
_map = _instantiator.LoadAndInstantiate<Map>("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<PackedScene>("res://src/items/dropped/DroppedItem.tscn");
|
||||
var dropped = droppedScene.Instantiate<DroppedItem>();
|
||||
dropped.Item = item;
|
||||
AddChild(dropped);
|
||||
dropped.Drop();
|
||||
}
|
||||
|
||||
public void ThrowItem(InventoryItem item)
|
||||
{
|
||||
var thrownScene = GD.Load<PackedScene>("res://src/items/thrown/ThrownItem.tscn");
|
||||
var thrown = thrownScene.Instantiate<ThrownItem>();
|
||||
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<PackedScene>("res://src/items/dropped/DroppedItem.tscn");
|
||||
var dropped = droppedScene.Instantiate<DroppedItem>();
|
||||
dropped.Item = item;
|
||||
AddChild(dropped);
|
||||
dropped.Drop();
|
||||
}
|
||||
|
||||
public void ThrowItem(InventoryItem item)
|
||||
{
|
||||
var thrownScene = GD.Load<PackedScene>("res://src/items/thrown/ThrownItem.tscn");
|
||||
var thrown = thrownScene.Instantiate<ThrownItem>();
|
||||
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<PackedScene>("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;
|
||||
|
||||
@@ -25,8 +25,6 @@ public interface IGame : IProvide<IGame>, IProvide<IGameRepo>, IProvide<IPlayer>
|
||||
|
||||
public void FloorExitReached();
|
||||
|
||||
public InventoryItem RerollItem(InventoryItem itemToReroll, bool insertIntoInventory = true);
|
||||
|
||||
public void GameOver();
|
||||
|
||||
public Task Save();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Chickensoft.AutoInject;
|
||||
using Chickensoft.Introspection;
|
||||
using Godot;
|
||||
using Zennysoft.Ma.Adapter;
|
||||
|
||||
namespace Zennysoft.Game.Ma;
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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<string> BroadcastMessage;
|
||||
|
||||
public Inventory()
|
||||
{
|
||||
Items = [];
|
||||
@@ -25,6 +28,20 @@ public partial class Inventory : Node, IInventory
|
||||
[Save("inventory_items")]
|
||||
public List<InventoryItem> 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)
|
||||
|
||||
@@ -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<ItemDatabase> lazy =
|
||||
new Lazy<ItemDatabase>(() => new ItemDatabase());
|
||||
|
||||
public static ItemDatabase Instance { get { return lazy.Value; } }
|
||||
|
||||
public ImmutableList<InventoryItem> Items { get; set; }
|
||||
|
||||
public InventoryItem PickItem<T>(T itemToExclude = null)
|
||||
public T PickItem<T>(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<InventoryItem>();
|
||||
var armorResources = DirAccess.GetFilesAt("res://src/items/armor/resources/");
|
||||
|
||||
36
Zennysoft.Game.Ma/src/items/ItemReroller.cs
Normal file
36
Zennysoft.Game.Ma/src/items/ItemReroller.cs
Normal file
@@ -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>(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);
|
||||
}
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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<IGame>();
|
||||
|
||||
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);
|
||||
|
||||
@@ -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<int> CurrentFloorNumber { get; }
|
||||
|
||||
public event Action<Transform3D> SpawnPointCreated;
|
||||
}
|
||||
|
||||
@@ -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<IGame>();
|
||||
|
||||
[Dependency]
|
||||
public IPlayer Player => this.DependOn<IPlayer>();
|
||||
|
||||
[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<Transform3D> 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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<Marker3D>())
|
||||
{
|
||||
if (numberOfItemsToSpawn <= 0)
|
||||
|
||||
@@ -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<IPlayer>
|
||||
{
|
||||
#region Dependency Injection
|
||||
public override void _Notification(int what) => this.Notify(what);
|
||||
|
||||
private PlayerLogic.IBinding PlayerBinding { get; set; } = default!;
|
||||
IPlayer IProvide<IPlayer>.Value() => this;
|
||||
|
||||
[Dependency] private IGameRepo _gameRepo => this.DependOn<IGameRepo>(() => 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<IGame>();
|
||||
#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<IPlayerLogic, PlayerLogic>(Lifestyle.Singleton);
|
||||
|
||||
PlayerLogic = container.GetInstance<IPlayerLogic>();
|
||||
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<IPlayerLogic, PlayerLogic>(Lifestyle.Singleton);
|
||||
_itemReroller = new ItemReroller(ItemDatabase.Instance);
|
||||
|
||||
PlayerLogic = container.GetInstance<IPlayerLogic>();
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,5 +20,6 @@ public partial class QuestTest : Area3D
|
||||
private void QuestTest_AreaEntered(Area3D area)
|
||||
{
|
||||
Game.QuestData.QuestMarker1 = true;
|
||||
QueueFree();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ using Chickensoft.AutoInject;
|
||||
using Chickensoft.GodotNodeInterfaces;
|
||||
using Chickensoft.Introspection;
|
||||
using Godot;
|
||||
using Zennysoft.Ma.Adapter;
|
||||
|
||||
namespace Zennysoft.Game.Ma;
|
||||
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -28,8 +28,6 @@ public partial class InventoryMenu : Control, IInventoryMenu
|
||||
|
||||
[Dependency] public IPlayer Player => this.DependOn<IPlayer>();
|
||||
|
||||
[Dependency] public IMap _map => this.DependOn<IMap>();
|
||||
|
||||
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)
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ public partial class PauseDebugMenu : Control, IDebugMenu
|
||||
{
|
||||
LoadNextFloorButton.Pressed += LoadNextFloorButton_Pressed;
|
||||
|
||||
_itemDatabase = new ItemDatabase();
|
||||
_itemDatabase = ItemDatabase.Instance;
|
||||
_spawnableItems = _itemDatabase.Items;
|
||||
|
||||
_spawnableEnemies =
|
||||
|
||||
@@ -18,6 +18,7 @@ public partial class SceneLoader : Node
|
||||
ResourceLoader.LoadThreadedRequest(sceneToLoad);
|
||||
_sceneToLoad = sceneToLoad;
|
||||
_loading = true;
|
||||
SetProcess(true);
|
||||
}
|
||||
|
||||
private void LoadScene()
|
||||
|
||||
Reference in New Issue
Block a user