dissertation / mainCode / Game / GameManager.cs
GameManager.cs
Raw
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngineInternal;
using Random = UnityEngine.Random;

public class GameManager : MonoBehaviour
{
    
    // interfaces
    public GameObject playerPrefab;
    public DifficultyManager difficultyManager = new DifficultyManager();
    public ScoreManager scoreManager;
    public LearningEngine learningEngine;
    
    // trackers
    public int noOfHits = 0;
    public int health = 100;
    public int noOfKills = 0;
    public float currentTimeElapsed;
    public List<GameObject> friendlySpawns = new List<GameObject>();
    public List<GameObject> enemySpawns = new List<GameObject>();
    public List<GameObject> currentEnemies = new List<GameObject>();
    
    // constants
    public float startTime;
    public GameResults results;
    public bool useKillsAsWincon;
    public float winConValue;
    public GameObject enemyToSpawn;
    public String logFileName = "GAMELOG.json";
    
    // difficulty affecting values
    public float enemyNoticeRate = 0.6f; // speed at which enemy starts firing upon seeing you
    public float enemyDamage = 10; // damage of enemy bullets
    public float enemyFireRate = 0.6f; // minimum time between enemy shots
    public float enemyMaxFireRate = 1.5f;
    public float enemyAimModifier = 0.05f; // bullet spread of enemies
    public float playerHealRate = 0.05f; // amount player heals per successful shot
    public float enemyHealth = 100; // enemy maximum health
    public float enemySpawnRate = 5; // number of enemies spawning on the map at once
    public float enemySpeed = 1.5f;
    
    // Start is called before the first frame update
    void Start()
    {
        
        
        learningEngine = GetComponent<LearningEngine>();
        useKillsAsWincon = true;
        winConValue = PlayerPrefs.GetFloat("targetKills");
        results = new GameResults();
        startTime = Time.time;
        var spawn = friendlySpawns[Random.Range(0, friendlySpawns.Count)];
        Destroy(playerPrefab);
        var newPlayer = Instantiate(playerPrefab, spawn.transform.position, spawn.transform.rotation);
        newPlayer.GetComponent<PlayerInput>().enabled = true;
        newPlayer.GetComponent<PlayerController>().enabled = true;
        newPlayer.GetComponent<PlayerMovement>().enabled = true;
        newPlayer.GetComponent<SlidingMovement>().enabled = true;
        newPlayer.GetComponent<InterpolatedTransformUpdater>().enabled = true;
        playerPrefab = newPlayer;
        
        SetInitialPrefs();
        
        if (!PlayerPrefs.HasKey("gameLog"))
        {
            PlayerPrefs.SetString("gameLog", JsonUtility.ToJson(new GameLog()));
        }

        if (PlayerPrefs.HasKey("levelShift") && PlayerPrefs.GetInt("levelShift") != 0 && PlayerPrefs.GetInt("difficultyAdjustmentEnabled") == 1)
        {

            var lastLevel = PlayerPrefs.GetInt("overallLevel");
           

            // set limits after
            var level = PlayerPrefs.GetInt("levelShift");
            PlayerPrefs.SetInt("overallLevel", lastLevel + level);
            enemyNoticeRate += (0.03f * level);
            enemyNoticeRate = Mathf.Clamp(enemyNoticeRate, 0.3f, 1f);
            PlayerPrefs.SetFloat("enemyNoticeRate", enemyNoticeRate);
            
            enemyDamage += (0.3f * level);
            enemyDamage = Mathf.Clamp(enemyDamage, 5f, 20f);
            PlayerPrefs.SetFloat("enemyDamage", enemyDamage);
            
            enemyFireRate -= (0.04f * level);
            enemyFireRate = Mathf.Clamp(enemyFireRate, 0.4f, 0.8f);
            PlayerPrefs.SetFloat("enemyFireRate", enemyFireRate);
            
            enemyMaxFireRate -= (0.04f * level);
            enemyMaxFireRate = Mathf.Clamp(enemyMaxFireRate, enemyFireRate, 2f);
            PlayerPrefs.SetFloat("enemyMaxFireRate", enemyMaxFireRate);
            
            enemyAimModifier -= (0.005f * level);
            enemyAimModifier = Mathf.Clamp(enemyAimModifier, 0.001f, 0.1f);
            PlayerPrefs.SetFloat("enemyAimModifier", enemyAimModifier);
            
            enemyHealth += (3f * level);
            enemyHealth = Mathf.Clamp(enemyHealth, 50f, 200f);
            PlayerPrefs.SetFloat("enemyHealth", enemyHealth);
            
            enemySpawnRate += (0.2f * level);
            enemySpawnRate = Mathf.Clamp(enemySpawnRate, 3, 15);
            PlayerPrefs.SetFloat("enemySpawnRate", enemySpawnRate);

            enemySpeed -= (0.05f * level);
            enemySpeed = Mathf.Clamp(enemySpeed, 0.25f, 2f);
            PlayerPrefs.SetFloat("enemySpeed", enemySpeed);

        } 
        


        SpawnEnemy((int) Math.Round(enemySpawnRate)); // change this to be rounding

    }

