Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using UnityEngine;
- using System.Collections;
- using System.Collections.Generic;
- public class Gun : MonoBehaviour {
- // Dependiences
- public GameObject bulletHolePrefab;
- public ParticleSystem muzzleFlash;
- public Transform muzzle;
- public Transform weaponModel;
- private Camera weaponCamera;
- // Properties of the gun
- public float damage;
- public int rateOfFire;
- public float maxVerticalRecoil;
- public float verticalRecoilStep;
- public float maxHorizontalRecoil;
- public float horizontalRecoilStep;
- public int magCapacity;
- public int maxAmmo;
- public float reloadingTime;
- public AudioClip shootAudio;
- public Vector3 hipPos;
- public Vector3 sightedPos;
- private Transform playerCamera;
- private float fireCooldown;
- private float fireInterval;
- private List<GameObject> bulletHolesList;
- [HideInInspector]
- public int ammoInMag;
- [HideInInspector]
- public int ammoLeft;
- public float verticalRecoil;
- public float horizontalRecoil;
- private float recoilCooldown;
- private bool isReloading = false;
- void Awake()
- {
- // set the right camera and move the weapon to hip pos
- weaponCamera = transform.parent.GetComponent<Camera>();
- weaponModel.localPosition = hipPos;
- playerCamera = transform.parent;
- //calculate the interval between shots to match the rate of fire
- if (rateOfFire > 1)
- fireInterval = 1f / (rateOfFire / 60);
- else
- fireInterval = 0.1f;
- // update the UI and set all the ammo to right values
- UIUpdate();
- ammoInMag = magCapacity;
- ammoLeft = 0;
- // zero out the recoil and cooldowns
- fireCooldown = 0;
- recoilCooldown = 0;
- }
- void Update () {
- //right click = zoom and sighted position, otherwise hip pos
- if(Input.GetKey(KeyCode.Mouse1))
- SightAim();
- else
- HipAim();
- //lmb = tries to fire, if weapon is automatic then fires automaticaly
- if (Input.GetButton("Fire1") && rateOfFire > 1)
- {
- TryToFire();
- }
- else if(Input.GetButtonDown("Fire1"))
- {
- TryToFire();
- }
- //r = reloads
- if(Input.GetKeyDown(KeyCode.R))
- {
- StartCoroutine(Reload());
- }
- //descreases fire cooldown as time passes, manages the right rate of fire
- if(fireCooldown > 0)
- {
- fireCooldown -= Time.deltaTime;
- }
- //calculates the recoil descrease
- RecoilChecks();
- }
- void RecoilChecks()
- {
- //the recoil value always decreases
- if (recoilCooldown > 0)
- recoilCooldown -= Time.deltaTime;
- //in case of recoil being lower than 0 it goes to zero
- if (recoilCooldown < 0)
- recoilCooldown = 0;
- //if you haven't shot in a while and there is vrecoil, decrease it
- if (verticalRecoil > 0 && recoilCooldown == 0)
- verticalRecoil -= (Time.deltaTime / 10f);
- //in case of recoil being lower than 0 it goes to zero
- if (verticalRecoil < 0)
- verticalRecoil = 0;
- //if you haven't shot in a while and there is hrecoil, decrease it
- if (horizontalRecoil != 0 && recoilCooldown == 0)
- {
- if(horizontalRecoil > 0)
- horizontalRecoil -= (Time.deltaTime / 10f);
- else
- horizontalRecoil += (Time.deltaTime / 10f);
- }
- //if the hrecoil is very close to 0, set it to 0
- if (Mathf.Abs(horizontalRecoil) < 0.001f)
- horizontalRecoil = 0;
- //try to bring the weapon to 0,0,0 (remove the visual recoil)
- if (transform.localRotation != Quaternion.Euler(Vector3.zero))
- transform.localRotation = Quaternion.Slerp(transform.localRotation, Quaternion.Euler(Vector3.zero), Time.deltaTime * 2);
- }
- void TryToFire()
- {
- //if the weapon is semi automatic or the fire cooldown is zero AND there is any ammo, fire
- if ((fireCooldown <= 0 || rateOfFire == 1) && ammoInMag > 0 && !isReloading)
- {
- //fire, decrease ammo in mag, add fire cooldown and update the UI
- Fire();
- ammoInMag--;
- fireCooldown += fireInterval;
- UIUpdate();
- }
- }
- void Fire()
- {
- //calculate the shot direction including the recoil
- Vector3 dir = playerCamera.forward + new Vector3(0, verticalRecoil, 0) + (playerCamera.right * horizontalRecoil);
- //the direction of the shot is the forward vector modified by the recoil
- Ray ray = new Ray(playerCamera.position, dir);
- RaycastHit hit;
- //play the fire sound and instantiate the particle system
- GetComponent<AudioSource>().PlayOneShot(shootAudio, 0.5f);
- Instantiate(muzzleFlash, muzzle.position, muzzle.rotation, muzzle);
- //[DEBUG] draw the ray in the preview
- Debug.DrawRay(playerCamera.position, playerCamera.forward * 100, Color.cyan);
- //if the raycast hit anything
- if (Physics.Raycast(ray, out hit, 100f))
- {
- //[DEBUG] draw a line between the player and hit point
- Debug.DrawLine(playerCamera.position, hit.point, Color.red);
- //instantiate a bullet hole and inflict weapon's damage on the hit target
- Instantiate(bulletHolePrefab, hit.point, Quaternion.FromToRotation(Vector3.up, hit.normal), hit.transform);
- DealDamage(hit);
- }
- //recoil using the firing direction
- Recoil(dir);
- }
- void DealDamage(RaycastHit hit)
- {
- //if we hit the enemy, damage it
- if(hit.transform.CompareTag("Enemy"))
- {
- hit.transform.SendMessage("TakeDamage", damage, SendMessageOptions.DontRequireReceiver);
- }
- }
- IEnumerator Reload()
- {
- //cant do few reloads at the same time
- if (isReloading || ammoInMag == magCapacity)
- yield break;
- //calculate the ammo needed to fill the mag
- int ammoNeeded = magCapacity - ammoInMag;
- //reloading takes a while
- isReloading = true;
- StartCoroutine(UIManager.instance.Reloading(reloadingTime));
- yield return new WaitForSeconds(reloadingTime);
- isReloading = false;
- //if we have more ammo than needed fill the mag and subtract ammo needed
- if(ammoLeft >= ammoNeeded)
- {
- ammoInMag = magCapacity;
- ammoLeft -= ammoNeeded;
- }
- else
- {
- // otherwise add all the ammo to the mag and zero the leftover ammo
- ammoInMag += ammoLeft;
- ammoLeft = 0;
- }
- //update the UI
- UIUpdate();
- }
- //in case reload is stopped by switching slots
- public void CancelReload()
- {
- StopCoroutine(Reload());
- isReloading = false;
- }
- void Recoil(Vector3 dir)
- {
- //recoil won't decrease until player hasn't shot for the next interval
- recoilCooldown += fireInterval;
- //if the vrecoil is below maximum, add more
- if(verticalRecoil <= maxVerticalRecoil)
- {
- verticalRecoil += verticalRecoilStep;
- }
- else
- {
- //otherwise set it to maximum
- verticalRecoil = maxVerticalRecoil;
- }
- //if the hrecoil is below maximum, add more
- if (Mathf.Abs(horizontalRecoil) <= maxHorizontalRecoil)
- {
- //the hrecoil is random, but in the range of the step
- float randomRecoil = Random.Range(-horizontalRecoilStep, horizontalRecoilStep);
- horizontalRecoil += randomRecoil;
- }
- else
- {
- //otherwise set it to maximum
- horizontalRecoil = maxHorizontalRecoil;
- }
- //play the firing animation and make the model look in the firing direction
- GetComponent<Animator>().SetTrigger("Fire");
- transform.rotation = Quaternion.LookRotation(dir, Vector3.up);
- }
- public void UIUpdate()
- {
- //update the ammo UI
- UIManager.instance.UpdateAmmoUI(ammoInMag, ammoLeft);
- }
- public void RefillAmmo(int amount)
- {
- //if you want to refill more ammo than you can carry, max it out, otherwise just add it
- if (ammoLeft + amount <= maxAmmo)
- ammoLeft += amount;
- else
- ammoLeft = maxAmmo;
- //update the ammo UI
- UIUpdate();
- }
- //aim through the sights
- void SightAim()
- {
- //decrease the fov for better visibility
- weaponCamera.fieldOfView = 20;
- //smoothly transform to sightpos
- if (Vector3.Distance(weaponModel.localPosition, sightedPos) <= 0.001f)
- weaponModel.localPosition = sightedPos;
- else
- weaponModel.localPosition = Vector3.Lerp(weaponModel.localPosition, sightedPos, Time.deltaTime * 10);
- }
- void HipAim()
- {
- //inscrease the fov for normal view
- weaponCamera.fieldOfView = 50;
- //smoothly transform to hippos
- if (Vector3.Distance(weaponModel.localPosition, hipPos) <= 0.001f)
- weaponModel.localPosition = hipPos;
- else
- weaponModel.localPosition = Vector3.Lerp(weaponModel.localPosition, hipPos, Time.deltaTime * 10);
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement