using Chickensoft.AutoInject; using Chickensoft.Collections; using Chickensoft.Introspection; using Godot; using System; using System.Linq; using System.Threading.Tasks; using Zennysoft.Game.Abstractions; 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; private string _sceneName; public void OnResolved() { AnimationPlayer.AnimationFinished += AnimationPlayer_AnimationFinished; this.Provide(); } private async void AnimationPlayer_AnimationFinished(StringName animName) { if (animName == "fade_out") { await LoadNewFloor(); FloorLoaded?.Invoke(); } } private async Task LoadNewFloor() { SpawnPointCreated?.Invoke((Vector3.Forward, new Vector3(-999, -999, -999))); var newFloor = await LoadNewFloor(_sceneName); ClearFloor(); AddChild(newFloor); InitializeFloor(newFloor); var floor = MapOrder.GetChildren().OfType().ElementAt(CurrentFloorNumber.Value); if (CurrentFloor is DungeonFloor dungeonFloor && floor is DungeonFloorNode dungeonFloorNode) dungeonFloor.SpawnEnemies(dungeonFloorNode); } public void FadeIn() => AnimationPlayer.Play("fade_in"); public void FadeOut() => AnimationPlayer.Play("fade_out"); 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 void ClearFloor() { CurrentFloor?.CallDeferred(MethodName.QueueFree, []); } 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) { CallDeferred(MethodName.FadeOut); _sceneName = sceneName; var dimmableAudio = GetTree().GetNodesInGroup("DimmableAudio").OfType(); foreach (var node in dimmableAudio) node.FadeOut(); } private void InitializeFloor(Node newFloor) { CurrentFloor = (IDungeonFloor)newFloor; SetupDungeonFloor(); CurrentFloor.FloorIsLoaded = true; CurrentFloorNumber.OnNext(CurrentFloorNumber.Value + 1); } 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); } }