Files
FueraDeEscala/Assets/Game Kit Controller/Scripts/Combat System/Melee Combat System/Slice System/sliceSystem.cs

790 lines
26 KiB
C#
Raw Normal View History

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class sliceSystem : MonoBehaviour
{
[Header ("Main Settings")]
[Space]
public Vector3 cutOverlapBoxSize = new Vector3 (5, 0.1f, 5);
public bool activateRigidbodiesOnNewObjects;
public float minDelayToSliceSameObject = 0.3f;
[Space]
[Header ("Objects To Affect Settings")]
[Space]
public LayerMask targetToDamageLayer;
public bool useObjectsToIgnoreList;
public List<GameObject> objectsToIgnoreList = new List<GameObject> ();
[Space]
[Header ("Force Settings")]
[Space]
public float forceToApplyToCutPart;
public ForceMode forceMode;
public float forceRadius;
public float forceUp;
[Space]
[Header ("Damage Settings")]
[Space]
public bool activateDamageOnSlice;
public float damageAmountToApplyOnSlice;
public bool ignoreShieldOnDamage = true;
public bool canActivateReactionSystemTemporally;
public int damageReactionID = -1;
public int damageTypeID = -1;
[Space]
[Header ("Physics Settings")]
[Space]
public bool updateLastObjectSpeed;
public bool applyForcesOnObjectsDetected;
public float addForceMultiplier;
public bool applyImpactForceToVehicles;
public float impactForceToVehiclesMultiplier;
public bool checkObjectLayerAndTagToApplyForces;
public LayerMask targetToApplyForceLayer;
public List<string> tagetToApplyForceTagList = new List<string> ();
[Space]
[Header ("Slice Transform Values Settings")]
[Space]
public List<sliceTransformValuesInfo> sliceTransformValuesInfoList = new List<sliceTransformValuesInfo> ();
[Space]
[Header ("Bullet Time Settings")]
[Space]
public bool ignoreTimeBulletOnRegularSlice;
[Space]
[Header ("Gizmo Settings")]
[Space]
public bool showGizmo;
public Color gizmoColor = Color.red;
public bool showDebugPrint;
[Space]
[Header ("Components")]
[Space]
public GameObject playerGameObject;
public Material defaultSliceMaterial;
public Transform cutPositionTransform;
public Transform cutDirectionTransform;
public Transform planeDefiner1;
public Transform planeDefiner2;
public Transform planeDefiner3;
bool usingCustomCutValues;
surfaceToSlice currentSurfaceToSlice;
Collider [] hits;
List<GameObject> hitsGameObjectList = new List<GameObject> ();
bool collidersListSent;
Vector3 currentCutPosition;
Quaternion currentCutRotation;
Vector3 currentCutUp;
Vector3 currentCutForward;
Vector3 currentCutDirection;
Vector3 currentPlaneDefiner1;
Vector3 currentPlaneDefiner2;
Vector3 currentPlaneDefiner3;
Vector3 currentCutOverlapBoxSize;
bool objectsDetectedOnLastSlice;
float lastTimeSliceActivated;
public void setCustomSliceTransformValues (string sliceInfoName)
{
int sliceIndex = sliceTransformValuesInfoList.FindIndex (a => a.Name == sliceInfoName);
if (sliceIndex > -1) {
sliceTransformValuesInfo currentSliceTransformValuesInfo = sliceTransformValuesInfoList [sliceIndex];
if (currentSliceTransformValuesInfo.sliceInfoEnabled) {
setCustomCutTransformValues (currentSliceTransformValuesInfo.cutOverlapBoxSize,
currentSliceTransformValuesInfo.cutPositionTransform,
currentSliceTransformValuesInfo.cutDirectionTransform,
currentSliceTransformValuesInfo.planeDefiner1,
currentSliceTransformValuesInfo.planeDefiner2,
currentSliceTransformValuesInfo.planeDefiner3);
activateCut ();
}
}
}
public void setCustomCutTransformValues (Vector3 newCutOverlapBoxSize,
Transform newcutPositionTransform,
Transform newCutDirectionTransform,
Transform newPlaneDefiner1,
Transform newPlaneDefiner2,
Transform newPlaneDefiner3)
{
usingCustomCutValues = true;
currentCutPosition = newcutPositionTransform.position;
currentCutRotation = newcutPositionTransform.rotation;
currentCutUp = newcutPositionTransform.up;
currentCutForward = newcutPositionTransform.forward;
currentCutDirection = newCutDirectionTransform.right;
currentPlaneDefiner1 = newPlaneDefiner1.position;
currentPlaneDefiner2 = newPlaneDefiner2.position;
currentPlaneDefiner3 = newPlaneDefiner3.position;
currentCutOverlapBoxSize = newCutOverlapBoxSize;
}
void setCurrentCutTransformValues ()
{
if (usingCustomCutValues) {
usingCustomCutValues = false;
return;
}
currentCutPosition = cutPositionTransform.position;
currentCutRotation = cutPositionTransform.rotation;
currentCutUp = cutPositionTransform.up;
currentCutForward = cutPositionTransform.forward;
currentCutDirection = cutDirectionTransform.right;
currentPlaneDefiner1 = planeDefiner1.position;
currentPlaneDefiner2 = planeDefiner2.position;
currentPlaneDefiner3 = planeDefiner3.position;
currentCutOverlapBoxSize = cutOverlapBoxSize;
}
bool currentSliceActivatedExternally;
public void activateCutExternally ()
{
currentSliceActivatedExternally = true;
activateCut ();
}
public void activateCut ()
{
if (lastTimeSliceActivated > 0) {
if (Time.time > lastTimeSliceActivated + 0.7f) {
currentSliceActivatedExternally = false;
lastTimeSliceActivated = 0;
}
}
objectsDetectedOnLastSlice = false;
setCurrentCutTransformValues ();
hits = Physics.OverlapBox (currentCutPosition, currentCutOverlapBoxSize, currentCutRotation, targetToDamageLayer);
if (hits.Length > 0) {
for (int i = 0; i < hits.Length; i++) {
Collider currentCollider = hits [i];
processObject (currentCollider.gameObject, currentCollider, hits [i].ClosestPointOnBounds (currentCutPosition));
}
}
collidersListSent = false;
lastTimeSliceActivated = Time.time;
}
public List<GameObject> getLastCollidersListDetected ()
{
hitsGameObjectList.Clear ();
if (!collidersListSent) {
if (hits.Length > 0) {
for (int i = 0; i < hits.Length; i++) {
hitsGameObjectList.Add (hits [i].gameObject);
}
}
}
collidersListSent = true;
return hitsGameObjectList;
}
public void processObject (GameObject obj, Collider objectCollider, Vector3 slicePosition)
{
if (useObjectsToIgnoreList) {
if (objectsToIgnoreList.Contains (obj)) {
return;
}
}
currentSurfaceToSlice = obj.GetComponent<surfaceToSlice> ();
if (currentSurfaceToSlice == null) {
currentSurfaceToSlice = sliceSystemUtils.getSurfaceToSlice (obj);
}
bool isVehicle = applyDamage.isVehicle (obj);
if (isVehicle) {
GameObject currentVehicle = applyDamage.getVehicle (obj);
if (currentVehicle != null) {
currentSurfaceToSlice = currentVehicle.GetComponent<surfaceToSlice> ();
if (currentSurfaceToSlice != null) {
obj = currentVehicle;
}
}
}
bool objectIsSliceSurfaceDisabled = false;
bool objectCanBeSliced = false;
if (showDebugPrint) {
print ("processing object " + obj.name);
}
bool ignoreRegularDamageIfCutSurfaceNotEnabled = false;
bool isIgnoreDamageIfSliceNotActivatedActive = false;
if (currentSurfaceToSlice != null) {
bool isCutSurfaceEnabled = currentSurfaceToSlice.isCutSurfaceEnabled ();
bool sliceCanBeActivated = currentSurfaceToSlice.sliceCanBeActivated (minDelayToSliceSameObject);
bool checkSliceDirectionResult = currentSurfaceToSlice.checkSliceDirectionResult (cutPositionTransform.right, cutPositionTransform.up);
isIgnoreDamageIfSliceNotActivatedActive = currentSurfaceToSlice.isIgnoreDamageIfSliceNotActivatedActive ();
if (showDebugPrint) {
print ("Surface cut enabled state " + isCutSurfaceEnabled +
" can activate slice " + sliceCanBeActivated +
"check Slice Direction Result " + checkSliceDirectionResult);
}
if (isCutSurfaceEnabled && sliceCanBeActivated && checkSliceDirectionResult) {
Material crossSectionMaterial = currentSurfaceToSlice.getCrossSectionMaterial ();
if (crossSectionMaterial == null) {
crossSectionMaterial = defaultSliceMaterial;
}
sliceCurrentObject (obj, objectCollider, crossSectionMaterial, slicePosition);
objectsDetectedOnLastSlice = true;
objectCanBeSliced = true;
} else {
if (isVehicle && isCutSurfaceEnabled) {
objectCanBeSliced = true;
}
}
if (!isCutSurfaceEnabled) {
objectIsSliceSurfaceDisabled = true;
ignoreRegularDamageIfCutSurfaceNotEnabled = currentSurfaceToSlice.isIgnoreRegularDamageIfCutSurfaceNotEnabled ();
}
} else {
if (showDebugPrint) {
print ("Surface to slice not found on " + obj.name);
}
}
if (!objectCanBeSliced && !ignoreRegularDamageIfCutSurfaceNotEnabled) {
if (activateDamageOnSlice && !isIgnoreDamageIfSliceNotActivatedActive) {
Vector3 damagePosition = currentCutPosition;
if (applyDamage.checkIfDead (obj)) {
damagePosition = obj.transform.position;
}
applyDamage.checkCanBeDamaged (gameObject, obj, damageAmountToApplyOnSlice, -currentCutForward, damagePosition,
playerGameObject, true, true, ignoreShieldOnDamage, false, true,
canActivateReactionSystemTemporally, damageReactionID, damageTypeID);
}
if (applyForcesOnObjectsDetected && !objectIsSliceSurfaceDisabled) {
if (!checkObjectLayerAndTagToApplyForces ||
((1 << obj.layer & targetToApplyForceLayer.value) == 1 << obj.layer && tagetToApplyForceTagList.Contains (obj.tag))) {
checkForceToApplyOnObject (obj);
}
}
}
}
public void sliceCurrentObject (GameObject obj, Collider objectCollider, Material crossSectionMaterial, Vector3 slicePosition)
{
if (showDebugPrint) {
print ("\n\n");
print ("CHECKING IF OBJECT IS CHARACTER " + currentSurfaceToSlice.isObjectCharacter ());
}
// slice the provided object using the transforms of this object
if (currentSurfaceToSlice.isObjectCharacter ()) {
bool isCharacterOrVehicle = applyDamage.getCharacterOrVehicle (obj) != null;
bool objectIsDead = applyDamage.checkIfDead (obj);
if (isCharacterOrVehicle && !objectIsDead) {
if (showDebugPrint) {
print ("CONFIRMED " + obj.name + " can be sliced and is not dead, PROCESSING CHARACTER");
}
processCharacter (obj);
return;
}
if (showDebugPrint) {
print ("SLICING " + obj.name + " is character " + isCharacterOrVehicle + " is dead " + objectIsDead);
}
Rigidbody mainObject = obj.GetComponent<Rigidbody> ();
bool mainObjectHasRigidbody = mainObject != null;
Vector3 lastSpeed = Vector3.zero;
if (mainObjectHasRigidbody) {
lastSpeed = mainObject.linearVelocity;
}
currentSurfaceToSlice.checkEventBeforeSlice ();
currentSurfaceToSlice.getMainSimpleSliceSystem ().activateSlice (objectCollider, positionInWorldSpace,
normalInWorldSpace, slicePosition, updateLastObjectSpeed, lastSpeed);
currentSurfaceToSlice.checkEventOnCut ();
bool canCheckTimeBulletResult = true;
if (!currentSliceActivatedExternally) {
if (ignoreTimeBulletOnRegularSlice) {
canCheckTimeBulletResult = false;
}
}
if (canCheckTimeBulletResult) {
currentSurfaceToSlice.checkTimeBulletOnCut ();
}
} else {
bool objectSliced = false;
GameObject object1 = null;
GameObject object2 = null;
currentSurfaceToSlice.checkEventBeforeSlice ();
obj = currentSurfaceToSlice.getMainSurfaceToSlice ();
sliceSystemUtils.sliceObject (currentCutPosition, obj, currentCutUp, crossSectionMaterial, ref objectSliced, ref object1, ref object2);
Vector3 objectPosition = obj.transform.position;
Quaternion objectRotation = obj.transform.rotation;
Transform objectParent = obj.transform.parent;
if (objectSliced) {
if (currentSurfaceToSlice.useParticlesOnSlice) {
Quaternion particlesRotation = Quaternion.LookRotation (positionInWorldSpace);
Instantiate (currentSurfaceToSlice.particlesOnSlicePrefab, slicePosition, particlesRotation);
}
currentSurfaceToSlice.checkEventOnCut ();
bool canCheckTimeBulletResult = true;
if (!currentSliceActivatedExternally) {
if (ignoreTimeBulletOnRegularSlice) {
canCheckTimeBulletResult = false;
}
}
if (canCheckTimeBulletResult) {
currentSurfaceToSlice.checkTimeBulletOnCut ();
}
Rigidbody mainObject = obj.GetComponent<Rigidbody> ();
bool mainObjectHasRigidbody = mainObject != null;
object1.transform.position = objectPosition;
object1.transform.rotation = objectRotation;
object2.transform.position = objectPosition;
object2.transform.rotation = objectRotation;
if (objectParent != null) {
object1.transform.SetParent (objectParent);
object2.transform.SetParent (objectParent);
}
surfaceToSlice newSurfaceToSlice1 = object1.AddComponent<surfaceToSlice> ();
surfaceToSlice newSurfaceToSlice2 = object2.AddComponent<surfaceToSlice> ();
currentSurfaceToSlice.copySurfaceInfo (newSurfaceToSlice1);
currentSurfaceToSlice.copySurfaceInfo (newSurfaceToSlice2);
newSurfaceToSlice1.checkDestroySlicedPartsAfterDelay ();
newSurfaceToSlice2.checkDestroySlicedPartsAfterDelay ();
float distance1 = GKC_Utils.distance (obj.transform.position, object1.transform.position);
float distance2 = GKC_Utils.distance (obj.transform.position, object2.transform.position);
float currentForceToApply = forceToApplyToCutPart;
ForceMode currentForceMode = forceMode;
if (currentSurfaceToSlice.useCustomForceMode) {
currentForceMode = currentSurfaceToSlice.customForceMode;
}
if (mainObjectHasRigidbody || activateRigidbodiesOnNewObjects) {
if (currentSurfaceToSlice.useCustomForceAmount) {
currentForceToApply = currentSurfaceToSlice.customForceAmount;
}
Rigidbody object1Rigidbody = object1.AddComponent<Rigidbody> ();
Rigidbody object2Rigidbody = object2.AddComponent<Rigidbody> ();
object1Rigidbody.interpolation = RigidbodyInterpolation.Interpolate;
object2Rigidbody.interpolation = RigidbodyInterpolation.Interpolate;
object2Rigidbody.AddExplosionForce (currentForceToApply, currentCutPosition, forceRadius, forceUp, currentForceMode);
object1Rigidbody.AddExplosionForce (currentForceToApply, currentCutPosition, forceRadius, forceUp, currentForceMode);
} else {
if (currentSurfaceToSlice.useCustomForceAmount) {
currentForceToApply = currentSurfaceToSlice.customForceAmount;
}
if (distance1 < distance2) {
Rigidbody object2Rigidbody = object2.AddComponent<Rigidbody> ();
object2Rigidbody.interpolation = RigidbodyInterpolation.Interpolate;
object2Rigidbody.AddExplosionForce (currentForceToApply, currentCutPosition, forceRadius, forceUp, currentForceMode);
} else {
Rigidbody object1Rigidbody = object1.AddComponent<Rigidbody> ();
object1Rigidbody.interpolation = RigidbodyInterpolation.Interpolate;
object1Rigidbody.AddExplosionForce (currentForceToApply, currentCutPosition, forceRadius, forceUp, currentForceMode);
}
}
if (currentSurfaceToSlice.useBoxCollider) {
object1.AddComponent<BoxCollider> ();
object2.AddComponent<BoxCollider> ();
} else {
MeshCollider object1Collider = object1.AddComponent<MeshCollider> ();
MeshCollider object2Collider = object2.AddComponent<MeshCollider> ();
object1Collider.convex = true;
object2Collider.convex = true;
}
if (currentSurfaceToSlice.setNewLayerOnCut) {
object1.layer = LayerMask.NameToLayer (currentSurfaceToSlice.newLayerOnCut);
object2.layer = LayerMask.NameToLayer (currentSurfaceToSlice.newLayerOnCut);
}
if (currentSurfaceToSlice.setNewTagOnCut) {
object1.tag = currentSurfaceToSlice.tag;
object2.tag = currentSurfaceToSlice.tag;
}
obj.SetActive (false);
}
}
}
public void checkForceToApplyOnObject (GameObject objectToDamage)
{
Rigidbody objectToDamageRigidbody = objectToDamage.GetComponent<Rigidbody> ();
Vector3 forceDirection = currentCutDirection;
float forceAmount = addForceMultiplier;
float forceToVehiclesMultiplier = impactForceToVehiclesMultiplier;
if (applyImpactForceToVehicles) {
Rigidbody objectToDamageMainRigidbody = applyDamage.applyForce (objectToDamage);
if (objectToDamageMainRigidbody) {
Vector3 force = forceAmount * forceDirection;
bool isVehicle = applyDamage.isVehicle (objectToDamage);
if (isVehicle) {
force *= forceToVehiclesMultiplier;
}
objectToDamageMainRigidbody.AddForce (objectToDamageMainRigidbody.mass * force, forceMode);
}
} else {
if (applyDamage.canApplyForce (objectToDamage)) {
if (showDebugPrint) {
print (objectToDamage.name);
}
Vector3 force = forceAmount * forceDirection;
if (objectToDamageRigidbody == null) {
objectToDamageRigidbody = objectToDamage.GetComponent<Rigidbody> ();
}
objectToDamageRigidbody.AddForce (objectToDamageRigidbody.mass * force, forceMode);
}
}
}
private Vector3 positionInWorldSpace
{
get
{
return (currentPlaneDefiner1 + currentPlaneDefiner2 + currentPlaneDefiner3) / 3f;
}
}
private Vector3 normalInWorldSpace
{
get
{
Vector3 t0 = currentPlaneDefiner1;
Vector3 t1 = currentPlaneDefiner2;
Vector3 t2 = currentPlaneDefiner3;
Vector3 vectorValue;
vectorValue.x = t0.y * (t1.z - t2.z) + t1.y * (t2.z - t0.z) + t2.y * (t0.z - t1.z);
vectorValue.y = t0.z * (t1.x - t2.x) + t1.z * (t2.x - t0.x) + t2.z * (t0.x - t1.x);
vectorValue.z = t0.x * (t1.y - t2.y) + t1.x * (t2.y - t0.y) + t2.x * (t0.y - t1.y);
return vectorValue;
}
}
void processCharacter (GameObject currentCharacter)
{
StartCoroutine (processCharacterCoroutine (currentCharacter));
}
List<Collider> colliders = new List<Collider> ();
IEnumerator processCharacterCoroutine (GameObject currentCharacter)
{
applyDamage.pushCharacterWithoutForceAndPauseGetUp (currentCharacter);
if (showDebugPrint) {
print ("ragdoll " + currentCharacter.name);
}
yield return new WaitForEndOfFrame ();
List<Collider> temporalHitsList = new List<Collider> ();
if (hits.Length > 0) {
for (int i = 0; i < hits.Length; i++) {
temporalHitsList.Add (hits [i]);
}
}
Collider [] temporalHits = Physics.OverlapBox (currentCutPosition, currentCutOverlapBoxSize, currentCutRotation, targetToDamageLayer);
bool bodyPartFound = false;
if (showDebugPrint) {
print ("activating ragdoll on " + currentCharacter.name);
}
if (showDebugPrint) {
print ("\n\n");
}
if (temporalHits.Length > 0) {
bool ragdollCollidersFoundOnCharacter = false;
colliders = null;
ragdollActivator currentRagdollActivator = currentCharacter.GetComponent<ragdollActivator> ();
if (currentRagdollActivator != null) {
colliders = currentRagdollActivator.getBodyColliderList ();
if (colliders != null && colliders.Count > 0) {
ragdollCollidersFoundOnCharacter = true;
}
}
Collider colliderToCheck = null;
float minDistance = 1000;
for (int i = 0; i < temporalHits.Length; i++) {
Collider currentCollider = temporalHits [i];
if (showDebugPrint) {
print ("checking " + currentCollider.name);
}
if (!temporalHitsList.Contains (currentCollider)) {
bool canActivateSliceResult = false;
if (ragdollCollidersFoundOnCharacter) {
if (showDebugPrint) {
print ("ragoll detected");
}
if (colliders.Contains (currentCollider)) {
canActivateSliceResult = true;
if (showDebugPrint) {
print ("ragdoll part found");
}
}
} else {
canActivateSliceResult = true;
}
if (canActivateSliceResult) {
if (showDebugPrint) {
print (currentCollider.name + " body part when killing");
}
if (applyDamage.isCharacter (currentCollider.gameObject)) {
bodyPartFound = true;
float currentDistance = GKC_Utils.distance (currentCutPosition, currentCollider.transform.position);
if (currentDistance < minDistance) {
minDistance = currentDistance;
colliderToCheck = currentCollider;
}
}
}
} else {
if (showDebugPrint) {
print (currentCollider.name + " already on temporal hist list");
}
}
}
if (bodyPartFound) {
if (currentCharacter != null) {
applyDamage.killCharacter (currentCharacter);
}
processObject (colliderToCheck.gameObject, colliderToCheck, currentCutPosition);
}
}
if (showDebugPrint) {
print (temporalHits.Length + " " + bodyPartFound);
}
}
public bool anyObjectDetectedOnLastSlice ()
{
return objectsDetectedOnLastSlice;
}
#if UNITY_EDITOR
void OnDrawGizmos ()
{
if (!showGizmo) {
return;
}
if (GKC_Utils.isCurrentSelectionActiveGameObject (gameObject)) {
DrawGizmos ();
}
}
void OnDrawGizmosSelected ()
{
DrawGizmos ();
}
void DrawGizmos ()
{
if (showGizmo) {
if (usingCustomCutValues) {
GKC_Utils.drawRectangleGizmo (currentCutPosition, currentCutRotation,
Vector3.zero, currentCutOverlapBoxSize, gizmoColor);
} else {
GKC_Utils.drawRectangleGizmo (cutPositionTransform.position, cutPositionTransform.rotation,
Vector3.zero, cutOverlapBoxSize, gizmoColor);
}
}
}
#endif
[System.Serializable]
public class sliceTransformValuesInfo
{
public string Name;
public bool sliceInfoEnabled;
public Vector3 cutOverlapBoxSize = new Vector3 (5, 0.1f, 5);
public Transform cutPositionTransform;
public Transform cutDirectionTransform;
public Transform planeDefiner1;
public Transform planeDefiner2;
public Transform planeDefiner3;
}
}