// Handles Fog of War.
// Worthless Bums 2012.


function fogOfWarClass::getTileCountX (%this)
{
	return 33;
}
function fogOfWarClass::getTileCountY (%this)
{
	return 33;
}
function fogOfWarClass::destroy (%this)
{
	for (%i = 0; %i < %this.getTileCountX(); %i++)
	{
		for (%j = 0; %j < %this.getTileCountY(); %j++)
		{
			if (isObject(%this.tiles[%i, %j]))
			{
				%this.tiles[%i, %j].safeDelete();
			}
		}
	}
}
function fogOfWarClass::setStaticTile (%this, %x, %y, %image, %param)	// Wtf did the last param use to do in old T2D tile layers?
{//echo("fogOfWarClass::setStaticTile()" SPC "sprite =" SPC %image SPC %x SPC %y);
    %this.tiles[%x, %y].Image = %image;
	%this.tiles[%x, %y].Size = "4 4";
	%this.tiles[%x, %y].SceneLayer = $FogOfWarLayer;
	//%this.tiles[%x, %y].visible = true;
	//addObjectToScene(%this.tiles[%x, %y]);
}
function fogOfWarClass::getTileType (%this, %x, %y, %param)				// Wtf did the last param use to do in old T2D tile layers?
{//echo("fogOfWarClass::getTileType()");
	// HACK
    return "dummyWord" SPC %this.tiles[%x, %y].Image;
	// END HACK
}
function fogOfWarClass::onLevelLoaded (%this, %scenegraph)
{//echo("fogOfWarClass::onLevelLoaded()");
return;	// Fog of war disabled for now! There is no such thing is tile layers/maps in T2D v3.0! E.g. fogOfWarClass and $fogOfWar do not properly exist!
	// Set $fogOfWar.
	$fogOfWar = %this;
	
	// Set fog of war position and size.
	$fogOfWar.position = "66.0 66.0";	// Values taken from the T2D v1.7.5 version!
	$fogOfWar.size = "132.0 132.0";		// Values taken from the T2D v1.7.5 version!
	
	// Shift position (Damn you, Detocroix!)
	%fowPositionX = getWord($fogOfWar.position, 0);
	%fowPositionY = getWord($fogOfWar.position, 1);
	%fowPositionY += $GlobalVerticalShift;
	$fogOfWar.position = %fowPositionX SPC %fowPositionY;
	
	// Set all tiles solid black.
	%this.init();
	
	// Show fog of war.
	$fogOfWar.showFogOfWar();
}
function fogOfWarClass::isClear (%this, %xIndex, %yIndex)
{//echo("fogOfWarClass::isClear()");
	return (getWord(%this.getTileType(%xIndex, %yIndex), 1) $= "Sprites:blank_1x1");
}
function fogOfWarClass::clear (%this)
{//echo("fogOfWarClass::clear()");
//echo("Fog of war tile layer clear.");
	for (%x = 0; %x < %this.getTileCountX(); %x++)
	{
		for (%y = 0; %y < %this.getTileCountY(); %y++)
		{
			%this.setStaticTile(%x, %y, "Sprites:blank_1x1", 0);
		}
	}
}
function fogOfWarClass::zoozleClear (%this)
{//echo("fogOfWarClass::zoozleClear()");
	for (%x = 0; %x < %this.getTileCountX(); %x++)
	{
		for (%y = 0; %y < %this.getTileCountY(); %y++)
		{
			if ($mazeRoom[%x, %y] == -12)
			{
				%this.setStaticTile(%x, %y, "Sprites:blackFog", 0);
			}
			else
			{
				%this.setStaticTile(%x, %y, "Sprites:blackFog70", 0);
			}
		}
	}
	%this.showFogOfWar();
}
function fogOfWarClass::findPathPDA (%this)
{//echo("fogOfWarClass::findPathPDA()");
	for (%x = 0; %x < %this.getTileCountX(); %x++)
	{
		for (%y = 0; %y < %this.getTileCountY(); %y++)
		{
			if (getWord(%this.getTileType(%x, %y), 1) $= "Sprites:blank_1x1")
			{
				%this.setStaticTile(%x, %y, "Sprites:blackFog70", 0);
			}
		}
	}
	%this.showFogOfWar();
}
function fogOfWarClass::init (%this)
{//echo("fogOfWarClass::init()");
	for (%x = 0; %x < %this.getTileCountX(); %x++)
	{
		for (%y = 0; %y < %this.getTileCountY(); %y++)
		{
			%this.tiles[%x, %y] = new Sprite();
			%this.setStaticTile(%x, %y, "Sprites:BlackFog", 0);
			%position = getTilePositionFromIndices(%x, %y);
			%this.tiles[%x, %y].Position = getWord(%position, 0) SPC getWord(%position, 1) + $GlobalVerticalShift;
			addObjectToScene(%this.tiles[%x, %y]);
		}
	}
}
function fogOfWarClass::updateMonsterVisibility (%this)
{//echo("fogOfWarClass::updateMonsterVisibility()");
	for (%i = 0; %i < $monsterList.getCount(); %i++)
	{
		$fogOfWar.updateTargetMonsterVisibility($monsterList.getObject(%i));
	}
}
function fogOfWarClass::updateTargetMonsterVisibility (%this, %monster)
{//echo("fogOfWarClass::updateTargetMonsterVisibility()");
	if (isSquadMember(%monster))	// Squad members should always be visible to the player!
	{
		return;
	}
	if (getWord(%this.getTileType(%monster.xIndex, %monster.yIndex), 1) $= "Sprites:blank_1x1")
	{
		%monster.setVisible(true);
		(%monster.floatingHPtext).visible = true;
		(%monster.floatingAPtext).visible = true;
	}
	else
	{//echo("1) Setting " @ %monster.name @ " invisible!");
		%monster.setVisible(false);
		(%monster.floatingHPtext).visible = false;
		(%monster.floatingAPtext).visible = false;
	}
}
function fogOfWarClass::showAndTellMonsters (%this)
{//echo("fogOfWarClass::showAndTellMonsters()");
	enforceSquadPersistence();
	for (%i = 0; %i < $monsterList.getCount(); %i++)
	{
		%monster = $monsterList.getObject(%i);
		//if (getWord(%this.getTileType(%monster.xIndex, %monster.yIndex), 1) $= "Sprites:blank_1x1")
		if (%this.isClear(%monster.xIndex, %monster.yIndex))
		{//echo("showing monster on tile" SPC %monster.xIndex @ ", " @ %monster.yIndex);
			%monster.setVisible(true);
			if (!%monster.hasBeenSpotted)
			{
				%monster.hasBeenSpotted = true;
				giveSpottingXP();
				playRobotShriekSfx();	// Need an alien variant of this sfx!
				schedule(250, 0, "enemySpottedChatter", $activeCharacter, %monster.isHuman, %monster.isRobot, %monster.isAlien);
			}
			%monster.isActive = true;
		}
		else
		{
			if (%monster.getVisible())
			{//echo("2) Setting " @ %monster.name @ " invisible on tile" SPC %monster.xIndex @ ", " @ %monster.yIndex);
				%monster.setVisible(false);
				%monster.SceneLayer = $monsterLayer;
				%monster.graph = $monsterGraph;
			}
			else
			{
				if (getRandom(1, 100) < $monsterBreakPursuitChance)
				{
					// Only go inactive if no squad member is near!
					if ((($leaderPersist	&&	VectorDist($playerSquad[0].getPosition(), %monster.getPosition()) >= 30.0)	|| !$leaderPersist)		&&
						(($scoutPersist		&&	VectorDist($playerSquad[1].getPosition(), %monster.getPosition()) >= 30.0)	|| !$scoutPersist)		&&
						(($grenadierPersist	&&	VectorDist($playerSquad[2].getPosition(), %monster.getPosition()) >= 30.0)	|| !$grenadierPersist)	&&
						(($supportPersist	&&	VectorDist($playerSquad[3].getPosition(), %monster.getPosition()) >= 30.0)	|| !$supportPersist))
					{
						%monster.isActive = false;
					}
				}
			}
		}
	}
}
function fogOfWarClass::fullCoverFog (%this)
{//echo("fogOfWarClass::fullCoverFog()");
	for (%x = 0; %x < %this.getTileCountX(); %x++)
	{
		for (%y = 0; %y < %this.getTileCountY(); %y++)
		{
			%tileImage = getWord(%this.getTileType(%x + %xIndex + 1, %y + %yIndex + 1), 1);
			if (%tileImage $= "Sprites:blank_1x1")
			{
				%this.setStaticTile(%x + %xIndex + 1, %y + %yIndex + 1, "Sprites:blackFog", 0);
			}
		}
	}
}
function fogOfWarClass::tileHasFog (%this, %xIndex, %yIndex)
{//echo("fogOfWarClass::tileHasFog()");
	return (getWord(%this.getTileType(%xIndex, %yIndex), 1) $= "Sprites:blank_1x1");
}
function fogOfWarClass::tileHasFullFog (%this, %xIndex, %yIndex)
{//echo("fogOfWarClass::tileHasFullFog()");
	return (getWord(%this.getTileType(%xIndex, %yIndex), 1) $= "Sprites:blackFog");
}
function fogOfWarClass::uncoverFogTile (%this, %xIndex, %yIndex)
{//echo("fogOfWarClass::uncoverFogTile()");
	%tileImage = getWord(%this.getTileType(%xIndex, %yIndex), 1);
	if (%tileImage !$= "Sprites:blank_1x1"	&&
		%tileImage !$= "Sprites:blackFog20"	&&
		%tileImage !$= "Sprites:blackFog40"	&&
		%tileImage !$= "Sprites:blackFog60"	&&
		%tileImage !$= "Sprites:blackFog80")
	{
		%this.fadeOutFogTile(%xIndex, %yIndex);
	}
}
function fogOfWarClass::fadeOutFogTile (%this, %xIndex, %yIndex)
{//echo("fogOfWarClass::fadeOutFogTile()");
	if ($FadingFogOfWarToggle)
	{
		%this.setStaticTile(%xIndex, %yIndex, "Sprites:blackFog80", 0);
		%this.schedule( 60, "setStaticTile", %xIndex, %yIndex, "Sprites:blackFog60", 0);
		%this.schedule(120, "setStaticTile", %xIndex, %yIndex, "Sprites:blackFog40", 0);
		%this.schedule(180, "setStaticTile", %xIndex, %yIndex, "Sprites:blackFog20", 0);
		%this.schedule(240, "setStaticTile", %xIndex, %yIndex, "Sprites:blank_1x1",  0);
	}
	else
	{
		%this.setStaticTile(%xIndex, %yIndex, "Sprites:blank_1x1", 0);
	}
	// Determine whether to show fleeing critters or not.
	if (!isObject($mazeRoom[%xIndex, %yIndex]))
	{
		%fleeingCritters = getRandom(1, 100);
		if (%fleeingCritters <= 10)
		{
			schedule(500, 0, "createFleeingCrittersAnimation", %xIndex, %yIndex);
		}
	}
}
function fogOfWarClass::fadeInFogTile (%this, %xIndex, %yIndex)
{//echo("fogOfWarClass::fadeInFogTile()");
	if ($FadingFogOfWarToggle)
	{
		%this.setStaticTile(%xIndex, %yIndex, "Sprites:blackFog20", 0);
		%this.schedule( 60, "setStaticTile", %xIndex, %yIndex, "Sprites:blackFog40", 0);
		%this.schedule(120, "setStaticTile", %xIndex, %yIndex, "Sprites:blackFog60", 0);
		%this.schedule(180, "setStaticTile", %xIndex, %yIndex, "Sprites:blackFog70", 0);
	}
	else
	{
		%this.setStaticTile(%xIndex, %yIndex, "Sprites:blackFog70", 0);
	}
}
function fogOfWarClass::hideFogTile (%this, %xIndex, %yIndex)
{//echo("fogOfWarClass::hideFogTile()");
	// Fog fade timing.
	%baseTime = $baseFogTime;//60;
	%timeIncrement = $fogIncrementTime;//60;
	// Schedule the static tile changes.
	if ($FadingFogOfWarToggle)
	{
		%this.setStaticTile(%xIndex, %yIndex, "Sprites:blackFog80", 0);
		%this.schedule(%baseTime, "setStaticTile", %xIndex, %yIndex, "Sprites:blackFog60", 0);
		%this.schedule(%baseTime + %timeIncrement, "setStaticTile", %xIndex, %yIndex, "Sprites:blackFog40", 0);
		%this.schedule(%baseTime + %timeIncrement * 2, "setStaticTile", %xIndex, %yIndex, "Sprites:blackFog20", 0);
		%this.schedule(%baseTime + %timeIncrement * 3, "setStaticTile", %xIndex, %yIndex, "Sprites:blank_1x1",  0);
	}
	else
	{
		%this.setStaticTile(%xIndex, %yIndex, "Sprites:blank_1x1", 0);
	}
}
function fogOfWarClass::showFogTile (%this, %xIndex, %yIndex)
{//echo("fogOfWarClass::showFogTile()");
	// Fog fade timing.
	%baseTime = $baseFogTime;
	%timeIncrement = $fogIncrementTime;
	if ($FadingFogOfWarToggle)
	{
		%this.setStaticTile(%xIndex, %yIndex, "Sprites:blackFog20", 0);
		%this.schedule(%baseTime, "setStaticTile", %xIndex, %yIndex, "Sprites:blackFog40", 0);
		%this.schedule(%baseTime + %timeIncrement, "setStaticTile", %xIndex, %yIndex, "Sprites:blackFog60", 0);
		%this.schedule(%baseTime + %timeIncrement * 2, "setStaticTile", %xIndex, %yIndex, "Sprites:blackFog70", 0);
	}
	else
	{
		%this.setStaticTile(%xIndex, %yIndex, "Sprites:blackFog70", 0);
	}
}
// NOTE: This gets called every squad movement! Must be fast!
function fogOfWarClass::initFogOfWar (%this)
{//echo("fogOfWarClass::initFogOfWar()");
	// Initialize fog of war dummy tileset.
	%mazeSizeX = 32;//36;		// Extended to cover East and South edges of the map!
	%mazeSizeY = 32;//36;		// Extended to cover East and South edges of the map!
	for (%i = 0; %i < %mazeSizeX; %i++)
	{
		for (%j = 0; %j < %mazeSizeY; %j++)
		{
			$dummyFogOfWar[%i, %j] = 1;
		}
	}
	// Enforce squad position!
	//enforceSquadPosition();		// Why is this here?!?
	// Flag fog of war tiles.
	if ($leaderPersist)
	{
		%this.flagSightRadius(0);
	}
	if ($scoutPersist)
	{
		%this.flagSightRadius(1);
	}
	if ($grenadierPersist)
	{
		%this.flagSightRadius(2);
	}
	if ($supportPersist)
	{
		%this.flagSightRadius(3);
	}
	%this.continueInitFogOfWar();
}
function getSquadBoundaries ()
{//echo("getSquadBoundaries()");
	// Only check near squad!
	// Find min and max x and y coordinate of all squad members.
	%minX = 63;
	%minY = 63;
	%maxX = 0;
	%maxY = 0;
	// Leader.
	if ($leaderPersist)
	{
		if ($playerSquad[0].xIndex < %minX)
		{
			%minX = $playerSquad[0].xIndex;
		}
		if ($playerSquad[0].xIndex > %maxX)
		{
			%maxX = $playerSquad[0].xIndex;
		}
		if ($playerSquad[0].yIndex < %minY)
		{
			%minY = $playerSquad[0].yIndex;
		}
		if ($playerSquad[0].yIndex > %maxY)
		{
			%maxY = $playerSquad[0].yIndex;
		}
	}
	// Scout.
	if ($scoutPersist)
	{
		if ($playerSquad[1].xIndex < %minX)
		{
			%minX = $playerSquad[1].xIndex;
		}
		if ($playerSquad[1].xIndex > %maxX)
		{
			%maxX = $playerSquad[1].xIndex;
		}
		if ($playerSquad[1].yIndex < %minY)
		{
			%minY = $playerSquad[1].yIndex;
		}
		if ($playerSquad[1].yIndex > %maxY)
		{
			%maxY = $playerSquad[1].yIndex;
		}
	}
	// Grenadier.
	if ($grenadierPersist)
	{
		if ($playerSquad[2].xIndex < %minX)
		{
			%minX = $playerSquad[2].xIndex;
		}
		if ($playerSquad[2].xIndex > %maxX)
		{
			%maxX = $playerSquad[2].xIndex;
		}
		if ($playerSquad[2].yIndex < %minY)
		{
			%minY = $playerSquad[2].yIndex;
		}
		if ($playerSquad[2].yIndex > %maxY)
		{
			%maxY = $playerSquad[2].yIndex;
		}
	}
	// Support.
	if ($supportPersist)
	{
		if ($playerSquad[3].xIndex < %minX)
		{
			%minX = $playerSquad[3].xIndex;
		}
		if ($playerSquad[3].xIndex > %maxX)
		{
			%maxX = $playerSquad[3].xIndex;
		}
		if ($playerSquad[3].yIndex < %minY)
		{
			%minY = $playerSquad[3].yIndex;
		}
		if ($playerSquad[3].yIndex > %maxY)
		{
			%maxY = $playerSquad[3].yIndex;
		}
	}
	return %minX SPC %maxX SPC %minY SPC %maxY;
}
// NOTE: Can optimize further! Look around each squad member individually instead of drawing a rectangle around all of them!
function fogOfWarClass::continueInitFogOfWar (%this)
{//echo("fogOfWarClass::continueInitFogOfWar()");
	// Get squad boundaries.
	%boundaries = getSquadBoundaries();
	%minX = getWord(%boundaries, 0);
	%maxX = getWord(%boundaries, 1);
	%minY = getWord(%boundaries, 2);
	%maxY = getWord(%boundaries, 3);
	// Round all values to an integer value just in case!
	%minX = mFloor(%minX);
	%maxX = mFloor(%maxX);
	%minY = mFloor(%minY);
	%maxY = mFloor(%maxY);
	// Sight radius around min and max points!
	%sightRadius = $squadSightRadius + 2;		// Capped at 4 + 2 = 6 for now!
	// Loop through and show/hide fog of war tiles.
	for (%i = %minX - %sightRadius; %i < %maxX + %sightRadius; %i++)
	{
		// Make sure we don't go out of bounds!
		if (%i >= 0	&&
			%i < 64)
		{
			for (%j = %minY - %sightRadius; %j < %maxY + %sightRadius; %j++)
			{
				// Make sure we don't go out of bounds!
				if (%j >= 0	&&
					%j < 64)
				{
					// Grab the fog of war tile image.
					%tileImage = getWord(%this.getTileType(%i, %j), 1);
					%substring = getSubStr(%tileImage, 0, 13);	// "Sprites:black" is 13 characters long.
					// Check current fog of war status.
					if (%substring $= "Sprites:blank")
					{
						// This fog of war tile is currently uncovered!
						if ($dummyFogOfWar[%i, %j] == 1)
						{
							// The dummy fog of war is covered!
							// NOTE: Schedule or execute immediately? Do it immediately for now...
							%this.showFogTile(%i, %j);
						}
					}
					else if (%substring $= "Sprites:black")
					{
						// This fog of war tile is currently covered!
						if ($dummyFogOfWar[%i, %j] == 0)
						{
							// The dummy fog of war is uncovered!
							// NOTE: Schedule or execute immediately? Do it immediately for now...
							%this.hideFogTile(%i, %j);
							
							// Determine if this is the stairs.
							if ($stairsXIndex == %i	&&
								$stairsYIndex == %j)
							{
								// Uncovered stairs! Inform the player.
								squadFoundStairs();
							}
						}
					}
				}
			}
		}
	}
}
// Perform fog of war post processing effects.
function fogOfWarClass::postFogOfWarProcessing (%this)
{//echo("fogOfWarClass::postFogOfWarProcessing()");
	// Get squad boundaries.
	%boundaries = getSquadBoundaries();
	%minX = getWord(%boundaries, 0);
	%maxX = getWord(%boundaries, 1);
	%minY = getWord(%boundaries, 2);
	%maxY = getWord(%boundaries, 3);
	// Account for squad sight radius.
	%minX -= $squadSightRadius + 2;
	%maxX += $squadSightRadius + 2;
	%minY -= $squadSightRadius + 2;
	%maxY += $squadSightRadius + 2;
	// Iterate over bounded section of fog of war tile map.
	for (%i = %minX; %i < %maxX; %i++)
	{
		for (%j = %minY; %j < %maxY; %j++)
		{
			// Temporary variables for cardinal directions.
			%northTile = 1;
			%southTile = 1;
			%eastTile = 1;
			%westTile = 1;
			%nwTile = 1;
			%neTile = 1;
			%swTile = 1;
			%seTile = 1;
			
			// Check this tile.
			%tileImage = getWord(%this.getTileType(%i, %j), 1);
			%substring = getSubStr(%tileImage, 0, 13);
			// This tile is black.
			if (%substring $= "Sprites:black")
			{
				// Check north tile.
				%tileImage = getWord(%this.getTileType(%i, %j - 1), 1);
				%substring = getSubStr(%tileImage, 0, 13);
				// This tile is blank.
				if (%substring $= "Sprites:blank")
				{
					%northTile = 0;
				}
				// Check south tile.
				%tileImage = getWord(%this.getTileType(%i, %j + 1), 1);
				%substring = getSubStr(%tileImage, 0, 13);
				// This tile is blank.
				if (%substring $= "Sprites:blank")
				{
					%southTile = 0;
				}
				// Check east tile.
				%tileImage = getWord(%this.getTileType(%i + 1, %j), 1);
				%substring = getSubStr(%tileImage, 0, 13);
				// This tile is blank.
				if (%substring $= "Sprites:blank")
				{
					%eastTile = 0;
				}
				// Check east tile.
				%tileImage = getWord(%this.getTileType(%i - 1, %j), 1);
				%substring = getSubStr(%tileImage, 0, 13);
				// This tile is blank.
				if (%substring $= "Sprites:blank")
				{
					%westTile = 0;
				}
				// Check north-west tile.
				%tileImage = getWord(%this.getTileType(%i - 1, %j - 1), 1);
				%substring = getSubStr(%tileImage, 0, 13);
				// This tile is blank.
				if (%substring $= "Sprites:blank")
				{
					%nwTile = 0;
				}
				// Check north-east tile.
				%tileImage = getWord(%this.getTileType(%i + 1, %j - 1), 1);
				%substring = getSubStr(%tileImage, 0, 13);
				// This tile is blank.
				if (%substring $= "Sprites:blank")
				{
					%neTile = 0;
				}
				// Check south-west tile.
				%tileImage = getWord(%this.getTileType(%i - 1, %j + 1), 1);
				%substring = getSubStr(%tileImage, 0, 13);
				// This tile is blank.
				if (%substring $= "Sprites:blank")
				{
					%swTile = 0;
				}
				// Check south-east tile.
				%tileImage = getWord(%this.getTileType(%i + 1, %j + 1), 1);
				%substring = getSubStr(%tileImage, 0, 13);
				// This tile is blank.
				if (%substring $= "Sprites:blank")
				{
					%seTile = 0;
				}
				if (!%northTile	||
					!%southTile	||
					!%eastTile	||
					!%westTile	||
					!%nwTile	||
					!%neTile	||
					!%swTile	||
					!%seTile)
				{
					%this.setStaticTile(%i, %j, "Sprites:blackFog60", 0);
				}
			}
		}
	}
}
// Flags fog of war tiles as show or not show.
function fogOfWarClass::flagSightRadius (%this, %characterIndex)
{//echo("fogOfWarClass::flagSightRadius()");
	// Make sure this character exists before continuing.
	if (isObject($playerSquad[%characterIndex]))
	{
		// Check tiles near the squad members.
		%radius = $playerSquad[%characterIndex].sight;
		// Hard cap of (max) 6 sight range!
		if (%radius > 6)
		{
			%radius = 6;
		}
		// Hard cap of (min) 1 sight range!
		else if (%radius < 1)
		{
			%radius = 1;
		}
		// Check for weapon attachment.
		if ((($playerSquad[%characterIndex]).laserSprite).image !$= "Sprites:Flashlight")
		{
			%radius--;
		}
		// Increase radius if unit is on a lifted tile.
		if (isObject($mazeLiftedTiles[$playerSquad[%characterIndex].xIndex, $playerSquad[%characterIndex].yIndex]))
		{
			%radius++;
		}
		// Calculate max distance.
		%maxDistance = (%radius + 1) * 4.0;			// It doesn't need to be exact since it's just an upper bound for %radius distance! Should be 4.0? 5.0 is a 25% buffer...
		// Get squad member position.
		%xIndex = $playerSquad[%characterIndex].xIndex;
		%yIndex = $playerSquad[%characterIndex].yIndex;
		// Get the tile BEHIND the character.
		// NOTE: Ignore out-of-bounds checking here - not necessary since it's checked below EXCEPT for the last case of the tile position the character is standing on.
		switch ($playerSquad[%characterIndex].facing)
		{
			case $northDirection: 	%yIndex++;
			case $southDirection: 	%yIndex--;
			case $eastDirection: 	%xIndex--;
			case $westDirection: 	%xIndex++;
		}
		// Can be used to skew squad members' fields of view in different directions.
		%xOffset = 0;
		%yOffset = 0;
		// Switch by unit facing.
		switch ($playerSquad[%characterIndex].facing)
		{
			case $northDirection:
				for (%y = -1 * %radius; %y <= 0; %y++)
				{
					if (%y + %yIndex + %yOffset >= 0	&&
						%y + %yIndex + %yOffset < $mazeDimension)
					{
						for (%x = %radius; %x >= -1 * %radius; %x--)
						{
							if (%x + %xIndex + %xOffset >= 0	&&
								%x + %xIndex + %xOffset < $mazeDimension)
							{
								if (%x != 0	||
									%y != 0)
								{
									%distance = VectorDist(getTilePositionFromIndices(%x + %xIndex + %xOffset, %y + %yIndex + %yOffset), $playerSquad[%characterIndex].getPosition());
									%distance = mAbs(%distance);
									if (%distance < %maxDistance)
									{
										%los = bresenhamLineAlgorithm($playerSquad[%characterIndex].xIndex, $playerSquad[%characterIndex].yIndex, %x + %xIndex + %xOffset, %y + %yIndex + %yOffset);
										if (%los)
										{
											$dummyFogOfWar[%x + %xIndex + %xOffset, %y + %yIndex + %yOffset] = 0;
										}
									}
								}
							}
						}
					}
					%radius--;
				}
				
			case $southDirection:
				for (%y = %radius; %y >= 0; %y--)
				{
					if (%y + %yIndex + %yOffset >= 0	&&
						%y + %yIndex + %yOffset < $mazeDimension)
					{
						for (%x = -1 * %radius; %x <= %radius; %x++)
						{
							if (%x + %xIndex + %xOffset >= 0	&&
								%x + %xIndex + %xOffset < $mazeDimension)
							{
								if (%x != 0	||
									%y != 0)
								{//echo("south distance check");
									%distance = VectorDist(getTilePositionFromIndices(%x + %xIndex + %xOffset, %y + %yIndex + %yOffset), $playerSquad[%characterIndex].getPosition());
									%distance = mAbs(%distance);
									if (%distance < %maxDistance)
									{
										%los = bresenhamLineAlgorithm($playerSquad[%characterIndex].xIndex, $playerSquad[%characterIndex].yIndex, %x + %xIndex + %xOffset, %y + %yIndex + %yOffset);
										if (%los)
										{//echo("have los!");
											$dummyFogOfWar[%x + %xIndex + %xOffset, %y + %yIndex + %yOffset] = 0;
										}
									}
								}
							}
						}
					}
					
					// Decrement radius for cone of vision.
					%radius--;
				}
				
			case $westDirection:
				for (%x = -1 * %radius; %x <= 0; %x++)
				{
					if (%x + %xIndex + %xOffset >= 0	&&
						%x + %xIndex + %xOffset < $mazeDimension)
					{
						for (%y = -1 * %radius; %y <= %radius; %y++)
						{
							if (%y + %yIndex + %yOffset >= 0	&&
								%y + %yIndex + %yOffset < $mazeDimension)
							{
								if (%x != 0	||
									%y != 0)
								{//echo("west distance check");
									%distance = VectorDist(getTilePositionFromIndices(%x + %xIndex + %xOffset, %y + %yIndex + %yOffset), $playerSquad[%characterIndex].getPosition());
									%distance = mAbs(%distance);
									if (%distance < %maxDistance)
									{
										%los = bresenhamLineAlgorithm($playerSquad[%characterIndex].xIndex, $playerSquad[%characterIndex].yIndex, %x + %xIndex + %xOffset, %y + %yIndex + %yOffset);
										if (%los)
										{//echo("have los!");
											$dummyFogOfWar[%x + %xIndex + %xOffset, %y + %yIndex + %yOffset] = 0;
										}
									}
								}
							}
						}
					}
					%radius--;
				}
				
			case $eastDirection:
				for (%x = %radius; %x >= 0; %x--)
				{
					if (%x + %xIndex + %xOffset >= 0	&&
						%x + %xIndex + %xOffset < $mazeDimension)
					{
						for (%y = %radius; %y >= -1 * %radius; %y--)
						{
							if (%y + %yIndex + %yOffset >= 0	&&
								%y + %yIndex + %yOffset < $mazeDimension)
							{
								if (%x != 0	||
									%y != 0)
								{//echo("east distance check");
									%distance = VectorDist(getTilePositionFromIndices(%x + %xIndex + %xOffset, %y + %yIndex + %yOffset), $playerSquad[%characterIndex].getPosition());
									%distance = mAbs(%distance);
									if (%distance < %maxDistance)
									{
										%los = bresenhamLineAlgorithm($playerSquad[%characterIndex].xIndex, $playerSquad[%characterIndex].yIndex, %x + %xIndex + %xOffset, %y + %yIndex + %yOffset);
										if (%los)
										{//echo("have los!");
											$dummyFogOfWar[%x + %xIndex + %xOffset, %y + %yIndex + %yOffset] = 0;
										}
									}
								}
							}
						}
					}
					%radius--;
				}
		}
		// (0, 0) is where the character is standing, so this should always be revealed.
		if (%xIndex >= 0				&&
			%xIndex <= $mazeDimension	&&
			%yIndex >= 0				&&
			%yIndex <= $mazeDimension)
		{
			$dummyFogOfWar[%xIndex, %yIndex] = 0;
		}
	}
}
function fogOfWarClass::showFogOfWar (%this)
{//echo("fogOfWarClass::showFogOfWar()");
	// Leave if there are no live squad members!
	if (!$leaderPersist		&&
		!$scoutPersist		&&
		!$grenadierPersist	&&
		!$supportPersist)
	{
		return;
	}
	%this.initFogOfWar();
	%this.schedule($showAndTellWait, "showAndTellMonsters");
}
function fogOfWarClass::owner (%this, %posX, %posY)
{//echo("fogOfWarClass::owner()");
	return getWord(%this.getTileCustomData(%posX, %posY), 0);
}