Overhaul game state logic to support gameplay loop

This commit is contained in:
2025-04-30 00:43:55 -07:00
parent 78cdda97b9
commit 68c91d8f13
60 changed files with 2503 additions and 1116 deletions

View File

@@ -9,5 +9,5 @@ public interface IAppLogic : ILogicBlock<AppLogic.State>;
[LogicBlock(typeof(State), Diagram = true)] [LogicBlock(typeof(State), Diagram = true)]
public partial class AppLogic : LogicBlock<AppLogic.State>, IAppLogic public partial class AppLogic : LogicBlock<AppLogic.State>, IAppLogic
{ {
public override Transition GetInitialState() => To<State.SplashScreen>(); public override Transition GetInitialState() => To<State.GameStarted>();
} }

View File

@@ -9,13 +9,14 @@ public partial class AppLogic
public partial record State public partial record State
{ {
[Meta] [Meta]
public partial record InGame : State, IGet<Input.GameOver> public partial record GameStarted : State
{ {
public InGame() public GameStarted()
{ {
this.OnEnter(() => this.OnEnter(() =>
{ {
Output(new Output.SetupGameScene());
Output(new Output.ShowGame()); Output(new Output.ShowGame());
Get<IAppRepo>().OnEnterGame(); Get<IAppRepo>().OnEnterGame();
}); });
@@ -25,12 +26,6 @@ public partial class AppLogic
OnDetach(() => Get<IAppRepo>().GameExited -= OnGameExited); OnDetach(() => Get<IAppRepo>().GameExited -= OnGameExited);
} }
public Transition On(in Input.GameOver input)
{
Output(new Output.RemoveExistingGame());
return To<MainMenu>();
}
public void OnGameExited() => Input(new Input.QuitGame()); public void OnGameExited() => Input(new Input.QuitGame());
} }
} }

View File

@@ -18,7 +18,7 @@ public partial class AppLogic
public Transition On(in Input.FadeOutFinished input) => public Transition On(in Input.FadeOutFinished input) =>
Get<Data>().ShouldLoadExistingGame Get<Data>().ShouldLoadExistingGame
? To<LoadingSaveFile>() ? To<LoadingSaveFile>()
: To<InGame>(); : To<GameStarted>();
} }
} }
} }

View File

@@ -15,7 +15,7 @@ public partial class AppLogic
this.OnEnter(() => Output(new Output.StartLoadingSaveFile())); this.OnEnter(() => Output(new Output.StartLoadingSaveFile()));
} }
public Transition On(in Input.SaveFileLoaded input) => To<InGame>(); public Transition On(in Input.SaveFileLoaded input) => To<GameStarted>();
} }
} }
} }

View File

@@ -1,43 +0,0 @@
using Chickensoft.Introspection;
using Chickensoft.LogicBlocks;
using Zennysoft.Game.Abstractions;
namespace Zennysoft.Ma.Adapter;
public partial class AppLogic
{
public partial record State
{
[Meta]
public partial record MainMenu : State, IGet<Input.NewGame>, IGet<Input.LoadGame>, IGet<Input.QuitGame>
{
public MainMenu()
{
this.OnEnter(() =>
{
Get<Data>().ShouldLoadExistingGame = false;
Output(new Output.SetupGameScene());
Get<IAppRepo>().OnMainMenuEntered();
Output(new Output.ShowMainMenu());
});
}
public Transition On(in Input.NewGame input)
{
return To<LeavingMenu>();
}
public Transition On(in Input.LoadGame input)
{
Get<Data>().ShouldLoadExistingGame = true;
return To<LeavingMenu>();
}
public Transition On(in Input.QuitGame input)
{
Output(new Output.ExitGame());
return ToSelf();
}
}
}
}

View File

@@ -24,7 +24,7 @@ public partial class AppLogic
); );
} }
public Transition On(in Input.FadeOutFinished input) => To<MainMenu>(); public Transition On(in Input.FadeOutFinished input) => To<GameStarted>();
public void OnSplashScreenSkipped() => public void OnSplashScreenSkipped() =>
Output(new Output.HideSplashScreen()); Output(new Output.HideSplashScreen());

View File

@@ -1,36 +0,0 @@
namespace Zennysoft.Ma.Adapter;
public partial class GameLogic
{
public static class Input
{
public readonly record struct StartGame;
public readonly record struct Initialize;
public readonly record struct GoToOverworld;
public readonly record struct SaveGame;
public readonly record struct OpenInventory;
public readonly record struct CloseInventory;
public readonly record struct FloorExitReached;
public readonly record struct HideFloorClearMenu;
public readonly record struct GameOver;
public readonly record struct GoToNextFloor;
public readonly record struct PauseGame;
public readonly record struct UnpauseGame;
public readonly record struct PauseMenuTransitioned;
public readonly record struct AskForTeleport;
public readonly record struct HideAskForTeleport;
}
}

View File

@@ -1,39 +0,0 @@
namespace Zennysoft.Ma.Adapter;
public partial class GameLogic
{
public static class Output
{
public readonly record struct StartGame;
public readonly record struct ShowPauseMenu;
public readonly record struct HidePauseMenu;
public readonly record struct ExitPauseMenu;
public readonly record struct SetPauseMode(bool IsPaused);
public readonly record struct ShowLostScreen;
public readonly record struct ExitLostScreen;
public readonly record struct LoadNextFloor;
public readonly record struct LoadMap;
public readonly record struct ShowFloorClearMenu;
public readonly record struct ExitFloorClearMenu;
public readonly record struct ShowAskForTeleport;
public readonly record struct HideAskForTeleport;
public readonly record struct GoToOverworld;
public readonly record struct SaveGame;
public readonly record struct DoubleExpTimeStart(int lengthOfTimeInSeconds);
}
}

View File

@@ -1,35 +0,0 @@
using Chickensoft.Introspection;
using Chickensoft.LogicBlocks;
namespace Zennysoft.Ma.Adapter;
public partial class GameLogic
{
[Meta]
public abstract partial record State : StateLogic<State>
{
protected State()
{
OnAttach(() =>
{
var gameRepo = Get<IGameRepo>();
gameRepo.IsPaused.Sync += OnIsPaused;
gameRepo.DoubleExpTimeStart += OnDoubleExpTimeStart;
gameRepo.Ended += OnGameEnded;
});
OnDetach(() =>
{
var gameRepo = Get<IGameRepo>();
gameRepo.IsPaused.Sync -= OnIsPaused;
gameRepo.DoubleExpTimeStart -= OnDoubleExpTimeStart;
gameRepo.Ended -= OnGameEnded;
});
}
private void OnDoubleExpTimeStart(int lengthOfTimeInSeconds) => Output(new Output.DoubleExpTimeStart(lengthOfTimeInSeconds));
private void OnGameEnded() => Output(new Output.ShowLostScreen());
public void OnIsPaused(bool isPaused) => Output(new Output.SetPauseMode(isPaused));
}
}

View File

@@ -1,13 +0,0 @@
using Chickensoft.Introspection;
using Chickensoft.LogicBlocks;
namespace Zennysoft.Ma.Adapter;
public interface IGameLogic : ILogicBlock<GameLogic.State>;
[Meta]
[LogicBlock(typeof(State), Diagram = true)]
public partial class GameLogic : LogicBlock<GameLogic.State>, IGameLogic
{
public override Transition GetInitialState() => To<State.MenuBackdrop>();
}

View File

@@ -0,0 +1,13 @@
using Chickensoft.Introspection;
using Chickensoft.LogicBlocks;
namespace Zennysoft.Ma.Adapter;
public interface IGameState : ILogicBlock<GameState.State>;
[Meta]
[LogicBlock(typeof(State), Diagram = true)]
public partial class GameState : LogicBlock<GameState.State>, IGameState
{
public override Transition GetInitialState() => To<State.MainMenu>();
}

View File

@@ -0,0 +1,29 @@
namespace Zennysoft.Ma.Adapter;
public partial class GameState
{
public static class Input
{
public readonly record struct NewGame;
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;
public readonly record struct MiniMapButtonPressed;
public readonly record struct PauseButtonPressed;
public readonly record struct DebugButtonPressed;
public readonly record struct FloorExitEntered;
public readonly record struct GameOver;
}
}

View File

@@ -0,0 +1,33 @@
namespace Zennysoft.Ma.Adapter;
public partial class GameState
{
public static class Output
{
public readonly record struct InitializeGame;
public readonly record struct LoadGameFromFile;
public readonly record struct OpenInventoryMenu;
public readonly record struct CloseInventoryMenu;
public readonly record struct OpenMiniMap;
public readonly record struct CloseMiniMap;
public readonly record struct OpenPauseScreen;
public readonly record struct ClosePauseScreen;
public readonly record struct LoadNextFloor;
public readonly record struct OpenFloorExitScreen;
public readonly record struct OpenDebugMenu;
public readonly record struct CloseDebugMenu;
public readonly record struct GameOver;
}
}

View File

@@ -0,0 +1,12 @@
using Chickensoft.Introspection;
using Chickensoft.LogicBlocks;
namespace Zennysoft.Ma.Adapter;
public partial class GameState
{
[Meta]
public abstract partial record State : StateLogic<State>
{
}
}

View File

@@ -0,0 +1,20 @@
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 DebugMenu : State, IGet<Input.DebugButtonPressed>
{
public Transition On(in Input.DebugButtonPressed input)
{
Output(new Output.CloseDebugMenu());
return To<InGame>();
}
}
}
}

View File

@@ -0,0 +1,30 @@
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 FloorExitScreen : State, IGet<Input.LoadNextFloor>, IGet<Input.ReturnToMainMenu>
{
public FloorExitScreen()
{
OnAttach(() => Get<IGameRepo>().Pause());
}
public Transition On(in Input.LoadNextFloor input)
{
Output(new Output.LoadNextFloor());
return To<InGame>();
}
public Transition On(in Input.ReturnToMainMenu input)
{
return To<MainMenu>();
}
}
}
}

View File

@@ -0,0 +1,25 @@
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 GameOver : State, IGet<Input.ContinueGame>, IGet<Input.ReturnToMainMenu>
{
public Transition On(in Input.ContinueGame input)
{
Output(new Output.InitializeGame());
return To<InGame>();
}
public Transition On(in Input.ReturnToMainMenu input)
{
return To<MainMenu>();
}
}
}
}

View File

@@ -0,0 +1,56 @@
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 InGame : State,
IGet<Input.InventoryButtonPressed>,
IGet<Input.MiniMapButtonPressed>,
IGet<Input.PauseButtonPressed>,
IGet<Input.DebugButtonPressed>,
IGet<Input.FloorExitEntered>,
IGet<Input.GameOver>
{
public Transition On(in Input.InventoryButtonPressed input)
{
Output(new Output.OpenInventoryMenu());
return To<InventoryScreen>();
}
public Transition On(in Input.MiniMapButtonPressed input)
{
Output(new Output.OpenMiniMap());
return To<MiniMapScreen>();
}
public Transition On(in Input.PauseButtonPressed input)
{
Output(new Output.OpenPauseScreen());
return To<PauseScreen>();
}
public Transition On(in Input.DebugButtonPressed input)
{
Output(new Output.OpenDebugMenu());
return To<DebugMenu>();
}
public Transition On(in Input.FloorExitEntered input)
{
Output(new Output.OpenFloorExitScreen());
return To<FloorExitScreen>();
}
public Transition On(in Input.GameOver input)
{
Output(new Output.GameOver());
return To<GameOver>();
}
}
}
}

View File

@@ -0,0 +1,20 @@
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 InventoryScreen : State, IGet<Input.InventoryButtonPressed>
{
public Transition On(in Input.InventoryButtonPressed input)
{
Output(new Output.CloseInventoryMenu());
return To<InGame>();
}
}
}
}

View File

@@ -0,0 +1,33 @@
using Chickensoft.Introspection;
using Chickensoft.LogicBlocks;
using Zennysoft.Game.Abstractions;
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());
return To<InGame>();
}
public Transition On(in Input.LoadGame input)
{
Output(new Output.LoadGameFromFile());
return To<InGame>();
}
}
}
}

View File

@@ -0,0 +1,20 @@
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 MiniMapScreen : State, IGet<Input.MiniMapButtonPressed>
{
public Transition On(in Input.MiniMapButtonPressed input)
{
Output(new Output.CloseMiniMap());
return To<InGame>();
}
}
}
}

View File

@@ -0,0 +1,20 @@
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 PauseScreen : State, IGet<Input.PauseButtonPressed>
{
public Transition On(in Input.PauseButtonPressed input)
{
Output(new Output.ClosePauseScreen());
return To<InGame>();
}
}
}
}

View File

@@ -1,26 +0,0 @@
using Chickensoft.Introspection;
namespace Zennysoft.Ma.Adapter;
public partial class GameLogic
{
public partial record State
{
[Meta]
public partial record AskForTeleport : Playing, IGet<Input.FloorExitReached>, IGet<Input.HideAskForTeleport>
{
public AskForTeleport()
{
this.OnAttach(() => { Get<IGameRepo>().Pause(); Output(new Output.ShowAskForTeleport()); });
this.OnDetach(() => { Output(new Output.HideAskForTeleport()); });
}
public Transition On(in Input.FloorExitReached input) => To<FloorClearedDecisionState>();
public Transition On(in Input.HideAskForTeleport input)
{
return To<Playing>();
}
}
}
}

View File

