| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485 |
- using UnityEngine;
- using System.Collections.Generic;
- using System.Linq;
- public class FacilityManager : MonoBehaviour
- {
- public static FacilityManager Instance { get; private set; }
- [Header("Available Facilities")]
- [SerializeField] private List<Facility> hotelFacilities = new List<Facility>();
- [Header("Facility Prefabs")]
- [SerializeField] private GameObject restaurantPrefab;
- [SerializeField] private GameObject barPrefab;
- [SerializeField] private GameObject gymPrefab;
- [SerializeField] private GameObject playAreaPrefab;
- [SerializeField] private GameObject valetStationPrefab;
- // Events
- public System.Action<Facility> OnFacilityAdded;
- public System.Action<Facility> OnFacilityRemoved;
- public System.Action<Guest, Facility> OnFacilityUsed;
- private void Awake()
- {
- if (Instance != null && Instance != this)
- {
- Destroy(this.gameObject);
- return;
- }
- Instance = this;
- }
- private void Start()
- {
- InitializeFacilities();
- }
- #region Initialization
- private void InitializeFacilities()
- {
- // Find existing facilities in the scene
- Facility[] existingFacilities = FindObjectsOfType<Facility>();
- foreach (Facility facility in existingFacilities)
- {
- if (!hotelFacilities.Contains(facility))
- {
- hotelFacilities.Add(facility);
- }
- }
- Debug.Log($"Initialized with {hotelFacilities.Count} facilities");
- }
- #endregion
- #region Facility Management
- public bool AddFacility(FacilityType facilityType, Vector3 position, Room associatedRoom = null)
- {
- GameObject facilityPrefab = GetFacilityPrefab(facilityType);
- if (facilityPrefab == null)
- {
- facilityPrefab = CreateDefaultFacilityPrefab(facilityType);
- }
- GameObject facilityObj = Instantiate(facilityPrefab, position, Quaternion.identity);
- Facility facility = facilityObj.GetComponent<Facility>();
- if (facility == null)
- {
- facility = facilityObj.AddComponent<Facility>();
- }
- // Configure facility
- facility.Initialize(facilityType, associatedRoom);
- hotelFacilities.Add(facility);
- OnFacilityAdded?.Invoke(facility);
- Debug.Log($"Added facility: {facilityType} at {position}");
- return true;
- }
- public bool RemoveFacility(Facility facility)
- {
- if (facility == null || !hotelFacilities.Contains(facility))
- {
- return false;
- }
- hotelFacilities.Remove(facility);
- OnFacilityRemoved?.Invoke(facility);
- Destroy(facility.gameObject);
- Debug.Log($"Removed facility: {facility.Type}");
- return true;
- }
- private GameObject GetFacilityPrefab(FacilityType facilityType)
- {
- switch (facilityType)
- {
- case FacilityType.Restaurant:
- return restaurantPrefab;
- case FacilityType.Bar:
- return barPrefab;
- case FacilityType.Gym:
- return gymPrefab;
- case FacilityType.PlayArea:
- return playAreaPrefab;
- case FacilityType.ValetParking:
- return valetStationPrefab;
- default:
- return null;
- }
- }
- private GameObject CreateDefaultFacilityPrefab(FacilityType facilityType)
- {
- GameObject facility = GameObject.CreatePrimitive(PrimitiveType.Cube);
- facility.name = facilityType.ToString();
- facility.transform.localScale = new Vector3(2f, 1f, 2f);
- // Set color based on facility type
- Color facilityColor = GetFacilityColor(facilityType);
- facility.GetComponent<Renderer>().material.color = facilityColor;
- return facility;
- }
- private Color GetFacilityColor(FacilityType facilityType)
- {
- switch (facilityType)
- {
- case FacilityType.Restaurant: return Color.red;
- case FacilityType.Bar: return new Color(0.5f, 0.2f, 0f); // Brown
- case FacilityType.Gym: return Color.yellow;
- case FacilityType.PlayArea: return Color.green;
- case FacilityType.ValetParking: return Color.blue;
- case FacilityType.Spa: return Color.magenta;
- case FacilityType.BusinessCenter: return Color.gray;
- case FacilityType.LaundryService: return Color.white;
- default: return Color.gray;
- }
- }
- #endregion
- #region Facility Queries
- public List<Facility> GetFacilitiesByType(FacilityType facilityType)
- {
- return hotelFacilities.Where(f => f.Type == facilityType).ToList();
- }
- public List<Facility> GetAvailableFacilities()
- {
- return hotelFacilities.Where(f => f.IsOperational).ToList();
- }
- public Facility GetNearestFacility(Vector3 position, FacilityType facilityType)
- {
- var facilitiesOfType = GetFacilitiesByType(facilityType);
- return facilitiesOfType
- .Where(f => f.IsOperational)
- .OrderBy(f => Vector3.Distance(f.transform.position, position))
- .FirstOrDefault();
- }
- public bool HasFacility(FacilityType facilityType)
- {
- return GetFacilitiesByType(facilityType).Any(f => f.IsOperational);
- }
- public float GetFacilitySatisfactionRating(FacilityType facilityType)
- {
- var facilities = GetFacilitiesByType(facilityType);
- if (facilities.Count == 0) return 0f;
- return facilities.Average(f => f.QualityRating);
- }
- #endregion
- #region Wish Fulfillment
- public bool CanFulfillWish(WishType wishType)
- {
- FacilityType requiredFacility = GetRequiredFacilityForWish(wishType);
- return HasFacility(requiredFacility);
- }
- public Facility FindFacilityForWish(WishType wishType, Vector3 guestPosition)
- {
- FacilityType requiredFacility = GetRequiredFacilityForWish(wishType);
- return GetNearestFacility(guestPosition, requiredFacility);
- }
- private FacilityType GetRequiredFacilityForWish(WishType wishType)
- {
- switch (wishType)
- {
- case WishType.Restaurant:
- return FacilityType.Restaurant;
- case WishType.BarService:
- return FacilityType.Bar;
- case WishType.PlayArea:
- return FacilityType.PlayArea;
- case WishType.ValetParking:
- return FacilityType.ValetParking;
- case WishType.WashingService:
- case WishType.CleaningService:
- return FacilityType.LaundryService;
- case WishType.ActivityPlanning:
- return FacilityType.BusinessCenter;
- case WishType.RoomService:
- return FacilityType.Restaurant; // Room service originates from restaurant
- default:
- return FacilityType.None;
- }
- }
- public float CalculateWishFulfillmentBonus(Guest guest)
- {
- if (guest?.Wishes == null) return 0f;
- float totalBonus = 0f;
- int fulfilledWishes = 0;
- foreach (var wish in guest.Wishes)
- {
- if (CanFulfillWish(wish.wishType))
- {
- totalBonus += wish.importance;
- fulfilledWishes++;
- }
- }
- // Bonus scales with the percentage of wishes that can be fulfilled
- float fulfillmentRate = guest.Wishes.Count > 0 ? (float)fulfilledWishes / guest.Wishes.Count : 0f;
- return totalBonus * fulfillmentRate;
- }
- #endregion
- #region Statistics and Information
- public List<Facility> GetAllFacilities()
- {
- return new List<Facility>(hotelFacilities);
- }
- public int GetFacilityCount(FacilityType facilityType)
- {
- return GetFacilitiesByType(facilityType).Count;
- }
- public Dictionary<FacilityType, int> GetFacilityCountByType()
- {
- Dictionary<FacilityType, int> counts = new Dictionary<FacilityType, int>();
- foreach (FacilityType type in System.Enum.GetValues(typeof(FacilityType)))
- {
- counts[type] = GetFacilityCount(type);
- }
- return counts;
- }
- public float GetOverallFacilityRating()
- {
- if (hotelFacilities.Count == 0) return 0f;
- return hotelFacilities.Average(f => f.QualityRating);
- }
- #endregion
- }
- // Facility Component
- public class Facility : MonoBehaviour
- {
- [Header("Facility Info")]
- [SerializeField] private FacilityType facilityType = FacilityType.None;
- [SerializeField] private string facilityName;
- [SerializeField] private bool isOperational = true;
- [Header("Quality and Capacity")]
- [SerializeField] private float qualityRating = 0.7f; // 0 to 1
- [SerializeField] private int maxCapacity = 10;
- [SerializeField] private List<Guest> currentUsers = new List<Guest>();
- [Header("Associated Room")]
- [SerializeField] private Room associatedRoom;
- [Header("Staff Requirements")]
- [SerializeField] private List<Staff.StaffType> requiredStaffTypes = new List<Staff.StaffType>();
- [SerializeField] private int minStaffCount = 1;
- // Events
- public System.Action<Guest> OnGuestUseFacility;
- public System.Action<Guest> OnGuestLeaveFacility;
- #region Properties
- public FacilityType Type => facilityType;
- public string FacilityName => string.IsNullOrEmpty(facilityName) ? facilityType.ToString() : facilityName;
- public bool IsOperational => isOperational && HasRequiredStaff();
- public float QualityRating => qualityRating;
- public int CurrentCapacity => currentUsers.Count;
- public int MaxCapacity => maxCapacity;
- public bool HasCapacity => CurrentCapacity < MaxCapacity;
- public Room AssociatedRoom => associatedRoom;
- #endregion
- public void Initialize(FacilityType type, Room room = null)
- {
- facilityType = type;
- associatedRoom = room;
- SetupFacilityDefaults();
- Debug.Log($"Initialized facility: {FacilityName}");
- }
- private void SetupFacilityDefaults()
- {
- switch (facilityType)
- {
- case FacilityType.Restaurant:
- maxCapacity = 20;
- requiredStaffTypes.Add(Staff.StaffType.Chef);
- break;
- case FacilityType.Bar:
- maxCapacity = 15;
- requiredStaffTypes.Add(Staff.StaffType.Chef); // Bartender would be ideal, but using chef for now
- break;
- case FacilityType.PlayArea:
- maxCapacity = 30;
- break;
- case FacilityType.ValetParking:
- maxCapacity = 50;
- requiredStaffTypes.Add(Staff.StaffType.Valet);
- break;
- case FacilityType.LaundryService:
- maxCapacity = 5;
- requiredStaffTypes.Add(Staff.StaffType.Housekeeper);
- break;
- }
- }
- #region Guest Interaction
- public bool CanGuestUseFacility(Guest guest)
- {
- if (!IsOperational || !HasCapacity)
- return false;
- // Check if guest has specific requirements for this facility
- return true;
- }
- public bool AddGuest(Guest guest)
- {
- if (!CanGuestUseFacility(guest))
- return false;
- currentUsers.Add(guest);
- OnGuestUseFacility?.Invoke(guest);
- Debug.Log($"Guest {guest.GuestName} is now using {FacilityName}");
- return true;
- }
- public bool RemoveGuest(Guest guest)
- {
- if (!currentUsers.Contains(guest))
- return false;
- currentUsers.Remove(guest);
- OnGuestLeaveFacility?.Invoke(guest);
- Debug.Log($"Guest {guest.GuestName} has left {FacilityName}");
- return true;
- }
- #endregion
- #region Staff Management
- private bool HasRequiredStaff()
- {
- if (requiredStaffTypes.Count == 0)
- return true;
- if (StaffManager.Instance == null)
- return false;
- foreach (var staffType in requiredStaffTypes)
- {
- if (StaffManager.Instance.GetStaffCount(staffType) < minStaffCount)
- return false;
- }
- return true;
- }
- public List<Staff.StaffType> GetRequiredStaffTypes()
- {
- return new List<Staff.StaffType>(requiredStaffTypes);
- }
- #endregion
- #region Facility Management
- public void SetOperational(bool operational)
- {
- isOperational = operational;
- if (!operational)
- {
- // Remove all current users
- var usersToRemove = new List<Guest>(currentUsers);
- foreach (var guest in usersToRemove)
- {
- RemoveGuest(guest);
- }
- }
- Debug.Log($"{FacilityName} is now {(operational ? "operational" : "closed")}");
- }
- public void UpgradeQuality(float qualityIncrease)
- {
- qualityRating = Mathf.Clamp01(qualityRating + qualityIncrease);
- Debug.Log($"{FacilityName} quality upgraded to {qualityRating:P0}");
- }
- public void IncreaseCapacity(int capacityIncrease)
- {
- maxCapacity += capacityIncrease;
- Debug.Log($"{FacilityName} capacity increased to {maxCapacity}");
- }
- #endregion
- private void OnMouseDown()
- {
- // Show facility info when clicked
- Debug.Log($"Facility: {FacilityName}\nType: {facilityType}\nOperational: {IsOperational}\nCapacity: {CurrentCapacity}/{MaxCapacity}\nQuality: {qualityRating:P0}");
- }
- private void OnDrawGizmosSelected()
- {
- // Draw facility area
- Gizmos.color = GetFacilityColor();
- Gizmos.DrawWireCube(transform.position, transform.localScale);
- // Draw capacity indicator
- Gizmos.color = Color.white;
- for (int i = 0; i < CurrentCapacity && i < 10; i++)
- {
- Vector3 userPos = transform.position + Vector3.up * (i * 0.5f + 1f);
- Gizmos.DrawWireSphere(userPos, 0.2f);
- }
- }
- private Color GetFacilityColor()
- {
- if (!IsOperational) return Color.gray;
- switch (facilityType)
- {
- case FacilityType.Restaurant: return Color.red;
- case FacilityType.Bar: return new Color(0.5f, 0.2f, 0f);
- case FacilityType.PlayArea: return Color.green;
- case FacilityType.ValetParking: return Color.blue;
- default: return Color.yellow;
- }
- }
- }
- // Enumerations
- public enum FacilityType
- {
- None,
- Restaurant,
- Bar,
- Gym,
- PlayArea,
- ValetParking,
- Spa,
- BusinessCenter,
- LaundryService,
- Pool,
- ConferenceRoom
- }
|