You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

340 lines
14 KiB
C#

4 years ago
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using MalbersAnimations.Events;
using MalbersAnimations.Scriptables;
using MalbersAnimations.Controller;
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using MalbersAnimations.Scriptables;
using UnityEngine.Events;
public class Grapple : MonoBehaviour
{
public MalbersAnimations.Controller.MAnimal Player;
public GameObject Camera;
public GameObject AttachmentPrefab;
public GameObject ropeSegment;
private GameObject attachment;
private Vector3 attachedPoint;
private Rigidbody attachedObject;
private MalbersAnimations.Controller.MAnimal attachedCharacter;
public float RopeSegmentLength;
public bool isAttached;
public float minDistance = 1.0f;
public float maxDistance = 30.0f;
public float pullForce = 20.0f;
public float MaxPullForce = 25.0f;
public float PushForce = 30.0f;
public float pullAccel = 20.0f;
public float playerWidth = 0.5f;
public float playerHeight = 1.6f;
public float playerHeightBuffer = 0.5f;
public float breakChainTime = 0.5f;
public float breakChainDistance = 0.5f;
public float defaultRopeSegmentOrientation = 90.0f;
private GameObject chain;
private bool limitingPosition;
private bool hasPullChainInputSequenceStarted;
private bool inputPaused;
private float pullChainInputTiming = 0.5f;
private float inputPauseTiming = 1.0f;
private float timer = 0.0f;
private bool grappling;
bool CheckInputDepressedThisFrame()
{
if (grappling)
{
grappling = false;
return true;
}
return Input.GetAxis("Fire1") > 0.0f;
}
public virtual void StartGrapple()
{
grappling = true;
}
// Start is called before the first frame update
void Start()
{
chain = new GameObject("Chain");
chain.AddComponent<LineRenderer>();
}
// Update is called once per frame
void Update()
{
timer += Time.deltaTime;
if (inputPaused)
{
if (timer < inputPauseTiming)
{
return;
}
else
{
inputPaused = false;
}
}
var cameraTransform = Camera.transform;
if (attachment != null)
{
attachedPoint = attachment.transform.position;
}
if (Vector3.Distance(Player.transform.position, attachedPoint) > maxDistance)
{
//check if time limit has passed for being beyond distance limit without breaking
}
if (Vector3.Distance(Player.transform.position, attachedPoint) > maxDistance + breakChainDistance)
{
if (attachment != null)
{
GameObject.Destroy(attachment);
var lineRenderer = chain.GetComponent<LineRenderer>();
lineRenderer.SetWidth(0, 0);
}
if (ropeSegment != null)
{
GameObject.Destroy(ropeSegment);
}
isAttached = false;
return;
}
if (isAttached)
{
// limit the position of both sides of the chain to the length of the chain
// // //
// //
if (Vector3.Distance(Player.transform.position, attachedPoint) > maxDistance)
{
var forceHeading = attachedPoint - cameraTransform.position;
var forceDirection = forceHeading / forceHeading.magnitude;
if (Player.GetComponent<Rigidbody>().velocity.x > MaxPullForce
|| Player.GetComponent<Rigidbody>().velocity.x < -MaxPullForce
|| Player.GetComponent<Rigidbody>().velocity.y > MaxPullForce
|| Player.GetComponent<Rigidbody>().velocity.y < -MaxPullForce)
{
Player.Force_Add(forceDirection, Vector3.Distance(Player.transform.position, attachedPoint), pullForce * 0.05f, false );
}
if (attachedObject != null && attachedObject.velocity != null && attachedObject.velocity.x > MaxPullForce
|| attachedObject.velocity.x < -MaxPullForce
|| attachedObject.velocity.y > MaxPullForce
|| attachedObject.velocity.y < -MaxPullForce)
{
attachedObject.AddForce(-forceDirection * Vector3.Distance(Player.transform.position, attachedPoint) * pullForce * 0.05f);
}
if (attachedCharacter != null && attachedCharacter.GetComponent<Rigidbody>().velocity.x > MaxPullForce
|| attachedCharacter.GetComponentInParent<Rigidbody>().velocity.x < -MaxPullForce
|| attachedCharacter.GetComponentInParent<Rigidbody>().velocity.y > MaxPullForce
|| attachedCharacter.GetComponentInParent<Rigidbody>().velocity.y < -MaxPullForce)
{
attachedCharacter.Force_Add(-forceDirection, Vector3.Distance(Player.transform.position, attachedPoint), pullForce * 0.05f, false );
}
limitingPosition = true;
}
if (limitingPosition && Vector3.Distance(Player.transform.position, attachedPoint) < maxDistance)
{
Debug.Log("Removing force");
Player.Force_Remove();
if (attachedObject != null)
{
attachedObject.velocity = new Vector3(0.0f, 0.0f, 0.0f);
}
if (attachedCharacter != null)
{
attachedCharacter.Force_Remove();
}
limitingPosition = false;
}
var lineRenderer = chain.GetComponent<LineRenderer>();
lineRenderer.SetColors (Color.blue, Color.blue);
lineRenderer.material = new Material(Shader.Find("Legacy Shaders/Particles/Additive"));
lineRenderer.SetWidth(1f, 1f);
lineRenderer.SetPosition(0, Player.transform.position);
lineRenderer.SetPosition(1, attachedPoint);
// Position
if (ropeSegment != null)
{
ropeSegment.transform.position = (attachedPoint + cameraTransform.position) / 2.0f;
// Rotation
var heading = attachedPoint - cameraTransform.position;
var direction = heading / heading.magnitude;
ropeSegment.transform.rotation = new Quaternion(direction.x, direction.y, direction.z + defaultRopeSegmentOrientation, 0);
// Scale
var distance = Vector3.Distance(attachedPoint, Player.transform.position);
ropeSegment.transform.localScale = new Vector3(0.1f, distance / 2, 0.1f);
}
if (hasPullChainInputSequenceStarted && timer > pullChainInputTiming)
{
Debug.Log("Detaching");
isAttached = false;
inputPaused = true;
timer = 0.0f;
hasPullChainInputSequenceStarted = false;
attachedObject = null;
attachedCharacter = null;
attachment.transform.parent = null;
GameObject.Destroy(ropeSegment);
GameObject.Destroy(attachment);
return;
lineRenderer.SetWidth(0, 0);
}
else if (hasPullChainInputSequenceStarted && CheckInputDepressedThisFrame())
{
Debug.Log("Pulling");
// This is the preferred way of calculating direction between two Vectors
// other ways might cause performance issues
// See here: https://docs.unity3d.com/2018.3/Documentation/Manual/DirectionDistanceFromOneObjectToAnother.html
// TODO: look into syntax/performance impact for (vector.position - vector.position).normalized
var forceHeading = attachedPoint - cameraTransform.position;
var forceDirection = forceHeading / forceHeading.magnitude;
var applyToSelf = true;
if (attachedObject != null)
{
attachedObject.AddForce(-forceDirection * pullForce);
applyToSelf = false;
}
if (attachedCharacter != null)
{
attachedCharacter.Force_Add(-forceDirection, pullForce, pullAccel, false );
applyToSelf = false;
}
if (applyToSelf)
{
Player.Force_Add(forceDirection, pullForce, pullAccel, false );
}
attachedPoint = new Vector3(0, 0, 0);
inputPaused = true;
timer = 0.0f;
hasPullChainInputSequenceStarted = false;
}
else if (!hasPullChainInputSequenceStarted && !CheckInputDepressedThisFrame())
{
Debug.Log("Starting Dettachment");
hasPullChainInputSequenceStarted = true;
timer = 0.0f;
}
}
else
{
if (attachment != null)
{
if (attachment.GetComponent<GrappleAttachment>().CollisionStuck)
{
// attachment.GetComponent<Rigidbody>().constraints = RigidbodyConstraints.FreezeAll;
inputPaused = false;
isAttached = true;
}
else
{
// attachment.GetComponent<Rigidbody>().constraints = RigidbodyConstraints.None;
}
if (Vector3.Distance(Player.transform.position, transform.position) > Player.GetComponent<Grapple>().maxDistance)
{
timer = 0.0f;
GameObject.Destroy(attachment);
inputPaused = false;
isAttached = false;
return;
}
}
var lineRenderer = chain.GetComponent<LineRenderer>();
if (CheckInputDepressedThisFrame())
{
var raycastStart = cameraTransform.position + transform.forward * minDistance;
if (Physics.Raycast(raycastStart, cameraTransform.forward, out RaycastHit raycastHit))
{
if (Vector3.Distance(Player.transform.position, raycastHit.point) < maxDistance)
{
Debug.Log("Attaching");
attachedPoint = raycastHit.point;
isAttached = true;
inputPaused = true;
timer = 0.0f;
hasPullChainInputSequenceStarted = false;
if (raycastHit.transform != null && raycastHit.transform.gameObject != null)
{
if (raycastHit.transform.gameObject.GetComponent<Rigidbody>() != null)
{
attachedObject = raycastHit.transform.gameObject.GetComponent<Rigidbody>();
}
else if (raycastHit.transform.gameObject.GetComponentInChildren<Rigidbody>() != null)
{
attachedObject = raycastHit.transform.gameObject.GetComponentInChildren<Rigidbody>();
}
if (raycastHit.transform.gameObject.GetComponent<MalbersAnimations.Controller.MAnimal>() != null)
{
attachedCharacter = raycastHit.transform.gameObject.GetComponent<MalbersAnimations.Controller.MAnimal>();
}
if (raycastHit.transform.gameObject.GetComponentInChildren<MalbersAnimations.Controller.MAnimal>() != null)
{
attachedCharacter = raycastHit.transform.gameObject.GetComponentInChildren<MalbersAnimations.Controller.MAnimal>();
}
}
if (attachment == null)
{
attachment = Instantiate(AttachmentPrefab);
}
timer = 0.0f;
inputPaused = true;
hasPullChainInputSequenceStarted = false;
attachment.transform.localScale = new Vector3(6.25f, 6.25f, 18.75f);
var heading = attachedPoint - cameraTransform.position;
var direction = heading / heading.magnitude;
attachment.transform.position = Player.transform.position + Quaternion.AngleAxis(direction.x, Vector3.right) * transform.forward * 1;
// attachment.transform.position = new Vector3(Player.transform.position.x, Player.transform.position.y + playerHeight + playerHeightBuffer, Player.transform.position.z + playerWidth * 2);
attachment.GetComponent<Rigidbody>().AddForce(direction * PushForce);
// attachment.GetComponent<Rigidbody>().AddForce(direction * PushForce, ForceMode.Impulse);
attachment.transform.position = raycastHit.point;
attachment.transform.rotation = (Quaternion.Euler(cameraTransform.rotation.x, gameObject.transform.rotation.y, 0));
if (attachedObject != null)
{
attachment.transform.parent = attachedObject.transform;
}
if (attachedCharacter != null)
{
attachment.transform.parent = attachedCharacter.transform;
}
}
else
{
Debug.Log("Missing / Too Far");
}
}
else
{
Debug.Log("Missing");
inputPaused = true;
timer = 0.0f;
hasPullChainInputSequenceStarted = false;
}
}
}
}
}