@@ -1,36 +0,0 @@
using Chickensoft.Introspection;
namespace Zennysoft.Ma.Adapter;
public partial class GameLogic
{
public partial record State
{
[Meta]
public partial record FloorClearedDecisionState : Playing, IGet<Input.GoToNextFloor>, IGet<Input.SaveGame>, IGet<Input.HideFloorClearMenu>
{
public FloorClearedDecisionState()
{
this.OnAttach(() => { Get<IGameRepo>().Pause(); Output(new Output.ShowFloorClearMenu()); });
this.OnDetach(() => { Output(new Output.ExitFloorClearMenu()); });
}
public Transition On(in Input.GoToNextFloor input)
{
Output(new Output.LoadNextFloor());
return ToSelf();
}
public Transition On(in Input.HideFloorClearMenu input)
{
return To<Playing>();
}
public Transition On(in Input.SaveGame input)
{
Output(new Output.SaveGame());
return To<Playing>();
}
}
}
}

View File

@@ -1,32 +0,0 @@
namespace Zennysoft.Ma.Adapter;
using Chickensoft.Introspection;
using Zennysoft.Game.Abstractions;
public partial class GameLogic
{
public partial record State
{
[Meta]
public partial record MenuBackdrop : State, IGet<Input.StartGame>, IGet<Input.Initialize>
{
public MenuBackdrop()
{
OnAttach(() => Get<IAppRepo>().GameEntered += OnGameEntered);
OnDetach(() => Get<IAppRepo>().GameEntered -= OnGameEntered);
}
public void OnGameEntered() => Input(new Input.StartGame());
public Transition On(in Input.StartGame input)
{
return To<Playing>();
}
public Transition On(in Input.Initialize input)
{
return ToSelf();
}
}
}
}

View File

@@ -1,26 +0,0 @@
using Chickensoft.Introspection;
using Chickensoft.LogicBlocks;
namespace Zennysoft.Ma.Adapter;
public partial class GameLogic
{
public partial record State
{
[Meta]
public partial record Paused : Playing, IGet<Input.UnpauseGame>
{
public Paused()
{
this.OnEnter(() =>
{
Get<IGameRepo>().Pause();
Output(new Output.ShowPauseMenu());
});
this.OnExit(() => Output(new Output.ExitPauseMenu()));
}
public virtual Transition On(in Input.UnpauseGame input) => To<Resuming>();
}
}
}

View File

@@ -1,37 +0,0 @@
using Chickensoft.Introspection;
namespace Zennysoft.Ma.Adapter;
public partial class GameLogic
{
public partial record State
{
[Meta]
public partial record Playing : State,
IGet<Input.AskForTeleport>,
IGet<Input.PauseGame>,
IGet<Input.GoToOverworld>
{
public Playing()
{
OnAttach(() =>
{
Output(new Output.StartGame());
Output(new Output.LoadMap());
});
}
public void OnEnded() => Input(new Input.GameOver());
public Transition On(in Input.AskForTeleport input) => To<AskForTeleport>();
public Transition On(in Input.PauseGame input) => To<Paused>();
public Transition On(in Input.GoToOverworld input)
{
Output(new Output.GoToOverworld());
return ToSelf();
}
}
}
}

View File

@@ -1,25 +0,0 @@
using Chickensoft.Introspection;
using Chickensoft.LogicBlocks;
namespace Zennysoft.Ma.Adapter;
public partial class GameLogic
{
public partial record State
{
[Meta]
public partial record Quit : State, IGet<Input.GoToOverworld>
{
public Quit()
{
this.OnEnter(() => Output(new Output.ShowLostScreen()));
}
public Transition On(in Input.GoToOverworld input)
{
Input(new Input.StartGame());
return To<Playing>();
}
}
}
}

View File

@@ -1,23 +0,0 @@
namespace Zennysoft.Ma.Adapter;
using Chickensoft.Introspection;
using Chickensoft.LogicBlocks;
public partial class GameLogic
{
public partial record State
{
[Meta]
public partial record Resuming : Playing, IGet<Input.PauseMenuTransitioned>
{
public Resuming()
{
this.OnEnter(() => Get<IGameRepo>().Resume());
this.OnExit(() => Output(new Output.HidePauseMenu()));
}
public Transition On(in Input.PauseMenuTransitioned input) =>
To<Playing>();
}
}
}

View File

@@ -13,7 +13,7 @@ public class Module
container.RegisterSingleton<ISaveFileManager<GameData>, SaveFileManager<GameData>>(); container.RegisterSingleton<ISaveFileManager<GameData>, SaveFileManager<GameData>>();
container.RegisterSingleton<IMaSaveFileManager<GameData>, MaSaveFileManager<GameData>>(); container.RegisterSingleton<IMaSaveFileManager<GameData>, MaSaveFileManager<GameData>>();
container.RegisterSingleton<IGameRepo, GameRepo>(); container.RegisterSingleton<IGameRepo, GameRepo>();
container.RegisterSingleton<IGameLogic, GameLogic>(); container.RegisterSingleton<IGameState, GameState>();
container.RegisterSingleton<IDimmableAudioStreamPlayer, DimmableAudioStreamPlayer>(); container.RegisterSingleton<IDimmableAudioStreamPlayer, DimmableAudioStreamPlayer>();
} }
} }

View File

