using System.Collections; using UnityEditor; using UnityEngine; using Valve.VR; public class Arrow : MonoBehaviour { //Default arrows values based on this https://www.bowhunter.com/editorial/heavy-vs-light-choosing-the-best-hunting-arrow/182978 with the 480gr public float m_MaxLaunchSpeedMeterPerSecond = 88.392f; public float m_Mass = 0.0311035f; public Transform m_Tip = null; public GameObject hay; public bool hasHayOn = false; public GameObject fireParticles; public GameObject explosionFX; public SteamVR_Action_Vibration hapticAction; public Rigidbody m_Rigidbody = null; private bool m_isStopped = true; private Vector3 m_LastPosition = Vector3.zero; private bool startIgnitionTime = false; public bool onFire = false; private float timer = 0.0f; private bool arrowGrabbed = false; public int arrowDamage = 1; private void Awake() { m_Rigidbody = GetComponent(); m_Rigidbody.mass = m_Mass; } private void Start() { m_LastPosition = transform.position; } private void Update() { if (startIgnitionTime) { if (hasHayOn) { if (!onFire) { Pulse(0.1f, 160, 1, SteamVR_Input_Sources.RightHand); timer += Time.deltaTime; if (timer >= 1.5f) { ActivateFireFX(); } } } } } private void FixedUpdate() { if (m_isStopped) return; // Rotate m_Rigidbody.MoveRotation(Quaternion.LookRotation(m_Rigidbody.velocity, transform.up) * Quaternion.Euler(270.0f, 0, 0)); // Collision RaycastHit hit; if (Physics.Linecast(m_LastPosition, m_Tip.position, out hit, 1<<0 | 1<<4 | 1<<8 | 1<<9 | 1<<10)) // Default, Water, Ground, Mountain, NotWalkable { GameObject go = hit.collider.gameObject; Stop(go); CheckDamage(go); } // Store position m_LastPosition = m_Tip.position; } private void Stop(GameObject hitObject) { m_isStopped = true; transform.parent = hitObject.transform; m_Rigidbody.isKinematic = true; m_Rigidbody.useGravity = false; CheckDamage(hitObject); if(hitObject.tag == "OilPool" && hasHayOn && onFire) { StartCoroutine(FireArrowHitOil(hitObject)); } } private void CheckDamage(GameObject hitObject) { MonoBehaviour[] behaviours = hitObject.GetComponents(); foreach(MonoBehaviour behaviour in behaviours) { if (behaviour is EnemyBodyPart damageable) { damageable.Damage(arrowDamage, onFire); break; } if (behaviour is DamageableObject damageablObjecte) { damageablObjecte.Damage(onFire, gameObject); break; } } } public void Fire(float pullValue, AudioSource audioSource) { Vector3 parentForward = transform.parent.forward; Fire(pullValue, parentForward, audioSource); } public void Fire(float pullValue, Vector3 parentForward, AudioSource audioSource) { audioSource.Play(); m_LastPosition = transform.position; m_isStopped = false; transform.SetParent(null, true); m_Rigidbody.isKinematic = false; m_Rigidbody.useGravity = true; m_Rigidbody.AddForce(parentForward * pullValue * m_MaxLaunchSpeedMeterPerSecond * m_Mass / Time.fixedDeltaTime); Destroy(gameObject, 5.0f); } private void OnTriggerEnter(Collider other) { if(other.gameObject.tag == "hayBucket") { Pulse(0.5f, 160, 1, SteamVR_Input_Sources.RightHand); AddHayOnTip(); GameObject.Find("SFX/WheatCrunch").GetComponent().Play(); } else if(other.gameObject.tag == "Fx") { startIgnitionTime = true; } } private void OnTriggerExit(Collider other) { if (other.gameObject.tag == "Fx") { //Set fire particle on arrow tip startIgnitionTime = false; } } public void AddHayOnTip() { GameObject hayOnArrow = Instantiate(hay, m_Tip); hayOnArrow.transform.localPosition = new Vector3(0, 0, 0); hayOnArrow.transform.localEulerAngles = Vector3.zero; hasHayOn = true; } public void ActivateFireFX() { onFire = true; fireParticles.SetActive(true); GameObject.Find("SFX/ArrowIgnition").GetComponent().Play(); } private IEnumerator FireArrowHitOil(GameObject collider) { yield return new WaitForSeconds(1.0f); GameObject explosion = Instantiate(explosionFX); explosion.transform.position = collider.transform.position; collider.GetComponent().Play(); Enemy[] enemies = FindObjectsOfType(typeof(Enemy)) as Enemy[]; foreach (Enemy enemy in enemies) { if (Vector3.Distance(enemy.transform.position, transform.position) < 4.0f) enemy.Kill(true, false); else if (Vector3.Distance(enemy.transform.position, transform.position) >= 4.0f && Vector3.Distance(enemy.transform.position, transform.position) < 6.0f) enemy.TakeDamage(1, true, false); } // PoolEmitter collider.transform.parent.gameObject.GetComponent().Play(); Destroy(collider, 2.5f); Destroy(explosion, 2.5f); } private void Pulse(float duration, float frequency, float amplitude, SteamVR_Input_Sources source) { hapticAction.Execute(0, duration, frequency, amplitude, source); } public void PlayArrowGrabSFX() { if (!arrowGrabbed) { arrowGrabbed = true; GameObject.Find("SFX/GrabArrow").GetComponent().Play(); } } }