240 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			240 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| using System;
 | |
| using System.Collections.Generic;
 | |
| using Fusion;
 | |
| using UnityEngine;
 | |
| 
 | |
| namespace TPSBR
 | |
| {
 | |
| 	public class AnnouncerContext
 | |
| 	{
 | |
| 		public NetworkRunner Runner;
 | |
| 		public GameplayMode GameplayMode;
 | |
| 
 | |
| 		public int ActivePlayers;
 | |
| 		public int BestScore;
 | |
| 		public PlayerStatistics PlayerStatistics;
 | |
| 	}
 | |
| 
 | |
| 	public class Announcer : SceneService
 | |
| 	{
 | |
| 		// PUBLIC MEMBERS
 | |
| 
 | |
| 		public Action<AnnouncementData> Announce;
 | |
| 
 | |
| 		// PRIVATE MEMBERS
 | |
| 
 | |
| 		[SerializeField]
 | |
| 		private AudioEffect _audio;
 | |
| 
 | |
| 		private AnnouncerContext _context;
 | |
| 		private Announcement[] _announcements;
 | |
| 
 | |
| 		private List<AnnouncementData> _collectedAnnouncements = new List<AnnouncementData>(32);
 | |
| 		private List<AnnouncementData> _waitingAnnouncements   = new List<AnnouncementData>(32);
 | |
| 
 | |
| 		// SceneService INTERFACE
 | |
| 
 | |
| 		protected override void OnTick()
 | |
| 		{
 | |
| 			if (ApplicationSettings.IsStrippedBatch == true)
 | |
| 				return;
 | |
| 
 | |
| 			var gameplayMode = Context.GameplayMode;
 | |
| 			if (gameplayMode == null)
 | |
| 				return;
 | |
| 
 | |
| 			if (Context.Runner == null || Context.Runner.Exists(gameplayMode.Object) == false)
 | |
| 				return;
 | |
| 
 | |
| 			if (gameplayMode.State != GameplayMode.EState.Active)
 | |
| 				return;
 | |
| 
 | |
| 			if (_context == null)
 | |
| 			{
 | |
| 				_context = new AnnouncerContext();
 | |
| 
 | |
| 				_context.Runner = Context.Runner;
 | |
| 				_context.GameplayMode = gameplayMode;
 | |
| 			}
 | |
| 
 | |
| 			PrepareContext();
 | |
| 
 | |
| 			if (_announcements == null)
 | |
| 			{
 | |
| 				var announcementObjects = gameplayMode.Announcements;
 | |
| 				_announcements = new Announcement[announcementObjects.Length];
 | |
| 
 | |
| 				for (int i = 0; i < announcementObjects.Length; i++)
 | |
| 				{
 | |
| 					var announcement = Instantiate(announcementObjects[i]);
 | |
| 					_announcements[i] = announcement;
 | |
| 
 | |
| 					announcement.Activate(_context);
 | |
| 				}
 | |
| 			}
 | |
| 
 | |
| 			UpdateAnnouncements();
 | |
| 		}
 | |
| 
 | |
| 		protected override void OnDeactivate()
 | |
| 		{
 | |
| 			if (_announcements != null)
 | |
| 			{
 | |
| 				for (int i = 0; i < _announcements.Length; i++)
 | |
| 				{
 | |
| 					_announcements[i].Deactivate();
 | |
| 					Destroy(_announcements[i]);
 | |
| 				}
 | |
| 
 | |
| 				_announcements = null;
 | |
| 			}
 | |
| 
 | |
| 			_context = null;
 | |
| 		}
 | |
| 
 | |
| 		protected override void OnDeinitialize()
 | |
| 		{
 | |
| 			Announce = null;
 | |
| 		}
 | |
| 
 | |
| 		// PRIVATE METHODS
 | |
| 
 | |
| 		private void PrepareContext()
 | |
| 		{
 | |
| 			_context.ActivePlayers = 0;
 | |
| 			_context.BestScore = 0;
 | |
| 
 | |
| 			foreach (var player in Context.NetworkGame.ActivePlayers)
 | |
| 			{
 | |
| 				if (player == null)
 | |
| 					continue;
 | |
| 
 | |
| 				var statistics = player.Statistics;
 | |
| 				if (statistics.IsValid == false)
 | |
| 					continue;
 | |
| 				if (statistics.IsEliminated == true)
 | |
| 					continue;
 | |
| 
 | |
| 				if (statistics.Score > _context.BestScore)
 | |
| 				{
 | |
| 					_context.BestScore = statistics.Score;
 | |
| 				}
 | |
| 
 | |
| 				_context.ActivePlayers++;
 | |
| 			}
 | |
| 
 | |
| 			var observedPlayer = Context.NetworkGame.GetPlayer(Context.ObservedPlayerRef);
 | |
| 			_context.PlayerStatistics = observedPlayer != null ? observedPlayer.Statistics : default;
 | |
| 		}
 | |
| 
 | |
| 		private void UpdateAnnouncements()
 | |
| 		{
 | |
| 			float deltaTime = Time.deltaTime;
 | |
| 
 | |
| 			// Collect
 | |
| 			for (int i = 0; i < _announcements.Length; i++)
 | |
| 			{
 | |
| 				Announcement announcement = _announcements[i];
 | |
| 
 | |
| 				if (announcement.IsFinished == true)
 | |
| 					continue;
 | |
| 
 | |
| 				announcement.Tick(_context, _collectedAnnouncements);
 | |
| 			}
 | |
| 
 | |
| 			// Add
 | |
| 			if (_collectedAnnouncements.Count > 0)
 | |
| 			{
 | |
| 				AddAnnouncements(_collectedAnnouncements);
 | |
| 				_collectedAnnouncements.Clear();
 | |
| 			}
 | |
| 
 | |
| 			// Update cooldowns
 | |
| 			for (int i = _waitingAnnouncements.Count - 1; i >= 0; i--)
 | |
| 			{
 | |
| 				AnnouncementData announcement = _waitingAnnouncements[i];
 | |
| 
 | |
| 				if (announcement.Cooldown > 0f)
 | |
| 				{
 | |
| 					announcement.Cooldown -= deltaTime;
 | |
| 					_waitingAnnouncements[i] = announcement;
 | |
| 				}
 | |
| 			}
 | |
| 
 | |
| 			// Try announce
 | |
| 			if (_waitingAnnouncements.Count > 0 && TryAnnounce(_waitingAnnouncements[0]) == true)
 | |
| 			{
 | |
| 				_waitingAnnouncements.RemoveAt(0);
 | |
| 			}
 | |
| 
 | |
| 			// Update validity
 | |
| 			for (int i = _waitingAnnouncements.Count - 1; i >= 0; i--)
 | |
| 			{
 | |
| 				AnnouncementData announcement = _waitingAnnouncements[i];
 | |
| 
 | |
| 				if (announcement.ValidCooldown > 0f)
 | |
| 				{
 | |
| 					announcement.ValidCooldown -= deltaTime;
 | |
| 					_waitingAnnouncements[i] = announcement;
 | |
| 				}
 | |
| 				else
 | |
| 				{
 | |
| 					_waitingAnnouncements.RemoveAt(i);
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		private void AddAnnouncements(List<AnnouncementData> newAnnouncements)
 | |
| 		{
 | |
| 			if (newAnnouncements.Count == 0)
 | |
| 				return;
 | |
| 
 | |
| 			for (int i = 0; i < newAnnouncements.Count; i++)
 | |
| 			{
 | |
| 				AnnouncementData newAnnouncement = newAnnouncements[i];
 | |
| 				newAnnouncement.ValidCooldown = newAnnouncement.ValidTime;
 | |
| 
 | |
| 				bool add = true;
 | |
| 
 | |
| 				for (int j = 0; j < _waitingAnnouncements.Count; j++)
 | |
| 				{
 | |
| 					if (_waitingAnnouncements[j].Channel == newAnnouncement.Channel)
 | |
| 					{
 | |
| 						if (_waitingAnnouncements[j].Priority <= newAnnouncement.Priority)
 | |
| 						{
 | |
| 							_waitingAnnouncements[j] = newAnnouncement;
 | |
| 						}
 | |
| 
 | |
| 						add = false;
 | |
| 					}
 | |
| 				}
 | |
| 
 | |
| 				if (add == true)
 | |
| 				{
 | |
| 					_waitingAnnouncements.Add(newAnnouncement);
 | |
| 				}
 | |
| 			}
 | |
| 
 | |
| 			_waitingAnnouncements.Sort((a, b) => b.Priority.CompareTo(a.Priority));
 | |
| 		}
 | |
| 
 | |
| 		private bool TryAnnounce(AnnouncementData announcement)
 | |
| 		{
 | |
| 			if (announcement.Cooldown > 0f)
 | |
| 				return false;
 | |
| 
 | |
| 			if (announcement.AudioMessage != null && announcement.AudioMessage.Clips.Length > 0)
 | |
| 			{
 | |
| 				if (_audio.IsPlaying == true)
 | |
| 					return false;
 | |
| 
 | |
| 				_audio.Play(announcement.AudioMessage);
 | |
| 			}
 | |
| 
 | |
| 			Announce?.Invoke(announcement);
 | |
| 
 | |
| 			return true;
 | |
| 		}
 | |
| 	}
 | |
| }
 |