using System; using System.Collections.Generic; using UltimateWater; using UnityEngine; using UnityEngine.Rendering; namespace PhysicsTools { [RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))] public class Rope : MonoBehaviour { public enum RopeGameplayType { NORMAL = 0, ICE = 1, FLOAT = 2 } [Serializable] public enum LOGGING { NONE = 0, INFO = 1, DEBUG = 2 } [Serializable] public enum RopeType { Procedural = 0, FromBones = 1 } [Serializable] public enum RendererType { None = 0, Continuous = 1, Segment = 2 } public delegate void BrokenHandler(object sender); public delegate void CreateHandler(object sender); public delegate void DeleteHandler(object sender); public RopeGameplayType ropeGameplayType; private List prevControlPoints = new List(); private bool prevKinematic = true; private bool prevHideChildren = true; private RendererType prevRendererType = RendererType.Continuous; public bool startJointSpringy; public SerializedSoftJointLimitSpring startJtSpring; public bool endJointSpringy; public SerializedSoftJointLimitSpring endJtSpring; private string prevStrStaticBones; public string strStaticBones; private HashSet staticBones = new HashSet(); public PhysicMaterial ropeMaterial; private GameObject springHolder; private Joint springJoint; [HideInInspector] public List lstComponentsCreated = new List(); public bool HideChildren = true; public LOGGING loggingType = LOGGING.INFO; public RopeType ropeType; public int numControlPoints = 2; public List controlPoints = new List(); public Transform startPosition; public float rate; [Range(0f, 10f)] public float gravity = 1f; public bool kinematic = true; private GameObject prevFirstBone; private GameObject prevLastBone; public GameObject firstBone; public GameObject lastBone; public bool sendRopeEvents; public RendererType rendererType = RendererType.Continuous; public LinkMesh linkMesh = new LinkMesh(); public Material continuousMaterial; public MeshRenderer meshRenderer; public MeshFilter meshFilter; public bool useColliders = true; public float radiusFactor = 1f; public float segmentBordersScaleFactor = 1f; public bool useSegmentBordersOffset; public SegmentProperties.Type segPropertyType; public SegmentPropertiesBox segPropertiesBox = new SegmentPropertiesBox(); public SegmentPropertiesCylinder segPropertiesCylinder = new SegmentPropertiesCylinder(); public JointProperties jointProp = new JointProperties(); private int initialNumSegemnts; public List lstSegments = new List(); private Mesh mesh; private Vector3[] vertexBuffer; private Vector2[] uv; private int[] indexBuffer; private Vector4[] tangents; public float totalLengthGet; public float tensionGet; public float totalLength; public float totalLengthColliders; public float ropeStretchThreshold = -1f; public float textureLength = 0.33f; private int numCirclePt = 3; public event BrokenHandler Broken; public event CreateHandler Created; public event DeleteHandler Deleted; public void setStartJointSpring(SoftJointLimitSpring sp) { startJtSpring = (SerializedSoftJointLimitSpring)sp; if (springJoint != null) { ConfigurableJoint configurableJoint = (ConfigurableJoint)springJoint.joint; if (configurableJoint != null) { configurableJoint.linearLimitSpring = getStartJtSpring(); configurableJoint.linearLimit = new SoftJointLimit { limit = 0.01f }; } } } public void setEndJointSpring(SoftJointLimitSpring sp) { endJtSpring = (SerializedSoftJointLimitSpring)sp; if (lstSegments.Count != 0) { ConfigurableJoint configurableJoint = ((lstSegments[lstSegments.Count - 1].next == null) ? null : ((ConfigurableJoint)lstSegments[lstSegments.Count - 1].next.joint)); if (configurableJoint != null) { configurableJoint.linearLimitSpring = getEndJtSpring(); configurableJoint.linearLimit = new SoftJointLimit { limit = 0.01f }; } } } public SegmentPropertiesBase getSegmentProperties() { switch (segPropertyType) { case SegmentProperties.Type.BOX: return segPropertiesBox; case SegmentProperties.Type.CYLINDER: return segPropertiesCylinder; default: return segPropertiesCylinder; } } public void setPhysicsMaterial(PhysicMaterial mat) { foreach (Segment lstSegment in lstSegments) { lstSegment.capsuleCollider.sharedMaterial = mat; } } private void Debug(string msg, LOGGING type) { if (type <= loggingType) { UnityEngine.Debug.Log(msg, this); } } private void OnJointBreak(float breakForce) { if (sendRopeEvents && this.Broken != null) { this.Broken(this); } } public void setContinuousMaterialMapping(float f) { textureLength = f; } public void setFirstBone(GameObject bone) { firstBone = bone; } public void setLastBone(GameObject bone) { lastBone = bone; } public List getSegments() { return lstSegments; } public void setStaticBoneList(string str) { staticBones.Clear(); str.Trim(); if (str != string.Empty) { string[] array = str.Split(','); string[] array2 = array; foreach (string text in array2) { string[] array3 = text.Split('-'); if (array3.Length == 1) { staticBones.Add(int.Parse(array3[0])); } else if (array3.Length == 2) { int num = int.Parse(array3[0]); int num2 = int.Parse(array3[1]); for (int j = num; j <= num2; j++) { staticBones.Add(j); } } } } strStaticBones = str; prevStrStaticBones = str; } public bool setControlPoints(List lstControlPoints) { if (numControlPoints < 2 && ropeType == RopeType.Procedural) { throw new ArgumentException("Control points should be more than 1"); } bool flag = false; if (numControlPoints != lstControlPoints.Count) { while (lstControlPoints.Count < numControlPoints) { lstControlPoints.Add(new ControlPoint()); } while (lstControlPoints.Count > numControlPoints) { lstControlPoints.RemoveAt(lstControlPoints.Count - 1); } flag = true; } for (int i = 0; i < lstControlPoints.Count; i++) { if (i < prevControlPoints.Count && !lstControlPoints[i].compare(prevControlPoints[i])) { flag = true; break; } } prevControlPoints.Clear(); for (int j = 0; j < lstControlPoints.Count; j++) { prevControlPoints.Add(lstControlPoints[j].clone()); } if (flag) { controlPoints.Clear(); for (int k = 0; k < prevControlPoints.Count; k++) { controlPoints.Add(prevControlPoints[k].clone()); } } numControlPoints = lstControlPoints.Count; return flag; } public SoftJointLimitSpring getStartJtSpring() { SoftJointLimitSpring result = default(SoftJointLimitSpring); if (startJointSpringy) { result.spring = startJtSpring.spring; result.damper = startJtSpring.damper; } else { float spring = (result.damper = 0f); result.spring = spring; } return result; } public SoftJointLimitSpring getEndJtSpring() { SoftJointLimitSpring result = default(SoftJointLimitSpring); if (endJointSpringy) { result.spring = endJtSpring.spring; result.damper = endJtSpring.damper; } else { float spring = (result.damper = 0f); result.spring = spring; } return result; } public void RefreshJointSpring() { setStartJointSpring(startJtSpring); setEndJointSpring(endJtSpring); } public void RefreshProperties(bool bForce) { Debug("Refreshing Properties Force = " + bForce, LOGGING.INFO); bool flag = bForce; if (numControlPoints < 2) { numControlPoints = 2; } bool flag2 = setControlPoints(controlPoints); flag = flag || flag2; if (prevStrStaticBones != strStaticBones) { setStaticBoneList(strStaticBones); flag = true; } if (flag) { regenerateRope(true); } if (prevHideChildren != HideChildren) { HideChildrenObjects(HideChildren); } if (prevKinematic != kinematic) { changeToKinematic(kinematic); } if (prevRendererType != rendererType) { setRendererType(rendererType); } linkMesh.update(); setLinkMesh(linkMesh); if (rendererType == RendererType.Continuous) { generateOverallMesh(); } Debug("Refreshing Properties Done", LOGGING.INFO); } public void setBreakingForce(float force) { Debug("Setting breaking force to " + force, LOGGING.INFO); foreach (Segment lstSegment in lstSegments) { if (lstSegment.next != null) { if (force != 0f) { lstSegment.next.joint.breakForce = force; } else { lstSegment.next.joint.breakForce = 1E+10f; } } } jointProp.breakingForce = force; Debug("Setting breaking force done", LOGGING.INFO); } public void setRendererType(RendererType rType) { Debug("Setting Renderer Type to " + rType, LOGGING.INFO); switch (rType) { case RendererType.Continuous: enableRendering(true); enableSegmentRendering(false); break; case RendererType.Segment: enableRendering(false); enableSegmentRendering(true); break; case RendererType.None: enableRendering(false); enableSegmentRendering(false); break; } rendererType = rType; prevRendererType = rType; } public void setLinkMesh(LinkMesh lMesh) { if (lMesh != null && lMesh.getMesh() != null) { foreach (Segment lstSegment in lstSegments) { lstSegment.meshFilter.sharedMesh = lMesh.getMesh(); lstSegment.meshRenderer.sharedMaterial = lMesh.meshMaterial; } } linkMesh = lMesh; } public void applyGravity(float f) { if (f == -1f) { return; } foreach (Segment lstSegment in lstSegments) { lstSegment.body.AddForce((0f - (1f - f)) * lstSegment.body.mass * Physics.gravity); } } public void updateMass(float m) { getSegmentProperties().massPerUnitLength = m; float mass = getSegmentProperties().massPerUnitLength * getSegmentProperties().length; foreach (Segment lstSegment in lstSegments) { lstSegment.body.mass = mass; } } private void HideChildrenObjects(bool bHide) { foreach (Segment lstSegment in lstSegments) { if (bHide) { lstSegment.seg.hideFlags = HideFlags.HideInHierarchy; } else { lstSegment.seg.hideFlags = HideFlags.None; } } prevHideChildren = bHide; } public List> getTrajectory() { List> list = new List>(); float num = segmentBordersScaleFactor; float num2 = ((!useSegmentBordersOffset || lstSegments.Count <= 0) ? 0f : lstSegments[0].capsuleCollider.radius); num2 *= num; float num3 = 1f; int num4 = lstSegments.Count; if (num4 > 30 && GameController.Instance.useFastRopeDraw) { num4 = 30; } List list2 = new List(); int num5 = 0; if (lstSegments.Count > 0) { foreach (Segment lstSegment in lstSegments) { if (list2.Count == 0) { PosOri posOri = new PosOri(lstSegment.seg.transform.TransformPoint(new Vector3(0f, 0f - getSegmentProperties().length - num2, 0f)), lstSegment.seg.transform.rotation); posOri.pos = startPosition.position; list2.Add(posOri); } PosOri item = new PosOri(lstSegment.seg.transform.position, lstSegment.seg.transform.rotation); list2.Add(item); if (lstSegment.next == null && num5 < num4 - 1) { PosOri item2 = new PosOri(lstSegment.seg.transform.TransformPoint(new Vector3(0f, getSegmentProperties().length * num3, 0f)), lstSegment.seg.transform.rotation); list2.Add(item2); list.Add(list2); list2 = new List(); } num5++; if (num5 > num4) { break; } } PosOri item3 = new PosOri(lstSegments[Mathf.Min(num4, lstSegments.Count) - 1].seg.transform.TransformPoint(new Vector3(0f, getSegmentProperties().length + num2, 0f)), lstSegments[0].seg.transform.rotation); list2.Add(item3); } list.Add(list2); return list; } private void generateMeshForTrajectory(List trajectory, Bezier interpolator, float totalLen, ref float lengthCovered, ref int lastVertId, ref int lastIndexID) { float num = ((segPropertyType != SegmentProperties.Type.CYLINDER) ? segPropertiesBox.width : segPropertiesCylinder.radius); num *= radiusFactor; float num2 = 6.28318f / (float)numCirclePt; Vector3[] array = new Vector3[numCirclePt]; Vector3[] array2 = new Vector3[numCirclePt]; for (int i = 0; i < numCirclePt; i++) { array[i] = new Vector3((float)((double)num * Math.Cos((float)i * num2)), 0f, (float)((double)num * Math.Sin((float)i * num2))); array2[i] = new Vector3((float)((double)(0f - num) * Math.Sin((float)i * num2)), 0f, (float)((double)num * Math.Cos((float)i * num2))); array2[i].Normalize(); } int num3 = lastVertId; Vector3 v = new Vector3(0f, 0f, 1f); Vector3 vector = new Vector3(1f, 1f, 1f); Vector3 vector2 = new Vector3(0.3f, 1f, 0.3f); Vector3 s = new Vector3(0.2f, 1f, 0.2f); float num4 = 0f; Vector3 vector3 = trajectory[0].pos; int num5 = trajectory.Count * 4; float deltaLen = totalLen / (float)(num5 - 1); for (int j = 0; j < num5; j++) { Vector3 vector4 = ((j != 0) ? interpolator.getNext(deltaLen).pos : trajectory[0].pos); if (j != 0) { v = vector4 - vector3; v.Normalize(); } else if (j == 0 && trajectory.Count > 1) { v = trajectory[1].pos - vector4; v.Normalize(); } Vector3 vector5 = vector4 - vector3; vector3 = vector4; Matrix4x4 matrix4x = default(Matrix4x4); for (int k = 0; k < numCirclePt; k++) { Quaternion q = Utility.createOrientation(v); if (GameController.Instance.fishingPlayer.currentHands.fishingLine.lineType == FishingLine.LineType.FLY && j >= num5 - 8) { matrix4x.SetTRS(vector4, q, s); } else { matrix4x.SetTRS(vector4, q, (!(vector4.y < 0f)) ? vector : vector2); } vertexBuffer[num3] = base.transform.InverseTransformPoint(matrix4x.MultiplyPoint(array[k])); if (j == 0) { } Vector3 vector6 = base.transform.InverseTransformDirection(matrix4x.MultiplyVector(array2[k])); tangents[num3] = new Vector4(vector6.x, vector6.y, vector6.z, -1f); if (j == 1) { } uv[num3] = new Vector2((float)k * 1f / (float)numCirclePt, (totalLen - num4) / textureLength); num3++; } num4 += vector5.magnitude; } if (true) { int num6 = lastIndexID; for (int l = 0; l < num5 - 1; l++) { for (int m = 0; m < numCirclePt; m++) { int num7 = l + lastVertId / numCirclePt; indexBuffer[num6++] = num7 * numCirclePt + m; indexBuffer[num6++] = (num7 + 1) * numCirclePt + m; indexBuffer[num6++] = num7 * numCirclePt + (m + 1) % numCirclePt; indexBuffer[num6++] = num7 * numCirclePt + (m + 1) % numCirclePt; indexBuffer[num6++] = (num7 + 1) * numCirclePt + m; indexBuffer[num6++] = (num7 + 1) * numCirclePt + (m + 1) % numCirclePt; } } lastIndexID = num6; } lengthCovered += num4; lastVertId = num3; } public void generateOverallMesh() { if ((bool)GameController.Instance.fishingPlayer && GameController.Instance.optimalRopeGenerator && ((GameController.Instance.fishingPlayer.currentHands.fakeStraightLine.enabled && ropeGameplayType != RopeGameplayType.FLOAT) || GameController.Instance.fishingPlayer.underwaterCamera.isTurnedOn)) { return; } List> trajectory = getTrajectory(); if (trajectory[0].Count <= 0) { return; } int num = 0; int num2 = 0; bool flag = false; foreach (List item in trajectory) { int num3 = item.Count * 4; num += num3; num2 += (num3 - 1) * (numCirclePt * 2); } int num4 = numCirclePt * num; if (vertexBuffer == null || num4 != vertexBuffer.Length) { flag = vertexBuffer == null || num4 > vertexBuffer.Length; vertexBuffer = new Vector3[num4]; tangents = new Vector4[num4]; uv = new Vector2[num4]; } if (indexBuffer == null || num2 * 3 != indexBuffer.Length) { indexBuffer = new int[num2 * 3]; } int lastVertId = 0; int lastIndexID = 0; List list = new List(); float num5 = 0f; foreach (List item2 in trajectory) { list.Add(new Bezier(item2)); num5 += list[list.Count - 1].TotalLength(); } float lengthCovered = 0f; for (int i = 0; i < trajectory.Count; i++) { generateMeshForTrajectory(trajectory[i], list[i], num5, ref lengthCovered, ref lastVertId, ref lastIndexID); } if (mesh == null) { mesh = new Mesh(); } if (flag) { mesh.vertices = vertexBuffer; mesh.triangles = indexBuffer; } else { mesh.triangles = indexBuffer; mesh.vertices = vertexBuffer; } mesh.uv = uv; mesh.RecalculateNormals(); mesh.tangents = tangents; meshFilter.sharedMesh = mesh; meshRenderer.sharedMaterial = continuousMaterial; mesh.bounds = new Bounds(base.transform.position, new Vector3(10000f, 10000f, 10000f)); } public void regenerateRope(bool bDestroyImmediate) { deleteRope(bDestroyImmediate); generateCatnaryRope(controlPoints.ToArray()); setLinkMesh(linkMesh); initialNumSegemnts = lstSegments.Count; } public void generateRope(ControlPoint[] arrPoints) { bool flag = false; List list = new List(arrPoints.Length); for (int i = 0; i < arrPoints.Length; i++) { list.Add(arrPoints[i].localPos); if (arrPoints[i].obj != null) { list[i] = arrPoints[i].obj.transform.TransformPoint(arrPoints[i].localPos); } else { list[i] = ((!flag) ? base.gameObject.transform.TransformPoint(arrPoints[i].localPos) : arrPoints[i].localPos); } } SCapsulePos sCapsulePos = new SCapsulePos(); bool flag2 = false; int last = 0; bool flag3 = false; Segment segment = null; Quaternion quaternion = Quaternion.identity; Quaternion quaternion2 = Quaternion.AngleAxis(jointProp.twistOffsetDeg, new Vector3(0f, 1f, 0f)); totalLength = 0f; Vector3 vector = list[0]; int num = 0; while (!flag2) { int num2 = last; flag2 = getNextCapsulePos(sCapsulePos, list, ref last, getSegmentProperties(), jointProp, false); Segment segment2 = null; if (sCapsulePos.fLen > 0f) { segment2 = createSegment(sCapsulePos.fLen, sCapsulePos.vPos, sCapsulePos.vDir); if (useColliders && num >= 0) { if ((bool)segment2.capsuleCollider) { segment2.capsuleCollider.enabled = true; } num = 0; } else { if ((bool)segment2.capsuleCollider) { segment2.capsuleCollider.enabled = false; } num++; } lstSegments.Add(segment2); if (segment != null) { totalLength += (sCapsulePos.vPos - vector).magnitude; vector = sCapsulePos.vPos; segment.next = createSegmentJoint(segment, segment2, quaternion); segment2.prev = segment.next; } GameObject gameObject = null; Vector3 vector2 = new Vector3(0f, 0f, 0f); bool flag4 = false; if (!flag3 && num2 == 0) { if (arrPoints[num2].attached) { gameObject = arrPoints[num2].obj; vector2 = arrPoints[num2].localPos; flag4 = true; } } else if (num2 != last && last < arrPoints.Length && arrPoints[last].attached) { gameObject = arrPoints[last].obj; vector2 = arrPoints[last].localPos; flag4 = true; } if (flag4) { vector2 = ((gameObject != null) ? gameObject.transform.TransformPoint(vector2) : ((!flag) ? base.gameObject.transform.TransformPoint(vector2) : vector2)); int jtPos = -1; Joint prev = new Joint(segment2.seg, gameObject, vector2, segment2.seg.transform.TransformDirection(0f, 1f, 0f), jointProp, this, jtPos); if (num2 == 0) { segment2.prev = prev; } flag3 = true; } segment = segment2; quaternion = quaternion2 * quaternion; } else { flag2 = true; } } if (lstSegments.Count == 1) { GameObject obj = arrPoints[last].obj; Vector3 localPos = arrPoints[last].localPos; int jtPos2 = -1; Segment segment3 = lstSegments[0]; Joint prev2 = new Joint(segment3.seg, obj, localPos, segment3.seg.transform.TransformDirection(0f, 1f, 0f), jointProp, this, jtPos2); segment3.prev = prev2; } if (lstSegments.Count > 0 && !lstSegments[lstSegments.Count - 1].seg.GetComponent()) { GameObject obj2 = arrPoints[last].obj; Vector3 localPos2 = arrPoints[last].localPos; int jtPos3 = -1; Segment segment4 = lstSegments[lstSegments.Count - 1]; Joint joint = new Joint(segment4.seg, obj2, localPos2, segment4.seg.transform.TransformDirection(0f, 1f, 0f), jointProp, this, jtPos3); } if (sendRopeEvents && this.Created != null) { this.Created(this); } } public void generateCatnaryRope(ControlPoint[] arrPoints) { Debug("Generating Catenary Rope " + arrPoints.ToString(), LOGGING.INFO); if (arrPoints.Length < 2) { return; } List list = new List(); Vector3 vector = ((!(arrPoints[0].obj != null)) ? arrPoints[0].localPos : arrPoints[0].obj.transform.TransformPoint(arrPoints[0].localPos)); list.Add(arrPoints[0]); for (int i = 1; i < arrPoints.Length; i++) { Vector3 vector2 = ((!(arrPoints[i].obj != null)) ? arrPoints[i].localPos : arrPoints[i].obj.transform.TransformPoint(arrPoints[i].localPos)); ControlPoint controlPoint = arrPoints[i - 1]; if (controlPoint.slackFraction > 1f) { float magnitude = (vector2 - vector).magnitude; SegmentPropertiesBase segmentProperties = getSegmentProperties(); List catenaryPts = Utility.getCatenaryPts(vector, vector2, magnitude * controlPoint.slackFraction, (int)(magnitude / segmentProperties.length)); for (int j = 1; j < catenaryPts.Count; j++) { ControlPoint controlPoint2 = new ControlPoint(); controlPoint2.attached = false; controlPoint2.obj = null; controlPoint2.localPos = catenaryPts[j]; if (j == catenaryPts.Count - 1) { controlPoint2.attached = arrPoints[i].attached; controlPoint2.obj = arrPoints[i].obj; controlPoint2.localPos = ((!(controlPoint2.obj != null)) ? controlPoint2.localPos : controlPoint2.obj.transform.InverseTransformPoint(controlPoint2.localPos)); } list.Add(controlPoint2); } } else { list.Add(arrPoints[i]); } vector = vector2; } generateRope(list.ToArray()); Debug("Generating Catenary Rope done", LOGGING.INFO); } public void deleteRope(bool bDestroyImmediate) { if (lstSegments != null) { foreach (Segment lstSegment in lstSegments) { if (bDestroyImmediate) { UnityEngine.Object.DestroyImmediate(lstSegment.seg); } else { UnityEngine.Object.Destroy(lstSegment.seg); } } lstSegments.Clear(); } if (springJoint != null) { UnityEngine.Object.Destroy(springJoint.joint); } if (springHolder != null) { UnityEngine.Object.Destroy(springHolder); } if (bDestroyImmediate) { clearOrphan(); } if (sendRopeEvents && this.Deleted != null) { this.Deleted(this); } } public float getLength() { return totalLength; } public float getLengthColliders() { return totalLengthColliders; } public float getTension() { if (springJoint != null && springJoint.joint != null) { ConfigurableJoint configurableJoint = (ConfigurableJoint)springJoint.joint; Vector3 vector = configurableJoint.connectedAnchor; Rigidbody connectedBody = configurableJoint.connectedBody; Vector3 vector2 = configurableJoint.anchor; Rigidbody body = lstSegments[0].body; if (connectedBody != null) { vector = connectedBody.transform.TransformPoint(vector); } if (body != null) { vector2 = body.transform.TransformPoint(vector2); } float num = (vector - vector2).magnitude - 0.01f; return num * configurableJoint.linearLimitSpring.spring; } if (lstSegments.Count > 0 && lstSegments[0].prev != null) { UnityEngine.Joint joint = lstSegments[0].prev.joint; Vector3 vector3 = joint.connectedAnchor; Rigidbody connectedBody2 = joint.connectedBody; Vector3 vector4 = joint.anchor; Rigidbody body2 = lstSegments[0].body; if (connectedBody2 != null) { vector3 = connectedBody2.transform.TransformPoint(vector3); } if (body2 != null) { vector4 = body2.transform.TransformPoint(vector4); } float num2 = (vector3 - vector4).magnitude - 0.01f; return num2 * ((ConfigurableJoint)joint).linearLimitSpring.spring; } return 0f; } public void breakRope(float fraction) { Debug("Breaking Rope from Fraction: " + fraction, LOGGING.INFO); int num = (int)((float)lstSegments.Count * fraction); if (num < lstSegments.Count - 1 && num >= 0) { Debug("Breaking Rope from segment: " + num, LOGGING.DEBUG); if (lstSegments[num].next != null) { UnityEngine.Object.Destroy(lstSegments[num].next.joint); lstSegments[num].next = null; lstSegments[num + 1].prev = null; } } Debug("Breaking Rope done", LOGGING.INFO); } public void setLength(float newLength) { newLength -= getLength(); changeLength(newLength); } public void changeLength(float deltaLen) { if (lstSegments.Count < 1 || deltaLen == 0f) { CalculateTotalLength(); return; } deltaLen *= 0.5f; int num = 0; Segment segment = lstSegments[num]; SegmentPropertiesBase segmentProperties = getSegmentProperties(); Vector3 localScale = segment.seg.transform.localScale; if (localScale.y > 0f) { localScale.y += deltaLen; } if (localScale.y < 0.01f) { localScale.y = 0.01f; } float num2 = 0.5f; float num3 = 1f; float num4 = 0f; float num5 = 0f; float num6 = segmentProperties.length * num2; num5 = ((SegmentPropertiesCylinder)segmentProperties).radius * 2f; if (localScale.y > (segmentProperties.length + num5) * num2) { Vector3 localScale2 = segment.seg.transform.localScale; localScale2.y = num6; segment.seg.transform.localScale = localScale2; float num7 = 0f; for (deltaLen = 0f - segmentProperties.length + localScale.y / num2; deltaLen > 0f; deltaLen -= num7) { num7 = Mathf.Clamp(deltaLen, 0.01f, num6); segment.seg.transform.position += segment.seg.transform.TransformDirection(0f, 1f, 0f) * num7; if (segment.next != null) { if (segment.next.joint.connectedBody != segment.body) { segment.next.joint.anchor = new Vector3(0f, (1f - jointProp.offsetScale) * num3, 0f); } else { segment.next.joint.connectedAnchor = new Vector3(0f, (1f - jointProp.offsetScale) * num3, 0f); } } Vector3 pos = segment.seg.transform.position - segment.seg.transform.TransformDirection(0f, 1f, 0f) * (num7 + segmentProperties.length / 2f); Segment segment2 = createSegment(num7 * 2f, pos, segment.seg.transform.TransformDirection(0f, 1f, 0f)); float num8 = jointProp.twistOffsetDeg * (float)(-1 + (initialNumSegemnts - lstSegments.Count)); num8 = (num8 + 36000f) % 360f; Quaternion quaternion = Quaternion.AngleAxis(num8, new Vector3(0f, 1f, 0f)); segment2.seg.transform.rotation = segment2.seg.transform.rotation * quaternion; Rigidbody connectedBody = segment.prev.joint.connectedBody; Vector3 connectedAnchor = segment.prev.joint.connectedAnchor; Vector3 vGlobalAnchor = ((!connectedBody) ? connectedAnchor : connectedBody.transform.TransformPoint(connectedAnchor)); Joint prev = new Joint(segment2.seg, (!connectedBody) ? null : connectedBody.gameObject, vGlobalAnchor, segment2.seg.transform.TransformDirection(0f, 1f, 0f), jointProp, this, -1); segment2.prev = prev; Joint prev2 = (segment2.next = new Joint(segment2, segment, jointProp, getSegmentProperties(), Quaternion.identity)); Joint prev3 = segment.prev; segment.prev = prev2; lstSegments.Insert(0, segment2); UnityEngine.Object.Destroy(prev3.joint); FixAnchors(segment2, num3); segment = segment2; } CalculateTotalLength(); } else if (localScale.y < num5 * num2) { while (deltaLen < 0f) { if (lstSegments.Count < num + 1 + 1) { UnityEngine.Debug.LogError("!!! changeLength lstSegments size error index !!!: " + num); if (GameController.Instance.fishingPlayer.currentState == FishingPlayer.PlayerState.FISHING || GameController.Instance.fishingPlayer.currentState == FishingPlayer.PlayerState.ICE_FISHING) { GameController.Instance.fishingPlayer.LineBreak(Utilities.GetTranslation("HUD_MESSAGE/LINE_BROKE_TENSION"), 0f); } return; } Segment segment3 = lstSegments[num + 1]; Vector3 localScale3 = segment3.seg.transform.localScale; localScale3.y = num6; segment3.seg.transform.localScale = localScale3; segment.seg.transform.position += segment.seg.transform.TransformDirection(0f, -1f, 0f) * localScale.y / num2; Vector3 connectedAnchor2 = segment.prev.joint.connectedAnchor; Rigidbody connectedBody2 = segment.prev.joint.connectedBody; Vector3 vGlobalAnchor2 = ((!connectedBody2) ? connectedAnchor2 : connectedBody2.transform.TransformPoint(connectedAnchor2)); Joint prev4 = new Joint(segment3.seg, (!connectedBody2) ? null : connectedBody2.gameObject, vGlobalAnchor2, segment3.seg.transform.TransformDirection(0f, 1f, 0f), jointProp, this, -1); segment3.prev = prev4; deltaLen += segment.seg.transform.localScale.y; lstSegments.Remove(segment); UnityEngine.Object.Destroy(segment.seg); FixAnchors(segment3, num3); segment = segment3; if (!(deltaLen < 0f)) { } } CalculateTotalLength(); } else { segment.seg.transform.localScale = localScale; FixAnchors(segment, num3); CalculateTotalLength(); } } public void FixAnchors(Segment seg, float anchorMult) { Joint prev = seg.prev; Joint next = seg.next; if (prev != null) { if (prev.joint.connectedBody != seg.body) { prev.joint.anchor = new Vector3(0f, (-1f + jointProp.offsetScale) * anchorMult, 0f); } else { prev.joint.connectedAnchor = new Vector3(0f, (-1f + jointProp.offsetScale) * anchorMult, 0f); } } if (next != null) { if (next.joint.connectedBody != seg.body) { next.joint.anchor = new Vector3(0f, (1f - jointProp.offsetScale) * anchorMult, 0f); } else { next.joint.connectedAnchor = new Vector3(0f, (1f - jointProp.offsetScale) * anchorMult, 0f); } } } private void clearOrphan() { Debug("Clear Orphan", LOGGING.INFO); if (lstComponentsCreated != null) { foreach (UnityEngine.Object item in lstComponentsCreated) { UnityEngine.Object.DestroyImmediate(item); } lstComponentsCreated.Clear(); } Debug("Clear Orphan done", LOGGING.INFO); } private void OnEnable() { } private void Awake() { meshRenderer = GetComponent(); meshFilter = GetComponent(); if (startPosition == null && (bool)controlPoints[0].obj) { startPosition = controlPoints[0].obj.transform; } List list = new List(); for (int i = 0; i < base.transform.childCount; i++) { if (base.transform.GetChild(i).name.Contains("__rope__")) { list.Add(base.transform.GetChild(i).gameObject); } } foreach (GameObject item in list) { UnityEngine.Object.Destroy(item); } lstSegments = new List(); if (ropeType == RopeType.FromBones) { rendererType = RendererType.None; } regenerateRope(true); setRendererType(rendererType); } private void Start() { } private void FixedUpdate() { changeLength(rate); if (gravity != -1f) { applyGravity(gravity); } } private void LateUpdate() { generateOverallMesh(); } private void checkBrokenJoints() { foreach (Segment lstSegment in lstSegments) { if (lstSegment.prev != null && lstSegment.prev.joint == null) { lstSegment.prev = null; } if (lstSegment.next != null && lstSegment.next.joint == null) { lstSegment.next = null; } } } private void checkStabilization() { foreach (Segment lstSegment in lstSegments) { float num = lstSegment.body.velocity.sqrMagnitude * lstSegment.body.mass + lstSegment.body.inertiaTensor.magnitude * lstSegment.body.angularVelocity.sqrMagnitude; if (num > lstSegment.body.mass * 25f) { lstSegment.body.velocity = new Vector3(0f, 0f, 0f); lstSegment.body.angularVelocity = new Vector3(0f, 0f, 0f); } } } public void changeToKinematic(bool b) { int num = 0; foreach (Segment lstSegment in lstSegments) { if (ropeType == RopeType.Procedural || (ropeType == RopeType.FromBones && !staticBones.Contains(num))) { lstSegment.body.isKinematic = b; } num++; } kinematic = b; prevKinematic = b; } private void enableRendering(bool b) { Debug("Enable Rendering " + b, LOGGING.INFO); meshRenderer.enabled = b; Debug("Enable Rendering done", LOGGING.INFO); } private void enableSegmentRendering(bool b) { Debug("Enable Segment Rendering " + b, LOGGING.INFO); foreach (Segment lstSegment in lstSegments) { lstSegment.meshRenderer.enabled = b; } Debug("Enable Segment Rendering done", LOGGING.INFO); } private bool getNextCapsulePos(SCapsulePos capPose, List vecPts, ref int last, SegmentPropertiesBase segProp, JointProperties jointProp, bool bExtraSegPosAtStart) { capPose.vPrevPos = capPose.vPos; capPose.vPrevDir = capPose.vDir; if (bExtraSegPosAtStart) { capPose.vPos += capPose.vDir * capPose.fLen * (1f - jointProp.offsetScale); capPose.vDir *= -1f; } bool result = false; if (capPose.vDir.magnitude != 0f) { Vector3 vDir = capPose.vDir; capPose.vPos += vDir * capPose.fLen * (1f - jointProp.offsetScale); } else { capPose.vPos = vecPts[last]; } int num = last + 1; if (num < vecPts.Count && num >= 0) { Vector3 vDir2 = vecPts[num] - capPose.vPos; float magnitude = vDir2.magnitude; vDir2.Normalize(); float length = segProp.length; capPose.fLen = length; capPose.vDir = vDir2; if (magnitude < segProp.length) { last = num; num = last + 1; if (last == 0 || last == vecPts.Count - 1) { capPose.fLen = magnitude; result = true; } } } if (bExtraSegPosAtStart) { capPose.vPos += capPose.vDir * capPose.fLen; capPose.vDir *= -1f; } return result; } private Segment createBoneSegment(float len, Vector3 pos, Vector3 dir, GameObject bone) { Quaternion q = Utility.createOrientation(dir); BoneSegment boneSegment = new BoneSegment("segment-" + lstSegments.Count + "__rope__", len, pos + dir * len / 2f, q, getSegmentProperties(), this, bone); boneSegment.seg.transform.parent = base.gameObject.transform; return boneSegment; } private Segment createSegment(float len, Vector3 pos, Vector3 dir) { Quaternion q = Utility.createOrientation(dir); Segment segment = new Segment("segment-" + lstSegments.Count + "__rope__", len, pos + dir * len / 2f, q, getSegmentProperties(), this); segment.seg.transform.parent = base.gameObject.transform; if ((bool)GameController.Instance) { segment.meshRenderer.enabled = true; segment.meshRenderer.material = GameController.Instance.waterInteractiveMaterial; segment.meshRenderer.shadowCastingMode = ShadowCastingMode.Off; } else { segment.meshRenderer.enabled = false; } if (totalLength <= 105f) { segment.waterInteractive = segment.seg.AddComponent(); segment.waterInteractive.Multiplier = 1.5f; } return segment; } private Joint createSegmentJoint(Segment seg1, Segment seg2, Quaternion twistOffset) { return new Joint(seg1, seg2, jointProp, getSegmentProperties(), twistOffset); } public void CalculateTotalLength() { totalLength = 0f; totalLengthColliders = 0f; for (int i = 0; i < lstSegments.Count; i++) { totalLengthColliders += lstSegments[i].seg.transform.localScale.y * lstSegments[i].capsuleCollider.height; if (i == 0) { totalLength += (lstSegments[i].seg.transform.position - controlPoints[0].obj.transform.position).magnitude; } if (i == lstSegments.Count - 1) { totalLength += (lstSegments[i].seg.transform.position - controlPoints[1].obj.transform.position).magnitude; } if (i > 0) { totalLength += (lstSegments[i].seg.transform.position - lstSegments[i - 1].seg.transform.position).magnitude; } } if (VRManager.IsVROn()) { totalLengthColliders *= GameController.Instance.fishingPlayer.vrHandsParent.transform.localScale.y; } if (ropeStretchThreshold > 0f && totalLength - totalLengthColliders > ropeStretchThreshold) { regenerateRope(true); UnityEngine.Debug.LogError("Rope stretch regenerate"); } } } }