    // Update is called once per frame
    void Update()
    {

        if (Input.GetKeyUp("escape"))
        {
            Cursor.lockState = CursorLockMode.None;
            Cursor.visible = true;
            SceneManager.LoadScene("MainMenu", LoadSceneMode.Single);
        }


        currentTimeElapsed = Time.time - startTime;
        if (CheckIfGameOver())
        {
            // add retry menu
            Cursor.lockState = CursorLockMode.None;
            Cursor.visible = true;
            ConstructJsonToPrefs();
            SceneManager.LoadScene("ResultsMenu", LoadSceneMode.Single);
        }
    }

    public void LogResults(GameResults result)
    {
        Logger log;
        if (File.Exists(Application.persistentDataPath + "/" + logFileName))
        {
            var sr = new StreamReader(Application.persistentDataPath + "/" + logFileName);
            var fileContents = sr.ReadToEnd();
            sr.Close();
            log = JsonUtility.FromJson<Logger>(fileContents);
        }
        else
        {
            log = new Logger();
        }
        log.resultsList.Add(result);
        var sr2 = new StreamWriter(Application.persistentDataPath + "/" + logFileName);
        var outJson = JsonUtility.ToJson(log);
        sr2.WriteLine(outJson);
        sr2.Close();

    }

    public void StoreDifficultySettings()
    {
        results.enemyDamage = PlayerPrefs.GetFloat("enemyDamage");
        results.enemyNoticeRate = PlayerPrefs.GetFloat("enemyNoticeRate");
        results.enemyFireRate = PlayerPrefs.GetFloat("enemyFireRate");
        results.enemyMaxFireRate = PlayerPrefs.GetFloat("enemyMaxFireRate");
        results.enemyAimModifier = PlayerPrefs.GetFloat("enemyAimModifier");
        results.enemyHealth = PlayerPrefs.GetFloat("enemyHealth");
        results.enemySpawnRate = PlayerPrefs.GetFloat("enemySpawnRate");
        results.enemySpeed = PlayerPrefs.GetFloat("enemySpeed");

        results.graphicalTipsEnabled = PlayerPrefs.GetInt("graphicsEnabled");
        results.textualTipsEnabled = PlayerPrefs.GetInt("textEnabled");
        results.ddaEnabled = PlayerPrefs.GetInt("difficultyAdjustmentEnabled");
        results.movingEnabled = PlayerPrefs.GetInt("playerTrackingEnabled");
        results.headshotEnabled = PlayerPrefs.GetInt("playerHeadshotEnabled");
        results.accuracyEnabled = PlayerPrefs.GetInt("playerAccuracyEnabled");
        results.ttdEnabled = PlayerPrefs.GetInt("playerTtdEnabled");
        results.ttkEnabled = PlayerPrefs.GetInt("playerTtkEnabled");
        results.vcEnabled = PlayerPrefs.GetInt("playerVerticalCrosshairEnabled");
        results.hcEnabled = PlayerPrefs.GetInt("playerHorizontalCrosshairEnabled");
        results.missesEnabled = PlayerPrefs.GetInt("playerMissesEnabled");
        results.dsEnabled = PlayerPrefs.GetInt("playerDamageSourcesEnabled");

    }

    public void ConstructJsonToPrefs()
    {
        results.kills = noOfKills;
        results.timeElapsed = currentTimeElapsed;
        results.timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
        results.health = health;
        results = scoreManager.SetResults(results);
        StoreDifficultySettings();
        var levelShift = difficultyManager.DecideLevel(results);
        PlayerPrefs.SetInt("levelShift", levelShift);
        var lastLevel = PlayerPrefs.GetInt("overallLevel");
        Debug.Log(difficultyManager.gamerScore);
        Debug.Log(lastLevel);
        results.score = difficultyManager.gamerScore * lastLevel;
        results.level = lastLevel;
        LogResults(results);
        var json = JsonUtility.ToJson(results);
        PlayerPrefs.SetString("lastGame", json);
        difficultyManager.LogGame(results);
    }

