Zabiju je
This commit is contained in:
213
Assets/GameManager/GameManager_Tasks.cs
Normal file
213
Assets/GameManager/GameManager_Tasks.cs
Normal file
@@ -0,0 +1,213 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
using GeoSus.Client;
|
||||
|
||||
namespace Subsystems
|
||||
{
|
||||
/// <summary>
|
||||
/// Round-robin task-to-minigame assignment, proximity detection, additive scene launch.
|
||||
/// </summary>
|
||||
public class GameManager_Tasks
|
||||
{
|
||||
private class TaskEntry
|
||||
{
|
||||
public GeoSus.Client.GameTask ServerTask;
|
||||
public string MinigameScene;
|
||||
public bool Completed;
|
||||
}
|
||||
|
||||
private GameClient _gameClient;
|
||||
private string[] _minigameScenes;
|
||||
private MonoBehaviour _host; // GameManager MonoBehaviour for coroutines
|
||||
private List<TaskEntry> _tasks = new List<TaskEntry>();
|
||||
private bool _minigameOpen;
|
||||
private string _loadedMinigameScene;
|
||||
|
||||
// Proximity state (checked every frame in UpdateProximity)
|
||||
public GeoSus.Client.GameTask NearbyTask { get; private set; }
|
||||
|
||||
private const float ProximityRadius = 5f; // metres / Unity units
|
||||
|
||||
public GameManager_Tasks(GameClient gameClient, string[] minigameScenes, MonoBehaviour host)
|
||||
{
|
||||
_gameClient = gameClient;
|
||||
_minigameScenes = minigameScenes ?? new string[0];
|
||||
_host = host;
|
||||
}
|
||||
|
||||
/// <summary>Called by Network subsystem when RoleAssigned fires.</summary>
|
||||
public void Initialize(List<GeoSus.Client.GameTask> serverTasks)
|
||||
{
|
||||
_tasks.Clear();
|
||||
if (_minigameScenes.Length == 0) return;
|
||||
|
||||
for (int i = 0; i < serverTasks.Count; i++)
|
||||
{
|
||||
_tasks.Add(new TaskEntry
|
||||
{
|
||||
ServerTask = serverTasks[i],
|
||||
MinigameScene = _minigameScenes[i % _minigameScenes.Length],
|
||||
Completed = false
|
||||
});
|
||||
}
|
||||
|
||||
// Create map markers
|
||||
GameManager.Instance?.mapSubsystem?.CreateTaskMarkers(serverTasks);
|
||||
Debug.Log($"[Tasks] Initialized {_tasks.Count} tasks.");
|
||||
}
|
||||
|
||||
/// <summary>Called every frame from GameManager.Update().</summary>
|
||||
public void UpdateProximity()
|
||||
{
|
||||
if (_minigameOpen) return;
|
||||
|
||||
NearbyTask = null;
|
||||
var myPos = _gameClient.MyPosition;
|
||||
if (myPos.Lat == 0 && myPos.Lon == 0) return;
|
||||
|
||||
foreach (var entry in _tasks)
|
||||
{
|
||||
if (entry.Completed) continue;
|
||||
double dist = myPos.DistanceTo(entry.ServerTask.Location);
|
||||
if (dist <= ProximityRadius)
|
||||
{
|
||||
NearbyTask = entry.ServerTask;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Drive the action button in UI
|
||||
var ui = GameManager.Instance?.uiSubsystem;
|
||||
if (ui == null || ui.IsPlayerDead) return;
|
||||
|
||||
bool isImpostor = _gameClient.MyRole == GeoSus.Client.PlayerRole.Impostor;
|
||||
|
||||
if (!isImpostor && NearbyTask != null)
|
||||
{
|
||||
ui.SetActionButton("USE", true, () => GameManager.Instance?.PerformAction());
|
||||
return;
|
||||
}
|
||||
|
||||
// Check body proximity
|
||||
if (!ui.IsCommsBlackout)
|
||||
{
|
||||
var body = _gameClient.FindNearbyBody(ProximityRadius);
|
||||
if (body != null)
|
||||
{
|
||||
ui.SetActionButton("REPORT", true, () => GameManager.Instance?.PerformAction());
|
||||
return;
|
||||
}
|
||||
|
||||
// Emergency meeting proximity
|
||||
if (_gameClient.CurrentLobbyState?.MapData != null)
|
||||
{
|
||||
double dist = myPos.DistanceTo(_gameClient.CurrentLobbyState.MapData.Center);
|
||||
if (dist <= ProximityRadius)
|
||||
{
|
||||
ui.SetActionButton("EMERGENCY", true, () => GameManager.Instance?.PerformAction());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Impostor kill
|
||||
if (isImpostor)
|
||||
{
|
||||
var target = _gameClient.FindNearbyPlayer(ProximityRadius);
|
||||
if (!string.IsNullOrEmpty(target))
|
||||
{
|
||||
ui.SetActionButton("KILL", true, () => GameManager.Instance?.PerformAction());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Nothing nearby
|
||||
ui.SetActionButton("", false);
|
||||
}
|
||||
|
||||
/// <summary>Called externally (e.g., GameManager.PerformAction) to launch the nearby task.</summary>
|
||||
public void TriggerNearbyTask()
|
||||
{
|
||||
OnUsePressed();
|
||||
}
|
||||
|
||||
private void OnUsePressed()
|
||||
{
|
||||
if (NearbyTask == null || _minigameOpen) return;
|
||||
var entry = _tasks.Find(t => t.ServerTask.TaskId == NearbyTask.TaskId);
|
||||
if (entry != null) _host.StartCoroutine(LaunchMinigame(entry));
|
||||
}
|
||||
|
||||
private IEnumerator LaunchMinigame(TaskEntry entry)
|
||||
{
|
||||
_minigameOpen = true;
|
||||
Debug.Log($"[Tasks] Launching minigame '{entry.MinigameScene}' for task '{entry.ServerTask.Name}'");
|
||||
|
||||
// Inform server that task started
|
||||
_gameClient.Send(new TaskStart { TaskId = entry.ServerTask.TaskId });
|
||||
|
||||
var op = SceneManager.LoadSceneAsync(entry.MinigameScene, LoadSceneMode.Additive);
|
||||
yield return op;
|
||||
|
||||
_loadedMinigameScene = entry.MinigameScene;
|
||||
|
||||
// Find the ITask component in the newly loaded scene
|
||||
Scene scene = SceneManager.GetSceneByName(entry.MinigameScene);
|
||||
ITask taskComponent = null;
|
||||
foreach (var root in scene.GetRootGameObjects())
|
||||
{
|
||||
taskComponent = root.GetComponentInChildren<ITask>();
|
||||
if (taskComponent != null) break;
|
||||
}
|
||||
|
||||
if (taskComponent == null)
|
||||
{
|
||||
Debug.LogWarning($"[Tasks] No ITask found in '{entry.MinigameScene}'. Auto-completing.");
|
||||
yield return FinishMinigame(entry, true);
|
||||
yield break;
|
||||
}
|
||||
|
||||
// Set task metadata
|
||||
taskComponent.TaskID = entry.ServerTask.TaskId;
|
||||
taskComponent.TaskName = entry.ServerTask.Name;
|
||||
taskComponent.TaskLocation = (entry.ServerTask.Location.Lat, entry.ServerTask.Location.Lon);
|
||||
|
||||
bool done = false;
|
||||
bool exited = false;
|
||||
taskComponent.Initialize(t => { done = true; });
|
||||
taskComponent.ExitTask(t => { exited = true; });
|
||||
|
||||
// Wait for completion or exit
|
||||
yield return new WaitUntil(() => done || exited);
|
||||
|
||||
yield return FinishMinigame(entry, done);
|
||||
}
|
||||
|
||||
private IEnumerator FinishMinigame(TaskEntry entry, bool completed)
|
||||
{
|
||||
if (completed)
|
||||
{
|
||||
entry.Completed = true;
|
||||
_gameClient.CompleteTask(entry.ServerTask.TaskId);
|
||||
Debug.Log($"[Tasks] Task '{entry.ServerTask.Name}' completed.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log($"[Tasks] Task '{entry.ServerTask.Name}' exited without completion.");
|
||||
}
|
||||
|
||||
// Unload minigame scene
|
||||
if (!string.IsNullOrEmpty(_loadedMinigameScene))
|
||||
{
|
||||
var unload = SceneManager.UnloadSceneAsync(_loadedMinigameScene);
|
||||
yield return unload;
|
||||
_loadedMinigameScene = null;
|
||||
}
|
||||
|
||||
_minigameOpen = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user