using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using UnityEngine;

// Token: 0x0200000D RID: 13
public class FOWSystem : MonoBehaviour
{
	// Token: 0x17000004 RID: 4
	// (get) Token: 0x0600009B RID: 155 RVA: 0x0000D038 File Offset: 0x0000B238
	private Texture2D texture0
	{
		get
		{
			return this.mTexture0;
		}
	}

	// Token: 0x17000005 RID: 5
	// (get) Token: 0x0600009C RID: 156 RVA: 0x0000D040 File Offset: 0x0000B240
	private Texture2D texture1
	{
		get
		{
			return this.mTexture1;
		}
	}

	// Token: 0x17000006 RID: 6
	// (get) Token: 0x0600009D RID: 157 RVA: 0x0000D048 File Offset: 0x0000B248
	private Texture2D textureMinimap
	{
		get
		{
			return this.mTextureMinimap;
		}
	}

	// Token: 0x17000007 RID: 7
	// (get) Token: 0x0600009E RID: 158 RVA: 0x0000D050 File Offset: 0x0000B250
	public float blendFactor
	{
		get
		{
			return this.mBlendFactor;
		}
	}

	// Token: 0x0600009F RID: 159 RVA: 0x0000D058 File Offset: 0x0000B258
	private void Awake()
	{
		FOWSystem.instance = this;
	}

	// Token: 0x060000A0 RID: 160 RVA: 0x0000D060 File Offset: 0x0000B260
	private IEnumerator Start()
	{
		while (!FOWSystem.readyToCreate)
		{
			yield return null;
		}
		this.saveFow = true;
		this.mTrans = base.transform;
		this.mHeights = new int[this.textureSize, this.textureSize];
		this.mSize = new Vector3((float)this.worldSize, this.heightRange.y - this.heightRange.x, (float)this.worldSize);
		this.mOrigin = this.mTrans.position;
		this.mOrigin.x = this.mOrigin.x - (float)this.worldSize * 0.5f;
		this.mOrigin.z = this.mOrigin.z - (float)this.worldSize * 0.5f;
		int num = this.textureSize * this.textureSize;
		if (!this.loaded)
		{
			this.mBuffer0 = new Color32[num];
			this.mBuffer1 = new Color32[num];
			this.mBuffer2 = new Color32[num];
		}
		this.losAreas = new int[num];
		this.CreateGrid();
		if (FOWSystem.onLoad != null)
		{
			FOWSystem.onLoad();
		}
		this.UpdateBuffer();
		this.RebuildTextures();
		this.mNextUpdate = Time.time + this.updateFrequency;
		this.mThread = new Thread(new ThreadStart(this.ThreadUpdate));
		this.mThread.Start();
		yield break;
	}

	// Token: 0x060000A1 RID: 161 RVA: 0x0000D070 File Offset: 0x0000B270
	private void OnDestroy()
	{
		if (this.mThread != null)
		{
			this.mThread.Abort();
			while (this.mThread.IsAlive)
			{
				Thread.Sleep(1);
			}
			this.mThread = null;
		}
		if (FOWSystem.onSave != null)
		{
			FOWSystem.onSave();
		}
		FOWSystem.onLoad = null;
		FOWSystem.onSave = null;
		FOWSystem.instance = null;
	}

	// Token: 0x060000A2 RID: 162 RVA: 0x0000D0D0 File Offset: 0x0000B2D0
	private void Update()
	{
		if (this.mTrans == null)
		{
			return;
		}
		if (this.textureBlendTime > 0f)
		{
			this.mBlendFactor = Mathf.Clamp01(this.mBlendFactor + Time.deltaTime / this.textureBlendTime);
		}
		else
		{
			this.mBlendFactor = 1f;
		}
		if (this.mState == FOWSystem.State.Blending)
		{
			float time = Time.time;
			if (this.mNextUpdate < time)
			{
				this.mNextUpdate = time + this.updateFrequency;
				this.mState = FOWSystem.State.NeedUpdate;
			}
		}
		else if (this.mState != FOWSystem.State.NeedUpdate)
		{
			if (this.mScreenHeight != Screen.height || this.mTexture0 == null)
			{
				this.RebuildTextures();
			}
			else if (this.mState == FOWSystem.State.UpdateTexture0)
			{
				this.mTexture0.SetPixels32(this.mBuffer0);
				this.mTexture0.Apply();
				this.mState = FOWSystem.State.UpdateTexture1;
				this.mBlendFactor = 0f;
			}
			else if (this.mState == FOWSystem.State.UpdateTexture1)
			{
				this.mTexture1.SetPixels32(this.mBuffer1);
				this.mTexture1.Apply();
				this.mState = FOWSystem.State.Blending;
			}
		}
		float num = 1f / (float)this.worldSize;
		float num2 = this.mTrans.position.x - (float)this.worldSize * 0.5f;
		float num3 = this.mTrans.position.z - (float)this.worldSize * 0.5f;
		Vector4 vector = new Vector4(-num2 * num, -num3 * num, num, this.mBlendFactor);
		this.boundsMin = num3;
		this.boundsMax = num3 + (float)this.worldSize;
		if (this.index == 0)
		{
			Shader.SetGlobalColor("_FOWUnexplored", this.unexploredColor);
			Shader.SetGlobalColor("_FOWExplored", this.exploredColor);
			Shader.SetGlobalVector("_FOWParams", vector);
			Shader.SetGlobalTexture("_FOWTex0", this.mTexture0);
			Shader.SetGlobalTexture("_FOWTex1", this.mTexture1);
			Shader.SetGlobalTexture("_FOWMinimap", this.mTextureMinimap);
		}
	}