@@ -8,9 +8,9 @@ public interface IPlayer : IKillable
{ {
public void InitializePlayerState(); public void InitializePlayerState();
public void Attack(); public void Activate();
public void PlayerPause(); public void Attack();
public void TakeDamage(double damage, ElementType elementType = ElementType.None, bool isCriticalHit = false); public void TakeDamage(double damage, ElementType elementType = ElementType.None, bool isCriticalHit = false);
@@ -44,7 +44,7 @@ public interface IPlayer : IKillable
public IInventory Inventory { get; } public IInventory Inventory { get; }
public PlayerStatController Stats { get; } public PlayerStats Stats { get; }
public Vector3 CurrentPosition { get; } public Vector3 CurrentPosition { get; }

View File

@@ -1,118 +0,0 @@
namespace Zennysoft.Ma.Adapter;
using Chickensoft.Collections;
using Godot;
using Zennysoft.Game.Ma;
public class PlayerStatController
{
public void Init(PlayerStats playerStats)
{
_currentHP.OnNext(playerStats.CurrentHP);
_maximumHP.OnNext(playerStats.MaximumHP);
_currentVT.OnNext(playerStats.CurrentVT);
_maximumVT.OnNext(playerStats.MaximumVT);
_currentExp.OnNext(playerStats.CurrentExp);
_expToNextLevel.OnNext(playerStats.ExpToNextLevel);
_currentLevel.OnNext(playerStats.CurrentLevel);
_currentAttack.OnNext(playerStats.CurrentAttack);
_bonusAttack.OnNext(playerStats.BonusAttack);
_maxAttack.OnNext(playerStats.MaxAttack);
_currentDefense.OnNext(playerStats.CurrentDefense);
_bonusDefense.OnNext(playerStats.BonusDefense);
_maxDefense.OnNext(playerStats.MaxDefense);
_luck.OnNext(playerStats.Luck);
}
public IAutoProp<int> CurrentHP => _currentHP;
public IAutoProp<int> MaximumHP => _maximumHP;
public IAutoProp<int> CurrentVT => _currentVT;
public IAutoProp<int> MaximumVT => _maximumVT;
public IAutoProp<int> CurrentAttack => _currentAttack;
public IAutoProp<int> MaxAttack => _maxAttack;
public IAutoProp<int> BonusAttack => _bonusAttack;
public IAutoProp<int> CurrentDefense => _currentDefense;
public IAutoProp<int> MaxDefense => _maxDefense;
public IAutoProp<int> BonusDefense => _bonusDefense;
public IAutoProp<double> CurrentExp => _currentExp;
public IAutoProp<int> ExpToNextLevel => _expToNextLevel;
public IAutoProp<int> CurrentLevel => _currentLevel;
public IAutoProp<double> Luck => _luck;
public void SetCurrentHP(int newValue)
{
var clampedValue = Mathf.Clamp(newValue, 0, MaximumHP.Value);
_currentHP.OnNext(clampedValue);
}
public void SetMaximumHP(int newValue)
{
_maximumHP.OnNext(newValue);
}
public void SetCurrentVT(int newValue)
{
var clampedValue = Mathf.Clamp(newValue, 0, MaximumVT.Value);
_currentVT.OnNext(clampedValue);
}
public void SetMaximumVT(int newValue)
{
_maximumVT.OnNext(newValue);
}
public void SetCurrentExp(double newValue)
{
_currentExp.OnNext(newValue);
}
public void SetCurrentLevel(int newValue)
{
_currentLevel.OnNext(newValue);
}
public void SetCurrentAttack(int newValue)
{
var clampedValue = Mathf.Clamp(newValue, 0, MaxAttack.Value);
_currentAttack.OnNext(clampedValue);
}
public void SetBonusAttack(int newValue)
{
_bonusAttack.OnNext(newValue);
}
public void SetMaxAttack(int newValue)
{
_maxAttack.OnNext(newValue);
}
public void SetCurrentDefense(int newValue)
{
var clampedValue = Mathf.Clamp(newValue, 0, MaxDefense.Value);
_currentDefense.OnNext(clampedValue);
}
public void SetBonusDefense(int newValue)
{
_bonusDefense.OnNext(newValue);
}
public void SetMaxDefense(int newValue)
{
_maxDefense.OnNext(newValue);
}
public void SetExpToNextLevel(int newValue)
{
_expToNextLevel.OnNext(newValue);
}
public void SetLuck(double newValue)
{
var clampedValue = Mathf.Clamp(newValue, 0, 1.0);
_luck.OnNext(clampedValue);
}
private readonly AutoProp<int> _currentHP = new(-1);
private readonly AutoProp<int> _maximumHP = new(-1);
private readonly AutoProp<int> _currentVT = new(-1);
private readonly AutoProp<int> _maximumVT = new(-1);
private readonly AutoProp<double> _currentExp = new(-1);
private readonly AutoProp<int> _currentLevel = new(-1);
private readonly AutoProp<int> _currentAttack = new(-1);
private readonly AutoProp<int> _bonusAttack = new(-1);
private readonly AutoProp<int> _maxAttack = new(-1);
private readonly AutoProp<int> _currentDefense = new(-1);
private readonly AutoProp<int> _bonusDefense = new(-1);
private readonly AutoProp<int> _maxDefense = new(-1);
private readonly AutoProp<int> _expToNextLevel = new(-1);
private readonly AutoProp<double> _luck = new(-1);
}

View File

@@ -4,7 +4,7 @@ using Chickensoft.Serialization;
namespace Zennysoft.Game.Ma; namespace Zennysoft.Game.Ma;
[Meta, Id("player_stats")] [Meta, Id("player_stats")]
public partial record PlayerStats public partial record PlayerInitialState
{ {
[Save("currentHP")] [Save("currentHP")]
public int CurrentHP { get; init; } public int CurrentHP { get; init; }

View File

@@ -0,0 +1,115 @@
namespace Zennysoft.Ma.Adapter;
using Chickensoft.Collections;
using Godot;
public class PlayerStats
{
public PlayerStats(AutoProp<int> currentHP,
AutoProp<int> maximumHP,
AutoProp<int> currentVT,
AutoProp<int> maximumVT,
AutoProp<int> currentAttack,
AutoProp<int> maxAttack,
AutoProp<int> bonusAttack,
AutoProp<int> currentDefense,
AutoProp<int> maxDefense,
AutoProp<int> bonusDefense,
AutoProp<double> currentExp,
AutoProp<int> expToNextLevel,
AutoProp<int> currentLevel,
AutoProp<double> luck)
{
CurrentHP = currentHP;
MaximumHP = maximumHP;
CurrentVT = currentVT;
MaximumVT = maximumVT;
CurrentAttack = currentAttack;
MaxAttack = maxAttack;
BonusAttack = bonusAttack;
CurrentDefense = currentDefense;
MaxDefense = maxDefense;
BonusDefense = bonusDefense;
CurrentExp = currentExp;
ExpToNextLevel = expToNextLevel;
CurrentLevel = currentLevel;
Luck = luck;
}
public AutoProp<int> CurrentHP { get; init; }
public AutoProp<int> MaximumHP { get; init; }
public AutoProp<int> CurrentVT { get; init; }
public AutoProp<int> MaximumVT { get; init; }
public AutoProp<int> CurrentAttack { get; init; }
public AutoProp<int> MaxAttack { get; init; }
public AutoProp<int> BonusAttack { get; init; }
public AutoProp<int> CurrentDefense { get; init; }
public AutoProp<int> MaxDefense { get; init; }
public AutoProp<int> BonusDefense { get; init; }
public AutoProp<double> CurrentExp { get; init; }
public AutoProp<int> ExpToNextLevel { get; init; }
public AutoProp<int> CurrentLevel { get; init; }
public AutoProp<double> Luck { get; init; }
public void SetCurrentHP(int newValue)
{
var clampedValue = Mathf.Clamp(newValue, 0, MaximumHP.Value);
CurrentHP.OnNext(clampedValue);
}
public void SetMaximumHP(int newValue)
{
MaximumHP.OnNext(newValue);
}
public void SetCurrentVT(int newValue)
{
var clampedValue = Mathf.Clamp(newValue, 0, MaximumVT.Value);
CurrentVT.OnNext(clampedValue);
}
public void SetMaximumVT(int newValue)
{
MaximumVT.OnNext(newValue);
}
public void SetCurrentExp(double newValue)
{
CurrentExp.OnNext(newValue);
}
public void SetCurrentLevel(int newValue)
{
CurrentLevel.OnNext(newValue);
}
public void SetCurrentAttack(int newValue)
{
var clampedValue = Mathf.Clamp(newValue, 0, MaxAttack.Value);
CurrentAttack.OnNext(clampedValue);
}
public void SetBonusAttack(int newValue)
{
BonusAttack.OnNext(newValue);
}
public void SetMaxAttack(int newValue)
{
MaxAttack.OnNext(newValue);
}
public void SetCurrentDefense(int newValue)
{
var clampedValue = Mathf.Clamp(newValue, 0, MaxDefense.Value);
CurrentDefense.OnNext(clampedValue);
}
public void SetBonusDefense(int newValue)
{
BonusDefense.OnNext(newValue);
}
public void SetMaxDefense(int newValue)
{
MaxDefense.OnNext(newValue);
}
public void SetExpToNextLevel(int newValue)
{
ExpToNextLevel.OnNext(newValue);
}
public void SetLuck(double newValue)
{
var clampedValue = Mathf.Clamp(newValue, 0, 1.0);
Luck.OnNext(clampedValue);
}
}

View File

@@ -6,6 +6,12 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<Compile Remove="Game\state\states\**" />
<EmbeddedResource Remove="Game\state\states\**" />
<None Remove="Game\state\states\**" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Chickensoft.GodotNodeInterfaces" Version="2.4.0" /> <PackageReference Include="Chickensoft.GodotNodeInterfaces" Version="2.4.0" />
<PackageReference Include="Chickensoft.Introspection" Version="2.2.0" /> <PackageReference Include="Chickensoft.Introspection" Version="2.2.0" />

View File

@@ -206,6 +206,7 @@ Load={
Debug={ Debug={
"deadzone": 0.2, "deadzone": 0.2,
"events": [Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":4,"pressure":0.0,"pressed":true,"script":null) "events": [Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":4,"pressure":0.0,"pressed":true,"script":null)
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":45,"key_label":0,"unicode":45,"location":0,"echo":false,"script":null)
] ]
} }

View File

@@ -28,21 +28,14 @@ public partial class App : CanvasLayer, IApp
public IAppLogic AppLogic { get; set; } = default!; public IAppLogic AppLogic { get; set; } = default!;
public AppLogic.IBinding AppBinding { get; set; } = default!; public AppLogic.IBinding AppBinding { get; set; } = default!;
[Node] public Menu Menu { get; set; } = default!;
[Node] public ISubViewport GameWindow { get; set; } = default!; [Node] public ISubViewport GameWindow { get; set; } = default!;
[Node] public ISplash Splash { get; set; } = default!;
[Node] public IColorRect BlankScreen { get; set; } = default!;
[Node] public IAnimationPlayer AnimationPlayer { get; set; } = default!;
public void Initialize() public void Initialize()
{ {
var container = new SimpleInjector.Container(); var container = new SimpleInjector.Container();
container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle(); container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle();
container.RegisterSingleton<IAppRepo, AppRepo>(); container.RegisterSingleton<IAppRepo, AppRepo>();
container.RegisterSingleton<IAppLogic, AppLogic>(); container.RegisterSingleton<IAppLogic, AppLogic>();
//container.Verify();
Instantiator = new Instantiator(GetTree()); Instantiator = new Instantiator(GetTree());
@@ -52,12 +45,6 @@ public partial class App : CanvasLayer, IApp
AppLogic.Set(AppRepo); AppLogic.Set(AppRepo);
AppLogic.Set(new AppLogic.Data()); AppLogic.Set(new AppLogic.Data());
Menu.NewGame += OnNewGame;
Menu.LoadGame += OnLoadGame;
Menu.Quit += OnQuit;
AnimationPlayer.AnimationFinished += OnAnimationFinished;
Input.MouseMode = Input.MouseModeEnum.Visible; Input.MouseMode = Input.MouseModeEnum.Visible;
this.Provide(); this.Provide();
} }
@@ -69,14 +56,9 @@ public partial class App : CanvasLayer, IApp
AppBinding AppBinding
.Handle((in AppLogic.Output.ShowSplashScreen _) => .Handle((in AppLogic.Output.ShowSplashScreen _) =>
{ {
HideMenus();
BlankScreen.Hide();
Splash.Show();
}) })
.Handle((in AppLogic.Output.HideSplashScreen _) => .Handle((in AppLogic.Output.HideSplashScreen _) =>
{ {
BlankScreen.Show();
FadeToBlack();
}) })
.Handle((in AppLogic.Output.SetupGameScene _) => .Handle((in AppLogic.Output.SetupGameScene _) =>
{ {
@@ -86,19 +68,9 @@ public partial class App : CanvasLayer, IApp
}) })
.Handle((in AppLogic.Output.ShowMainMenu _) => .Handle((in AppLogic.Output.ShowMainMenu _) =>
{ {
// Load everything while we're showing a black screen, then fade in.
HideMenus();
Menu.Show();
FadeInFromBlack();
Menu.NewGameButton.GrabFocus();
}) })
.Handle((in AppLogic.Output.FadeToBlack _) => FadeToBlack())
.Handle((in AppLogic.Output.HideGame _) => FadeToBlack())
.Handle((in AppLogic.Output.ShowGame _) => .Handle((in AppLogic.Output.ShowGame _) =>
{ {
HideMenus();
FadeInFromBlack();
}) })
.Handle((in AppLogic.Output.StartLoadingSaveFile _) => .Handle((in AppLogic.Output.StartLoadingSaveFile _) =>
{ {
@@ -126,36 +98,6 @@ public partial class App : CanvasLayer, IApp
AppLogic.Input(new AppLogic.Input.SaveFileLoaded()); AppLogic.Input(new AppLogic.Input.SaveFileLoaded());
} }
public void FadeInFromBlack()
{
BlankScreen.Show();
AnimationPlayer.Play("fade_in");
}
public void FadeToBlack()
{
BlankScreen.Show();
AnimationPlayer.Play("fade_out");
}
public void HideMenus()
{
Splash.Hide();
Menu.Hide();
}
public void OnAnimationFinished(StringName animation)
{
if (animation == "fade_in")
{
AppLogic.Input(new AppLogic.Input.FadeInFinished());
BlankScreen.Hide();
return;
}
AppLogic.Input(new AppLogic.Input.FadeOutFinished());
}
public void OnExitTree() public void OnExitTree()
{ {
AppLogic.Stop(); AppLogic.Stop();

View File

@@ -1,62 +1,6 @@
[gd_scene load_steps=8 format=3 uid="uid://cagfc5ridmteu"] [gd_scene load_steps=2 format=3 uid="uid://cagfc5ridmteu"]
[ext_resource type="Script" uid="uid://d1f8blk5ucqvq" path="res://src/app/App.cs" id="1_rt73h"] [ext_resource type="Script" uid="uid://d1f8blk5ucqvq" path="res://src/app/App.cs" id="1_rt73h"]
[ext_resource type="PackedScene" uid="uid://rfvnddfqufho" path="res://src/menu/Menu.tscn" id="2_kvwo1"]
[ext_resource type="PackedScene" uid="uid://bd0p761qakisw" path="res://src/menu/splash/Splash.tscn" id="3_3st5l"]
[sub_resource type="Animation" id="Animation_3st5l"]
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("BlankScreenControl/BlankScreen:color")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Color(0, 0, 0, 1)]
}
[sub_resource type="Animation" id="Animation_1uiag"]
resource_name = "fade_in"
length = 0.1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("BlankScreenControl/BlankScreen:color")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.1),
"transitions": PackedFloat32Array(1, 1),
"update": 0,
"values": [Color(0, 0, 0, 1), Color(0, 0, 0, 0)]
}
[sub_resource type="Animation" id="Animation_v0mgf"]
resource_name = "fade_out"
length = 0.1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("BlankScreenControl/BlankScreen:color")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.1),
"transitions": PackedFloat32Array(1, 1),
"update": 0,
"values": [Color(0, 0, 0, 0), Color(0, 0, 0, 1)]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_3st5l"]
_data = {
&"RESET": SubResource("Animation_3st5l"),
&"fade_in": SubResource("Animation_1uiag"),
&"fade_out": SubResource("Animation_v0mgf")
}
[node name="App" type="CanvasLayer"] [node name="App" type="CanvasLayer"]
process_mode = 3 process_mode = 3
@@ -76,36 +20,5 @@ transparent_bg = true
handle_input_locally = false handle_input_locally = false
audio_listener_enable_2d = true audio_listener_enable_2d = true
audio_listener_enable_3d = true audio_listener_enable_3d = true
size = Vector2i(1280, 960) size = Vector2i(1920, 1080)
render_target_update_mode = 4 render_target_update_mode = 4
[node name="Menu" parent="." instance=ExtResource("2_kvwo1")]
unique_name_in_owner = true
visible = false
[node name="Splash" parent="." instance=ExtResource("3_3st5l")]
unique_name_in_owner = true
[node name="BlankScreenControl" type="Control" parent="."]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="BlankScreen" type="ColorRect" parent="BlankScreenControl"]
unique_name_in_owner = true
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
color = Color(0, 0, 0, 1)
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
unique_name_in_owner = true
libraries = {
&"": SubResource("AnimationLibrary_3st5l")
}

View File

@@ -5826,77 +5826,6 @@ _data = {
&"secondary_attack_right": SubResource("Animation_5duvr") &"secondary_attack_right": SubResource("Animation_5duvr")
} }
[sub_resource type="Animation" id="Animation_vx836"]
resource_name = "appear_front"
length = 1.41667
step = 0.0833333
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Sprite3D/SubViewportContainer/SubViewport/Scrolls:animation")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [&"appear_front"]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("Sprite3D/SubViewportContainer/SubViewport/Scrolls:frame")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0, 0.0833333, 0.166667, 0.25, 0.333333, 0.416667, 0.5, 0.583333, 0.666666, 0.75, 0.833333, 0.916666, 1, 1.08333, 1.16667, 1.25, 1.33333, 1.41667),
"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),
"update": 1,
"values": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17]
}
[sub_resource type="Animation" id="Animation_iu7fp"]
resource_name = "front"
length = 8.91667
loop_mode = 2
step = 0.0833333
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Sprite3D/SubViewportContainer/SubViewport/Scrolls:animation")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [&"front"]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("Sprite3D/SubViewportContainer/SubViewport/Scrolls:frame")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0, 0.0833333, 0.166667, 0.25, 0.333333, 0.416667, 0.5, 0.583333, 0.666666, 0.75, 0.833333, 0.916666, 1, 1.08333, 1.16667, 1.25, 1.33333, 1.41667, 1.5, 1.58333, 1.66667, 1.75, 1.83333, 1.91667, 2, 2.08333, 2.16667, 2.25, 2.33333, 2.41667, 2.5, 2.58333, 2.66667, 2.75, 2.83333, 2.91667, 3, 3.08333, 3.16667, 3.25, 3.33333, 3.41667, 3.5, 3.58333, 3.66667, 3.75, 3.83333, 3.91667, 4, 4.08333, 4.16667, 4.25, 4.33333, 4.41666, 4.5, 4.58333, 4.66666, 4.75, 4.83316, 4.91666, 5, 5.08333, 5.16666, 5.25, 5.33333, 5.41666, 5.5, 5.58333, 5.66666, 5.75, 5.83333, 5.91666, 6, 6.08333, 6.16666, 6.25, 6.33333, 6.41666, 6.5, 6.58333, 6.66666, 6.75, 6.83333, 6.91666, 7, 7.08333, 7.16666, 7.25, 7.33333, 7.41666, 7.5, 7.58333, 7.66666, 7.75, 7.83333, 7.91666, 8, 8.08333, 8.16666, 8.25, 8.33333, 8.41666, 8.5, 8.58333, 8.66666, 8.75, 8.83333, 8.91666),
"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),
"update": 1,
"values": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107]
}
tracks/2/type = "value"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("Sprite3D/SubViewportContainer/SubViewport/Scrolls:z_index")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [0]
}
[sub_resource type="Animation" id="Animation_f7k3w"] [sub_resource type="Animation" id="Animation_f7k3w"]
length = 0.001 length = 0.001
tracks/0/type = "value" tracks/0/type = "value"
@@ -5965,6 +5894,35 @@ tracks/1/keys = {
"values": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17] "values": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17]
} }
[sub_resource type="Animation" id="Animation_vx836"]
resource_name = "appear_front"
length = 1.41667
step = 0.0833333
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Sprite3D/SubViewportContainer/SubViewport/Scrolls:animation")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [&"appear_front"]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("Sprite3D/SubViewportContainer/SubViewport/Scrolls:frame")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0, 0.0833333, 0.166667, 0.25, 0.333333, 0.416667, 0.5, 0.583333, 0.666666, 0.75, 0.833333, 0.916666, 1, 1.08333, 1.16667, 1.25, 1.33333, 1.41667),
"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),
"update": 1,
"values": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17]
}
[sub_resource type="Animation" id="Animation_t2d7k"] [sub_resource type="Animation" id="Animation_t2d7k"]
resource_name = "appear_left" resource_name = "appear_left"
length = 1.41667 length = 1.41667
@@ -6023,6 +5981,90 @@ tracks/1/keys = {
"values": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17] "values": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17]
} }
[sub_resource type="Animation" id="Animation_p70s4"]
resource_name = "back"
length = 8.91667
loop_mode = 2
step = 0.0833333
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Sprite3D/SubViewportContainer/SubViewport/Scrolls:animation")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [&"back"]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("Sprite3D/SubViewportContainer/SubViewport/Scrolls:frame")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0, 0.0833333, 0.166667, 0.25, 0.333333, 0.416667, 0.5, 0.583333, 0.666666, 0.75, 0.833333, 0.916666, 1, 1.08333, 1.16667, 1.25, 1.33333, 1.41667, 1.5, 1.58333, 1.66667, 1.75, 1.83333, 1.91667, 2, 2.08333, 2.16667, 2.25, 2.33333, 2.41667, 2.5, 2.58333, 2.66667, 2.75, 2.83333, 2.91667, 3, 3.08333, 3.16667, 3.25, 3.33333, 3.41667, 3.5, 3.58333, 3.66667, 3.75, 3.83333, 3.91667, 4, 4.08333, 4.16667, 4.25, 4.33333, 4.41666, 4.5, 4.58333, 4.66666, 4.75, 4.83316, 4.91666, 5, 5.08333, 5.16666, 5.25, 5.33333, 5.41666, 5.5, 5.58333, 5.66666, 5.75, 5.83333, 5.91666, 6, 6.08333, 6.16666, 6.25, 6.33333, 6.41666, 6.5, 6.58333, 6.66666, 6.75, 6.83333, 6.91666, 7, 7.08333, 7.16666, 7.25, 7.33333, 7.41666, 7.5, 7.58333, 7.66666, 7.75, 7.83333, 7.91666, 8, 8.08333, 8.16666, 8.25, 8.33333, 8.41666, 8.5, 8.58333, 8.66666, 8.75, 8.83333, 8.91666),
"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),
"update": 1,
"values": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107]
}
tracks/2/type = "value"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("Sprite3D/SubViewportContainer/SubViewport/Scrolls:z_index")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [-1]
}
[sub_resource type="Animation" id="Animation_iu7fp"]
resource_name = "front"
length = 8.91667
loop_mode = 2
step = 0.0833333
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Sprite3D/SubViewportContainer/SubViewport/Scrolls:animation")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [&"front"]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("Sprite3D/SubViewportContainer/SubViewport/Scrolls:frame")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0, 0.0833333, 0.166667, 0.25, 0.333333, 0.416667, 0.5, 0.583333, 0.666666, 0.75, 0.833333, 0.916666, 1, 1.08333, 1.16667, 1.25, 1.33333, 1.41667, 1.5, 1.58333, 1.66667, 1.75, 1.83333, 1.91667, 2, 2.08333, 2.16667, 2.25, 2.33333, 2.41667, 2.5, 2.58333, 2.66667, 2.75, 2.83333, 2.91667, 3, 3.08333, 3.16667, 3.25, 3.33333, 3.41667, 3.5, 3.58333, 3.66667, 3.75, 3.83333, 3.91667, 4, 4.08333, 4.16667, 4.25, 4.33333, 4.41666, 4.5, 4.58333, 4.66666, 4.75, 4.83316, 4.91666, 5, 5.08333, 5.16666, 5.25, 5.33333, 5.41666, 5.5, 5.58333, 5.66666, 5.75, 5.83333, 5.91666, 6, 6.08333, 6.16666, 6.25, 6.33333, 6.41666, 6.5, 6.58333, 6.66666, 6.75, 6.83333, 6.91666, 7, 7.08333, 7.16666, 7.25, 7.33333, 7.41666, 7.5, 7.58333, 7.66666, 7.75, 7.83333, 7.91666, 8, 8.08333, 8.16666, 8.25, 8.33333, 8.41666, 8.5, 8.58333, 8.66666, 8.75, 8.83333, 8.91666),
"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),
"update": 1,
"values": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107]
}
tracks/2/type = "value"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("Sprite3D/SubViewportContainer/SubViewport/Scrolls:z_index")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [0]
}
[sub_resource type="Animation" id="Animation_behrq"] [sub_resource type="Animation" id="Animation_behrq"]
resource_name = "left" resource_name = "left"
length = 8.91667 length = 8.91667
@@ -6095,48 +6137,6 @@ tracks/2/keys = {
"values": [-1] "values": [-1]
} }
[sub_resource type="Animation" id="Animation_p70s4"]
resource_name = "back"
length = 8.91667
loop_mode = 2
step = 0.0833333
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Sprite3D/SubViewportContainer/SubViewport/Scrolls:animation")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [&"back"]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("Sprite3D/SubViewportContainer/SubViewport/Scrolls:frame")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0, 0.0833333, 0.166667, 0.25, 0.333333, 0.416667, 0.5, 0.583333, 0.666666, 0.75, 0.833333, 0.916666, 1, 1.08333, 1.16667, 1.25, 1.33333, 1.41667, 1.5, 1.58333, 1.66667, 1.75, 1.83333, 1.91667, 2, 2.08333, 2.16667, 2.25, 2.33333, 2.41667, 2.5, 2.58333, 2.66667, 2.75, 2.83333, 2.91667, 3, 3.08333, 3.16667, 3.25, 3.33333, 3.41667, 3.5, 3.58333, 3.66667, 3.75, 3.83333, 3.91667, 4, 4.08333, 4.16667, 4.25, 4.33333, 4.41666, 4.5, 4.58333, 4.66666, 4.75, 4.83316, 4.91666, 5, 5.08333, 5.16666, 5.25, 5.33333, 5.41666, 5.5, 5.58333, 5.66666, 5.75, 5.83333, 5.91666, 6, 6.08333, 6.16666, 6.25, 6.33333, 6.41666, 6.5, 6.58333, 6.66666, 6.75, 6.83333, 6.91666, 7, 7.08333, 7.16666, 7.25, 7.33333, 7.41666, 7.5, 7.58333, 7.66666, 7.75, 7.83333, 7.91666, 8, 8.08333, 8.16666, 8.25, 8.33333, 8.41666, 8.5, 8.58333, 8.66666, 8.75, 8.83333, 8.91666),
"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),
"update": 1,
"values": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107]
}
tracks/2/type = "value"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("Sprite3D/SubViewportContainer/SubViewport/Scrolls:z_index")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [-1]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_bhhf1"] [sub_resource type="AnimationLibrary" id="AnimationLibrary_bhhf1"]
_data = { _data = {
&"RESET": SubResource("Animation_f7k3w"), &"RESET": SubResource("Animation_f7k3w"),

View File

@@ -31,13 +31,13 @@ public partial class Game : Node3D, IGame
public IInstantiator Instantiator { get; set; } = default!; public IInstantiator Instantiator { get; set; } = default!;
public IGameLogic GameLogic { get; set; } = default!; public IGameState GameState { get; set; } = default!;
public IGameEventDepot GameEventDepot { get; set; } = default!; public IGameEventDepot GameEventDepot { get; set; } = default!;
public IGameRepo GameRepo { get; set; } = default!; public IGameRepo GameRepo { get; set; } = default!;
public GameLogic.IBinding GameBinding { get; set; } = default!; public GameState.IBinding GameBinding { get; set; } = default!;
[Dependency] public IAppRepo AppRepo => this.DependOn<IAppRepo>(); [Dependency] public IAppRepo AppRepo => this.DependOn<IAppRepo>();
@@ -55,6 +55,8 @@ public partial class Game : Node3D, IGame
[Node] private Timer DoubleEXPTimer { get; set; } = default!; [Node] private Timer DoubleEXPTimer { get; set; } = default!;
[Node] private IPlayer Player { get; set; } = default!; [Node] private IPlayer Player { get; set; } = default!;
[Node] private MainMenu MainMenu { get; set; } = default!;
#endregion #endregion
#region Save #region Save
@@ -80,14 +82,14 @@ public partial class Game : Node3D, IGame
Module.Bootstrap(_container); Module.Bootstrap(_container);
GameRepo = _container.GetInstance<IGameRepo>(); GameRepo = _container.GetInstance<IGameRepo>();
GameLogic = _container.GetInstance<IGameLogic>(); GameState = _container.GetInstance<IGameState>();
GameEventDepot = new GameEventDepot(); GameEventDepot = new GameEventDepot();
GameLogic.Set(GameRepo); GameState.Set(GameRepo);
GameLogic.Set(AppRepo); GameState.Set(AppRepo);
GameLogic.Set(GameEventDepot); GameState.Set(GameEventDepot);
GameLogic.Set(Player); GameState.Set(Player);
GameLogic.Set(Map); GameState.Set(Map);
GameLogic.Set(InGameUI); GameState.Set(InGameUI);
Instantiator = new Instantiator(GetTree()); Instantiator = new Instantiator(GetTree());
RescuedItems = new RescuedItemDatabase(); RescuedItems = new RescuedItemDatabase();
@@ -96,37 +98,25 @@ public partial class Game : Node3D, IGame
{ {
var gameData = new GameData() var gameData = new GameData()
{ {
PlayerData = new PlayerData() PlayerData = new PlayerData()
{ {
PlayerStats = new PlayerStats() PlayerStats = Player.Stats,
{
CurrentHP = Player.Stats.CurrentHP.Value,
MaximumHP = Player.Stats.MaximumHP.Value,
CurrentVT = Player.Stats.CurrentVT.Value,
MaximumVT = Player.Stats.MaximumVT.Value,
CurrentAttack = Player.Stats.CurrentAttack.Value,
BonusAttack = Player.Stats.BonusAttack.Value,
MaxAttack = Player.Stats.MaxAttack.Value,
CurrentDefense = Player.Stats.CurrentDefense.Value,
BonusDefense = Player.Stats.BonusDefense.Value,
MaxDefense = Player.Stats.MaxDefense.Value,
CurrentExp = Player.Stats.CurrentExp.Value,
CurrentLevel = Player.Stats.CurrentLevel.Value,
ExpToNextLevel = Player.Stats.ExpToNextLevel.Value,
Luck = Player.Stats.Luck.Value
},
Inventory = Player.Inventory Inventory = Player.Inventory
}, },
MapData = new MapData() MapData = new MapData()
{ {
FloorScenes = Map.FloorScenes FloorScenes = Map.FloorScenes
}, },
RescuedItems = new RescuedItemDatabase() { Items = RescuedItems.Items } RescuedItems = new RescuedItemDatabase()
{
Items = RescuedItems.Items
}
}; };
return gameData; return gameData;
}, },
onLoad: (chunk, data) => onLoad:
(chunk, data) =>
{ {
RescuedItems = data.RescuedItems; RescuedItems = data.RescuedItems;
chunk.LoadChunkSaveData(data.PlayerData); chunk.LoadChunkSaveData(data.PlayerData);
@@ -157,30 +147,78 @@ public partial class Game : Node3D, IGame
} }
); );
GameBinding = GameLogic.Bind(); GameBinding = GameState.Bind();
GameBinding GameBinding
.Handle((in GameLogic.Output.StartGame _) => .Handle((in GameState.Output.InitializeGame _) =>
{ {
InitializeGame();
Map.LoadMap();
GameRepo.Resume(); GameRepo.Resume();
InGameUI.Show(); InGameUI.Show();
Player.InitializePlayerState(); InGameUI.PlayerInfoUI.Activate();
Player.TeleportPlayer(Map.CurrentFloor.GetPlayerSpawnPoint());
Player.Activate();
}) })
.Handle((in GameLogic.Output.GoToOverworld _) => .Handle((in GameState.Output.LoadGameFromFile _) =>
{ {
GameEventDepot.OnOverworldEntered(); LoadExistingGame();
}) })
.Handle((in GameLogic.Output.SetPauseMode output) => CallDeferred(nameof(SetPauseMode), output.IsPaused)) .Handle((in GameState.Output.OpenPauseScreen _) =>
.Handle((in GameLogic.Output.ShowPauseMenu _) =>
{ {
GameRepo.Pause();
PauseMenu.Show(); PauseMenu.Show();
PauseMenu.FadeIn(); PauseMenu.FadeIn();
Input.MouseMode = Input.MouseModeEnum.Visible; Input.MouseMode = Input.MouseModeEnum.Visible;
PauseMenu.SetProcessUnhandledInput(true); PauseMenu.SetProcessUnhandledInput(true);
}) })
.Handle((in GameLogic.Output.HidePauseMenu _) => { PauseMenu.Hide(); }) .Handle((in GameState.Output.ClosePauseScreen _) =>
.Handle((in GameLogic.Output.ExitPauseMenu _) => { PauseMenu.FadeOut(); Input.MouseMode = Input.MouseModeEnum.Visible; PauseMenu.SetProcessUnhandledInput(false); })
.Handle((in GameLogic.Output.LoadNextFloor _) =>
{ {
PauseMenu.FadeOut();
Input.MouseMode = Input.MouseModeEnum.Visible;
PauseMenu.SetProcessUnhandledInput(false);
GameRepo.Resume();
})
.Handle((in GameState.Output.OpenInventoryMenu _) =>
{
InGameUI.InventoryMenu.RefreshInventoryScreen();
InGameUI.InventoryMenu.Show();
InGameUI.InventoryMenu.SetProcessInput(true);
})
.Handle((in GameState.Output.CloseInventoryMenu _) =>
{
InGameUI.InventoryMenu.Hide();
InGameUI.InventoryMenu.SetProcessInput(false);
})
.Handle((in GameState.Output.OpenMiniMap _) =>
{
InGameUI.MiniMap.SetProcessUnhandledInput(true);
InGameUI.MiniMap.Show();
})
.Handle((in GameState.Output.CloseMiniMap _) =>
{
InGameUI.MiniMap.SetProcessUnhandledInput(false);
InGameUI.MiniMap.Hide();
})
.Handle((in GameState.Output.OpenDebugMenu _) =>
{
InGameUI.DebugMenu.Show();
InGameUI.PlayerInfoUI.Hide();
GameRepo.Pause();
})
.Handle((in GameState.Output.CloseDebugMenu _) =>
{
InGameUI.DebugMenu.Hide();
InGameUI.PlayerInfoUI.Show();
GameRepo.Resume();
})
.Handle((in GameState.Output.OpenFloorExitScreen _) =>
{
InGameUI.UseTeleportPrompt.Show();
InGameUI.UseTeleportPrompt.FadeIn();
})
.Handle((in GameState.Output.LoadNextFloor _) =>
{
InGameUI.UseTeleportPrompt.FadeOut();
Map.SpawnNextFloor(); Map.SpawnNextFloor();
if (Player.EquippedWeapon.Value.ItemTag == ItemTag.BreaksOnChange) if (Player.EquippedWeapon.Value.ItemTag == ItemTag.BreaksOnChange)
{ {
@@ -200,59 +238,49 @@ public partial class Game : Node3D, IGame
Player.Unequip(itemToDestroy); Player.Unequip(itemToDestroy);
Player.Inventory.Remove(itemToDestroy); Player.Inventory.Remove(itemToDestroy);
} }
FloorClearMenu.FadeOut();
}) })
.Handle((in GameLogic.Output.LoadMap _) => { Map.LoadMap(); }) .Handle((in GameState.Output.GameOver _) =>
.Handle((in GameLogic.Output.ShowFloorClearMenu _) => { FloorClearMenu.Show(); FloorClearMenu.FadeIn(); })
.Handle((in GameLogic.Output.ExitFloorClearMenu _) => { FloorClearMenu.FadeOut(); })
.Handle((in GameLogic.Output.ShowAskForTeleport _) => { GameRepo.Pause(); InGameUI.UseTeleportPrompt.FadeIn(); InGameUI.SetProcessInput(true); })
.Handle((in GameLogic.Output.HideAskForTeleport _) => { GameRepo.Resume(); InGameUI.UseTeleportPrompt.FadeOut(); InGameUI.SetProcessInput(false); })
.Handle((in GameLogic.Output.ShowLostScreen _) => { DeathMenu.Show(); DeathMenu.FadeIn(); })
.Handle((in GameLogic.Output.ExitLostScreen _) => { DeathMenu.FadeOut(); })
.Handle((in GameLogic.Output.DoubleExpTimeStart output) => { DoubleEXPTimer.WaitTime = output.lengthOfTimeInSeconds; DoubleEXPTimer.Start(); })
.Handle((in GameLogic.Output.SaveGame _) =>
{ {
SaveFile.Save(); GameRepo.Pause();
AppRepo.OnExitGame(); DeathMenu.FadeIn();
GetTree().Quit();
// Back to title screen
}); });
GameLogic.Start();
GameLogic.Input(new GameLogic.Input.Initialize());
GameState.Start();
this.Provide(); this.Provide();
PauseMenu.TransitionCompleted += OnPauseMenuTransitioned;
PauseMenu.UnpauseButtonPressed += PauseMenu_UnpauseButtonPressed;
InGameUI.UseTeleportPrompt.TeleportToNextFloor += UseTeleportPrompt_TeleportToNextFloor; InGameUI.UseTeleportPrompt.TeleportToNextFloor += UseTeleportPrompt_TeleportToNextFloor;
InGameUI.UseTeleportPrompt.CloseTeleportPrompt += UseTeleportPrompt_CloseTeleportPrompt;
FloorClearMenu.GoToNextFloor += FloorClearMenu_GoToNextFloor;
FloorClearMenu.SaveAndExit += FloorClearMenu_SaveAndExit;
FloorClearMenu.TransitionCompleted += FloorClearMenu_TransitionCompleted; FloorClearMenu.TransitionCompleted += FloorClearMenu_TransitionCompleted;
GameRepo.RestorativePickedUp += GameEventDepot_RestorativePickedUp; GameRepo.RestorativePickedUp += GameEventDepot_RestorativePickedUp;
DoubleEXPTimer.Timeout += DoubleEXPTimer_Timeout; DoubleEXPTimer.Timeout += DoubleEXPTimer_Timeout;
MainMenu.NewGame += OnNewGame;
MainMenu.LoadGame += OnLoadGame;
MainMenu.Quit += OnQuit;
DeathMenu.NewGame += OnContinueGame;
DeathMenu.QuitGame += OnQuit;
GameRepo.IsPaused.Sync += IsPaused_Sync;
_effectService = new EffectService(this, Player, Map); _effectService = new EffectService(this, Player, Map);
MainMenu.Show();
} }
public void LoadExistingGame() => SaveFile.Load().ContinueWith((_) => CallDeferred(nameof(FinishedLoadingSaveFile))); public void LoadExistingGame() => SaveFile.Load().ContinueWith((_) => CallDeferred(nameof(FinishedLoadingSaveFile)));
public void TogglePause() public void InitializeGame()
{ {
if (GameLogic.Value is GameLogic.State.Paused) Map.InitializeMapData();
GameLogic.Input(new GameLogic.Input.UnpauseGame()); Player.InitializePlayerState();
else
GameLogic.Input(new GameLogic.Input.PauseGame());
} }
public void FloorExitReached() public void FloorExitReached()
{ {
GameLogic.Input(new GameLogic.Input.AskForTeleport());
GameEventDepot.OnTeleportEntered(); GameEventDepot.OnTeleportEntered();
GameState.Input(new GameState.Input.FloorExitEntered());
} }
public async Task UseItem(InventoryItem item) public async Task UseItem(InventoryItem item)
@@ -335,20 +363,15 @@ public partial class Game : Node3D, IGame
return rolledItem; return rolledItem;
} }
public void GameOver()
{
GameState.Input(new GameState.Input.GameOver());
}
public override void _Input(InputEvent @event) public override void _Input(InputEvent @event)
{ {
if (@event.IsActionPressed(GameInputs.Debug) && !InGameUI.DebugMenu.Visible) if (@event.IsActionPressed(GameInputs.Debug))
{ GameState.Input(new GameState.Input.DebugButtonPressed());
InGameUI.DebugMenu.Show();
InGameUI.PlayerInfoUI.Hide();
GameRepo.Pause();
}
else if (@event.IsActionPressed(GameInputs.Debug) && InGameUI.DebugMenu.Visible)
{
InGameUI.DebugMenu.Hide();
InGameUI.PlayerInfoUI.Show();
GameRepo.Resume();
}
} }
private void DropRestorative(Vector3 vector) private void DropRestorative(Vector3 vector)
@@ -359,49 +382,24 @@ public partial class Game : Node3D, IGame
restorative.GlobalPosition = vector; restorative.GlobalPosition = vector;
} }
private void UseTeleportPrompt_CloseTeleportPrompt() => GameLogic.Input(new GameLogic.Input.HideAskForTeleport());
private void UseTeleportPrompt_TeleportToNextFloor() private void UseTeleportPrompt_TeleportToNextFloor()
{ {
GameLogic.Input(new GameLogic.Input.FloorExitReached()); InGameUI.UseTeleportPrompt.FadeIn();
GameState.Input(new GameState.Input.LoadNextFloor());
GameEventDepot.OnDungeonAThemeAreaEntered(); GameEventDepot.OnDungeonAThemeAreaEntered();
} }
private void PauseMenu_UnpauseButtonPressed() => GameLogic.Input(new GameLogic.Input.UnpauseGame());
private void Player_PauseButtonPressed() => GameLogic.Input(new GameLogic.Input.PauseGame());
private void FloorClearMenu_TransitionCompleted() private void FloorClearMenu_TransitionCompleted()
{ {
GameRepo.Resume(); GameRepo.Resume();
if (Player.EquippedWeapon.Value.ItemTag == ItemTag.BreaksOnChange)
Player.Unequip(Player.EquippedWeapon.Value);
if (Player.EquippedArmor.Value.ItemTag == ItemTag.BreaksOnChange)
Player.Unequip(Player.EquippedArmor.Value);
if (Player.EquippedAccessory.Value.ItemTag == ItemTag.BreaksOnChange)
Player.Unequip(Player.EquippedAccessory.Value);
} }
private void FloorClearMenu_GoToNextFloor() => GameLogic.Input(new GameLogic.Input.GoToNextFloor());
private void FloorClearMenu_SaveAndExit() => GameLogic.Input(new GameLogic.Input.SaveGame());
private void GameEventDepot_RestorativePickedUp(IHealthPack obj) => Player.Stats.SetCurrentVT(Player.Stats.CurrentVT.Value + (int)obj.RestoreAmount); private void GameEventDepot_RestorativePickedUp(IHealthPack obj) => Player.Stats.SetCurrentVT(Player.Stats.CurrentVT.Value + (int)obj.RestoreAmount);
private void SetPauseMode(bool isPaused) private void IsPaused_Sync(bool isPaused) => GetTree().Paused = isPaused;
{
if (GetTree() != null)
GetTree().Paused = isPaused;
}
private void DoubleEXPTimer_Timeout() => GameRepo.EndDoubleExp(); private void DoubleEXPTimer_Timeout() => GameRepo.EndDoubleExp();
public void NextFloorLoaded() => GameLogic.Input(new GameLogic.Input.HideFloorClearMenu());
private void OnPauseMenuTransitioned() => GameLogic.Input(new GameLogic.Input.PauseMenuTransitioned());
public void OnStart() => GameLogic.Input(new GameLogic.Input.StartGame());
private void FinishedLoadingSaveFile() => EmitSignal(SignalName.SaveFileLoaded); private void FinishedLoadingSaveFile() => EmitSignal(SignalName.SaveFileLoaded);
private void EnactConsumableItemEffects(ConsumableItem consumableItem) private void EnactConsumableItemEffects(ConsumableItem consumableItem)
@@ -498,4 +496,26 @@ public partial class Game : Node3D, IGame
else else
GameRepo.RemoveItemFromInventory(item); GameRepo.RemoveItemFromInventory(item);
} }
private void OnNewGame()
{
GameState.Input(new GameState.Input.NewGame());
MainMenu.Hide();
}
private void OnContinueGame()
{
GameState.Input(new GameState.Input.ContinueGame());
}
private void OnLoadGame()
{
GameState.Input(new GameState.Input.LoadGame());
MainMenu.Hide();
}
private void OnQuit()
{
MainMenu.Hide();
}
} }

