392 lines
10 KiB
C#
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>();
|
|
}
|
|
}
|
|
}
|
|
}
|