305 lines
8.0 KiB
C#
305 lines
8.0 KiB
C#
using UnityEngine;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using GameKitController.Audio;
|
|
|
|
public class spearProjectile : projectileSystem
|
|
{
|
|
[Header ("Main Settings")]
|
|
[Space]
|
|
|
|
public LayerMask layer;
|
|
|
|
public float rayDistance = 1;
|
|
public float carryingRagdollSpeedMultiplier = 3;
|
|
public float maxProjectileSpeedClamp = 30;
|
|
public float capsuleCastRadius = 2;
|
|
|
|
public float delayToDropSpearIfNotSurfaceFound = 10;
|
|
|
|
[Space]
|
|
[Header ("Other Settings")]
|
|
[Space]
|
|
|
|
public bool useGeneralProbabilityToKillTargets;
|
|
[Range (0, 100)] public float generalProbabilityToKillTargets;
|
|
|
|
[Space]
|
|
[Header ("Debug")]
|
|
[Space]
|
|
|
|
public bool surfaceFound;
|
|
public bool carryingRagdoll;
|
|
|
|
[Space]
|
|
[Header ("Components")]
|
|
[Space]
|
|
|
|
public Transform raycastPositionTransform;
|
|
|
|
ragdollActivator currentRagdoll;
|
|
|
|
Vector3 previousVelocity;
|
|
Transform currentRagdollRootMotion;
|
|
bool firstSurfaceDetected;
|
|
Vector3 surfacePoint;
|
|
float extraDistanceRaycast = 5;
|
|
Collider[] hitColliders;
|
|
|
|
float lastTimeSpearCarryingRagdoll;
|
|
|
|
Coroutine updateCoroutine;
|
|
|
|
|
|
public void stopUpdateCoroutine ()
|
|
{
|
|
if (updateCoroutine != null) {
|
|
StopCoroutine (updateCoroutine);
|
|
}
|
|
}
|
|
|
|
IEnumerator updateSystemCoroutine ()
|
|
{
|
|
var waitTime = new WaitForFixedUpdate ();
|
|
|
|
while (true) {
|
|
updateSystem ();
|
|
|
|
yield return waitTime;
|
|
}
|
|
}
|
|
|
|
void updateSystem ()
|
|
{
|
|
if (carryingRagdoll) {
|
|
if (surfaceFound) {
|
|
stopUpdateCoroutine ();
|
|
} else {
|
|
if (!firstSurfaceDetected) {
|
|
if (Physics.Linecast (currentRagdollRootMotion.position, currentRagdollRootMotion.position + transform.forward * extraDistanceRaycast, out hit, layer)) {
|
|
if (!hit.collider.GetComponent<Rigidbody> ()) {
|
|
firstSurfaceDetected = true;
|
|
surfacePoint = hit.point;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (firstSurfaceDetected) {
|
|
float currentDistance = GKC_Utils.distance (currentRagdollRootMotion.position, surfacePoint);
|
|
|
|
if (currentDistance < rayDistance) {
|
|
surfaceFound = true;
|
|
}
|
|
|
|
if (currentDistance < extraDistanceRaycast) {
|
|
if (carryingRagdollSpeedMultiplier > 1) {
|
|
carryingRagdollSpeedMultiplier = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (Physics.Linecast (currentRagdollRootMotion.position, currentRagdollRootMotion.position + transform.forward * rayDistance, out hit, layer)) {
|
|
if (!hit.collider.GetComponent<Rigidbody> ()) {
|
|
surfaceFound = true;
|
|
}
|
|
}
|
|
|
|
Vector3 movementValue = transform.InverseTransformDirection (transform.forward) * (Mathf.Abs (previousVelocity.magnitude) * carryingRagdollSpeedMultiplier * Time.deltaTime);
|
|
|
|
if (maxProjectileSpeedClamp != 0) {
|
|
if (Mathf.Abs (movementValue.magnitude) > maxProjectileSpeedClamp) {
|
|
movementValue = Vector3.ClampMagnitude (movementValue, maxProjectileSpeedClamp);
|
|
}
|
|
}
|
|
|
|
transform.Translate (movementValue);
|
|
|
|
if (Time.time > lastTimeSpearCarryingRagdoll + delayToDropSpearIfNotSurfaceFound) {
|
|
surfaceFound = true;
|
|
|
|
mainRigidbody.isKinematic = false;
|
|
|
|
mainRigidbody.useGravity = true;
|
|
|
|
mainRigidbody.AddForce (transform.forward * Mathf.Abs (previousVelocity.magnitude) * carryingRagdollSpeedMultiplier);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//when the bullet touchs a surface, then
|
|
public void checkObjectDetected (Collider col)
|
|
{
|
|
if (canActivateEffect (col)) {
|
|
setProjectileUsedState (true);
|
|
|
|
enableOrDisableMainTrailRenderer (false);
|
|
|
|
//set the bullet kinematic
|
|
objectToDamage = col.GetComponent<Collider> ().gameObject;
|
|
|
|
setProjectileScorch ();
|
|
|
|
previousVelocity = mainRigidbody.linearVelocity;
|
|
|
|
mainRigidbody.isKinematic = true;
|
|
|
|
if (carryingRagdoll) {
|
|
return;
|
|
}
|
|
|
|
Rigidbody objectToDamageRigidbody = objectToDamage.GetComponent<Rigidbody> ();
|
|
|
|
Transform currentCharacter = null;
|
|
|
|
GameObject currentCharacterGameObject = applyDamage.getCharacterOrVehicle (objectToDamage);
|
|
|
|
if (currentCharacterGameObject != null) {
|
|
currentCharacter = currentCharacterGameObject.transform;
|
|
}
|
|
|
|
bool bodyPartOnRagdollDetected = false;
|
|
|
|
bool isCharacter = applyDamage.isCharacter (objectToDamage);
|
|
|
|
if (objectToDamageRigidbody != null) {
|
|
currentRagdoll = objectToDamage.GetComponent<ragdollActivator> ();
|
|
|
|
if (currentRagdoll == null) {
|
|
if (currentCharacter != null) {
|
|
currentRagdoll = currentCharacter.GetComponent<ragdollActivator> ();
|
|
|
|
bodyPartOnRagdollDetected = true;
|
|
}
|
|
}
|
|
|
|
if (currentRagdoll != null) {
|
|
Vector3 currentPosition = transform.position;
|
|
|
|
List<ragdollActivator.bodyPart> bones = currentRagdoll.getBodyPartsList ();
|
|
|
|
float distance = Mathf.Infinity;
|
|
|
|
int index = -1;
|
|
|
|
for (int i = 0; i < bones.Count; i++) {
|
|
float currentDistance = GKC_Utils.distance (bones [i].transform.position, currentPosition);
|
|
|
|
if (currentDistance < distance) {
|
|
distance = currentDistance;
|
|
index = i;
|
|
}
|
|
}
|
|
|
|
if (index != -1) {
|
|
if (applyDamage.checkIfDead (objectToDamage)) {
|
|
if (bodyPartOnRagdollDetected) {
|
|
transform.SetParent (objectToDamage.transform);
|
|
} else {
|
|
mainRigidbody.isKinematic = false;
|
|
|
|
mainRigidbody.linearVelocity = previousVelocity;
|
|
|
|
setProjectileUsedState (false);
|
|
|
|
currentRagdoll.setRagdollOnExternalParent (transform);
|
|
}
|
|
}
|
|
}
|
|
} else if (currentCharacter != null) {
|
|
isCharacter = false;
|
|
|
|
transform.SetParent (currentCharacter);
|
|
} else if (objectToDamage != null) {
|
|
transform.SetParent (objectToDamage.transform);
|
|
}
|
|
} else if (currentCharacter != null) {
|
|
transform.SetParent (currentCharacter);
|
|
|
|
isCharacter = false;
|
|
}
|
|
|
|
if (isCharacter) {
|
|
setIgnoreParentDestroyedState (true);
|
|
}
|
|
|
|
checkProjectilesParent ();
|
|
|
|
|
|
bool activateSliceResult = true;
|
|
|
|
if (!currentProjectileInfo.killInOneShot) {
|
|
activateSliceResult = false;
|
|
} else {
|
|
if (useGeneralProbabilityToKillTargets) {
|
|
float randomProbability = UnityEngine.Random.Range (0, 101);
|
|
|
|
if (randomProbability > generalProbabilityToKillTargets) {
|
|
activateSliceResult = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
//add velocity if the touched object has rigidbody
|
|
if (activateSliceResult) {
|
|
applyDamage.killCharacter (gameObject, objectToDamage, -transform.forward, transform.position, currentProjectileInfo.owner, false);
|
|
|
|
if (!bodyPartOnRagdollDetected) {
|
|
if (currentRagdoll != null) {
|
|
projectilePaused = true;
|
|
|
|
transform.SetParent (null);
|
|
|
|
currentRagdollRootMotion = currentRagdoll.getRootMotion ();
|
|
|
|
currentRagdollRootMotion.SetParent (transform);
|
|
|
|
currentRagdollRootMotion.GetComponent<Rigidbody> ().isKinematic = true;
|
|
|
|
currentRagdoll.setRagdollOnExternalParent (transform);
|
|
|
|
setProjectileUsedState (false);
|
|
|
|
lastTimeSpearCarryingRagdoll = Time.time;
|
|
|
|
carryingRagdoll = true;
|
|
|
|
updateCoroutine = StartCoroutine (updateSystemCoroutine ());
|
|
}
|
|
}
|
|
} else {
|
|
applyDamage.checkHealth (gameObject, objectToDamage, currentProjectileInfo.projectileDamage, -transform.forward,
|
|
transform.position, currentProjectileInfo.owner, false, true, currentProjectileInfo.ignoreShield, false, currentProjectileInfo.damageCanBeBlocked,
|
|
currentProjectileInfo.canActivateReactionSystemTemporally, currentProjectileInfo.damageReactionID, currentProjectileInfo.damageTypeID);
|
|
}
|
|
|
|
if (currentProjectileInfo.applyImpactForceToVehicles) {
|
|
Rigidbody objectToDamageMainRigidbody = applyDamage.applyForce (objectToDamage);
|
|
|
|
if (objectToDamageMainRigidbody != null) {
|
|
Vector3 force = transform.forward * currentProjectileInfo.impactForceApplied;
|
|
|
|
objectToDamageMainRigidbody.AddForce (force * objectToDamageMainRigidbody.mass, currentProjectileInfo.forceMode);
|
|
}
|
|
} else {
|
|
if (applyDamage.canApplyForce (objectToDamage)) {
|
|
Vector3 force = transform.forward * currentProjectileInfo.impactForceApplied;
|
|
|
|
objectToDamageRigidbody.AddForce (force * objectToDamageRigidbody.mass, currentProjectileInfo.forceMode);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public override void resetProjectile ()
|
|
{
|
|
base.resetProjectile ();
|
|
|
|
stopUpdateCoroutine ();
|
|
|
|
surfaceFound = false;
|
|
carryingRagdoll = false;
|
|
firstSurfaceDetected = false;
|
|
}
|
|
} |