	// Token: 0x060000A3 RID: 163 RVA: 0x0000D2CC File Offset: 0x0000B4CC
	public Vector4 GetParams()
	{
		float num = 1f / (float)this.worldSize;
		float num2 = this.mTrans.position.x - (float)this.worldSize * 0.5f;
		float num3 = this.mTrans.position.z - (float)this.worldSize * 0.5f;
		return new Vector4(-num2 * num, -num3 * num, num, this.mBlendFactor);
	}

	// Token: 0x060000A4 RID: 164 RVA: 0x0000D338 File Offset: 0x0000B538
	public void SetGlobalShaderVariables()
	{
		this.isActive = true;
		float num = 1f / (float)this.worldSize;
		this.mTrans = base.transform;
		float num2 = this.mTrans.position.x - (float)this.worldSize * 0.5f;
		float num3 = this.mTrans.position.z - (float)this.worldSize * 0.5f;
		Vector4 vector = new Vector4(-num2 * num, -num3 * num, num, this.mBlendFactor);
		Shader.SetGlobalColor("_FOWUnexplored", this.unexploredColor);
		Shader.SetGlobalColor("_FOWExplored", this.exploredColor);
		Shader.SetGlobalVector("_FOWParams", vector);
		Shader.SetGlobalTexture("_FOWTex0", this.mTexture0);
		Shader.SetGlobalTexture("_FOWTex1", this.mTexture1);
		Shader.SetGlobalTexture("_FOWMinimap", this.mTextureMinimap);
	}

	// Token: 0x060000A5 RID: 165 RVA: 0x0000D418 File Offset: 0x0000B618
	private void RebuildTextures()
	{
		this.mScreenHeight = Screen.height;
		if (this.mTexture0 != null)
		{
			Object.Destroy(this.mTexture0);
		}
		if (this.mTexture1 != null)
		{
			Object.Destroy(this.mTexture1);
		}
		bool flag = QualitySettings.activeColorSpace == ColorSpace.Linear;
		this.mTexture0 = new Texture2D(this.textureSize, this.textureSize, TextureFormat.ARGB32, false, flag);
		this.mTexture1 = new Texture2D(this.textureSize, this.textureSize, TextureFormat.ARGB32, false, flag);
		this.mTextureMinimap = new Texture2D(this.textureSize, this.textureSize, TextureFormat.ARGB32, false, flag);
		this.mTexture0.wrapMode = TextureWrapMode.Clamp;
		this.mTexture1.wrapMode = TextureWrapMode.Clamp;
		this.mTextureMinimap.wrapMode = TextureWrapMode.Clamp;
		this.mTexture0.SetPixels32(this.mBuffer0);
		this.mTexture0.Apply();
		this.mTexture1.SetPixels32(this.mBuffer1);
		this.mTexture1.Apply();
		this.mState = FOWSystem.State.Blending;
		Links.x.sceneMap.UpdateScreenSize();
	}

	// Token: 0x060000A6 RID: 166 RVA: 0x0000D52C File Offset: 0x0000B72C
	private void ThreadUpdate()
	{
		Stopwatch stopwatch = new Stopwatch();
		for (;;)
		{
			if (this.mState == FOWSystem.State.NeedUpdate)
			{
				stopwatch.Reset();
				stopwatch.Start();
				this.UpdateBuffer();
				stopwatch.Stop();
				if (this.debug)
				{
					Debug.Log(stopwatch.ElapsedMilliseconds);
				}
				this.mElapsed = 0.001f * (float)stopwatch.ElapsedMilliseconds;
				this.mState = FOWSystem.State.UpdateTexture0;
			}
			Thread.Sleep(1);
		}
	}

	// Token: 0x060000A7 RID: 167 RVA: 0x0000D59C File Offset: 0x0000B79C
	private void OnDrawGizmosSelected()
	{
		Gizmos.matrix = base.transform.localToWorldMatrix;
		Gizmos.color = Color.yellow;
		Gizmos.DrawWireCube(new Vector3(0f, (this.heightRange.x + this.heightRange.y) * 0.5f, 0f), new Vector3((float)this.worldSize, this.heightRange.y - this.heightRange.x, (float)this.worldSize));
	}

	// Token: 0x060000A8 RID: 168 RVA: 0x0000D620 File Offset: 0x0000B820
	private bool IsVisible(int sx, int sy, int fx, int fy, float outer, int sightHeight, int variance)
	{
		int num = Mathf.Abs(fx - sx);
		int num2 = Mathf.Abs(fy - sy);
		int num3 = ((sx < fx) ? 1 : (-1));
		int num4 = ((sy < fy) ? 1 : (-1));
		int num5 = num - num2;
		float num6 = (float)sightHeight;
		float num7 = (float)this.mHeights[fx, fy];
		float num8 = 1f / outer;
		while (sx != fx || sy != fy)
		{
			int num9 = fx - sx;
			int num10 = fy - sy;
			float num11 = num8 * Mathf.Sqrt((float)(num9 * num9 + num10 * num10));
			if ((float)this.mHeights[sx, sy] > Mathf.Lerp(num7, num6, num11) + (float)variance)
			{
				return false;
			}
			int num12 = num5 << 1;
			if (num12 > -num2)
			{
				num5 -= num2;
				sx += num3;
			}
			if (num12 < num)
			{
				num5 += num;
				sy += num4;
			}
		}
		return true;
	}

	// Token: 0x060000A9 RID: 169 RVA: 0x0000D6EF File Offset: 0x0000B8EF
	public int WorldToGridHeight(float height)
	{
		return Mathf.Clamp(Mathf.RoundToInt(height / this.mSize.y * 255f), 0, 255);
	}

