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

392 lines
10 KiB
C#

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<List<Collider>> 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<FishTargetArea> areas;
public float pointSpacing = 2f;
public bool generateOnStart = true;
public bool IsDebugMode;
public int numPoints;
public LayerMask GroundLayerMask;
private List<FishTarget> overallPoints;
private List<FishTarget> bottomPoints;
private List<FishTarget> surfacePoints;
private Transform _Container;
public GameObject _OverallPointPrefab;
public GameObject _BottomPointPrefab;
public GameObject _SurfacePointPrefab;
private List<FishArea> fishAreas;
public List<FishTargetArea> 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<MeshRenderer>(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<FishArea>().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<FishTarget> 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<FishTarget> 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<Transform> list = new List<Transform>();
List<Transform> list2 = new List<Transform>();
List<Transform> list3 = new List<Transform>();
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<Transform>(list);
list3 = new List<Transform>();
list = new List<Transform>();
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<FishTarget>();
bottomPoints = new List<FishTarget>();
surfacePoints = new List<FishTarget>();
List<Transform> list = new List<Transform>();
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<FishTarget>();
area.OverallPoints = new List<FishTarget>();
area.SurfacePoints = new List<FishTarget>();
}
}
}
}