Start restructure of game data to support save/load

This commit is contained in:
2025-03-04 02:39:27 -08:00
parent a9cb43b79e
commit d35e81a9a8
8 changed files with 238 additions and 54 deletions

View File

@@ -1,9 +1,11 @@
using Chickensoft.Collections;
using Chickensoft.AutoInject;
using Chickensoft.Collections;
using Chickensoft.SaveFileBuilder;
using Godot;
namespace GameJamDungeon;
public interface IPlayer : IKillable
public interface IPlayer : IKillable, IProvide<ISaveChunk<PlayerStats>>
{
public void Attack();
@@ -47,7 +49,7 @@ public interface IPlayer : IKillable
public IInventory Inventory { get; }
public PlayerStats Stats { get; }
public PlayerStatController Stats { get; }
public Vector3 CurrentPosition { get; }

View File

@@ -19,12 +19,16 @@ public partial class Player : CharacterBody3D, IPlayer
private PlayerLogic.IBinding PlayerBinding { get; set; } = default!;
#endregion
#region Save
public ISaveChunk<PlayerStats> PlayerChunk { get; set; } = default!;
#endregion
public double CurrentHP => Stats.CurrentHP.Value;
public Vector3 CurrentPosition => GlobalPosition;
public Basis CurrentBasis => Transform.Basis;
public PlayerStats Stats { get; set; } = default!;
public PlayerStatController Stats { get; set; } = default!;
public IInventory Inventory { get; private set; } = default!;
@@ -48,6 +52,8 @@ public partial class Player : CharacterBody3D, IPlayer
[Dependency]
public ISaveChunk<GameData> GameChunk => this.DependOn<ISaveChunk<GameData>>();
ISaveChunk<PlayerStats> IProvide<ISaveChunk<PlayerStats>>.Value() => PlayerChunk;
#endregion
#region Event Signals
@@ -110,25 +116,28 @@ public partial class Player : CharacterBody3D, IPlayer
public void Setup()
{
Settings = new PlayerLogic.Settings() { RotationSpeed = PlayerStatResource.RotationSpeed, MoveSpeed = PlayerStatResource.MoveSpeed, Acceleration = PlayerStatResource.Acceleration };
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
});
Stats = new PlayerStats();
Inventory = new Inventory();
Stats.SetCurrentHP(PlayerStatResource.CurrentHP);
Stats.SetMaximumHP(PlayerStatResource.MaximumHP);
Stats.SetCurrentVT(PlayerStatResource.CurrentVT);
Stats.SetMaximumVT(PlayerStatResource.MaximumVT);
Stats.SetCurrentAttack(PlayerStatResource.CurrentAttack);
Stats.SetBonusAttack(PlayerStatResource.BonusAttack);
Stats.SetMaxAttack(PlayerStatResource.MaxAttack);
Stats.SetCurrentDefense(PlayerStatResource.CurrentDefense);
Stats.SetBonusDefense(PlayerStatResource.BonusDefense);
Stats.SetMaxDefense(PlayerStatResource.MaxDefense);
Stats.SetCurrentExp(PlayerStatResource.CurrentExp);
Stats.SetCurrentLevel(PlayerStatResource.CurrentLevel);
Stats.SetExpToNextLevel(PlayerStatResource.ExpToNextLevel);
Stats.SetLuck(PlayerStatResource.Luck);
PlayerLogic = new PlayerLogic();
PlayerLogic.Set(this as IPlayer);
PlayerLogic.Set(Settings);
@@ -155,6 +164,30 @@ public partial class Player : CharacterBody3D, IPlayer
public void OnResolved()
{
PlayerChunk = new SaveChunk<PlayerStats>(
onSave: (chunk) => new PlayerStats
{
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
},
onLoad: (chunk, data) =>
{
Stats.Init(data);
}
);
PlayerBinding = PlayerLogic.Bind();
PlayerBinding
@@ -169,8 +202,10 @@ public partial class Player : CharacterBody3D, IPlayer
{
});
this.Provide();
GameChunk.AddChunk(PlayerChunk);
PlayerLogic.Start();
this.Provide();
HealthTimer.Timeout += OnHealthTimerTimeout;
Hitbox.AreaEntered += Hitbox_AreaEntered;
}
@@ -225,7 +260,7 @@ public partial class Player : CharacterBody3D, IPlayer
public void RaiseVT(int amountToRaise)
{
if (Stats.CurrentVT.Value == Stats.MaximumVT.Value)
if (Stats.CurrentVT == Stats.MaximumVT)
{
Stats.SetMaximumVT(Stats.MaximumVT.Value + amountToRaise);
Stats.SetCurrentVT(Stats.MaximumVT.Value);

View File

@@ -1,38 +1,76 @@
using Chickensoft.Collections;
using Chickensoft.Introspection;
using Chickensoft.Serialization;
using Godot;
namespace GameJamDungeon;
[Meta, Id("player_stats")]
public partial record PlayerStats
{
[Save("currentHP")]
public IAutoProp<int> CurrentHP => _currentHP;
public int CurrentHP { get; init; }
[Save("maximumHP")]
public IAutoProp<int> MaximumHP => _maximumHP;
public int MaximumHP { get; init; }
[Save("currentVT")]
public IAutoProp<int> CurrentVT => _currentVT;
public int CurrentVT { get; init; }
[Save("maximumVT")]
public IAutoProp<int> MaximumVT => _maximumVT;
public int MaximumVT { get; init; }
[Save("currentExp")]
public IAutoProp<int> CurrentExp => _currentExp;
public int CurrentExp { get; init; }
[Save("currentLevel")]
public IAutoProp<int> CurrentLevel => _currentLevel;
public int CurrentLevel { get; init; }
[Save("currentAttack")]
public IAutoProp<int> CurrentAttack => _currentAttack;
public int CurrentAttack { get; init; }
[Save("bonusAttack")]
public IAutoProp<int> BonusAttack => _bonusAttack;
public int BonusAttack { get; init; }
[Save("maxAttack")]
public IAutoProp<int> MaxAttack => _maxAttack;
public int MaxAttack { get; init; }
[Save("currentDefense")]
public IAutoProp<int> CurrentDefense => _currentDefense;
public int CurrentDefense { get; init; }
[Save("bonusDefense")]
public IAutoProp<int> BonusDefense => _bonusDefense;
public int BonusDefense { get; init; }
[Save("maxDefense")]
public IAutoProp<int> MaxDefense => _maxDefense;
public int MaxDefense { get; init; }
[Save("expToNextLevel")]
public IAutoProp<int> ExpToNextLevel => _expToNextLevel;
public int ExpToNextLevel { get; init; }
[Save("luck")]
public double Luck { get; init; }
}
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);
_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);
_expToNextLevel.OnNext(playerStats.ExpToNextLevel);
_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<int> CurrentExp => _currentExp;
public IAutoProp<int> ExpToNextLevel => _expToNextLevel;
public IAutoProp<int> CurrentLevel => _currentLevel;
public IAutoProp<double> Luck => _luck;
public void SetCurrentHP(int newValue)
@@ -97,18 +135,18 @@ public partial record PlayerStats
_luck.OnNext(clampedValue);
}
private readonly AutoProp<int> _currentHP = new(int.MaxValue);
private readonly AutoProp<int> _maximumHP = new(int.MaxValue);
private readonly AutoProp<int> _currentVT = new(int.MaxValue);
private readonly AutoProp<int> _maximumVT = new(int.MaxValue);
private readonly AutoProp<int> _currentExp = new(int.MaxValue);
private readonly AutoProp<int> _currentLevel = new(int.MaxValue);
private readonly AutoProp<int> _currentAttack = new(int.MaxValue);
private readonly AutoProp<int> _bonusAttack = new(int.MaxValue);
private readonly AutoProp<int> _maxAttack = new(int.MaxValue);
private readonly AutoProp<int> _currentDefense = new(int.MaxValue);
private readonly AutoProp<int> _bonusDefense = new(int.MaxValue);
private readonly AutoProp<int> _maxDefense = new(int.MaxValue);
private readonly AutoProp<int> _expToNextLevel = new(int.MaxValue);
private readonly AutoProp<double> _luck = new(double.MaxValue);
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<int> _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);
}