using System.Collections;
using UnityEngine;
using TMPro;
public class ModularGun : MonoBehaviour
{
public enum FireMode { SemiAuto, Burst, FullAuto }
[Header("Gun Settings")]
public float damage = 10f;
public float range = 100f;
public float fireRate = 15f;
public float impactForce = 30f;
[Header("Ammo Settings")]
public int maxAmmo = 10;
private int currentAmmo;
public float reloadTime = 1f;
private bool isReloading = false;
[Header("Spread & Multi-Bullet")]
public float spread = 0.05f;
public int bulletsPerShot = 1;
[Header("Fire Mode")]
public FireMode fireMode = FireMode.FullAuto;
public int burstCount = 3;
[Header("Effects & Layers")]
public LayerMask WhatIsEnemy;
public GameObject enemyImpactEffect;
public GameObject defaultImpactEffect;
private int ignorePlayerMask;
[Header("Headshot Settings")]
public float headshotMultiplier = 2.0f;
public string headTag = "Head";
[Header("References")]
public Camera fpsCamera;
public Animator holderAnimator;
public Animator weaponAnimator;
public TextMeshProUGUI ammotext;
public CamRecoil recoil;
public PlayerMovement playermovement;
public ShootEffect effect;
public Animator crosshairAnim;
public PlayerUpgrades upgrades;
public Blood blood;
public ScreenEffectsController screenEffectsController;
private float nextTimeToFire = 0f;
private bool isShooting = false;
void Start()
{
upgrades = GameObject.FindGameObjectWithTag("Upgrades").GetComponent<PlayerUpgrades>();
ignorePlayerMask = ~LayerMask.GetMask("Player");
if (upgrades.extraAmmoPerReload)
maxAmmo += (int)(maxAmmo / 3f);
if (upgrades.improvedAccuracy)
spread += spread / 3f;
if (upgrades.highRishHighReward)
damage *= 2f;
currentAmmo = maxAmmo;
}
void OnEnable()
{
isReloading = false;
if (holderAnimator != null)
holderAnimator.SetBool("IsReloading", false);
}
void Update()
{
if (isReloading) return;
ammotext.SetText(currentAmmo.ToString());
if (currentAmmo <= 0 || (Input.GetKey(KeyCode.R) && currentAmmo != maxAmmo))
{
StartCoroutine(Reload());
return;
}
HandleFireInput();
UpdateRunningAnimation();
}
void HandleFireInput()
{
if (fireMode == FireMode.FullAuto && Input.GetButton("Fire1") && Time.time >= nextTimeToFire)
{
nextTimeToFire = Time.time + 1f / fireRate;
Shoot();
}
else if (fireMode == FireMode.SemiAuto && Input.GetButtonDown("Fire1") && Time.time >= nextTimeToFire)
{
nextTimeToFire = Time.time + 1f / fireRate;
Shoot();
}
else if (fireMode == FireMode.Burst && Input.GetButtonDown("Fire1") && !isShooting)
{
StartCoroutine(BurstFire());
}
}
void UpdateRunningAnimation()
{
if (!isReloading)
{
bool isWalking = playermovement.state == PlayerMovement.MovementState.walking;
bool isMoving = Input.GetAxisRaw("Horizontal") != 0 || Input.GetAxisRaw("Vertical") != 0;
holderAnimator.SetBool("Running", isWalking && isMoving);
}
}
IEnumerator Reload()
{
crosshairAnim.SetBool("Reloading", true);
isReloading = true;
if (holderAnimator != null)
holderAnimator.SetBool("IsReloading", true);
yield return new WaitForSeconds(reloadTime * upgrades.reloadSpeedMultiplier - 0.25f);
if (holderAnimator != null)
holderAnimator.SetBool("IsReloading", false);
yield return new WaitForSeconds(0.25f);
currentAmmo = maxAmmo;
crosshairAnim.SetBool("Reloading", false);
isReloading = false;
}
void Shoot()
{
if (currentAmmo <= 0) return;
weaponAnimator.Play(weaponAnimator.gameObject.name + "Shoot", -1, 0f);
crosshairAnim.Play("CrosshairShoot", -1, 0f);
recoil.Fire();
currentAmmo--;
StartCoroutine(effect.Flash());
screenEffectsController.PulseChromatic(1.0f, 0.2f);
screenEffectsController.PulseBloom(10f, 0.1f);
screenEffectsController.DesaturationFlash(0.1f);
screenEffectsController.LensPunch(-0.5f, 0.15f);
for (int i = 0; i < bulletsPerShot; i++)
{
Vector3 direction = (fpsCamera.transform.forward + new Vector3(
Random.Range(-spread, spread),
Random.Range(-spread, spread),
Random.Range(-spread, spread)
)).normalized;
RaycastHit hit;
if (Physics.Raycast(fpsCamera.transform.position, direction, out hit, range, ignorePlayerMask))
{
Debug.DrawRay(fpsCamera.transform.position + fpsCamera.transform.forward * 0.7f, direction * range, Color.red, 1.5f);
Debug.Log($"Raycast hit: {hit.transform.name}");
float finalDamage = damage;
Target enemyTarget = hit.transform.GetComponentInParent<Target>();
if (enemyTarget != null)
{
if (hit.collider.CompareTag(headTag))
{
finalDamage *= headshotMultiplier;
blood.GainBlood(30);
Debug.Log("HEADSHOT! Damage: " + finalDamage);
}
if (currentAmmo == maxAmmo - 1 && upgrades.extraFirstBulletDamage)
{
finalDamage = 150;
}
enemyTarget.TakeDamage(finalDamage);
}
if (hit.rigidbody != null)
{
hit.rigidbody.AddForce(-hit.normal * impactForce);
}
GameObject impactPrefab = ((WhatIsEnemy & (1 << hit.transform.gameObject.layer)) != 0) ? enemyImpactEffect : defaultImpactEffect;
GameObject impactGO = Instantiate(impactPrefab, hit.point, Quaternion.LookRotation(hit.normal));
Destroy(impactGO, 2f);
}
}
}
IEnumerator BurstFire()
{
isShooting = true;
for (int i = 0; i < burstCount; i++)
{
if (currentAmmo > 0)
{
Shoot();
yield return new WaitForSeconds(1f / fireRate);
}
else break;
}
isShooting = false;
}
}