using System.Collections.Generic; using System.Linq; using UFS2.Gameplay; using UFS2.ScriptableObjects; using UnityEngine; namespace ShiningGames.UFS2 { public class FishTargetBaker : MonoBehaviour { public static FishTargetBaker Instance; private List> targetsVolumes; [Tooltip("Insert here colliders for create in their volume targets for fish systems, volume it's repesent one of place eg lake or area of fish spawners")] [SerializeField] private List areas; public float pointSpacing = 2f; public bool generateOnStart = true; public bool IsDebugMode; public int numPoints; public LayerMask GroundLayerMask; private List overallPoints; private List bottomPoints; private List surfacePoints; private Transform _Container; public GameObject _OverallPointPrefab; public GameObject _BottomPointPrefab; public GameObject _SurfacePointPrefab; private List fishAreas; public List Areas => areas; public void Awake() { Instance = this; } private void Start() { FindFishAreas(); foreach (FishTargetArea area in areas) { Collider[] volumes = area.Volumes; for (int i = 0; i < volumes.Length; i++) { volumes[i].TryGetComponent(out var component); if ((bool)component) { component.enabled = false; } } } FloodTargetArea(); } private void OnDrawGizmos() { if (IsDebugMode) { DrawTargets(surfacePoints); DrawTargets(bottomPoints); DrawTargets(overallPoints); } } private void FindFishAreas() { fishAreas = GetComponentsInChildren().ToList(); if (fishAreas.Count <= 0) { return; } areas.Clear(); foreach (FishArea fishArea in fishAreas) { fishArea.Validate(); FishTargetArea item = new FishTargetArea { Volumes = fishArea.Area }; areas.Add(item); } } public static FishTarget GetRandomTarget(FishBehaviourType fishBehaviourType, Transform cullTarget = null) { FishTarget result = new FishTarget(); if ((bool)cullTarget) { FishTargetArea fishTargetArea = null; foreach (FishTargetArea area in Instance.Areas) { Collider[] volumes = area.Volumes; foreach (Collider collider in volumes) { if (cullTarget.position.x >= collider.bounds.min.x && cullTarget.position.z >= collider.bounds.min.z && cullTarget.position.x <= collider.bounds.max.x && cullTarget.position.z <= collider.bounds.max.z) { fishTargetArea = area; break; } } if (fishTargetArea != null) { break; } } if (fishTargetArea == null) { float num = float.MaxValue; foreach (FishTargetArea area2 in Instance.Areas) { Collider[] volumes = area2.Volumes; foreach (Collider collider2 in volumes) { float num2 = Vector3.Distance(cullTarget.position, collider2.bounds.center); if (num2 < num) { num = num2; fishTargetArea = area2; } } } } List list = fishTargetArea.OverallPoints; switch (fishBehaviourType) { case FishBehaviourType.PassivePredator: list = ((Random.Range(0f, 1f) > 0.5f) ? fishTargetArea.OverallPoints : fishTargetArea.BottomPoints); break; case FishBehaviourType.Deep: list = fishTargetArea.BottomPoints; break; } float num3 = (float)(fishTargetArea.SurfacePoints.Count + fishTargetArea.OverallPoints.Count + fishTargetArea.BottomPoints.Count) * 0.1f; if ((float)list.Count < num3) { if ((float)fishTargetArea.OverallPoints.Count >= num3) { list = fishTargetArea.OverallPoints; } else if ((float)fishTargetArea.BottomPoints.Count >= num3) { list = fishTargetArea.BottomPoints; } else if ((float)fishTargetArea.SurfacePoints.Count >= num3) { list = fishTargetArea.SurfacePoints; } } result = list[Random.Range(0, list.Count)]; } else { switch (fishBehaviourType) { case FishBehaviourType.ActivePredator: result = GetRandomOverallTarget(); break; case FishBehaviourType.PassivePredator: result = ((Random.Range(0f, 1f) > 0.5f) ? GetRandomOverallTarget() : GetRandomBottomTarget()); break; case FishBehaviourType.Deep: result = GetRandomBottomTarget(); break; case FishBehaviourType.Normal: result = GetRandomOverallTarget(); break; } } return result; } public bool CheckIfFishCanBeSpawnedInArea(FishEntity fishEntity, FishTargetArea fishTargetArea) { bool result = true; if (fishAreas != null && fishAreas.Count > 0) { FishArea fishArea = fishAreas.FirstOrDefault((FishArea area) => area.Area[0] == fishTargetArea.Volumes[0]); if (fishArea != null) { FishArea.FishInArea fishInArea = fishArea.FishInAreaList.FirstOrDefault((FishArea.FishInArea element) => element.fishData == fishEntity.Data); if (fishInArea != null && fishInArea.spawnWeight <= 0f) { result = false; } } } return result; } public static FishTarget GetRandomOverallTarget() { if (Instance.overallPoints != null && Instance.overallPoints.Count != 0) { return Instance.overallPoints[Random.Range(0, Instance.overallPoints.Count - 1)]; } return null; } public static FishTarget GetRandomBottomTarget() { if (Instance.bottomPoints != null && Instance.bottomPoints.Count != 0) { return Instance.bottomPoints[Random.Range(0, Instance.bottomPoints.Count - 1)]; } return null; } public static FishTarget GetRandomSurfaceTarget() { if (Instance.surfacePoints != null && Instance.surfacePoints.Count != 0) { return Instance.surfacePoints[Random.Range(0, Instance.surfacePoints.Count - 1)]; } return null; } private Transform CreateTargetInArea(Vector3 pos, FishDeepType groundType, FishTargetArea area) { Transform t = null; switch (groundType) { case FishDeepType.Overall: { Create(_OverallPointPrefab, area, out var fishTarget3); area.OverallPoints.Add(fishTarget3); overallPoints.Add(fishTarget3); break; } case FishDeepType.Bottom: { Create(_BottomPointPrefab, area, out var fishTarget2); area.BottomPoints.Add(fishTarget2); bottomPoints.Add(fishTarget2); break; } case FishDeepType.Surface: { Create(_SurfacePointPrefab, area, out var fishTarget); area.SurfacePoints.Add(fishTarget); surfacePoints.Add(fishTarget); break; } } return t; void Create(GameObject prefab, FishTargetArea farea, out FishTarget reference) { GameObject gameObject = Object.Instantiate(prefab, pos, Quaternion.identity, _Container); gameObject.SetActive(value: true); t = gameObject.transform; reference = new FishTarget { Transform = gameObject.transform, Area = farea, GroundType = groundType }; } } private void DrawTargets(List targets) { foreach (FishTarget target in targets) { Gizmos.DrawWireSphere(target.Transform.position, 0.25f); } } private void FloodTargetArea() { FindFishAreas(); ClearTargetArea(); foreach (FishTargetArea area in areas) { Transform transform = new GameObject("Area").transform; transform.transform.parent = base.transform; transform.localPosition = Vector3.zero; transform.localRotation = Quaternion.identity; Collider[] volumes = area.Volumes; foreach (Collider volume in volumes) { FishArea fishArea = fishAreas.FirstOrDefault((FishArea area) => area.Area.Contains(volume)); float num = ((fishArea != null && fishArea.PointSpacingOverride > 0f) ? fishArea.PointSpacingOverride : pointSpacing); _Container = new GameObject("TargetsVolume").transform; _Container.transform.parent = transform; _Container.localPosition = Vector3.zero; _Container.localRotation = Quaternion.identity; List list = new List(); List list2 = new List(); List list3 = new List(); Bounds bounds = volume.bounds; Vector3 size = bounds.size; Vector3 vector = new Vector3(volume.bounds.min.x, volume.bounds.max.y, volume.bounds.min.z); for (float num2 = 0f; num2 < size.x; num2 += num) { for (float num3 = 0f; num3 < size.z; num3 += num) { Vector3 vector2 = vector + new Vector3(num2, 0f, num3); if (!GameWaterSystem.FindWaterLevelAtLocation(vector2, out var waterLevel)) { continue; } vector2.y = waterLevel - 0.1f; if (Physics.OverlapSphere(vector2, num * 0.5f, GroundLayerMask).Length == 0) { float num4 = 5f; if (!Physics.Raycast(vector2 + Vector3.up * num4, Vector3.down, out var _, num4, GroundLayerMask)) { Transform item = CreateTargetInArea(vector2, FishDeepType.Surface, area); list2.Add(item); } } } } int count = list2.Count; Vector3 vector3 = Vector3.down * num; int num5 = (int)(size.y / num + 1f); while (count > 0) { foreach (Transform item4 in list2) { if (bounds.Contains(item4.position + vector3)) { if (Physics.Raycast(item4.position, vector3, out var hitInfo2, num, GroundLayerMask)) { Transform item2 = CreateTargetInArea(hitInfo2.point, FishDeepType.Bottom, area); list3.Add(item2); } else { Transform item3 = CreateTargetInArea(item4.position + vector3, FishDeepType.Overall, area); list3.Add(item3); list.Add(list3.Last()); } } } list2 = new List(list); list3 = new List(); list = new List(); count = list2.Count; num5--; Debug.Log($"Points to check {list2.Count}"); if (num5 <= 0) { Debug.Log("VOLUME ITERATION THRESHOLD!!!"); break; } } } } } private void ClearTargetArea() { overallPoints = new List(); bottomPoints = new List(); surfacePoints = new List(); List list = new List(); foreach (Transform item in base.transform) { if (item.name == "Area") { list.Add(item); } } list.ForEach(delegate(Transform element) { Object.DestroyImmediate(element.gameObject); }); foreach (FishTargetArea area in areas) { area.BottomPoints = new List(); area.OverallPoints = new List(); area.SurfacePoints = new List(); } } } }