    public void SetInitialPrefs()
    {
        if (!PlayerPrefs.HasKey("enemyNoticeRate"))
        {
            PlayerPrefs.SetFloat("enemyNoticeRate", enemyNoticeRate);
            PlayerPrefs.SetFloat("enemyDamage", enemyDamage);
            PlayerPrefs.SetFloat("enemyFireRate", enemyFireRate);
            PlayerPrefs.SetFloat("enemyMaxFireRate", enemyMaxFireRate);
            PlayerPrefs.SetFloat("enemyAimModifier", enemyAimModifier);
            PlayerPrefs.SetFloat("enemyHealth", enemyHealth);
            PlayerPrefs.SetFloat("enemySpawnRate", enemySpawnRate);
            PlayerPrefs.SetFloat("enemySpeed", enemySpeed);
        }

        enemyNoticeRate = PlayerPrefs.GetFloat("enemyNoticeRate");
        enemyDamage = PlayerPrefs.GetFloat("enemyDamage");
        enemyFireRate = PlayerPrefs.GetFloat("enemyFireRate");
        enemyMaxFireRate = PlayerPrefs.GetFloat("enemyMaxFireRate");
        enemyAimModifier = PlayerPrefs.GetFloat("enemyAimModifier");
        enemyHealth = PlayerPrefs.GetFloat("enemyHealth");
        enemySpawnRate = PlayerPrefs.GetFloat("enemySpawnRate");
        enemySpeed = PlayerPrefs.GetFloat("enemySpeed");


    }
    
    public bool CheckIfGameOver()
    {

        if (health < 1)
        {
            results.won = false;
            return true;
        }

        if (noOfKills >= winConValue)
        {
            results.won = true;
            return true;
        }

        return false;
    }
    
    public void SpawnEnemy(int count)
    {
        for (var i = 0; i < count; i++)
        {
            GameObject finalSpawn = null;
            
            // shuffle spawn list
            for (int j = 0; j < enemySpawns.Count; j++) {
                GameObject temp = enemySpawns[j];
                int randomIndex = Random.Range(j, enemySpawns.Count);
                enemySpawns[j] = enemySpawns[randomIndex];
                enemySpawns[randomIndex] = temp;
            }


            for (var j = 0; j < enemySpawns.Count; j++)
            {
                var spawn = enemySpawns[j];
                var position = spawn.transform.position;
                var origin = new Vector3(position.x, position.y + 4, position.z);
                var dir = (playerPrefab.transform.position - origin).normalized;
                RaycastHit hit;
                var cantSeePlayer = false;
                if (Physics.Raycast(origin, dir, out hit, Mathf.Infinity))
                {
                    if (!hit.collider.gameObject.CompareTag("Player"))
                    {
                        cantSeePlayer = true;
                    }
                }

                var tooCloseToExisting = false;

                for (int k = 0; k < currentEnemies.Count; k++)
                {
                    if (Vector3.Distance(spawn.transform.position, currentEnemies[k].transform.position) < 10f)
                    {
                        tooCloseToExisting = true;
                    }
                }
                
                if (cantSeePlayer && !tooCloseToExisting)
                {
                    finalSpawn = spawn;
                    break;
                }
            }

            if (finalSpawn != null)
            {
                var enemy = Instantiate(enemyToSpawn, finalSpawn.transform.position, finalSpawn.transform.rotation);
                enemy.GetComponent<EnemyManager>().SetConstants();
                currentEnemies.Add(enemy);
            }
        }
    }

    public void RemoveEnemy(GameObject enemy)
    {
        currentEnemies.Remove(enemy);
    }

    public float GetScore()
    {
        return scoreManager.GetScore();
    }
    
    public void AddHit()
    {
        noOfHits += 1;
    }

    public void AddKill()
    {
        noOfKills += 1;
    }

    public int GetNoKills()
    {
        return noOfKills;
    }
    
    public int GetNoHits()
    {
        return noOfHits;
    }

    public int GetHealth()
    {
        return health;
    }

    public float GetCurrentElapsedTime()
    {
        return currentTimeElapsed;
    }

    public void DealDamage(int damage)
    {
        health -= damage;
    }

    public void ReportTimeToDamage(float time, EnemyManager enemy)
    {
        scoreManager.timesToDamage.Add(time);
        learningEngine.ReportTimeToDamage(time, enemy);
    }
    

    public void ReportHealthLoss(float health, EnemyManager enemy)
    {
        scoreManager.healthLossPerEnemy.Add(health);
        learningEngine.ReportHealthLoss(enemy, (int) health);
    }

    public void ReportTimeToKill(float time, EnemyManager enemy)
    {
        scoreManager.timesToKill.Add(time);
        learningEngine.ReportTimeToKill(time, enemy);
    }

    public void ReportHitShot(bool headshot, EnemyManager enemy)
    {
        if (headshot)
        {
            scoreManager.headshots += 1;
            
        }
        learningEngine.ReportHeadshot(headshot, enemy);
        scoreManager.hitshots += 1;
    }

    public void ReportFiredShot()
    {
        scoreManager.firedshots += 1;
    }

    public void HealPlayer(float damage)
    {
        health += (int) Math.Round(damage * playerHealRate); // round this properly
    }

}