123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273 |
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- using QFSW.MOP2;
- using Sirenix.OdinInspector;
- using KairoEngine.Core;
- using KairoEngine.Inventory;
- using KairoEngine.SFX;
- using KairoEngine.Utilities.Statistics;
- namespace KairoEngine.CharacterSystem
- {
- public class Bullet : MonoBehaviour
- {
- public string muzzlePrefabPool = "";
- public string hitPrefabPool = "";
- public List<GameObject> trails;
- [ReadOnly, ShowInInspector] public ItemFirearmRef firearmRef;
- [ReadOnly] public CharacterController character;
- public bool bounce = false;
- public bool alwaysSpawnHitPrefab = false;
- public float bounceForce = 10;
-
- [FoldoutGroup("Inpact Sound Effects")] public SFXClip concreteSFX;
- [FoldoutGroup("Inpact Sound Effects")] public SFXClip dirtSFX;
- [FoldoutGroup("Inpact Sound Effects")] public SFXClip fleshSFX;
- [FoldoutGroup("Inpact Sound Effects")] public SFXClip grassSFX;
- [FoldoutGroup("Inpact Sound Effects")] public SFXClip metalSFX;
- [FoldoutGroup("Inpact Sound Effects")] public SFXClip mudSFX;
- [FoldoutGroup("Inpact Sound Effects")] public SFXClip sandSFX;
- [FoldoutGroup("Inpact Sound Effects")] public SFXClip stoneSFX;
- [FoldoutGroup("Inpact Sound Effects")] public SFXClip woodSFX;
-
- private float counter = 0f;
- public Vector3 startPos;
- private float speedRandomness;
- private Vector3 offset;
- private bool collided;
- private Rigidbody rb;
- private GameObject target;
- private ItemBaseFirearm itemBaseFirearm;
- private float speed;
- private bool hitEnemy = false;
- public string bulletPrefabPool = "";
- public void Initialize(Transform source, ItemFirearmRef firearmRef, CharacterController character, string bulletPrefabPool = "")
- {
- this.firearmRef = firearmRef;
- this.character = character;
- this.bulletPrefabPool = bulletPrefabPool;
- startPos = source.position;
- this.gameObject.transform.position = source.position;
- this.transform.rotation = source.rotation;
- if(rb == null) rb = GetComponent<Rigidbody>();
- rb.isKinematic = false;
- itemBaseFirearm = (ItemBaseFirearm)firearmRef.item;
- counter = 0;
- hitEnemy = false;
- target = null;
- collided = false;
- CalculateAccuracy();
- MuzzleFX();
- }
- void FixedUpdate()
- {
- if (speed != 0 && rb != null)
- {
- rb.position += (transform.forward + offset) * (speed * Time.deltaTime);
- }
- counter += Time.deltaTime;
- if (counter > itemBaseFirearm.ammoType.lifetime)
- {
- RemoveBullet();
- }
- }
- void OnCollisionEnter(Collision co)
- {
- if(co.gameObject.GetComponent<DamageEmitter>() != null) return;
- if (!bounce)
- {
- if (co.gameObject.tag != "Bullet" && !collided)
- {
- collided = true;
- if (trails.Count > 0)
- {
- for (int i = 0; i < trails.Count; i++)
- {
- trails[i].transform.parent = null;
- var ps = trails[i].GetComponent<ParticleSystem>();
- if (ps != null)
- {
- ps.Stop();
- Destroy(ps.gameObject, ps.main.duration + ps.main.startLifetime.constantMax);
- }
- }
- }
- PlayInpactSound(co);
- //speed = 0;
- rb.isKinematic = true;
- ContactPoint contact = co.contacts[0];
- Quaternion rot = Quaternion.FromToRotation(Vector3.up, contact.normal);
- Vector3 pos = contact.point;
- WorldObject worldObject = co.gameObject.transform.root.GetComponent<WorldObject>();
- DamageController damageController = null;
- DamagePoint damagePoint = co.gameObject.GetComponent<DamagePoint>();
- if(worldObject != null)
- {
- if(worldObject.IsCharacter()) damageController = worldObject.character.damageController;
- }
- if(damageController == null && damagePoint == null)
- {
- HitFX(pos, rot);
- RemoveBullet();
- }
- else if(damagePoint != null)
- {
- damagePoint.damageController.Damage(this, pos, damagePoint );
- hitEnemy = true;
- }
- else if(damageController != null)
- {
- damageController.Damage(this, pos);
- hitEnemy = true;
- }
- // if(damageController != null)
- // {
- // Rigidbody rigidbody = damageController.GetComponentInChildren<Rigidbody>();
- // if(rigidbody != null)
- // {
- // rigidbody.AddForce(transform.forward * 2, ForceMode.Impulse);
- // }
- // }
- }
- }
- else
- {
- rb.useGravity = true;
- rb.drag = 0.5f;
- ContactPoint contact = co.contacts[0];
- rb.AddForce(Vector3.Reflect((contact.point - startPos).normalized, contact.normal) * bounceForce, ForceMode.Impulse);
- RemoveBullet();
- }
- }
- public void RemoveBullet()
- {
- ProcessStatistics();
- if(bulletPrefabPool == "") Destroy(this.gameObject);
- else MasterObjectPooler.Instance.GetPool(bulletPrefabPool).Release(this.gameObject);
- }
- private void MuzzleFX()
- {
- GameObject muzzleVFX = null;
- if(muzzlePrefabPool != "")
- {
- muzzleVFX = MasterObjectPooler.Instance.GetPool(muzzlePrefabPool).GetObject();
- muzzleVFX.transform.position = startPos;
- muzzleVFX.transform.forward = gameObject.transform.forward + offset;
- }
- }
- private void HitFX(Vector3 pos, Quaternion rot)
- {
- GameObject hitVFX = null;
- if(hitPrefabPool != "")
- {
- hitVFX = MasterObjectPooler.Instance.GetPool(hitPrefabPool).GetObject();
- hitVFX.transform.position = pos;
- hitVFX.transform.rotation = rot;
- }
- }
- private void CalculateAccuracy()
- {
- float accuracy = itemBaseFirearm.Accuracy(firearmRef) + firearmRef.accuracyModifier;
- if(accuracy > 100) accuracy = 100;
- if(accuracy < 50) accuracy = 50;
- speed = itemBaseFirearm.ammoType.bulletSpeed;
- //used to create a radius for the accuracy and have a very unique randomness
- if (accuracy != 100)
- {
- accuracy = 1 - (accuracy / 100) ;
- for (int i = 0; i < 2; i++)
- {
- var val = 1 * Random.Range(-accuracy, accuracy);
- var index = Random.Range(0, 2);
- if (i == 0)
- {
- if (index == 0)
- offset = new Vector3(0, -val, 0);
- else
- offset = new Vector3(0, val, 0);
- }
- else
- {
- if (index == 0)
- offset = new Vector3(0, offset.y, -val);
- else
- offset = new Vector3(0, offset.y, val);
- }
- }
- }
- }
- private void ProcessStatistics()
- {
- if(character.unique_name == "player-character_")
- {
- Statistics.GetData("ShotsFired").AddInteger(1);
- if(hitEnemy == true)
- {
- Statistics.GetData("ShotsHit").AddInteger(1);
- }
- }
- }
- void PlayInpactSound(Collision co)
- {
- //Debug.Log(co.collider.material.name);
- SFXClip clip = null;
- string materialName = co.collider.material.name;
- materialName = materialName.Replace(" (Instance)", "");
- switch (materialName)
- {
- case "Concrete":
- clip = concreteSFX;
- break;
- case "Dirt":
- clip = dirtSFX;
- break;
- case "Flesh":
- clip = fleshSFX;
- break;
- case "Grass":
- clip = grassSFX;
- break;
- case "Metal":
- clip = metalSFX;
- break;
- case "Mud":
- clip = mudSFX;
- break;
- case "Sand":
- clip = sandSFX;
- break;
- case "Stone":
- clip = stoneSFX;
- break;
- case "Wood":
- clip = woodSFX;
- break;
- default:
- break;
- }
- if(clip == null)
- {
- Debug.LogWarning($"Missing inpact SFX clip for material \'{materialName}\' ({co.gameObject.name})", co.gameObject);
- return;
- }
- else SoundController.EmmitSound(clip, co.contacts[0].point);
- }
- }
- }
|