Added IInteractable and Stations

This commit is contained in:
2026-04-26 09:36:55 +02:00
parent b872b52632
commit 48448a9cff
12 changed files with 291 additions and 36 deletions

View File

@@ -4,6 +4,7 @@ using Subsystems;
using System.Collections;
using System;
using TMPro;
using System.Collections.Generic;
/*
GameManager - hlavní tøida pro správu hry
GameManager_Network - subsystém pro správu komunikace se serverem
@@ -20,6 +21,7 @@ public class GameManager : MonoBehaviour
protected GameManager_UI uiSubsystem;
protected GameManager_Map mapSubsystem;
protected GameManager_Input inputSubsystem;
protected GameManager_Game gameSubsystem;
protected GameClient gameClient;
@@ -49,6 +51,9 @@ public class GameManager : MonoBehaviour
private GameManager_Network _secondNetwork;
private GameManager_Network _thirdNetwork;
[Header("Tasks")]
public List<TaskData> AvailableTasks = new List<TaskData>();
public StationSettings settings = new StationSettings();
void Start()
{
@@ -72,6 +77,7 @@ public class GameManager : MonoBehaviour
networkSubsystem = new GameManager_Network(gameClient);
mapSubsystem = new GameManager_Map(gameClient, MapCenterPoint, buildingSettings, pathwaySettings, areaSettings);
inputSubsystem = new GameManager_Input(gameClient, Player, testMode);
gameSubsystem = new GameManager_Game(gameClient, Player, MapCenterPoint, AvailableTasks);
networkSubsystem.OpenConection();
}
private void Update()
@@ -133,6 +139,10 @@ public class GameManager : MonoBehaviour
{
networkSubsystem.StartGame();
}
public void Interact()
{
//TODO: Interakce s úkoly
}
void OnApplicationQuit()
{
gameClient.Disconnect();

View File

@@ -0,0 +1,117 @@
using GeoSus.Client;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using static UnityEngine.Rendering.RayTracingAccelerationStructure;
namespace Subsystems
{
[System.Serializable]
public class StationSettings
{
public GameObject TaskStationPrefab;
public GameObject SabotageStationPrefab;
public GameObject MeetingStationPrefab;
public GameObject BodyStationPrefab;
}
public class GameManager_Game
{
private GameClient _gameClient;
private GameObject _player;
private GameObject _map;
private float _range;
private List<TaskData> _availableTasks;
public List<GameObject> Stations { get; private set; }
private StationSettings _stationSettings;
public GameManager_Game(GameClient client, GameObject player, GameObject map, List<TaskData> availableTasks, float range = 20f, StationSettings stationSettings = null)
{
_gameClient = client;
_player = player;
_map = map;
_availableTasks = availableTasks;
_range = range;
_stationSettings = stationSettings;
}
public bool CheckSightLine(Vector3 target)
{
RaycastHit hit;
Vector3 direction = target - _player.transform.position;
Ray ray = new Ray(new Vector3(_player.transform.position.x, 0.1f, _player.transform.position.z), direction);
Physics.Raycast(ray, out hit, _range);
if (hit.collider.tag == "Player")
{
Debug.Log("Target is visible");
return true;
}
else
{
Debug.Log("Target is not visible");
return false;
}
}
public void InitializeStation(Position pos, StationType type)
{
GameObject stationPrefab = null;
PlayerRole? reqRole = null;
switch (type)
{
case StationType.Task:
stationPrefab = _stationSettings.TaskStationPrefab;
reqRole = PlayerRole.Crew;
break;
case StationType.Sabotage:
stationPrefab = _stationSettings.SabotageStationPrefab;
break;
case StationType.Meeting:
stationPrefab = _stationSettings.MeetingStationPrefab;
break;
case StationType.Body:
stationPrefab = _stationSettings.BodyStationPrefab;
break;
default:
Debug.LogError("Invalid station type");
break;
}
var station = UnityEngine.Object.Instantiate(stationPrefab);
station.transform.position = pos.ToLocalVector3(_gameClient.CurrentLobbyState.MapData.Center);
Stations.Add(station);
IInteractable interactable = station.GetComponent<IInteractable>();
interactable.Location = pos;
interactable.InteractionRange = _range;
/*Stations = new List<GameObject>();
foreach (var task in _gameClient.MyTasks)
{
System.Random rnd = new System.Random();
int index = rnd.Next(0, _availableTasks.Count);
var station = UnityEngine.Object.Instantiate(_stationPrefab);
ITask TaskSettings = station.GetComponent<ITask>();
TaskSettings.TaskID = task.TaskId;
TaskSettings.TaskLocation = task.Location;
station.transform.position = TaskSettings.TaskLocation.ToLocalVector3(_gameClient.CurrentLobbyState.MapData.Center);
station.SetActive(false);
Stations.Add(station);
}*/
}
void CheckForPlayers()
{
foreach (var player in _gameClient.PlayerPositions.Where(p => p.Value.State == PlayerState.Alive))
{
if (CheckSightLine(player.Value.Position.ToLocalVector3(_gameClient.CurrentLobbyState.MapData.Center)))
{
Debug.Log($"Player {player.Key} is visible");
//TODO: Render player on map
}
else
{
Debug.Log($"Player {player.Key} is not visible");
}
}
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: aba57c59fb2a19141a4868fa6a5c924c

View File

@@ -110,7 +110,7 @@ namespace Subsystems
}
else
{
Debug.Log("GPS failed, trying again...");)
Debug.Log("GPS failed, trying again...");
_GPSState = GPSState.Uninitialized;
}
}

