578 lines
15 KiB
C#
578 lines
15 KiB
C#
using System;
|
|
using Obvious.Soap;
|
|
using SoapCustomVariable;
|
|
using UnityEngine;
|
|
|
|
public class FishController : MonoBehaviourExtended, IBatchFixedUpdate
|
|
{
|
|
private static readonly int MoveSpeedHash = Animator.StringToHash("Move");
|
|
|
|
public FishFSMReference fishState;
|
|
|
|
public UpdateManager.UpdateMode UpdateMode = UpdateManager.UpdateMode.Always;
|
|
|
|
public float stamina = 1f;
|
|
|
|
public Vector3? followPosition;
|
|
|
|
[SerializeField]
|
|
private float mass = 10f;
|
|
|
|
[SerializeField]
|
|
private FloatVariable fightMoveSpeed;
|
|
|
|
[SerializeField]
|
|
private FSMVariable playerFSM;
|
|
|
|
[SerializeField]
|
|
public GameObjectVariable currentFightFishObject;
|
|
|
|
[SerializeField]
|
|
private GameObjectVariable playerGameObject;
|
|
|
|
[SerializeField]
|
|
private ScriptableEventNoParam onGearDamaged;
|
|
|
|
[SerializeField]
|
|
private ScriptableEventFishData onFishCatch;
|
|
|
|
[SerializeField]
|
|
private ScriptableEventFishData onFishRelease;
|
|
|
|
[SerializeField]
|
|
private ScriptableEventFishData onFishCollect;
|
|
|
|
[SerializeField]
|
|
private Lure connectedLure;
|
|
|
|
[SerializeField]
|
|
private FishingSetController connectedFishingSet;
|
|
|
|
private FishModelBindings _FishModelBindings;
|
|
|
|
private FishZoneObject _fishZoneObject;
|
|
|
|
private Vector3 _currentDirection;
|
|
|
|
private Vector3 _lastPosition;
|
|
|
|
[OwnComponent(0)]
|
|
private FishAI _AI;
|
|
|
|
private ConfigurableJoint joint;
|
|
|
|
[OwnComponent(0)]
|
|
private WaterBody waterBody;
|
|
|
|
[OwnComponent(0)]
|
|
private Rigidbody rbody;
|
|
|
|
private Animator _animator;
|
|
|
|
private bool _isFightMode;
|
|
|
|
private FishData fishData;
|
|
|
|
private GameObject model;
|
|
|
|
private Vector3 _startPosition;
|
|
|
|
private Vector3 _moveDirection;
|
|
|
|
private float lastTimeChangeRotation;
|
|
|
|
private float length;
|
|
|
|
private Vector3 _anchor;
|
|
|
|
private bool _isThrown;
|
|
|
|
private float lastTimeInWaterExit;
|
|
|
|
private float _stateTimer;
|
|
|
|
private float lastTimeTensionDirChange;
|
|
|
|
private int directionOfFight;
|
|
|
|
private float lineReeledAmount;
|
|
|
|
public float Mass => mass;
|
|
|
|
public Vector3 Velocity => rbody.linearVelocity;
|
|
|
|
public FishData FishData => fishData;
|
|
|
|
public Transform JawAnchor => _FishModelBindings.Jaw;
|
|
|
|
public bool inWater => waterBody.InWater;
|
|
|
|
public float moveSpeed { get; private set; }
|
|
|
|
public bool isFightMode => _isFightMode;
|
|
|
|
private bool IsConnectedToJoint => joint != null;
|
|
|
|
private float rngRotateTime => Time.time + UnityEngine.Random.Range(1f, 2.5f);
|
|
|
|
private event Action onPostInitialization = delegate
|
|
{
|
|
};
|
|
|
|
public void Initialize(FishData fishData, FishZoneObject fishZone, float mass)
|
|
{
|
|
this.fishData = fishData;
|
|
this.fishData.Weight = mass;
|
|
_fishZoneObject = fishZone;
|
|
this.mass = mass;
|
|
length = fishData.LWR.Evaluate(mass);
|
|
float num = length * 1.73f;
|
|
model = UnityEngine.Object.Instantiate(fishData.GetModel(), base.transform);
|
|
_FishModelBindings = model.GetComponent<FishModelBindings>();
|
|
model.transform.localScale = new Vector3(num, num, num);
|
|
base.gameObject.name = fishData.name + " " + mass + "kg";
|
|
model.transform.localPosition = Vector3.zero;
|
|
_FishModelBindings.TailSetEnable(setEnable: false);
|
|
_AI.length = length;
|
|
_AI.anchor = JawAnchor;
|
|
_AI.fishData = fishData;
|
|
rbody = GetComponent<Rigidbody>();
|
|
joint = GetComponentInChildren<ConfigurableJoint>();
|
|
rbody.mass = mass;
|
|
this.onPostInitialization();
|
|
}
|
|
|
|
public void Reinitialize(FishData fishData, float mass)
|
|
{
|
|
if (model == null)
|
|
{
|
|
throw new InvalidOperationException("Fish was not initialized before. Call Initialize() first.");
|
|
}
|
|
if (fishState.Value != FishState.idle && fishState.Value != FishState.patrol)
|
|
{
|
|
throw new InvalidOperationException($"It is not safe to reinitialize a fish in state {fishState.Value}");
|
|
}
|
|
this.fishData = fishData;
|
|
this.fishData.Weight = mass;
|
|
this.mass = mass;
|
|
length = fishData.LWR.Evaluate(mass);
|
|
float num = length * 1.73f;
|
|
if (model != null)
|
|
{
|
|
UnityEngine.Object.Destroy(model.gameObject);
|
|
model = null;
|
|
_FishModelBindings = null;
|
|
}
|
|
model = UnityEngine.Object.Instantiate(fishData.GetModel(), base.transform);
|
|
_FishModelBindings = model.GetComponent<FishModelBindings>();
|
|
model.transform.localScale = new Vector3(num, num, num);
|
|
base.gameObject.name = fishData.name + " " + mass + "kg";
|
|
model.transform.localPosition = Vector3.zero;
|
|
_FishModelBindings.TailSetEnable(setEnable: false);
|
|
_AI.length = length;
|
|
_AI.anchor = JawAnchor;
|
|
_AI.fishData = fishData;
|
|
rbody = GetComponent<Rigidbody>();
|
|
joint = GetComponentInChildren<ConfigurableJoint>();
|
|
rbody.mass = mass;
|
|
}
|
|
|
|
private new void Awake()
|
|
{
|
|
base.Awake();
|
|
WaterBody obj = waterBody;
|
|
obj.OnWaterChangeState = (Action<bool>)Delegate.Combine(obj.OnWaterChangeState, new Action<bool>(OnWaterEnterExit));
|
|
fishState.OnValueChanged += FishStateOnOnValueChanged;
|
|
_startPosition = base.transform.position;
|
|
onPostInitialization += delegate
|
|
{
|
|
_AI.SetRandomizedMoveToTargetPosition(_startPosition);
|
|
};
|
|
}
|
|
|
|
private void Start()
|
|
{
|
|
OnWaterEnterExit(waterBody.InWater);
|
|
}
|
|
|
|
public void BatchFixedUpdate()
|
|
{
|
|
}
|
|
|
|
private void FixedUpdate()
|
|
{
|
|
StateHandler();
|
|
}
|
|
|
|
public void BatchUpdate()
|
|
{
|
|
}
|
|
|
|
private void OnEnable()
|
|
{
|
|
UpdateManager.RegisterSlicedFixedUpdate(this);
|
|
currentFightFishObject.OnValueChanged += CurrentFightFishObject_OnValueChanged;
|
|
}
|
|
|
|
private void OnDisable()
|
|
{
|
|
UpdateManager.DeregisterSlicedFixedUpdate(this);
|
|
currentFightFishObject.OnValueChanged -= CurrentFightFishObject_OnValueChanged;
|
|
}
|
|
|
|
private void FishStateOnOnValueChanged(FishState state)
|
|
{
|
|
if (fishState.PreviousValue == FishState.catched)
|
|
{
|
|
rbody.detectCollisions = true;
|
|
}
|
|
switch (state)
|
|
{
|
|
case FishState.catched:
|
|
rbody.automaticInertiaTensor = false;
|
|
rbody.detectCollisions = false;
|
|
rbody.linearVelocity = Vector3.zero;
|
|
rbody.angularVelocity = Vector3.zero;
|
|
break;
|
|
case FishState.idle:
|
|
_stateTimer = Time.time + UnityEngine.Random.Range(1f, 3f);
|
|
break;
|
|
case FishState.patrol:
|
|
_AI.SetRandomizedMoveToTargetPosition(_startPosition);
|
|
break;
|
|
}
|
|
}
|
|
|
|
private void StateHandler()
|
|
{
|
|
switch (fishState.Value)
|
|
{
|
|
case FishState.idle:
|
|
if (_stateTimer < Time.time)
|
|
{
|
|
fishState.Value = FishState.patrol;
|
|
}
|
|
break;
|
|
case FishState.patrol:
|
|
{
|
|
float magnitude = rbody.linearVelocity.magnitude;
|
|
_FishModelBindings.Animator.SetFloat(MoveSpeedHash, magnitude);
|
|
if ((bool)_AI.lure)
|
|
{
|
|
_AI.SeekUpdateHandler(3f);
|
|
if (_AI.isTargetReached)
|
|
{
|
|
_AI.lure.transform.position = JawAnchor.position;
|
|
AttachLure(_AI.lure.RBody);
|
|
fishState.Value = FishState.eat;
|
|
break;
|
|
}
|
|
_AI.SetMovePosition(_AI.lure.transform.position);
|
|
if (_AI.lure.IsFishConnected || !_AI.lure.isInWater)
|
|
{
|
|
_AI.SetLure(null);
|
|
_AI.SetRandomizedMoveToTargetPosition(_startPosition);
|
|
}
|
|
break;
|
|
}
|
|
if (followPosition.HasValue)
|
|
{
|
|
float num2 = Vector3.Distance(base.transform.position, followPosition.Value);
|
|
float multiply2 = Mathf.Lerp(1f, 4f, Mathf.Clamp01(num2 / 10f));
|
|
_AI.SeekUpdateHandler(multiply2);
|
|
_AI.SetMovePosition(followPosition.Value);
|
|
break;
|
|
}
|
|
_AI.SeekUpdateHandler();
|
|
if (_AI.isTargetReached)
|
|
{
|
|
if (UnityEngine.Random.Range(0f, 1f) > 0.35f)
|
|
{
|
|
fishState.Value = FishState.idle;
|
|
}
|
|
else
|
|
{
|
|
_AI.SetRandomizedMoveToTargetPosition(_startPosition);
|
|
}
|
|
}
|
|
if (!waterBody.InWater)
|
|
{
|
|
_AI.SetRandomizedMoveToTargetPosition(_startPosition);
|
|
}
|
|
break;
|
|
}
|
|
case FishState.eat:
|
|
{
|
|
float magnitude = rbody.linearVelocity.magnitude;
|
|
if (!connectedFishingSet)
|
|
{
|
|
break;
|
|
}
|
|
float num = 1f - connectedFishingSet.Tension / mass;
|
|
_FishModelBindings.Animator.SetFloat(MoveSpeedHash, magnitude);
|
|
if (inWater)
|
|
{
|
|
if (num < 0.9f)
|
|
{
|
|
fishState.Value = FishState.fight;
|
|
break;
|
|
}
|
|
_AI.LureEatUpdateHandler((stamina > 0f) ? 3f : 0f);
|
|
}
|
|
else
|
|
{
|
|
_AI.SetMoveToTargetPosition(Vector3.down * 10f);
|
|
}
|
|
if (_AI.isTargetReached)
|
|
{
|
|
_AI.SetRandomizedMoveToTargetPosition(_startPosition);
|
|
}
|
|
rbody.useGravity = !inWater;
|
|
UpdateMoveSpeed();
|
|
break;
|
|
}
|
|
case FishState.fight:
|
|
{
|
|
float magnitude = rbody.linearVelocity.magnitude;
|
|
if (!connectedFishingSet)
|
|
{
|
|
break;
|
|
}
|
|
float num = connectedFishingSet.Tension / mass;
|
|
_FishModelBindings.Animator.SetFloat(MoveSpeedHash, magnitude);
|
|
Vector3 position = connectedFishingSet.transform.position;
|
|
position.y = base.transform.position.y - 1f;
|
|
Vector3 normalized = (base.transform.position - position).normalized;
|
|
if (inWater)
|
|
{
|
|
if (num > 0.85f * stamina)
|
|
{
|
|
Vector3 vector = normalized;
|
|
if (directionOfFight == -1)
|
|
{
|
|
vector = Quaternion.AngleAxis(-95f, Vector3.up) * normalized;
|
|
directionOfFight = 1;
|
|
}
|
|
else if (directionOfFight == 1)
|
|
{
|
|
vector = Quaternion.AngleAxis(95f, Vector3.up) * normalized;
|
|
directionOfFight = -1;
|
|
}
|
|
_AI.SetMoveToTargetPosition(base.transform.position + vector * 10f);
|
|
}
|
|
if (Time.time > lastTimeTensionDirChange)
|
|
{
|
|
Vector3 vector2 = normalized;
|
|
bool flag = UnityEngine.Random.Range(0f, 100f) < 30f;
|
|
if (num > 0.25f * stamina || flag)
|
|
{
|
|
if (directionOfFight == -1)
|
|
{
|
|
vector2 = Quaternion.AngleAxis(-95f, Vector3.up) * normalized;
|
|
directionOfFight = 1;
|
|
}
|
|
else if (directionOfFight == 1)
|
|
{
|
|
vector2 = Quaternion.AngleAxis(95f, Vector3.up) * normalized;
|
|
directionOfFight = -1;
|
|
}
|
|
else
|
|
{
|
|
bool flag2 = UnityEngine.Random.Range(0f, 1f) < 0.5f;
|
|
vector2 = Quaternion.AngleAxis(flag2 ? (-95f) : 95f, Vector3.up) * normalized;
|
|
directionOfFight = ((!flag2) ? 1 : (-1));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
directionOfFight = 0;
|
|
}
|
|
_AI.SetMoveToTargetPosition(base.transform.position + vector2 * 10f);
|
|
lastTimeTensionDirChange = Time.time + UnityEngine.Random.Range(2f, 3f);
|
|
Debug.Log(">>>>>>>>>>Change dir to: " + directionOfFight);
|
|
}
|
|
stamina -= Time.deltaTime * num * 0.01f;
|
|
float multiply = 6f;
|
|
if (lineReeledAmount < 0f && stamina <= 0f)
|
|
{
|
|
multiply = 0f;
|
|
}
|
|
_AI.FightUpdateHandler(multiply);
|
|
}
|
|
else if (lastTimeInWaterExit < Time.time)
|
|
{
|
|
lastTimeInWaterExit = Time.time + 1f;
|
|
lastTimeTensionDirChange = Time.time + UnityEngine.Random.Range(1f, 2f);
|
|
Vector3 moveToTargetPosition = normalized;
|
|
moveToTargetPosition.y = -2f;
|
|
_AI.SetMoveToTargetPosition(moveToTargetPosition);
|
|
}
|
|
_FishModelBindings.Animator.SetBool("Jump", num > 0.75f);
|
|
stamina = Mathf.Clamp(stamina, 0f, 1f);
|
|
rbody.useGravity = !inWater;
|
|
UpdateMoveSpeed();
|
|
break;
|
|
}
|
|
case FishState.catched:
|
|
rbody.detectCollisions = false;
|
|
rbody.automaticInertiaTensor = true;
|
|
_FishModelBindings.Animator.SetFloat(MoveSpeedHash, (stamina > 0f) ? 0.1f : 0f);
|
|
if (_isThrown && inWater)
|
|
{
|
|
fishState.Value = FishState.idle;
|
|
_isThrown = false;
|
|
}
|
|
break;
|
|
case FishState.seek:
|
|
case FishState.followTarget:
|
|
case FishState.chase:
|
|
break;
|
|
}
|
|
}
|
|
|
|
private void UpdateMoveSpeed()
|
|
{
|
|
Vector3 position = base.transform.position;
|
|
moveSpeed = Vector3.Distance(_lastPosition, position);
|
|
_lastPosition = position;
|
|
}
|
|
|
|
private Vector3 RandomPointInCone(Vector3 forward, float angle)
|
|
{
|
|
float minInclusive = Mathf.Cos(angle * (MathF.PI / 180f));
|
|
float f = UnityEngine.Random.Range(0f, MathF.PI * 2f);
|
|
float num = UnityEngine.Random.Range(minInclusive, 1f);
|
|
float num2 = Mathf.Sqrt(1f - num * num);
|
|
Vector3 vector = new Vector3(num2 * Mathf.Cos(f), num2 * Mathf.Sin(f), num);
|
|
return Quaternion.FromToRotation(Vector3.forward, forward.normalized) * vector;
|
|
}
|
|
|
|
public void AttachToFishingSet(FishingSetController fishingSetController)
|
|
{
|
|
connectedFishingSet = fishingSetController;
|
|
connectedFishingSet.OnLineReeled += ConnectedFishingSetOnOnLineReeled;
|
|
}
|
|
|
|
private void ConnectedFishingSetOnOnLineReeled(float obj)
|
|
{
|
|
lineReeledAmount = obj;
|
|
}
|
|
|
|
public void AttachLure(Rigidbody lureRb)
|
|
{
|
|
if (!(currentFightFishObject.Value != null))
|
|
{
|
|
currentFightFishObject.Value = base.gameObject;
|
|
base.transform.parent = null;
|
|
attach();
|
|
}
|
|
void attach()
|
|
{
|
|
connectedLure = lureRb.GetComponent<Lure>();
|
|
connectedLure.ConnectFish(this);
|
|
_anchor = model.transform.localPosition + JawAnchor.localPosition * model.transform.localScale.x;
|
|
playerFSM.Value = State.fight;
|
|
_FishModelBindings.TailSetEnable(setEnable: true);
|
|
_isFightMode = true;
|
|
joint.anchor = _anchor;
|
|
joint.connectedBody = lureRb;
|
|
ConfigurableJoint configurableJoint = joint;
|
|
ConfigurableJoint configurableJoint2 = joint;
|
|
ConfigurableJointMotion configurableJointMotion = (joint.zMotion = ConfigurableJointMotion.Locked);
|
|
ConfigurableJointMotion xMotion = (configurableJoint2.yMotion = configurableJointMotion);
|
|
configurableJoint.xMotion = xMotion;
|
|
}
|
|
}
|
|
|
|
public void SetJoint(Rigidbody rb)
|
|
{
|
|
joint.connectedBody = rb;
|
|
}
|
|
|
|
public void Catch()
|
|
{
|
|
_FishModelBindings.Animator.SetBool("Jump", value: false);
|
|
SFXGameManagement.PlaySound("gather splash", base.transform);
|
|
Debug.Log("Catched Fish" + fishData.name + " " + mass + "kg");
|
|
fishState.Value = FishState.catched;
|
|
}
|
|
|
|
public void CollectFish()
|
|
{
|
|
_isFightMode = false;
|
|
rbody.automaticCenterOfMass = false;
|
|
rbody.centerOfMass = -JawAnchor.localPosition;
|
|
rbody.detectCollisions = false;
|
|
}
|
|
|
|
public void Throw(Vector3 force)
|
|
{
|
|
DisconnectFromAttachment();
|
|
_AI.ResetBehaviour();
|
|
_isThrown = true;
|
|
rbody.linearVelocity = force;
|
|
rbody.detectCollisions = true;
|
|
rbody.automaticCenterOfMass = true;
|
|
currentFightFishObject.Value = null;
|
|
}
|
|
|
|
public void FishDestroy()
|
|
{
|
|
OnFishCollect_OnRaised(fishData);
|
|
}
|
|
|
|
private void DisconnectFromAttachment()
|
|
{
|
|
connectedFishingSet.OnLineReeled -= ConnectedFishingSetOnOnLineReeled;
|
|
connectedFishingSet = null;
|
|
currentFightFishObject.Value = null;
|
|
joint.connectedBody = null;
|
|
ConfigurableJoint configurableJoint = joint;
|
|
ConfigurableJoint configurableJoint2 = joint;
|
|
ConfigurableJointMotion configurableJointMotion = (joint.zMotion = ConfigurableJointMotion.Free);
|
|
ConfigurableJointMotion xMotion = (configurableJoint2.yMotion = configurableJointMotion);
|
|
configurableJoint.xMotion = xMotion;
|
|
connectedLure.ConnectFish(null);
|
|
connectedLure = null;
|
|
rbody.linearVelocity = Vector3.zero;
|
|
stamina = 1f;
|
|
_FishModelBindings.TailSetEnable(setEnable: false);
|
|
_isFightMode = false;
|
|
}
|
|
|
|
private void OnFishCollect_OnRaised(FishData obj)
|
|
{
|
|
if (!(obj != fishData))
|
|
{
|
|
if (currentFightFishObject.Value == base.gameObject)
|
|
{
|
|
currentFightFishObject.Value = null;
|
|
}
|
|
DisconnectFromAttachment();
|
|
UnityEngine.Object.Destroy(base.gameObject);
|
|
}
|
|
}
|
|
|
|
private void CurrentFightFishObject_OnValueChanged(GameObject obj)
|
|
{
|
|
_ = base.gameObject == obj;
|
|
}
|
|
|
|
private void OnWaterEnterExit(bool inWater)
|
|
{
|
|
if (inWater)
|
|
{
|
|
rbody.useGravity = false;
|
|
rbody.linearDamping = 3f;
|
|
rbody.angularDamping = 1f;
|
|
}
|
|
else
|
|
{
|
|
rbody.useGravity = true;
|
|
lastTimeChangeRotation = 0f;
|
|
rbody.linearDamping = 1.5f;
|
|
rbody.angularDamping = 2f;
|
|
}
|
|
}
|
|
}
|