You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

415 lines
14 KiB
C#

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
[AddComponentMenu("Enviro/Weather Zone")]
public class EnviroZone : MonoBehaviour {
public enum WeatherUpdateMode
{
GameTimeHours,
RealTimeMinutes
}
[Tooltip("Defines the zone name.")]
public string zoneName;
[Tooltip("Uncheck to remove OnTriggerExit call when using overlapping zone layout.")]
public bool ExitToDefault = true;
[Tooltip("Enable this option to force to change weather preset. Disable that option and same weather can occure in row.")]
public bool forceWeatherChange = false;
public List<EnviroWeatherPrefab> zoneWeather = new List<EnviroWeatherPrefab>();
public List<EnviroWeatherPrefab> curPossibleZoneWeather;
[Header("Zone weather settings:")]
[Tooltip("Add all weather prefabs for this zone here.")]
public List<EnviroWeatherPreset> zoneWeatherPresets = new List<EnviroWeatherPreset>();
[Tooltip("Shall weather changes occure based on gametime or realtime?")]
public WeatherUpdateMode updateMode = WeatherUpdateMode.GameTimeHours;
[Tooltip("Defines how often (gametime hours or realtime minutes) the system will heck to change the current weather conditions.")]
public float WeatherUpdateIntervall = 6f;
[Header("Zone scaling and gizmo:")]
[Tooltip("Enable this to use a mesh for zone trigger.")]
public bool useMeshZone = false;
[Tooltip("Custom Zone Mesh")]
public Mesh zoneMesh;
[Tooltip("Defines the zone scale.")]
public Vector3 zoneScale = new Vector3 (100f, 100f, 100f);
[Tooltip("Defines the color of the zone's gizmo in editor mode.")]
public Color zoneGizmoColor = Color.gray;
[Header("Current active weather:")]
[Tooltip("The current active weather conditions.")]
public EnviroWeatherPrefab currentActiveZoneWeatherPrefab;
public EnviroWeatherPreset currentActiveZoneWeatherPreset;
[HideInInspector]public EnviroWeatherPrefab lastActiveZoneWeatherPrefab;
[HideInInspector]public EnviroWeatherPreset lastActiveZoneWeatherPreset;
private BoxCollider zoneCollider;
private MeshCollider zoneMeshCollider;
private double nextUpdate;
private float nextUpdateRealtime;
public bool init = false;
private bool isDefault;
void Start ()
{
if (zoneWeatherPresets.Count > 0)
{
if (!useMeshZone)
{
zoneCollider = gameObject.AddComponent<BoxCollider>();
zoneCollider.isTrigger = true;
}
else
{
zoneMeshCollider = gameObject.AddComponent<MeshCollider>();
zoneMeshCollider.sharedMesh = zoneMesh;
zoneMeshCollider.convex = true;
zoneMeshCollider.isTrigger = true;
}
if (!EnviroSkyMgr.instance.IsDefaultZone(gameObject))
EnviroSkyMgr.instance.RegisterZone (this);
else
isDefault = true;
UpdateZoneScale ();
nextUpdate = EnviroSkyMgr.instance.GetCurrentTimeInHours() + WeatherUpdateIntervall;
nextUpdateRealtime = Time.time + (WeatherUpdateIntervall * 60f);
}
else
{
Debug.Log("Please add Weather Prefabs to Zone:" + gameObject.name);
}
}
public void UpdateZoneScale ()
{
if (!isDefault && !useMeshZone)
zoneCollider.size = zoneScale;
else if (!isDefault && useMeshZone)
transform.localScale = zoneScale;
else if (isDefault && !useMeshZone)
zoneCollider.size = (Vector3.one * (1f / transform.localScale.y)) * 0.25f;
}
public void CreateZoneWeatherTypeList ()
{
// Add new WeatherPrefabs
for ( int i = 0; i < zoneWeatherPresets.Count; i++)
{
if (zoneWeatherPresets [i] == null) {
Debug.Log ("Warning! Missing Weather Preset in Zone: " + this.zoneName);
return;
}
bool addThis = true;
for (int i2 = 0; i2 < EnviroSkyMgr.instance.GetCurrentWeatherPresetList().Count; i2++)
{
if (zoneWeatherPresets [i] == EnviroSkyMgr.instance.GetCurrentWeatherPresetList()[i2])
{
addThis = false;
zoneWeather.Add (EnviroSkyMgr.instance.GetCurrentWeatherPrefabList()[i2]);
}
}
if (addThis) {
GameObject wPrefab = new GameObject ();
EnviroWeatherPrefab wP = wPrefab.AddComponent<EnviroWeatherPrefab> ();
wP.weatherPreset = zoneWeatherPresets [i];
wPrefab.name = wP.weatherPreset.Name;
// Check and create particle systems.
for (int w = 0; w < wP.weatherPreset.effectSystems.Count; w++)
{
if (wP.weatherPreset.effectSystems [w] == null || wP.weatherPreset.effectSystems [w].prefab == null) {
Debug.Log ("Warning! Missing Particle System Entry: " + wP.weatherPreset.Name);
Destroy (wPrefab);
return;
}
GameObject eS = (GameObject)Instantiate (wP.weatherPreset.effectSystems [w].prefab, wPrefab.transform);
eS.transform.localPosition = wP.weatherPreset.effectSystems [w].localPositionOffset;
eS.transform.localEulerAngles = wP.weatherPreset.effectSystems [w].localRotationOffset;
ParticleSystem pS = eS.GetComponent<ParticleSystem> ();
if (pS != null)
wP.effectSystems.Add (pS);
else {
pS = eS.GetComponentInChildren<ParticleSystem> ();
if (pS != null)
wP.effectSystems.Add (pS);
else {
Debug.Log ("No Particle System found in prefab in weather preset: " + wP.weatherPreset.Name);
Destroy (wPrefab);
return;
}
}
}
wP.effectEmmisionRates.Clear ();
wPrefab.transform.parent = EnviroSkyMgr.instance.GetVFXHolder().transform;
wPrefab.transform.localPosition = Vector3.zero;
wPrefab.transform.localRotation = Quaternion.identity;
zoneWeather.Add(wP);
EnviroSkyMgr.instance.GetCurrentWeatherPrefabList().Add (wP);
EnviroSkyMgr.instance.GetCurrentWeatherPresetList().Add (zoneWeatherPresets [i]);
}
}
// Setup Particle Systems Emission Rates
for (int i = 0; i < zoneWeather.Count; i++)
{
for (int i2 = 0; i2 < zoneWeather[i].effectSystems.Count; i2++)
{
zoneWeather[i].effectEmmisionRates.Add(EnviroSkyMgr.instance.GetEmissionRate(zoneWeather[i].effectSystems[i2]));
EnviroSkyMgr.instance.SetEmissionRate(zoneWeather[i].effectSystems[i2],0f);
}
}
//Set initial weather
if (isDefault && EnviroSkyMgr.instance.GetStartWeatherPreset() != null)
{
EnviroSkyMgr.instance.ChangeWeatherInstant(EnviroSkyMgr.instance.GetStartWeatherPreset());
for (int i = 0; i < zoneWeather.Count; i++)
{
if(zoneWeather[i].weatherPreset == EnviroSkyMgr.instance.GetStartWeatherPreset())
{
currentActiveZoneWeatherPrefab = zoneWeather[i];
lastActiveZoneWeatherPrefab = zoneWeather[i];
}
}
currentActiveZoneWeatherPreset = EnviroSkyMgr.instance.GetStartWeatherPreset();
lastActiveZoneWeatherPreset = EnviroSkyMgr.instance.GetStartWeatherPreset();
}
else
{
currentActiveZoneWeatherPrefab = zoneWeather [0];
lastActiveZoneWeatherPrefab = zoneWeather [0];
currentActiveZoneWeatherPreset = zoneWeatherPresets [0];
lastActiveZoneWeatherPreset = zoneWeatherPresets [0];
}
nextUpdate = EnviroSkyMgr.instance.GetCurrentTimeInHours() + WeatherUpdateIntervall;
}
void BuildNewWeatherList ()
{
curPossibleZoneWeather = new List<EnviroWeatherPrefab> ();
for (int i = 0; i < zoneWeather.Count; i++)
{
switch (EnviroSkyMgr.instance.GetCurrentSeason())
{
case EnviroSeasons.Seasons.Spring:
if (zoneWeather[i].weatherPreset.Spring)
curPossibleZoneWeather.Add(zoneWeather[i]);
break;
case EnviroSeasons.Seasons.Summer:
if (zoneWeather[i].weatherPreset.Summer)
curPossibleZoneWeather.Add(zoneWeather[i]);
break;
case EnviroSeasons.Seasons.Autumn:
if (zoneWeather[i].weatherPreset.Autumn)
curPossibleZoneWeather.Add(zoneWeather[i]);
break;
case EnviroSeasons.Seasons.Winter:
if (zoneWeather[i].weatherPreset.winter)
curPossibleZoneWeather.Add(zoneWeather[i]);
break;
}
}
}
EnviroWeatherPrefab PossibiltyCheck ()
{
List<EnviroWeatherPrefab> over = new List<EnviroWeatherPrefab> ();
for (int i = 0 ; i < curPossibleZoneWeather.Count;i++)
{
int würfel = UnityEngine.Random.Range (0,100);
if (EnviroSkyMgr.instance.GetCurrentSeason() == EnviroSeasons.Seasons.Spring)
{
if (würfel <= curPossibleZoneWeather[i].weatherPreset.possibiltyInSpring)
over.Add(curPossibleZoneWeather[i]);
}else
if (EnviroSkyMgr.instance.GetCurrentSeason() == EnviroSeasons.Seasons.Summer)
{
if (würfel <= curPossibleZoneWeather[i].weatherPreset.possibiltyInSummer)
over.Add(curPossibleZoneWeather[i]);
}else
if (EnviroSkyMgr.instance.GetCurrentSeason() == EnviroSeasons.Seasons.Autumn)
{
if (würfel <= curPossibleZoneWeather[i].weatherPreset.possibiltyInAutumn)
over.Add(curPossibleZoneWeather[i]);
}else
if (EnviroSkyMgr.instance.GetCurrentSeason() == EnviroSeasons.Seasons.Winter)
{
if (würfel <= curPossibleZoneWeather[i].weatherPreset.possibiltyInWinter)
over.Add(curPossibleZoneWeather[i]);
}
}
// No other preset to change to return the current one.
if (over.Count == 0)
return currentActiveZoneWeatherPrefab;
if (forceWeatherChange)
{
if (over[0].weatherPreset == currentActiveZoneWeatherPreset)
{
if (over.Count > 1)
{
EnviroSkyMgr.instance.NotifyZoneWeatherChanged(over[1].weatherPreset, this);
return over[1];
}
else
{
EnviroSkyMgr.instance.NotifyZoneWeatherChanged(over[0].weatherPreset, this);
return over[0];
}
}
else
{
EnviroSkyMgr.instance.NotifyZoneWeatherChanged(over[0].weatherPreset, this);
return over[0];
}
}
else
{
//Change to the first preset we have in that list.
EnviroSkyMgr.instance.NotifyZoneWeatherChanged(over[0].weatherPreset, this);
return over[0];
}
}
void WeatherUpdate ()
{
nextUpdate = EnviroSkyMgr.instance.GetCurrentTimeInHours() + WeatherUpdateIntervall;
nextUpdateRealtime = Time.time + (WeatherUpdateIntervall * 60f);
BuildNewWeatherList ();
lastActiveZoneWeatherPrefab = currentActiveZoneWeatherPrefab;
lastActiveZoneWeatherPreset = currentActiveZoneWeatherPreset;
currentActiveZoneWeatherPrefab = PossibiltyCheck ();
currentActiveZoneWeatherPreset = currentActiveZoneWeatherPrefab.weatherPreset;
EnviroSkyMgr.instance.NotifyZoneWeatherChanged (currentActiveZoneWeatherPreset, this);
}
IEnumerator CreateWeatherListLate ()
{
yield return 0;
CreateZoneWeatherTypeList ();
init = true;
}
void LateUpdate()
{
if (EnviroSkyMgr.instance == null)
{
Debug.Log("No EnviroSky instance found!");
return;
}
if (EnviroSkyMgr.instance.IsStarted() && !init)
{
if (zoneWeatherPresets.Count < 1)
{
Debug.Log("Zone with no Presets! Please assign at least one preset. Deactivated for now!");
this.enabled = false;
return;
}
if (isDefault)
{
CreateZoneWeatherTypeList();
init = true;
}
else
StartCoroutine(CreateWeatherListLate());
}
if (updateMode == WeatherUpdateMode.GameTimeHours)
{
if (EnviroSkyMgr.instance.GetCurrentTimeInHours() > nextUpdate && EnviroSkyMgr.instance.IsAutoWeatherUpdateActive() && EnviroSkyMgr.instance.IsStarted())
WeatherUpdate();
}
else
{
if (Time.time > nextUpdateRealtime && EnviroSkyMgr.instance.IsAutoWeatherUpdateActive() && EnviroSkyMgr.instance.IsStarted())
WeatherUpdate();
}
if (EnviroSkyMgr.instance.Player == null)
{
// Debug.Log("No Player Assigned in EnviroSky object!");
return;
}
if (isDefault && init && !useMeshZone)
zoneCollider.center = new Vector3(0f, ((EnviroSkyMgr.instance.Player.transform.position.y - transform.position.y) / transform.lossyScale.y), 0f);
}
/// Triggers
void OnTriggerEnter (Collider col)
{
if (EnviroSkyMgr.instance == null)
return;
if (EnviroSkyMgr.instance.GetUseWeatherTag()) {
if (col.gameObject.tag == EnviroSkyMgr.instance.GetEnviroSkyTag()) {
Debug.Log("Change Zone by Tag");
EnviroSkyMgr.instance.SetCurrentActiveZone(this);
EnviroSkyMgr.instance.NotifyZoneChanged (this);
}
} else {
if (EnviroSkyMgr.instance.IsEnviroSkyAttached(col.gameObject)) {
Debug.Log("Change Zone by Component");
EnviroSkyMgr.instance.SetCurrentActiveZone(this);
EnviroSkyMgr.instance.NotifyZoneChanged (this);
}
}
}
void OnTriggerExit (Collider col)
{
if (ExitToDefault == false || EnviroSkyMgr.instance == null)
return;
if (EnviroSkyMgr.instance.GetUseWeatherTag()) {
if (col.gameObject.tag == EnviroSkyMgr.instance.GetEnviroSkyTag()) {
EnviroSkyMgr.instance.SetToZone(0);
EnviroSkyMgr.instance.NotifyZoneChanged (EnviroSkyMgr.instance.GetZoneByID(0));
}
} else {
if (EnviroSkyMgr.instance.IsEnviroSkyAttached(col.gameObject)) {
EnviroSkyMgr.instance.SetToZone(0);
EnviroSkyMgr.instance.NotifyZoneChanged (EnviroSkyMgr.instance.GetZoneByID(0));
}
}
}
void OnDrawGizmos ()
{
Gizmos.color = zoneGizmoColor;
Matrix4x4 rotationMatrix = Matrix4x4.TRS(transform.position, transform.rotation, Vector3.one);
Gizmos.matrix = rotationMatrix;
if (useMeshZone && zoneMesh != null)
Gizmos.DrawMesh(zoneMesh, 0, Vector3.zero, Quaternion.identity, zoneScale);
else
Gizmos.DrawCube(Vector3.zero, new Vector3(zoneScale.x, zoneScale.y, zoneScale.z));
}
}