View File

@@ -1,4 +1,4 @@
[gd_scene load_steps=13 format=3 uid="uid://33ek675mfb5n"] [gd_scene load_steps=19 format=3 uid="uid://33ek675mfb5n"]
[ext_resource type="Script" uid="uid://chftlu4proh3d" path="res://src/game/Game.cs" id="1_ytcii"] [ext_resource type="Script" uid="uid://chftlu4proh3d" path="res://src/game/Game.cs" id="1_ytcii"]
[ext_resource type="Shader" uid="uid://dmjxo4k2rx1an" path="res://src/app/App.gdshader" id="2_6ifxs"] [ext_resource type="Shader" uid="uid://dmjxo4k2rx1an" path="res://src/app/App.gdshader" id="2_6ifxs"]
@@ -10,7 +10,9 @@
[ext_resource type="Script" uid="uid://cbal5oeaha4nx" path="res://src/ui/pause_menu/PauseMenu.cs" id="11_5ng8c"] [ext_resource type="Script" uid="uid://cbal5oeaha4nx" path="res://src/ui/pause_menu/PauseMenu.cs" id="11_5ng8c"]
[ext_resource type="PackedScene" uid="uid://pu6gp8de3ck4" path="res://src/ui/floor_clear/FloorClearMenu.tscn" id="11_rya1n"] [ext_resource type="PackedScene" uid="uid://pu6gp8de3ck4" path="res://src/ui/floor_clear/FloorClearMenu.tscn" id="11_rya1n"]
[ext_resource type="PackedScene" uid="uid://dbtfgrtgpr4qg" path="res://src/ui/death_menu/DeathMenu.tscn" id="11_wypid"] [ext_resource type="PackedScene" uid="uid://dbtfgrtgpr4qg" path="res://src/ui/death_menu/DeathMenu.tscn" id="11_wypid"]
[ext_resource type="PackedScene" uid="uid://rfvnddfqufho" path="res://src/menu/MainMenu.tscn" id="12_ejjr5"]
[ext_resource type="PackedScene" uid="uid://blbqgw3wosc1w" path="res://src/ui/pause_menu/PauseMenu.tscn" id="12_yev8k"] [ext_resource type="PackedScene" uid="uid://blbqgw3wosc1w" path="res://src/ui/pause_menu/PauseMenu.tscn" id="12_yev8k"]
[ext_resource type="PackedScene" uid="uid://bd0p761qakisw" path="res://src/menu/splash/Splash.tscn" id="13_8i5je"]
[sub_resource type="ShaderMaterial" id="ShaderMaterial_e75a2"] [sub_resource type="ShaderMaterial" id="ShaderMaterial_e75a2"]
shader = ExtResource("2_6ifxs") shader = ExtResource("2_6ifxs")
@@ -21,6 +23,60 @@ shader_parameter/scale_resolution = false
shader_parameter/target_resolution_scale = 4 shader_parameter/target_resolution_scale = 4
shader_parameter/enable_recolor = false shader_parameter/enable_recolor = false
[sub_resource type="Animation" id="Animation_3st5l"]
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("BlankScreenControl/BlankScreen:color")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Color(0, 0, 0, 1)]
}
[sub_resource type="Animation" id="Animation_1uiag"]
resource_name = "fade_in"
length = 0.1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("BlankScreenControl/BlankScreen:color")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.1),
"transitions": PackedFloat32Array(1, 1),
"update": 0,
"values": [Color(0, 0, 0, 1), Color(0, 0, 0, 0)]
}
[sub_resource type="Animation" id="Animation_v0mgf"]
resource_name = "fade_out"
length = 0.1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("BlankScreenControl/BlankScreen:color")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.1),
"transitions": PackedFloat32Array(1, 1),
"update": 0,
"values": [Color(0, 0, 0, 0), Color(0, 0, 0, 1)]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_3st5l"]
_data = {
&"RESET": SubResource("Animation_3st5l"),
&"fade_in": SubResource("Animation_1uiag"),
&"fade_out": SubResource("Animation_v0mgf")
}
[node name="Game" type="Node3D"] [node name="Game" type="Node3D"]
process_mode = 3 process_mode = 3
script = ExtResource("1_ytcii") script = ExtResource("1_ytcii")
@@ -84,3 +140,36 @@ visible = false
unique_name_in_owner = true unique_name_in_owner = true
visible = false visible = false
script = ExtResource("11_5ng8c") script = ExtResource("11_5ng8c")
[node name="MainMenu" parent="." instance=ExtResource("12_ejjr5")]
unique_name_in_owner = true
[node name="Splash" parent="." instance=ExtResource("13_8i5je")]
unique_name_in_owner = true
visible = false
[node name="BlankScreenControl" type="Control" parent="."]
visible = false
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="BlankScreen" type="ColorRect" parent="BlankScreenControl"]
unique_name_in_owner = true
visible = false
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
color = Color(0, 0, 0, 1)
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
unique_name_in_owner = true
libraries = {
&"": SubResource("AnimationLibrary_3st5l")
}

