using UnityEngine; using System.Collections.Generic; using System.Collections; public class HotelManager : MonoBehaviour { public static HotelManager Instance { get; private set; } [Header("Hotel Settings")] [SerializeField] private int maxGuestsPerDay = 20; [SerializeField] private float guestArrivalInterval = 30f; // seconds [SerializeField] private Transform guestSpawnPoint; [Header("Guest Prefabs")] [SerializeField] private GameObject[] guestPrefabs; [SerializeField] private GameObject defaultGuestPrefab; [Header("Hotel Stats")] [SerializeField] private float hotelRating = 3f; // 1 to 5 stars [SerializeField] private int totalRooms = 0; [SerializeField] private int availableRooms = 0; private List hotelRooms = new List(); private List currentGuests = new List(); private List waitingGuests = new List(); private bool isHotelOpen = false; private int guestsArrivedToday = 0; private float timeUntilNextGuest = 0f; // Events public System.Action OnGuestArrived; public System.Action OnGuestLeft; public System.Action OnGuestAssignedRoom; public System.Action OnRoomAdded; private void Awake() { if (Instance != null && Instance != this) { Destroy(this.gameObject); return; } Instance = this; } private void Start() { SubscribeToEvents(); SetupSpawnPoint(); // Wait for hotel to open before spawning guests if (GameManager.Instance != null) { GameManager.OnHotelOpened += OnHotelOpened; } } private void OnDestroy() { UnsubscribeFromEvents(); } private void Update() { if (isHotelOpen) { HandleGuestArrivals(); UpdateHotelStats(); } } #region Hotel Operations private void OnHotelOpened() { isHotelOpen = true; Debug.Log("Hotel is now open! Guests will start arriving."); // Start spawning guests timeUntilNextGuest = guestArrivalInterval; } private void HandleGuestArrivals() { if (!isHotelOpen) return; timeUntilNextGuest -= Time.deltaTime; if (timeUntilNextGuest <= 0 && guestsArrivedToday < maxGuestsPerDay) { SpawnGuest(); // Calculate next arrival time (with some randomness) float randomFactor = UnityEngine.Random.Range(0.5f, 1.5f); timeUntilNextGuest = guestArrivalInterval * randomFactor; // Adjust based on hotel rating (higher rating = more guests) timeUntilNextGuest /= (hotelRating / 3f); } } private void SpawnGuest() { if (guestSpawnPoint == null) { Debug.LogWarning("No guest spawn point set!"); return; } // Choose guest type based on hotel rating Guest.GuestType guestType = ChooseGuestType(); GameObject guestPrefab = ChooseGuestPrefab(guestType); if (guestPrefab == null) { Debug.LogWarning("No guest prefab available!"); return; } GameObject guestObj = Instantiate(guestPrefab, guestSpawnPoint.position, guestSpawnPoint.rotation); Guest guest = guestObj.GetComponent(); if (guest == null) { guest = guestObj.AddComponent(); } // Set guest properties guest.GuestName = GenerateGuestName(); // Set guest type based on hotel rating SetGuestType(guest, guestType); guestsArrivedToday++; Debug.Log($"Guest {guest.GuestName} ({guestType}) has arrived!"); } private Guest.GuestType ChooseGuestType() { // Higher rated hotels get more high-profile guests float rand = UnityEngine.Random.value; if (hotelRating >= 4.5f && rand < 0.1f) return Guest.GuestType.Celebrity; else if (hotelRating >= 4f && rand < 0.2f) return Guest.GuestType.VIP; else if (rand < 0.3f) return Guest.GuestType.Business; else if (rand < 0.5f) return Guest.GuestType.Family; else return Guest.GuestType.Regular; } private GameObject ChooseGuestPrefab(Guest.GuestType guestType) { // For now, use default prefab. Later can be expanded for specific types if (defaultGuestPrefab != null) return defaultGuestPrefab; if (guestPrefabs != null && guestPrefabs.Length > 0) return guestPrefabs[UnityEngine.Random.Range(0, guestPrefabs.Length)]; return CreateDefaultGuestPrefab(); } private GameObject CreateDefaultGuestPrefab() { // Create a simple guest prefab if none is provided GameObject guest = GameObject.CreatePrimitive(PrimitiveType.Capsule); guest.name = "Guest"; // Add NavMeshAgent guest.AddComponent(); // Add Guest script guest.AddComponent(); // Set color guest.GetComponent().material.color = Color.blue; return guest; } private void SetGuestType(Guest guest, Guest.GuestType guestType) { // This would be expanded to set specific properties based on type // For now, just log the type Debug.Log($"Setting guest type to: {guestType}"); } private string GenerateGuestName() { string[] firstNames = { "Alex", "Jamie", "Casey", "Jordan", "Riley", "Morgan", "Quinn", "Blake", "Drew", "Sage" }; string[] lastNames = { "Parker", "Reed", "Blake", "Gray", "Stone", "Fox", "Lane", "Cross", "Vale", "Knox" }; return $"{firstNames[UnityEngine.Random.Range(0, firstNames.Length)]} {lastNames[UnityEngine.Random.Range(0, lastNames.Length)]}"; } #endregion #region Room Management public void AddRoom(Room room) { if (room != null) { hotelRooms.Add(room); totalRooms++; availableRooms++; OnRoomAdded?.Invoke(room); UpdateHotelStats(); Debug.Log($"Room added. Total rooms: {totalRooms}, Available: {availableRooms}"); } } public Room GetAvailableRoom(Guest guest) { // Find an available room that matches guest preferences foreach (Room room in hotelRooms) { if (room.isComplete && !room.IsOccupied()) { // For now, assign any available room // Later can be expanded to match guest preferences room.SetOccupied(true, guest); availableRooms--; Debug.Log($"Assigned room to {guest.GuestName}"); return room; } } Debug.Log($"No available rooms for {guest.GuestName}"); return null; } public void ReleaseRoom(Room room) { if (room != null && room.IsOccupied()) { room.SetOccupied(false); availableRooms++; Debug.Log($"Room released. Available rooms: {availableRooms}"); } } public List GetAllRooms() { return new List(hotelRooms); } public int GetAvailableRoomCount() { return availableRooms; } #endregion #region Guest Management private void SubscribeToEvents() { Guest.OnGuestArrived += OnGuestArrivedHandler; Guest.OnGuestLeft += OnGuestLeftHandler; Guest.OnGuestAssignedRoom += OnGuestAssignedRoomHandler; } private void UnsubscribeFromEvents() { Guest.OnGuestArrived -= OnGuestArrivedHandler; Guest.OnGuestLeft -= OnGuestLeftHandler; Guest.OnGuestAssignedRoom -= OnGuestAssignedRoomHandler; } private void OnGuestArrivedHandler(Guest guest) { currentGuests.Add(guest); OnGuestArrived?.Invoke(guest); Debug.Log($"Hotel Manager: {guest.GuestName} has arrived. Current guests: {currentGuests.Count}"); } private void OnGuestLeftHandler(Guest guest) { currentGuests.Remove(guest); waitingGuests.Remove(guest); // Release room if guest had one if (guest.AssignedRoom != null) { ReleaseRoom(guest.AssignedRoom); } OnGuestLeft?.Invoke(guest); Debug.Log($"Hotel Manager: {guest.GuestName} has left. Current guests: {currentGuests.Count}"); } private void OnGuestAssignedRoomHandler(Guest guest) { waitingGuests.Remove(guest); OnGuestAssignedRoom?.Invoke(guest); Debug.Log($"Hotel Manager: {guest.GuestName} has been assigned a room"); } public List GetCurrentGuests() { return new List(currentGuests); } public List GetWaitingGuests() { return new List(waitingGuests); } #endregion #region Hotel Statistics private void UpdateHotelStats() { // Calculate hotel rating based on guest satisfaction if (currentGuests.Count > 0) { float totalSatisfaction = 0f; int guestsWithFeedback = 0; foreach (Guest guest in currentGuests) { if (guest.AssignedRoom != null) // Only count guests who have checked in { totalSatisfaction += guest.SatisfactionLevel; guestsWithFeedback++; } } if (guestsWithFeedback > 0) { float averageSatisfaction = totalSatisfaction / guestsWithFeedback; // Slowly adjust hotel rating based on satisfaction float targetRating = 1f + (averageSatisfaction * 4f); // Convert 0-1 to 1-5 scale hotelRating = Mathf.Lerp(hotelRating, targetRating, Time.deltaTime * 0.1f); hotelRating = Mathf.Clamp(hotelRating, 1f, 5f); } } } public float GetHotelRating() { return hotelRating; } public int GetTotalGuests() { return currentGuests.Count; } public float GetOccupancyRate() { if (totalRooms == 0) return 0f; return (float)(totalRooms - availableRooms) / totalRooms; } #endregion #region Utility Methods private void SetupSpawnPoint() { if (guestSpawnPoint == null) { // Create a default spawn point GameObject spawnObj = new GameObject("Guest Spawn Point"); spawnObj.transform.position = new Vector3(0, 0, -15f); // Outside the initial room guestSpawnPoint = spawnObj.transform; spawnObj.transform.SetParent(this.transform); } } public bool IsHotelOpen() { return isHotelOpen; } private void OnDrawGizmosSelected() { if (guestSpawnPoint != null) { Gizmos.color = Color.green; Gizmos.DrawWireSphere(guestSpawnPoint.position, 1f); Gizmos.DrawWireCube(guestSpawnPoint.position + Vector3.up, Vector3.one * 0.5f); } } #endregion } // Extension methods for Room class public static class RoomExtensions { private static Dictionary roomOccupancy = new Dictionary(); public static bool IsOccupied(this Room room) { return roomOccupancy.ContainsKey(room) && roomOccupancy[room] != null; } public static void SetOccupied(this Room room, bool occupied, Guest guest = null) { if (occupied && guest != null) { roomOccupancy[room] = guest; } else { roomOccupancy.Remove(room); } } public static Guest GetOccupant(this Room room) { return roomOccupancy.ContainsKey(room) ? roomOccupancy[room] : null; } }