	// Token: 0x060000AA RID: 170 RVA: 0x0000D714 File Offset: 0x0000B914
	public virtual void CreateGrid()
	{
		Vector3 vector = this.mOrigin;
		vector.y += this.mSize.y;
		float num = (float)this.worldSize / (float)this.textureSize;
		bool flag = this.raycastRadius > 0f;
		Diorama component = GameObject.Find("Diorama").GetComponent<Diorama>();
		List<SphereCollider> fogColliders = component.fogColliders;
		List<Bounds> fogColliderBounds = component.fogColliderBounds;
		float num2 = (float)this.textureSize / (float)this.worldSize;
		Vector3 vector2 = this.mOrigin;
		for (int i = 0; i < this.textureSize; i++)
		{
			vector.z = this.mOrigin.z + (float)i * num;
			int j = 0;
			while (j < this.textureSize)
			{
				vector.x = this.mOrigin.x + (float)j * num;
				bool flag2 = false;
				vector2 = this.mOrigin;
				vector2.x += (float)j;
				vector2.z += (float)i;
				vector2 = vector;
				for (int k = 0; k < fogColliders.Count; k++)
				{
					if (!flag2)
					{
						SphereCollider sphereCollider = fogColliders[k];
						Vector3 center = fogColliderBounds[k].center;
						vector2.y = center.y;
						float x = fogColliderBounds[k].extents.x;
						if ((vector2 - center).sqrMagnitude < x * x)
						{
							flag2 = true;
						}
					}
				}
				int num3 = Mathf.RoundToInt(vector.x * num2);
				int num4 = Mathf.RoundToInt(vector.z * num2);
				Mathf.Clamp(num3, 0, this.textureSize - 1);
				num4 = Mathf.Clamp(num4, 0, this.textureSize - 1);
				int num5 = this.textureSize;
				if (flag2)
				{
					this.losAreas[j + i * this.textureSize] = 1;
				}
				else
				{
					this.losAreas[j + i * this.textureSize] = 0;
				}
				if (this.raycastMask == 0)
				{
					goto IL_02D4;
				}
				if (flag)
				{
					RaycastHit raycastHit;
					if (!Physics.SphereCast(new Ray(vector, Vector3.down), this.raycastRadius, out raycastHit, this.mSize.y, this.raycastMask))
					{
						goto IL_02D4;
					}
					bool flag3 = false;
					if (raycastHit.collider.gameObject.layer == 16 && raycastHit.collider.gameObject.GetComponent<Puzzle>())
					{
						flag3 = true;
					}
					if (flag3)
					{
						goto IL_02D4;
					}
					this.mHeights[j, i] = this.WorldToGridHeight(vector.y - raycastHit.distance - this.raycastRadius);
				}
				else
				{
					RaycastHit raycastHit;
					if (!Physics.Raycast(new Ray(vector, Vector3.down), out raycastHit, this.mSize.y, this.raycastMask))
					{
						goto IL_02D4;
					}
					this.mHeights[j, i] = this.WorldToGridHeight(vector.y - raycastHit.distance);
				}
				IL_02E4:
				j++;
				continue;
				IL_02D4:
				this.mHeights[j, i] = 0;
				goto IL_02E4;
			}
		}
	}

	// Token: 0x060000AB RID: 171 RVA: 0x0000DA2C File Offset: 0x0000BC2C
	public void UpdateGrid(Vector3 center, float radius)
	{
		Vector3 vector = this.mOrigin;
		vector.y += this.mSize.y;
		float num = (float)this.worldSize / (float)this.textureSize;
		bool flag = this.raycastRadius > 0f;
		Vector3 vector2 = this.mOrigin;
		for (int i = 0; i < this.textureSize; i++)
		{
			vector.z = this.mOrigin.z + (float)i * num;
			for (int j = 0; j < this.textureSize; j++)
			{
				vector.x = this.mOrigin.x + (float)j * num;
				bool flag2 = false;
				vector2 = this.mOrigin;
				vector2.x += (float)j;
				vector2.z += (float)i;
				vector2 = vector;
				center.y = vector2.y;
				if ((vector2 - center).sqrMagnitude < radius * radius)
				{
					flag2 = true;
				}
				if (this.raycastMask != 0 && flag2)
				{
					RaycastHit raycastHit;
					if (flag)
					{
						if (Physics.SphereCast(new Ray(vector, Vector3.down), this.raycastRadius, out raycastHit, this.mSize.y, this.raycastMask))
						{
							bool flag3 = false;
							if (raycastHit.collider.gameObject.layer == 16 && raycastHit.collider.gameObject.GetComponent<Puzzle>())
							{
								flag3 = true;
							}
							if (!flag3)
							{
								this.mHeights[j, i] = this.WorldToGridHeight(vector.y - raycastHit.distance - this.raycastRadius);
							}
						}
					}
					else if (Physics.Raycast(new Ray(vector, Vector3.down), out raycastHit, this.mSize.y, this.raycastMask))
					{
						this.mHeights[j, i] = this.WorldToGridHeight(vector.y - raycastHit.distance);
					}
				}
			}
		}
	}