View File

@@ -26,11 +26,9 @@ public interface IGame : IProvide<IGameRepo>, IProvide<IGameEventDepot>, IProvid
public void FloorExitReached(); public void FloorExitReached();
public void NextFloorLoaded();
public void EnemyDefeated(Vector3 defeatedLocation, EnemyStatResource enemyStatResource); public void EnemyDefeated(Vector3 defeatedLocation, EnemyStatResource enemyStatResource);
public void TogglePause();
public InventoryItem RerollItem(InventoryItem itemToReroll, bool insertIntoInventory = true); public InventoryItem RerollItem(InventoryItem itemToReroll, bool insertIntoInventory = true);
public void GameOver();
} }

View File

@@ -80,20 +80,6 @@ public partial class InventoryMenu : Control, IInventoryMenu
public void OnResolved() public void OnResolved()
{ {
Player.Stats.CurrentHP.Sync += CurrentHP_Sync;
Player.Stats.MaximumHP.Sync += MaximumHP_Sync;
Player.Stats.CurrentVT.Sync += CurrentVT_Sync;
Player.Stats.MaximumVT.Sync += MaximumVT_Sync;
Player.Stats.CurrentAttack.Sync += CurrentAttack_Sync;
Player.Stats.MaxAttack.Sync += MaxAttack_Sync;
Player.Stats.CurrentDefense.Sync += CurrentDefense_Sync;
Player.Stats.MaxDefense.Sync += MaxDefense_Sync;
Player.Stats.CurrentExp.Sync += CurrentExp_Sync;
Player.Stats.ExpToNextLevel.Sync += ExpToNextLevel_Sync;
Player.Stats.CurrentLevel.Sync += CurrentLevel_Sync;
Player.Stats.BonusAttack.Sync += BonusAttack_Sync;
Player.Stats.BonusDefense.Sync += BonusDefense_Sync;
SetProcessInput(false); SetProcessInput(false);
} }
@@ -144,6 +130,20 @@ public partial class InventoryMenu : Control, IInventoryMenu
public async Task RefreshInventoryScreen() public async Task RefreshInventoryScreen()
{ {
Player.Stats.CurrentHP.Sync += CurrentHP_Sync;
Player.Stats.MaximumHP.Sync += MaximumHP_Sync;
Player.Stats.CurrentVT.Sync += CurrentVT_Sync;
Player.Stats.MaximumVT.Sync += MaximumVT_Sync;
Player.Stats.CurrentAttack.Sync += CurrentAttack_Sync;
Player.Stats.MaxAttack.Sync += MaxAttack_Sync;
Player.Stats.CurrentDefense.Sync += CurrentDefense_Sync;
Player.Stats.MaxDefense.Sync += MaxDefense_Sync;
Player.Stats.CurrentExp.Sync += CurrentExp_Sync;
Player.Stats.ExpToNextLevel.Sync += ExpToNextLevel_Sync;
Player.Stats.CurrentLevel.Sync += CurrentLevel_Sync;
Player.Stats.BonusAttack.Sync += BonusAttack_Sync;
Player.Stats.BonusDefense.Sync += BonusDefense_Sync;
await ClearItems(); await ClearItems();
PopulateInventory(); PopulateInventory();
PopulatePlayerInfo(); PopulatePlayerInfo();
@@ -166,6 +166,19 @@ public partial class InventoryMenu : Control, IInventoryMenu
} }
else else
{ {
Player.Stats.CurrentHP.Sync -= CurrentHP_Sync;
Player.Stats.MaximumHP.Sync -= MaximumHP_Sync;
Player.Stats.CurrentVT.Sync -= CurrentVT_Sync;
Player.Stats.MaximumVT.Sync -= MaximumVT_Sync;
Player.Stats.CurrentAttack.Sync -= CurrentAttack_Sync;
Player.Stats.MaxAttack.Sync -= MaxAttack_Sync;
Player.Stats.CurrentDefense.Sync -= CurrentDefense_Sync;
Player.Stats.MaxDefense.Sync -= MaxDefense_Sync;
Player.Stats.CurrentExp.Sync -= CurrentExp_Sync;
Player.Stats.ExpToNextLevel.Sync -= ExpToNextLevel_Sync;
Player.Stats.CurrentLevel.Sync -= CurrentLevel_Sync;
Player.Stats.BonusAttack.Sync -= BonusAttack_Sync;
Player.Stats.BonusDefense.Sync -= BonusDefense_Sync;
_gameRepo.CloseInventory(); _gameRepo.CloseInventory();
} }
} }

