This class is attached to every fireable weapon in the game and allows for modifiable attributes such as
- Time to ADS (aim down sight)
- Weapon accuracy via hip-fire vs ADS
- Single fire vs Automatic
- Time between firing
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FireableWeapon : AbstractWeapon
{
[SerializeField] protected Transform originalPosition;
[SerializeField] protected Transform adsPosition;
private Transform currentBeginPosition;
[SerializeField] protected Transform bulletSpawn;
protected Transform weaponTransform;
[SerializeField] protected float adsSpeed;
[SerializeField] protected float force;
[SerializeField] protected float inaccuracyAmount;
[SerializeField] protected float inaccuracyAmountAiming;
[SerializeField] protected AudioSource reloadAudioSource;
[SerializeField] protected AudioSource dryFireAudioSource;
[SerializeField] protected AudioSource flipSwitchAudioSource;
[SerializeField] protected GameObject reticuleGO;
[SerializeField] protected Sprite reticuleSprite;
protected bool ads;
[SerializeField] protected int magazineSize;
[SerializeField] protected int bulletsLeftInMagazine;
[SerializeField] protected Enums.BulletType bulletType;
[SerializeField] protected List fireModes;
[SerializeField] protected Enums.FireMode activeFireMode;
[SerializeField] protected bool useInaccuracy;
[SerializeField] protected int numberOfProjecticles = 1;
[SerializeField] protected float meleeDistance;
[SerializeField] protected float meleeRadius;
[SerializeField] private SpritePool bulletHolePool;
protected bool triggerIsDepressed;
public GameObject muzzleFlash;
public Transform muzzleFlashLocation;
public void Start()
{
this.Initialize();
}
public void Awake()
{
this.Initialize();
}
public new void Update()
{
base.Update();
this.HandlePos();
}
public new void Initialize()
{
base.Initialize();
this.lastAttack = this.timeBetweenAttacks;
this.SetReticule();
this.GetWeaponPositions();
if (this.fireModes == null || this.fireModes.Count == 0)
{
Debug.Log("fireModes is null or empty.");
}
if (this.activeFireMode != Enums.FireMode.Single && this.fireModes.Count == 1)
{
this.activeFireMode = this.fireModes[0];
}
}
public override void Attack()
{
if (this.EnoughTimePassedSinceLastShot())
{
if (this.activeFireMode == Enums.FireMode.Single)
{
if (!this.triggerIsDepressed)
{
this.HandleSingleFire();
}
}
else if (this.activeFireMode == Enums.FireMode.Auto)
{
this.HandleSingleFire();
}
}
}
protected virtual void HandleSingleFire()
{
if (this.bulletsLeftInMagazine > 0)
{
this.FireHelper();
}
else if (!this.triggerIsDepressed)
{
this.dryFireAudioSource.Play();
}
}
private void FireHelper()
{
this.FireHelper2();
for(int i = 0; i < this.numberOfProjecticles; i++)
{
Vector3 forward = this.GetForwardVector(ads, this.useInaccuracy);
RaycastHit hit;
if (Physics.Raycast(this.bulletSpawn.position, forward, out hit))
{
//this.ApplyBulletHole(hit);
this.AddForceToRigidbody(hit);
this.CheckIfHittable(hit);
}
}
}
/**
* Get a bullet hole sprite from the object pool and place at location of hit, and rotation of the hit's normal.
* Attach to hit transform.
**/
private void ApplyBulletHole(RaycastHit hit)
{
if(this.bulletHolePool != null)
{
GameObject tempBulletHole = this.bulletHolePool.GetSprite(true, hit.point, Quaternion.FromToRotation(Vector3.up, hit.normal));
tempBulletHole.transform.parent = hit.transform;
}
}
private void FireHelper2()
{
this.animator.SetTrigger("Attack");
this.attackAudioSource.Play();
this.bulletsLeftInMagazine--;
this.lastAttack = 0f;
Destroy(Instantiate(this.muzzleFlash, this.muzzleFlashLocation.position, this.muzzleFlash.transform.rotation), 0.25f);
}
protected Vector3 GetForwardVector(bool ads, bool useInaccuracy)
{
Vector3 forward = transform.forward;
if(!useInaccuracy)
{
return forward;
}
if (this.ads)
{
forward.x += Random.Range(-inaccuracyAmountAiming, inaccuracyAmountAiming);
forward.y += Random.Range(-inaccuracyAmountAiming, inaccuracyAmountAiming);
forward.z += Random.Range(-inaccuracyAmountAiming, inaccuracyAmountAiming);
}
else
{
forward.x += Random.Range(-inaccuracyAmount, inaccuracyAmount);
forward.y += Random.Range(-inaccuracyAmount, inaccuracyAmount);
forward.z += Random.Range(-inaccuracyAmount, inaccuracyAmount);
}
return forward;
}
protected void AddForceToRigidbody(RaycastHit hit)
{
Rigidbody rbTemp = hit.rigidbody;
if (rbTemp != null)
{
rbTemp.AddForce(-hit.normal * this.force);
}
}
public override void AltAttack()
{
this.animator.SetTrigger("AltAttack");
Vector3 finalPoint = this.bulletSpawn.position + (this.bulletSpawn.forward * this.meleeDistance);
bool playAudio = false;
Collider[] toHit = Physics.OverlapSphere(finalPoint, this.meleeRadius);
foreach (Collider obj in toHit)
{
Vector3 direction = obj.transform.position - this.bulletSpawn.position;
RaycastHit hit;
if (Physics.Raycast(this.bulletSpawn.position, direction, out hit))
{
playAudio = true;
this.AddForceToRigidbody(hit);
this.CheckIfHittable(hit);
}
}
if(playAudio)
{
this.altAttackAudioSource.Play();
}
}
void SetReticule()
{
this.reticuleGO = GameObject.Find("Reticule");
if (this.reticuleGO == null)
{
Debug.LogError("reticuleGO is null.");
}
}
void GetWeaponPositions()
{
this.weaponTransform = this.gameObject.transform.Find("Weapon");
if (this.weaponTransform == null)
{
Debug.Log("weaponTransform is null.");
}
this.originalPosition = this.gameObject.transform.Find("OriginalPosition");
if (this.originalPosition == null)
{
Debug.Log("originalPosition is null.");
}
this.adsPosition = this.gameObject.transform.Find("ADSPosition");
if (this.adsPosition == null)
{
Debug.Log("adsPosition is null.");
}
this.bulletSpawn = this.gameObject.transform.parent.Find("BulletSpawn");
if (this.bulletSpawn == null)
{
Debug.Log("bulletSpawn is null.");
}
this.currentBeginPosition = this.originalPosition;
}
public void Reload()
{
this.reloadAudioSource.Play();
if (this.animator != null)
{
this.animator.SetTrigger("Reload");
}
}
public void SetADS(bool ads)
{
this.ads = ads;
//this.animator.SetBool("ADS", this.ads);
if (this.ads)
{
this.currentBeginPosition = this.adsPosition;
this.reticuleGO.SetActive(false);
}
else
{
this.currentBeginPosition = this.originalPosition;
this.reticuleGO.SetActive(true);
}
}
public void SetTriggerIsDepressed(bool triggerIsDepressed)
{
this.triggerIsDepressed = triggerIsDepressed;
}
public void IncrementFireMode()
{
if (this.fireModes.Count > 1)
{
int index = this.fireModes.IndexOf(this.activeFireMode);
this.activeFireMode = this.fireModes[++index % this.fireModes.Count];
this.animator.SetTrigger("FlipSwitch");
this.flipSwitchAudioSource.Play();
}
}
public bool EnoughTimePassedSinceLastShot()
{
return this.lastAttack >= this.timeBetweenAttacks;
}
protected void CheckIfHittable(RaycastHit hit)
{
Hittable hittable = Utility.CheckForInSelfAndParents(hit.collider.gameObject);
if (hittable != null)
{
hittable.GetHit(hit, this.damage);
}
}
void HandlePos()
{
Vector3 newPos;
float step = this.adsSpeed * Time.deltaTime;
newPos = this.currentBeginPosition.localPosition;
weaponTransform.localPosition = Vector3.MoveTowards(weaponTransform.localPosition, newPos, step);
}
public int GetMagazineSize()
{
return this.magazineSize;
}
public int GetBulletsLeftInMagazine()
{
return this.bulletsLeftInMagazine;
}
public void SetBulletsLeftInMagazine(int bulletsLeftInMagazine)
{
this.bulletsLeftInMagazine = bulletsLeftInMagazine;
this.Reload();
}
public Enums.BulletType GetBulletType()
{
return this.bulletType;
}
}