using Godot; using System; using System.Linq; using System.Threading.Tasks; using Cirno.Scripts; using Cirno.Scripts.Components.FSM; using Cirno.Scripts.Controllers; using Cirno.Scripts.Enums; using Cirno.Scripts.Misc; using Cirno.Scripts.Resources; using Godot.Collections; using Cirno.Scripts.Utils; using Environment = Godot.Environment; public partial class GameManager : Node2D { public static GameManager Instance { get; private set; } private Hud _hud; private PlayerFSMProxy _player; public PlayerStateMachine Player => _player.PlayerFSM; private Node2D _cameraTarget; public Vector2? PlayerPosition => _player?.GlobalPosition ?? null; public Vector2? PlayerVelocity => _player?.Velocity ?? null; [Export] public MapResource MapResource { get; private set; } [Export] public PackedScene PlayerTemplate { get; set; } [Export] public Dictionary SpawnMarkers { get; private set; } = new(); //[Export] public Marker2D PlayerSpawnMarker { get; set; } private InventoryManager _inventoryManager { get; set; } //private AlarmManager _alarmManager { get; set; } //public InventoryManager Inventory => _inventoryManager; //public AlarmManager AlarmManager => _alarmManager; [Export] public StringName PauseActionName { get; private set; } = "pause"; [Export] public TilemapAvoidance NavigationTilemap { get; private set; } private Node2D _bulletsContainer; public Node2D BulletsContainer => _bulletsContainer; [Signal] public delegate void PlayerRespawnedEventHandler(); public Vector2 LastCheckpointPosition { get; set; } private AudioManager _audioManager; [Export] public Node2D PlayerParentNode { get; set; } [Export] public int EggStartIndex = 0; [Export] public NavigationRegion2D NavigationRegion { get; private set; } [Signal] public delegate void ManagerReadyEventHandler(); // Called when the node enters the scene tree for the first time. public override void _Ready() { Instance = this; var gsm = new GameStateManager(); gsm.ProcessMode = ProcessModeEnum.Always; this.AddChild(gsm); gsm.Init(GameState.Playing); RenderingServer.SetDefaultClearColor(Colors.Black); if (GlobalState.Instance.SessionSettings.GameMode is GameMode.Roguelite) { if (GlobalState.Instance.SessionSettings.LevelNumber < 0) { // TODO: Change based on which level we're going to GlobalState.Instance.SessionSettings.LevelNumber = 0; } } else { GlobalState.Session.LevelNumber = MapResource.LevelId; } GlobalState.Instance.ChangeCursor(false); if (GlobalState.Instance.SessionSettings.AllowSaving) { GlobalState.Instance.SaveGame(); } _audioManager = new AudioManager(); this.AddChild(_audioManager); _hud = GetNodeOrNull("HUD"); if (_hud == null) GD.Print("No HUD in scene."); _cameraTarget = GetNodeOrNull("CameraTarget"); if (_cameraTarget == null) GD.Print("No camera target in scene."); _inventoryManager = GetNodeOrNull("InventoryManager"); if (_inventoryManager == null) GD.Print("No inventory manager in scene."); //_alarmManager = GetNode("AlarmManager"); SpawnBulletsContainer(); if (_hud != null) { GameStateManager.Instance.GameStateChange += _hud.OnGameStateChanged; } if (_inventoryManager != null && _hud != null) { //_inventoryManager.ItemAdded += (item, currentAmount) => _hud.AddInventoryItem(item, currentAmount); //_inventoryManager.ItemRemoved += (item, currentAmount) => _hud.RemoveInventoryItem(item, currentAmount); _inventoryManager.WeaponUpdate += key => _hud.EquipWeapon(key); } PlayerRespawned += OnPlayerRespawned; //_ = DelayPlayerSpawn(); CallDeferred(MethodName.DelayPlayerSpawn); CallDeferred(MethodName.OnFinished); } private void OnFinished() { EmitSignalManagerReady(); } private void OnPlayerRespawned() { this.ClearBullets(); } public void ApplyMapStartData(MapStartDataResource mapStartData) { EggStartIndex = mapStartData.EggIndex; //MapStartData = mapStartData; // StartingEquipment.AddRange(mapStartData.StartingEquipment); } public void AddMotivation(float motivation) { Player.AddMotivation(motivation); } public void ApplySessionState(SessionSettings settings) { //_inventoryManager.Load(settings.Items); } private void DelayPlayerSpawn() { if (SpawnMarkers.Any()) { SpawnPlayer(); } else { GD.Print("No player spawn marker in scene."); return; } if (_player != null && _hud != null) { // _player.HealthChanged += (newHealth, maxHealth) => _hud.UpdateHealth(newHealth, maxHealth); // // _player.ShieldChanged += (newShield, maxShield) => _hud.UpdateShield(newShield, maxShield); // // _player.InteractableAreaEntered += (interactable) => _hud.UpdateInteractable(interactable); // // _player.Death += () => // { // // Show Game Over // _hud.ShowGameOver(); // }; } else { GD.Print("No player and hud in scene"); return; } // Wait before the player is fully initialized before spawning weapons on it CallDeferred(MethodName.SpawnWeapons); } public void SpawnPlayer() { if (_player != null) return; //_player = this.CreateChild(PlayerTemplate, PlayerSpawnMarker.Position ); _player = PlayerTemplate.Instantiate(); //this.CallDeferred("add_child", _player); if (PlayerParentNode is not null) { PlayerParentNode.AddChild(_player); _player.Owner = PlayerParentNode; } else { this.AddChild(_player); _player.Owner = this; } _player.Transform = this.GlobalTransform; _player.GlobalPosition = GetStartPosition(); LastCheckpointPosition = _player.GlobalPosition; //_player.GlobalPosition = PlayerSpawnMarker.Position; CameraTargetPlayer(); // // if (_cameraTarget != null) // { // _cameraTarget.Reparent(_player, true); // _cameraTarget.GlobalPosition = _player.Position; // } } private Vector2 GetStartPosition() { if (MapResource != null) { if (SpawnMarkers.TryGetValue(EggStartIndex, out var spawnMarker)) { var marker = GetNode(spawnMarker); return marker.Position; // Why position and not globalposition? I have no idea } } var m = GetNode(SpawnMarkers.First().Value); return m.GlobalPosition; } public void CameraTargetPlayer() { if (_player is null) return; CameraTargetObject(_player); } public void CameraTargetObject(Node2D target, Vector2? offset = null) { if (_cameraTarget is null) return; _cameraTarget.Reparent(target, true); _cameraTarget.GlobalPosition = target.GlobalPosition; if (offset.HasValue) { _cameraTarget.Position += offset.Value; } } private void SpawnWeapons() { foreach (var startingItem in MapResource.StartData.StartingEquipment) { _inventoryManager.AddItem(startingItem); } foreach (var item in MapResource.StartData.RemoveEquipment) { _inventoryManager.RemoveItem(item); } } private void SpawnBulletsContainer() { _bulletsContainer = new Node2D(); _bulletsContainer.Name = "BulletsContainer"; _bulletsContainer.ProcessMode = ProcessModeEnum.Pausable; AddChild(_bulletsContainer); } // public void TogglePause() // { // if (GameState == GameState.Paused) // { // Unpause(); // } // else if (GameState == GameState.Playing) // { // Pause(); // } // } private void DelayedUnpause() { GetTree().SetPause(false); } public void ClearBullets() { PoolingManager.Instance.DisableAllBullets(); // if (_bulletsContainer is null) return; // foreach (var node in _bulletsContainer.GetChildren()) // { // node.QueueFree(); // } } public void RecalculateTilemap(Vector2 position) { //CallDeferred(MethodName.RecalculateTilemapDeferred, position); } private void RecalculateTilemapDeferred(Vector2 position) { //NavigationTilemap.Recalculate(position); GD.Print("Rebaking tilemap"); NavigationRegion.BakeNavigationPolygon(true); } public void RebakeNavigation() { GD.Print("Rebaking tilemap"); //NavigationRegion.BakeNavigationPolygon(true); } }