<repo_name>AjdinGaco/3DGameFinalProject<file_sep>/README.md
# 3DGameFinalProject
Ajdin 3DGame final project
<file_sep>/Assets/Scripts/EnemyAi.cs
﻿using System.Collections;
using System.Collections.Generic;
using System.Threading;
using UnityEditor;
using UnityEngine;

public class EnemyAi : MonoBehaviour
{
    public GameObject enemyHead;
    public GameObject enemyBullet;
    public GameObject bulletspawnplace;
    public GameObject targeter;
    public string tagToTarget = "Player";
    public float detectionRange = 20f;
    public float dmgBullet = 10f;
    public float speedBullet = 100f;
    public float cooldownShoot = 1f;
    public float aimSpeed = 10f;
    private bool canShoot = true;
    private bool TagWithinRange;

    private GameObject tagTarget;


    public AudioSource shootingEffect;

    private void FixedUpdate()

    {
        CheckForNearbyTag();
    }
    void CheckForNearbyTag()
    {
        GameObject[] plist = GameObject.FindGameObjectsWithTag(tagToTarget);
        TagWithinRange = false;
        foreach (GameObject item in plist)
        {
            if (Vector3.Distance(this.transform.position, item.transform.position) < detectionRange)
            {
                TagWithinRange = true;
                tagTarget = item;
            }
        }
    }
    void AimAtTag()
    {
        if (tagTarget != null)
        {
            targeter.transform.LookAt(tagTarget.transform.position);
            float step = aimSpeed * Time.deltaTime;

            enemyHead.transform.rotation = Quaternion.RotateTowards(enemyHead.transform.rotation, targeter.transform.rotation, step);
        }
    }
    bool CanHitTag()
    {
        RaycastHit hit;
        if (Physics.Raycast(enemyHead.transform.position, enemyHead.transform.forward, out hit, detectionRange * 1.2f))
        {
            if (hit.transform.tag == tagToTarget)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        else
        {
            return false;
        }

    }
    // Update is called once per frame
    void Shoot()
    {
        GameObject Shot = (GameObject)Instantiate(enemyBullet, bulletspawnplace.transform.position, bulletspawnplace.transform.rotation);
        //Here i will adjust the dmg the shot does based on the charge
        Damage shotdamage = Shot.GetComponent<Damage>();
        BulletLogic shotlogic = Shot.GetComponent<BulletLogic>();
        shotdamage.damageAmount = dmgBullet;
        shotlogic.m_Speed = speedBullet;
        canShoot = false;
        cooldowntimer = cooldownShoot;

        shootingEffect.GetComponent<AudioSource>().Play();
    }
    private float cooldowntimer;
    void ShootCooldown()
    {
        cooldowntimer -= Time.deltaTime;
        if (cooldowntimer < 0)
        {
            canShoot = true;
        }
    }
    void Update()
    {
        if (TagWithinRange)
        {
            AimAtTag();
        }
        if (CanHitTag() && canShoot)
        {
            Shoot();
        }
        if (!canShoot)
        {
            ShootCooldown();
        }

    }
}
<file_sep>/Assets/Scripts/BulletLogic.cs
﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BulletLogic : MonoBehaviour
{
    public float m_Speed = 10f;   // this is the projectile's speed
    public float m_Lifespan = 3f; // this is the projectile's lifespan (in seconds)
    public float accel = 1f;
    public float StormtrooperVariable = 0;



    private Rigidbody m_Rigidbody;
    void Awake()
    {
        m_Rigidbody = GetComponent<Rigidbody>();
    }
    void Start()
    {
        Vector3 posoffset = new Vector3(Random.Range(-StormtrooperVariable, StormtrooperVariable), 0, Random.Range(-StormtrooperVariable, StormtrooperVariable));
        m_Rigidbody.AddForce((m_Rigidbody.transform.forward + posoffset) * m_Speed);
        if (gameObject.name.Contains("(Clone)"))
        {
            //If this is a clone then it must DIE!
            Destroy(gameObject, m_Lifespan);
        }
        else
        {

        }
    }
    private void Update()
    {
        m_Rigidbody.AddForce(m_Rigidbody.transform.forward * accel * Time.deltaTime);
    }
}
<file_sep>/Assets/Scripts/MenuItem.cs
﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class MenuItem : MonoBehaviour
{
    public string LeveltoLoadOnPress;
    // Start is called before the first frame update
    void Start()
    {
        this.GetComponent<Renderer>().material.color = Color.black;
    }

    void OnMouseEnter()
    {
        this.GetComponent<Renderer>().material.color = Color.red;
    }

    void OnMouseExit()
    {
        this.GetComponent<Renderer>().material.color = Color.black;
    }
    private void OnMouseDown()
    {
        SceneManager.LoadScene(LeveltoLoadOnPress.ToString());
    }
}
<file_sep>/Assets/Scripts/PlayerController.cs
﻿using System.Collections;
using System.Collections.Generic;
using UnityEditorInternal;
using UnityEngine;

public class PlayerController : MonoBehaviour
{
    public Transform playerHead;
    public Rigidbody playerBody;
    public float moveSpeed = 1000f;
    public float maxspeed = 100f;
    public float CameraSpeed = 3f;

