using System; using System.Collections; using System.Linq; using Obvious.Soap; using Obvious.Soap.Attributes; using UFS3; using UnityEngine; using UnityWaterTools; public class Lure : MonoBehaviour, IInitializable { private static readonly int Speed = Animator.StringToHash("speed"); public MeshRenderer lureMeshRenderer; public float lureSize; public Transform lookTarget; [SerializeField] private FloatVariable lineLength; [Tooltip("This variable defines is main lure for raising events")] [SerializeField] private bool isHeadingAttach; [ShowIf("isHeadingAttach")] [SerializeField] private ConfigurableJoint joint; [ShowIf("isHeadingAttach")] [SerializeField] private GameObjectVariable rodTip; [ShowIf("isHeadingAttach")] [SerializeField] private GameObjectVariable lureCurrent; [ShowIf("isHeadingAttach")] [SerializeField] private Vector3Variable lurePosition; [ShowIf("isHeadingAttach")] [SerializeField] private FloatVariable lureDistanceToTip; [ShowIf("isHeadingAttach")] [SerializeField] private GameObjectVariable fishCatchLureTarget; [ShowIf("isHeadingAttach")] [SerializeField] private ScriptableEventNoParam onGroundEnter; [ShowIf("isHeadingAttach")] [SerializeField] private ScriptableEventNoParam onGroundExit; private SphereCollider collider; private Animator _lureAnimator; private Rigidbody rBody; private WaterFloater waterFloater; private LureData _LureData; private BaitData _BaitData; private Quaternion lureRotation = Quaternion.identity; private MeshRenderer[] lureMeshRenderers; private FishController _hookedToFish; private Vector3 _lastPosition; private Vector3 _linearDirection; private bool _wasRenderersLoaded; private bool _isAnimated; private bool _isGrounded; private float _efficiency; private float _moveSpeed; public float moveSpeed => _moveSpeed; public bool isGrounded => _isGrounded; public LureData LureData { get { return _LureData; } private set { _LureData = value; } } public BaitData BaitData => _BaitData; public bool IsFishConnected => _hookedToFish != null; public bool IsBait => _BaitData != null; public bool IsLure => _LureData != null; public bool isInWater => waterFloater.InWater; public Vector3 Velocity => rBody.linearVelocity; public Rigidbody RBody => rBody; public ConfigurableJoint Joint => joint; public event Action OnDestroyRaised; public event Action OnWaterStateChanged; public event Action OnGroundCollisionChangeState; public event Action onBoatTouched; public event Action OnFishEat; public event Action OnFishSpit; private void Awake() { waterFloater = GetComponent(); rBody = GetComponent(); collider = GetComponent(); waterFloater.OnWaterEnter += WaterFloater_OnWaterEnter; waterFloater.OnWaterEnter += delegate(bool x) { this.OnWaterStateChanged?.Invoke(x); }; WaterFloater_OnWaterEnter(waterFloater.InWater); } private IEnumerator Start() { if (isHeadingAttach) { lureCurrent.Value = base.gameObject; } joint = ((joint == null) ? GetComponent() : joint); SetLureJointDistance(lineLength.Value); rBody.detectCollisions = false; waterFloater.enabled = false; yield return new WaitForSeconds(2f); waterFloater.enabled = true; rBody.detectCollisions = true; } public bool IsCollide() { return Physics.OverlapSphere(base.transform.position, 0.2f, LayerMask.GetMask("Terrain", "BoatStatic", "Water Reflections", "Default")).Length != 0; } public bool IsCollide(Vector3 direction) { return Physics.Raycast(base.transform.position, direction.normalized, direction.magnitude, LayerMask.GetMask("Terrain", "BoatStatic", "Water Reflections")); } public void SetRenderersVisbile(bool isVisbile) { if (lureMeshRenderers != null) { lureMeshRenderers.ToList().ForEach(delegate(MeshRenderer x) { x.enabled = isVisbile; }); } } public void ConnectFish(FishController fish) { if (fish == null) { this.OnFishSpit?.Invoke(); _hookedToFish = null; SetRenderersVisbile(isVisbile: true); } else { this.OnFishEat?.Invoke(fish); _hookedToFish = fish; rBody.linearDamping = 0.1f; SetRenderersVisbile(isVisbile: false); } } private void WaterFloater_OnWaterEnter(bool inWater) { if (isHeadingAttach) { if (inWater) { SFXGameManagement.PlaySound("splash lure", base.transform); rBody.linearDamping = ((_hookedToFish == null) ? 3f : 0.1f); rBody.angularDamping = 2f; } else { rBody.linearDamping = 1f; rBody.angularDamping = 1f; } } } public void SetLureJointDistance(float limit) { joint.linearLimit = new SoftJointLimit { limit = limit }; } private void LateUpdate() { if (!isHeadingAttach) { return; } if (!_wasRenderersLoaded) { GetRendereres(); _lureAnimator = GetComponentInChildren(); _isAnimated = (object)_lureAnimator != null; _wasRenderersLoaded = true; } _efficiency = Mathf.Clamp01(_efficiency); if (_isGrounded || !waterFloater.InWater) { _efficiency = 0f; } _efficiency += Time.deltaTime * 0.1f; collider.radius = _efficiency * 3f; lurePosition.Value = base.transform.position; _linearDirection = base.transform.position - _lastPosition; _lastPosition = base.transform.position; _moveSpeed = _linearDirection.magnitude; Transform child = base.transform.GetChild(0); if (IsLure && waterFloater.InWater) { if (!_isGrounded && _hookedToFish == null) { rBody.freezeRotation = true; if (moveSpeed > 0.0001f) { lureRotation = Quaternion.LookRotation(_linearDirection.normalized, Vector3.up); } float value = Mathf.Clamp(moveSpeed / Time.deltaTime, 0f, 1f) * _LureData.twitchySpeed; _lureAnimator?.SetFloat(Speed, value); if (_LureData.axisNormal != Vector3.zero) { lureRotation = AlignToSurfaceAndForward(_LureData.axisNormal, child.forward); } } else if (_hookedToFish != null) { rBody.freezeRotation = true; child.rotation = _hookedToFish.transform.rotation; _lureAnimator?.SetFloat(Speed, 0f); } else { _lureAnimator?.SetFloat(Speed, 0f); rBody.freezeRotation = false; } } else { rBody.freezeRotation = false; _lureAnimator?.SetFloat(Speed, 0f); } child.rotation = Quaternion.Slerp(child.rotation, lureRotation, Time.deltaTime * 2f); static Quaternion AlignToSurfaceAndForward(Vector3 surfaceNormal, Vector3 desiredForward) { return Quaternion.LookRotation(Vector3.ProjectOnPlane(desiredForward, surfaceNormal).normalized, surfaceNormal); } } private void OnDrawGizmos() { if (rBody != null) { Gizmos.color = Color.green; Vector3 position = base.transform.position; Vector3 vector = _linearDirection * 10f; Gizmos.DrawLine(position, position + vector); Gizmos.DrawSphere(position + vector, 0.035f); } } private void OnDestroy() { this.OnDestroyRaised?.Invoke(); } private void PhysicsHandler() { if (waterFloater.InWater) { rBody.AddForce(Vector3.up * 14f, ForceMode.Acceleration); } } private void OnCollisionEnter(Collision collision) { if (isHeadingAttach) { if (collision.gameObject.layer == LayerMask.NameToLayer("Terrain")) { this.OnGroundCollisionChangeState?.Invoke(obj: true); onGroundEnter.Raise(); _isGrounded = true; } if (collision.gameObject.layer == LayerMask.NameToLayer("BoatStatic")) { this.onBoatTouched?.Invoke(); _isGrounded = true; } } } private void OnCollisionExit(Collision collision) { if (isHeadingAttach && collision.gameObject.layer == LayerMask.NameToLayer("Terrain")) { this.OnGroundCollisionChangeState?.Invoke(obj: false); onGroundExit.Raise(); _isGrounded = false; } } public void SetJoint(Rigidbody rb) { joint.connectedBody = rb; } public void EnableCollision(bool enable) { if (rBody == null) { rBody = GetComponent(); } rBody.detectCollisions = enable; } public void SetKinematic(bool value) { rBody.isKinematic = value; } private void GetRendereres() { lureMeshRenderers = GetComponentsInChildren(); } public void Initialize(LureData Value) { LureData = Value; lureSize = Value.size; } public void Initialize(BaitData Value) { _BaitData = Value; } }