Refactor stats
This commit is contained in:
@@ -1,15 +1,14 @@
|
|||||||
using System.Text.Json;
|
using System.Text.Json.Serialization.Metadata;
|
||||||
using System.Text.Json.Serialization.Metadata;
|
|
||||||
|
|
||||||
namespace Zennysoft.Game.Abstractions;
|
namespace Zennysoft.Game.Abstractions;
|
||||||
|
|
||||||
public interface ISaveFileManager<T>
|
public interface ISaveFileManager
|
||||||
{
|
{
|
||||||
public Task WriteToFile(T gameData, params IJsonTypeInfoResolver?[] resolvers);
|
public Task WriteToFile<T>(T gameData, params IJsonTypeInfoResolver?[] resolvers);
|
||||||
|
|
||||||
public Task WriteToFile(T gameData, string filePath, params IJsonTypeInfoResolver?[] resolvers);
|
public Task WriteToFile<T>(T gameData, string filePath, params IJsonTypeInfoResolver?[] resolvers);
|
||||||
|
|
||||||
public Task<T?> ReadFromFile(params IJsonTypeInfoResolver?[] resolvers);
|
public Task<object?> ReadFromFile(params IJsonTypeInfoResolver?[] resolvers);
|
||||||
|
|
||||||
public Task<T?> ReadFromFile(string filePath, params IJsonTypeInfoResolver?[] resolvers);
|
public Task<object?> ReadFromFile(string filePath, params IJsonTypeInfoResolver?[] resolvers);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ using Zennysoft.Game.Abstractions;
|
|||||||
|
|
||||||
namespace Zennysoft.Game.Implementation;
|
namespace Zennysoft.Game.Implementation;
|
||||||
|
|
||||||
public class SaveFileManager<T> : ISaveFileManager<T>
|
public class SaveFileManager : ISaveFileManager
|
||||||
{
|
{
|
||||||
private readonly IFileSystem _fileSystem;
|
private readonly IFileSystem _fileSystem;
|
||||||
private readonly JsonSerializerOptions _jsonOptions;
|
private readonly JsonSerializerOptions _jsonOptions;
|
||||||
@@ -36,14 +36,14 @@ public class SaveFileManager<T> : ISaveFileManager<T>
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public Task<T?> ReadFromFile(params IJsonTypeInfoResolver?[] resolvers)
|
public Task<object?> ReadFromFile(params IJsonTypeInfoResolver?[] resolvers)
|
||||||
{
|
{
|
||||||
if (!_fileSystem.File.Exists(_defaultSaveLocation))
|
if (!_fileSystem.File.Exists(_defaultSaveLocation))
|
||||||
throw new FileNotFoundException();
|
throw new FileNotFoundException();
|
||||||
return ReadFromFile(_defaultSaveLocation, resolvers);
|
return ReadFromFile(_defaultSaveLocation, resolvers);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<T?> ReadFromFile(string filePath, params IJsonTypeInfoResolver?[] resolvers)
|
public async Task<object?> ReadFromFile(string filePath, params IJsonTypeInfoResolver?[] resolvers)
|
||||||
{
|
{
|
||||||
if (!_fileSystem.File.Exists(filePath))
|
if (!_fileSystem.File.Exists(filePath))
|
||||||
throw new FileNotFoundException();
|
throw new FileNotFoundException();
|
||||||
@@ -52,15 +52,15 @@ public class SaveFileManager<T> : ISaveFileManager<T>
|
|||||||
|
|
||||||
var resolver = new SerializableTypeResolver();
|
var resolver = new SerializableTypeResolver();
|
||||||
_jsonOptions.TypeInfoResolver = JsonTypeInfoResolver.Combine([resolver, .. resolvers]);
|
_jsonOptions.TypeInfoResolver = JsonTypeInfoResolver.Combine([resolver, .. resolvers]);
|
||||||
return JsonSerializer.Deserialize<T?>(json, _jsonOptions);
|
return JsonSerializer.Deserialize<object?>(json, _jsonOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task WriteToFile(T gameData, params IJsonTypeInfoResolver?[] resolvers)
|
public Task WriteToFile<T>(T gameData, params IJsonTypeInfoResolver?[] resolvers)
|
||||||
{
|
{
|
||||||
return WriteToFile(gameData, _defaultSaveLocation, resolvers);
|
return WriteToFile(gameData, _defaultSaveLocation, resolvers);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task WriteToFile(T gameData, string filePath, params IJsonTypeInfoResolver?[] resolvers)
|
public async Task WriteToFile<T>(T gameData, string filePath, params IJsonTypeInfoResolver?[] resolvers)
|
||||||
{
|
{
|
||||||
var resolver = new SerializableTypeResolver();
|
var resolver = new SerializableTypeResolver();
|
||||||
_jsonOptions.TypeInfoResolver = JsonTypeInfoResolver.Combine([resolver, .. resolvers]);
|
_jsonOptions.TypeInfoResolver = JsonTypeInfoResolver.Combine([resolver, .. resolvers]);
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ public partial class AppLogic
|
|||||||
public partial record State
|
public partial record State
|
||||||
{
|
{
|
||||||
[Meta]
|
[Meta]
|
||||||
public partial record MainMenu : State, IGet<Input.NewGame>, IGet<Input.EnemyViewerOpened>
|
public partial record MainMenu : State, IGet<Input.NewGame>, IGet<Input.LoadGame>, IGet<Input.EnemyViewerOpened>
|
||||||
{
|
{
|
||||||
public MainMenu()
|
public MainMenu()
|
||||||
{
|
{
|
||||||
@@ -16,6 +16,7 @@ public partial class AppLogic
|
|||||||
public Transition On(in Input.NewGame input) => To<GameStarted>();
|
public Transition On(in Input.NewGame input) => To<GameStarted>();
|
||||||
|
|
||||||
public Transition On(in Input.EnemyViewerOpened input) => To<EnemyViewer>();
|
public Transition On(in Input.EnemyViewerOpened input) => To<EnemyViewer>();
|
||||||
|
public Transition On(in Input.LoadGame input) => To<LoadingSaveFile>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
using Chickensoft.Collections;
|
||||||
|
|
||||||
|
namespace Zennysoft.Ma.Adapter;
|
||||||
|
|
||||||
|
public interface IAttackComponent
|
||||||
|
{
|
||||||
|
public IAutoProp<int> CurrentAttack { get; }
|
||||||
|
|
||||||
|
public IAutoProp<int> MaximumAttack { get; }
|
||||||
|
|
||||||
|
public IAutoProp<int> BonusAttack { get; }
|
||||||
|
|
||||||
|
public int TotalAttack { get; }
|
||||||
|
|
||||||
|
public void Restore(int restoreAmount);
|
||||||
|
|
||||||
|
public void Reduce(int reduceAmount);
|
||||||
|
|
||||||
|
public void SetAttack(int attack);
|
||||||
|
|
||||||
|
public void RaiseMaximumAttack(int raiseAmount);
|
||||||
|
|
||||||
|
public void RaiseBonusAttack(int raiseAmount);
|
||||||
|
|
||||||
|
public void ResetBonusAttack();
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
using Chickensoft.Collections;
|
||||||
|
|
||||||
|
namespace Zennysoft.Ma.Adapter;
|
||||||
|
|
||||||
|
public interface IDefenseComponent
|
||||||
|
{
|
||||||
|
public IAutoProp<int> CurrentDefense { get; }
|
||||||
|
|
||||||
|
public IAutoProp<int> MaximumDefense { get; }
|
||||||
|
|
||||||
|
public IAutoProp<int> BonusDefense { get; }
|
||||||
|
|
||||||
|
public int TotalDefense { get; }
|
||||||
|
|
||||||
|
public void Restore(int restoreAmount);
|
||||||
|
|
||||||
|
public void Reduce(int reduceAmount);
|
||||||
|
|
||||||
|
public void SetDefense(int attack);
|
||||||
|
|
||||||
|
public void RaiseMaximumDefense(int raiseAmount);
|
||||||
|
|
||||||
|
public void RaiseBonusDefense(int raiseAmount);
|
||||||
|
|
||||||
|
public void ResetBonusDefense();
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
using Chickensoft.Collections;
|
||||||
|
using Zennysoft.Ma.Adapter;
|
||||||
|
|
||||||
|
namespace Zennysoft.Ma.Adapter;
|
||||||
|
public interface IEquipmentComponent
|
||||||
|
{
|
||||||
|
public IAutoProp<EquipableItem> EquippedWeapon { get; }
|
||||||
|
|
||||||
|
public IAutoProp<EquipableItem> EquippedArmor { get; }
|
||||||
|
|
||||||
|
public IAutoProp<EquipableItem> EquippedAccessory { get; }
|
||||||
|
|
||||||
|
public void Equip(EquipableItem equipable);
|
||||||
|
|
||||||
|
public void Unequip(EquipableItem equipable);
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
using Chickensoft.Collections;
|
||||||
|
|
||||||
|
namespace Zennysoft.Ma.Adapter;
|
||||||
|
|
||||||
|
public interface IExperiencePointsComponent
|
||||||
|
{
|
||||||
|
public IAutoProp<int> CurrentExp { get; }
|
||||||
|
|
||||||
|
public IAutoProp<int> ExpToNextLevel { get; }
|
||||||
|
|
||||||
|
public IAutoProp<double> ExpGainRate { get; }
|
||||||
|
|
||||||
|
public IAutoProp<int> Level { get; }
|
||||||
|
|
||||||
|
public void Gain(int baseExpGain);
|
||||||
|
|
||||||
|
public void LevelUp();
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
using Chickensoft.Collections;
|
||||||
|
using Chickensoft.Serialization;
|
||||||
|
|
||||||
|
namespace Zennysoft.Ma.Adapter;
|
||||||
|
|
||||||
|
public interface IHealthComponent
|
||||||
|
{
|
||||||
|
[Save("current_hp")]
|
||||||
|
public IAutoProp<int> CurrentHP { get; }
|
||||||
|
|
||||||
|
[Save("maximum_hp")]
|
||||||
|
public IAutoProp<int> MaximumHP { get; }
|
||||||
|
|
||||||
|
public event Action? HealthReachedZero;
|
||||||
|
public event Action? DamageTaken;
|
||||||
|
|
||||||
|
public bool AtFullHealth { get; }
|
||||||
|
|
||||||
|
public void Heal(int healAmount);
|
||||||
|
|
||||||
|
public void Damage(int damageAmount);
|
||||||
|
|
||||||
|
public void SetHealth(int health);
|
||||||
|
|
||||||
|
public void RaiseMaximumHP(int raiseAmount);
|
||||||
|
}
|
||||||
10
Zennysoft.Game.Ma.Implementation/Components/LuckComponent.cs
Normal file
10
Zennysoft.Game.Ma.Implementation/Components/LuckComponent.cs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
using Chickensoft.Collections;
|
||||||
|
|
||||||
|
namespace Zennysoft.Ma.Adapter;
|
||||||
|
|
||||||
|
public interface ILuckComponent
|
||||||
|
{
|
||||||
|
public IAutoProp<int> Luck { get; }
|
||||||
|
|
||||||
|
public void SetLuck(int value);
|
||||||
|
}
|
||||||
20
Zennysoft.Game.Ma.Implementation/Components/VTComponent.cs
Normal file
20
Zennysoft.Game.Ma.Implementation/Components/VTComponent.cs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
using Chickensoft.Collections;
|
||||||
|
|
||||||
|
namespace Zennysoft.Ma.Adapter;
|
||||||
|
|
||||||
|
public interface IVTComponent
|
||||||
|
{
|
||||||
|
public IAutoProp<int> CurrentVT { get; }
|
||||||
|
|
||||||
|
public IAutoProp<int> MaximumVT { get; }
|
||||||
|
|
||||||
|
public bool AtFullVT { get; }
|
||||||
|
|
||||||
|
public void Restore(int restoreAmount);
|
||||||
|
|
||||||
|
public void Reduce(int reduceAmount);
|
||||||
|
|
||||||
|
public void SetVT(int vt);
|
||||||
|
|
||||||
|
public void RaiseMaximumVT(int raiseAmount);
|
||||||
|
}
|
||||||
@@ -1,11 +1,10 @@
|
|||||||
using Godot;
|
using Chickensoft.GodotNodeInterfaces;
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
using Zennysoft.Game.Implementation.Components;
|
|
||||||
using Zennysoft.Game.Ma;
|
using Zennysoft.Game.Ma;
|
||||||
|
|
||||||
namespace Zennysoft.Ma.Adapter.Entity
|
namespace Zennysoft.Ma.Adapter.Entity
|
||||||
{
|
{
|
||||||
public interface IEnemy
|
public interface IEnemy : ICharacterBody3D
|
||||||
{
|
{
|
||||||
public void Activate();
|
public void Activate();
|
||||||
|
|
||||||
@@ -17,19 +16,15 @@ namespace Zennysoft.Ma.Adapter.Entity
|
|||||||
|
|
||||||
public void ReturnToDefaultState();
|
public void ReturnToDefaultState();
|
||||||
|
|
||||||
public void TakeDamage(int damage);
|
|
||||||
|
|
||||||
public void SetTarget(Vector3 targetPosition);
|
|
||||||
|
|
||||||
public void SetEnemyPosition(Vector3 position);
|
|
||||||
|
|
||||||
public void LookAtTarget(Vector3 target);
|
|
||||||
|
|
||||||
public IDungeonRoom GetCurrentRoom(ImmutableList<IDungeonRoom> dungeonRooms);
|
public IDungeonRoom GetCurrentRoom(ImmutableList<IDungeonRoom> dungeonRooms);
|
||||||
|
|
||||||
public AttackComponent AttackComponent { get; }
|
public void MoveEnemyToNewRoom(IDungeonRoom newRoom);
|
||||||
|
|
||||||
public DefenseComponent DefenseComponent { get; }
|
public IHealthComponent HealthComponent { get; }
|
||||||
|
|
||||||
|
public IAttackComponent AttackComponent { get; }
|
||||||
|
|
||||||
|
public IDefenseComponent DefenseComponent { get; }
|
||||||
|
|
||||||
public int InitialHP { get; }
|
public int InitialHP { get; }
|
||||||
|
|
||||||
|
|||||||
@@ -1,18 +0,0 @@
|
|||||||
using Chickensoft.Introspection;
|
|
||||||
using Chickensoft.Serialization;
|
|
||||||
using Zennysoft.Game.Ma;
|
|
||||||
|
|
||||||
namespace Zennysoft.Ma.Adapter;
|
|
||||||
|
|
||||||
[Meta, Id("game_data")]
|
|
||||||
public partial record GameData
|
|
||||||
{
|
|
||||||
[Save("player_data")]
|
|
||||||
public required PlayerData PlayerData { get; init; }
|
|
||||||
|
|
||||||
[Save("map_data")]
|
|
||||||
public required MapData MapData { get; init; }
|
|
||||||
|
|
||||||
[Save("rescued_items")]
|
|
||||||
public required RescuedItemDatabase RescuedItems { get; init; }
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
using Chickensoft.Collections;
|
using Chickensoft.Collections;
|
||||||
using Godot;
|
using Godot;
|
||||||
using Zennysoft.Game.Abstractions;
|
using Zennysoft.Game.Abstractions;
|
||||||
|
using Zennysoft.Game.Implementation;
|
||||||
|
|
||||||
namespace Zennysoft.Ma.Adapter;
|
namespace Zennysoft.Ma.Adapter;
|
||||||
|
|
||||||
|
|||||||
@@ -19,11 +19,13 @@ public partial class GameState
|
|||||||
public Transition On(in Input.ContinueGame input)
|
public Transition On(in Input.ContinueGame input)
|
||||||
{
|
{
|
||||||
Output(new Output.InitializeGame());
|
Output(new Output.InitializeGame());
|
||||||
|
Output(new Output.LoadGameFromFile());
|
||||||
return To<InGame>();
|
return To<InGame>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Transition On(in Input.LoadGame input)
|
public Transition On(in Input.LoadGame input)
|
||||||
{
|
{
|
||||||
|
Output(new Output.InitializeGame());
|
||||||
Output(new Output.LoadGameFromFile());
|
Output(new Output.LoadGameFromFile());
|
||||||
return To<InGame>();
|
return To<InGame>();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
namespace Zennysoft.Ma.Adapter;
|
using Zennysoft.Game.Implementation;
|
||||||
|
|
||||||
|
namespace Zennysoft.Ma.Adapter;
|
||||||
|
|
||||||
public interface IInventory
|
public interface IInventory
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using Chickensoft.Introspection;
|
using Chickensoft.Introspection;
|
||||||
using Chickensoft.Serialization;
|
using Chickensoft.Serialization;
|
||||||
using Zennysoft.Game.Abstractions;
|
using Zennysoft.Game.Abstractions;
|
||||||
|
using Zennysoft.Game.Implementation;
|
||||||
|
|
||||||
namespace Zennysoft.Ma.Adapter;
|
namespace Zennysoft.Ma.Adapter;
|
||||||
|
|
||||||
|
|||||||
@@ -22,3 +22,24 @@ public partial class BoxItemTagEnumContext : JsonSerializerContext;
|
|||||||
|
|
||||||
[JsonSerializable(typeof(ElementType))]
|
[JsonSerializable(typeof(ElementType))]
|
||||||
public partial class ElementTypeEnumContext : JsonSerializerContext;
|
public partial class ElementTypeEnumContext : JsonSerializerContext;
|
||||||
|
|
||||||
|
[JsonSerializable(typeof(IHealthComponent))]
|
||||||
|
public partial class HealthComponentContext : JsonSerializerContext;
|
||||||
|
|
||||||
|
[JsonSerializable(typeof(IVTComponent))]
|
||||||
|
public partial class VTComponentContext : JsonSerializerContext;
|
||||||
|
|
||||||
|
[JsonSerializable(typeof(IAttackComponent))]
|
||||||
|
public partial class AttackComponentContext : JsonSerializerContext;
|
||||||
|
|
||||||
|
[JsonSerializable(typeof(IDefenseComponent))]
|
||||||
|
public partial class DefenseComponentContext : JsonSerializerContext;
|
||||||
|
|
||||||
|
[JsonSerializable(typeof(IExperiencePointsComponent))]
|
||||||
|
public partial class ExperiencePointsComponentContext : JsonSerializerContext;
|
||||||
|
|
||||||
|
[JsonSerializable(typeof(ILuckComponent))]
|
||||||
|
public partial class LuckComponentContext : JsonSerializerContext;
|
||||||
|
|
||||||
|
[JsonSerializable(typeof(IEquipmentComponent))]
|
||||||
|
public partial class EquipmentComponentContext : JsonSerializerContext;
|
||||||
@@ -1,9 +1,7 @@
|
|||||||
using SimpleInjector;
|
using SimpleInjector;
|
||||||
using System.IO.Abstractions;
|
using System.IO.Abstractions;
|
||||||
using Zennysoft.Game.Abstractions;
|
using Zennysoft.Game.Abstractions;
|
||||||
using Zennysoft.Game.Abstractions.Entity;
|
|
||||||
using Zennysoft.Game.Implementation;
|
using Zennysoft.Game.Implementation;
|
||||||
using Zennysoft.Ma.Adapter.Entity;
|
|
||||||
|
|
||||||
namespace Zennysoft.Ma.Adapter;
|
namespace Zennysoft.Ma.Adapter;
|
||||||
|
|
||||||
@@ -12,8 +10,8 @@ public class Module
|
|||||||
public static void Bootstrap(Container container)
|
public static void Bootstrap(Container container)
|
||||||
{
|
{
|
||||||
container.RegisterSingleton<IFileSystem, FileSystem>();
|
container.RegisterSingleton<IFileSystem, FileSystem>();
|
||||||
container.RegisterSingleton<ISaveFileManager<GameData>, SaveFileManager<GameData>>();
|
container.RegisterSingleton<ISaveFileManager, SaveFileManager>();
|
||||||
container.RegisterSingleton<IMaSaveFileManager<GameData>, MaSaveFileManager<GameData>>();
|
container.RegisterSingleton<IMaSaveFileManager, MaSaveFileManager>();
|
||||||
container.RegisterSingleton<IGameRepo, GameRepo>();
|
container.RegisterSingleton<IGameRepo, GameRepo>();
|
||||||
container.RegisterSingleton<IGameState, GameState>();
|
container.RegisterSingleton<IGameState, GameState>();
|
||||||
container.RegisterSingleton<IDimmableAudioStreamPlayer, DimmableAudioStreamPlayer>();
|
container.RegisterSingleton<IDimmableAudioStreamPlayer, DimmableAudioStreamPlayer>();
|
||||||
|
|||||||
@@ -1,57 +1,39 @@
|
|||||||
using Chickensoft.Collections;
|
using Godot;
|
||||||
using Godot;
|
|
||||||
using Zennysoft.Game.Abstractions;
|
using Zennysoft.Game.Abstractions;
|
||||||
using Zennysoft.Game.Implementation.Components;
|
|
||||||
|
|
||||||
namespace Zennysoft.Ma.Adapter;
|
namespace Zennysoft.Ma.Adapter;
|
||||||
|
|
||||||
public interface IPlayer : IKillable
|
public interface IPlayer : IKillable
|
||||||
{
|
{
|
||||||
public void InitializePlayerState();
|
|
||||||
|
|
||||||
public void Activate();
|
public void Activate();
|
||||||
|
|
||||||
public void Deactivate();
|
public void Deactivate();
|
||||||
|
|
||||||
public void Attack();
|
|
||||||
|
|
||||||
public void TakeDamage(Damage damage);
|
public void TakeDamage(Damage damage);
|
||||||
|
|
||||||
public void Knockback(float impulse);
|
public void Knockback(float impulse);
|
||||||
|
|
||||||
public void LevelUp();
|
public void LevelUp();
|
||||||
|
|
||||||
public void Move(float delta);
|
|
||||||
|
|
||||||
public void TeleportPlayer(Transform3D newTransform);
|
public void TeleportPlayer(Transform3D newTransform);
|
||||||
|
|
||||||
public void SetHealthTimerStatus(bool isActive);
|
|
||||||
|
|
||||||
public IInventory Inventory { get; }
|
public IInventory Inventory { get; }
|
||||||
|
|
||||||
public Vector3 CurrentPosition { get; }
|
public Vector3 CurrentPosition { get; }
|
||||||
|
|
||||||
public Basis CurrentBasis { get; }
|
public Basis CurrentBasis { get; }
|
||||||
|
|
||||||
public AutoProp<EquipableItem> EquippedWeapon { get; }
|
public IHealthComponent HealthComponent { get; }
|
||||||
|
|
||||||
public AutoProp<EquipableItem> EquippedArmor { get; }
|
public IVTComponent VTComponent { get; }
|
||||||
|
|
||||||
public AutoProp<EquipableItem> EquippedAccessory { get; }
|
public IAttackComponent AttackComponent { get; }
|
||||||
|
|
||||||
public void Equip(EquipableItem equipable);
|
public IDefenseComponent DefenseComponent { get; }
|
||||||
|
|
||||||
public void Unequip(EquipableItem equipable);
|
public IExperiencePointsComponent ExperiencePointsComponent { get; }
|
||||||
|
|
||||||
public HealthComponent HealthComponent { get; }
|
public ILuckComponent LuckComponent { get; }
|
||||||
|
|
||||||
public VTComponent VTComponent { get; }
|
public IEquipmentComponent EquipmentComponent { get; }
|
||||||
|
|
||||||
public AttackComponent AttackComponent { get; }
|
|
||||||
|
|
||||||
public DefenseComponent DefenseComponent { get; }
|
|
||||||
|
|
||||||
public ExperiencePointsComponent ExperiencePointsComponent { get; }
|
|
||||||
|
|
||||||
public LuckComponent LuckComponent { get; }
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
using Chickensoft.Introspection;
|
|
||||||
using Chickensoft.Serialization;
|
|
||||||
using Zennysoft.Ma.Adapter;
|
|
||||||
|
|
||||||
namespace Zennysoft.Game.Ma;
|
|
||||||
|
|
||||||
[Meta, Id("player_data")]
|
|
||||||
public partial record PlayerData
|
|
||||||
{
|
|
||||||
[Save("player_inventory")]
|
|
||||||
public required IInventory Inventory { get; init; }
|
|
||||||
}
|
|
||||||
|
|
||||||
[Meta, Id("map_data")]
|
|
||||||
public partial record MapData
|
|
||||||
{
|
|
||||||
}
|
|
||||||
@@ -4,28 +4,28 @@ using Zennysoft.Game.Abstractions;
|
|||||||
|
|
||||||
namespace Zennysoft.Ma.Adapter;
|
namespace Zennysoft.Ma.Adapter;
|
||||||
|
|
||||||
public interface IMaSaveFileManager<T>
|
public interface IMaSaveFileManager
|
||||||
{
|
{
|
||||||
Task Save(T gameData);
|
Task Save<T>(T gameData);
|
||||||
|
|
||||||
Task<T?> Load();
|
Task<object?> Load();
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class MaSaveFileManager<T> : IMaSaveFileManager<T>
|
public sealed class MaSaveFileManager : IMaSaveFileManager
|
||||||
{
|
{
|
||||||
private readonly ISaveFileManager<T> _saveFileManager;
|
private readonly ISaveFileManager _saveFileManager;
|
||||||
private ImmutableList<IJsonTypeInfoResolver> _converters;
|
private ImmutableList<IJsonTypeInfoResolver> _converters;
|
||||||
|
|
||||||
public MaSaveFileManager(ISaveFileManager<T> saveFileManager)
|
public MaSaveFileManager(ISaveFileManager saveFileManager)
|
||||||
{
|
{
|
||||||
_saveFileManager = saveFileManager;
|
_saveFileManager = saveFileManager;
|
||||||
_converters = [WeaponTagEnumContext.Default, ItemTagEnumContext.Default, ElementTypeEnumContext.Default, AccessoryTagEnumContext.Default, ThrowableItemTagEnumContext.Default, UsableItemTagEnumContext.Default, BoxItemTagEnumContext.Default];
|
_converters = [HealthComponentContext.Default, WeaponTagEnumContext.Default, ItemTagEnumContext.Default, ElementTypeEnumContext.Default, AccessoryTagEnumContext.Default, ThrowableItemTagEnumContext.Default, UsableItemTagEnumContext.Default, BoxItemTagEnumContext.Default];
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Save(T gameData)
|
public async Task Save<T>(T gameData)
|
||||||
{
|
{
|
||||||
await _saveFileManager.WriteToFile(gameData, [.. _converters]);
|
await _saveFileManager.WriteToFile(gameData, [.. _converters]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<T?> Load() => await _saveFileManager.ReadFromFile([.. _converters]);
|
public async Task<object?> Load() => await _saveFileManager.ReadFromFile([.. _converters]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Chickensoft.Introspection;
|
using Chickensoft.Introspection;
|
||||||
using Chickensoft.LogicBlocks;
|
using Chickensoft.LogicBlocks;
|
||||||
|
using Zennysoft.Game.Implementation;
|
||||||
|
|
||||||
|
|
||||||
namespace Zennysoft.Ma.Adapter;
|
namespace Zennysoft.Ma.Adapter;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Zennysoft.Game.Ma;
|
using Zennysoft.Game.Implementation;
|
||||||
|
using Zennysoft.Game.Ma;
|
||||||
|
|
||||||
namespace Zennysoft.Ma.Adapter;
|
namespace Zennysoft.Ma.Adapter;
|
||||||
public partial class InGameUILogic
|
public partial class InGameUILogic
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
using Chickensoft.Collections;
|
using Chickensoft.Collections;
|
||||||
using Godot;
|
using System;
|
||||||
|
using Zennysoft.Ma.Adapter;
|
||||||
|
|
||||||
namespace Zennysoft.Game.Implementation.Components;
|
namespace Zennysoft.Game.Ma;
|
||||||
|
|
||||||
public class AttackComponent
|
public class AttackComponent : IAttackComponent
|
||||||
{
|
{
|
||||||
public IAutoProp<int> CurrentAttack => _currentAttack;
|
public IAutoProp<int> CurrentAttack => _currentAttack;
|
||||||
|
|
||||||
@@ -49,4 +50,14 @@ public class AttackComponent
|
|||||||
_maximumAttack.OnNext(raiseAmount);
|
_maximumAttack.OnNext(raiseAmount);
|
||||||
Restore(raiseAmount);
|
Restore(raiseAmount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void RaiseBonusAttack(int raiseAmount)
|
||||||
|
{
|
||||||
|
_bonusAttack.OnNext(_bonusAttack.Value + raiseAmount);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ResetBonusAttack()
|
||||||
|
{
|
||||||
|
_bonusAttack.OnNext(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
1
Zennysoft.Game.Ma/src/Components/AttackComponent.cs.uid
Normal file
1
Zennysoft.Game.Ma/src/Components/AttackComponent.cs.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://ctyq0v5nsmyv4
|
||||||
@@ -1,9 +1,10 @@
|
|||||||
using Chickensoft.Collections;
|
using Chickensoft.Collections;
|
||||||
using Godot;
|
using System;
|
||||||
|
using Zennysoft.Ma.Adapter;
|
||||||
|
|
||||||
namespace Zennysoft.Game.Implementation.Components;
|
namespace Zennysoft.Game.Ma;
|
||||||
|
|
||||||
public class DefenseComponent
|
public class DefenseComponent : IDefenseComponent
|
||||||
{
|
{
|
||||||
public IAutoProp<int> CurrentDefense => _currentDefense;
|
public IAutoProp<int> CurrentDefense => _currentDefense;
|
||||||
|
|
||||||
1
Zennysoft.Game.Ma/src/Components/DefenseComponent.cs.uid
Normal file
1
Zennysoft.Game.Ma/src/Components/DefenseComponent.cs.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://c0ynebyuj4jwe
|
||||||
45
Zennysoft.Game.Ma/src/Components/EquipmentComponent.cs
Normal file
45
Zennysoft.Game.Ma/src/Components/EquipmentComponent.cs
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
using Chickensoft.Collections;
|
||||||
|
using Zennysoft.Ma.Adapter;
|
||||||
|
|
||||||
|
namespace Zennysoft.Game.Ma;
|
||||||
|
public class EquipmentComponent : IEquipmentComponent
|
||||||
|
{
|
||||||
|
public IAutoProp<EquipableItem> EquippedWeapon => _equippedWeapon;
|
||||||
|
|
||||||
|
public IAutoProp<EquipableItem> EquippedArmor => _equippedArmor;
|
||||||
|
|
||||||
|
public IAutoProp<EquipableItem> EquippedAccessory => _equippedAccessory;
|
||||||
|
|
||||||
|
public AutoProp<EquipableItem> _equippedWeapon;
|
||||||
|
|
||||||
|
public AutoProp<EquipableItem> _equippedArmor;
|
||||||
|
|
||||||
|
public AutoProp<EquipableItem> _equippedAccessory;
|
||||||
|
|
||||||
|
public EquipmentComponent()
|
||||||
|
{
|
||||||
|
_equippedWeapon = new AutoProp<EquipableItem>(new Weapon());
|
||||||
|
_equippedArmor = new AutoProp<EquipableItem>(new Armor());
|
||||||
|
_equippedAccessory = new AutoProp<EquipableItem>(new Accessory());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Equip(EquipableItem equipable)
|
||||||
|
{
|
||||||
|
if (equipable is Weapon weapon)
|
||||||
|
_equippedWeapon.OnNext(weapon);
|
||||||
|
if (equipable is Armor armor)
|
||||||
|
_equippedArmor.OnNext(armor);
|
||||||
|
if (equipable is Accessory accessory)
|
||||||
|
_equippedAccessory.OnNext(accessory);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Unequip(EquipableItem equipable)
|
||||||
|
{
|
||||||
|
if (equipable is Weapon weapon)
|
||||||
|
_equippedWeapon.OnNext(new Weapon());
|
||||||
|
if (equipable is Armor armor)
|
||||||
|
_equippedArmor.OnNext(new Armor());
|
||||||
|
if (equipable is Accessory accessory)
|
||||||
|
_equippedAccessory.OnNext(new Accessory());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
uid://bntwm4big7gnm
|
||||||
@@ -1,8 +1,10 @@
|
|||||||
using Chickensoft.Collections;
|
using Chickensoft.Collections;
|
||||||
|
using System;
|
||||||
|
using Zennysoft.Ma.Adapter;
|
||||||
|
|
||||||
namespace Zennysoft.Game.Implementation.Components;
|
namespace Zennysoft.Game.Ma;
|
||||||
|
|
||||||
public class ExperiencePointsComponent
|
public class ExperiencePointsComponent : IExperiencePointsComponent
|
||||||
{
|
{
|
||||||
public IAutoProp<int> CurrentExp => _currentExp;
|
public IAutoProp<int> CurrentExp => _currentExp;
|
||||||
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
uid://dyxfogbt1th04
|
||||||
@@ -1,11 +1,16 @@
|
|||||||
using Chickensoft.Collections;
|
using Chickensoft.Collections;
|
||||||
|
using Chickensoft.Serialization;
|
||||||
|
using System;
|
||||||
|
using Zennysoft.Ma.Adapter;
|
||||||
|
|
||||||
namespace Zennysoft.Game.Implementation.Components;
|
namespace Zennysoft.Game.Ma;
|
||||||
|
|
||||||
public class HealthComponent
|
public class HealthComponent : IHealthComponent
|
||||||
{
|
{
|
||||||
|
[Save("current_hp")]
|
||||||
public IAutoProp<int> CurrentHP => _currentHP;
|
public IAutoProp<int> CurrentHP => _currentHP;
|
||||||
|
|
||||||
|
[Save("maximum_hp")]
|
||||||
public IAutoProp<int> MaximumHP => _maximumHP;
|
public IAutoProp<int> MaximumHP => _maximumHP;
|
||||||
|
|
||||||
private readonly AutoProp<int> _currentHP;
|
private readonly AutoProp<int> _currentHP;
|
||||||
1
Zennysoft.Game.Ma/src/Components/HealthComponent.cs.uid
Normal file
1
Zennysoft.Game.Ma/src/Components/HealthComponent.cs.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://c2e62jpounk1h
|
||||||
@@ -1,8 +1,9 @@
|
|||||||
using Chickensoft.Collections;
|
using Chickensoft.Collections;
|
||||||
|
using Zennysoft.Ma.Adapter;
|
||||||
|
|
||||||
namespace Zennysoft.Game.Implementation.Components;
|
namespace Zennysoft.Game.Ma;
|
||||||
|
|
||||||
public class LuckComponent
|
public class LuckComponent : ILuckComponent
|
||||||
{
|
{
|
||||||
public IAutoProp<int> Luck => _luck;
|
public IAutoProp<int> Luck => _luck;
|
||||||
|
|
||||||
1
Zennysoft.Game.Ma/src/Components/LuckComponent.cs.uid
Normal file
1
Zennysoft.Game.Ma/src/Components/LuckComponent.cs.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://dfrj2surolauj
|
||||||
@@ -1,8 +1,10 @@
|
|||||||
using Chickensoft.Collections;
|
using Chickensoft.Collections;
|
||||||
|
using System;
|
||||||
|
using Zennysoft.Ma.Adapter;
|
||||||
|
|
||||||
namespace Zennysoft.Game.Implementation.Components;
|
namespace Zennysoft.Game.Ma;
|
||||||
|
|
||||||
public class VTComponent
|
public class VTComponent : IVTComponent
|
||||||
{
|
{
|
||||||
public IAutoProp<int> CurrentVT => _currentVT;
|
public IAutoProp<int> CurrentVT => _currentVT;
|
||||||
|
|
||||||
1
Zennysoft.Game.Ma/src/Components/VTComponent.cs.uid
Normal file
1
Zennysoft.Game.Ma/src/Components/VTComponent.cs.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://b0tagp4amvy2v
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
using Chickensoft.AutoInject;
|
using Chickensoft.AutoInject;
|
||||||
using Chickensoft.Introspection;
|
using Chickensoft.Introspection;
|
||||||
using Godot;
|
using Godot;
|
||||||
|
using System;
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Zennysoft.Game.Implementation.Components;
|
|
||||||
using Zennysoft.Ma.Adapter;
|
using Zennysoft.Ma.Adapter;
|
||||||
using Zennysoft.Ma.Adapter.Entity;
|
using Zennysoft.Ma.Adapter.Entity;
|
||||||
|
|
||||||
@@ -26,11 +26,11 @@ public abstract partial class Enemy : CharacterBody3D, IEnemy, IProvide<IEnemyLo
|
|||||||
[Dependency] protected IPlayer _player => this.DependOn(() => GetParent().GetChildren().OfType<IPlayer>().Single());
|
[Dependency] protected IPlayer _player => this.DependOn(() => GetParent().GetChildren().OfType<IPlayer>().Single());
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
public HealthComponent HealthComponent { get; private set; }
|
public IHealthComponent HealthComponent { get; private set; }
|
||||||
|
|
||||||
public AttackComponent AttackComponent { get; private set; }
|
public IAttackComponent AttackComponent { get; private set; }
|
||||||
|
|
||||||
public DefenseComponent DefenseComponent { get; private set; }
|
public IDefenseComponent DefenseComponent { get; private set; }
|
||||||
|
|
||||||
public virtual IEnemyModelView EnemyModelView { get; set; } = default!;
|
public virtual IEnemyModelView EnemyModelView { get; set; } = default!;
|
||||||
|
|
||||||
@@ -118,36 +118,6 @@ public abstract partial class Enemy : CharacterBody3D, IEnemy, IProvide<IEnemyLo
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetTarget(Vector3 targetPosition) => TargetPosition = targetPosition;
|
|
||||||
|
|
||||||
public virtual void SetEnemyPosition(Vector3 newPosition)
|
|
||||||
{
|
|
||||||
GlobalPosition = newPosition;
|
|
||||||
|
|
||||||
if (this is IHavePatrolBehavior patrolEnemy)
|
|
||||||
patrolEnemy.PatrolBehavior.HomePosition = GlobalPosition;
|
|
||||||
|
|
||||||
_enemyLogic.Input(new EnemyLogic.Input.Reset());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void LookAtTarget(Vector3 targetPosition)
|
|
||||||
{
|
|
||||||
var lookDirection = GlobalPosition - targetPosition;
|
|
||||||
if (lookDirection != GlobalPosition)
|
|
||||||
LookAt(new Vector3(lookDirection.X, GlobalPosition.Y, lookDirection.Z), Vector3.Up);
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual void TakeDamage(int damage)
|
|
||||||
{
|
|
||||||
GD.Print($"Enemy Hit for {damage} damage.");
|
|
||||||
HealthComponent.Damage(damage);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void EnemyModelView_HitPlayer(object sender, System.EventArgs e)
|
|
||||||
{
|
|
||||||
_player.TakeDamage(new Damage(AttackComponent.TotalAttack, ElementType.None, false, false, false));
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual void TakeHit()
|
public virtual void TakeHit()
|
||||||
{
|
{
|
||||||
_enemyLogic.Input(new EnemyLogic.Input.Alert());
|
_enemyLogic.Input(new EnemyLogic.Input.Alert());
|
||||||
@@ -181,4 +151,37 @@ public abstract partial class Enemy : CharacterBody3D, IEnemy, IProvide<IEnemyLo
|
|||||||
_enemyLogic.Stop();
|
_enemyLogic.Stop();
|
||||||
EnemyBinding.Dispose();
|
EnemyBinding.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual void MoveEnemyToNewRoom(IDungeonRoom newRoom)
|
||||||
|
{
|
||||||
|
if (newRoom is MonsterRoom monsterRoom)
|
||||||
|
{
|
||||||
|
var spawnPoints = monsterRoom.EnemySpawnPoints.GetChildren().OfType<Marker3D>().ToList();
|
||||||
|
var spawnPointsGodotCollection = new Godot.Collections.Array<Marker3D>(spawnPoints);
|
||||||
|
var randomSpawnPoint = spawnPointsGodotCollection.PickRandom();
|
||||||
|
|
||||||
|
GlobalPosition = randomSpawnPoint.GlobalPosition;
|
||||||
|
|
||||||
|
if (this is IHavePatrolBehavior patrolEnemy)
|
||||||
|
patrolEnemy.PatrolBehavior.HomePosition = GlobalPosition;
|
||||||
|
|
||||||
|
_enemyLogic.Input(new EnemyLogic.Input.Reset());
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new NotImplementedException($"Only {nameof(MonsterRoom)} types are currently supported.");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void LookAtTarget(Vector3 targetPosition)
|
||||||
|
{
|
||||||
|
var lookDirection = GlobalPosition - targetPosition;
|
||||||
|
if (lookDirection != GlobalPosition)
|
||||||
|
LookAt(new Vector3(lookDirection.X, GlobalPosition.Y, lookDirection.Z), Vector3.Up);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void SetTarget(Vector3 targetPosition) => TargetPosition = targetPosition;
|
||||||
|
|
||||||
|
private void EnemyModelView_HitPlayer(object sender, System.EventArgs e)
|
||||||
|
{
|
||||||
|
_player.TakeDamage(new Damage(AttackComponent.TotalAttack, ElementType.None, false, false, false));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ public abstract partial class Enemy2D : Enemy
|
|||||||
|
|
||||||
[Node] private EnemyModelView2D _enemyModelView { get; set; } = default!;
|
[Node] private EnemyModelView2D _enemyModelView { get; set; } = default!;
|
||||||
|
|
||||||
public void OnReady()
|
public void OnEnterTree()
|
||||||
{
|
{
|
||||||
LineOfSight.BodyEntered += LineOfSight_BodyEntered;
|
LineOfSight.BodyEntered += LineOfSight_BodyEntered;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,12 +23,16 @@ public partial class FollowBehavior : Node3D, IBehavior
|
|||||||
private NavigationAgent3D _navigationAgent;
|
private NavigationAgent3D _navigationAgent;
|
||||||
private Timer _thinkTimer;
|
private Timer _thinkTimer;
|
||||||
|
|
||||||
public void Init(NavigationAgent3D navigationAgent)
|
public FollowBehavior()
|
||||||
{
|
{
|
||||||
_navigationAgent = navigationAgent;
|
|
||||||
_thinkTimer = new Timer() { WaitTime = _thinkTime };
|
_thinkTimer = new Timer() { WaitTime = _thinkTime };
|
||||||
_thinkTimer.Timeout += OnTimeout;
|
_thinkTimer.Timeout += OnTimeout;
|
||||||
AddChild(_thinkTimer);
|
AddChild(_thinkTimer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Init(NavigationAgent3D navigationAgent)
|
||||||
|
{
|
||||||
|
_navigationAgent = navigationAgent;
|
||||||
SetPhysicsProcess(false);
|
SetPhysicsProcess(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,11 +28,15 @@ public partial class PatrolBehavior : Node3D, IBehavior
|
|||||||
|
|
||||||
[Signal] public delegate void OnVelocityComputedEventHandler(Vector3 safeVelocity);
|
[Signal] public delegate void OnVelocityComputedEventHandler(Vector3 safeVelocity);
|
||||||
|
|
||||||
public void OnReady()
|
public PatrolBehavior()
|
||||||
{
|
{
|
||||||
_patrolTimer = new Timer() { WaitTime = _patrolTime };
|
_patrolTimer = new Timer() { WaitTime = _patrolTime };
|
||||||
_patrolTimer.Timeout += PatrolTimer_Timeout;
|
_patrolTimer.Timeout += PatrolTimer_Timeout;
|
||||||
AddChild(_patrolTimer);
|
AddChild(_patrolTimer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnReady()
|
||||||
|
{
|
||||||
SetPhysicsProcess(false);
|
SetPhysicsProcess(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ public partial class Sproingy : Enemy2D, IHavePatrolBehavior, IHaveEngagePlayerB
|
|||||||
|
|
||||||
[Node] public Area3D PlayerDetector { get; set; } = default!;
|
[Node] public Area3D PlayerDetector { get; set; } = default!;
|
||||||
|
|
||||||
public new void OnReady()
|
public void OnReady()
|
||||||
{
|
{
|
||||||
FollowBehavior.Init(NavigationAgent);
|
FollowBehavior.Init(NavigationAgent);
|
||||||
PatrolBehavior.Init(NavigationAgent);
|
PatrolBehavior.Init(NavigationAgent);
|
||||||
|
|||||||
@@ -81,6 +81,8 @@ shape = SubResource("CylinderShape3D_drfkj")
|
|||||||
|
|
||||||
[node name="EnemyModelView" parent="Visual" instance=ExtResource("4_o3b7p")]
|
[node name="EnemyModelView" parent="Visual" instance=ExtResource("4_o3b7p")]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
|
_upperThreshold = 0.5
|
||||||
|
_lowerThreshold = -0.5
|
||||||
|
|
||||||
[node name="Components" type="Node3D" parent="."]
|
[node name="Components" type="Node3D" parent="."]
|
||||||
|
|
||||||
|
|||||||
@@ -33,46 +33,22 @@ shape = SubResource("CapsuleShape3D_7uhtm")
|
|||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
|
|
||||||
[node name="Skeleton3D" parent="EnemyModelView/Armature" index="0"]
|
[node name="Skeleton3D" parent="EnemyModelView/Armature" index="0"]
|
||||||
bones/0/position = Vector3(-0.260271, -1.05324, -1.96773)
|
bones/0/position = Vector3(-0.260254, -1.05135, -1.96786)
|
||||||
bones/0/rotation = Quaternion(0.0915277, -0.692111, -0.0341586, 0.715149)
|
|
||||||
bones/1/rotation = Quaternion(0.0828172, 0.0642671, -0.39627, 0.91213)
|
|
||||||
bones/2/rotation = Quaternion(-0.137837, 0.137086, 0.403643, 0.894025)
|
|
||||||
bones/3/rotation = Quaternion(-0.00338816, 0.00852271, 0.0152662, 0.999842)
|
|
||||||
bones/4/rotation = Quaternion(0.037164, 0.133882, 0.101977, 0.985036)
|
|
||||||
bones/5/rotation = Quaternion(-0.0397875, -0.0104688, 0.0235613, 0.998875)
|
|
||||||
bones/6/rotation = Quaternion(-0.0474983, -0.294201, -0.744151, 0.597854)
|
bones/6/rotation = Quaternion(-0.0474983, -0.294201, -0.744151, 0.597854)
|
||||||
bones/7/rotation = Quaternion(0.0788712, -0.0306685, -0.220772, 0.971647)
|
bones/11/rotation = Quaternion(-0.779814, -0.0573517, 0.0816353, 0.61801)
|
||||||
bones/8/rotation = Quaternion(-0.127286, 0.0273856, -0.425308, 0.895635)
|
bones/15/rotation = Quaternion(-0.21544, 0.745303, 0.613567, -0.147118)
|
||||||
bones/9/rotation = Quaternion(-0.0931654, 0.0493592, -0.752794, 0.649757)
|
|
||||||
bones/10/rotation = Quaternion(0.0429966, 0.0102923, 0.363547, 0.930526)
|
|
||||||
bones/11/rotation = Quaternion(-0.779773, -0.0573165, 0.0817155, 0.618054)
|
|
||||||
bones/12/rotation = Quaternion(-0.607818, -0.670503, -0.284916, 0.31592)
|
|
||||||
bones/13/rotation = Quaternion(-0.255941, 0.586097, -0.127235, 0.758153)
|
|
||||||
bones/14/rotation = Quaternion(-0.513517, -0.227335, -0.228787, 0.795157)
|
|
||||||
bones/15/rotation = Quaternion(-0.215465, 0.745342, 0.613525, -0.147065)
|
|
||||||
bones/16/rotation = Quaternion(-0.486067, -0.16412, -0.362283, 0.778174)
|
bones/16/rotation = Quaternion(-0.486067, -0.16412, -0.362283, 0.778174)
|
||||||
bones/17/rotation = Quaternion(-0.0553629, -0.0361614, 0.62832, 0.77514)
|
bones/17/rotation = Quaternion(-0.0553629, -0.0361614, 0.62832, 0.77514)
|
||||||
bones/18/rotation = Quaternion(-0.119289, 0.0998131, -0.0173011, 0.987678)
|
bones/19/position = Vector3(-0.379519, -1.19848, -1.72293)
|
||||||
bones/19/position = Vector3(-0.381043, -1.19992, -1.71791)
|
bones/19/rotation = Quaternion(0.627358, 0.293207, 0.545673, -0.471903)
|
||||||
bones/19/rotation = Quaternion(0.627663, 0.29282, 0.545153, -0.472338)
|
bones/20/rotation = Quaternion(-0.327492, -0.423093, -0.300135, 0.789722)
|
||||||
bones/20/rotation = Quaternion(-0.327815, -0.422723, -0.300673, 0.789581)
|
bones/21/rotation = Quaternion(-0.0604877, 0.00129843, 0.48965, 0.869818)
|
||||||
bones/21/rotation = Quaternion(-0.0604945, 0.00129838, 0.489705, 0.869786)
|
bones/26/position = Vector3(-0.0278308, -1.11395, -2.01914)
|
||||||
bones/22/rotation = Quaternion(0.156218, 0.0483037, -0.624744, 0.763516)
|
bones/27/rotation = Quaternion(-0.202309, 0.424634, 0.137996, 0.871616)
|
||||||
bones/23/rotation = Quaternion(0.123936, -0.00678731, -0.347765, 0.92933)
|
bones/28/rotation = Quaternion(-0.0627943, -0.00116438, -0.501344, 0.862966)
|
||||||
bones/24/rotation = Quaternion(0.427621, 0.561851, 0.530083, 0.469549)
|
|
||||||
bones/25/position = Vector3(4.82744, -12.3397, 0.183847)
|
|
||||||
bones/25/rotation = Quaternion(-0.400051, 0.463947, -0.598439, 0.516317)
|
|
||||||
bones/26/position = Vector3(-0.0233502, -1.11395, -2.01916)
|
|
||||||
bones/26/rotation = Quaternion(0.608697, -0.3155, -0.575514, -0.445793)
|
|
||||||
bones/27/rotation = Quaternion(-0.202236, 0.424675, 0.137941, 0.871622)
|
|
||||||
bones/28/rotation = Quaternion(-0.0627838, -0.00116445, -0.50126, 0.863015)
|
|
||||||
bones/29/rotation = Quaternion(0.150998, -0.0515735, 0.668372, 0.726511)
|
|
||||||
bones/31/position = Vector3(-7.29038, -6.72226, -0.133983)
|
|
||||||
bones/31/rotation = Quaternion(-0.453784, 0.542292, 0.542291, -0.453784)
|
|
||||||
bones/32/rotation = Quaternion(0.456756, 0.539878, -0.539587, -0.456893)
|
|
||||||
|
|
||||||
[node name="BoneAttachment3D" parent="EnemyModelView/Armature/Skeleton3D" index="0"]
|
[node name="BoneAttachment3D" parent="EnemyModelView/Armature/Skeleton3D" index="0"]
|
||||||
transform = Transform3D(-0.266252, -0.0359368, -0.963233, -0.333724, -0.934064, 0.127095, -0.904288, 0.355294, 0.236703, -1.68948, 8.20049, 4.9569)
|
transform = Transform3D(-0.266252, -0.0359368, -0.963233, -0.333724, -0.934064, 0.127095, -0.904288, 0.355294, 0.236703, -1.68946, 8.20239, 4.95677)
|
||||||
|
|
||||||
[node name="Collision" type="Area3D" parent="."]
|
[node name="Collision" type="Area3D" parent="."]
|
||||||
collision_layer = 2048
|
collision_layer = 2048
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ using Zennysoft.Game.Abstractions;
|
|||||||
using Zennysoft.Ma.Adapter;
|
using Zennysoft.Ma.Adapter;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Zennysoft.Game.Implementation.Components;
|
|
||||||
|
|
||||||
[Meta(typeof(IAutoNode))]
|
[Meta(typeof(IAutoNode))]
|
||||||
public partial class Game : Node3D, IGame
|
public partial class Game : Node3D, IGame
|
||||||
@@ -95,7 +94,8 @@ public partial class Game : Node3D, IGame
|
|||||||
|
|
||||||
PlayerData = new PlayerData()
|
PlayerData = new PlayerData()
|
||||||
{
|
{
|
||||||
Inventory = _player.Inventory
|
Inventory = (Inventory)_player.Inventory,
|
||||||
|
HealthComponent = (HealthComponent)_player.HealthComponent,
|
||||||
},
|
},
|
||||||
MapData = new MapData()
|
MapData = new MapData()
|
||||||
{
|
{
|
||||||
@@ -119,7 +119,7 @@ public partial class Game : Node3D, IGame
|
|||||||
|
|
||||||
public void OnResolved()
|
public void OnResolved()
|
||||||
{
|
{
|
||||||
var saveFileManager = _container.GetInstance<IMaSaveFileManager<GameData>>();
|
var saveFileManager = _container.GetInstance<IMaSaveFileManager>();
|
||||||
SaveFile = new SaveFile<GameData>(
|
SaveFile = new SaveFile<GameData>(
|
||||||
root: GameChunk,
|
root: GameChunk,
|
||||||
onSave: saveFileManager.Save,
|
onSave: saveFileManager.Save,
|
||||||
@@ -127,7 +127,7 @@ public partial class Game : Node3D, IGame
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var gameData = await saveFileManager.Load();
|
var gameData = await saveFileManager.Load() as GameData;
|
||||||
return gameData;
|
return gameData;
|
||||||
}
|
}
|
||||||
catch (FileNotFoundException)
|
catch (FileNotFoundException)
|
||||||
@@ -138,7 +138,6 @@ public partial class Game : Node3D, IGame
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
GameBinding = GameState.Bind();
|
GameBinding = GameState.Bind();
|
||||||
GameBinding
|
GameBinding
|
||||||
.Handle((in GameState.Output.InitializeGame _) =>
|
.Handle((in GameState.Output.InitializeGame _) =>
|
||||||
@@ -200,22 +199,22 @@ public partial class Game : Node3D, IGame
|
|||||||
.Handle((in GameState.Output.LoadNextFloor _) =>
|
.Handle((in GameState.Output.LoadNextFloor _) =>
|
||||||
{
|
{
|
||||||
FloorClearMenu.FadeOut();
|
FloorClearMenu.FadeOut();
|
||||||
_map.LoadFloor();
|
Task.Run(() => _map.LoadFloor());
|
||||||
if (_player.EquippedWeapon.Value.ItemTag == ItemTag.BreaksOnChange)
|
if (_player.EquipmentComponent.EquippedWeapon.Value.ItemTag == ItemTag.BreaksOnChange)
|
||||||
{
|
{
|
||||||
var itemToDestroy = _player.EquippedWeapon.Value;
|
var itemToDestroy = _player.EquipmentComponent.EquippedWeapon.Value;
|
||||||
_player.Unequip(itemToDestroy);
|
_player.Unequip(itemToDestroy);
|
||||||
_player.Inventory.Remove(itemToDestroy);
|
_player.Inventory.Remove(itemToDestroy);
|
||||||
}
|
}
|
||||||
if (_player.EquippedArmor.Value.ItemTag == ItemTag.BreaksOnChange)
|
if (_player.EquipmentComponent.EquippedArmor.Value.ItemTag == ItemTag.BreaksOnChange)
|
||||||
{
|
{
|
||||||
var itemToDestroy = _player.EquippedArmor.Value;
|
var itemToDestroy = _player.EquipmentComponent.EquippedArmor.Value;
|
||||||
_player.Unequip(itemToDestroy);
|
_player.Unequip(itemToDestroy);
|
||||||
_player.Inventory.Remove(itemToDestroy);
|
_player.Inventory.Remove(itemToDestroy);
|
||||||
}
|
}
|
||||||
if (_player.EquippedAccessory.Value.ItemTag == ItemTag.BreaksOnChange)
|
if (_player.EquipmentComponent.EquippedAccessory.Value.ItemTag == ItemTag.BreaksOnChange)
|
||||||
{
|
{
|
||||||
var itemToDestroy = _player.EquippedAccessory.Value;
|
var itemToDestroy = _player.EquipmentComponent.EquippedAccessory.Value;
|
||||||
_player.Unequip(itemToDestroy);
|
_player.Unequip(itemToDestroy);
|
||||||
_player.Inventory.Remove(itemToDestroy);
|
_player.Inventory.Remove(itemToDestroy);
|
||||||
}
|
}
|
||||||
@@ -245,6 +244,7 @@ public partial class Game : Node3D, IGame
|
|||||||
_effectService = new EffectService(this, _player, _map);
|
_effectService = new EffectService(this, _player, _map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
|
||||||
public void OnReady()
|
public void OnReady()
|
||||||
{
|
{
|
||||||
InitializeGame();
|
InitializeGame();
|
||||||
@@ -254,22 +254,22 @@ public partial class Game : Node3D, IGame
|
|||||||
InGameUI.PlayerInfoUI.Activate();
|
InGameUI.PlayerInfoUI.Activate();
|
||||||
_player.Activate();
|
_player.Activate();
|
||||||
}
|
}
|
||||||
|
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
|
||||||
|
|
||||||
private void FloorClearMenu_SaveAndExit()
|
private void FloorClearMenu_SaveAndExit()
|
||||||
{
|
{
|
||||||
//SaveFile.Save();
|
|
||||||
_player.Deactivate();
|
_player.Deactivate();
|
||||||
GameState.Input(new GameState.Input.ReturnToMainMenu());
|
GameState.Input(new GameState.Input.ReturnToMainMenu());
|
||||||
InGameUI.Hide();
|
InGameUI.Hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void FloorClearMenu_GoToNextFloor() => GameState.Input(new GameState.Input.LoadNextFloor());
|
private void FloorClearMenu_GoToNextFloor() => GameState.Input(new GameState.Input.LoadNextFloor());
|
||||||
|
|
||||||
public void LoadExistingGame() => SaveFile.Load().ContinueWith((_) => CallDeferred(nameof(FinishedLoadingSaveFile)));
|
public void LoadExistingGame() => SaveFile.Load().ContinueWith((_) => CallDeferred(nameof(FinishedLoadingSaveFile)));
|
||||||
|
|
||||||
public void InitializeGame()
|
public void InitializeGame()
|
||||||
{
|
{
|
||||||
_map.InitializeMapData();
|
_map.InitializeMapData();
|
||||||
_player.InitializePlayerState();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void FloorExitReached()
|
public void FloorExitReached()
|
||||||
|
|||||||
43
Zennysoft.Game.Ma/src/game/GameData.cs
Normal file
43
Zennysoft.Game.Ma/src/game/GameData.cs
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
using Chickensoft.Introspection;
|
||||||
|
using Chickensoft.Serialization;
|
||||||
|
using Zennysoft.Game.Ma;
|
||||||
|
|
||||||
|
namespace Zennysoft.Ma.Adapter;
|
||||||
|
|
||||||
|
[Meta, Id("game_data")]
|
||||||
|
public partial record GameData
|
||||||
|
{
|
||||||
|
[Save("player_data")]
|
||||||
|
public required PlayerData PlayerData { get; init; }
|
||||||
|
|
||||||
|
[Save("map_data")]
|
||||||
|
public required MapData MapData { get; init; }
|
||||||
|
|
||||||
|
[Save("rescued_items")]
|
||||||
|
public required RescuedItemDatabase RescuedItems { get; init; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial record PlayerData
|
||||||
|
{
|
||||||
|
[Save("inventory")]
|
||||||
|
public required Inventory Inventory { get; init; }
|
||||||
|
[Save("health_component")]
|
||||||
|
public required HealthComponent HealthComponent { get; init; }
|
||||||
|
[Save("vt_component")]
|
||||||
|
public VTComponent VTComponent { get; init; }
|
||||||
|
[Save("attack_component")]
|
||||||
|
public AttackComponent AttackComponent { get; init; }
|
||||||
|
[Save("defense_component")]
|
||||||
|
public DefenseComponent DefenseComponent { get; init; }
|
||||||
|
[Save("experience_points_component")]
|
||||||
|
public ExperiencePointsComponent ExperiencePointsComponent { get; init; }
|
||||||
|
[Save("luck_component")]
|
||||||
|
public LuckComponent LuckComponent { get; init; }
|
||||||
|
[Save("equipment_component")]
|
||||||
|
public EquipmentComponent EquipmentComponent { get; init; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial record MapData
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
@@ -4,8 +4,8 @@ namespace Zennysoft.Game.Ma;
|
|||||||
using Chickensoft.AutoInject;
|
using Chickensoft.AutoInject;
|
||||||
using Chickensoft.GodotNodeInterfaces;
|
using Chickensoft.GodotNodeInterfaces;
|
||||||
using Chickensoft.SaveFileBuilder;
|
using Chickensoft.SaveFileBuilder;
|
||||||
using Godot;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Zennysoft.Game.Implementation;
|
||||||
using Zennysoft.Ma.Adapter;
|
using Zennysoft.Ma.Adapter;
|
||||||
|
|
||||||
public interface IGame : IProvide<IGame>, IProvide<IGameRepo>, IProvide<IPlayer>, IProvide<IMap>, IProvide<ISaveChunk<GameData>>, INode3D
|
public interface IGame : IProvide<IGame>, IProvide<IGameRepo>, IProvide<IPlayer>, IProvide<IMap>, IProvide<ISaveChunk<GameData>>, INode3D
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using System.Linq;
|
|||||||
using System;
|
using System;
|
||||||
using Zennysoft.Ma.Adapter;
|
using Zennysoft.Ma.Adapter;
|
||||||
using Zennysoft.Ma.Adapter.Entity;
|
using Zennysoft.Ma.Adapter.Entity;
|
||||||
|
using Zennysoft.Game.Implementation;
|
||||||
|
|
||||||
namespace Zennysoft.Game.Ma;
|
namespace Zennysoft.Game.Ma;
|
||||||
|
|
||||||
@@ -37,12 +38,7 @@ public class EffectService
|
|||||||
var enemyList = validRooms.SelectMany(x => x.GetEnemiesInCurrentRoom());
|
var enemyList = validRooms.SelectMany(x => x.GetEnemiesInCurrentRoom());
|
||||||
|
|
||||||
foreach (var enemy in enemyList)
|
foreach (var enemy in enemyList)
|
||||||
{
|
enemy.MoveEnemyToNewRoom(currentMonsterRoom);
|
||||||
var spawnPoints = currentMonsterRoom.EnemySpawnPoints.GetChildren().OfType<Marker3D>().ToList();
|
|
||||||
var spawnPointsGodotCollection = new Godot.Collections.Array<Marker3D>(spawnPoints);
|
|
||||||
var randomSpawnPoint = spawnPointsGodotCollection.PickRandom();
|
|
||||||
enemy.SetEnemyPosition(randomSpawnPoint.GlobalPosition);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void KillHalfEnemiesInRoom()
|
public void KillHalfEnemiesInRoom()
|
||||||
@@ -54,8 +50,8 @@ public class EffectService
|
|||||||
var currentMonsterRoom = (MonsterRoom)currentRoom;
|
var currentMonsterRoom = (MonsterRoom)currentRoom;
|
||||||
var enemyList = currentMonsterRoom.GetEnemiesInCurrentRoom().ToList();
|
var enemyList = currentMonsterRoom.GetEnemiesInCurrentRoom().ToList();
|
||||||
var enemiesToKill = enemyList.Count / 2;
|
var enemiesToKill = enemyList.Count / 2;
|
||||||
//for (var i = 0; i < enemiesToKill; i++)
|
for (var i = 0; i < enemiesToKill; i++)
|
||||||
// enemyList[i].Die();
|
enemyList[i].Die();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void TurnAllEnemiesInRoomIntoHealingItem()
|
public void TurnAllEnemiesInRoomIntoHealingItem()
|
||||||
@@ -68,8 +64,8 @@ public class EffectService
|
|||||||
var currentEnemies = currentRoom.EnemiesInRoom;
|
var currentEnemies = currentRoom.EnemiesInRoom;
|
||||||
foreach (var enemy in currentEnemies)
|
foreach (var enemy in currentEnemies)
|
||||||
{
|
{
|
||||||
//enemy.Die();
|
enemy.Die();
|
||||||
//DropHealingItem(enemy.GetEnemyGlobalPosition());
|
DropHealingItem(enemy.GlobalPosition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,9 +91,7 @@ public class EffectService
|
|||||||
if (currentRoom is not MonsterRoom)
|
if (currentRoom is not MonsterRoom)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var currentEnemies = currentRoom.EnemiesInRoom;
|
currentRoom.EnemiesInRoom.ForEach(e => e.HealthComponent.SetHealth(e.HealthComponent.MaximumHP.Value));
|
||||||
//foreach (var enemy in currentEnemies)
|
|
||||||
// enemy.SetCurrentHP(enemy.GetMaximumHP());
|
|
||||||
_player.HealthComponent.SetHealth(_player.HealthComponent.MaximumHP.Value);
|
_player.HealthComponent.SetHealth(_player.HealthComponent.MaximumHP.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,8 +104,12 @@ public class EffectService
|
|||||||
|
|
||||||
var currentEnemies = currentRoom.EnemiesInRoom;
|
var currentEnemies = currentRoom.EnemiesInRoom;
|
||||||
var hpToAbsorb = 0.0;
|
var hpToAbsorb = 0.0;
|
||||||
//foreach (var enemy in currentEnemies)
|
foreach (var enemy in currentEnemies)
|
||||||
// hpToAbsorb += enemy.CurrentHP.Value * 0.05;
|
{
|
||||||
|
var absorbAmount = enemy.HealthComponent.MaximumHP.Value * 0.05;
|
||||||
|
enemy.HealthComponent.Damage((int)absorbAmount);
|
||||||
|
hpToAbsorb += absorbAmount;
|
||||||
|
}
|
||||||
_player.HealthComponent.Heal((int)hpToAbsorb);
|
_player.HealthComponent.Heal((int)hpToAbsorb);
|
||||||
GD.Print("HP to absorb: " + hpToAbsorb);
|
GD.Print("HP to absorb: " + hpToAbsorb);
|
||||||
}
|
}
|
||||||
@@ -127,7 +125,7 @@ public class EffectService
|
|||||||
foreach (var enemy in currentEnemies)
|
foreach (var enemy in currentEnemies)
|
||||||
{
|
{
|
||||||
var damageDealt = DamageCalculator.CalculateDamage(new Damage(20, elementType, false, false, false), 10, new ElementalResistanceSet(0, 0, 0, 0, 0));
|
var damageDealt = DamageCalculator.CalculateDamage(new Damage(20, elementType, false, false, false), 10, new ElementalResistanceSet(0, 0, 0, 0, 0));
|
||||||
enemy.TakeDamage(damageDealt);
|
enemy.HealthComponent.Damage(damageDealt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,28 +150,25 @@ public class EffectService
|
|||||||
|
|
||||||
public void RaiseCurrentWeaponAttack()
|
public void RaiseCurrentWeaponAttack()
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(_player.EquippedWeapon.Value.ItemName))
|
if (string.IsNullOrEmpty(_player.EquipmentComponent.EquippedWeapon.Value.ItemName))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var currentWeapon = (Weapon)_player.EquippedWeapon.Value;
|
var currentWeapon = (Weapon)_player.EquipmentComponent.EquippedWeapon.Value;
|
||||||
currentWeapon.IncreaseWeaponAttack(1);
|
currentWeapon.IncreaseWeaponAttack(1);
|
||||||
//_player.ModifyBonusAttack(1);
|
_player.AttackComponent.RaiseBonusAttack(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RaiseCurrentArmorDefense()
|
public void RaiseCurrentArmorDefense()
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(_player.EquippedArmor.Value.ItemName))
|
if (string.IsNullOrEmpty(_player.EquipmentComponent.EquippedArmor.Value.ItemName))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var currentArmor = (Armor)_player.EquippedArmor.Value;
|
var currentArmor = (Armor)_player.EquipmentComponent.EquippedArmor.Value;
|
||||||
currentArmor.IncreaseArmorDefense(1);
|
currentArmor.IncreaseArmorDefense(1);
|
||||||
_player.DefenseComponent.RaiseBonusDefense(1);
|
_player.DefenseComponent.RaiseBonusDefense(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RaiseLevel()
|
public void RaiseLevel() => _player.LevelUp();
|
||||||
{
|
|
||||||
_player.LevelUp();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void TeleportToRandomRoom(IEnemy enemy)
|
public void TeleportToRandomRoom(IEnemy enemy)
|
||||||
{
|
{
|
||||||
@@ -189,11 +184,8 @@ public class EffectService
|
|||||||
|
|
||||||
var roomsGodotCollection = new Godot.Collections.Array<MonsterRoom>(validRooms);
|
var roomsGodotCollection = new Godot.Collections.Array<MonsterRoom>(validRooms);
|
||||||
var randomRoom = roomsGodotCollection.PickRandom();
|
var randomRoom = roomsGodotCollection.PickRandom();
|
||||||
var spawnPoints = randomRoom.EnemySpawnPoints.GetChildren().OfType<Marker3D>().ToList();
|
|
||||||
var spawnPointsGodotCollection = new Godot.Collections.Array<Marker3D>(spawnPoints);
|
|
||||||
var randomSpawnPoint = spawnPointsGodotCollection.PickRandom();
|
|
||||||
|
|
||||||
enemy.SetEnemyPosition(randomSpawnPoint.GlobalPosition);
|
enemy.MoveEnemyToNewRoom(randomRoom);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void TeleportToRandomRoom(IPlayer player)
|
public void TeleportToRandomRoom(IPlayer player)
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using Godot;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Zennysoft.Game.Abstractions;
|
using Zennysoft.Game.Abstractions;
|
||||||
|
using Zennysoft.Game.Implementation;
|
||||||
using Zennysoft.Ma.Adapter;
|
using Zennysoft.Ma.Adapter;
|
||||||
|
|
||||||
namespace Zennysoft.Game.Ma;
|
namespace Zennysoft.Game.Ma;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using Chickensoft.Introspection;
|
using Chickensoft.Introspection;
|
||||||
using Chickensoft.Serialization;
|
using Chickensoft.Serialization;
|
||||||
using Godot;
|
using Godot;
|
||||||
|
using Zennysoft.Game.Implementation;
|
||||||
using Zennysoft.Ma.Adapter;
|
using Zennysoft.Ma.Adapter;
|
||||||
|
|
||||||
namespace Zennysoft.Game.Ma;
|
namespace Zennysoft.Game.Ma;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using Chickensoft.Introspection;
|
using Chickensoft.Introspection;
|
||||||
using Chickensoft.Serialization;
|
using Chickensoft.Serialization;
|
||||||
using Godot;
|
using Godot;
|
||||||
|
using Zennysoft.Game.Implementation;
|
||||||
using Zennysoft.Ma.Adapter;
|
using Zennysoft.Ma.Adapter;
|
||||||
|
|
||||||
namespace Zennysoft.Game.Ma;
|
namespace Zennysoft.Game.Ma;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
using Chickensoft.GodotNodeInterfaces;
|
using Chickensoft.GodotNodeInterfaces;
|
||||||
using Chickensoft.Introspection;
|
using Chickensoft.Introspection;
|
||||||
using Godot;
|
using Godot;
|
||||||
|
using Zennysoft.Game.Implementation;
|
||||||
using Zennysoft.Ma.Adapter;
|
using Zennysoft.Ma.Adapter;
|
||||||
|
|
||||||
namespace Zennysoft.Game.Ma;
|
namespace Zennysoft.Game.Ma;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using Chickensoft.Introspection;
|
using Chickensoft.Introspection;
|
||||||
using Chickensoft.Serialization;
|
using Chickensoft.Serialization;
|
||||||
using Godot;
|
using Godot;
|
||||||
|
using Zennysoft.Game.Implementation;
|
||||||
using Zennysoft.Ma.Adapter;
|
using Zennysoft.Ma.Adapter;
|
||||||
|
|
||||||
namespace Zennysoft.Game.Ma;
|
namespace Zennysoft.Game.Ma;
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ using Chickensoft.AutoInject;
|
|||||||
using Chickensoft.Introspection;
|
using Chickensoft.Introspection;
|
||||||
using Godot;
|
using Godot;
|
||||||
using Zennysoft.Game.Abstractions;
|
using Zennysoft.Game.Abstractions;
|
||||||
using Zennysoft.Ma.Adapter;
|
|
||||||
|
|
||||||
namespace Zennysoft.Game.Ma;
|
namespace Zennysoft.Game.Ma;
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using Chickensoft.Introspection;
|
|||||||
using Chickensoft.Serialization;
|
using Chickensoft.Serialization;
|
||||||
using Godot;
|
using Godot;
|
||||||
using Zennysoft.Game.Abstractions;
|
using Zennysoft.Game.Abstractions;
|
||||||
|
using Zennysoft.Game.Implementation;
|
||||||
using Zennysoft.Ma.Adapter;
|
using Zennysoft.Ma.Adapter;
|
||||||
|
|
||||||
namespace Zennysoft.Game.Ma;
|
namespace Zennysoft.Game.Ma;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using Chickensoft.Introspection;
|
using Chickensoft.Introspection;
|
||||||
using Chickensoft.Serialization;
|
using Chickensoft.Serialization;
|
||||||
using Godot;
|
using Godot;
|
||||||
|
using Zennysoft.Game.Implementation;
|
||||||
using Zennysoft.Ma.Adapter;
|
using Zennysoft.Ma.Adapter;
|
||||||
|
|
||||||
namespace Zennysoft.Game.Ma;
|
namespace Zennysoft.Game.Ma;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using Chickensoft.AutoInject;
|
using Chickensoft.AutoInject;
|
||||||
using Chickensoft.Introspection;
|
using Chickensoft.Introspection;
|
||||||
using Godot;
|
using Godot;
|
||||||
|
using Zennysoft.Game.Implementation;
|
||||||
using Zennysoft.Ma.Adapter;
|
using Zennysoft.Ma.Adapter;
|
||||||
using Zennysoft.Ma.Adapter.Entity;
|
using Zennysoft.Ma.Adapter.Entity;
|
||||||
|
|
||||||
@@ -108,22 +109,22 @@ public partial class ThrownItem : RigidBody3D
|
|||||||
{
|
{
|
||||||
switch (throwableItem.ThrowableItemTag)
|
switch (throwableItem.ThrowableItemTag)
|
||||||
{
|
{
|
||||||
//case ThrowableItemTag.LowerTargetTo1HP:
|
case ThrowableItemTag.LowerTargetTo1HP:
|
||||||
// enemy.TakeDamage(enemy.CurrentHP.Value - 1, ignoreDefense: true, ignoreElementalResistance: true);
|
enemy.HealthComponent.SetHealth(1);
|
||||||
// break;
|
break;
|
||||||
case ThrowableItemTag.TeleportToRandomLocation:
|
case ThrowableItemTag.TeleportToRandomLocation:
|
||||||
_effectService.TeleportToRandomRoom(enemy);
|
_effectService.TeleportToRandomRoom(enemy);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
var damageDealt = DamageCalculator.CalculateDamage(new Damage(throwableItem.ThrowDamage, throwableItem.ElementType, false, false, false), 10, new ElementalResistanceSet(0, 0, 0, 0, 0));
|
var damageDealt = DamageCalculator.CalculateDamage(new Damage(throwableItem.ThrowDamage, throwableItem.ElementType, false, false, false), 10, new ElementalResistanceSet(0, 0, 0, 0, 0));
|
||||||
enemy.TakeDamage(damageDealt);
|
enemy.HealthComponent.Damage(damageDealt);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var damageDealt = DamageCalculator.CalculateDamage(new Damage(ItemThatIsThrown.ThrowDamage, ElementType.None, false, false, false), 10, new ElementalResistanceSet(0, 0, 0, 0, 0));
|
var damageDealt = DamageCalculator.CalculateDamage(new Damage(ItemThatIsThrown.ThrowDamage, ElementType.None, false, false, false), 10, new ElementalResistanceSet(0, 0, 0, 0, 0));
|
||||||
enemy.TakeDamage(damageDealt);
|
enemy.HealthComponent.Damage(damageDealt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
using Chickensoft.Introspection;
|
using Chickensoft.Introspection;
|
||||||
using Chickensoft.Serialization;
|
using Chickensoft.Serialization;
|
||||||
using Godot;
|
using Godot;
|
||||||
|
using Zennysoft.Game.Implementation;
|
||||||
using Zennysoft.Ma.Adapter;
|
using Zennysoft.Ma.Adapter;
|
||||||
|
|
||||||
namespace Zennysoft.Game.Ma;
|
namespace Zennysoft.Game.Ma;
|
||||||
|
|||||||
@@ -3,9 +3,7 @@ using Chickensoft.Collections;
|
|||||||
using Chickensoft.GodotNodeInterfaces;
|
using Chickensoft.GodotNodeInterfaces;
|
||||||
using Chickensoft.SaveFileBuilder;
|
using Chickensoft.SaveFileBuilder;
|
||||||
using Godot;
|
using Godot;
|
||||||
using System.Collections.Immutable;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Zennysoft.Ma.Adapter;
|
|
||||||
|
|
||||||
namespace Zennysoft.Game.Ma;
|
namespace Zennysoft.Game.Ma;
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ using Chickensoft.AutoInject;
|
|||||||
using Chickensoft.Introspection;
|
using Chickensoft.Introspection;
|
||||||
using Godot;
|
using Godot;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Zennysoft.Game.Implementation;
|
||||||
using Zennysoft.Ma.Adapter;
|
using Zennysoft.Ma.Adapter;
|
||||||
|
|
||||||
namespace Zennysoft.Game.Ma;
|
namespace Zennysoft.Game.Ma;
|
||||||
|
|||||||
@@ -1,12 +1,10 @@
|
|||||||
using Chickensoft.AutoInject;
|
using Chickensoft.AutoInject;
|
||||||
using Chickensoft.Collections;
|
|
||||||
using Chickensoft.GodotNodeInterfaces;
|
using Chickensoft.GodotNodeInterfaces;
|
||||||
using Chickensoft.Introspection;
|
using Chickensoft.Introspection;
|
||||||
using Chickensoft.SaveFileBuilder;
|
using Chickensoft.SaveFileBuilder;
|
||||||
using Godot;
|
using Godot;
|
||||||
using SimpleInjector;
|
using SimpleInjector;
|
||||||
using System;
|
using System;
|
||||||
using Zennysoft.Game.Implementation.Components;
|
|
||||||
using Zennysoft.Ma.Adapter;
|
using Zennysoft.Ma.Adapter;
|
||||||
using Zennysoft.Ma.Adapter.Entity;
|
using Zennysoft.Ma.Adapter.Entity;
|
||||||
|
|
||||||
@@ -27,17 +25,19 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<ISaveChunk<Play
|
|||||||
public ISaveChunk<PlayerData> PlayerChunk { get; set; } = default!;
|
public ISaveChunk<PlayerData> PlayerChunk { get; set; } = default!;
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
public HealthComponent HealthComponent { get; private set; }
|
public IHealthComponent HealthComponent { get; private set; }
|
||||||
|
|
||||||
public VTComponent VTComponent { get; private set; }
|
public IVTComponent VTComponent { get; private set; }
|
||||||
|
|
||||||
public AttackComponent AttackComponent { get; private set; }
|
public IAttackComponent AttackComponent { get; private set; }
|
||||||
|
|
||||||
public DefenseComponent DefenseComponent { get; private set; }
|
public IDefenseComponent DefenseComponent { get; private set; }
|
||||||
|
|
||||||
public ExperiencePointsComponent ExperiencePointsComponent { get; private set; }
|
public IExperiencePointsComponent ExperiencePointsComponent { get; private set; }
|
||||||
|
|
||||||
public LuckComponent LuckComponent { get; private set; }
|
public ILuckComponent LuckComponent { get; private set; }
|
||||||
|
|
||||||
|
public IEquipmentComponent EquipmentComponent { get; private set; }
|
||||||
|
|
||||||
public Vector3 CurrentPosition => GlobalPosition;
|
public Vector3 CurrentPosition => GlobalPosition;
|
||||||
|
|
||||||
@@ -45,15 +45,6 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<ISaveChunk<Play
|
|||||||
|
|
||||||
public IInventory Inventory { get; private set; } = default!;
|
public IInventory Inventory { get; private set; } = default!;
|
||||||
|
|
||||||
public AutoProp<EquipableItem> EquippedWeapon => _equippedWeapon;
|
|
||||||
private AutoProp<EquipableItem> _equippedWeapon { get; set; } = new AutoProp<EquipableItem>(new Weapon());
|
|
||||||
|
|
||||||
public AutoProp<EquipableItem> EquippedArmor => _equippedArmor;
|
|
||||||
private AutoProp<EquipableItem> _equippedArmor { get; set; } = new AutoProp<EquipableItem>(new Armor());
|
|
||||||
|
|
||||||
public AutoProp<EquipableItem> EquippedAccessory => _equippedAccessory;
|
|
||||||
private AutoProp<EquipableItem> _equippedAccessory { get; set; } = new AutoProp<EquipableItem>(new Accessory());
|
|
||||||
|
|
||||||
private PlayerLogic.Settings Settings { get; set; } = default!;
|
private PlayerLogic.Settings Settings { get; set; } = default!;
|
||||||
|
|
||||||
private IPlayerLogic PlayerLogic { get; set; } = default!;
|
private IPlayerLogic PlayerLogic { get; set; } = default!;
|
||||||
@@ -119,14 +110,16 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<ISaveChunk<Play
|
|||||||
private Vector3 _knockbackDirection = Vector3.Zero;
|
private Vector3 _knockbackDirection = Vector3.Zero;
|
||||||
|
|
||||||
#region Initialization
|
#region Initialization
|
||||||
public void InitializePlayerState()
|
public Player()
|
||||||
{
|
{
|
||||||
Inventory = new Inventory();
|
Inventory = new Inventory();
|
||||||
SetProcessInput(false);
|
HealthComponent = new HealthComponent(InitialHP);
|
||||||
SetPhysicsProcess(false);
|
VTComponent = new VTComponent(InitialVT);
|
||||||
|
AttackComponent = new AttackComponent(InitialAttack);
|
||||||
HealthTimer.WaitTime = _healthTimerWaitTime;
|
DefenseComponent = new DefenseComponent(InitialDefense);
|
||||||
HealthTimer.Timeout += OnHealthTimerTimeout;
|
ExperiencePointsComponent = new ExperiencePointsComponent();
|
||||||
|
LuckComponent = new LuckComponent(InitialLuck);
|
||||||
|
EquipmentComponent = new EquipmentComponent();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Setup()
|
public void Setup()
|
||||||
@@ -138,9 +131,6 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<ISaveChunk<Play
|
|||||||
PlayerLogic.Set(this as IPlayer);
|
PlayerLogic.Set(this as IPlayer);
|
||||||
PlayerLogic.Set(Settings);
|
PlayerLogic.Set(Settings);
|
||||||
PlayerLogic.Set(_gameRepo);
|
PlayerLogic.Set(_gameRepo);
|
||||||
|
|
||||||
Hitbox.AreaEntered += Hitbox_AreaEntered;
|
|
||||||
CollisionDetector.AreaEntered += CollisionDetector_AreaEntered;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnResolved()
|
public void OnResolved()
|
||||||
@@ -150,11 +140,13 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<ISaveChunk<Play
|
|||||||
PlayerChunk = new SaveChunk<PlayerData>(
|
PlayerChunk = new SaveChunk<PlayerData>(
|
||||||
onSave: (chunk) => new PlayerData()
|
onSave: (chunk) => new PlayerData()
|
||||||
{
|
{
|
||||||
Inventory = Inventory
|
Inventory = (Inventory)Inventory,
|
||||||
|
HealthComponent = (HealthComponent)HealthComponent
|
||||||
},
|
},
|
||||||
onLoad: (chunk, data) =>
|
onLoad: (chunk, data) =>
|
||||||
{
|
{
|
||||||
Inventory = data.Inventory;
|
Inventory = data.Inventory;
|
||||||
|
HealthComponent = data.HealthComponent;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -173,22 +165,18 @@ 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()
|
||||||
{
|
{
|
||||||
|
Hitbox.AreaEntered += Hitbox_AreaEntered;
|
||||||
|
CollisionDetector.AreaEntered += CollisionDetector_AreaEntered;
|
||||||
SwordSlashAnimation.Position = GetViewport().GetVisibleRect().Size / 2;
|
SwordSlashAnimation.Position = GetViewport().GetVisibleRect().Size / 2;
|
||||||
HealthComponent = new HealthComponent(InitialHP);
|
|
||||||
HealthComponent.HealthReachedZero += Die;
|
HealthComponent.HealthReachedZero += Die;
|
||||||
|
HealthTimer.WaitTime = _healthTimerWaitTime;
|
||||||
VTComponent = new VTComponent(InitialVT);
|
HealthTimer.Timeout += OnHealthTimerTimeout;
|
||||||
AttackComponent = new AttackComponent(InitialAttack);
|
SetProcessInput(false);
|
||||||
DefenseComponent = new DefenseComponent(InitialDefense);
|
SetPhysicsProcess(false);
|
||||||
ExperiencePointsComponent = new ExperiencePointsComponent();
|
|
||||||
LuckComponent = new LuckComponent(InitialLuck);
|
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -206,20 +194,7 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<ISaveChunk<Play
|
|||||||
SetHealthTimerStatus(false);
|
SetHealthTimerStatus(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Attack()
|
private void SetHealthTimerStatus(bool isActive)
|
||||||
{
|
|
||||||
if (PlayerIsHittingGeometry())
|
|
||||||
{
|
|
||||||
AnimationPlayer.Play("hit_wall");
|
|
||||||
_gameRepo.OnPlayerAttackedWall();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
PlayAttackAnimation();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetHealthTimerStatus(bool isActive)
|
|
||||||
{
|
{
|
||||||
if (isActive)
|
if (isActive)
|
||||||
HealthTimer.Start();
|
HealthTimer.Start();
|
||||||
@@ -227,22 +202,6 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<ISaveChunk<Play
|
|||||||
HealthTimer.Stop();
|
HealthTimer.Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Move(float delta)
|
|
||||||
{
|
|
||||||
var rawInput = GlobalInputVector;
|
|
||||||
var strafeLeftInput = LeftStrafeInputVector;
|
|
||||||
var strafeRightInput = RightStrafeInputVector;
|
|
||||||
|
|
||||||
var transform = Transform;
|
|
||||||
transform.Basis = new Basis(Vector3.Up, Settings.RotationSpeed * -rawInput.X * delta) * transform.Basis;
|
|
||||||
var moveDirection = new Vector3(strafeRightInput - strafeLeftInput, 0, rawInput.Z).Normalized();
|
|
||||||
var velocity = Basis * moveDirection * Settings.MoveSpeed * Settings.Acceleration;
|
|
||||||
_knockbackStrength *= 0.9f;
|
|
||||||
Transform = Transform with { Basis = transform.Basis };
|
|
||||||
Velocity = velocity + (_knockbackDirection * _knockbackStrength);
|
|
||||||
MoveAndSlide();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void TeleportPlayer(Transform3D newTransform)
|
public void TeleportPlayer(Transform3D newTransform)
|
||||||
{
|
{
|
||||||
Transform = newTransform;
|
Transform = newTransform;
|
||||||
@@ -250,7 +209,7 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<ISaveChunk<Play
|
|||||||
|
|
||||||
public void TakeDamage(Damage damage)
|
public void TakeDamage(Damage damage)
|
||||||
{
|
{
|
||||||
var damageReceived = DamageCalculator.CalculateDamage(damage, DefenseComponent.TotalDefense, ((Armor)_equippedArmor.Value).Stats.ElementalResistanceSet);
|
var damageReceived = DamageCalculator.CalculateDamage(damage, DefenseComponent.TotalDefense, ((Armor)EquipmentComponent.EquippedArmor.Value).Stats.ElementalResistanceSet);
|
||||||
HealthComponent.Damage(damageReceived);
|
HealthComponent.Damage(damageReceived);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -306,21 +265,21 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<ISaveChunk<Play
|
|||||||
|
|
||||||
if (equipable is Weapon weapon)
|
if (equipable is Weapon weapon)
|
||||||
{
|
{
|
||||||
Unequip(_equippedWeapon.Value);
|
Unequip(EquipmentComponent.EquippedWeapon.Value);
|
||||||
weapon.IsEquipped = true;
|
weapon.IsEquipped = true;
|
||||||
_equippedWeapon.OnNext(weapon);
|
EquipmentComponent.Equip(weapon);
|
||||||
}
|
}
|
||||||
else if (equipable is Armor armor)
|
else if (equipable is Armor armor)
|
||||||
{
|
{
|
||||||
Unequip(_equippedArmor.Value);
|
Unequip(EquipmentComponent.EquippedArmor.Value);
|
||||||
armor.IsEquipped = true;
|
armor.IsEquipped = true;
|
||||||
_equippedArmor.OnNext(armor);
|
EquipmentComponent.Equip(armor);
|
||||||
}
|
}
|
||||||
else if (equipable is Accessory accessory)
|
else if (equipable is Accessory accessory)
|
||||||
{
|
{
|
||||||
Unequip(_equippedAccessory.Value);
|
Unequip(EquipmentComponent.EquippedAccessory.Value);
|
||||||
accessory.IsEquipped = true;
|
accessory.IsEquipped = true;
|
||||||
_equippedAccessory.OnNext(accessory);
|
EquipmentComponent.Equip(accessory);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
throw new NotImplementedException("Item type is not supported.");
|
throw new NotImplementedException("Item type is not supported.");
|
||||||
@@ -331,17 +290,17 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<ISaveChunk<Play
|
|||||||
if (equipable is Weapon weapon)
|
if (equipable is Weapon weapon)
|
||||||
{
|
{
|
||||||
weapon.IsEquipped = false;
|
weapon.IsEquipped = false;
|
||||||
_equippedWeapon.OnNext(new Weapon());
|
EquipmentComponent.Unequip(weapon);
|
||||||
}
|
}
|
||||||
else if (equipable is Armor armor)
|
else if (equipable is Armor armor)
|
||||||
{
|
{
|
||||||
armor.IsEquipped = false;
|
armor.IsEquipped = false;
|
||||||
_equippedArmor.OnNext(new Armor());
|
EquipmentComponent.Unequip(armor);
|
||||||
}
|
}
|
||||||
else if (equipable is Accessory accessory)
|
else if (equipable is Accessory accessory)
|
||||||
{
|
{
|
||||||
accessory.IsEquipped = false;
|
accessory.IsEquipped = false;
|
||||||
_equippedAccessory.OnNext(new Accessory());
|
EquipmentComponent.Unequip(accessory);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
throw new NotImplementedException("Item type is not supported.");
|
throw new NotImplementedException("Item type is not supported.");
|
||||||
@@ -365,6 +324,19 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<ISaveChunk<Play
|
|||||||
|
|
||||||
private static float RightStrafeInputVector => Input.GetActionStrength(GameInputs.StrafeRight);
|
private static float RightStrafeInputVector => Input.GetActionStrength(GameInputs.StrafeRight);
|
||||||
|
|
||||||
|
private void Attack()
|
||||||
|
{
|
||||||
|
if (PlayerIsHittingGeometry())
|
||||||
|
{
|
||||||
|
AnimationPlayer.Play("hit_wall");
|
||||||
|
_gameRepo.OnPlayerAttackedWall();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PlayAttackAnimation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void ThrowItem()
|
private void ThrowItem()
|
||||||
{
|
{
|
||||||
var itemScene = GD.Load<PackedScene>("res://src/items/throwable/ThrowableItem.tscn");
|
var itemScene = GD.Load<PackedScene>("res://src/items/throwable/ThrowableItem.tscn");
|
||||||
@@ -376,7 +348,7 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<ISaveChunk<Play
|
|||||||
|
|
||||||
private void PlayAttackAnimation()
|
private void PlayAttackAnimation()
|
||||||
{
|
{
|
||||||
var attackSpeed = ((Weapon)EquippedWeapon.Value).AttackSpeed;
|
var attackSpeed = ((Weapon)EquipmentComponent.EquippedWeapon.Value).AttackSpeed;
|
||||||
AnimationPlayer.SetSpeedScale((float)attackSpeed);
|
AnimationPlayer.SetSpeedScale((float)attackSpeed);
|
||||||
AnimationPlayer.Play("attack");
|
AnimationPlayer.Play("attack");
|
||||||
_gameRepo.OnPlayerAttack();
|
_gameRepo.OnPlayerAttack();
|
||||||
@@ -388,13 +360,29 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<ISaveChunk<Play
|
|||||||
PlayerBinding.Dispose();
|
PlayerBinding.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void Move(float delta)
|
||||||
|
{
|
||||||
|
var rawInput = GlobalInputVector;
|
||||||
|
var strafeLeftInput = LeftStrafeInputVector;
|
||||||
|
var strafeRightInput = RightStrafeInputVector;
|
||||||
|
|
||||||
|
var transform = Transform;
|
||||||
|
transform.Basis = new Basis(Vector3.Up, Settings.RotationSpeed * -rawInput.X * delta) * transform.Basis;
|
||||||
|
var moveDirection = new Vector3(strafeRightInput - strafeLeftInput, 0, rawInput.Z).Normalized();
|
||||||
|
var velocity = Basis * moveDirection * Settings.MoveSpeed * Settings.Acceleration;
|
||||||
|
_knockbackStrength *= 0.9f;
|
||||||
|
Transform = Transform with { Basis = transform.Basis };
|
||||||
|
Velocity = velocity + (_knockbackDirection * _knockbackStrength);
|
||||||
|
MoveAndSlide();
|
||||||
|
}
|
||||||
|
|
||||||
private void OnPlayerPositionUpdated(Vector3 globalPosition) => GlobalPosition = globalPosition;
|
private void OnPlayerPositionUpdated(Vector3 globalPosition) => GlobalPosition = globalPosition;
|
||||||
|
|
||||||
private void OnHealthTimerTimeout()
|
private void OnHealthTimerTimeout()
|
||||||
{
|
{
|
||||||
if (VTComponent.CurrentVT.Value > 0)
|
if (VTComponent.CurrentVT.Value > 0)
|
||||||
{
|
{
|
||||||
if (((Accessory)EquippedAccessory.Value).AccessoryTag == AccessoryTag.HalfVTConsumption)
|
if (((Accessory)EquipmentComponent.EquippedAccessory.Value).AccessoryTag == AccessoryTag.HalfVTConsumption)
|
||||||
reduceOnTick = !reduceOnTick;
|
reduceOnTick = !reduceOnTick;
|
||||||
|
|
||||||
HealthComponent.Heal(1);
|
HealthComponent.Heal(1);
|
||||||
@@ -415,21 +403,21 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<ISaveChunk<Play
|
|||||||
|
|
||||||
private void HitEnemy(IEnemy enemy)
|
private void HitEnemy(IEnemy enemy)
|
||||||
{
|
{
|
||||||
var ignoreElementalResistance = ((Weapon)EquippedWeapon.Value).WeaponTag == WeaponTag.IgnoreAffinity;
|
var ignoreElementalResistance = ((Weapon)EquipmentComponent.EquippedWeapon.Value).WeaponTag == WeaponTag.IgnoreAffinity;
|
||||||
var isCriticalHit = BattleExtensions.IsCriticalHit(LuckComponent.Luck.Value);
|
var isCriticalHit = BattleExtensions.IsCriticalHit(LuckComponent.Luck.Value);
|
||||||
var element = ((Weapon)EquippedWeapon.Value).WeaponElement;
|
var element = ((Weapon)EquipmentComponent.EquippedWeapon.Value).WeaponElement;
|
||||||
var baseAttack = new Damage(
|
var baseAttack = new Damage(
|
||||||
(int)(AttackComponent.TotalAttack * ((Weapon)EquippedWeapon.Value).ElementalDamageBonus),
|
(int)(AttackComponent.TotalAttack * ((Weapon)EquipmentComponent.EquippedWeapon.Value).ElementalDamageBonus),
|
||||||
element,
|
element,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
ignoreElementalResistance);
|
ignoreElementalResistance);
|
||||||
var damageDealt = DamageCalculator.CalculateDamage(baseAttack, enemy.DefenseComponent.TotalDefense, new ElementalResistanceSet(0, 0, 0, 0, 0));
|
var damageDealt = DamageCalculator.CalculateDamage(baseAttack, enemy.DefenseComponent.TotalDefense, new ElementalResistanceSet(0, 0, 0, 0, 0));
|
||||||
enemy.TakeDamage(damageDealt);
|
enemy.HealthComponent.Damage(damageDealt);
|
||||||
|
|
||||||
if (((Weapon)EquippedWeapon.Value).WeaponTag == WeaponTag.Knockback && enemy is IKnockbackable knockbackable)
|
if (((Weapon)EquipmentComponent.EquippedWeapon.Value).WeaponTag == WeaponTag.Knockback && enemy is IKnockbackable knockbackable)
|
||||||
knockbackable.Knockback(0.3f, -CurrentBasis.Z.Normalized());
|
knockbackable.Knockback(0.3f, -CurrentBasis.Z.Normalized());
|
||||||
if (((Weapon)EquippedWeapon.Value).WeaponTag == WeaponTag.SelfDamage)
|
if (((Weapon)EquipmentComponent.EquippedWeapon.Value).WeaponTag == WeaponTag.SelfDamage)
|
||||||
TakeDamage(new Damage(5, ElementType.None, false, true, true));
|
TakeDamage(new Damage(5, ElementType.None, false, true, true));
|
||||||
|
|
||||||
_gameRepo.OnPlayerAttackedEnemy();
|
_gameRepo.OnPlayerAttackedEnemy();
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
using Chickensoft.Collections;
|
|
||||||
using Zennysoft.Game.Implementation.Components;
|
|
||||||
|
|
||||||
namespace Zennysoft.Game.Ma;
|
|
||||||
|
|
||||||
public interface ICharacterStats
|
|
||||||
{
|
|
||||||
public HealthComponent HP { get; }
|
|
||||||
|
|
||||||
public IAutoProp<int> CurrentAttack { get; }
|
|
||||||
|
|
||||||
public IAutoProp<int> CurrentDefense { get; }
|
|
||||||
|
|
||||||
public IAutoProp<int> MaxAttack { get; }
|
|
||||||
|
|
||||||
public IAutoProp<int> MaxDefense { get; }
|
|
||||||
|
|
||||||
public IAutoProp<double> Luck { get; }
|
|
||||||
}
|
|
||||||
18
Zennysoft.Game.Ma/src/ui/inventory_menu/IItemSlot.cs
Normal file
18
Zennysoft.Game.Ma/src/ui/inventory_menu/IItemSlot.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
using Chickensoft.GodotNodeInterfaces;
|
||||||
|
using Zennysoft.Game.Implementation;
|
||||||
|
using Zennysoft.Ma.Adapter;
|
||||||
|
|
||||||
|
namespace Zennysoft.Game.Ma;
|
||||||
|
|
||||||
|
public interface IItemSlot : IHBoxContainer
|
||||||
|
{
|
||||||
|
public InventoryItem Item { get; set; }
|
||||||
|
|
||||||
|
public void SetItemStyle();
|
||||||
|
|
||||||
|
public void SetSelectedItemStyle();
|
||||||
|
|
||||||
|
public void SetEquippedItemStyle();
|
||||||
|
|
||||||
|
public void SetEquippedSelectedItemStyle();
|
||||||
|
}
|
||||||
1
Zennysoft.Game.Ma/src/ui/inventory_menu/IItemSlot.cs.uid
Normal file
1
Zennysoft.Game.Ma/src/ui/inventory_menu/IItemSlot.cs.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://cyit2s4ahwfqf
|
||||||
@@ -4,6 +4,7 @@ using Chickensoft.Introspection;
|
|||||||
using Godot;
|
using Godot;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Zennysoft.Game.Implementation;
|
||||||
using Zennysoft.Ma.Adapter;
|
using Zennysoft.Ma.Adapter;
|
||||||
|
|
||||||
namespace Zennysoft.Game.Ma;
|
namespace Zennysoft.Game.Ma;
|
||||||
@@ -344,7 +345,7 @@ public partial class InventoryMenu : Control, IInventoryMenu
|
|||||||
if (equipableItem.IsEquipped)
|
if (equipableItem.IsEquipped)
|
||||||
{
|
{
|
||||||
ItemEffectLabel.Text = $"{itemSlot.Item.GetType()} unequipped.";
|
ItemEffectLabel.Text = $"{itemSlot.Item.GetType()} unequipped.";
|
||||||
Player.Unequip(equipableItem);
|
Player.EquipmentComponent.Unequip(equipableItem);
|
||||||
itemSlot.SetSelectedItemStyle();
|
itemSlot.SetSelectedItemStyle();
|
||||||
if (equipableItem.ItemTag == ItemTag.BreaksOnChange)
|
if (equipableItem.ItemTag == ItemTag.BreaksOnChange)
|
||||||
Player.Inventory.Remove(equipableItem);
|
Player.Inventory.Remove(equipableItem);
|
||||||
@@ -352,7 +353,7 @@ public partial class InventoryMenu : Control, IInventoryMenu
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
ItemEffectLabel.Text = $"{itemSlot.Item.GetType()} equipped.";
|
ItemEffectLabel.Text = $"{itemSlot.Item.GetType()} equipped.";
|
||||||
Player.Equip(equipableItem);
|
Player.EquipmentComponent.Equip(equipableItem);
|
||||||
itemSlot.SetEquippedSelectedItemStyle();
|
itemSlot.SetEquippedSelectedItemStyle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,25 +1,12 @@
|
|||||||
using Chickensoft.AutoInject;
|
using Chickensoft.AutoInject;
|
||||||
using Chickensoft.GodotNodeInterfaces;
|
|
||||||
using Chickensoft.Introspection;
|
using Chickensoft.Introspection;
|
||||||
using Godot;
|
using Godot;
|
||||||
using Zennysoft.Game.Abstractions;
|
using Zennysoft.Game.Abstractions;
|
||||||
|
using Zennysoft.Game.Implementation;
|
||||||
using Zennysoft.Ma.Adapter;
|
using Zennysoft.Ma.Adapter;
|
||||||
|
|
||||||
namespace Zennysoft.Game.Ma;
|
namespace Zennysoft.Game.Ma;
|
||||||
|
|
||||||
public interface IItemSlot : IHBoxContainer
|
|
||||||
{
|
|
||||||
public InventoryItem Item { get; set; }
|
|
||||||
|
|
||||||
public void SetItemStyle();
|
|
||||||
|
|
||||||
public void SetSelectedItemStyle();
|
|
||||||
|
|
||||||
public void SetEquippedItemStyle();
|
|
||||||
|
|
||||||
public void SetEquippedSelectedItemStyle();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Meta(typeof(IAutoNode))]
|
[Meta(typeof(IAutoNode))]
|
||||||
public partial class ItemSlot : HBoxContainer, IItemSlot
|
public partial class ItemSlot : HBoxContainer, IItemSlot
|
||||||
{
|
{
|
||||||
@@ -27,8 +14,6 @@ public partial class ItemSlot : HBoxContainer, IItemSlot
|
|||||||
|
|
||||||
[Dependency] public IPlayer Player => this.DependOn<IPlayer>();
|
[Dependency] public IPlayer Player => this.DependOn<IPlayer>();
|
||||||
|
|
||||||
//[Node] public Label EquipBonus { get; set; } = default!;
|
|
||||||
|
|
||||||
[Node] public TextureRect ItemTexture { get; set; } = default!;
|
[Node] public TextureRect ItemTexture { get; set; } = default!;
|
||||||
|
|
||||||
[Node] public Label ItemName { get; set; } = default!;
|
[Node] public Label ItemName { get; set; } = default!;
|
||||||
@@ -36,7 +21,9 @@ public partial class ItemSlot : HBoxContainer, IItemSlot
|
|||||||
[Node] public Label ItemCount { get; set; } = default!;
|
[Node] public Label ItemCount { get; set; } = default!;
|
||||||
|
|
||||||
private static LabelSettings ItemFont => GD.Load<LabelSettings>("res://src/ui/label_settings/MainTextBold.tres");
|
private static LabelSettings ItemFont => GD.Load<LabelSettings>("res://src/ui/label_settings/MainTextBold.tres");
|
||||||
|
|
||||||
private static LabelSettings SelectedItemFont => GD.Load<LabelSettings>("res://src/ui/label_settings/MainTextFontItalicized.tres");
|
private static LabelSettings SelectedItemFont => GD.Load<LabelSettings>("res://src/ui/label_settings/MainTextFontItalicized.tres");
|
||||||
|
|
||||||
private static LabelSettings EquippedItemFont => GD.Load<LabelSettings>("res://src/ui/label_settings/MainTextFontEquipped.tres");
|
private static LabelSettings EquippedItemFont => GD.Load<LabelSettings>("res://src/ui/label_settings/MainTextFontEquipped.tres");
|
||||||
|
|
||||||
private static LabelSettings SelectedEquippedItemFont => GD.Load<LabelSettings>("res://src/ui/label_settings/MainTextFontSelectedEquipped.tres");
|
private static LabelSettings SelectedEquippedItemFont => GD.Load<LabelSettings>("res://src/ui/label_settings/MainTextFontSelectedEquipped.tres");
|
||||||
@@ -45,9 +32,9 @@ public partial class ItemSlot : HBoxContainer, IItemSlot
|
|||||||
{
|
{
|
||||||
ItemName.Text = Item.ItemName;
|
ItemName.Text = Item.ItemName;
|
||||||
ItemTexture.Texture = Item.GetTexture();
|
ItemTexture.Texture = Item.GetTexture();
|
||||||
Player.EquippedWeapon.Sync += EquipableItem_Sync;
|
Player.EquipmentComponent.EquippedWeapon.Sync += EquipableItem_Sync;
|
||||||
Player.EquippedArmor.Sync += EquipableItem_Sync;
|
Player.EquipmentComponent.EquippedArmor.Sync += EquipableItem_Sync;
|
||||||
Player.EquippedAccessory.Sync += EquipableItem_Sync;
|
Player.EquipmentComponent.EquippedAccessory.Sync += EquipableItem_Sync;
|
||||||
|
|
||||||
if (Item is IStackable stackableItem)
|
if (Item is IStackable stackableItem)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ using Godot;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Zennysoft.Game.Implementation;
|
||||||
using Zennysoft.Ma.Adapter;
|
using Zennysoft.Ma.Adapter;
|
||||||
|
|
||||||
namespace Zennysoft.Game.Ma;
|
namespace Zennysoft.Game.Ma;
|
||||||
|
|||||||
Reference in New Issue
Block a user