// Handles Monster Spawns.
// Worthless Bums 2012.


// Test function to print out the names of all current enemies.
function printMonsterNames ()
{//echo('printMonsterNames()");
	for (%i = 0; %i < $monsterList.getCount(); %i++)
	{
		echo("monster " @ %i @ " name is " @ ($monsterList.getObject(%i).name));
	}
}
function getRandomMonsterType ()
{//echo("getRandomMonsterType()");
	return getRandom(0, $maxMonsterTypes);
}
function clearMonsterList ()
{//echo("clearMonsterList()");
	// Clear the monster list!
	for (%i = 0; %i < $monsterList.getCount(); %i++)
	{
		($monsterList.getObject(%i)).safeDelete();
	}
	$monsterList = new SimSet();
}
function spawnMonsters (%numberOfMonsters)
{//echo("spawnMonsters()");
//echo("%numberOfMonsters =" SPC %numberOfMonsters);
	if ($generateTutorialLevel)
	{
		return;
	}
	%offset = 4;
	if (%offset > $mazeDimension)
	{
		return false;
	}
	clearMonsterList();
	%safeZone = getSafeZone();
	%minX = getWord(%safeZone, 0);
	%maxX = getWord(%safeZone, 1);
	%minY = getWord(%safeZone, 2);
	%maxY = getWord(%safeZone, 3);
	for (%i = 0; %i < %numberOfMonsters; %i++)
	{//echo("%i =" SPC %i);
		if ($monsterList.getCount() >= $maxMonsters)
		{
			return false;
		}
		// Make sure we spawn on a passable tile!
		// Lock the number of random placement attempts to avoid an infinite loop.
		%attempts = 0;
		%maxAttempts = 20;
		%spawnMonster = false;
		do
		{
			%attempts++;
			// Generate a random position within specified bounds.
			%randomX = getRandom(%offset, $mazeDimension - 1 - %offset);
			%randomY = getRandom(%offset, $mazeDimension - 1 - %offset);
			// Make sure the tile is not in the safe zone!
			if ((%randomX < %minX	||	%randomX > %maxX)	&&
				(%randomY < %minY	||	%randomY > %maxY))
			{
				// Make sure the tile is clear!
				if (tileIsClearOfObstructions(%randomX, %randomY))
				{
					%spawnMonster = true;
					break;
				}
			}
		} while (($mazeRoom[%randomX, %randomY].status == 0 || $mazeRoom[%randomX, %randomY].status == -1 || $mazeRoom[%randomX, %randomY].status == -2)	&&		// Tile status 1 is walkable, 0 is not walkable. NOTE: This is potentially an infinite loop if the maze room is filled with unwalkable tiles!
				 %attempts < %maxAttempts)
		if (%spawnMonster)
		{
			%monsterSpawn = spawnRandomMonster(%randomX, %randomY);
			%sleepChance = getRandom(1, 100);
			if (%sleepChance <= $sleepChance)
			{
				createSleepAnimation(%monsterSpawn);
			}
			handleLiftedTileMarker(%monsterSpawn);
			$monsterList.add(%monsterSpawn);
		}
	}
	
	// Chance to spawn a non-boss variant!
	%spawnBossVariantChance = 20;
	if ($overworldLocation !$= "Command Deck")		// After Command Deck.
	{
		if (getRandom(1, 100) <= %spawnBossVariantChance	&&
			tileIsClearOfUnits($stairsXIndex, $stairsYIndex))
		{
			spawnNonBossHulk();
			updateMonsterFloatingText();
		}
	}
	else if ($engineeringDeckLevel >= 5)			// After Engineering Deck.
	{
		if (getRandom(1, 100) <= %spawnBossVariantChance	&&
			tileIsClearOfUnits($stairsXIndex, $stairsYIndex))
		{
			%revenantSpawn = spawnMonster(3, $stairsXIndex, $stairsYIndex);
			%revenantSpawn.name = "Revenion";
			createUnitShadow(%revenantSpawn);
			$monsterList.add(%revenantSpawn);
			updateMonsterFloatingText();
		}
	}
	else if ($medicalDeckLevel >= 5)				// After Medical Deck.
	{
		if (getRandom(1, 100) <= %spawnBossVariantChance	&&
			tileIsClearOfUnits($stairsXIndex, $stairsYIndex))
		{
			%brainienSpawn = spawnMonster(15, $stairsXIndex, $stairsYIndex);
			%brainienSpawn.name = "Brainian";
			createUnitShadow(%brainienSpawn);
			$monsterList.add(%brainienSpawn);
			updateMonsterFloatingText();
		}
	}
	else if ($armoryDeckLevel >= 5)				// After Armory Deck.
	{
		if (getRandom(1, 100) <= %spawnBossVariantChance	&&
			tileIsClearOfUnits($stairsXIndex, $stairsYIndex))
		{
			%gunboatSpawn = spawnMonster(17, $stairsXIndex, $stairsYIndex);
			%gunboatSpawn.name = "Gunboat";
			createUnitShadow(%gunboatSpawn);
			$monsterList.add(%gunboatSpawn);
			updateMonsterFloatingText();
		}
	}
	else if ($bridgeDeckLevel >= 5)				// After Bridge Deck.
	{
		if (getRandom(1, 100) <= %spawnBossVariantChance	&&
			tileIsClearOfUnits($stairsXIndex, $stairsYIndex))
		{
			%matricsSpawn = spawnMonster(18, $stairsXIndex, $stairsYIndex);
			%matricsSpawn.name = "Matrics";
			createUnitShadow(%matricsSpawn);
			$monsterList.add(%matricsSpawn);
			updateMonsterFloatingText();
		}
	}
	$maxMonsters = $monsterList.getCount();		// Need this for calculating Hostile Control on decks!
	
	// Don't allow zero monsters!
	// NOTE: Beware infinite loop!
	if ($monsterList.getCount() <= 0)
	{//echo("IF");checksWallStatuses();
		spawnMonsters(%numberOfMonsters);
	}
	else
	{//echo("ELSE");checksWallStatuses();
		spawnMonsterGroups();
	}
}
function spawnMonsterGroups ()
{//echo("spawnMonsterGroups()");
	// For every monster check the neighboring eight tiles and spawn random monsters if clear.
	for (%i = 0; %i < $monsterList.getCount(); %i++)
	{
		%groupRoll = getRandom(1, 100);
		if (%groupRoll <= $MonsterGroupChance)
		{//echo("IF");checksWallStatuses();
			spawnMonsterAlly(%i);
		}
	}
}
function spawnMonsterAlly (%monsterIndex)
{//echo("spawnMonsterAlly()");
	%monster = $monsterList.getObject(%monsterIndex);
	%xIndex = %monster.xIndex;
	%yIndex = %monster.yIndex;
	%xIndex += getRandom(-1, 1);
	%yIndex += getRandom(-1, 1);
	if (%xIndex >= 0	&& 	%xIndex < $mazeDimension	&&
		%yIndex >= 0	&& 	%yIndex < $mazeDimension	&&
		$mazeRoom[%xIndex, %yIndex].status == 1			&&
		tileIsClearOfObstructions(%xIndex, %yIndex))
	{
		%monsterSpawn = spawnRandomMonster(%xIndex, %yIndex);
		// Handle sleep animations for sleeping monsters!
		%sleepChance = getRandom(1, 100);
		if (%sleepChance <= $sleepChance)
		{
			createSleepAnimation(%monsterSpawn);
		}
		$monsterList.add(%monsterSpawn);
	}
}
function getRandomDungeonMonsterType ()
{//echo("getRandomDungeonMonsterType()");
	switch$ ($overworldLocation)
	{
		case "Command Deck":
			if ($dungeonLevel <= 1)
			{
				// Brute.
				%monsterType = 0;
			}
			else
			{
				%monsterType = getRandom(1, 100);
				if (%monsterType <= 30)
				{
					// Brute.
					%monsterType = 0;
				}
				else if (%monsterType <= 60)
				{
					// Bruton.
					%monsterType = 16;
				}
				else if (%monsterType <= 80)
				{
					// Bucket.
					%monsterType = 5;
				}
				else if (%monsterType <= 100)
				{
					// Flamejack.
					%monsterType = 1;
				}
			}
			
		case "Engineering Deck":
			%monsterType = getRandom(1, 100);
			if (%monsterType <= 25)
			{
				// Thopter.
				%monsterType = 6;
			}
			else if (%monsterType <= 60)
			{
				// Flamejack.
				%monsterType = 1;
			}
			else if (%monsterType <= 80)
			{
				// Tick.
				%monsterType = 8;
			}
			else if (%monsterType <= 100)
			{
				// Torgon.
				%monsterType = 10;
			}
			
		case "Medical Deck":
			%monsterType = getRandom(1, 100);
			if (%monsterType <= 15)
			{
				// Ripsaw.
				%monsterType = 7;
			}
			else if (%monsterType <= 30)
			{
				// Amputator.
				%monsterType = 9;
			}
			else if (%monsterType <= 60)
			{
				// Torgon.
				%monsterType = 10;
			}
			else if (%monsterType <= 80)
			{
				// Sapper.
				%monsterType = 14;
			}
			else if (%monsterType <= 100)
			{
				// TorSniper.
				%monsterType = 11;
			}
			/*else if (%monsterType <= 100)
			{
				// Brainien.
				%monsterType = 15;
			}*/
			
		case "Armory Deck":
			%monsterType = getRandom(1, 100);
			if (%monsterType <= 20)
			{
				// Torgon.
				%monsterType = 10;
			}
			else if (%monsterType <= 40)
			{
				// Sapper.
				%monsterType = 14;
			}
			else if (%monsterType <= 60)
			{
				// TorSniper.
				%monsterType = 11;
			}
			else if (%monsterType <= 100)
			{
				// TorScout.
				%monsterType = 12;
			}
			/*else
			{
				// TorChaser.
				%monsterType = 13;
			}*/
			
		case "Bridge Deck":
			if ($dungeonLevel <= 1)
			{
				%monsterType = getRandom(1, 100);
				if (%monsterType <= 75)
				{
					// Torgon.
					%monsterType = 10;
				}
				else if (%monsterType <= 100)
				{
					// Sapper.
					%monsterType = 14;
				}
			}
			else
			{
				%monsterType = getRandom(1, 100);
				if (%monsterType <= 25)
				{
					// Torgon.
					%monsterType = 10;
				}
				else if (%monsterType <= 40)
				{
					// Sapper.
					%monsterType = 14;
				}
				else if (%monsterType <= 60)
				{
					// TorSniper.
					%monsterType = 11;
				}
				else if (%monsterType <= 90)
				{
					// TorScout.
					%monsterType = 12;
				}
				else
				{
					// TorChaser.
					%monsterType = 13;
				}
			}
			
		case "Alien Deck":
			if ($dungeonLevel <= 1)
			{
				%monsterType = getRandom(1, 100);
				if (%monsterType <= 75)
				{
					// Bruton.
					%monsterType = 16;
				}
				else if (%monsterType <= 100)
				{
					// Sapper.
					%monsterType = 14;
				}
			}
			else
			{
				%monsterType = getRandom(1, 100);
				if (%monsterType <= 30)
				{
					// Bruton.
					%monsterType = 16;
				}
				else if (%monsterType <= 45)
				{
					// Sapper.
					%monsterType = 14;
				}
				else if (%monsterType <= 60)
				{
					// TorSniper.
					%monsterType = 11;
				}
				else if (%monsterType <= 90)
				{
					// TorScout.
					%monsterType = 12;
				}
				else
				{
					// Torgon.
					%monsterType = 10;
				}
			}
	}
	//return 16;	// For testing purposes only!
	return %monsterType;
}
function getRandomDirection ()
{//echo("getRandomDirection()");
	return getRandom(1, 4);
}
function spawnRandomMonster (%xIndex, %yIndex)
{//echo("spawnRandomMonster()");
	%monsterType = getRandomDungeonMonsterType();
	%randomMonster = spawnMonster(%monsterType, %xIndex, %yIndex);
	// NOTE: Might be changed when batching/groups are implemented!
	setMonsterFacing(getRandomDirection(), %randomMonster);
	return %randomMonster;
}