View File

@@ -0,0 +1,28 @@
using Chickensoft.AutoInject;
using Chickensoft.GodotNodeInterfaces;
using Chickensoft.SaveFileBuilder;
using Godot;
using System.Collections.Generic;
namespace Zennysoft.Game.Ma;
public interface IMap : INode3D, IProvide<ISaveChunk<MapData>>
{
void LoadMap();
void LoadFloor();
List<string> FloorScenes { get; }
IDungeonFloor CurrentFloor { get; }
void SpawnNextFloor();
Transform3D GetPlayerSpawnPosition();
IDungeonRoom GetPlayersCurrentRoom();
void InitializeMapData();
public int CurrentFloorNumber { get; }
}

View File

@@ -0,0 +1 @@
uid://b2q36geko8vms

View File

@@ -1,5 +1,4 @@
using Chickensoft.AutoInject; using Chickensoft.AutoInject;
using Chickensoft.GodotNodeInterfaces;
using Chickensoft.Introspection; using Chickensoft.Introspection;
using Chickensoft.SaveFileBuilder; using Chickensoft.SaveFileBuilder;
using Godot; using Godot;
@@ -9,24 +8,6 @@ using Zennysoft.Ma.Adapter;
namespace Zennysoft.Game.Ma; namespace Zennysoft.Game.Ma;
public interface IMap : INode3D, IProvide<ISaveChunk<MapData>>
{
void LoadMap();
List<string> FloorScenes { get; }
IDungeonFloor CurrentFloor { get; }
void SpawnNextFloor();
Transform3D GetPlayerSpawnPosition();
IDungeonRoom GetPlayersCurrentRoom();
public int CurrentFloorNumber { get; }
}
[Meta(typeof(IAutoNode))] [Meta(typeof(IAutoNode))]
public partial class Map : Node3D, IMap public partial class Map : Node3D, IMap
{ {
@@ -50,7 +31,7 @@ public partial class Map : Node3D, IMap
[Export] [Export]
private Godot.Collections.Array<PackedScene> _floors { get; set; } = default!; private Godot.Collections.Array<PackedScene> _floors { get; set; } = default!;
public List<string> FloorScenes { get; private set; } public List<string> FloorScenes { get; private set; } = [];
public IDungeonFloor CurrentFloor { get; private set; } public IDungeonFloor CurrentFloor { get; private set; }
@@ -58,8 +39,6 @@ public partial class Map : Node3D, IMap
public void OnResolved() public void OnResolved()
{ {
FloorScenes = [];
MapChunk = new SaveChunk<MapData>( MapChunk = new SaveChunk<MapData>(
onSave: (chunk) => new MapData() onSave: (chunk) => new MapData()
{ {
@@ -74,31 +53,41 @@ public partial class Map : Node3D, IMap
GameChunk.AddChunk(MapChunk); GameChunk.AddChunk(MapChunk);
this.Provide(); this.Provide();
InitializeMapData();
}
public void InitializeMapData()
{
ClearMap();
FloorScenes = [];
foreach (var floor in _floors)
FloorScenes.Add(floor.ResourcePath);
CurrentFloorNumber = 0;
} }
public void LoadMap() public void LoadMap()
{ {
foreach (var floor in _floors)
FloorScenes.Add(floor.ResourcePath);
LoadFloor(); LoadFloor();
CurrentFloor.InitializeDungeon(); CurrentFloor.InitializeDungeon();
var transform = GetPlayerSpawnPosition(); var transform = GetPlayerSpawnPosition();
Player.TeleportPlayer(transform); Player.TeleportPlayer(transform);
CurrentFloor.FloorIsLoaded = true; CurrentFloor.FloorIsLoaded = true;
Game.NextFloorLoaded(); }
private void ClearMap()
{
CurrentFloor?.CallDeferred(MethodName.QueueFree, []);
} }
public void SpawnNextFloor() public void SpawnNextFloor()
{ {
var oldFloor = CurrentFloor; ClearMap();
oldFloor.CallDeferred(MethodName.QueueFree, []);
LoadFloor(); LoadFloor();
CurrentFloor.InitializeDungeon(); CurrentFloor.InitializeDungeon();
var transform = GetPlayerSpawnPosition(); var transform = GetPlayerSpawnPosition();
Player.TeleportPlayer(transform); Player.TeleportPlayer(transform);
CurrentFloor.FloorIsLoaded = true; CurrentFloor.FloorIsLoaded = true;
Game.NextFloorLoaded();
CurrentFloorNumber += 1; CurrentFloorNumber += 1;
} }
@@ -111,13 +100,16 @@ public partial class Map : Node3D, IMap
public Transform3D GetPlayerSpawnPosition() => CurrentFloor.GetPlayerSpawnPoint(); public Transform3D GetPlayerSpawnPosition() => CurrentFloor.GetPlayerSpawnPoint();
private void LoadFloor() public void LoadFloor()
{ {
ClearMap();
var currentFloorScene = FloorScenes.First(); var currentFloorScene = FloorScenes.First();
var instantiator = new Instantiator(GetTree()); var instantiator = new Instantiator(GetTree());
var loadedScene = instantiator.LoadAndInstantiate<Node3D>(currentFloorScene); var loadedScene = instantiator.LoadAndInstantiate<Node3D>(currentFloorScene);
AddChild(loadedScene); AddChild(loadedScene);
CurrentFloor = (IDungeonFloor)loadedScene; CurrentFloor = (IDungeonFloor)loadedScene;
FloorScenes.Remove(currentFloorScene); FloorScenes.Remove(currentFloorScene);
var transform = GetPlayerSpawnPosition();
Player.TeleportPlayer(transform);
} }
} }

View File

@@ -1,21 +1,12 @@
[gd_scene load_steps=14 format=3 uid="uid://by67pn7fdsg1m"] [gd_scene load_steps=5 format=3 uid="uid://by67pn7fdsg1m"]
[ext_resource type="Script" uid="uid://14e8mu48ed4" path="res://src/map/Map.cs" id="1_bw70o"] [ext_resource type="Script" uid="uid://14e8mu48ed4" path="res://src/map/Map.cs" id="1_bw70o"]
[ext_resource type="PackedScene" uid="uid://dl6h1djc27ddl" path="res://src/map/dungeon/floors/Floor00.tscn" id="2_0m8h8"] [ext_resource type="PackedScene" uid="uid://dl6h1djc27ddl" path="res://src/map/dungeon/floors/Floor00.tscn" id="3_s7lwc"]
[ext_resource type="PackedScene" uid="uid://bc1sp6xwe0j65" path="res://src/map/dungeon/floors/Floor01.tscn" id="2_merfv"] [ext_resource type="PackedScene" uid="uid://dmiqwmivkjgmq" path="res://src/map/dungeon/floors/Floor02.tscn" id="4_0qcd2"]
[ext_resource type="PackedScene" uid="uid://g28xmp6cn16h" path="res://src/map/dungeon/floors/Floor10.tscn" id="3_caf7v"] [ext_resource type="PackedScene" uid="uid://bc1sp6xwe0j65" path="res://src/map/dungeon/floors/Floor01.tscn" id="4_1ny7u"]
[ext_resource type="PackedScene" uid="uid://w2peiubnalof" path="res://src/map/dungeon/floors/Floor20.tscn" id="3_y74f3"]
[ext_resource type="PackedScene" uid="uid://dmiqwmivkjgmq" path="res://src/map/dungeon/floors/Floor02.tscn" id="4_8y0oy"]
[ext_resource type="PackedScene" uid="uid://dl1scvkp8r5sw" path="res://src/map/dungeon/floors/Floor03.tscn" id="5_uag72"]
[ext_resource type="PackedScene" uid="uid://cikq7vuorlpbl" path="res://src/map/dungeon/floors/Floor04.tscn" id="6_55rmo"]
[ext_resource type="PackedScene" uid="uid://t7cac7801bnk" path="res://src/map/dungeon/floors/Floor05.tscn" id="7_f6kwn"]
[ext_resource type="PackedScene" uid="uid://da107mywg18x1" path="res://src/map/dungeon/floors/Floor06.tscn" id="8_ne2vg"]
[ext_resource type="PackedScene" uid="uid://cgtqjgh1f5fqi" path="res://src/map/dungeon/floors/Floor07.tscn" id="9_abpbr"]
[ext_resource type="PackedScene" uid="uid://dg20ovvj2m2lp" path="res://src/map/dungeon/floors/Floor08.tscn" id="10_caf7v"]
[ext_resource type="PackedScene" uid="uid://b5jk743ng6fqg" path="res://src/map/dungeon/floors/Floor09.tscn" id="11_y74f3"]
[node name="Map" type="Node3D"] [node name="Map" type="Node3D"]
script = ExtResource("1_bw70o") script = ExtResource("1_bw70o")
_floors = Array[PackedScene]([ExtResource("2_0m8h8"), ExtResource("2_merfv"), ExtResource("4_8y0oy"), ExtResource("5_uag72"), ExtResource("6_55rmo"), ExtResource("7_f6kwn"), ExtResource("8_ne2vg"), ExtResource("9_abpbr"), ExtResource("10_caf7v"), ExtResource("11_y74f3"), ExtResource("3_caf7v"), ExtResource("3_y74f3")]) _floors = Array[PackedScene]([ExtResource("3_s7lwc"), ExtResource("4_1ny7u"), ExtResource("4_0qcd2")])
[node name="WorldEnvironment" type="WorldEnvironment" parent="."] [node name="WorldEnvironment" type="WorldEnvironment" parent="."]

View File

@@ -1,6 +1,7 @@
using Chickensoft.AutoInject; using Chickensoft.AutoInject;
using Chickensoft.Introspection; using Chickensoft.Introspection;
using Godot; using Godot;
using Zennysoft.Ma.Adapter;
namespace Zennysoft.Game.Ma; namespace Zennysoft.Game.Ma;
@@ -63,5 +64,9 @@ public partial class BossRoomA : Node3D, IBossRoom
public void ExitReached() public void ExitReached()
=> Game.FloorExitReached(); => Game.FloorExitReached();
private void Exit_AreaEntered(Area3D area) => ExitReached(); private void Exit_AreaEntered(Area3D area)
{
if (area.GetOwner() is IPlayer)
ExitReached();
}
} }

View File

@@ -1,6 +1,7 @@
using Chickensoft.AutoInject; using Chickensoft.AutoInject;
using Chickensoft.Introspection; using Chickensoft.Introspection;
using Godot; using Godot;
using Zennysoft.Ma.Adapter;
namespace Zennysoft.Game.Ma; namespace Zennysoft.Game.Ma;
@@ -21,5 +22,9 @@ public partial class ExitRoom : DungeonRoom
public void ExitReached() public void ExitReached()
=> Game.FloorExitReached(); => Game.FloorExitReached();
private void Exit_AreaEntered(Area3D area) => ExitReached(); private void Exit_AreaEntered(Area3D area)
{
if (area.GetOwner() is IPlayer)
ExitReached();
}
} }