	// Token: 0x060000AC RID: 172 RVA: 0x0000DC34 File Offset: 0x0000BE34
	private void UpdateBuffer()
	{
		if (FOWSystem.mAdded.Count > 0)
		{
			List<FOWSystem.Revealer> list = FOWSystem.mAdded;
			lock (list)
			{
				while (FOWSystem.mAdded.Count > 0)
				{
					int num = FOWSystem.mAdded.Count - 1;
					FOWSystem.mRevealers.Add(FOWSystem.mAdded[num]);
					FOWSystem.mAdded.RemoveAt(num);
				}
			}
		}
		if (FOWSystem.mRemoved.Count > 0)
		{
			List<FOWSystem.Revealer> list = FOWSystem.mRemoved;
			lock (list)
			{
				while (FOWSystem.mRemoved.Count > 0)
				{
					int num2 = FOWSystem.mRemoved.Count - 1;
					FOWSystem.mRevealers.Remove(FOWSystem.mRemoved[num2]);
					FOWSystem.mRemoved.RemoveAt(num2);
				}
			}
		}
		float num3 = ((this.textureBlendTime > 0f) ? Mathf.Clamp01(this.mBlendFactor + this.mElapsed / this.textureBlendTime) : 1f);
		int i = 0;
		int num4 = this.mBuffer0.Length;
		while (i < num4)
		{
			this.mBuffer0[i] = Color32.Lerp(this.mBuffer0[i], this.mBuffer1[i], num3);
			this.mBuffer1[i].r = 0;
			i++;
		}
		float num5 = (float)this.textureSize / (float)this.worldSize;
		int j = 0;
		int count = FOWSystem.mRevealers.Count;
		while (j < count)
		{
			FOWSystem.Revealer revealer = FOWSystem.mRevealers[j];
			if (revealer.isActive)
			{
				FOWSystem.Revealer revealer2 = revealer;
				lock (revealer2)
				{
					if (revealer.los == FOWSystem.LOSChecks.None)
					{
						this.RevealUsingRadius(revealer, num5);
					}
					else if (revealer.los == FOWSystem.LOSChecks.OnlyOnce)
					{
						this.RevealUsingCache(revealer, num5);
					}
					else
					{
						this.RevealUsingLOS(revealer, num5);
					}
				}
			}
			j++;
		}
		for (int k = 0; k < this.blurIterations; k++)
		{
			this.BlurVisibility();
		}
		this.RevealVisible();
	}

	// Token: 0x060000AD RID: 173 RVA: 0x0000DE78 File Offset: 0x0000C078
	private void RevealUsingRadius(FOWSystem.Revealer r, float worldToTex)
	{
		Vector3 vector = r.pos - this.mOrigin;
		int num = Mathf.RoundToInt((vector.x - r.outer) * worldToTex);
		int num2 = Mathf.RoundToInt((vector.z - r.outer) * worldToTex);
		int num3 = Mathf.RoundToInt((vector.x + r.outer) * worldToTex);
		int num4 = Mathf.RoundToInt((vector.z + r.outer) * worldToTex);
		int num5 = Mathf.RoundToInt(vector.x * worldToTex);
		int num6 = Mathf.RoundToInt(vector.z * worldToTex);
		num5 = Mathf.Clamp(num5, 0, this.textureSize - 1);
		num6 = Mathf.Clamp(num6, 0, this.textureSize - 1);
		int num7 = Mathf.RoundToInt(r.outer * r.outer * worldToTex * worldToTex);
		int num8 = this.textureSize - 1;
		for (int i = num2; i < num4; i++)
		{
			if (i > 0 && i < num8)
			{
				int num9 = i * this.textureSize;
				for (int j = num; j < num3; j++)
				{
					if (j > 0 && j < num8)
					{
						int num10 = j - num5;
						int num11 = i - num6;
						if (num10 * num10 + num11 * num11 < num7)
						{
							this.mBuffer1[j + num9].r = byte.MaxValue;
						}
					}
				}
			}
		}
	}

