Files
Ultimate-Fishing-Simulator-…/Assets/Scripts/Assembly-CSharp/FishController.cs
2026-03-04 09:37:33 +08:00

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;
}
}
}