View File

@@ -2,6 +2,7 @@ using Chickensoft.AutoInject;
using Chickensoft.Introspection; using Chickensoft.Introspection;
using Godot; using Godot;
using System.Collections.Immutable; using System.Collections.Immutable;
using Zennysoft.Ma.Adapter;
namespace Zennysoft.Game.Ma; namespace Zennysoft.Game.Ma;
@@ -27,7 +28,11 @@ public partial class Floor0 : Node3D, IDungeonFloor
FloorIsLoaded = true; FloorIsLoaded = true;
} }
private void Exit_AreaEntered(Area3D area) => ExitReached(); private void Exit_AreaEntered(Area3D area)
{
if (area.GetOwner() is IPlayer)
ExitReached();
}
public void ExitReached() => Game.FloorExitReached(); public void ExitReached() => Game.FloorExitReached();
public void InitializeDungeon() { return; } public void InitializeDungeon() { return; }

File diff suppressed because one or more lines are too long

View File

@@ -5,15 +5,15 @@ using Godot;
namespace Zennysoft.Game.Ma; namespace Zennysoft.Game.Ma;
public interface IMenu : IControl public interface IMainMenu : IControl
{ {
event Menu.NewGameEventHandler NewGame; event MainMenu.NewGameEventHandler NewGame;
event Menu.LoadGameEventHandler LoadGame; event MainMenu.LoadGameEventHandler LoadGame;
event Menu.QuitEventHandler Quit; event MainMenu.QuitEventHandler Quit;
} }
[Meta(typeof(IAutoNode))] [Meta(typeof(IAutoNode))]
public partial class Menu : Control, IMenu public partial class MainMenu : Control, IMainMenu
{ {
public override void _Notification(int what) => this.Notify(what); public override void _Notification(int what) => this.Notify(what);

View File

@@ -1,15 +1,15 @@
[gd_scene load_steps=2 format=3 uid="uid://rfvnddfqufho"] [gd_scene load_steps=2 format=3 uid="uid://rfvnddfqufho"]
[ext_resource type="Script" uid="uid://14b7o2c6cgry" path="res://src/menu/Menu.cs" id="1_vehpg"] [ext_resource type="Script" uid="uid://14b7o2c6cgry" path="res://src/menu/MainMenu.cs" id="1_y6722"]
[node name="Menu" type="Control"] [node name="MainMenu" type="Control"]
layout_mode = 3 layout_mode = 3
anchors_preset = 15 anchors_preset = 15
anchor_right = 1.0 anchor_right = 1.0
anchor_bottom = 1.0 anchor_bottom = 1.0
grow_horizontal = 2 grow_horizontal = 2
grow_vertical = 2 grow_vertical = 2
script = ExtResource("1_vehpg") script = ExtResource("1_y6722")
[node name="MarginContainer" type="MarginContainer" parent="."] [node name="MarginContainer" type="MarginContainer" parent="."]
layout_mode = 1 layout_mode = 1

View File

@@ -31,7 +31,8 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<ISaveChunk<Play
public Vector3 CurrentPosition => GlobalPosition; public Vector3 CurrentPosition => GlobalPosition;
public Basis CurrentBasis => Transform.Basis; public Basis CurrentBasis => Transform.Basis;
public PlayerStatController Stats { get; set; } = default!;
public PlayerStats Stats { get; set; } = default!;
public IInventory Inventory { get; private set; } = default!; public IInventory Inventory { get; private set; } = default!;
@@ -61,12 +62,7 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<ISaveChunk<Play
#region Exports #region Exports
[Export] [Export]
public PlayerStatResource PlayerStatResource { get; set; } = default!; private PlayerStatResource _playerStatResource { get; set; } = default!;
[Export]
private WeaponStats _defaultWeapon { get; set; } = default!;
[Export]
private ArmorStats _defaultArmor { get; set; } = default!;
#endregion #endregion
#region Node Dependencies #region Node Dependencies
@@ -100,6 +96,32 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<ISaveChunk<Play
#region Initialization #region Initialization
public void InitializePlayerState() public void InitializePlayerState()
{ {
Inventory = new Inventory();
Stats = InitializePlayerStats();
SetProcessInput(false);
SetPhysicsProcess(false);
EquippedWeapon.Changed += EquippedWeapon_Sync;
EquippedArmor.Changed += EquippedArmor_Sync;
EquippedAccessory.Changed += EquippedAccessory_Sync;
Stats.CurrentHP.Changed += CurrentHP_Sync;
Stats.CurrentExp.Changed += CurrentEXP_Sync;
HealthTimer.WaitTime = _healthTimerWaitTime;
HealthTimer.Timeout += OnHealthTimerTimeout;
}
public void Setup()
{
var container = new SimpleInjector.Container();
container.Register<IPlayerLogic, PlayerLogic>(Lifestyle.Singleton);
//container.Verify();
PlayerLogic = container.GetInstance<IPlayerLogic>();
PlayerLogic.Set(this as IPlayer);
PlayerLogic.Set(Settings);
PlayerLogic.Set(Stats);
PlayerLogic.Set(_gameRepo);
_expToNextLevel = new Dictionary<int, int> _expToNextLevel = new Dictionary<int, int>
{ {
{ 2, 12 }, { 2, 12 },
@@ -112,97 +134,38 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<ISaveChunk<Play
}; };
_damageCalculator = new DamageCalculator(); _damageCalculator = new DamageCalculator();
Stats = new PlayerStatController();
Stats.Init(
new PlayerStats
{
CurrentHP = PlayerStatResource.CurrentHP,
MaximumHP = PlayerStatResource.MaximumHP,
CurrentVT = PlayerStatResource.CurrentVT,
MaximumVT = PlayerStatResource.MaximumVT,
CurrentAttack = PlayerStatResource.CurrentAttack,
BonusAttack = PlayerStatResource.BonusAttack,
MaxAttack = PlayerStatResource.MaxAttack,
CurrentDefense = PlayerStatResource.CurrentDefense,
BonusDefense = PlayerStatResource.BonusDefense,
MaxDefense = PlayerStatResource.MaxDefense,
CurrentExp = PlayerStatResource.CurrentExp,
CurrentLevel = PlayerStatResource.CurrentLevel,
ExpToNextLevel = PlayerStatResource.ExpToNextLevel,
Luck = PlayerStatResource.Luck
});
Inventory = new Inventory();
var defaultWeapon = new Weapon
{
Stats = _defaultWeapon
};
var defaultArmor = new Armor
{
Stats = _defaultArmor
};
Inventory.TryAdd(defaultWeapon);
Inventory.TryAdd(defaultArmor);
Equip(defaultWeapon);
Equip(defaultArmor);
EquippedWeapon.Sync += EquippedWeapon_Sync;
EquippedArmor.Sync += EquippedArmor_Sync;
EquippedAccessory.Sync += EquippedAccessory_Sync;
Stats.CurrentHP.Sync += CurrentHP_Sync;
Stats.CurrentExp.Sync += CurrentEXP_Sync;
HealthTimer.WaitTime = _healthTimerWaitTime;
HealthTimer.Timeout += OnHealthTimerTimeout;
Hitbox.AreaEntered += Hitbox_AreaEntered; Hitbox.AreaEntered += Hitbox_AreaEntered;
CollisionDetector.AreaEntered += CollisionDetector_AreaEntered; CollisionDetector.AreaEntered += CollisionDetector_AreaEntered;
AnimationPlayer.AnimationFinished += OnAnimationFinished; AnimationPlayer.AnimationFinished += OnAnimationFinished;
} }
public void Setup()
{
var container = new SimpleInjector.Container();
container.Register<IPlayerLogic, PlayerLogic>(Lifestyle.Singleton);
//container.Verify();
Settings = new PlayerLogic.Settings() { RotationSpeed = PlayerStatResource.RotationSpeed, MoveSpeed = PlayerStatResource.MoveSpeed, Acceleration = PlayerStatResource.Acceleration };
PlayerLogic = container.GetInstance<IPlayerLogic>();
PlayerLogic.Set(this as IPlayer);
PlayerLogic.Set(Settings);
PlayerLogic.Set(Stats);
PlayerLogic.Set(_gameRepo);
}
public void OnResolved() public void OnResolved()
{ {
Settings = new PlayerLogic.Settings() { RotationSpeed = _playerStatResource.RotationSpeed, MoveSpeed = _playerStatResource.MoveSpeed, Acceleration = _playerStatResource.Acceleration };
PlayerChunk = new SaveChunk<PlayerData>( PlayerChunk = new SaveChunk<PlayerData>(
onSave: (chunk) => new PlayerData() onSave: (chunk) => new PlayerData()
{ {
PlayerStats = new PlayerStats() PlayerStats = Stats,
{
CurrentHP = Stats.CurrentHP.Value,
MaximumHP = Stats.MaximumHP.Value,
CurrentVT = Stats.CurrentVT.Value,
MaximumVT = Stats.MaximumVT.Value,
CurrentAttack = Stats.CurrentAttack.Value,
BonusAttack = Stats.BonusAttack.Value,
MaxAttack = Stats.MaxAttack.Value,
CurrentDefense = Stats.CurrentDefense.Value,
BonusDefense = Stats.BonusDefense.Value,
MaxDefense = Stats.MaxDefense.Value,
CurrentExp = Stats.CurrentExp.Value,
CurrentLevel = Stats.CurrentLevel.Value,
ExpToNextLevel = Stats.ExpToNextLevel.Value,
Luck = Stats.Luck.Value
},
Inventory = Inventory Inventory = Inventory
}, },
onLoad: (chunk, data) => onLoad: (chunk, data) =>
{ {
Stats.Init(data.PlayerStats); Stats = new PlayerStats(
data.PlayerStats.CurrentHP,
data.PlayerStats.MaximumHP,
data.PlayerStats.CurrentVT,
data.PlayerStats.MaximumVT,
data.PlayerStats.CurrentAttack,
data.PlayerStats.BonusAttack,
data.PlayerStats.MaxAttack,
data.PlayerStats.CurrentDefense,
data.PlayerStats.BonusDefense,
data.PlayerStats.MaxDefense,
data.PlayerStats.CurrentExp,
data.PlayerStats.CurrentLevel,
data.PlayerStats.ExpToNextLevel,
data.PlayerStats.Luck);
Inventory = data.Inventory; Inventory = data.Inventory;
} }
); );
@@ -234,25 +197,29 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<ISaveChunk<Play
PlayerLogic.Start(); PlayerLogic.Start();
this.Provide(); this.Provide();
SetProcessInput(false);
SetPhysicsProcess(false);
} }
public void OnReady() public void OnReady()
{ {
SetPhysicsProcess(true);
SwordSlashAnimation.Position = GetViewport().GetVisibleRect().Size / 2; SwordSlashAnimation.Position = GetViewport().GetVisibleRect().Size / 2;
} }
#endregion #endregion
public void Activate()
{
SetProcessInput(true);
SetPhysicsProcess(true);
HealthTimer.Start();
}
public void Attack() public void Attack()
{ {
PlayerLogic.Input(new PlayerLogic.Input.Attack()); PlayerLogic.Input(new PlayerLogic.Input.Attack());
} }
public void PlayerPause()
{
Game.TogglePause();
}
public void RaiseHP(int amountToRaise) public void RaiseHP(int amountToRaise)
{ {
Stats.SetMaximumHP(Stats.MaximumHP.Value + amountToRaise); Stats.SetMaximumHP(Stats.MaximumHP.Value + amountToRaise);
@@ -374,17 +341,17 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<ISaveChunk<Play
HealthTimer.WaitTime = _healthTimerWaitTime; HealthTimer.WaitTime = _healthTimerWaitTime;
HealthTimer.Timeout -= OnHealthTimerTimeout; HealthTimer.Timeout -= OnHealthTimerTimeout;
Hitbox.AreaEntered -= Hitbox_AreaEntered; SetProcessInput(false);
CollisionDetector.AreaEntered -= CollisionDetector_AreaEntered; SetPhysicsProcess(false);
AnimationPlayer.AnimationFinished -= OnAnimationFinished; //Hitbox.AreaEntered -= Hitbox_AreaEntered;
PlayerLogic.Input(new PlayerLogic.Input.Die()); //CollisionDetector.AreaEntered -= CollisionDetector_AreaEntered;
//AnimationPlayer.AnimationFinished -= OnAnimationFinished;
Game.GameOver();
} }
public override void _UnhandledInput(InputEvent @event) public override void _Input(InputEvent @event)
{ {
if (@event.IsActionPressed(GameInputs.Pause))
PlayerPause();
if (@event.IsActionPressed(GameInputs.Attack)) if (@event.IsActionPressed(GameInputs.Attack))
Attack(); Attack();
} }
@@ -637,6 +604,27 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<ISaveChunk<Play
} }
} }
private PlayerStats InitializePlayerStats()
{
var playerStats = new PlayerStats(
currentHP: new AutoProp<int>(_playerStatResource.CurrentHP),
maximumHP: new AutoProp<int>(_playerStatResource.MaximumHP),
currentVT: new AutoProp<int>(_playerStatResource.CurrentVT),
maximumVT: new AutoProp<int>(_playerStatResource.MaximumVT),
currentAttack: new AutoProp<int>(_playerStatResource.CurrentAttack),
currentDefense: new AutoProp<int>(_playerStatResource.CurrentDefense),
maxAttack: new AutoProp<int>(_playerStatResource.MaxAttack),
maxDefense: new AutoProp<int>(_playerStatResource.MaxDefense),
bonusAttack: new AutoProp<int>(_playerStatResource.BonusAttack),
bonusDefense: new AutoProp<int>(_playerStatResource.BonusDefense),
currentExp: new AutoProp<double>(_playerStatResource.CurrentExp),
expToNextLevel: new AutoProp<int>(_playerStatResource.ExpToNextLevel),
currentLevel: new AutoProp<int>(_playerStatResource.CurrentLevel),
luck: new AutoProp<double>(_playerStatResource.Luck));
return playerStats;
}
private bool PlayerIsHittingGeometry() private bool PlayerIsHittingGeometry()
{ {
var collisions = WallCheck.GetCollidingBodies(); var collisions = WallCheck.GetCollidingBodies();

View File

@@ -1,10 +1,8 @@
[gd_scene load_steps=62 format=4 uid="uid://cfecvvav8kkp6"] [gd_scene load_steps=60 format=4 uid="uid://cfecvvav8kkp6"]
[ext_resource type="Script" uid="uid://yxmiqy7i0t7r" path="res://src/player/Player.cs" id="1_xcol5"] [ext_resource type="Script" uid="uid://yxmiqy7i0t7r" path="res://src/player/Player.cs" id="1_xcol5"]
[ext_resource type="Script" uid="uid://s6ku2kyc4rbk" path="res://src/player/PlayerStatResource.cs" id="2_ebyyx"]
[ext_resource type="Script" uid="uid://6edayafleq8y" path="res://src/hitbox/Hitbox.cs" id="2_lb3qc"] [ext_resource type="Script" uid="uid://6edayafleq8y" path="res://src/hitbox/Hitbox.cs" id="2_lb3qc"]
[ext_resource type="Script" uid="uid://s6ku2kyc4rbk" path="res://src/player/PlayerStatResource.cs" id="2_xq68d"]
[ext_resource type="Resource" uid="uid://bpdbuf0k0exb5" path="res://src/items/weapons/resources/Swan Sword Odette.tres" id="3_es4xk"]
[ext_resource type="Resource" uid="uid://ce2vfa2t3io67" path="res://src/items/armor/resources/AtonersAdornments.tres" id="4_bj1ma"]
[ext_resource type="Texture2D" uid="uid://c6r3dhnkuw22w" path="res://src/vfx/hit_effects/FIRE_STRIKE_1.0.png" id="5_wr6lo"] [ext_resource type="Texture2D" uid="uid://c6r3dhnkuw22w" path="res://src/vfx/hit_effects/FIRE_STRIKE_1.0.png" id="5_wr6lo"]
[ext_resource type="Texture2D" uid="uid://m6xsyhnt67sh" path="res://src/player/dont_look_in_here/tendomaya_body0_tex00.png" id="6_es4xk"] [ext_resource type="Texture2D" uid="uid://m6xsyhnt67sh" path="res://src/player/dont_look_in_here/tendomaya_body0_tex00.png" id="6_es4xk"]
[ext_resource type="Texture2D" uid="uid://b5qjlbcesth53" path="res://src/vfx/Weapon Strikes/NON ELEMENTAL SLASH.png" id="6_p34sl"] [ext_resource type="Texture2D" uid="uid://b5qjlbcesth53" path="res://src/vfx/Weapon Strikes/NON ELEMENTAL SLASH.png" id="6_p34sl"]
@@ -12,25 +10,26 @@
[ext_resource type="Texture2D" uid="uid://qxq1jjr1cojo" path="res://src/player/dont_look_in_here/tendomaya_face10_tex00.png" id="7_g183x"] [ext_resource type="Texture2D" uid="uid://qxq1jjr1cojo" path="res://src/player/dont_look_in_here/tendomaya_face10_tex00.png" id="7_g183x"]
[ext_resource type="Texture2D" uid="uid://brr8uow0xte2o" path="res://src/player/dont_look_in_here/tendomaya_face20_tex00.png" id="8_ojh85"] [ext_resource type="Texture2D" uid="uid://brr8uow0xte2o" path="res://src/player/dont_look_in_here/tendomaya_face20_tex00.png" id="8_ojh85"]
[sub_resource type="Resource" id="Resource_btp2w"] [sub_resource type="Resource" id="Resource_bj1ma"]
script = ExtResource("2_xq68d") script = ExtResource("2_ebyyx")
RotationSpeed = 1.5 RotationSpeed = 1.5
MoveSpeed = 8.0 MoveSpeed = 4.0
Acceleration = 1.0 Acceleration = 2.0
CurrentHP = 100 CurrentHP = 1
MaximumHP = 100 MaximumHP = 100
CurrentVT = 0 CurrentVT = 1
MaximumVT = 90 MaximumVT = 100
CurrentExp = 0 CurrentExp = 0
ExpToNextLevel = 10 ExpToNextLevel = 12
CurrentLevel = 1 CurrentLevel = 1
CurrentAttack = 8 CurrentAttack = 10
BonusAttack = 0 BonusAttack = 0
MaxAttack = 8 MaxAttack = 10
CurrentDefense = 1 CurrentDefense = 10
BonusDefense = 0 BonusDefense = 0
MaxDefense = 1 MaxDefense = 10
Luck = 0.05 Luck = 0.1
metadata/_custom_type_script = "uid://s6ku2kyc4rbk"
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_dw45s"] [sub_resource type="CapsuleShape3D" id="CapsuleShape3D_dw45s"]
radius = 1.0 radius = 1.0
@@ -490,9 +489,7 @@ height = 1.6909
collision_layer = 806 collision_layer = 806
collision_mask = 775 collision_mask = 775
script = ExtResource("1_xcol5") script = ExtResource("1_xcol5")
PlayerStatResource = SubResource("Resource_btp2w") _playerStatResource = SubResource("Resource_bj1ma")
_defaultWeapon = ExtResource("3_es4xk")
_defaultArmor = ExtResource("4_bj1ma")
[node name="PlayerGeometryCollision" type="CollisionShape3D" parent="."] [node name="PlayerGeometryCollision" type="CollisionShape3D" parent="."]
transform = Transform3D(-0.0242402, 0, 0.999706, 0, 1, 0, -0.999706, 0, -0.0242402, 0, 1.06447, -0.153069) transform = Transform3D(-0.0242402, 0, 0.999706, 0, 1, 0, -0.999706, 0, -0.0242402, 0, 1.06447, -0.153069)

View File

@@ -17,11 +17,11 @@ public partial class PlayerStatResource : Resource
[Export(PropertyHint.Range, "0, 100, 0.1")] [Export(PropertyHint.Range, "0, 100, 0.1")]
public float Acceleration { get; set; } = 4f; public float Acceleration { get; set; } = 4f;
[Export] public int CurrentHP { get; set; } [Export(PropertyHint.Range, "1, 200, 1")] public int CurrentHP { get; set; }
[Export] public int MaximumHP { get; set; } [Export(PropertyHint.Range, "1, 200, 1")] public int MaximumHP { get; set; }
[Export] public int CurrentVT { get; set; } [Export(PropertyHint.Range, "1, 200, 1")] public int CurrentVT { get; set; }
[Export] public int MaximumVT { get; set; } [Export(PropertyHint.Range, "1, 200, 1")] public int MaximumVT { get; set; }
[Export] public int CurrentExp { get; set; } [Export] public int CurrentExp { get; set; }
[Export] public int ExpToNextLevel { get; set; } [Export] public int ExpToNextLevel { get; set; }

View File

@@ -17,6 +17,11 @@ public partial class DeathMenu : Control, IDeathMenu
{ {
public override void _Notification(int what) => this.Notify(what); public override void _Notification(int what) => this.Notify(what);
[Signal]
public delegate void NewGameEventHandler();
[Signal]
public delegate void QuitGameEventHandler();
[Dependency] Game Game => this.DependOn<Game>(); [Dependency] Game Game => this.DependOn<Game>();
[Node] public IAnimationPlayer AnimationPlayer { get; set; } = default!; [Node] public IAnimationPlayer AnimationPlayer { get; set; } = default!;
@@ -42,13 +47,13 @@ public partial class DeathMenu : Control, IDeathMenu
private void Exit_Pressed() private void Exit_Pressed()
{ {
GetTree().Quit(); EmitSignal(SignalName.QuitGame);
} }
private void Continue_Pressed() private void Continue_Pressed()
{ {
FadeOut(); FadeOut();
Game.GameLogic.Input(new GameLogic.Input.GoToOverworld()); EmitSignal(SignalName.NewGame);
} }
public void FadeIn() => AnimationPlayer.Play("fade_in"); public void FadeIn() => AnimationPlayer.Play("fade_in");

View File

@@ -17,6 +17,18 @@ tracks/0/keys = {
"update": 0, "update": 0,
"values": [Color(1, 1, 1, 1)] "values": [Color(1, 1, 1, 1)]
} }
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath(".:visible")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0.001),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [false]
}
[sub_resource type="Animation" id="Animation_q2nvr"] [sub_resource type="Animation" id="Animation_q2nvr"]
resource_name = "fade_in" resource_name = "fade_in"
@@ -33,6 +45,18 @@ tracks/0/keys = {
"update": 0, "update": 0,
"values": [Color(1, 1, 1, 0), Color(1, 1, 1, 1)] "values": [Color(1, 1, 1, 0), Color(1, 1, 1, 1)]
} }
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath(".:visible")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [true]
}
[sub_resource type="Animation" id="Animation_6ji3u"] [sub_resource type="Animation" id="Animation_6ji3u"]
resource_name = "fade_out" resource_name = "fade_out"
@@ -49,6 +73,18 @@ tracks/0/keys = {
"update": 0, "update": 0,
"values": [Color(1, 1, 1, 1), Color(1, 1, 1, 0)] "values": [Color(1, 1, 1, 1), Color(1, 1, 1, 0)]
} }
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath(".:visible")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0, 0.5),
"transitions": PackedFloat32Array(1, 1),
"update": 1,
"values": [true, false]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_ek7oy"] [sub_resource type="AnimationLibrary" id="AnimationLibrary_ek7oy"]
_data = { _data = {

View File

@@ -9,6 +9,8 @@ namespace Zennysoft.Game.Ma;
public interface IPlayerInfoUI : IControl public interface IPlayerInfoUI : IControl
{ {
public void DisplayMessage(string message); public void DisplayMessage(string message);
public void Activate();
} }
[Meta(typeof(IAutoNode))] [Meta(typeof(IAutoNode))]
@@ -33,6 +35,10 @@ public partial class PlayerInfoUI : Control, IPlayerInfoUI
public void OnResolved() public void OnResolved()
{ {
_labelSettings = GD.Load<LabelSettings>("res://src/ui/label_settings/InventoryFullAlertLabelSetting.tres"); _labelSettings = GD.Load<LabelSettings>("res://src/ui/label_settings/InventoryFullAlertLabelSetting.tres");
}
public void Activate()
{
Player.Stats.CurrentHP.Sync += CurrentHP_Sync; Player.Stats.CurrentHP.Sync += CurrentHP_Sync;
Player.Stats.MaximumHP.Sync += MaximumHP_Sync; Player.Stats.MaximumHP.Sync += MaximumHP_Sync;