using Chickensoft.AutoInject; using Chickensoft.Collections; using Chickensoft.Introspection; using Godot; using System; using System.Linq; using System.Threading.Tasks; namespace Zennysoft.Game.Ma; [Meta(typeof(IAutoNode))] public partial class Map : Node3D, IMap { public override void _Notification(int what) => this.Notify(what); [Dependency] public IGame Game => this.DependOn(); [Node] public Node MapOrder { get; set; } = default!; [Node] public AnimationPlayer AnimationPlayer { get; set; } = default!; public IDungeonFloor CurrentFloor { get; private set; } public AutoProp CurrentFloorNumber { get; private set; } = new AutoProp(0); private readonly string _floorFilePath = @"res://src/map/dungeon/floors/"; public event Action SpawnPointCreated; public event Action FloorLoaded; public void OnResolved() { this.Provide(); } public void InitializeMapData() { CurrentFloorNumber.OnNext(-1); } public IDungeonRoom GetPlayersCurrentRoom() { var rooms = CurrentFloor.Rooms; var playersRoom = rooms.SingleOrDefault(x => x.IsPlayerInRoom); return playersRoom; } public Transform3D GetPlayerSpawnPosition() => CurrentFloor.GetPlayerSpawnPoint(); public async Task LoadFloor() { var floor = MapOrder.GetChildren().OfType().ElementAt(CurrentFloorNumber.Value + 1); var sceneToLoad = LayoutToScenePathConverter.Convert(floor); await LoadFloor(sceneToLoad); } public async Task LoadFloor(string sceneName) { AnimationPlayer.CallDeferred(AnimationPlayer.MethodName.Play, "fade_out"); ClearMap(); var newFloor = await LoadNewFloor(sceneName); AddChild(newFloor); InitializeFloor(newFloor); var floor = MapOrder.GetChildren().OfType().ElementAt(CurrentFloorNumber.Value + 1); if (CurrentFloor is DungeonFloor dungeonFloor && floor is DungeonFloorNode dungeonFloorNode) dungeonFloor.SpawnEnemies(dungeonFloorNode); AnimationPlayer.CallDeferred(AnimationPlayer.MethodName.Play, ("fade_in")); } public void ClearMap() { AnimationPlayer.CallDeferred(AnimationPlayer.MethodName.Play, "fade_out"); CurrentFloor?.CallDeferred(MethodName.QueueFree, []); SpawnPointCreated?.Invoke(new Transform3D(Basis.Identity, new Vector3(-999, -999, -999))); } private void InitializeFloor(Node newFloor) { CurrentFloor = (IDungeonFloor)newFloor; SetupDungeonFloor(); CurrentFloor.FloorIsLoaded = true; CurrentFloorNumber.OnNext(CurrentFloorNumber.Value + 1); FloorLoaded?.Invoke(); } private async Task LoadNewFloor(string sceneName) { var sceneLoader = new SceneLoader(); AddChild(sceneLoader); sceneLoader.LoadSceneRequest(sceneName); await ToSignal(sceneLoader, SceneLoader.SignalName.SceneLoaded); var result = sceneLoader.LoadedScene; sceneLoader.QueueFree(); return result; } private void SetupDungeonFloor() { CurrentFloor.InitializeDungeon(); var transform = GetPlayerSpawnPosition(); SpawnPointCreated?.Invoke(transform); } }