using ExitGames.Client.Photon; using Photon.Pun; using Photon.Realtime; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.SceneManagement; public class GameManager : MonoBehaviourPunCallbacks, IOnEventCallback { public Transform SpawnPositionsParent; private Transform[] SpawnPositions; public LootItemScriptableObject[] loots; public Transform LootSpawnPointsParent; LootSpawner[] LootSpawnPoints; [Header("Default Loots")] public List DeathmatchDefaultInventory; private double m_startTime; public int DeathmatchRoundLength = 600; public int DeathmtachRoundCountdown = 5; public int TDM_MinPlayers = 4; public double StartTime{ get{ return m_startTime; } set{ m_startTime = value; UIManager.instance.SetTimer(value, DeathmatchRoundLength); } } bool testingMode =false; private void Awake() { if(!PhotonNetwork.IsConnected){ testingMode=true; PhotonNetwork.ConnectUsingSettings(); } instance = this; LootSpawnPoints = LootSpawnPointsParent.GetComponentsInChildren(); SpawnPositions = new Transform[SpawnPositionsParent.childCount]; for (int i=0; i < SpawnPositionsParent.childCount; i++) { SpawnPositions[i] = SpawnPositionsParent.GetChild(i); } } //Statics public static List partyMembers = new List(); public static string partyId; public static string RoomName; public static bool isInit =false; public static string desiredGameMode = GameModes.Deathmatch.ToString(); public static GameManager instance; public static PlayerController localPlayer; void ResetStatics(){ isInit=false; instance=null; localPlayer= null; } void Start() { Photon.Realtime.RoomOptions options = new Photon.Realtime.RoomOptions() { IsOpen = true, IsVisible=true }; PhotonNetwork.JoinOrCreateRoom(RoomName, options, Photon.Realtime.TypedLobby.Default); } public override void OnConnectedToMaster() { base.OnConnectedToMaster(); if(testingMode){ PhotonNetwork.JoinOrCreateRoom("TEST",new RoomOptions(){IsOpen= true, IsVisible=true}, TypedLobby.Default); } } List m_loots = new List(); public override void OnJoinedRoom() { base.OnJoinedRoom(); StartCoroutine(KickstartGame()); // UIManager.instance.loadingPanel.SetActive(false); } void SpawnLoots(){ foreach(LootSpawner spawnPoint in LootSpawnPoints) { float totalLuck = 0; Dictionary startLuck = new Dictionary(); foreach(LootGroup group in spawnPoint.groups) { startLuck.Add(group, totalLuck); totalLuck += group.chance; } float luck = Random.Range(0f, totalLuck); float a = 0; foreach (KeyValuePair pair in startLuck) { if(luck > pair.Value && luck < pair.Value + pair.Key.chance) { for(int i=0; i < pair.Key.loots.Count; i++) { a += Mathf.PI * 0.2f; // float a = Mathf.Sin(((float)i / (float)pair.Key.loots.Count) * (Mathf.PI)); float x = Mathf.Sin(a); float y = Mathf.Cos(a); Vector3 point = spawnPoint.transform.position + new Vector3(x, 0, y); m_loots.Add(PhotonNetwork.InstantiateRoomObject(pair.Key.loots[i].spawnableName, point, Quaternion.identity)); } break; } } } } public void SpawnPickup(string spawnableName, Vector3 point, int count =1){ if(PhotonNetwork.IsMasterClient){ _spawnPickup(spawnableName, point, count); }else{ photonView.RPC("RpcSpawnPickup", RpcTarget.MasterClient, spawnableName, count, point); } } [PunRPC] void RpcSpawnPickup(string spawnableName, Vector3 point, int count=1){ if(PhotonNetwork.IsMasterClient){ _spawnPickup(spawnableName, point,count); } } void _spawnPickup(string spawnableName, Vector3 point, int count = 1){ GameObject loot = PhotonNetwork.InstantiateRoomObject(spawnableName, point, Quaternion.identity); loot.GetComponent().SetCount(count); m_loots.Add(loot); } // Update is called once per frame float timer => DeathmatchRoundLength - (float)(PhotonNetwork.Time -StartTime); bool isFinished =false; void Update() { if(!isInit){return;} if(PhotonNetwork.IsMasterClient){ if(timer <=0 ){ //Game Over if(!isFinished){ isFinished=true; FinishRound(); } } } } public void FinishRound(){ if(desiredGameMode == GameModes.Deathmatch.ToString()){ FinishDeathmatch(); }else if(desiredGameMode == GameModes.TeamDeathmatch.ToString()){ FinishTeamdeathmatch(); } if(PhotonNetwork.IsMasterClient){ StartCoroutine(Coroutine_SubmitSession()); } Cursor.lockState = CursorLockMode.None; Cursor.visible = true; CameraFollow.Pause(); PhotonNetwork.LeaveRoom(); StartCoroutine(PlayAgain()); } void FinishDeathmatch(){ int position =0; for(position=0; position < Leaderboard.list.Length; position++){ if(Leaderboard.list[position] == localPlayer.playerNetwork){ break; } } if(desiredGameMode == GameModes.Deathmatch.ToString()){ UIManager.ShowDeathmatchFinishScreen(position, Leaderboard.list[0].username); } } void FinishTeamdeathmatch(){ KeyValuePair winnerTeam = new KeyValuePair("",0); foreach(KeyValuePair team in LeaderboardTDM.unsortedTeamScores){ if(team.Value > winnerTeam.Value){ winnerTeam = team; } } if(desiredGameMode == GameModes.Deathmatch.ToString()){ UIManager.ShowTDMFinishScreen(winnerTeam.Key); } } IEnumerator PlayAgain(){ yield return new WaitForSeconds(10f); ResetStatics(); SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex); } IEnumerator Coroutine_SubmitSession(){ WWWForm form = new WWWForm(); form.AddField("champion", Leaderboard.list[0].username); form.AddField("master_client", localPlayer.playerNetwork.username); form.AddField("match_code", PhotonNetwork.CurrentRoom.CustomProperties["uuid"].ToString()); string playerList = ""; foreach(PlayerNetwork player in Leaderboard.list){ playerList += player.username +","; } form.AddField("players", playerList); WWW req= new WWW(UserDataManager.GetApiUrl("add_session"),form); yield return req; Debug.Log("Session record add response: " + req.text); WWWForm form2 = new WWWForm(); form2.AddField("username", UserDataManager.instance.Username); WWW req2 = new WWW(UserDataManager.GetApiUrl("add_match_count"),form2); yield return req2; } public float minPlayerSpawnBetweenDist = 2; public Transform GetRandomSpawnPoint() { Transform farthest= SpawnPositions[0]; PlayerNetwork[] players = FindObjectsOfType(); //Debug.Log($"DistPlayer count {SpawnPositions.Length} : {players.Length}"); for(int i =0; i < SpawnPositions.Length; i++){ bool tooClose = false; for(int ii=0; ii < players.Length; ii++){ float dist = Vector3.Distance(SpawnPositions[i].position, players[ii].transform.position); // Debug.Log("DistPlayer : " + dist); if(dist < minPlayerSpawnBetweenDist){ tooClose=true; break; } } if(!tooClose){return SpawnPositions[i];} } return SpawnPositions[Random.Range(0, SpawnPositions.Length)]; } ExitGames.Client.Photon.Hashtable CustomData; public int DeathmatchMinPlayerCount = 1; int customPlayerId=0; IEnumerator KickstartGame(){ PlayerNetwork[] players = FindObjectsOfType(); // Debug.Log("Player cound :" + players.Length); int iterations = 0; while(players.Length <=0){ players = FindObjectsOfType(); // Debug.Log("Player cound :" + players.Length + ", iterations: " + iterations); yield return new WaitForSeconds(0.1f); iterations++; if(iterations > 5){ break; } } customPlayerId = players.Length; localPlayer = PhotonNetwork.Instantiate("Player", SpawnPositions[customPlayerId].position, Quaternion.identity).GetComponentInChildren(); // localPlayer.GetComponent().SetPartyName(partyName,partyId); UIManager.instance.RoundLength = DeathmatchRoundLength; localPlayer.GetComponent().AutoAssignParty(); //Wait for Players if(PhotonNetwork.IsMasterClient){ while(PhotonNetwork.CurrentRoom.PlayerCount <(desiredGameMode == GameModes.TeamDeathmatch.ToString() ? TDM_MinPlayers : DeathmatchMinPlayerCount)){ yield return new WaitForSeconds(0.5f); UIManager.WaitingForPlayers(); } ExitGames.Client.Photon.Hashtable customData= new ExitGames.Client.Photon.Hashtable(); customData.Add("uuid", Helpers.GetRandomCode(8)); PhotonNetwork.CurrentRoom.SetCustomProperties(customData); }else{ UIManager.WaitingForPlayers(); } if(PhotonNetwork.IsMasterClient){ Debug.Log("Sending Timer Signal"); RaiseEventOptions raiseEventOptions = new RaiseEventOptions{Receivers = ReceiverGroup.All}; PhotonNetwork.RaiseEvent(GameStartEventCode, null, raiseEventOptions, SendOptions.SendReliable); } } public static LootItemScriptableObject GetLootByName(string spawnableName) { foreach(LootItemScriptableObject loot in instance.loots) { if(loot.spawnableName == spawnableName) { return loot; } } return null; } void OnEnable() { PhotonNetwork.AddCallbackTarget(this); } void OnDisable() { PhotonNetwork.RemoveCallbackTarget(this); } public const byte GameStartEventCode= 1; public const byte BeginGameModeCode= 2; public void OnEvent(EventData photonEvent) { byte eventCode = photonEvent.Code; if(eventCode == GameStartEventCode) { StartCoroutine(BeginStartTimer()); }else if(eventCode == BeginGameModeCode){ isInit=true; object[] customData = (object[])photonEvent.CustomData; StartTime = (double)customData[0]; desiredGameMode = customData[1].ToString(); Debug.Log("Starting game"); if(PhotonNetwork.IsMasterClient){ SpawnLoots(); StartCoroutine(HideRoomIn((float)DeathmatchRoundLength /2f)); } InventoryManager.ResetStocks(); if(desiredGameMode == GameModes.Deathmatch.ToString() || desiredGameMode == GameModes.TeamDeathmatch.ToString()){ InventoryManager.instance.GiveDefaultLoots(DeathmatchDefaultInventory); } localPlayer.transform.position = SpawnPositions[customPlayerId].position; } } IEnumerator HideRoomIn(float length){ yield return new WaitForSeconds(length); Debug.Log("Hiding this room"); PhotonNetwork.CurrentRoom.IsOpen = false; } IEnumerator BeginStartTimer(){ int t = DeathmtachRoundCountdown; while(t > 0){ UIManager.SetStatusText("Starting game in " + t); yield return new WaitForSecondsRealtime(1); t--; } UIManager.SetStatusText(""); if(PhotonNetwork.IsMasterClient){ RaiseEventOptions raiseEventOptions = new RaiseEventOptions{Receivers = ReceiverGroup.All}; PhotonNetwork.RaiseEvent(BeginGameModeCode, new object[]{PhotonNetwork.Time, desiredGameMode}, raiseEventOptions, SendOptions.SendReliable); } } } [System.Serializable] public struct InventoryEntry{ public LootItemScriptableObject loot; public int count; } public enum GameModes{ Deathmatch, TeamDeathmatch, BattleRoyale }