2025-09-24 11:24:38 +05:00

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;
}
}
}