    public bool grouded = false;
    //Jumping vars
    private bool jumping = false;
    private bool jumpReady = true;
    private float jumpCooldown = 0.20f;
    public float jumpforce = 100f;

    public KeyCode ControlForward = KeyCode.Z, ControlBack = KeyCode.S, ControlRight = KeyCode.D, ControlLeft = KeyCode.Q, ControlJump = KeyCode.Space;
    private bool noinput = false;
    private int CX = 0, CY = 0;

    void Start()
    {
        Cursor.lockState = CursorLockMode.Locked;
        Cursor.visible = false;
    }

    // Update is called once per frame
    void Update()
    {
        ReadController();
        CameraLook();
        Movement();
    }




    Vector2 rotation = new Vector2(0, 0);
    private void CameraLook()
    {
        rotation.y += Input.GetAxis("Mouse X");
        rotation.x += -Input.GetAxis("Mouse Y");
        playerHead.transform.eulerAngles = (Vector2)rotation * CameraSpeed;

        //WILL FIX LATER? GAVE UP DUE TO MY OWN LAZYNESS
        playerBody.angularVelocity = new Vector3(0, 0, 0);
        playerBody.transform.rotation = Quaternion.Euler(0, rotation.y * CameraSpeed, 0);

    }
    private void ReadController()
    {
        if (Input.GetKey(ControlForward) && !Input.GetKey(ControlBack))
            CY = 1;
        else if (!Input.GetKey(ControlForward) && Input.GetKey(ControlBack))
            CY = -1;
        else
            CY = 0;

        if (Input.GetKey(ControlLeft) && !Input.GetKey(ControlRight))
            CX = -1;
        else if (!Input.GetKey(ControlLeft) && Input.GetKey(ControlRight))
            CX = 1;
        else
            CX = 0;
        if (Input.GetKeyDown(ControlJump))
            jumping = true;
        else
            jumping = false;

        if (CX == 0 && CY == 0 && !jumping)
            noinput = true;
        else
            noinput = false;
    }
    private void Movement()
    {
        //Better gravity
        playerBody.AddForce(Vector3.down * Time.deltaTime * 10);

        ContraMovement();

        if (jumping && grouded)
            Jump();

        float multiplier = 1;

        if (!grouded)
            multiplier = 0.5f;
        playerBody.AddForce(playerBody.transform.forward * CY * moveSpeed * Time.deltaTime * multiplier);
        playerBody.AddForce(playerBody.transform.right * CX * moveSpeed * Time.deltaTime * multiplier);
    }

    public Vector3 GetVelocity()
    {
        return playerBody.velocity;
    }
    private void ContraMovement()
    {
        if (noinput && grouded)
        {
            playerBody.velocity = playerBody.velocity * 0.9f;
        }

        if (playerBody.velocity.y > 0 && CY < 0)
            playerBody.AddForce(playerBody.transform.forward * Time.deltaTime * CY * 0.5f);
        if (playerBody.velocity.y < 0 && CY > 0)
            playerBody.AddForce(playerBody.transform.forward * Time.deltaTime * CY * 0.5f);

        if (playerBody.velocity.x > 0 && CX < 0)
            playerBody.AddForce(playerBody.transform.right * Time.deltaTime * CX * 0.5f);
        if (playerBody.velocity.x < 0 && CX > 0)
            playerBody.AddForce(playerBody.transform.right * Time.deltaTime * CX * 0.5f);

    }

    private void Jump()
    {
        if (jumpReady && grouded)
        {
            jumpReady = false;
            playerBody.AddForce(Vector2.up * jumpforce * 2f);
            // make it a bit smoother
            playerBody.AddForce(Vector2.up * jumpforce);


            Invoke(nameof(ResetJump), jumpCooldown);
        }
    }
    private void ResetJump()
    {
        jumpReady = true;
    }

    public void AddForce(Vector3 AddedForce)
    {
        playerBody.AddForce(AddedForce);
    }