function spawnHulk ()
{//echo("spawnHulk()");
	powerElevatorOff();
	%hulkSpawn = spawnMonster(4, $stairsXIndex, $stairsYIndex);
	createUnitShadow(%hulkSpawn);
	$monsterList.add(%hulkSpawn);
	updateElevatorArrowAnimation();
}
function spawnNonBossHulk ()
{//echo("spawnNonBossHulk()");
	%hulkSpawn = spawnMonster(4, $stairsXIndex, $stairsYIndex);
	createUnitShadow(%hulkSpawn);
	$monsterList.add(%hulkSpawn);
}
function spawnRevenant ()
{//echo("spawnRevenant()");
	powerElevatorOff();
	%revenantSpawn = spawnMonster(3, $stairsXIndex, $stairsYIndex);
	createUnitShadow(%revenantSpawn);
	$monsterList.add(%revenantSpawn);
	updateElevatorArrowAnimation();
}
// Spawns a Revenion from the specified monster.
function spawnRevenion (%monster)
{//echo("spawnRevenion()");
	powerElevatorOff();
	updateElevatorArrowAnimation();
	if (%monster.currentHealth > %damage)
	{//echo("Revenant still alive!");
		// Make sure we have at least one free tile to move to!
		if ((tileIsClearOfObstructions(%monster.xIndex, %monster.yIndex - 1)	&&	tileIsClearOfUnits(%monster.xIndex, %monster.yIndex - 1))	||
			(tileIsClearOfObstructions(%monster.xIndex, %monster.yIndex + 1)	&&	tileIsClearOfUnits(%monster.xIndex, %monster.yIndex + 1))	||
			(tileIsClearOfObstructions(%monster.xIndex + 1, %monster.yIndex)	&&	tileIsClearOfUnits(%monster.xIndex + 1, %monster.yIndex))	||
			(tileIsClearOfObstructions(%monster.xIndex - 1, %monster.yIndex)	&&	tileIsClearOfUnits(%monster.xIndex - 1, %monster.yIndex)))
		{
			%spawnAttempts = 20;
			for (%i = 0; %i < %spawnAttempts; %i++)
			{
				// Randomly choose an adjacent tile to spawn on.
				%direction = getRandom(1, 4);
				%directionXIndex = %monster.xIndex;
				%directionYIndex = %monster.yIndex;
				switch (%direction)
				{
					case $northDirection:	%directionYIndex--;
					case $southDirection:	%directionYIndex++;
					case $eastDirection:	%directionXIndex++;
					case $westDirection:	%directionXIndex--;
				}
				// Look for a free tile adjacent to the hit Revenant.
				if (tileIsClearOfObstructions(%directionXIndex, %directionYIndex)	&&
					tileIsClearOfUnits(%directionXIndex, %directionYIndex))
				{//echo("Revenant tile clear!");
					%revenantMaxActionPoints = %monster.maximumActionPoints - 1;
					//echo("%revenantMaxActionPoints =" SPC %revenantMaxActionPoints);
					if (%revenantMaxActionPoints > 1)
					{//echo("Spawning Revenant!");
						%revenantSpawn = spawnMonster(3, %directionXIndex, %directionYIndex);
						%revenantSpawn.name = "Revenion";
						%revenantSpawn.currentActionPoints = %revenantMaxActionPoints;
						%revenantSpawn.maximumActionPoints = %revenantMaxActionPoints;
						%revenantSpawn.currentHealth = %revenantMaxActionPoints * 5;
						%revenantSpawn.maxHealth = %revenantMaxActionPoints * 5;
						createUnitShadow(%revenantSpawn);
						$monsterList.add(%revenantSpawn);
						updateMonsterFloatingText();
						return true;
					}
				}
			}
		}
		else
		{//echo("no clear tiles!");
			return false;
		}
	}
	return false;
}
// Spawns a Brainien in the level that needs to be killed to power the elevator!
function spawnBrainien ()
{//echo("spawnBrainien()");
	powerElevatorOff();
	%brainienSpawn = spawnMonster(15, $stairsXIndex, $stairsYIndex);
	createUnitShadow(%brainienSpawn);
	$monsterList.add(%brainienSpawn);
	updateElevatorArrowAnimation();
}
// Spawns a Gunship in the level that needs to be killed to power the elevator!
function spawnGunship ()
{//echo("spawnGunship()");
	powerElevatorOff();
	%gunshipSpawn = spawnMonster(17, $stairsXIndex, $stairsYIndex);
	%gunshipSpawn.setPosition(getWord(%gunshipSpawn.position, 0), getWord(%gunshipSpawn.position, 1) - $GunshipUnitVerticalShift);
	createUnitShadow(%gunshipSpawn);
	$monsterList.add(%gunshipSpawn);
	updateElevatorArrowAnimation();
}
// Spawns a Matrix in the level that needs to be killed to power the elevator!
function spawnMatrix ()
{//echo("spawnMatrix()");
	powerElevatorOff();
	%matrixSpawn = spawnMonster(18, $stairsXIndex, $stairsYIndex);
	%matrixSpawn.setPosition(getWord(%matrixSpawn.position, 0), getWord(%matrixSpawn.position, 1) - $MatrixUnitVerticalShift);
	createUnitShadow(%matrixSpawn);
	$monsterList.add(%matrixSpawn);
	updateElevatorArrowAnimation();
}
// Spawns a Matrix unit.
function spawnMatrixUnit (%monster)
{//echo("spawnMatrixUnit()");
	%monsterType = 16;	// Bruton.
	%matrixSpawn = spawnMonster(%monsterType, %monster.xIndex, %monster.yIndex);				// Spawn on top of the Matrix.
	%spawnXPos = getWord(getTilePositionFromIndices(%monster.xIndex, %monster.yIndex - 1), 0);
	%spawnYPos = getWord(getTilePositionFromIndices(%monster.xIndex, %monster.yIndex - 1), 1);
	%matrixSpawn.moveTo(%spawnXPos, %spawnYPos, 15.0, true, false);					// Move to south floor tile.
	inPlaceMonsterActionGrowAndShrink(%matrixSpawn);
	%matrixSpawn.yIndex--;
	$MonsterList.add(%matrixSpawn);
}
// Spawns a Patriarch in the level that needs to be killed to power the elevator!
function spawnPatriarch ()
{//echo("spawnPatriarch()");
	powerElevatorOff();
	%patriarchSpawn = spawnMonster(19, $stairsXIndex, $stairsYIndex);
	createUnitShadow(%patriarchSpawn);
	$monsterList.add(%patriarchSpawn);
	updateElevatorArrowAnimation();
}

