Files
2026-03-04 10:03:45 +08:00

339 lines
12 KiB
C#

using System;
using System.Collections;
using Obvious.Soap;
using ShiningGames.UFS2;
using UFS2.ScriptableObjects;
using UltimateWater;
using UnityEngine;
using Voxus.Random;
namespace UFS2.Gameplay
{
public class FishSpawner : MonoBehaviour
{
[Range(0f, 100f)]
public int InstantiateCount = 1;
public int FishPoolMaxSize = 100;
[SerializeField]
private LevelFishData LevelFishData;
[SerializeField]
private Vector3Variable player_CurrentPosition;
[SerializeField]
private FloatVariable lineTension;
public bool IsTriggerCollider;
public GameObject ObjectPool;
private float lastSpawnTime;
private const float spawnCooldown = 1f;
public static event Action<FishEntity, int> OnSpawnFish;
public static event Action<FishEntity> OnDespawnFish;
public static event Action OnStartFishesSpawned;
private void OnEnable()
{
FishEntity.OnPostSpitOutBait += FishEntity_OnPostSpitOutBait;
FishEntity.OnOldFishKill += FishEntity_OnPostSpitOutBait;
MultiplayerFishSpawner.OnNetworkedFishSpawn += MultiplayerFishSpawner_OnNetworkedFishSpawn;
MultiplayerFishSpawner.OnNetworkedFishDelete += MultiplayerFishSpawner_OnNetworkedFishDelete;
MultiplayerFishSpawner.OnFishDeleteAfterInteraction += MultiplayerFishSpawner_OnFishDeleteAfterInteraction;
}
private void OnDisable()
{
FishEntity.OnPostSpitOutBait -= FishEntity_OnPostSpitOutBait;
FishEntity.OnOldFishKill -= FishEntity_OnPostSpitOutBait;
MultiplayerFishSpawner.OnNetworkedFishSpawn -= MultiplayerFishSpawner_OnNetworkedFishSpawn;
MultiplayerFishSpawner.OnNetworkedFishDelete -= MultiplayerFishSpawner_OnNetworkedFishDelete;
MultiplayerFishSpawner.OnFishDeleteAfterInteraction -= MultiplayerFishSpawner_OnFishDeleteAfterInteraction;
}
private void FishEntity_OnPostSpitOutBait(FishEntity fish)
{
if (!MultiplayerFishSpawner.IsSlave)
{
InstantiateNewFish(1);
}
}
private void MultiplayerFishSpawner_OnNetworkedFishSpawn(MultiplayerFishSpawner.NetworkedFish networkedFish)
{
if (MultiplayerFishSpawner.IsSlave)
{
networkedFish.fishEntity = InstantiateNewFish(networkedFish.fishID, networkedFish.fishWeight, networkedFish.position, networkedFish.targetAreaID);
}
}
private void MultiplayerFishSpawner_OnNetworkedFishDelete(MultiplayerFishSpawner.NetworkedFish networkedFish)
{
if (MultiplayerFishSpawner.IsSlave)
{
FishEntity fishEntity = networkedFish.fishEntity;
if (fishEntity != null)
{
FishSpawner.OnDespawnFish?.Invoke(fishEntity);
fishEntity.gameObject.Destroy();
}
}
}
private void MultiplayerFishSpawner_OnFishDeleteAfterInteraction()
{
if (!MultiplayerFishSpawner.IsSlave)
{
InstantiateNewFish(1);
}
}
private void Start()
{
int count = ((!MultiplayerFishSpawner.IsSlave) ? LevelFishData.StartCount : 0);
InstantiateNewFish(count);
StartCoroutine(WaitForStartFishGenerated(count));
}
private void Update()
{
InstantiateExtraFish();
}
private IEnumerator WaitForStartFishGenerated(int count)
{
OnSpawnFish += FishSpawner_OnSpawnFish;
while (count > 0)
{
yield return null;
}
FishSpawner.OnStartFishesSpawned?.Invoke();
OnSpawnFish -= FishSpawner_OnSpawnFish;
void FishSpawner_OnSpawnFish(FishEntity obj, int levelFishDataIndex)
{
count--;
}
}
public static void Despawn(FishEntity fish)
{
FishSpawner.OnDespawnFish?.Invoke(fish);
}
public void KillFishes()
{
FishEntity[] componentsInChildren = ObjectPool.GetComponentsInChildren<FishEntity>();
foreach (FishEntity fishEntity in componentsInChildren)
{
FishSpawner.OnDespawnFish?.Invoke(fishEntity);
fishEntity.gameObject.Destroy();
}
}
public void InstantiateExtraFish()
{
if (MultiplayerFishSpawner.IsMaster)
{
int count = Singleton<FishEntityManager>.Instance.CullTransforms.Count;
int count2 = Singleton<FishEntityManager>.Instance.AllFishes.Count;
int num = LevelFishData.StartCount;
if (count >= 7)
{
num = 70;
}
if (count >= 14)
{
num = 120;
}
if (count2 < num && Time.time - lastSpawnTime >= 1f)
{
lastSpawnTime = Time.time;
InstantiateNewFish(1);
}
}
}
public FishEntity InstantiateNewFish(int fishIndex, float weight, Vector3 position, int targetAreaID)
{
if (fishIndex < 0 || fishIndex >= LevelFishData.FishesSetting.Count)
{
Debug.LogError("Invalid fish index specified for spawning.");
return null;
}
LevelFishData.FishDataHelper fishDataHelper = LevelFishData.FishesSetting[fishIndex];
GameObject original = fishDataHelper.FishData.LoadFishResource(weight);
GameObject gameObject = new GameObject("FishObject " + fishDataHelper.FishData.Name + " " + weight);
GameObject gameObject2 = UnityEngine.Object.Instantiate(original, gameObject.transform);
gameObject2.transform.localPosition = Vector3.zero;
gameObject2.transform.localRotation = Quaternion.identity;
Transform jointAnchor = gameObject2.GetComponent<FFish>().jointAnchor;
Transform transform = gameObject2.GetComponentInChildren<SpringJoint>().transform;
if (transform.TryGetComponent<Collider>(out var component))
{
UnityEngine.Object.Destroy(component);
}
Collider[] componentsInChildren = gameObject2.GetComponentsInChildren<Collider>();
for (int i = 0; i < componentsInChildren.Length; i++)
{
componentsInChildren[i].isTrigger = true;
}
UnityEngine.Object.Destroy(gameObject2.GetComponent<FFishRagDoll>());
UnityEngine.Object.Destroy(gameObject2.GetComponent<FFish>());
UnityEngine.Object.Destroy(gameObject2.GetComponentInChildren<SpringJoint>());
Rigidbody[] componentsInChildren2 = gameObject2.GetComponentsInChildren<Rigidbody>();
for (int i = 0; i < componentsInChildren2.Length; i++)
{
UnityEngine.Object.Destroy(componentsInChildren2[i]);
}
FishTargetArea fishTargetArea = FishTargetBaker.Instance.Areas[targetAreaID];
LocalAvoidance localAvoidance = gameObject.AddComponent<LocalAvoidance>();
localAvoidance.TailRag = transform;
localAvoidance.Target = fishTargetArea.GetRandomTarget(fishDataHelper.FishData.BehaviourType).Transform;
FishEntity fishEntity = gameObject.AddComponent<FishEntity>();
FishPhysics fishPhysics = gameObject.AddComponent<FishPhysics>();
gameObject.AddComponent<Rigidbody>().collisionDetectionMode = CollisionDetectionMode.ContinuousDynamic;
gameObject.AddComponent<FishScanner>();
gameObject2.GetComponent<Animator>().cullingMode = AnimatorCullingMode.CullCompletely;
fishPhysics.ImportData(fishDataHelper.FishData, weight);
fishEntity.InitializeData(fishDataHelper.FishData, weight);
fishEntity.Player_CurrentPosition = player_CurrentPosition;
fishEntity.CurrentArea = fishTargetArea;
fishEntity.transform.position = position;
fishEntity.transform.parent = ObjectPool.transform;
fishEntity.JointAnchor = jointAnchor;
FishSpawner.OnSpawnFish?.Invoke(fishEntity, fishIndex);
return fishEntity;
}
public GameObject InstantiateFishDummy(int fishIndex, float weight, Vector3 position)
{
if (fishIndex < 0 || fishIndex >= LevelFishData.FishesSetting.Count)
{
Debug.LogError("Invalid fish index specified for spawning.");
return null;
}
LevelFishData.FishDataHelper fishDataHelper = LevelFishData.FishesSetting[fishIndex];
GameObject original = fishDataHelper.FishData.LoadFishResource(weight);
GameObject gameObject = new GameObject("FishObject " + fishDataHelper.FishData.Name + " " + weight);
gameObject.transform.position = position;
GameObject gameObject2 = UnityEngine.Object.Instantiate(original, gameObject.transform);
gameObject2.transform.localPosition = Vector3.zero;
gameObject2.transform.localRotation = Quaternion.identity;
_ = gameObject2.GetComponent<FFish>().jointAnchor;
if (gameObject2.GetComponentInChildren<SpringJoint>().transform.TryGetComponent<Collider>(out var component))
{
UnityEngine.Object.Destroy(component);
}
Collider[] componentsInChildren = gameObject2.GetComponentsInChildren<Collider>();
for (int i = 0; i < componentsInChildren.Length; i++)
{
UnityEngine.Object.Destroy(componentsInChildren[i]);
}
UnityEngine.Object.Destroy(gameObject2.GetComponent<FFishRagDoll>());
UnityEngine.Object.Destroy(gameObject2.GetComponent<FFish>());
UnityEngine.Object.Destroy(gameObject2.GetComponentInChildren<SpringJoint>());
Rigidbody[] componentsInChildren2 = gameObject2.GetComponentsInChildren<Rigidbody>();
for (int i = 0; i < componentsInChildren2.Length; i++)
{
UnityEngine.Object.Destroy(componentsInChildren2[i]);
}
gameObject2.GetComponent<Animator>().cullingMode = AnimatorCullingMode.CullCompletely;
gameObject2.transform.localScale = fishDataHelper.FishData.GetFishScale(weight);
return gameObject;
}
public void InstantiateNewFish(int count)
{
StartCoroutine(Spawn());
IEnumerator Spawn()
{
yield return null;
RandomGaussian randomGenerator = new RandomGaussian(0.2f, 0.4f);
randomGenerator.SetSeed(UnityEngine.Random.value);
for (int i = 0; i < count; i++)
{
LevelFishData.FishDataHelper randomFishDataToSpawn = LevelFishData.GetRandomFishDataToSpawn();
int arg = LevelFishData.FishesSetting.IndexOf(randomFishDataToSpawn);
Vector2 weight = randomFishDataToSpawn.Weight;
float t = Mathf.Clamp01(randomGenerator.Get());
float weight2 = Mathf.Lerp(weight.x, weight.y, t);
GameObject original = randomFishDataToSpawn.FishData.LoadFishResource(weight2);
GameObject gameObject = new GameObject("FishObject " + randomFishDataToSpawn.FishData.Name + " " + weight2);
GameObject gameObject2 = UnityEngine.Object.Instantiate(original, gameObject.transform);
gameObject2.transform.localPosition = Vector3.zero;
gameObject2.transform.localRotation = Quaternion.identity;
Transform jointAnchor = gameObject2.GetComponent<FFish>().jointAnchor;
Transform transform = gameObject2.GetComponentInChildren<SpringJoint>().transform;
if (transform.TryGetComponent<Collider>(out var component))
{
UnityEngine.Object.Destroy(component);
}
Collider[] componentsInChildren = gameObject2.GetComponentsInChildren<Collider>();
for (int j = 0; j < componentsInChildren.Length; j++)
{
componentsInChildren[j].isTrigger = true;
}
UnityEngine.Object.Destroy(gameObject2.GetComponent<FFishRagDoll>());
UnityEngine.Object.Destroy(gameObject2.GetComponent<FFish>());
UnityEngine.Object.Destroy(gameObject2.GetComponentInChildren<SpringJoint>());
Rigidbody[] componentsInChildren2 = gameObject2.GetComponentsInChildren<Rigidbody>();
for (int j = 0; j < componentsInChildren2.Length; j++)
{
UnityEngine.Object.Destroy(componentsInChildren2[j]);
}
LocalAvoidance localAvoidance = gameObject.AddComponent<LocalAvoidance>();
localAvoidance.TailRag = transform;
FishEntity fishEntity = gameObject.AddComponent<FishEntity>();
FishPhysics fishPhysics = gameObject.AddComponent<FishPhysics>();
gameObject.AddComponent<Rigidbody>().collisionDetectionMode = CollisionDetectionMode.ContinuousDynamic;
gameObject.AddComponent<FishScanner>();
Animator component2 = gameObject2.GetComponent<Animator>();
FishTarget startFishTarget = GetStartFishTarget(randomFishDataToSpawn.FishData.FishDeepType);
localAvoidance.Target = startFishTarget.Transform;
component2.cullingMode = AnimatorCullingMode.CullCompletely;
fishPhysics.ImportData(randomFishDataToSpawn.FishData, weight2);
fishEntity.InitializeData(randomFishDataToSpawn.FishData, weight2);
fishEntity.Player_CurrentPosition = player_CurrentPosition;
fishEntity.CurrentArea = startFishTarget.Area;
fishEntity.transform.position = startFishTarget.Transform.position;
fishEntity.transform.parent = ObjectPool.transform;
fishEntity.JointAnchor = jointAnchor;
FishSpawner.OnSpawnFish?.Invoke(fishEntity, arg);
yield return null;
}
}
}
private FishTarget GetStartFishTarget(FishDeepType deepType)
{
FishTarget fishTarget = null;
fishTarget = deepType switch
{
FishDeepType.Overall => FishTargetBaker.GetRandomOverallTarget(),
FishDeepType.Bottom => FishTargetBaker.GetRandomBottomTarget(),
FishDeepType.Surface => FishTargetBaker.GetRandomSurfaceTarget(),
_ => FishTargetBaker.GetRandomOverallTarget(),
};
if (fishTarget == null)
{
fishTarget = FishTargetBaker.GetRandomOverallTarget();
}
if (fishTarget == null)
{
fishTarget = FishTargetBaker.GetRandomBottomTarget();
}
if (fishTarget == null)
{
fishTarget = FishTargetBaker.GetRandomSurfaceTarget();
}
return fishTarget;
}
}
}