Newer
Older
TheVengeance-Project-IADE-Unity2D / Assets / Scripts / NPC / NPCManager.cs
using MyCollections.Managers;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.Tilemaps;

public class NPCManager : MonoBehaviour
{
    [SerializeField] private List<NPCController> npcList = new List<NPCController>();
    [SerializeField] private UIHandler uiHandler;
    [SerializeField] private DialogueManager dialogueManager;
    [SerializeField] private WorldUIObserver worldUIHandler;

    public Tilemap tilemap;
    public TilemapCollider2D tilemapCollider; // Attach this to the tilemap with collider

    private BoundsInt bounds;
    private List<Vector3Int> allTilePositions = new List<Vector3Int>();
    [SerializeField] private List<Vector2> waypoints = new List<Vector2>();
    [SerializeField] private uint waypointsNumber = 20;
    [SerializeField] private float warnRadius = 5f;
    [SerializeField] private LayerMask targetLayerMask;

    private CombatState combatstate;
    private GameStateManager gameStateManager;
    private Action<GameObject, NPCController> onTargetSpoted;

    public CombatState CombatState
    {
        get { return combatstate; }
        set { combatstate = value; }
    }

    //Properties
    public UIHandler UIhandler => uiHandler;
    public DialogueManager DialogueManager => dialogueManager;
    public WorldUIObserver WorldUIHandler => worldUIHandler;
    public Action<GameObject, NPCController> OnTargetSpoted => onTargetSpoted;

    private void Awake()
    {

    }

    // Start is called before the first frame update
    void Start()
    {
        gameStateManager = GameStateManager.Instance;

        foreach (NPCController npc in npcList)
        {
            npc.AddObserver(uiHandler);

            if (npc is InteractableNPC)
            {
                npc.AddObserver(dialogueManager);
            }

            npc.AddObserver(worldUIHandler);
        }

        onTargetSpoted += SetCombatState;

        GetAllTilePositions();
        GenerateRandomPositions(waypointsNumber);
    }



    //When an enemy NPC detects the player it will create a combat state
    //If a state already exists the npc's notified by other npc's or spoted the target
    //Each group (NPC manager) has it's own Combat State

    public void SetCombatState(GameObject target, NPCController intervenient)
    {
        if (combatstate == null)
        {
            //Create a combat state if it doesn't exists one
            combatstate = new CombatState(target, intervenient);

            //Add to the manager
            gameStateManager.AddCombatState(combatstate);

            return;
        }

        //Adds the NPC to the current combat State
        combatstate.AddIntervenient(intervenient);
    }

    private void GetAllTilePositions()
    {
        // Get all tile positions
        bounds = tilemap.cellBounds;
        allTilePositions = new List<Vector3Int>();

        for (int x = bounds.xMin; x < bounds.xMax; x++)
        {
            for (int y = bounds.yMin; y < bounds.yMax; y++)
            {
                Vector3Int tilePos = new Vector3Int(x, y, 0);
                if (tilemap.HasTile(tilePos))
                {
                    allTilePositions.Add(tilePos); // Add valid tile positions
                }
            }
        }
    }

    private void GenerateRandomPositions(uint amount)
    {
        // Get a random index from the tile positions
        if (allTilePositions.Count > 0)
        {
            for (int i = 0; i < amount; i++)
            {
                int randomIndex = UnityEngine.Random.Range(0, allTilePositions.Count);
                Vector3Int randomTilePos = allTilePositions[randomIndex];
                //Debug.Log($"Random Tile Position: {randomTilePos}");

                // Get the corresponding world position if needed
                Vector3 worldPos = tilemap.CellToWorld(randomTilePos);
                //Debug.Log($"World Position of Random Tile: {worldPos}");
                waypoints.Add(worldPos);
            }
        }
        else
        {
            Debug.LogWarning("No tiles found in the tilemap!");
        }
    }

    // Update is called once per frame
    void Update()
    {

    }

    public void RequestPosition(Agent agent)
    {
        int randomIndex = UnityEngine.Random.Range(0, waypoints.Count);
        Vector2 newPosition = waypoints[randomIndex];
        agent.SetDestination(newPosition);
    }

    private void OnEnable()
    {
        foreach (NPCController npc in npcList)
        {
            npc.gameObject.SetActive(true);
        }
    }

    private IEnumerator ActivateNPCsAfterDelay()
    {
        // Wait until 1 second has passed since the level loaded
        while (Time.timeSinceLevelLoad < 5f)
        {
            yield return null; // Wait for the next frame
        }

        // Once 1 second has passed, activate the NPCs
        foreach (NPCController npc in npcList)
        {
            npc.gameObject.SetActive(true);
        }
    }

    void OnDisable()
    {
        foreach (NPCController npc in npcList)
        {
            npc.gameObject.SetActive(false);
        }
    }
}