function spawnMonster (%monsterType, %xIndex, %yIndex)
{//echo("spawnMonster()");
	switch (%monsterType)
	{
		case  0:	// Brute.
			// Randomly spawn a larger Brute!
			%largerBruteRoll = getRandom(1, 100);
			// "Normal" Brute stats.
			%imageMap = "Sprites:Brute";
			%size = "4 4";
			%currentHealth = $bruteBaseHP;
			%maxHealth = $bruteBaseHP;
			%currentActionPoints = $bruteBaseAP;
			%maximumActionPoints = $bruteBaseAP;
			%armorRating = $bruteBaseAR;
			%baseDamage = 12;
			%attackModifier = $bruteBaseAttack;
			%evasion = $bruteBaseEvasion;
			%canRange = $bruteBaseCanRange;
			%baseMeleeDamage = $bruteBaseMeleeDamage;
			%baseRangeDamage = $bruteBaseRangeDamage;
			
			%randomMonster = new Sprite()
			{
				name = "Brute";
				level = $bruteBaseLevel;
				SceneLayer = $monsterLayer;
				graph = $monsterGraph;
				scenegraph = levelSceneGraph;
				Animation = "Sprites:BruteIdleSouthAnimation";
				position = getTilePositionFromIndices(%xIndex, %yIndex);
				size = %size;
				visible = true;
				xIndex = %xIndex;
				yIndex = %yIndex;
				facing = $southDirection;
				currentHealth = %currentHealth;
				maxHealth = %maxHealth;
				currentActionPoints = %currentActionPoints;
				maximumActionPoints = %maximumActionPoints;
				armorRating = %armorRating;
				baseDamage = %baseDamage;
				attackModifier = %attackModifier;
				evasion = %evasion;
				canBurrow = false;
				burrow = false;
				canRange = %canRange;
				defensiveCaster = false;
				range = $bruteBaseRange;		// In Torque internal units - tiles are 4x4.
				hasBeenSpotted = 0;
				isActive = $MonstersStartActive;
				meleeDamageType = $bruteBaseMeleeDamageType;
				rangeDamageType = $bruteBaseRangeDamageType;
				baseMeleeDamage = %baseMeleeDamage;
				baseRangeDamage = %baseRangeDamage;
				isHuman = $bruteBaseIsHuman;
				isRobot = $bruteBaseIsRobot;
				isAlien = $bruteBaseIsAlien;
				weapon = null;
				healthIndicator = null;
				sleepAnimation = null;
				onFireEffect = null;
				chargeAnimation = null;
				stasis = false;
				demolitions = 0;
			};
			
		case  1:	// Flamejack.
			%randomMonster = new Sprite()
			{
				name = "Flamejack";
				level = $flamejackBaseLevel;
				SceneLayer = $monsterLayer;
				graph = $monsterGraph;
				scenegraph = levelSceneGraph;
				animation = "Sprites:FlamejackIdleSouthAnimation";
				position = getTilePositionFromIndices(%xIndex, %yIndex);
				size = "4 4";
				visible = true;
				xIndex = %xIndex;
				yIndex = %yIndex;
				facing = $southDirection;
				currentHealth = $flamejackBaseHP;
				maxHealth = $flamejackBaseHP;
				currentActionPoints = $flamejackBaseAP;
				maximumActionPoints = $flamejackBaseAP;
				armorRating = $flamejackBaseAR;
				baseDamage = 30;
				attackModifier = $flamejackBaseAttack;
				evasion = $flamejackBaseEvasion;
				canBurrow = false;
				burrow = false;
				canRange = $flamejackBaseCanRange;
				defensiveCaster = false;
				range = $flamejackBaseRange;		// In Torque internal units - tiles are 4x4.
				hasBeenSpotted = 0;
				isActive = $MonstersStartActive;
				meleeDamageType = $flamejackBaseMeleeDamageType;
				rangeDamageType = $flamejackBaseRangeDamageType;
				baseMeleeDamage = $flamejackBaseMeleeDamage;
				baseRangeDamage = $flamejackBaseRangeDamage;
				isHuman = $flamejackBaseIsHuman;
				isRobot = $flamejackBaseIsRobot;
				isAlien = $flamejackBaseIsAlien;
				weapon = null;
				healthIndicator = null;
				sleepAnimation = null;
				onFireEffect = null;
				chargeAnimation = null;
				stasis = false;
				demolitions = 0;
			};
			
		case  2:	// Acidjack.
			// Just place a static sprite at the specified location for now.
			/*%randomMonster = new Sprite()
			{
				// General Stats.
				name = "Acidjack";
				level = 1;
				SceneLayer = $monsterLayer;
				graph = $monsterGraph;
				scenegraph = levelSceneGraph;
				imageMap = "acidjack_1ImageMap";
				position = getTilePositionFromIndices(%xIndex, %yIndex);
				size = "4 4";
				visible = true;
				xIndex = %xIndex;
				yIndex = %yIndex;
				facing = $southDirection;
				// Monster stats.
				currentHealth = 16;
				maxHealth = 16;
				currentActionPoints = 3;
				maximumActionPoints = 3;
				armorRating = 6;
				baseDamage = 20;
				attackModifier = 75;
				evasion = 20;
				// Monster burrow.
				canBurrow = false;
				burrow = false;
				// Monster range.
				canRange = false;
				defensiveCaster = false;
				range = 0;		// In Torque internal units - tiles are 4x4.
				// If this monster has been spotted by the squad (currently used for experience gain).
				hasBeenSpotted = 0;
				// Whether this monster is active or not.
				isActive = $MonstersStartActive;
				// Melee damage type.
				meleeDamageType = "acid";
				// Range damage type.
				rangeDamageType = "acid";
				// Base melee damage.
				baseMeleeDamage = 7;
				// Base range damage.
				baseRangeDamage = 5;
				
				// Monster Types.
				isHuman = false;
				isRobot = true;
				isAlien = false;
				
				// Weapon.
				weapon = null;
				// Health Indicator.
				healthIndicator = null;
				// Sleep Animation.
				sleepAnimation = null;
				// Fire Particle Effect.
				onFireEffect = null;
				// Thrasher charge animation.
				chargeAnimation = null;
				
				// Stasis.
				stasis = false;
				
				// Stats and skills.
				demolitions = 0;
			};*/
			
		case  3:	// Revenant.
			%randomMonster = new Sprite()
			{
				name = "Revenant";
				level = $revenantBaseLevel;
				SceneLayer = $monsterLayer;
				graph = $monsterGraph;
				scenegraph = levelSceneGraph;
				Animation = "Sprites:RevenantIdleSouthAnimation";
				position = getTallUnitTilePositionFromIndices(%xIndex, %yIndex);//getTilePositionFromIndices(%xIndex, %yIndex);
				size = "4 8";
				visible = true;
				xIndex = %xIndex;
				yIndex = %yIndex;
				facing = $southDirection;
				currentHealth = $revenantBaseHP;
				maxHealth = $revenantBaseHP;
				currentActionPoints = $revenantBaseAP;
				maximumActionPoints = $revenantBaseAP;
				armorRating = $revenantBaseAR;
				baseDamage = 20;
				attackModifier = $revenantBaseAttack;
				evasion = $revenantBaseEvasion;
				canBurrow = false;
				burrow = false;
				canRange = $revenantBaseCanRange;
				defensiveCaster = false;
				range = $revenantBaseRange;		// In Torque internal units - tiles are 4x4.
				hasBeenSpotted = 0;
				isActive = $MonstersStartActive;
				meleeDamageType = $revenantBaseMeleeDamageType;
				rangeDamageType = $revenantBaseRangeDamageType;
				baseMeleeDamage = $revenantBaseMeleeDamage;
				baseRangeDamage = $revenantBaseRangeDamage;
				isHuman = false;
				isRobot = true;
				isAlien = false;
				weapon = null;
				healthIndicator = null;
				sleepAnimation = null;
				onFireEffect = null;
				chargeAnimation = null;
				stasis = false;
				demolitions = 0;
			};
			
		case  4:	// Hulk.
			%imageMap = "hulk_1ImageMap";
			%size = "8 8";
			%currentHealth = 120;
			%maxHealth = 120;
			%currentActionPoints = 4;
			%maximumActionPoints = 4;
			%armorRating = 8;
			%baseDamage = 20;
			%attackModifier = 75;
			%evasion = 15;
			%canRange = true;
			%baseMeleeDamage = 15;
			%baseRangeDamage = 9;
			%randomMonster = new Sprite()
			{
				name = "Hulk";
				level = $hulkBaseLevel;
				SceneLayer = $monsterLayer;
				graph = $monsterGraph;
				scenegraph = levelSceneGraph;
				Animation = "Sprites:HulkIdleSouthAnimation";
				position = getTallUnitTilePositionFromIndices(%xIndex, %yIndex);//getTilePositionFromIndices(%xIndex, %yIndex);
				size = %size;
				visible = true;
				xIndex = %xIndex;
				yIndex = %yIndex;
				facing = $southDirection;
				currentHealth = $hulkBaseHP;
				maxHealth = $hulkBaseHP;
				currentActionPoints = $hulkBaseAP;
				maximumActionPoints = $hulkBaseAP;
				armorRating = $hulkBaseAR;
				baseDamage = %baseDamage;
				attackModifier = $hulkBaseAttack;
				evasion = $hulkBaseEvasion;
				canBurrow = false;
				burrow = false;
				canRange = $hulkBaseCanRange;		// True for charge ability, false otherwise!
				defensiveCaster = false;
				range = $hulkBaseRange;		// In Torque internal units - tiles are 4x4.
				hasBeenSpotted = 0;
				isActive = $MonstersStartActive;
				meleeDamageType = $hulkBaseMeleeDamageType;
				rangeDamageType = $hulkBaseRangeDamageType;
				baseMeleeDamage = $hulkBaseMeleeDamage;
				baseRangeDamage = $hulkBaseRangeDamage;
				isHuman = false;
				isRobot = true;
				isAlien = false;
				weapon = null;
				healthIndicator = null;
				sleepAnimation = null;
				onFireEffect = null;
				chargeAnimation = null;
				stasis = false;
				demolitions = 0;
			};
			
		case  5:	// Bucket.
			%randomMonster = new Sprite()
			{
				name = "Bucket";
				level = $bucketBaseLevel;
				SceneLayer = $monsterLayer;
				graph = $monsterGraph;
				scenegraph = levelSceneGraph;
				Animation = "Sprites:BucketIdleSouthAnimation";
				position = getTilePositionFromIndices(%xIndex, %yIndex);
				size = "4 4";
				visible = true;
				xIndex = %xIndex;
				yIndex = %yIndex;
				facing = $southDirection;
				currentHealth = $bucketBaseHP;
				maxHealth = $bucketBaseHP;
				currentActionPoints = $bucketBaseAP;
				maximumActionPoints = $bucketBaseAP;
				armorRating = $bucketBaseAR;
				baseDamage = 9;
				attackModifier = $bucketBaseAttack;
				evasion = $bucketBaseEvasion;
				canBurrow = false;
				burrow = false;
				canRange = $bucketBaseCanRange;
				defensiveCaster = false;
				range = $bucketBaseRange;		// In Torque internal units - tiles are 4x4.
				hasBeenSpotted = 0;
				isActive = $MonstersStartActive;
				meleeDamageType = $bucketBaseMeleeDamageType;
				rangeDamageType = $bucketBaseMeleeDamageType;
				baseMeleeDamage = $bucketBaseMeleeDamage;
				baseRangeDamage = $bucketBaseRangeDamage;
				isHuman = $bucketBaseIsHuman;
				isRobot = $bucketBaseIsRobot;
				isAlien = $bucketBaseIsAlien;
				weapon = null;
				healthIndicator = null;
				sleepAnimation = null;
				onFireEffect = null;
				chargeAnimation = null;
				stasis = false;
				demolitions = 0;
			};
			
		case  6:	// Thopter.
			%randomMonster = new Sprite()
			{
				name = "Thopter";
				level = $thopterBaseLevel;
				SceneLayer = $monsterLayer;
				graph = $monsterGraph;
				scenegraph = levelSceneGraph;
				Animation = "Sprites:ThopterIdleSouthAnimation";
				position = getTilePositionFromIndices(%xIndex, %yIndex);
				size = "4 4";
				visible = true;
				xIndex = %xIndex;
				yIndex = %yIndex;
				facing = $southDirection;
				currentHealth = $thopterBaseHP;
				maxHealth = $thopterBaseHP;
				currentActionPoints = $thopterBaseAP;
				maximumActionPoints = $thopterBaseAP;
				armorRating = $thopterBaseAR;
				baseDamage = 8;
				attackModifier = $thopterBaseAttack;
				evasion = $thopterBaseEvasion;
				canBurrow = false;
				burrow = false;
				canRange = $thopterBaseCanRange;
				defensiveCaster = false;
				range = $thopterBaseRange;		// In Torque internal units - tiles are 4x4.
				hasBeenSpotted = 0;
				isActive = $MonstersStartActive;
				meleeDamageType = $thopterBaseMeleeDamageType;
				rangeDamageType = $thopterBaseRangeDamageType;
				baseMeleeDamage = $thopterBaseMeleeDamage;
				baseRangeDamage = $thopterBaseRangeDamage;
				isHuman = $thopterBaseIsHuman;
				isRobot = $thopterBaseIsRobot;
				isAlien = $thopterBaseIsAlien;
				weapon = null;
				healthIndicator = null;
				sleepAnimation = null;
				onFireEffect = null;
				chargeAnimation = null;
				stasis = false;
				demolitions = 0;
			};
			
		case  7:	// Ripsaw.
			%randomMonster = new Sprite()
			{
				name = "Ripsaw";
				level = $ripsawBaseLevel;
				SceneLayer = $monsterLayer;
				graph = $monsterGraph;
				scenegraph = levelSceneGraph;
				Animation = "Sprites:RipsawIdleSouthAnimation";
				position = getTilePositionFromIndices(%xIndex, %yIndex);
				size = "4 4";
				visible = true;
				xIndex = %xIndex;
				yIndex = %yIndex;
				facing = $southDirection;
				currentHealth = $ripsawBaseHP;
				maxHealth = $ripsawBaseHP;
				currentActionPoints = $ripsawBaseAP;
				maximumActionPoints = $ripsawBaseAP;
				armorRating = $ripsawBaseAR;
				baseDamage = 12;
				attackModifier = $ripsawBaseAttack;
				evasion = $ripsawBaseEvasion;
				canBurrow = false;
				burrow = false;
				canRange = $ripsawBaseCanRange;
				defensiveCaster = false;
				range = $ripsawBaseRange;		// In Torque internal units - tiles are 4x4.
				hasBeenSpotted = 0;
				isActive = $MonstersStartActive;
				meleeDamageType = $ripsawBaseMeleeDamageType;
				rangeDamageType = $ripsawBaseRangeDamageType;
				baseMeleeDamage = $ripsawBaseMeleeDamage;
				baseRangeDamage = $ripsawBaseRangeDamage;
				isHuman = $ripsawBaseIsHuman;
				isRobot = $ripsawBaseIsRobot;
				isAlien = $ripsawBaseIsAlien;
				weapon = null;
				healthIndicator = null;
				sleepAnimation = null;
				onFireEffect = null;
				chargeAnimation = null;
				stasis = false;
				demolitions = 0;
			};
			
		case  8:	// Tick.
			%randomMonster = new Sprite()
			{
				name = "Tick";
				level = $tickBaseLevel;
				SceneLayer = $monsterLayer;
				graph = $monsterGraph;
				scenegraph = levelSceneGraph;
				Animation = "Sprites:TickIdleSouthAnimation";
				position = getTilePositionFromIndices(%xIndex, %yIndex);
				size = "4 4";
				visible = true;
				xIndex = %xIndex;
				yIndex = %yIndex;
				facing = $southDirection;
				currentHealth = $tickBaseHP;
				maxHealth = $tickBaseHP;
				currentActionPoints = $tickBaseAP;
				maximumActionPoints = $tickBaseAP;
				armorRating = $tickBaseAR;
				baseDamage = 10;
				attackModifier = $tickBaseAttack;
				evasion = $tickBaseEvasion;
				canBurrow = false;
				burrow = false;
				canRange = $tickBaseCanRange;
				defensiveCaster = false;
				range = $tickBaseRange;		// In Torque internal units - tiles are 4x4.
				hasBeenSpotted = 0;
				isActive = $MonstersStartActive;
				meleeDamageType = $tickBaseMeleeDamageType;
				rangeDamageType = $tickBaseRangeDamageType;
				baseMeleeDamage = $tickBaseMeleeDamage;
				baseRangeDamage = $tickBaseRangeDamage;
				isHuman = $tickBaseIsHuman;
				isRobot = $tickBaseIsRobot;
				isAlien = $tickBaseIsAlien;
				weapon = null;
				healthIndicator = null;
				sleepAnimation = null;
				onFireEffect = null;
				chargeAnimation = null;
				stasis = false;
				demolitions = 0;
			};
			
		case  9:	// Amputator.
			%randomMonster = new Sprite()
			{
				name = "Amputator";
				level = $amputatorBaseLevel;
				SceneLayer = $monsterLayer;
				graph = $monsterGraph;
				scenegraph = levelSceneGraph;
				Animation = "Sprites:AmputatorIdleSouthAnimation";
				position = getTilePositionFromIndices(%xIndex, %yIndex);
				size = "4 4";
				visible = true;
				xIndex = %xIndex;
				yIndex = %yIndex;
				facing = $southDirection;
				currentHealth = $amputatorBaseHP;
				maxHealth = $amputatorBaseHP;
				currentActionPoints = $amputatorBaseAP;
				maximumActionPoints = $amputatorBaseAP;
				armorRating = $amputatorBaseAR;
				baseDamage = 10;
				attackModifier = $amputatorBaseAttack;
				evasion = $amputatorBaseEvasion;
				canBurrow = false;
				burrow = false;
				canRange = $amputatorBaseCanRange;
				defensiveCaster = false;
				range = $amputatorBaseRange;		// In Torque internal units - tiles are 4x4.
				hasBeenSpotted = 0;
				isActive = $MonstersStartActive;
				meleeDamageType = $amputatorBaseMeleeDamageType;
				rangeDamageType = $amputatorBaseRangeDamageType;
				baseMeleeDamage = $amputatorBaseMeleeDamage;
				baseRangeDamage = $amputatorBaseRangeDamage;
				isHuman = $amputatorBaseIsHuman;
				isRobot = $amputatorBaseIsRobot;
				isAlien = $amputatorBaseIsAlien;
				weapon = null;
				healthIndicator = null;
				sleepAnimation = null;
				onFireEffect = null;
				chargeAnimation = null;
				stasis = false;
				demolitions = 0;
			};
			
		case 10:	// Torgon.
			%randomMonster = new Sprite()
			{
				name = "Torgon";
				level = $torgonBaseLevel;
				SceneLayer = $monsterLayer;
				graph = $monsterGraph;
				scenegraph = levelSceneGraph;
				Animation = "Sprites:TorgonIdleSouthAnimation";
				position = getTilePositionFromIndices(%xIndex, %yIndex);
				size = "4 4";
				visible = true;
				xIndex = %xIndex;
				yIndex = %yIndex;
				facing = $southDirection;
				currentHealth = $torgonBaseHP;
				maxHealth = $torgonBaseHP;
				currentActionPoints = $torgonBaseAP;
				maximumActionPoints = $torgonBaseAP;
				armorRating = $torgonBaseAR;
				baseDamage = 6;
				attackModifier = $torgonBaseAttack;
				evasion = $torgonBaseEvasion;
				canBurrow = false;
				burrow = false;
				canRange = $torgonBaseCanRange;
				defensiveCaster = false;
				range = $torgonBaseRange;		// In Torque internal units - tiles are 4x4.
				hasBeenSpotted = 0;
				isActive = $MonstersStartActive;
				meleeDamageType = $torgonBaseMeleeDamageType;
				rangeDamageType = $torgonBaseRangeDamageType;
				baseMeleeDamage = $torgonBaseMeleeDamage;
				baseRangeDamage = $torgonBaseRangeDamage;
				isHuman = $torgonBaseIsHuman;
				isRobot = $torgonBaseIsRobot;
				isAlien = $torgonBaseIsAlien;
				weapon = null;
				healthIndicator = null;
				sleepAnimation = null;
				onFireEffect = null;
				chargeAnimation = null;
				stasis = false;
				demolitions = 0;
			};
			
		case 11:	// TorSniper.
			%randomMonster = new Sprite()
			{
				name = "TorSniper";
				level = $torsniperBaseLevel;
				SceneLayer = $monsterLayer;
				graph = $monsterGraph;
				scenegraph = levelSceneGraph;
				Animation = "Sprites:TorSniperIdleSouthAnimation";
				position = getTilePositionFromIndices(%xIndex, %yIndex);
				size = "4 4";
				visible = true;
				xIndex = %xIndex;
				yIndex = %yIndex;
				facing = $southDirection;
				currentHealth = $torsniperBaseHP;
				maxHealth = $torsniperBaseHP;
				currentActionPoints = $torsniperBaseAP;
				maximumActionPoints = $torsniperBaseAP;
				armorRating = $torsniperBaseAR;
				baseDamage = 3;
				attackModifier = $torsniperBaseAttack;
				evasion = $torsniperBaseEvasion;
				canBurrow = false;
				burrow = false;
				canRange = $torsniperBaseCanRange;
				defensiveCaster = false;
				range = $torsniperBaseRange;		// In Torque internal units - tiles are 4x4.
				hasBeenSpotted = 0;
				isActive = $MonstersStartActive;
				meleeDamageType = $torsniperBaseMeleeDamageType;
				rangeDamageType = $torsniperBaseRangeDamageType;
				baseMeleeDamage = $torsniperBaseMeleeDamage;
				baseRangeDamage = $torsniperBaseRangeDamage;
				isHuman = $torsniperBaseIsHuman;
				isRobot = $torsniperBaseIsRobot;
				isAlien = $torsniperBaseIsAlien;
				weapon = null;
				healthIndicator = null;
				sleepAnimation = null;
				onFireEffect = null;
				chargeAnimation = null;
				stasis = false;
				demolitions = 0;
			};
			
		case 12:	// TorScout.
			%randomMonster = new Sprite()
			{
				name = "TorScout";
				level = $torscoutBaseLevel;
				SceneLayer = $monsterLayer;
				graph = $monsterGraph;
				scenegraph = levelSceneGraph;
				Animation = "Sprites:TorScoutIdleSouthAnimation";
				position = getTilePositionFromIndices(%xIndex, %yIndex);
				size = "4 4";
				visible = true;
				xIndex = %xIndex;
				yIndex = %yIndex;
				facing = $southDirection;
				currentHealth = $torscoutBaseHP;
				maxHealth = $torscoutBaseHP;
				currentActionPoints = $torscoutBaseAP;
				maximumActionPoints = $torscoutBaseAP;
				armorRating = $torscoutBaseAR;
				baseDamage = 2;
				attackModifier = $torscoutBaseAttack;
				evasion = $torscoutBaseEvasion;
				canBurrow = false;
				burrow = false;
				canRange = $torscoutBaseCanRange;
				defensiveCaster = false;
				range = $torscoutBaseRange;		// In Torque internal units - tiles are 4x4.
				hasBeenSpotted = 0;
				isActive = $MonstersStartActive;
				meleeDamageType = $torscoutBaseMeleeDamageType;
				rangeDamageType = $torscoutBaseRangeDamageType;
				baseMeleeDamage = $torscoutBaseMeleeDamage;
				baseRangeDamage = $torscoutBaseRangeDamage;
				isHuman = $torscoutBaseIsHuman;
				isRobot = $torscoutBaseIsRobot;
				isAlien = $torscoutBaseIsAlien;
				weapon = null;
				healthIndicator = null;
				sleepAnimation = null;
				onFireEffect = null;
				chargeAnimation = null;
				stasis = false;
				demolitions = 0;
			};
			
		case 13:	// TorChaser.
			%randomMonster = new Sprite()
			{
				name = "TorChaser";
				level = $torchaserBaseLevel;
				SceneLayer = $monsterLayer;
				graph = $monsterGraph;
				scenegraph = levelSceneGraph;
				Animation = "Sprites:TorChaserIdleSouthAnimation";
				position = getTilePositionFromIndices(%xIndex, %yIndex);
				size = "4 4";
				visible = true;
				xIndex = %xIndex;
				yIndex = %yIndex;
				facing = $southDirection;
				currentHealth = $torchaserBaseHP;
				maxHealth = $torchaserBaseHP;
				currentActionPoints = $torchaserBaseAP;
				maximumActionPoints = $torchaserBaseAP;
				armorRating = $torchaserBaseAR;
				baseDamage = 9;
				attackModifier = $torchaserBaseAttack;
				evasion = $torchaserBaseEvasion;
				canBurrow = false;
				burrow = false;
				canRange = $torchaserBaseCanRange;
				defensiveCaster = false;
				range = $torchaserBaseRange;		// In Torque internal units - tiles are 4x4.
				hasBeenSpotted = 0;
				isActive = $MonstersStartActive;
				meleeDamageType = $torchaserBaseMeleeDamageType;
				rangeDamageType = $torchaserBaseRangeDamageType;
				baseMeleeDamage = $torchaserBaseMeleeDamage;
				baseRangeDamage = $torchaserBaseRangeDamage;
				isHuman = $torchaserBaseIsHuman;
				isRobot = $torchaserBaseIsRobot;
				isAlien = $torchaserBaseIsAlien;
				weapon = null;
				healthIndicator = null;
				sleepAnimation = null;
				onFireEffect = null;
				chargeAnimation = null;
				stasis = false;
				demolitions = 0;
			};
			
		case 14:	// Sapper.
			%randomMonster = new Sprite()
			{
				name = "Sapper";
				level = $sapperBaseLevel;
				SceneLayer = $monsterLayer;
				graph = $monsterGraph;
				scenegraph = levelSceneGraph;
				Animation = "Sprites:SapperIdleSouthAnimation";
				position = getTilePositionFromIndices(%xIndex, %yIndex);
				size = "4 4";
				visible = true;
				xIndex = %xIndex;
				yIndex = %yIndex;
				facing = $southDirection;
				currentHealth = $sapperBaseHP;
				maxHealth = $sapperBaseHP;
				currentActionPoints = $sapperBaseAP;
				maximumActionPoints = $sapperBaseAP;
				armorRating = $sapperBaseAR;
				baseDamage = 3;
				attackModifier = $sapperBaseAttack;
				evasion = $sapperBaseEvasion;
				canBurrow = false;
				burrow = false;
				canRange = $sapperBaseCanRange;
				defensiveCaster = false;
				range = $sapperBaseRange;		// In Torque internal units - tiles are 4x4.
				hasBeenSpotted = 0;
				isActive = $MonstersStartActive;
				meleeDamageType = $sapperBaseMeleeDamageType;
				rangeDamageType = $sapperBaseRangeDamageType;
				baseMeleeDamage = $sapperBaseMeleeDamage;
				baseRangeDamage = $sapperBaseRangeDamage;
				isHuman = $sapperBaseIsHuman;
				isRobot = $sapperBaseIsRobot;
				isAlien = $sapperBaseIsAlien;
				weapon = null;
				healthIndicator = null;
				sleepAnimation = null;
				onFireEffect = null;
				chargeAnimation = null;
				stasis = false;
				demolitions = 4;
			};
			
		case 15:	// Brainien.
			%randomMonster = new Sprite()
			{
				name = "Brainien";
				level = $brainienBaseLevel;
				SceneLayer = $monsterLayer;
				graph = $monsterGraph;
				scenegraph = levelSceneGraph;
				Animation = "Sprites:BrainienIdleSouthAnimation";
				position = getTilePositionFromIndices(%xIndex, %yIndex);
				size = "4 4";
				visible = true;
				xIndex = %xIndex;
				yIndex = %yIndex;
				facing = $southDirection;
				currentHealth = $brainienBaseHP;
				maxHealth = $brainienBaseHP;
				currentActionPoints = $brainienBaseAP;
				maximumActionPoints = $brainienBaseAP;
				armorRating = $brainienBaseAR;
				baseDamage = 8;
				attackModifier = $brainienBaseAttack;
				evasion = $brainienBaseEvasion;
				canBurrow = false;
				burrow = false;
				canRange = $brainienBaseCanRange;
				defensiveCaster = false;
				range = $brainienBaseRange;
				hasBeenSpotted = 0;
				isActive = $MonstersStartActive;
				meleeDamageType = $brainienBaseMeleeDamageType;
				rangeDamageType = $brainienBaseRangeDamageType;
				baseMeleeDamage = $brainienBaseMeleeDamage;
				baseRangeDamage = $brainienBaseRangeDamage;
				isHuman = $brainienBaseIsHuman;
				isRobot = $brainienBaseIsRobot;
				isAlien = $brainienBaseIsAlien;
				weapon = null;
				healthIndicator = null;
				sleepAnimation = null;
				onFireEffect = null;
				chargeAnimation = null;
				stasis = false;
				demolitions = 0;
			};
			
		case  16:	// Bruton.
			%randomMonster = new Sprite()
			{
				name = "Bruton";
				level = $brutonBaseLevel;
				SceneLayer = $monsterLayer;
				graph = $monsterGraph;
				scenegraph = levelSceneGraph;
				Animation = "Sprites:BrutonIdleSouthAnimation";
				position = getTilePositionFromIndices(%xIndex, %yIndex);
				size = "4 4";
				visible = true;
				xIndex = %xIndex;
				yIndex = %yIndex;
				facing = $southDirection;
				currentHealth = $brutonBaseHP;
				maxHealth = $brutonBaseHP;
				currentActionPoints = $brutonBaseAP;
				maximumActionPoints = $brutonBaseAP;
				armorRating = $brutonBaseAR;
				baseDamage = 7;
				attackModifier = $brutonBaseAttack;
				evasion = $brutonBaseEvasion;
				canBurrow = false;
				burrow = false;
				canRange = $brutonBaseCanRange;
				defensiveCaster = false;
				range = $brutonBaseRange;
				hasBeenSpotted = 0;
				isActive = $MonstersStartActive;
				meleeDamageType = $brutonBaseMeleeDamageType;
				rangeDamageType = $brutonBaseRangeDamageType;
				baseMeleeDamage = $brutonBaseMeleeDamage;
				baseRangeDamage = $brutonBaseRangeDamage;
				isHuman = $brutonBaseIsHuman;
				isRobot = $brutonBaseIsRobot;
				isAlien = $brutonBaseIsAlien;
				weapon = null;
				healthIndicator = null;
				sleepAnimation = null;
				onFireEffect = null;
				chargeAnimation = null;
				stasis = false;
				demolitions = 0;
			};
			
		case 17:	// Gunship.
			%randomMonster = new Sprite()
			{
				name = "Gunship";
				level = $gunshipBaseLevel;
				SceneLayer = $monsterLayer;
				graph = $monsterGraph;
				scenegraph = levelSceneGraph;
				Animation = "Sprites:GunshipIdleSouthAnimation";
				position = getTilePositionFromIndices(%xIndex, %yIndex);
				size = "8 8";
				visible = true;
				xIndex = %xIndex;
				yIndex = %yIndex;
				facing = $southDirection;
				currentHealth = $gunshipBaseHP;
				maxHealth = $gunshipBaseHP;
				currentActionPoints = $gunshipBaseAP;
				maximumActionPoints = $gunshipBaseAP;
				armorRating = $gunshipBaseAR;
				baseDamage = 2;
				attackModifier = $gunshipBaseAttack;
				evasion = $gunshipBaseEvasion;
				canBurrow = false;
				burrow = false;
				canRange = $gunshipBaseCanRange;
				defensiveCaster = false;
				range = $gunshipBaseRange;		// In Torque internal units - tiles are 4x4.
				hasBeenSpotted = 0;
				isActive = $MonstersStartActive;
				meleeDamageType = $gunshipBaseMeleeDamageType;
				rangeDamageType = $gunshipBaseRangeDamageType;
				baseMeleeDamage = $gunshipBaseMeleeDamage;
				baseRangeDamage = $gunshipBaseRangeDamage;
				isHuman = $gunshipBaseIsHuman;
				isRobot = $gunshipBaseIsRobot;
				isAlien = $gunshipBaseIsAlien;
				weapon = null;
				healthIndicator = null;
				sleepAnimation = null;
				onFireEffect = null;
				chargeAnimation = null;
				stasis = false;
				demolitions = 8;
			};
			
		case 18:	// Matrix.
			%randomMonster = new Sprite()
			{
				name = "Matrix";
				level = $MatrixBaseLevel;
				SceneLayer = $monsterLayer;
				graph = $monsterGraph;
				scenegraph = levelSceneGraph;
				Animation = "Sprites:MatrixIdleSouthAnimation";
				position = getTilePositionFromIndices(%xIndex, %yIndex);
				size = "8 8";
				visible = true;
				xIndex = %xIndex;
				yIndex = %yIndex;
				facing = $southDirection;
				currentHealth = $MatrixBaseHP;
				maxHealth = $MatrixBaseHP;
				currentActionPoints = $MatrixBaseAP;
				maximumActionPoints = $MatrixBaseAP;
				armorRating = $MatrixBaseAR;
				baseDamage = 2;
				attackModifier = $MatrixBaseAttack;
				evasion = $MatrixBaseEvasion;
				canBurrow = false;
				burrow = false;
				canRange = $MatrixBaseCanRange;
				defensiveCaster = false;
				range = $MatrixBaseRange;		// In Torque internal units - tiles are 4x4.
				hasBeenSpotted = 0;
				isActive = $MonstersStartActive;
				meleeDamageType = $MatrixBaseMeleeDamageType;
				rangeDamageType = $MatrixBaseRangeDamageType;
				baseMeleeDamage = $MatrixBaseMeleeDamage;
				baseRangeDamage = $MatrixBaseRangeDamage;
				isHuman = $MatrixBaseIsHuman;
				isRobot = $MatrixBaseIsRobot;
				isAlien = $MatrixBaseIsAlien;
				weapon = null;
				healthIndicator = null;
				sleepAnimation = null;
				onFireEffect = null;
				chargeAnimation = null;
				stasis = false;
				demolitions = 8;
			};
			
		case 19:	// Patriarch.
			%randomMonster = new Sprite()
			{
				name = "Patriarch";
				level = $PatriarchBaseLevel;
				SceneLayer = $monsterLayer;
				graph = $monsterGraph;
				scenegraph = levelSceneGraph;
				Animation = "Sprites:PatriarchIdleSouthAnimation";
				position = getTilePositionFromIndices(%xIndex, %yIndex);
				size = "4 4";
				visible = true;
				xIndex = %xIndex;
				yIndex = %yIndex;
				facing = $southDirection;
				currentHealth = $PatriarchBaseHP;
				maxHealth = $PatriarchBaseHP;
				currentActionPoints = $PatriarchBaseAP;
				maximumActionPoints = $PatriarchBaseAP;
				armorRating = $PatriarchBaseAR;
				baseDamage = 2;
				attackModifier = $PatriarchBaseAttack;
				evasion = $PatriarchBaseEvasion;
				canBurrow = false;
				burrow = false;
				canRange = $PatriarchBaseCanRange;
				defensiveCaster = false;
				range = $PatriarchBaseRange;		// In Torque internal units - tiles are 4x4.
				hasBeenSpotted = 0;
				isActive = $MonstersStartActive;
				meleeDamageType = $PatriarchBaseMeleeDamageType;
				rangeDamageType = $PatriarchBaseRangeDamageType;
				baseMeleeDamage = $PatriarchBaseMeleeDamage;
				baseRangeDamage = $PatriarchBaseRangeDamage;
				isHuman = $PatriarchBaseIsHuman;
				isRobot = $PatriarchBaseIsRobot;
				isAlien = $PatriarchBaseIsAlien;
				weapon = null;
				healthIndicator = null;
				sleepAnimation = null;
				onFireEffect = null;
				chargeAnimation = null;
				stasis = false;
				demolitions = 8;
			};
	}
	// Strip physics!
	%randomMonster.CollisionPhysicsReceieve = "0";
	%randomMonster.CollisionPhysicsSend = "0";
	// Lock in original unit sizes to account for rapid growing/shrinking!
	%randomMonster.originalSize = %randomMonster.size;
	%randomMonster = adjustMonsterForDifficulty(%randomMonster);
	addObjectToScene(%randomMonster);
	return %randomMonster;
}