jimmy tremblay-Bernier c1bf5a4ca1 initial commit
2022-03-12 22:04:30 -04:00

190 lines
6.9 KiB
C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class AlliesMovement : MonoBehaviour
{
public GameObject m_ArrowPrefab = null;
public NavMeshAgent playerAgent;
public GameObject targetPosition;
public GameObject ExitPosition;// Just so AlliesManager doesn't need to track it
private Animator selfAnimator = null;
private ArcPrediction m_Predictor = null;
private float triggerRadius = 1f;
private bool previousAnimationStateWasAiming = false;
public float arrowForceMin = 0.3f;
public float arrowForceMax = 0.9f;
private Vector3 target;
private string ennemyChestName = "Spine_01";
private string selfHeadName = "Head";
public AudioSource m_bowShootingSound;
// Update is called once per frame
void FixedUpdate()
{
NavMeshSetup();
}
void Awake()
{
selfAnimator = GetComponent<Animator>();
}
void Start()
{
m_Predictor = GetComponentInChildren<ArcPrediction>();
m_Predictor.HideArc();
}
private void OnDestroy()
{
playerAgent.enabled = false;
}
private void NavMeshSetup()
{
if (!playerAgent.enabled)
{
playerAgent.enabled = true;
}
NavmeshAgentMovement();
}
void NavmeshAgentMovement()
{
if (NearTargetPosition())
{
TryShootEnemy();
}
else
{
selfAnimator.runtimeAnimatorController = Resources.Load("Animations/SlowRun/SlowRunController") as RuntimeAnimatorController;
playerAgent.SetDestination(targetPosition.transform.position);
}
}
void TryShootEnemy()
{
Enemy[] enemies = GameObject.FindObjectsOfType<Enemy>();
if (enemies.Length > 0)
{
Vector3 selfHead = GetChildWithName(transform, selfHeadName).position;
Enemy closestVisibleEnemy = null;
float enemyClosestDistence = 1000000000f;
foreach (Enemy enemy in enemies)
{
//Aim for the chest for higher odds of touching
Vector3 enemyChest = GetChildWithName(enemy.transform, ennemyChestName).position;
if (Vector3.Distance(enemyChest, selfHead) < enemyClosestDistence)
{
if (Physics.Linecast(selfHead, enemyChest, out RaycastHit hit))
{
if (hit.collider.transform.IsChildOf(enemy.transform))// Found a closer enemy that is visible that can be shot
{
closestVisibleEnemy = enemy;
enemyClosestDistence = Vector3.Distance(enemyChest, selfHead);
}
} else// Did not colide anything, including the enemy, so it should be fine to shoot?
{
closestVisibleEnemy = enemy;
enemyClosestDistence = Vector3.Distance(enemyChest, selfHead);
}
}
}
if (closestVisibleEnemy != null)
{
//Aim for the chest for higher odds of touching
Vector3 enemyChest = GetChildWithName(closestVisibleEnemy.transform, ennemyChestName).position;
transform.LookAt(enemyChest);
bool nextAnimationStateWasAiming = selfAnimator.GetCurrentAnimatorStateInfo(0).IsName("Aiming");
if(nextAnimationStateWasAiming != previousAnimationStateWasAiming){
target = enemyChest;
}
previousAnimationStateWasAiming = nextAnimationStateWasAiming;
if (selfAnimator.runtimeAnimatorController.name != "BowDrawController")
{
selfAnimator.runtimeAnimatorController = Resources.Load("Animations/BowDraw/BowDrawController") as RuntimeAnimatorController;
}
}
else
{
if (selfAnimator.runtimeAnimatorController.name != "Idle")
{
selfAnimator.runtimeAnimatorController = Resources.Load("Animations/Idle/Idle") as RuntimeAnimatorController;
}
}
}else
{
if (selfAnimator.runtimeAnimatorController.name != "Idle")
{
selfAnimator.runtimeAnimatorController = Resources.Load("Animations/Idle/Idle") as RuntimeAnimatorController;
}
}
}
private Transform GetChildWithName(Transform parent, string name)
{
if(parent.childCount > 0)
{
foreach (Transform child in parent)
{
if (child.name == name)
return child;
if (child.childCount > 0)
{
Transform subChild = GetChildWithName(child, name);
if (subChild != null)
{
return subChild;
}
}
}
}
return null;
}
bool NearTargetPosition()
{
if (targetPosition != null)
{
return Vector3.Distance(targetPosition.transform.position, this.transform.position) < triggerRadius;
}
return true; // If no target is set, assume it's in position
}
// Called by an animation event
private void FireArrow()
{
// Arrow setup
Transform bowTransform = GetChildWithName(transform, "ModifiedAssetBowWithBlender");
GameObject arrowObject = Instantiate(m_ArrowPrefab, bowTransform.position, new Quaternion(0, 1f, -0.1f, 0.2f));
Arrow arrow = arrowObject.GetComponent<Arrow>();
Vector3 shootingDirection = new Vector3(target.x,bowTransform.position.y, target.z);
arrowObject.transform.LookAt(shootingDirection);
arrowObject.GetComponent<Rigidbody>().detectCollisions = false;
// Figuring out the required force
float arrowForce = arrowForceMin;
float flightTime = 1.4142135f*Mathf.Sqrt((target.y - bowTransform.position.y)/Physics.gravity.y);
float distanceX = target.x - bowTransform.position.x;
float distanceZ = target.z - bowTransform.position.z;
float targetSpeed = Mathf.Sqrt(distanceX*distanceX+distanceZ*distanceZ)/flightTime;
float neededPower = targetSpeed / arrow.m_MaxLaunchSpeedMeterPerSecond;
if(neededPower > arrowForceMin && neededPower < arrowForceMax){
arrowForce = neededPower;
} else if (neededPower > arrowForceMax){ // Likely gonna miss, but lmao nice try
arrowForce = arrowForceMax;
}
// Fire the arrow
m_Predictor.RenderArc(arrowForce * arrow.m_MaxLaunchSpeedMeterPerSecond, 20, arrowObject.transform.forward);
arrow.Fire(arrowForce, arrowObject.transform.forward, m_bowShootingSound);
}
}