using System; using Lean.Pool; using Obvious.Soap; using Photon.Pun; using QFSW.QC; using RootMotion.FinalIK; using ShiningGames.UFS2; using Sirenix.Utilities; using UFS2.ScriptableObjects; using UnityEngine; namespace UFS2.Gameplay { public class FishEntity : FishFSM { private static FishEntity _CurrentFishInFight; private static FishEntity _CurrentFishInAttack; [Command("FishStaminaMod", "default 1", Platform.AllPlatforms, MonoTargetType.Single)] public static float StaminaModifier = 1f; [Command("FishSpeedMod", "default 1", Platform.AllPlatforms, MonoTargetType.Single)] public static float GlobalSpeedModifier = 1f; [SerializeField] private Vector3Variable player_CurrentPosition; [SerializeField] private FishData _Data; [SerializeField] private Transform _JointAnchor; private float _Weight; private FishPhysics _Physics; private FishScanner _FishScanner; private Animator _Animator; private LocalAvoidance _AI; private CCDIK _IK; public FishTargetArea CurrentArea; private LODGroup lodGroup; private Material[][] rendererMaterialsOriginal; private Material[][] rendererMaterialsEagle; public Transform LureTarget; public Transform networkedTarget; public FRod rod; public float WeightTugging; public float FightTime; public float Stamina01; public bool IsCatched; private bool _IsCulled = true; private bool _IsHooked; private float lastCatchTime; private float lastServerRequestTime; private float nextCatchDelayInterval = 15f; private bool _IsAtracted; private bool _IsScarred; public bool IsInDistanceToLure; public bool IsInDistanceToBait; public static FishEntity CurrentFishInFight { get { return _CurrentFishInFight; } set { _CurrentFishInFight = value; FishEntity.OnSetCurrentFishInFight?.Invoke(value); } } public static FishEntity CurrentFishInAttack { get { return _CurrentFishInAttack; } set { _CurrentFishInAttack = value; FishEntity.OnSetCurrentFishInAttack?.Invoke(value); } } public Vector3Variable Player_CurrentPosition { set { player_CurrentPosition = value; } } public Transform JointAnchor { get { return _JointAnchor; } set { _JointAnchor = value; } } public Vector3 GetJointAnchorPositionScaled => Vector3.Scale(JointAnchor.localPosition, base.transform.GetChild(0).localScale); public FishData Data => _Data; public FishPhysics Physics => _Physics; public LocalAvoidance AI => _AI; public Transform Target { get { return _AI.Target; } set { _AI.Target = value; } } public FishScanner FishScanner => _FishScanner; public float Weight => _Weight; public bool IsHooked { get { return _IsHooked; } set { _IsHooked = value; if (_IsHooked) { FishEntity.OnFishHooked?.Invoke(); } } } public float LastCatchTime { get { return lastCatchTime; } set { lastCatchTime = value; } } public FishState CurrentFishState => _State; public bool IsCanFight => _IsCanFight; private bool _CanInteractWithRod { get { if ((bool)rod) { if (!(FScriptsHandler.Instance.m_PlayerMain.currentRod == null)) { return FScriptsHandler.Instance.m_PlayerMain.currentRod == rod; } return true; } return false; } } private bool _IsCanAttack { get { if (!_IsDistanceToPlayerTresholdReached && (CurrentFishInAttack == null || CurrentFishInAttack == this) && CurrentFishInFight == null && (bool)LureTarget && CanFightWithLure() && GameWaterSystem.IsPositionUnderWater(LureTarget.position)) { return _CanInteractWithRod; } return false; } } private bool _IsCanFight { get { if (CurrentFishInFight == this && (bool)LureTarget) { return _CanInteractWithRod; } return false; } } private bool _IsCanSendRequest => lastServerRequestTime + 0.2f < Time.time; public float MoveSpeed { get { return _AI.MoveSpeed; } set { float moveSpeed = Mathf.Clamp(value, 0f, Data.MoveMaxSpeed); _AI.MoveSpeed = moveSpeed; } } private bool _IsDistanceToPlayerTresholdReached => _DistanceToPlayer < 3.5f; private float _DistanceToPlayer => Vector3.Distance(player_CurrentPosition.Value, base.transform.position); public bool IsCulled { get { return _IsCulled; } set { _IsCulled = value; } } public static event Action OnSetCurrentFishInFight; public static event Action OnSetCurrentFishInAttack; public static event Action OnBaitLock; public static event Action OnPreSpitOutBait; public static event Action OnPostSpitOutBait; public static event Action OnOldFishKill; public static event Action OnFishHooked; public float GetMoveSpeedAnimation() { return _AI.MoveSpeed * 0.25f; } private void FPlayer_OnFishPicked() { if (!(CurrentFishInFight != this)) { IsCatched = true; } } private void FRod_OnLineCutedGlobal(Transform obj) { TryDestroyFish(); } private void FReel_OnReelDamagedGlobal(Transform obj) { TryDestroyFish(); } private void FRod_OnRodDamagedGlobal(Transform obj) { TryDestroyFish(); } private void Start() { _IK = GetComponentInChildren(); _Physics = GetComponent(); _FishScanner = GetComponent(); _Animator = GetComponentInChildren(); _AI = GetComponent(); _AI.OnLureHit += _AI_OnBaitHit; _Physics.OnEnterWater += BuildSplash; _Physics.Rbody.mass = 15f; InitializeFSM(this); SetIKAndAnimatorLayers(0f); SetUpRendererMaterialsOriginal(); if (IsCulled) { Cull(); } else { Draw(); } if (MultiplayerFishSpawner.IsOnline) { networkedTarget = new GameObject(base.name + "_NT").GetComponent(); networkedTarget.SetParent(base.transform.parent); } } private new void OnDestroy() { base.OnDestroy(); if (networkedTarget != null) { UnityEngine.Object.Destroy(networkedTarget.gameObject); } CleanupRendererMaterialsEagle(); } public void ResetRotate() { _AI.ResetRoot(); } private void _AI_OnBaitHit(RaycastHit obj) { SetLureTarget(obj.transform); } public void SetLureTarget(Transform target) { if ((bool)CurrentFishInFight) { return; } FRod fRod = null; FHook component2; if (target.TryGetComponent(out var component)) { fRod = component.currentRod; } else if (target.TryGetComponent(out component2)) { fRod = component2.currentRod; } if ((bool)fRod) { bool flag = false; int gameItemIndexByItemId = GameManager.Instance._playerData.GetGameItemIndexByItemId(GameManager.ItemType.Bait, Singleton.Instance.GetCurrentPlayerData().PlayerSlotsEquip[fRod.indexOfslot].bait.ID); if ((bool)fRod.currentLure && IsLureAccepted(gameItemIndexByItemId)) { flag = true; } else if ((bool)fRod.currentBait && IsBaitAccepted(gameItemIndexByItemId)) { flag = true; } bool flag2 = false; if (!fRod.currentBait) { flag2 = true; } else { gameItemIndexByItemId = GameManager.Instance._playerData.GetGameItemIndexByItemId(GameManager.ItemType.Hook, Singleton.Instance.GetCurrentPlayerData().PlayerSlotsEquip[fRod.indexOfslot].hook.ID); flag2 = GameManager.Instance.gameHooks[gameItemIndexByItemId].CheckIsFishAccept(Weight); } if (flag && flag2) { rod = fRod; LureTarget = target; } } } public void ResetBaitRefferences() { LureTarget = null; if ((bool)rod && rod.currentFishEntity == this) { rod.currentFishEntity = null; } rod = null; LastCatchTime = Time.time; } public void SetCurrentFishInAttack() { if (!CurrentFishInAttack) { CurrentFishInAttack = this; } } public void ResetCurrentFishInAttack() { if (CurrentFishInAttack == this) { CurrentFishInAttack = null; } } public void SetCurrentFishInFight(FRod rod) { if (!CurrentFishInFight) { CurrentFishInFight = this; rod.currentFishEntity = this; this.rod = rod; } } public void ResetCurrentFishInFight() { ResetBaitRefferences(); if (CurrentFishInFight == this) { CurrentFishInFight = null; } } public void EnableAIRaycasting() { _AI.IsUpdateEnabled = true; } private void FishEntity_OnPostSpitOutBait(FishEntity fish) { ChangeState(FishState.Idle); } private void FishEntityManager_OnGrowFish(FishEntity fish, float weightNew) { if (!(fish != this)) { TryGrowFish(weightNew); } } private void FishEntityManager_OnFishReachMaxSize(FishEntity fish) { if (!(fish != this)) { TryKillOldFish(); } } public void SetIKAndAnimatorLayers(float weight) { _IK.solver.SetIKPositionWeight(weight); _Animator.SetLayerWeight(_Animator.GetLayerIndex("Jump"), weight); _Animator.SetLayerWeight(_Animator.GetLayerIndex("Attack"), weight); _Animator.SetLayerWeight(_Animator.GetLayerIndex("Fight"), weight); } public float GetIKAndAnimatorLayers() { return _IK.solver.GetIKPositionWeight(); } public void SetUpRendererMaterialsOriginal() { lodGroup = GetComponentInChildren(); if (!(lodGroup != null)) { return; } LOD[] lODs = lodGroup.GetLODs(); rendererMaterialsOriginal = new Material[lODs.Length][]; for (int i = 0; i < lODs.Length; i++) { Renderer renderer = ((lODs[i].renderers.Length != 0) ? lODs[i].renderers[0] : null); if (renderer != null) { rendererMaterialsOriginal[i] = renderer.sharedMaterials; } else { rendererMaterialsOriginal[i] = new Material[0]; } } } private void CleanupRendererMaterialsEagle() { if (rendererMaterialsEagle == null) { return; } Material[][] array = rendererMaterialsEagle; for (int i = 0; i < array.Length; i++) { array[i].ForEach(delegate(Material element) { UnityEngine.Object.Destroy(element); }); } rendererMaterialsEagle = null; } private void LODCorrection() { LODGroup componentInChildren = base.gameObject.GetComponentInChildren(); if (componentInChildren == null) { Debug.LogError("Fish have not LOD Group: " + base.name); return; } SkinnedMeshRenderer component = componentInChildren.GetComponent(); if (componentInChildren.transform.childCount == 0) { Debug.LogWarning("Problem with lods in fish " + base.gameObject.name); return; } GameObject obj = UnityEngine.Object.Instantiate(componentInChildren.transform.GetChild(0).gameObject, component.transform); obj.transform.localPosition = Vector3.zero; obj.transform.localRotation = Quaternion.identity; obj.transform.localScale = Vector3.one; SkinnedMeshRenderer component2 = obj.GetComponent(); component2.sharedMesh = component.sharedMesh; LOD[] lODs = componentInChildren.GetLODs(); lODs[0].renderers[0] = component2; componentInChildren.SetLODs(lODs); UnityEngine.Object.Destroy(component); } private void InstallMeshRenderer() { SkinnedMeshRenderer componentInChildren = GetComponentInChildren(); MeshRenderer meshRenderer = base.gameObject.AddComponent(); MeshFilter meshFilter = base.gameObject.AddComponent(); meshRenderer.material = componentInChildren.material; meshFilter.sharedMesh = componentInChildren.sharedMesh; componentInChildren.enabled = false; _Animator.enabled = false; } private void OnEnable() { FPlayer.OnFishPicked += FPlayer_OnFishPicked; FishCatchPanel.OnFishKeepGlobal += TryDestroyFish; FishCatchPanel.OnFishReleaseGlobal += TryDestroyFish; FRod.OnRodDamagedGlobal += FRod_OnRodDamagedGlobal; FReel.OnReelDamagedGlobal += FReel_OnReelDamagedGlobal; FRod.OnLineCutedGlobal += FRod_OnLineCutedGlobal; FHook.OnHookWaterExit += OnLureChangeWaterState; FHook.OnHookWaterEnter += OnLureChangeWaterState; FLure.OnLureEnterWater += OnLureChangeWaterState; FLure.OnLureExitWater += OnLureChangeWaterState; OnPostSpitOutBait += FishEntity_OnPostSpitOutBait; FRod.OnEquipmentBreak = (Action)Delegate.Combine(FRod.OnEquipmentBreak, new Action(FRodOnEQBreak)); FishEntityManager.OnGrowFish += FishEntityManager_OnGrowFish; FishEntityManager.OnFishReachMaxSize += FishEntityManager_OnFishReachMaxSize; } private void OnDisable() { FPlayer.OnFishPicked -= FPlayer_OnFishPicked; FishCatchPanel.OnFishKeepGlobal -= TryDestroyFish; FishCatchPanel.OnFishReleaseGlobal -= TryDestroyFish; FRod.OnRodDamagedGlobal -= FRod_OnRodDamagedGlobal; FReel.OnReelDamagedGlobal -= FReel_OnReelDamagedGlobal; FRod.OnLineCutedGlobal -= FRod_OnLineCutedGlobal; FHook.OnHookWaterExit -= OnLureChangeWaterState; FHook.OnHookWaterEnter -= OnLureChangeWaterState; FLure.OnLureEnterWater -= OnLureChangeWaterState; FLure.OnLureExitWater -= OnLureChangeWaterState; OnPostSpitOutBait -= FishEntity_OnPostSpitOutBait; FRod.OnEquipmentBreak = (Action)Delegate.Remove(FRod.OnEquipmentBreak, new Action(FRodOnEQBreak)); FishEntityManager.OnGrowFish -= FishEntityManager_OnGrowFish; FishEntityManager.OnFishReachMaxSize -= FishEntityManager_OnFishReachMaxSize; } private void FRodOnEQBreak(object obj) { TryDestroyFish(); } private void OnLureChangeWaterState() { if (!(CurrentFishInFight == this)) { ResetBaitRefferences(); } } public void Update() { if (!IsCulled) { _FSM.Update(); if (MultiplayerFishSpawner.IsOnline) { StateSwitchMultiplayer(); } else { StateSwitchSingleplayer(); } } } private void StateSwitchSingleplayer() { switch (_State) { case FishState.Idle: if (_StateChangeTime < Time.time) { ChangeState(FishState.MoveToWaypoint); } if (_IsCanAttack) { ChangeState(FishState.Atack); } if (_IsAtracted) { ChangeState(FishState.Interest); } break; case FishState.Atack: if (!_IsCanAttack || Target == null) { ResetBaitRefferences(); SetStateTimer(2f); ChangeState(FishState.Idle); break; } if (IsInDistanceToLure) { ChangeState(FishState.Fight); } if ((bool)Target && !GameWaterSystem.IsPositionUnderWater(Target.position)) { ChangeState(FishState.Idle); } break; case FishState.MoveToWaypoint: if (Target == null) { ChangeState(FishState.Idle); break; } if (GetDistanceToTarget() <= _Physics.Rbody.velocity.magnitude) { ChangeState(FishState.Idle); SetStateTimer(UnityEngine.Random.Range(0.5f, 5f)); } if (_IsAtracted) { ChangeState(FishState.Interest); } if (_IsCanAttack) { ChangeState(FishState.Atack); } break; case FishState.Fight: if (!_IsCanFight) { ResetCurrentFishInFight(); ChangeState(FishState.Idle); } else if (IsCatched) { ChangeState(FishState.Catched); } break; case FishState.Interest: if (Target == null) { ChangeState(FishState.Idle); } else if (!_IsAtracted) { ChangeState(FishState.MoveToWaypoint); } break; case FishState.Dash: case FishState.Stun: case FishState.Catched: case FishState.BaitEat: break; } } private void StateSwitchMultiplayer() { MultiplayerFishSpawner.NetworkedFish networkedFish = MultiplayerFishSpawner.GetNetworkedFish(this); networkedTarget.position = networkedFish.position; MultiplayerFishSpawner.CheckFishInteractionWithPlayer(this, out var withLocalPlayer, out var _); bool flag = MultiplayerFishSpawner.CheckFishInteractionWithPlayer(this); switch (_State) { case FishState.Idle: case FishState.MoveToWaypoint: ChangeState(FishState.MultiplayerIdle); break; case FishState.MultiplayerIdle: if (HandleInteractionWithLocalPlayer() || withLocalPlayer) { break; } if (MultiplayerFishSpawner.IsMaster) { if (_StateChangeTime < Time.time) { ChangeState(FishState.MultiplayerMoveToWaypoint); } } else if (GetDistanceToTarget() > 0.2f) { ChangeState(FishState.MultiplayerMoveToWaypoint); } break; case FishState.MultiplayerMoveToWaypoint: if (HandleInteractionWithLocalPlayer() || withLocalPlayer) { break; } if (MultiplayerFishSpawner.IsMaster) { if (Target == null) { ChangeState(FishState.MultiplayerIdle); } else if (GetDistanceToTarget() <= _Physics.Rbody.velocity.magnitude) { ChangeState(FishState.MultiplayerIdle); SetStateTimer(UnityEngine.Random.Range(0.5f, 5f)); } } else if (Target == null || GetDistanceToTarget() <= _Physics.Rbody.velocity.magnitude) { ChangeState(FishState.MultiplayerIdle); } break; case FishState.MultiplayerHide: if (!flag) { ChangeState(FishState.MultiplayerIdle); } break; case FishState.Atack: if (!withLocalPlayer || !_IsCanAttack || Target == null) { ResetBaitRefferences(); ChangeState(FishState.MultiplayerIdle); } else if (IsInDistanceToLure) { ChangeState(FishState.Fight); } break; case FishState.Fight: if (!withLocalPlayer || !_IsCanFight) { ResetCurrentFishInFight(); ChangeState(FishState.MultiplayerIdle); } else if (IsCatched) { ChangeState(FishState.Catched); } break; case FishState.Interest: if (!withLocalPlayer || Target == null) { ChangeState(FishState.MultiplayerIdle); } else if (!_IsAtracted) { ChangeState(FishState.MoveToWaypoint); } break; case FishState.Dash: case FishState.Stun: case FishState.Catched: case FishState.BaitEat: break; } } public void OnGUI() { if (GameManager.IsDevModeAllowed && !(CurrentFishInFight == null) && CurrentFishInFight == this) { string text = $"Distance: {_DistanceToPlayer}"; if (!(Camera.main == null)) { Vector3 vector = Camera.main.WorldToScreenPoint(base.gameObject.transform.position); Vector2 vector2 = GUI.skin.label.CalcSize(new GUIContent(text)); GUI.Label(new Rect(vector.x, (float)Screen.height - vector.y, vector2.x, vector2.y), text); } } } public void TryAttract(Transform target) { if (!_IsAtracted && !_IsScarred) { Target = target; if (Vector3.Distance(base.transform.position, target.position) >= 0.5f) { _IsAtracted = true; } else { _IsScarred = true; } } } public bool IsLureAccepted(int id) { foreach (GameManager.AcceptFishBait acceptFishLure in Data.acceptFishLures) { if (acceptFishLure.baitId == id) { Debug.Log(base.gameObject.name + " accept lure"); return true; } } Debug.Log(base.gameObject.name + " is not accept lure"); return false; } public bool IsBaitAccepted(int id) { foreach (GameManager.AcceptFishBait acceptFishBait in Data.acceptFishBaits) { if (acceptFishBait.baitId == id) { Debug.Log(base.gameObject.name + " accept bait"); return true; } } Debug.Log(base.gameObject.name + " is not accept bait"); return false; } public void EagleEyeRender(bool isEagleEyeEnabled = false, Material eagleMaterial = null, float opacity = 0f) { if (lodGroup == null) { return; } if (isEagleEyeEnabled && eagleMaterial == null) { throw new ArgumentNullException("eagleMaterial", "Eagle Eye mode is enabled, but no material was provided."); } if (isEagleEyeEnabled) { if (rendererMaterialsEagle == null) { rendererMaterialsEagle = new Material[rendererMaterialsOriginal.Length][]; for (int i = 0; i < rendererMaterialsOriginal.Length; i++) { rendererMaterialsEagle[i] = new Material[rendererMaterialsOriginal[i].Length]; for (int j = 0; j < rendererMaterialsOriginal[i].Length; j++) { rendererMaterialsEagle[i][j] = new Material(eagleMaterial) { mainTexture = rendererMaterialsOriginal[i][j].mainTexture }; } } } if (lodGroup.gameObject.layer != LayerMask.NameToLayer("EagleEye")) { lodGroup.gameObject.layer = LayerMask.NameToLayer("EagleEye"); LOD[] lODs = lodGroup.GetLODs(); for (int k = 0; k < lODs.Length; k++) { if (lODs[k].renderers.Length != 0 && lODs[k].renderers[0] != null) { lODs[k].renderers[0].sharedMaterials = rendererMaterialsEagle[k]; } } } Material[][] array = rendererMaterialsEagle; foreach (Material[] array2 in array) { for (int m = 0; m < array2.Length; m++) { array2[m].SetFloat("_Opacity", opacity); } } } else { if (lodGroup.gameObject.layer == LayerMask.NameToLayer("Fish")) { return; } lodGroup.gameObject.layer = LayerMask.NameToLayer("Fish"); LOD[] lODs2 = lodGroup.GetLODs(); for (int n = 0; n < lODs2.Length; n++) { if (lODs2[n].renderers.Length != 0 && lODs2[n].renderers[0] != null) { lODs2[n].renderers[0].sharedMaterials = rendererMaterialsOriginal[n]; } } } } public void SpitOutBait() { if (!(CurrentFishInFight != this)) { FishEntity.OnPreSpitOutBait?.Invoke(this); ResetCurrentFishInFight(); Physics.RemoveJoint(); FishEntity.OnPostSpitOutBait?.Invoke(this); } } public void LostAttract() { _IsAtracted = false; } public void Cull() { Physics.Rbody.isKinematic = true; Physics.Rbody.velocity = Vector3.zero; base.transform.position = new Vector3(0f, 1000f, 0f); IsCulled = true; ChangeState(FishState.Idle); } public void Draw() { base.transform.position = Target.position; Physics.Rbody.isKinematic = false; Physics.Rbody.freezeRotation = true; IsCulled = false; ChangeState(FishState.Idle); } public void Draw(FishTarget target) { CurrentArea = target.Area; base.transform.position = target.Transform.position; Physics.Rbody.isKinematic = false; IsCulled = false; ChangeState(FishState.Idle); } private void BuildSplash() { Vector3 position = base.transform.position; Rigidbody rbody = Physics.Rbody; if (!(rbody.velocity.y > 0.3f)) { Vector3 vector = Vector3.one * base.transform.localScale.x; vector *= Mathf.Max(0.07f, 0.04f * Mathf.Abs(rbody.velocity.y)); int num = 0; GameObject obj = LeanPool.Spawn(FScriptsHandler.Instance.waterFishSplash[num]); GameWaterSystem.FindWaterLevelAtLocation(base.transform.position, out var waterLevel); obj.transform.position = new Vector3(position.x, waterLevel + 0.05f, position.z); obj.GetComponent().volume = 0.5f * vector.x; vector = Vector3.ClampMagnitude(vector, 1f); obj.transform.localScale = vector * 1.5f; } } public void SetAIEnabled(bool value) { _AI.IsEnabled = value; } public void SetRandomWaypoint(float moveSpeed) { FishTarget randomTarget = CurrentArea.GetRandomTarget(_Data.BehaviourType); if (randomTarget != null && !(randomTarget.Transform == null)) { _AI.Target = randomTarget.Transform; _AI.MoveSpeed = moveSpeed; } } public float GetDistanceToTarget() { return Vector3.Distance(_AI.Target.position, base.transform.position); } public void SetAnimatorFloat(string s, float f) { if (_Animator == null) { Debug.LogWarning("There is no animator"); } else { _Animator.SetFloat(s, f); } } public void SetAnimatorBool(string s, bool b) { if (_Animator == null) { Debug.LogWarning("There is no animator"); } else { _Animator.SetBool(s, b); } } public void ClampMaxDistance(float maxDistance, Transform targetTransform) { if (Vector3.Distance(base.transform.position, targetTransform.position) > maxDistance) { Vector3 normalized = (base.transform.position - targetTransform.position).normalized; base.transform.position = targetTransform.position + normalized * maxDistance; } } public void InitializeData(FishData data, float weight) { _Data = data; _Weight = weight; base.transform.GetChild(0).localScale = data.GetFishScale(weight); } private float GetDistanceThreshold(Vector3 target, float speed) { Vector3 b = JointAnchor.position + base.transform.forward * speed; return Vector3.Distance(target, b); } private bool CanFightWithLure() { return LastCatchTime + nextCatchDelayInterval < Time.time; } private void SetStateTimer(float timer) { _StateChangeTime = timer + Time.time; } private bool HandleInteractionWithLocalPlayer() { bool result = false; MultiplayerFishSpawner.CheckFishInteractionWithPlayer(this, out var withLocalPlayer, out var withRemotePlayer); MultiplayerFishSpawner.NetworkedFish networkedFish = MultiplayerFishSpawner.GetNetworkedFish(this); if (withRemotePlayer) { ChangeState(FishState.MultiplayerHide); result = true; } else if (withLocalPlayer) { ChangeState(FishState.Atack); result = true; } else if (_IsCanAttack || _IsAtracted) { if (networkedFish.actorInControl == PhotonNetwork.LocalPlayer.ActorNumber) { MultiplayerFishSpawner.SpawnMultiplayerFishEntity(this); } else if (_IsCanSendRequest) { MultiplayerFishSpawner.FishControlRequest(this); lastServerRequestTime = Time.time; } } else if (networkedFish.actorInControl == PhotonNetwork.LocalPlayer.ActorNumber && _IsCanSendRequest) { MultiplayerFishSpawner.FishControlRequestCancel(this); lastServerRequestTime = Time.time; } return result; } public void ReJoinChwytak(Rigidbody newJoin) { if (!TryGetComponent(out var component)) { component = base.gameObject.AddComponent(); } component.anchor = base.transform.InverseTransformVector(JointAnchor.position - base.transform.position); component.autoConfigureConnectedAnchor = false; component.connectedAnchor = Vector3.zero; component.xMotion = ConfigurableJointMotion.Locked; component.yMotion = ConfigurableJointMotion.Locked; component.zMotion = ConfigurableJointMotion.Locked; component.angularXMotion = ConfigurableJointMotion.Free; component.angularYMotion = ConfigurableJointMotion.Free; component.angularZMotion = ConfigurableJointMotion.Free; component.connectedBody = newJoin; component.projectionMode = JointProjectionMode.PositionAndRotation; } [Command("destroy_hooked_fish", Platform.AllPlatforms, MonoTargetType.Single)] private void TryDestroyFish() { if (!(CurrentFishInFight != this)) { Debug.Log("DestroyFish now"); FishSpawner.Despawn(CurrentFishInFight); UnityEngine.Object.Destroy(base.gameObject); FishEntity.OnPreSpitOutBait?.Invoke(this); FishEntity.OnPostSpitOutBait?.Invoke(this); ResetCurrentFishInFight(); ResetCurrentFishInAttack(); } } public void TryGrowFish(float weightNew) { if (!(CurrentFishInFight == this) && CurrentFishState != FishState.Atack && !MultiplayerFishSpawner.CheckFishInteractionWithPlayer(this) && !IsCulled) { InitializeData(Data, weightNew); } } public void TryKillOldFish() { if (!(CurrentFishInFight == this) && CurrentFishState != FishState.Atack && !MultiplayerFishSpawner.CheckFishInteractionWithPlayer(this) && !IsCulled) { FishSpawner.Despawn(this); UnityEngine.Object.Destroy(base.gameObject); FishEntity.OnOldFishKill?.Invoke(this); } } [Command("attach_fish", Platform.AllPlatforms, MonoTargetType.Single)] private void TryAttachNearFish() { if (CurrentFishInFight != null) { return; } float num = float.PositiveInfinity; FLure fLure = UnityEngine.Object.FindObjectOfType(); FishEntity fishEntity = null; FishEntity[] array = UnityEngine.Object.FindObjectsOfType(); foreach (FishEntity fishEntity2 in array) { float num2 = Vector3.Distance(fLure.transform.position, fishEntity2.transform.position); if (num2 < num) { fishEntity = fishEntity2; num = num2; } } Debug.Log($"FISH ATTACH {fishEntity}"); if (fishEntity != null) { fishEntity.SetLureTarget(fLure.transform); fishEntity.ChangeState(FishState.Atack); } } [Command("toggle-fish-movement", MonoTargetType.All, Platform.AllPlatforms)] public void ToggleFishLabel() { AI.enabled = !AI.enabled; } } }