GeoSus
This commit is contained in:
@@ -29,7 +29,11 @@ namespace Subsystems
|
||||
// Proximity state (checked every frame in UpdateProximity)
|
||||
public GeoSus.Client.GameTask NearbyTask { get; private set; }
|
||||
|
||||
private const float ProximityRadius = 5f; // metres / Unity units
|
||||
// P13b: per-check distances pulled from the server-snapshotted lobby
|
||||
// settings (null-fallback to 5m matches the old hardcoded behavior).
|
||||
// Different actions use different fields so a host can tune e.g. a
|
||||
// long-range "spotter" task radius without also widening kill range.
|
||||
private const float ProximityRadiusFallback = 5f;
|
||||
|
||||
public GameManager_Tasks(GameClient gameClient, string[] minigameScenes, MonoBehaviour host)
|
||||
{
|
||||
@@ -64,6 +68,16 @@ namespace Subsystems
|
||||
{
|
||||
if (_minigameOpen) return;
|
||||
|
||||
// P13b: distances now come from the per-lobby settings snapshot
|
||||
// instead of one hardcoded 5m radius for everything. ?? fallback
|
||||
// matches the old behavior when running against an old server.
|
||||
var state = GameManager.Instance?.networkSubsystem?.State;
|
||||
var settings = state?.Settings;
|
||||
double taskDist = settings?.TaskStartDistanceM ?? ProximityRadiusFallback;
|
||||
double reportDist = settings?.ReportDistanceM ?? ProximityRadiusFallback;
|
||||
double emergencyDist = settings?.EmergencyMeetingCallRadiusM?? ProximityRadiusFallback;
|
||||
double killDist = settings?.KillDistanceM ?? ProximityRadiusFallback;
|
||||
|
||||
NearbyTask = null;
|
||||
var myPos = _gameClient.MyPosition;
|
||||
if (myPos.Lat == 0 && myPos.Lon == 0) return;
|
||||
@@ -72,7 +86,7 @@ namespace Subsystems
|
||||
{
|
||||
if (entry.Completed) continue;
|
||||
double dist = myPos.DistanceTo(entry.ServerTask.Location);
|
||||
if (dist <= ProximityRadius)
|
||||
if (dist <= taskDist)
|
||||
{
|
||||
NearbyTask = entry.ServerTask;
|
||||
break;
|
||||
@@ -94,7 +108,7 @@ namespace Subsystems
|
||||
// Check body proximity
|
||||
if (!ui.IsCommsBlackout)
|
||||
{
|
||||
var body = _gameClient.FindNearbyBody(ProximityRadius);
|
||||
var body = _gameClient.FindNearbyBody(reportDist);
|
||||
if (body != null)
|
||||
{
|
||||
ui.SetActionButton("REPORT", true, () => GameManager.Instance?.PerformAction());
|
||||
@@ -105,7 +119,7 @@ namespace Subsystems
|
||||
if (_gameClient.CurrentLobbyState?.MapData != null)
|
||||
{
|
||||
double dist = myPos.DistanceTo(_gameClient.CurrentLobbyState.MapData.Center);
|
||||
if (dist <= ProximityRadius)
|
||||
if (dist <= emergencyDist)
|
||||
{
|
||||
ui.SetActionButton("EMERGENCY", true, () => GameManager.Instance?.PerformAction());
|
||||
return;
|
||||
@@ -116,16 +130,28 @@ namespace Subsystems
|
||||
// Impostor kill
|
||||
if (isImpostor)
|
||||
{
|
||||
var target = _gameClient.FindNearbyPlayer(ProximityRadius);
|
||||
var target = _gameClient.FindNearbyPlayer(killDist);
|
||||
if (!string.IsNullOrEmpty(target))
|
||||
{
|
||||
ui.SetActionButton("KILL", true, () => GameManager.Instance?.PerformAction());
|
||||
// Hide sabotage menu while a kill is on offer (cleaner HUD).
|
||||
ui.SetSabotageMenuVisible(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Nothing nearby
|
||||
ui.SetActionButton("", false);
|
||||
|
||||
// P13g: persistent sabotage menu for impostors when no proximity
|
||||
// action is on offer. Hidden when state isn't suitable - dead,
|
||||
// not-impostor, in meeting, sabotage already active, or comms
|
||||
// blackout (the impostor's own sabotage triggers a UI lock).
|
||||
bool inPlayingPhase = state != null && state.Phase == GeoSus.Client.GamePhase.Playing;
|
||||
bool sabotageActive = state?.ActiveSabotage != null;
|
||||
bool showSabMenu = isImpostor && !ui.IsPlayerDead && inPlayingPhase &&
|
||||
!sabotageActive && !ui.IsCommsBlackout;
|
||||
ui.SetSabotageMenuVisible(showSabMenu);
|
||||
}
|
||||
|
||||
/// <summary>Called externally (e.g., GameManager.PerformAction) to launch the nearby task.</summary>
|
||||
@@ -146,10 +172,33 @@ namespace Subsystems
|
||||
_minigameOpen = true;
|
||||
Debug.Log($"[Tasks] Launching minigame '{entry.MinigameScene}' for task '{entry.ServerTask.Name}'");
|
||||
|
||||
// Validate that the scene name resolves to a build-included scene.
|
||||
// LoadSceneAsync silently returns null when the scene name doesn't
|
||||
// match (case-sensitive) or isn't in EditorBuildSettings, which
|
||||
// leaves the action button looking dead from the player's POV.
|
||||
if (string.IsNullOrEmpty(entry.MinigameScene) ||
|
||||
!Application.CanStreamedLevelBeLoaded(entry.MinigameScene))
|
||||
{
|
||||
Debug.LogError($"[Tasks] Minigame scene '{entry.MinigameScene}' is not loadable. " +
|
||||
$"Check the scene name (case-sensitive) and that it's enabled in Build Settings.");
|
||||
GameManager.Instance?.uiSubsystem?.ShowToast(
|
||||
$"Task scene missing: {entry.MinigameScene}");
|
||||
_minigameOpen = false;
|
||||
yield break;
|
||||
}
|
||||
|
||||
// Inform server that task started
|
||||
_gameClient.Send(new TaskStart { TaskId = entry.ServerTask.TaskId });
|
||||
|
||||
var op = SceneManager.LoadSceneAsync(entry.MinigameScene, LoadSceneMode.Additive);
|
||||
if (op == null)
|
||||
{
|
||||
Debug.LogError($"[Tasks] LoadSceneAsync returned null for '{entry.MinigameScene}'.");
|
||||
GameManager.Instance?.uiSubsystem?.ShowToast(
|
||||
$"Task scene failed to load: {entry.MinigameScene}");
|
||||
_minigameOpen = false;
|
||||
yield break;
|
||||
}
|
||||
yield return op;
|
||||
|
||||
_loadedMinigameScene = entry.MinigameScene;
|
||||
|
||||
Reference in New Issue
Block a user