1
0
forked from cgvr/DeltaVR
Files
DeltaVR3DModelGeneration/Assets/_PROJECT/Components/Bow/Scripts/ArcheryRange.cs
T

252 lines
7.2 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using _PROJECT.Scripts.Bow;
using FishNet.Component.Transforming;
using FishNet.Object;
using FishNet.Object.Synchronizing;
using System;
using System.Collections.Generic;
using System.Linq;
using TMPro;
using Unity.XR.CoreUtils;
using UnityEngine;
using Random = UnityEngine.Random;
public class ArcheryRange : NetworkBehaviour
{
public TMP_Text highScoreText;
public TMP_Text timeLeftText;
public TMP_Text scoreText;
public Transform targetStartPosition;
public Transform targetEndPosition;
public GameObject targetPrefab;
public StartTarget startTarget;
public QuestMarker questMarker;
public GameObject archeryTargetPointsText;
public Vector3 minRandomOffset = new Vector3(0f, -2f, -5f);
public Vector3 maxRandomOffset = new Vector3(0f, 2f, 5f);
public float roundLength = 60f;
public float targetSpawnTime = 3f;
public float targetSizeIncrease = 10f;
public ModelDisplay modelDisplay;
public KeyboardManager keyboardManager;
private List<ArcheryTarget> _targets;
[SyncVar]
private float _score;
private float _maxScore;
private float _roundEndTime;
private float _nextTargetTime;
private bool _roundActive;
private readonly List<XROrigin> _presentPlayers = new();
private XROrigin _scoredPlayer;
public override void OnStartServer()
{
base.OnStartServer();
_roundActive = false;
_targets = new List<ArcheryTarget>();
_score = 0;
_maxScore = 0;
_roundEndTime = 0f;
_maxScore = LoadScoreFromDisk();
//+Debug.Log($"highScore is {_maxScore}");
StartCoroutine(DelayedSetHighScoreText(10f)); // Cannot immediately assign these values because fishnet needs time.
}
private System.Collections.IEnumerator DelayedSetHighScoreText(float delaySeconds)
{
yield return new WaitForSeconds(delaySeconds);
SetHighScoreText($"High Score: {_maxScore}");
}
private void OnTriggerEnter(Collider other)
{
SetHighScoreText($"High Score: {_maxScore}"); // Refresh high score UI
XROrigin enteredPlayer = other.GetComponent<XROrigin>();
if (enteredPlayer == null || _presentPlayers.Contains(enteredPlayer))
return;
_presentPlayers.Add(enteredPlayer); // Adds to the end
}
private void OnTriggerExit(Collider other)
{
XROrigin exitedPlayer = other.GetComponent<XROrigin>();
if (exitedPlayer == null) return;
_presentPlayers.Remove(exitedPlayer); // Shifts others left automatically
if (exitedPlayer == _scoredPlayer) keyboardManager.DeActivate(); // If the player ´refuses to enter their name.
}
public override void OnStopServer()
{
base.OnStopServer();
SaveScoreToDisk(_maxScore);
}
// Update is called once per frame
void Update()
{
if (!IsServer) return;
if (!_roundActive) return;
if (Time.time >= _roundEndTime)
{
ResetRange();
}
else
{
SetTimeLeftText($"Time Left: {Math.Ceiling((_roundEndTime - Time.time) % 60)}");
if (Time.time >= _nextTargetTime)
{
_nextTargetTime = Time.time + targetSpawnTime;
SpawnTarget();
}
}
}
private void SpawnTarget()
{
if (!IsServer) return;
var randomPos = targetStartPosition.position + new Vector3(
Random.Range(minRandomOffset.x, maxRandomOffset.x),
(float) Math.Round(Random.Range(minRandomOffset.y, maxRandomOffset.y)),
Random.Range(minRandomOffset.z, maxRandomOffset.z)
);
var target = SpawnTarget(randomPos);
_targets.Add(target);
}
private ArcheryTarget SpawnTarget(Vector3 randomPos)
{
// Spawn default UFO
GameObject targetObject = Instantiate(targetPrefab, randomPos, targetStartPosition.rotation, null);
if (modelDisplay.Model != null)
{
// Spawn generated object directly as default UFO's child
GameObject childObject = Instantiate(modelDisplay.Model);
childObject.transform.SetParent(targetObject.transform, false);
childObject.transform.localScale *= targetSizeIncrease;
// Disable UFO's default body
targetObject.transform.Find("Body").gameObject.SetActive(false);
}
ArcheryTarget target = targetObject.GetComponent<ArcheryTarget>();
target.endPosition = targetEndPosition.position;
target.addScore = AddScore;
Spawn(targetObject);
return target;
}
public void ResetRange()
{
if (!IsServer) return;
foreach (var target in _targets.Where(target => target != null))
{
Despawn(target.gameObject, DespawnType.Pool);
}
_targets = new List<ArcheryTarget>();
if (_maxScore < _score) _maxScore = _score;
if (_presentPlayers.Count != 0) // If there are players in the area.
{
// Gives the score to the player longest-lasting in the area. It would be better to give it to the player that fired the starting arrow, but I'm not spending 10 hours on this.
XROrigin scoringPlayer = _presentPlayers.First();
Menu playermenu = scoringPlayer.GetComponentInChildren<Menu>();
_scoredPlayer = scoringPlayer;
playermenu.setCanvasVisibility(false); // Deactivates the menu to avoid overlap issues.
Transform keyboardPlacement = playermenu.updateMenuTransform();
keyboardManager.Activate(_score, keyboardPlacement);
SaveScoreToDisk(_maxScore);
SetHighScoreText($"High Score: {_maxScore}");
}
_score = 0;
startTarget.ShowTarget();
_roundActive = false;
SetTimeLeftText("");
}
public void StartRound()
{
if (!IsServer) return;
_roundEndTime = Time.time + roundLength;
_nextTargetTime = Time.time;
_roundActive = true;
questMarker.gameObject.SetActive(false);
}
public void AddScore(float distance)
{
if (!IsServer) return;
_score += distance;
SetScoreText($"Score: {_score}");
}
[ObserversRpc]
public void SetHighScoreText(string text)
{
highScoreText.text = text;
}
[ObserversRpc]
public void SetScoreText(string text)
{
scoreText.text = text;
}
[ObserversRpc]
public void SetTimeLeftText(string text)
{
timeLeftText.text = text;
}
public class SaveData
{
public float HighScore;
}
public void SaveScoreToDisk(float highScore)
{
SaveData data = new SaveData { HighScore = highScore };
string json = JsonUtility.ToJson(data);
System.IO.File.WriteAllText("highscore.json", json);
}
public float LoadScoreFromDisk()
{
if (System.IO.File.Exists("highscore.json"))
{
string json = System.IO.File.ReadAllText("highscore.json");
SaveData data = JsonUtility.FromJson<SaveData>(json);
return data.HighScore;
}
return 0f; // default score
}
}