    private void OnCollisionEnter(Collision collision)
    {
        if (collision.gameObject.tag == "Floor")
            grouded = true;
    }
    private void OnCollisionExit(Collision collision)
    {
        if (collision.gameObject.tag == "Floor")
            grouded = false;

    }
}
<file_sep>/Assets/Scripts/GunControll.cs
﻿using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEditorInternal;
using UnityEngine;

public class GunControll : MonoBehaviour
{
    //This gun has both the functions of an grapling and and chargeable gun :D
    public GameObject playerCam;
    public GameObject playerBody;
    public GameObject playerGun; // For turning it and stuff
    public float maxGrapleDis = 10f;
    public string tagForGrapplable = "AbleToGrapTo";

    public Transform gunPoint;
    private SpringJoint grapjoint;

    public LineRenderer grapRope;
    private Vector3 grappleEndpoint;

    //Gun Setttings
    private float charge = 0f;
    public float chargeSpeed = 1f;
    public float chargeMax = 10f;
    public float chargeStartScale = 1f;
    public float chargeToScaleRation = 1f;
    public float chargeToDamage = 1f;
    public float chargedShotSpeed = 10;
    public float chargeToKnockBackValue = 100f;
    public GameObject projectile;

    public GameObject graplingHitPrefab;
    public AudioSource chargingSoundEffect;
    public AudioSource shootingSoundEffect;

    public bool canGrapple;


    private bool fireGrapple = false, chargeShot = false;
    public float GetChargePercentage()
    {
        return (charge / chargeMax);
    }
    void Update()
    {
        canGrapple = CheckIfCanGrapple();
        MouseInput();
        GunControl();
        DrawRope();
    }
    void GunControl()
    {
        if (fireGrapple)
            GraplingFire();
        else
        {
            ResetLookGun();
            GraplingStop();
        }
        if (chargeShot)
            ChargeShot();
        else if (charge > 0) // That means there is a shot ready to fire
        {
            ShootChargedShot();
        }


    }

    private void ChargeShot()
    {
        if (charge == 0)
        {
            chargingSoundEffect.GetComponent<AudioSource>().Play();
        }
        if (charge < chargeMax)
        {
            charge += chargeSpeed * Time.deltaTime;
        }
        else
        {
            chargingSoundEffect.GetComponent<AudioSource>().Stop();
        }
            
        
    }
    private void ShootChargedShot()
    {
        GameObject Shot = (GameObject)Instantiate(projectile, gunPoint.position, gunPoint.rotation);
        //Here i will adjust the dmg the shot does based on the charge

        Damage shotdamage = Shot.GetComponent<Damage>();
        BulletLogic shotlogic = Shot.GetComponent<BulletLogic>();
        shotdamage.damageAmount = charge * chargeToDamage;
        Shot.transform.localScale = Shot.transform.localScale * (chargeStartScale + charge) * chargeToScaleRation;
        shotlogic.m_Speed = chargedShotSpeed;

        playerBody.GetComponent<PlayerController>().AddForce(-playerCam.transform.forward * charge * chargeToKnockBackValue); // KnockBaco

        chargingSoundEffect.GetComponent<AudioSource>().Stop();
        shootingSoundEffect.GetComponent<AudioSource>().Play();
        charge = 0f;

    }

