214 lines
4.8 KiB
C#
214 lines
4.8 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using Moonlit.Utils;
|
|
using UnityEngine;
|
|
|
|
namespace Moonlit.IceFishing
|
|
{
|
|
internal class HolesController : Singleton<HolesController>
|
|
{
|
|
[Serializable]
|
|
public enum HitResult
|
|
{
|
|
Occupied = 0,
|
|
Terrain = 1,
|
|
Unoccupied = 2
|
|
}
|
|
|
|
[Serializable]
|
|
public class HitInfo
|
|
{
|
|
public HitResult Result = HitResult.Unoccupied;
|
|
|
|
public List<Hole> FoundHoles;
|
|
}
|
|
|
|
[Serializable]
|
|
private class SaveData
|
|
{
|
|
public List<HoleData> holes = new List<HoleData>();
|
|
}
|
|
|
|
[Header("Hole")]
|
|
public GameObject HolePrefab;
|
|
|
|
[SerializeField]
|
|
private GameObject _HolesParent;
|
|
|
|
public Material iceMaterial;
|
|
|
|
[Header("Random snow to draw")]
|
|
[SerializeField]
|
|
private List<GameObject> _DrilledSnowList;
|
|
|
|
[Header("Settings")]
|
|
public float MinWaterDepth = 1f;
|
|
|
|
public float WaterRaiseTime = 0.2f;
|
|
|
|
public int MaxHoleCount = 100;
|
|
|
|
private string _HoleTag = "Hole";
|
|
|
|
private string _TerrainTag = "Terrain";
|
|
|
|
private string _IceTag = "Ice";
|
|
|
|
private List<Hole> _Pool = new List<Hole>();
|
|
|
|
public string HoleTag
|
|
{
|
|
get
|
|
{
|
|
return _HoleTag;
|
|
}
|
|
}
|
|
|
|
public string TerrainTag
|
|
{
|
|
get
|
|
{
|
|
return _TerrainTag;
|
|
}
|
|
}
|
|
|
|
public string IceTag
|
|
{
|
|
get
|
|
{
|
|
return _IceTag;
|
|
}
|
|
}
|
|
|
|
public string Save()
|
|
{
|
|
SaveData saveData = new SaveData();
|
|
saveData.holes = (from x in _Pool
|
|
select x.Data into x
|
|
where x.IsFinished
|
|
select x).ToList();
|
|
string text = JsonUtility.ToJson(saveData, true);
|
|
if (string.IsNullOrEmpty(text))
|
|
{
|
|
Debug.LogError("Save data is empty!");
|
|
return null;
|
|
}
|
|
return text;
|
|
}
|
|
|
|
public void Load(string saveJson)
|
|
{
|
|
RemoveAll();
|
|
SaveData saveData = JsonUtility.FromJson<SaveData>(saveJson);
|
|
for (int i = 0; i < saveData.holes.Count; i++)
|
|
{
|
|
Create(saveData.holes[i]);
|
|
}
|
|
}
|
|
|
|
public Hole Create(HoleData data)
|
|
{
|
|
Hole hole = null;
|
|
GameObject gameObject = null;
|
|
if (MaxHoleCount >= 0)
|
|
{
|
|
while (_Pool.Count > MaxHoleCount)
|
|
{
|
|
UnityEngine.Object.Destroy(_Pool.First().gameObject);
|
|
_Pool.RemoveAt(0);
|
|
}
|
|
if (_Pool.Count == MaxHoleCount)
|
|
{
|
|
hole = _Pool.First();
|
|
_Pool.RemoveAt(0);
|
|
gameObject = hole.gameObject;
|
|
_Pool.Add(hole);
|
|
}
|
|
else
|
|
{
|
|
gameObject = UnityEngine.Object.Instantiate(HolePrefab, data.Position, Quaternion.identity);
|
|
gameObject.transform.parent = base.transform;
|
|
gameObject.name = "Hole";
|
|
hole = gameObject.GetComponent<Hole>();
|
|
_Pool.Add(hole);
|
|
}
|
|
}
|
|
hole.Set(data);
|
|
return hole;
|
|
}
|
|
|
|
public void Remove(Hole hole)
|
|
{
|
|
UnityEngine.Object.Destroy(hole.gameObject);
|
|
_Pool.Remove(hole);
|
|
}
|
|
|
|
public void RemoveAll()
|
|
{
|
|
foreach (Hole item in _Pool)
|
|
{
|
|
UnityEngine.Object.Destroy(item.gameObject);
|
|
}
|
|
_Pool.Clear();
|
|
}
|
|
|
|
public HitInfo HitCheck(Vector3 position, float radius)
|
|
{
|
|
HitInfo hitInfo = new HitInfo();
|
|
hitInfo.Result = HitResult.Unoccupied;
|
|
Vector3 point = position - Vector3.up * Singleton<HolesController>.Instance.MinWaterDepth;
|
|
Vector3 point2 = position + Vector3.up * 1f;
|
|
RaycastHit[] source = Physics.CapsuleCastAll(point, point2, radius, Vector3.up);
|
|
List<RaycastHit> list = source.Where((RaycastHit x) => x.collider.CompareTag(_HoleTag)).ToList();
|
|
if (list.Count > 0)
|
|
{
|
|
hitInfo.FoundHoles = list.Select((RaycastHit x) => x.collider.GetComponent<Hole>()).ToList();
|
|
hitInfo.Result = HitResult.Occupied;
|
|
return hitInfo;
|
|
}
|
|
List<RaycastHit> list2 = source.Where((RaycastHit x) => x.collider.CompareTag(_TerrainTag)).ToList();
|
|
List<RaycastHit> list3 = source.Where((RaycastHit x) => x.collider.gameObject.layer == LayerMask.NameToLayer("Default") || x.collider.gameObject.layer == LayerMask.NameToLayer("Terrain")).ToList();
|
|
if (list2.Count > 0 || list3.Count > 0)
|
|
{
|
|
hitInfo.Result = HitResult.Terrain;
|
|
}
|
|
return hitInfo;
|
|
}
|
|
|
|
public Vector3 FindIcePosition(Vector3 point)
|
|
{
|
|
RaycastHit[] source = (from x in Physics.RaycastAll(point, Vector3.down)
|
|
where x.collider.CompareTag(_IceTag)
|
|
select x).ToArray();
|
|
if (source.Count() != 0)
|
|
{
|
|
point.y = source.Max((RaycastHit x) => x.point.y);
|
|
return point;
|
|
}
|
|
source = (from x in Physics.RaycastAll(point, Vector3.up)
|
|
where x.collider.CompareTag(_IceTag)
|
|
select x).ToArray();
|
|
if (source.Count() != 0)
|
|
{
|
|
point.y = source.Max((RaycastHit x) => x.point.y);
|
|
return point;
|
|
}
|
|
return Vector3.zero;
|
|
}
|
|
|
|
public float GetIceThickness(Vector3 point)
|
|
{
|
|
float num = Math.Abs((Mathf.Sin((point.x + point.y + point.x * point.y) * 0.1f) + 1f) * 0.2f + 0.4f);
|
|
num = 0.6f;
|
|
Debug.Log("Ice Thickness: " + num);
|
|
return num;
|
|
}
|
|
|
|
public GameObject GetRandomSnowPrefab()
|
|
{
|
|
return _DrilledSnowList[UnityEngine.Random.Range(0, _DrilledSnowList.Count)];
|
|
}
|
|
}
|
|
}
|