View File

@@ -133,6 +133,8 @@ namespace Subsystems{
// Vytvoření mesh pro budovu
MeshFilter meshFilter = building.AddComponent<MeshFilter>();
MeshRenderer meshRenderer = building.AddComponent<MeshRenderer>();
MeshCollider meshCollider = building.AddComponent<MeshCollider>();
building.tag = "Map";
float height;
Material mat;
@@ -157,6 +159,7 @@ namespace Subsystems{
}
Mesh mesh = CreateExtrudedPolygonMesh(b.Outline, height);
meshFilter.mesh = mesh;
meshCollider.sharedMesh = mesh;
//TODO: material by type
// Použijeme barvu podle typu budovy
@@ -169,6 +172,7 @@ namespace Subsystems{
GameObject BuildPathwayMesh(MapPathway w)
{
var path = new GameObject($"Path_{w.Name ?? "Unknown"}");
path.tag = "Map";
// Použijeme LineRenderer pro jednoduchost
LineRenderer line = path.AddComponent<LineRenderer>();
@@ -235,6 +239,7 @@ namespace Subsystems{
GameObject BuildAreaMesh(MapArea a)
{
var area = new GameObject($"Area_{a.Name ?? "Unknown"}");
area.tag = "Map";
MeshFilter meshFilter = area.AddComponent<MeshFilter>();
MeshRenderer meshRenderer = area.AddComponent<MeshRenderer>();

View File

@@ -105,6 +105,10 @@ namespace Subsystems
case "MapDataError":
Debug.Log("Received MapData server error");
break;
case "SabotageStarted":
Debug.Log("Sabotage started");
HandleSabotageStarted(gameEvent);
break;
default:
Debug.Log("Received GameEvent of type: " + gameEvent.EventType);
break;
@@ -157,6 +161,36 @@ namespace Subsystems
_gameClient.StartGame();
}
#region GameEvent Handlers
private void HandleSabotageStarted(GameEvent gameEvent)
{
SabotageStartedPayload payload = gameEvent.GetPayload<SabotageStartedPayload>();
switch (payload.Type)
{
case SabotageType.CommsBlackout:
for(int i = 0;i < payload.RequiredSimultaneousRepairs; i++)
{
//create stations
}
//Ui.alert
//DisableComms
return;
case SabotageType.CriticalMeltdown:
for (int i = 0; i < payload.RequiredSimultaneousRepairs; i++)
{
//create stations
}
//UI.alert
//UI Time remain
return;
default:
Debug.Log($"Sabotage of unknown type: {payload.Type}");
return;
}
}
#endregion
}
}

View File

@@ -6,16 +6,20 @@ using UnityEngine;
{
Task //TODO: Typy úkolù
}*/
[System.Serializable]
public class TaskData
{
//TaskType
public GameObject TaskPrefab;
}
public interface ITask
{
public string TaskID { get; } // Unikátní ID úkolu pro server
public TaskType TaskType { get; } // Typ úkolu
public string TaskName { get; } // Viditelný název úkolu
public Position TaskLocation { get; } // Polohy na mapì
public bool IsCompleted { get; } // Stav dokonèení úkolu
public string TaskID { get; set; } // Unikátní ID úkolu pro server
public TaskType TaskType { get; set; } // Typ úkolu
public string TaskName { get; set; } // Viditelný název úkolu
public Position TaskLocation { get; set; } // Polohy na mapì
public bool IsCompleted { get; } // Stav dokončení úkolu
void Initialize(Action<ITask> onCompleted); // Vytvoøení tasku + naètení postupu
void ExitTask(Action<ITask> onExit); // Pøi opuštìní úkolu poslat hotovo / uložit postup / reset
@@ -35,6 +39,7 @@ public class Wires : ITask{
{
IsCompleted = false;
_onCompleted = onCompleted;
}
public void ExitTask(Action<ITask> onExit) //Zavøení tasku
{
@@ -51,3 +56,18 @@ public class Wires : ITask{
}
*/
public enum StationType
{
Sabotage,
Task,
Meeting,
Body
}
public interface IInteractable
{
public StationType Type { get; set; } // Typ stanice
public Position Location { get; set; } // Pozice na mapě
public PlayerRole? ReqRole { get; set; } // Požadovaná role hráče Impostor / Crewmate / Any = null
public float InteractionRange { get; set; } // Dosah interakce
void Interact(PlayerRole role); // Spuštění interakce
}

View File

@@ -0,0 +1,83 @@
using GeoSus.Client;
using System;
using UnityEngine;
using System.Linq;
public class Station : IInteractable
{
public StationType Type { get; set; }
public Position Location { get; set; }
public PlayerRole? ReqRole { get; set; }
public float InteractionRange { get; set; }
protected GameObject interfaceInstance;
public GameObject Interface; // Prefab pro interakci (napø. UI pro úkol nebo sabotáže)
public virtual void Interact(PlayerRole role)
{
if (ReqRole.HasValue && role != ReqRole.Value)
{
Debug.Log("You do not have the required role to interact with this station.");
return;
}
else
{
interfaceInstance = UnityEngine.Object.Instantiate(Interface); // Zobrazí interakèní UI
}
}
public Station(Position location, float interactionRange)
{
Location = location;
InteractionRange = interactionRange;
}
}
public class TaskStation : Station
{
public string TaskID { get; set; } // Unikátní ID úkolu pro server
private GameClient _gameClient;
public TaskStation(Position pos, float interactionRange, GameClient gameClient, string taskID) : base(pos, interactionRange)
{
Type = StationType.Task;
ReqRole = PlayerRole.Crew;
_gameClient = gameClient;
}
public ITask Task { get; set; }
public override void Interact(PlayerRole role)
{
if(interfaceInstance != null)
{
ResumeTask();
return;
}
base.Interact(role);
Task = interfaceInstance.GetComponent<ITask>();
Task.TaskID = TaskID;
Task.Initialize(OnTaskCompleted);
}
private void ResumeTask()
{
interfaceInstance.SetActive(true); // Zobrazí interakèní UI
}
private void OnTaskCompleted(ITask task)
{
_gameClient.CompleteTask(task.TaskID);
task.ExitTask(OnTaskExit);
Debug.Log($"Task {task.TaskName} completed and sent to server.");
}
private void OnTaskExit(ITask task)
{
if (task.IsCompleted)
{
UnityEngine.Object.Destroy(interfaceInstance); // Znièí interakèní UI
Debug.Log($"Task {task.TaskName} completed and sent to server.");
}
else
{
interfaceInstance.SetActive(false); // Skryje interakèní UI
Debug.Log($"Task {task.TaskName} was not completed, but exited.");
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 0ca1825585bf9bc42bd3b11985048465

View File

@@ -2282,6 +2282,11 @@ MonoBehaviour:
DefaultMat: {fileID: 2100000, guid: 5a46533bdf4003449bc9146ccef44e27, type: 2}
Player: {fileID: 1161233721}
testMode: 1
AvailableTasks:
- TaskPrefab: {fileID: 0}
Stations:
- Type: 0
Prefab: {fileID: 0}
--- !u!1 &1403738861
GameObject:
m_ObjectHideFlags: 0

View File

@@ -2,8 +2,9 @@
%TAG !u! tag:unity3d.com,2011:
--- !u!78 &1
TagManager:
serializedVersion: 2
tags: []
serializedVersion: 3
tags:
- Map
layers:
- Default
- TransparentFX
@@ -50,27 +51,3 @@ TagManager:
- Light Layer 5
- Light Layer 6
- Light Layer 7
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-