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<(Vector3 Rotation, Vector3 Position)> 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 (Vector3 Rotation, Vector3 Position) GetPlayerSpawnPosition() { var spawnPoint = CurrentFloor.GetPlayerSpawnPoint(); return (spawnPoint.Rotation, spawnPoint.Position); } 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); 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((Vector3.Forward, 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); } }