    public bool CheckIfCanGrapple() // This is mostly meant for the Hud
    {
        RaycastHit hit;
        if (Physics.Raycast(playerCam.transform.position, playerCam.transform.forward, out hit, maxGrapleDis))
        {
            if (hit.transform.gameObject.tag == tagForGrapplable && !playerBody.GetComponent<SpringJoint>())
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        else
        {
            return false;
        }
    }

    private RaycastHit lastHit;
    void GraplingFire()
    {
        RaycastHit hit;
        if (Physics.Raycast(playerCam.transform.position, playerCam.transform.forward, out hit, maxGrapleDis))
        {
            if (hit.transform.gameObject.tag == tagForGrapplable && !playerBody.GetComponent<SpringJoint>())
            {
                lastHit = hit;
                grappleEndpoint = hit.point;
                grapjoint = playerBody.gameObject.AddComponent<SpringJoint>();
                grapjoint.autoConfigureConnectedAnchor = false;
                grapjoint.connectedAnchor = hit.point;
                float distance = Vector3.Distance(playerBody.transform.position, hit.point);
                grapjoint.maxDistance = distance * 0.8f;
                grapjoint.minDistance = 0;

                grapjoint.spring = 1f;
                grapjoint.damper = 5f;
                grapjoint.massScale = 4.5f;

                //Enable the rope thing to work
                grapRope.positionCount = 2;

                // Hit Effect
                Instantiate(graplingHitPrefab, gunPoint.position, gunPoint.rotation);

            }
            else if (playerBody.GetComponent<SpringJoint>())
            {
                //Lenght Adjust so it feels a bit better
                float distance = Vector3.Distance(playerBody.transform.position, lastHit.point);
                if (distance < grapjoint.maxDistance)
                {
                    grapjoint.maxDistance = distance * 0.9f;
                }
                grapjoint.minDistance = 0;
            }
        }
    }
    void GraplingStop()
    {
        if (playerBody.GetComponent<SpringJoint>())
        {
            grapRope.positionCount = 0;
            Destroy(grapjoint);
        }


    }
    void ResetLookGun()
    {
        playerGun.transform.localRotation = Quaternion.Euler(0, 0, 0);
    }

    private Vector3 grappledPos;

    void DrawRope()
    {
        if (grapjoint && grapRope.positionCount > 0)
        {
            grappledPos = Vector3.Lerp(grappledPos, grappleEndpoint, Time.deltaTime * 8f);
            grapRope.SetPosition(0, gunPoint.position);
            grapRope.SetPosition(1, grappledPos);
        }
    }
    void MouseInput()
    {
        if (Input.GetMouseButton(0))
            fireGrapple = true;
        else
            fireGrapple = false;
        if (Input.GetMouseButton(1))
            chargeShot = true;
        else
            chargeShot = false;
    }
}
<file_sep>/Assets/Scripts/ParticleControll.cs
﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ParticleControll : MonoBehaviour
{

    // This is mostly for controlling the particles of the player, depending on varius things. This is only meant o make it looks a bit fancier :D

    private ParticleSystem playerParticles;
    private PlayerController playerControl;
    private void Start()
    {
        playerParticles = this.GetComponent<ParticleSystem>();
        playerControl = this.GetComponent<PlayerController>();
    }

    //= playerControl.GetVelocity().x + playerControl.GetVelocity().y;
    void Update()
    {
        if (!playerControl.grouded)
        {
            playerParticles.enableEmission = true;
            playerParticles.emissionRate = 5f + playerControl.GetVelocity().x + playerControl.GetVelocity().y;
        }
        else
        {
            playerParticles.enableEmission = false;
        }
    }
}
<file_sep>/Assets/Scripts/HudController.cs
﻿using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.UI;

public class HudController : MonoBehaviour
{
    public GameObject player;
    public GameObject cursor;
    public RectTransform chargeRect; // This is the Rect Tranform of the charge meter
    public RectTransform hpRect; // This is the Rect Tranform of the HP meter
    public Text livesText;
    //Due to my inability to work with children i have taken the easy route to just manualy select them


    private GunControll playerguncontroll;

    // Start is called before the first frame update
    void Start()
    {
        if (player == null)
        {
            GameObject[] plist = GameObject.FindGameObjectsWithTag("Player");
            player = plist[0];

        }
        playerguncontroll = player.GetComponent<GunControll>();
    }

    // Update is called once per frame
    void Update()
    {
        UpdateWeaponCharge();
        UpdatePlayerHPandLives();
        UpdateCursor();
    }


    void UpdateCursor()
    {
        // This changes the cursor color depending if the target can be grappled
        if (playerguncontroll.CheckIfCanGrapple())
            cursor.GetComponent<Image>().color = new Color32(0, 255, 0, 100);
        else
            cursor.GetComponent<Image>().color = new Color32(255, 255, 225, 50);
    }
    void UpdateWeaponCharge()
    {
        float chargepercentage = playerguncontroll.GetChargePercentage() * 100;
        float num = chargeRect.transform.parent.gameObject.GetComponent<RectTransform>().sizeDelta.y / 2;
        chargeRect.transform.localPosition = new Vector3(0, -num + (chargepercentage * (num / 100)), 0);
        chargeRect.sizeDelta = new Vector2(20f, chargepercentage);
    }

    void UpdatePlayerHPandLives()
    {
        float chargepercentage = player.GetComponent<Health>().healthPoints / player.GetComponent<Health>().respawnHealthPoints * 100;
        float num = hpRect.transform.parent.gameObject.GetComponent<RectTransform>().sizeDelta.y / 2;

        hpRect.transform.localPosition = new Vector3(0, num - (chargepercentage * (num / 100)), 0);
        hpRect.sizeDelta = new Vector2(20f, chargepercentage * 2);


        livesText.text = player.GetComponent<Health>().numberOfLives.ToString();
    }
}
<file_sep>/Assets/Scripts/Goal.cs
﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class Goal : MonoBehaviour
{
    public string LeveltoLoadOnPress;

    private void Start()
    {
        if (LeveltoLoadOnPress == null)
        {
            LeveltoLoadOnPress = Application.loadedLevelName;
        }

    }
    private void OnTriggerEnter(Collider other)
    {
        if (other.gameObject.tag == "Player")
        {
            print("Level Completed");
            SceneManager.LoadScene(LeveltoLoadOnPress.ToString());
        }
    }
}