	// Token: 0x060000AE RID: 174 RVA: 0x0000DFC0 File Offset: 0x0000C1C0
	private void RevealUsingLOS(FOWSystem.Revealer r, float worldToTex)
	{
		Vector3 vector = r.pos - this.mOrigin;
		int num = Mathf.RoundToInt((vector.x - r.outer) * worldToTex);
		int num2 = Mathf.RoundToInt((vector.z - r.outer) * worldToTex);
		int num3 = Mathf.RoundToInt((vector.x + r.outer) * worldToTex);
		int num4 = Mathf.RoundToInt((vector.z + r.outer) * worldToTex);
		num = Mathf.Clamp(num, 0, this.textureSize - 1);
		num3 = Mathf.Clamp(num3, 0, this.textureSize - 1);
		num2 = Mathf.Clamp(num2, 0, this.textureSize - 1);
		num4 = Mathf.Clamp(num4, 0, this.textureSize - 1);
		int num5 = Mathf.RoundToInt(vector.x * worldToTex);
		int num6 = Mathf.RoundToInt(vector.z * worldToTex);
		num5 = Mathf.Clamp(num5, 0, this.textureSize - 1);
		num6 = Mathf.Clamp(num6, 0, this.textureSize - 1);
		int num7 = Mathf.RoundToInt(r.inner * r.inner * worldToTex * worldToTex);
		int num8 = Mathf.RoundToInt(r.outer * r.outer * worldToTex * worldToTex);
		int num9 = this.WorldToGridHeight(r.pos.y);
		int num10 = Mathf.RoundToInt(Mathf.Clamp01(this.margin / (this.heightRange.y - this.heightRange.x)) * 255f);
		Color32 color = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue);
		new Color32(0, byte.MaxValue, 0, byte.MaxValue);
		int num11 = this.textureSize - 1;
		for (int i = num2; i < num4; i++)
		{
			if (i > 0 && i < num11)
			{
				for (int j = num; j < num3; j++)
				{
					if (j > 0 && j < num11)
					{
						int num12 = j - num5;
						int num13 = i - num6;
						int num14 = num12 * num12 + num13 * num13;
						int num15 = j + i * this.textureSize;
						if (num14 < num7 || (num5 == j && num6 == i))
						{
							this.mBuffer1[num15] = color;
						}
						else if (num14 < num8)
						{
							Vector2 vector2 = new Vector2((float)num12, (float)num13);
							vector2.Normalize();
							vector2 *= r.inner;
							int num16 = num5 + Mathf.RoundToInt(vector2.x);
							int num17 = num6 + Mathf.RoundToInt(vector2.y);
							if (num16 > -1 && num16 < this.textureSize && num17 > -1 && num17 < this.textureSize && this.IsVisible(num16, num17, j, i, Mathf.Sqrt((float)num14), num9, num10))
							{
								if (this.losAreas[num15] == 1)
								{
									this.mBuffer1[num15] = color;
								}
								else
								{
									this.mBuffer1[num15] = color;
								}
							}
						}
					}
				}
			}
		}
	}

	// Token: 0x060000AF RID: 175 RVA: 0x0000E2B0 File Offset: 0x0000C4B0
	private void RevealUsingCache(FOWSystem.Revealer r, float worldToTex)
	{
		if (!r.isValid)
		{
			this.RevealIntoCache(r, worldToTex);
		}
		Color32 color = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue);
		bool[] cachedBuffer = r.cachedBuffer;
		int num = this.textureSize - 1;
		int i = r.cachedY;
		int num2 = r.cachedY + r.cachedSize;
		while (i < num2)
		{
			if (i > 0 && i < num)
			{
				int num3 = i * this.textureSize;
				int num4 = (i - r.cachedY) * r.cachedSize;
				int j = r.cachedX;
				int num5 = r.cachedX + r.cachedSize;
				while (j < num5)
				{
					if (j > 0 && j < num)
					{
						int num6 = j - r.cachedX + num4;
						if (cachedBuffer[num6])
						{
							this.mBuffer1[j + num3] = color;
						}
					}
					j++;
				}
			}
			i++;
		}
	}

	// Token: 0x060000B0 RID: 176 RVA: 0x0000E390 File Offset: 0x0000C590
	private void RevealIntoCache(FOWSystem.Revealer r, float worldToTex)
	{
		Vector3 vector = r.pos - this.mOrigin;
		int num = Mathf.RoundToInt((vector.x - r.outer) * worldToTex);
		int num2 = Mathf.RoundToInt((vector.z - r.outer) * worldToTex);
		int num3 = Mathf.RoundToInt((vector.x + r.outer) * worldToTex);
		int num4 = Mathf.RoundToInt((vector.z + r.outer) * worldToTex);
		int num5 = Mathf.RoundToInt(vector.x * worldToTex);
		int num6 = Mathf.RoundToInt(vector.z * worldToTex);
		num5 = Mathf.Clamp(num5, 0, this.textureSize - 1);
		num6 = Mathf.Clamp(num6, 0, this.textureSize - 1);
		int num7 = Mathf.Max(Mathf.RoundToInt((float)(num3 - num)), Mathf.RoundToInt((float)(num4 - num2)));
		int num8 = num7 * num7;
		if (r.cachedBuffer == null || r.cachedBuffer.Length != num8)
		{
			r.cachedBuffer = new bool[num8];
		}
		int i = 0;
		int num9 = num7 * num7;
		while (i < num9)
		{
			r.cachedBuffer[i] = false;
			i++;
		}
		int num10 = Mathf.RoundToInt(r.inner * r.inner * worldToTex * worldToTex);
		int num11 = Mathf.RoundToInt(r.outer * r.outer * worldToTex * worldToTex);
		int num12 = Mathf.RoundToInt(Mathf.Clamp01(this.margin / (this.heightRange.y - this.heightRange.x)) * 255f);
		int num13 = this.WorldToGridHeight(r.pos.y);
		int num14 = this.textureSize - 1;
		for (int j = num2; j < num4; j++)
		{
			if (j > 0 && j < num14)
			{
				for (int k = num; k < num3; k++)
				{
					if (k > 0 && k < num14)
					{
						int num15 = k - num5;
						int num16 = j - num6;
						int num17 = num15 * num15 + num16 * num16;
						if (num17 < num10 || (num5 == k && num6 == j))
						{
							r.cachedBuffer[k - num + (j - num2) * num7] = true;
						}
						else if (num17 < num11)
						{
							Vector2 vector2 = new Vector2((float)num15, (float)num16);
							vector2.Normalize();
							vector2 *= r.inner;
							int num18 = num5 + Mathf.RoundToInt(vector2.x * worldToTex);
							int num19 = num6 + Mathf.RoundToInt(vector2.y * worldToTex);
							if (num18 > -1 && num18 < this.textureSize && num19 > -1 && num19 < this.textureSize && this.IsVisible(num18, num19, k, j, Mathf.Sqrt((float)num17), num13, num12))
							{
								r.cachedBuffer[k - num + (j - num2) * num7] = true;
							}
						}
					}
				}
			}
		}
		r.cachedSize = num7;
		r.cachedX = num;
		r.cachedY = num2;
		r.isValid = true;
	}

	// Token: 0x060000B1 RID: 177 RVA: 0x0000E674 File Offset: 0x0000C874
	private void BlurVisibility()
	{
		for (int i = 0; i < this.textureSize; i++)
		{
			int num = i * this.textureSize;
			int num2 = i - 1;
			if (num2 < 0)
			{
				num2 = 0;
			}
			int num3 = i + 1;
			if (num3 == this.textureSize)
			{
				num3 = i;
			}
			num2 *= this.textureSize;
			num3 *= this.textureSize;
			for (int j = 0; j < this.textureSize; j++)
			{
				int num4 = j - 1;
				if (num4 < 0)
				{
					num4 = 0;
				}
				int num5 = j + 1;
				if (num5 == this.textureSize)
				{
					num5 = j;
				}
				int num6 = j + num;
				int num7 = (int)this.mBuffer1[num6].r;
				num7 += (int)this.mBuffer1[num4 + num].r;
				num7 += (int)this.mBuffer1[num5 + num].r;
				num7 += (int)this.mBuffer1[j + num2].r;
				num7 += (int)this.mBuffer1[j + num3].r;
				num7 += (int)this.mBuffer1[num4 + num2].r;
				num7 += (int)this.mBuffer1[num5 + num2].r;
				num7 += (int)this.mBuffer1[num4 + num3].r;
				num7 += (int)this.mBuffer1[num5 + num3].r;
				Color32 color = this.mBuffer2[num6];
				color.r = (byte)(num7 / 9);
				this.mBuffer2[num6] = color;
			}
		}
		Color32[] array = this.mBuffer1;
		this.mBuffer1 = this.mBuffer2;
		this.mBuffer2 = array;
	}

	// Token: 0x060000B2 RID: 178 RVA: 0x0000E840 File Offset: 0x0000CA40
	private void RevealVisible()
	{
		default(Color);
		Color32 color = new Color(0f, 0f, 0f, 0f);
		for (int i = 0; i < this.textureSize; i++)
		{
			int num = i * this.textureSize;
			for (int j = 0; j < this.textureSize; j++)
			{
				int num2 = j + num;
				Color32 color2 = this.mBuffer1[num2];
				if (color2.g < color2.r && this.saveFow)
				{
					color2.g = color2.r;
					int g = (int)color2.g;
					if (this.losAreas[num2] == 1)
					{
						color2.a = 1;
					}
					else
					{
						color2.a = 0;
					}
					color.a = (byte)g;
					this.mBuffer1[num2] = color2;
				}
			}
		}
	}

	// Token: 0x060000B3 RID: 179 RVA: 0x0000E934 File Offset: 0x0000CB34
	public void Save()
	{
		FOWSystem.GetRevealedBuffer();
		int num = FOWSystem.instance.textureSize * FOWSystem.instance.textureSize;
		List<float> list = new List<float>();
		for (int i = 0; i < num; i++)
		{
			list.Add((float)FOWSystem.instance.mBuffer0[i].g);
		}
		if (Records.x.inOverworldMap)
		{
			Links.x.gaia.UpdateOverworldFow(list);
			return;
		}
		string text = Records.x.openBook + "/" + Links.x.diorama.sceneName + "_FOW";
		ES3.Save<List<float>>("Fow", list, text);
		ES3.Save<int>("FowSize", FOWSystem.instance.textureSize, text);
	}

	// Token: 0x060000B4 RID: 180 RVA: 0x0000E9F4 File Offset: 0x0000CBF4
	public void Load()
	{
		string text = Records.x.openBook + "/" + Links.x.diorama.sceneName + "_FOW";
		if (ES3.FileExists(text))
		{
			List<float> list = ES3.Load<List<float>>("Fow", text);
			int num = FOWSystem.instance.textureSize * FOWSystem.instance.textureSize;
			if (list.Count != num)
			{
				Debug.LogError("Buffer size mismatch. Fog is " + num.ToString() + ", but passed array is " + list.Count.ToString());
			}
			else
			{
				if (FOWSystem.instance.mBuffer0 == null)
				{
					FOWSystem.instance.mBuffer0 = new Color32[num];
					FOWSystem.instance.mBuffer1 = new Color32[num];
					FOWSystem.instance.mBuffer2 = new Color32[num];
				}
				this.loaded = true;
				Color color = default(Color);
				for (int i = 0; i < num; i++)
				{
					color.r = (float)FOWSystem.instance.mBuffer0[i].r;
					color.g = list[i];
					color.b = (float)FOWSystem.instance.mBuffer0[i].b;
					color.a = (float)FOWSystem.instance.mBuffer0[i].a;
					FOWSystem.instance.mBuffer0[i] = color;
					color.r = (float)FOWSystem.instance.mBuffer1[i].r;
					color.g = list[i];
					color.b = (float)FOWSystem.instance.mBuffer1[i].b;
					color.a = (float)FOWSystem.instance.mBuffer1[i].a;
					FOWSystem.instance.mBuffer1[i] = color;
				}
			}
			this.RebuildTextures();
			for (int j = 0; j < this.textureSize; j++)
			{
				int num2 = j * this.textureSize;
				int num3 = j - 1;
				if (num3 < 0)
				{
					num3 = 0;
				}
				int num4 = j + 1;
				if (num4 == this.textureSize)
				{
					num4 = j;
				}
				num3 *= this.textureSize;
				num4 *= this.textureSize;
				for (int k = 0; k < this.textureSize; k++)
				{
					int num5 = k - 1;
					if (num5 < 0)
					{
						num5 = 0;
					}
					int num6 = k + 1;
					if (num6 == this.textureSize)
					{
						num6 = k;
					}
					int num7 = k + num2;
					int num8 = (int)FOWSystem.instance.mBuffer1[num7].g;
					num8 += (int)FOWSystem.instance.mBuffer1[num5 + num2].g;
					num8 += (int)FOWSystem.instance.mBuffer1[num6 + num2].g;
					num8 += (int)FOWSystem.instance.mBuffer1[k + num3].g;
					num8 += (int)FOWSystem.instance.mBuffer1[k + num4].g;
					num8 += (int)FOWSystem.instance.mBuffer1[num5 + num3].g;
					num8 += (int)FOWSystem.instance.mBuffer1[num6 + num3].g;
					num8 += (int)FOWSystem.instance.mBuffer1[num5 + num4].g;
					num8 += (int)FOWSystem.instance.mBuffer1[num6 + num4].g;
					Color32 color2 = FOWSystem.instance.mBuffer2[num7];
					color2.g = (byte)(num8 / 9);
					FOWSystem.instance.mBuffer2[num7] = color2;
				}
			}
			Color32[] array = FOWSystem.instance.mBuffer1;
			FOWSystem.instance.mBuffer1 = FOWSystem.instance.mBuffer2;
			FOWSystem.instance.mBuffer2 = array;
		}
	}

	// Token: 0x060000B5 RID: 181 RVA: 0x0000EE00 File Offset: 0x0000D000
	public static byte[] GetRevealedBuffer()
	{
		if (FOWSystem.instance == null || FOWSystem.instance.mBuffer1 == null)
		{
			return null;
		}
		int num = FOWSystem.instance.textureSize * FOWSystem.instance.textureSize;
		byte[] array = new byte[num];
		for (int i = 0; i < num; i++)
		{
			array[i] = FOWSystem.instance.mBuffer1[i].g;
		}
		return array;
	}

	// Token: 0x060000B6 RID: 182 RVA: 0x0000EE6C File Offset: 0x0000D06C
	public static void SetRevealedBuffer(byte[] arr)
	{
		if (FOWSystem.instance == null || arr == null)
		{
			return;
		}
		int num = FOWSystem.instance.textureSize * FOWSystem.instance.textureSize;
		if (arr.Length != num)
		{
			Debug.LogError("Buffer size mismatch. Fog is " + num.ToString() + ", but passed array is " + arr.Length.ToString());
			return;
		}
		if (FOWSystem.instance.mBuffer0 == null)
		{
			FOWSystem.instance.mBuffer0 = new Color32[num];
			FOWSystem.instance.mBuffer1 = new Color32[num];
		}
		for (int i = 0; i < num; i++)
		{
			FOWSystem.instance.mBuffer0[i].g = arr[i];
			FOWSystem.instance.mBuffer1[i].g = arr[i];
		}
	}

	// Token: 0x060000B7 RID: 183 RVA: 0x0000EF38 File Offset: 0x0000D138
	public static void RevealAll()
	{
		if (FOWSystem.instance == null)
		{
			return;
		}
		int num = FOWSystem.instance.textureSize * FOWSystem.instance.textureSize;
		if (FOWSystem.instance.mBuffer0 == null)
		{
			FOWSystem.instance.mBuffer0 = new Color32[num];
			FOWSystem.instance.mBuffer1 = new Color32[num];
		}
		for (int i = 0; i < num; i++)
		{
			FOWSystem.instance.mBuffer0[i].g = byte.MaxValue;
			FOWSystem.instance.mBuffer1[i].g = byte.MaxValue;
		}
	}

	// Token: 0x060000B8 RID: 184 RVA: 0x0000EFD8 File Offset: 0x0000D1D8
	public static FOWSystem.Revealer CreateRevealer()
	{
		FOWSystem.Revealer revealer = new FOWSystem.Revealer();
		revealer.isActive = false;
		List<FOWSystem.Revealer> list = FOWSystem.mAdded;
		lock (list)
		{
			FOWSystem.mAdded.Add(revealer);
		}
		return revealer;
	}

	// Token: 0x060000B9 RID: 185 RVA: 0x0000F02C File Offset: 0x0000D22C
	public static void DeleteRevealer(FOWSystem.Revealer rev)
	{
		List<FOWSystem.Revealer> list = FOWSystem.mRemoved;
		lock (list)
		{
			FOWSystem.mRemoved.Add(rev);
		}
	}

	// Token: 0x060000BA RID: 186 RVA: 0x0000F070 File Offset: 0x0000D270
	public bool IsVisible(Vector3 pos)
	{
		FOWSystem fowsystem = FOWSystem.instance;
		if (fowsystem == null)
		{
			return true;
		}
		if (fowsystem.mBuffer0 == null)
		{
			return false;
		}
		pos -= fowsystem.mOrigin;
		float num = (float)fowsystem.textureSize / (float)fowsystem.worldSize;
		int num2 = Mathf.RoundToInt(pos.x * num);
		int num3 = Mathf.RoundToInt(pos.z * num);
		int num4 = Mathf.Clamp(num2, 0, fowsystem.textureSize - 1);
		num3 = Mathf.Clamp(num3, 0, fowsystem.textureSize - 1);
		int num5 = num4 + num3 * fowsystem.textureSize;
		return fowsystem.mBuffer1[num5].r > 0 || fowsystem.mBuffer0[num5].r > 0;
	}

	// Token: 0x060000BB RID: 187 RVA: 0x0000F124 File Offset: 0x0000D324
	public bool IsVisibleWorm(Vector3 pos)
	{
		FOWSystem fowsystem = FOWSystem.instance;
		if (fowsystem == null)
		{
			return true;
		}
		if (fowsystem.mBuffer0 == null)
		{
			return false;
		}
		pos -= fowsystem.mOrigin;
		float num = (float)fowsystem.textureSize / (float)fowsystem.worldSize;
		int num2 = Mathf.RoundToInt(pos.x * num);
		int num3 = Mathf.RoundToInt(pos.z * num);
		int num4 = Mathf.Clamp(num2, 0, fowsystem.textureSize - 1);
		num3 = Mathf.Clamp(num3, 0, fowsystem.textureSize - 1);
		int num5 = num4 + num3 * fowsystem.textureSize;
		return fowsystem.mBuffer1[num5].g > 0 || fowsystem.mBuffer0[num5].g > 0;
	}

	// Token: 0x060000BC RID: 188 RVA: 0x0000F1D8 File Offset: 0x0000D3D8
	public static bool IsExplored(Vector3 pos)
	{
		FOWSystem fowsystem = FOWSystem.instance;
		if (fowsystem == null)
		{
			return true;
		}
		if (fowsystem.mBuffer0 == null)
		{
			return false;
		}
		pos -= fowsystem.mOrigin;
		float num = (float)fowsystem.textureSize / (float)fowsystem.worldSize;
		int num2 = Mathf.RoundToInt(pos.x * num);
		int num3 = Mathf.RoundToInt(pos.z * num);
		num2 = Mathf.Clamp(num2, 0, fowsystem.textureSize - 1);
		num3 = Mathf.Clamp(num3, 0, fowsystem.textureSize - 1);
		return fowsystem.mBuffer0[num2 + num3 * fowsystem.textureSize].g > 0;
	}

	// Token: 0x040001FD RID: 509
	[Header("Joseph")]
	public int worldSize = 256;

	// Token: 0x040001FE RID: 510
	public int index;

	// Token: 0x040001FF RID: 511
	public bool isActive;

	// Token: 0x04000200 RID: 512
	public static FOWSystem.OnSaveOrLoad onSave;

	// Token: 0x04000201 RID: 513
	public static FOWSystem.OnSaveOrLoad onLoad;

	// Token: 0x04000202 RID: 514
	public static FOWSystem instance;

	// Token: 0x04000203 RID: 515
	public static bool readyToCreate = true;

	// Token: 0x04000204 RID: 516
	private static List<FOWSystem.Revealer> mRevealers = new List<FOWSystem.Revealer>();

	// Token: 0x04000205 RID: 517
	private static List<FOWSystem.Revealer> mAdded = new List<FOWSystem.Revealer>();

	// Token: 0x04000206 RID: 518
	private static List<FOWSystem.Revealer> mRemoved = new List<FOWSystem.Revealer>();

	// Token: 0x04000207 RID: 519
	protected int[,] mHeights;

	// Token: 0x04000208 RID: 520
	protected Transform mTrans;

	// Token: 0x04000209 RID: 521
	protected Vector3 mOrigin = Vector3.zero;

	// Token: 0x0400020A RID: 522
	protected Vector3 mSize = Vector3.one;

	// Token: 0x0400020B RID: 523
	protected Color32[] mBuffer0;

	// Token: 0x0400020C RID: 524
	protected Color32[] mBuffer1;

	// Token: 0x0400020D RID: 525
	protected Color32[] mBuffer2;

	// Token: 0x0400020E RID: 526
	protected int[] losAreas;

	// Token: 0x0400020F RID: 527
	public Texture2D mTexture0;

	// Token: 0x04000210 RID: 528
	public Texture2D mTexture1;

	// Token: 0x04000211 RID: 529
	public Texture2D mTextureMinimap;

	// Token: 0x04000212 RID: 530
	protected float mBlendFactor;

	// Token: 0x04000213 RID: 531
	protected float mNextUpdate;

	// Token: 0x04000214 RID: 532
	protected int mScreenHeight;

	// Token: 0x04000215 RID: 533
	protected FOWSystem.State mState;

	// Token: 0x04000216 RID: 534
	private Thread mThread;

	// Token: 0x04000217 RID: 535
	private float mElapsed;

	// Token: 0x04000218 RID: 536
	[Header("Hannah")]
	public Color unexploredColor = new Color(0f, 0f, 0f, 1f);

	// Token: 0x04000219 RID: 537
	public Color exploredColor = new Color(0.28627f, 0.28627f, 0.28627f, 1f);

	// Token: 0x0400021A RID: 538
	public int textureSize = 128;

	// Token: 0x0400021B RID: 539
	private float updateFrequency = 0.01f;

	// Token: 0x0400021C RID: 540
	public float textureBlendTime = 0.5f;

	// Token: 0x0400021D RID: 541
	public int blurIterations = 2;

	// Token: 0x0400021E RID: 542
	public Vector2 heightRange = new Vector2(0f, 10f);

	// Token: 0x0400021F RID: 543
	private LayerMask raycastMask = 537068033;

	// Token: 0x04000220 RID: 544
	public float raycastRadius = 0.1f;

	// Token: 0x04000221 RID: 545
	public float margin = 0.4f;

	// Token: 0x04000222 RID: 546
	private bool debug;

	// Token: 0x04000223 RID: 547
	private bool loaded;

	// Token: 0x04000224 RID: 548
	public float boundsMin;

	// Token: 0x04000225 RID: 549
	public float boundsMax;

	// Token: 0x04000226 RID: 550
	public bool saveFow = true;

	// Token: 0x02000120 RID: 288
	public enum LOSChecks
	{
		// Token: 0x04002713 RID: 10003
		None,
		// Token: 0x04002714 RID: 10004
		OnlyOnce,
		// Token: 0x04002715 RID: 10005
		EveryUpdate
	}

	// Token: 0x02000121 RID: 289
	public class Revealer
	{
		// Token: 0x04002716 RID: 10006
		public bool isValid;

		// Token: 0x04002717 RID: 10007
		public bool isActive;

		// Token: 0x04002718 RID: 10008
		public FOWSystem.LOSChecks los;

		// Token: 0x04002719 RID: 10009
		public Vector3 pos = Vector3.zero;

		// Token: 0x0400271A RID: 10010
		public float inner;

		// Token: 0x0400271B RID: 10011
		public float outer;

		// Token: 0x0400271C RID: 10012
		public bool[] cachedBuffer;

		// Token: 0x0400271D RID: 10013
		public int cachedSize;

		// Token: 0x0400271E RID: 10014
		public int cachedX;

		// Token: 0x0400271F RID: 10015
		public int cachedY;
	}

	// Token: 0x02000122 RID: 290
	public enum State
	{
		// Token: 0x04002721 RID: 10017
		Blending,
		// Token: 0x04002722 RID: 10018
		NeedUpdate,
		// Token: 0x04002723 RID: 10019
		UpdateTexture0,
		// Token: 0x04002724 RID: 10020
		UpdateTexture1
	}

	// Token: 0x02000123 RID: 291
	// (Invoke) Token: 0x060016EB RID: 5867
	public delegate void OnSaveOrLoad();
}
