// Handles Floating Text.
// Worthless Bums 2012.


// Test function for scrolling floating text.
function sft (%characterIndex)
{//echo("sft()");
	%target = $playerSquad[%characterIndex];
	%text = "-5";
	scrollFloatingText(%target, %text, 0);
}

// Calculates damage and accuracy of a character against a monster.
function calculateDamageAndAccuracy (%currentCharacter, %monster)
{//echo("calculateDamageAndAccuracy()");
	if (!isObject($playerSquad[%currentCharacter])	||
		!isObject(%monster))
	{
		return "0 0";	// Hack! Why doesn't %monster exist sometimes?
	}

	// Grab character weapon damage and accuracy
	%damage = ($playerSquad[%currentCharacter].weapon).damage;
	%attackRating = ($playerSquad[%currentCharacter].weapon).accuracy;
	
	// Check for Stat/Skill based weapon boosting effects!
	if ($playerSquad[%currentCharacter].arms > 0)
	{
		%damage += $playerSquad[%currentCharacter].arms;
		%attackRating += $playerSquad[%currentCharacter].arms * $armsAccuracyModifier;
	}
	
	// Check for weapon stat boosting effects!
	// NOTE: Should his be a separate function?
	// Check for weapon attachment.
	if ((($playerSquad[%currentCharacter]).laserSprite).image !$= "Sprites:Flashlight")
	{
		%attackRating += $laserSightAccuracyBonus;
		if ($playerSquad[%currentCharacter].perks $= "Sweeper")	// "Sweeper" perk grants bonus Laser Sight damage!
		{
			%damage += 2;
		}
	}
	if (isObject($mazeLiftedTiles[$playerSquad[%currentCharacter].xIndex, $playerSquad[%currentCharacter].yIndex])	&&
		!isObject($mazeLiftedTiles[%monster.xIndex, %monster.yIndex]))
	{//echo("HEIGHT BONUS!");
		%attackRating += $HeightAccuracyBonus;
	}
	else if (!isObject($mazeLiftedTiles[$playerSquad[%currentCharacter].xIndex, $playerSquad[%currentCharacter].yIndex])	&&
			 isObject($mazeLiftedTiles[%monster.xIndex, %monster.yIndex]))
	{//echo("HEIGHT PENALTY!");
		%attackRating -= $HeightAccuracyPenalty;
	}
	
	// Check for talent effects.
	// Leader.
	if ($squadStim)
	{
		%damage += $squadStimDamageBoost;
		%attackRating += $squadStimAccuracyBoost;
	}
	// Scout.
	if ($playerSquad[%currentCharacter].characterClass == 1)
	{
		%talents = $playerSquad[%currentCharacter].talents;
		if (getWord(%talents, 3) == 7)								// Biohazard.
		{
			%damage += $biohazardDamageBoost;
		}
	}
	// Support.
	if ($playerSquad[%currentCharacter].characterClass == 3)
	{
		if ($squadBunkerDown)
		{
			%attackRating += 10;
		}
		if ($squadSprayFire)
		{
			%damage *= 2;
			%attackRating /= 2;
		}
		if ($squadDoubleTap)
		{
			%attackRating += 10;
		}
		if ($squadHailMary)
		{
			%attackRating += 10;
		}
	}
	// Engineer.
	if ($playerSquad[%currentCharacter].characterClass == 4)
	{
		if (getWord($playerSquad[%currentCharacter].talents, 1) == 1	&&	// Stun Shots.
			%monster.isRobot)
		{
			%damage += $stunShotsDamageBoost;
		}
		if (getWord($playerSquad[%currentCharacter].talents, 5) == 1)		// Active Targeting.
		{
			%attackRating += $activeTargetingAccuracyBoost;
		}
	}
	// Check for squad effects that negate evasion first!
	if ($squadScoped	&&
		$playerSquad[%currentCharacter].characterClass == 1)
	{//echo("Scoped DETECTED!");
		%attackRating += $scopedAccuracyBoost;
		%damage += $scopedDamageBoost;
	}
	if ($playerSquad[%currentCharacter].xIndex == %monster.xIndex	&&
		mAbs($playerSquad[%currentCharacter].yIndex - %monster.yIndex) == ($playerSquad[%currentCharacter].weapon).range)
	{
		%attackRating = 100;
	}
	else if ($playerSquad[%currentCharacter].yIndex == %monster.yIndex	&&
			 mAbs($playerSquad[%currentCharacter].xIndex - %monster.xIndex) == ($playerSquad[%currentCharacter].weapon).range)
	{
		%attackRating = 100;
	}
	// Support class marines with the Sentry talent have a 100% chance to hit in Guard Mode!
	else if ($monsterTurnOngoing	&&
			 $playerSquad[%currentCharacter].guardMode	&&
			 $playerSquad[%currentCharacter].characterClass == 3	&&
			 getWord($playerSquad[%currentCharacter].talents, 5) == 1)
	{
		%attackRating = 100;
	}
	// Support class marines with the Sentry talent have a 100% chance to hit flank shots!
	else if (directionsFlank($playerSquad[%currentCharacter].facing, %monster.facing)	&&
			 $playerSquad[%currentCharacter].characterClass == 3	&&
			 getWord($playerSquad[%currentCharacter].talents, 7) == 1)
	{
		%attackRating = 100;
	}
	// "Close Combat" perk grants a 100% chance to hit adjacent enemies, even with ranged attacks!
	if ($playerSquad[%currentCharacter].perks $= "CloseCombat")
	{
		%adjacentMonsterIndex = getAdjacentFacingMonster($playerSquad[%currentCharacter]);
		if (%adjacentMonsterIndex != -1	&&
			%monster == $MonsterList.getObject(%adjacentMonsterIndex))
		{
			%attackRating = 100;
		}
	}
	// If the marine is a Support with the Shark Rounds talent.
	%effectiveArmorRating = %monster.armorRating;
	if ($playerSquad[%currentCharacter].characterClass == 3	&&
		getWord($playerSquad[%currentCharacter].talents, 3) == 1)
	{
		%effectiveArmorRating = mRound(%monster.armorRating * ((100 - $sharkRoundsIgnoreArmor) / 100));
	}
	// Reduce damage done by monster's armor rating.
	%damage -= %effectiveArmorRating;
	// Make sure damage doesn't "heal" the enemy! Floor damage at 0.
	if (%damage < 0)
	{
		%damage = 0;
	}
	
	if (%attackRating > 100)
	{
		%attackRating = 100;
	}
	
	// Return damage and accuracy.
	return %damage SPC %attackRating;
}

// Handles floating text for fire control toggle.
function fireControlFloatingText (%monster)
{//echo("fireControlFloatingText()");
	// Grab active character weapon.
	%currentCharacter = $activeCharacter;
	%weapon = $playerSquad[%currentCharacter].weapon;
	// Calculate modifed damage and accuracy against the monster.
	%calculatedDamageAndAccuracy = calculateDamageAndAccuracy(%currentCharacter, %monster);
	%damage = getWord(%calculatedDamageAndAccuracy, 0);
	%attackRating = getWord(%calculatedDamageAndAccuracy, 1);
	
	// Compose texts.
	%damageText = %damage;
	%accuracyText = %attackRating;
	
	// Set MonsterTargetStatsText text for Monster Target Panel!
	%damageTextColor = "";//"\c2";
	%accuracyTextColor = "";//"\c3";
	%maxRangeInfoTextColor = "";//"\c6";
	if (%attackRating >= 100)
	{
		%accuracyTextColor = "";//"\c5";
	}
	%fireKeybind = strreplace($PrimaryBind, "keyboard", "");
	%fireKeybind = strreplace(%fireKeybind, "keyboard ", "");
	%fireKeybind = strreplace(%fireKeybind, "keyboard\t", "");
	%fireKeybind = strreplace(%fireKeybind, " ", "");
	%statsText = "";
	if (%attackRating >= 100)
	{
		%statsText = "Tap [" @ %fireKeybind @ "] to fire."													NL
					 %damageTextColor @ %damage SPC "damage," @ %accuracyTextColor SPC %attackRating @ "%";
	}
	else
	{
		%statsText = "Tap [" @ %fireKeybind @ "] to fire."													NL
					 %damageTextColor @ %damage SPC "damage," @ %accuracyTextColor SPC %attackRating @ "%"	NL
					 %maxRangeInfoTextColor @ "Accuracy is 100%"											NL
					 %maxRangeInfoTextColor @ "at max range (" @ ($playerSquad[$activeCharacter].weapon).range @ ")";
	}
	MonsterTargetStatsText.setText(%statsText);
	return true;
}
// Deletes the current fire control floating text.
function deleteFireControlFloatingText ()
{//echo("deleteFireControlFloatingText()");
	if (isObject($fireControlDamageFloatingText))
	{
		$fireControlDamageFloatingText.setLifetime(0.0);
		$fireControlDamageFloatingText.safeDelete();
	}
	if (isObject($fireControlAccuracyFloatingText))
	{
		$fireControlAccuracyFloatingText.setLifetime(0.0);
		$fireControlAccuracyFloatingText.safeDelete();
	}
}

// Scrolls some floating text up from the specified target.
function scrollFloatingText (%target, %text, %textType, %hitType)
{//echo("scrollFloatingText()");
//echo("%text =" SPC %text);
//echo("%textType =" SPC %textType);
//echo("%hitType =" SPC %hitType);
	if (!isObject(%target))
	{
		return;
	}
	// Default text color is red.
	%textColor = "20 0 0";
	// Change "damage" popups depending on damage types!
	switch$ (%textType)
	{
		case "physical":
			%textColor = "20 0 0";
			%textType = "damage";
			
		case "fire":
			%textColor = "20 0 0";
			%textType = "damage";
			
		case "frost":
			%textColor = "0 0 20";
			%textType = "damage";
			
		case "acid":
			%textColor = "0 20 0";
			%textType = "damage";
			
		case "explosive":
			%textColor = "20 20 0";
			%textType = "damage";
			
		case "electricity":
			%textColor = "0 0 20";
			%textType = "damage";
			
		case "ammoCounter":
			%textColor = "255 255 0";
			%textType = "ammoCounter";
	}
	
	// Set position.
	%xPosition = getWord(%target.getPosition(), 0);
	%yPosition = getWord(%target.getPosition(), 1);
	
	// Hit Type switch (e.g. crit).
	switch$ (%hitType)
	{
		case "crit":
			%floatingCritText = new ImageFont();
			%floatingCritText.SceneLayer = $RenderedFontSceneLayer;
			%floatingCritText.Image = $RenderedFontImage;
			%floatingCritText.FontSize = $RenderedFontSize;
			%floatingCritText.BlendColor = "255 255 255";
			%floatingCritText.Text = %hitType;
			%floatingCritText.Position = %xPosition SPC %yPosition + 3;
			addObjectToScene(%floatingCritText);
			
			//%floatingCritText.moveTo(%xPosition, %yPosition - 2, 10.0, true, false);
			%floatingCritText.setLifetime(0.5);
			
		case "ammoCounter":
			if (isObject($floatingAmmoCounterText))
			{
				$floatingAmmoCounterText.safeDelete();
			}
			$floatingAmmoCounterText = new ImageFont();
			$floatingAmmoCounterText.SceneLayer = $RenderedFontSceneLayer;
			$floatingAmmoCounterText.Image = $RenderedFontImage;
			$floatingAmmoCounterText.FontSize = $RenderedFontSize;
			$floatingAmmoCounterText.BlendColor = %textColor;
			$floatingAmmoCounterText.Text = %text SPC "ammo left!";
			$floatingAmmoCounterText.Position = %xPosition SPC %yPosition - 2;
			addObjectToScene($floatingAmmoCounterText);
			
			//$floatingAmmoCounterText.mount($playerSquad[$activeCharacter], 0.0, 1.7, 50.0, true, false, true, true);
			$floatingAmmoCounterText.setLifetime(1.5);
	}
	
	// Switch by text type.
	switch$ (%textType)
	{
		case "damage":
			%floatingText = new ImageFont();
			%floatingText.SceneLayer = $RenderedFontSceneLayer;
			%floatingText.Image = $RenderedFontImage;
			%floatingText.FontSize = $RenderedFontSize;
			%floatingText.BlendColor = %textColor;
			%floatingText.Text = %text;
			%floatingText.Position = %xPosition SPC %yPosition + 2;
			addObjectToScene(%floatingText);
			
		case "miss":
			%floatingText = new ImageFont();
			%floatingText.SceneLayer = $RenderedFontSceneLayer;
			%floatingText.Image = $RenderedFontImage;
			%floatingText.FontSize = $RenderedFontSize;
			%floatingText.BlendColor = "255 255 255";
			%floatingText.Text = %text;
			%floatingText.Position = %xPosition SPC %yPosition + 2;
			addObjectToScene(%floatingText);
			
		case "flank":
			%floatingText = new ImageFont();
			%floatingText.SceneLayer = $RenderedFontSceneLayer;
			%floatingText.Image = $RenderedFontImage;
			%floatingText.FontSize = $RenderedFontSize;
			%floatingText.BlendColor = "255 255 0";
			%floatingText.Text = %textType;
			%floatingText.Position = %xPosition SPC %yPosition + 3;
			addObjectToScene(%floatingText);
			
		case "apLoss":
			////%floatingText.moveTo(%xPosition, %yPosition + 2, 10.0, true, false);
			%floatingText.setLifetime(0.5);
			%floatingText = new ImageFont();
			%floatingText.SceneLayer = $RenderedFontSceneLayer;
			%floatingText.Image = $RenderedFontImage;
			%floatingText.FontSize = $RenderedFontSize;
			%floatingText.BlendColor = "255 0 255";
			%floatingText.Text = %text;
			%floatingText.Position = %xPosition SPC %yPosition - 1;
			addObjectToScene(%floatingText);
			%floatingText.setLifetime(0.5);
			return;
			
		case "arLoss":
			%floatingText = new ImageFont();
			%floatingText.SceneLayer = $RenderedFontSceneLayer;
			%floatingText.Image = $RenderedFontImage;
			%floatingText.FontSize = $RenderedFontSize;
			%floatingText.BlendColor = "0 20 0";
			%floatingText.Text = %text;
			%floatingText.Position = %xPosition SPC %yPosition - 1;
			addObjectToScene(%floatingText);
			////%floatingText.moveTo(%xPosition, %yPosition + 2, 10.0, true, false);
			%floatingText.setLifetime(0.5);
			return;
			
		case "regen":
			%floatingText = new ImageFont();
			%floatingText.SceneLayer = $RenderedFontSceneLayer;
			%floatingText.Image = $RenderedFontImage;
			%floatingText.FontSize = $RenderedFontSize;
			%floatingText.BlendColor = "0 20 0";
			%floatingText.Text = %text;
			%floatingText.Position = %xPosition SPC %yPosition + 1;
			addObjectToScene(%floatingText);
			
		case "talent":
			// Select text color based on active character.
			%textColor = "20 0 0";
			switch ($playerSquad[$activeCharacter].characterClass)
			{
				case 0:	%textColor = "0 1 0";
				case 1:	%textColor = "1 0 1";
				case 2:	%textColor = "0 0 1";
				case 3:	%textColor = "1 0 0";
				case 4:	%textColor = "1 1 0";
			}
			%floatingText = new ImageFont();
			%floatingText.SceneLayer = $RenderedFontSceneLayer;
			%floatingText.Image = $RenderedFontImage;
			%floatingText.FontSize = $RenderedFontSize;
			%floatingText.BlendColor = %textColor;
			%floatingText.Text = %text;
			%floatingText.Position = %xPosition SPC %yPosition + 2;
			addObjectToScene(%floatingText);
	}
	
	if (isObject(%floatingText))
	{
		////%floatingText.moveTo(%xPosition, %yPosition - 2, 10.0, true, false);
		%floatingText.setLifetime(0.5);
	}
}

// Scrolling (additional) info text on a unit!
function scrollInfoText (%target, %info)
{//echo("scrollInfoText()");
	scrollInfoTextWithBuffer(%target, %info, 5.0);
}
function scrollInfoTextWithBuffer (%target, %info, %verticalBuffer)
{//echo("scrollInfoTextWithBuffer()");
	%text = %info;
	%textType = "dialogue";
	%xPosition = getWord(%target.getPosition(), 0);
	%yPosition = getWord(%target.getPosition(), 1);
	if (isObject(%target.tInfoPopup))
	{
		(%target.tInfoPopup).safedelete();
	}
	%moveSpeed = 12.0;
	%lifetime = 6.0;
	%foregroundSceneLayer = 0;
	%foregroundTextColor = "255 255 255";
	%backgroundSceneLayer = 0;
	%backgroundTextColor = "0 1 0 0.35";
	// Delete background text.
	if (isObject(%target.tInfoBackgroundPopup))
	{
		(%target.tInfoBackgroundPopup).safeDelete();
	}
	if (isObject(%target.tInfoBackgroundPopup2))
	{
		(%target.tInfoBackgroundPopup2).safeDelete();
	}
	if (isObject(%target.tInfoBackgroundPopup3))
	{
		(%target.tInfoBackgroundPopup3).safeDelete();
	}
	if (isObject(%target.tInfoBackgroundPopup4))
	{
		(%target.tInfoBackgroundPopup4).safeDelete();
	}
	// Up.
	switch$ (%textType)
	{
		case "dialogue":
			%backgroundFloatingText = new ImageFont();
			%backgroundFloatingText.SceneLayer = $RenderedFontSceneLayer;
			%backgroundFloatingText.Image = $RenderedFontImage;
			%backgroundFloatingText.FontSize = $RenderedFontSize;
			%backgroundFloatingText.BlendColor = %backgroundTextColor;
			%backgroundFloatingText.Text = %text;
			%backgroundFloatingText.Position = %xPosition SPC %yPosition - 2.0 + $RenderedFontOutlinePadding;
			addObjectToScene(%backgroundFloatingText);
			%target.tInfoBackgroundPopup = %backgroundFloatingText;
	}
	//%backgroundFloatingText.moveTo(%xPosition, %yPosition - 2.1 + %verticalBuffer, %moveSpeed, true, false);
	%backgroundFloatingText.setLifetime(%lifetime);
	// Down.
	switch$ (%textType)
	{
		case "dialogue":
			%backgroundFloatingText2 = new ImageFont();
			%backgroundFloatingText2.SceneLayer = $RenderedFontSceneLayer;
			%backgroundFloatingText2.Image = $RenderedFontImage;
			%backgroundFloatingText2.FontSize = $RenderedFontSize;
			%backgroundFloatingText2.BlendColor = %backgroundTextColor;
			%backgroundFloatingText2.Text = %text;
			%backgroundFloatingText2.Position = %xPosition SPC %yPosition - 2.0 - $RenderedFontOutlinePadding;
			addObjectToScene(%backgroundFloatingText2);
			%target.tInfoBackgroundPopup2 = %backgroundFloatingText2;
	}
	//%backgroundFloatingText2.moveTo(%xPosition, %yPosition - 1.9 + %verticalBuffer, %moveSpeed, true, false);
	%backgroundFloatingText2.setLifetime(%lifetime);
	// Left.
	switch$ (%textType)
	{
		case "dialogue":
			%backgroundFloatingText3 = new ImageFont();
			%backgroundFloatingText3.SceneLayer = $RenderedFontSceneLayer;
			%backgroundFloatingText3.Image = $RenderedFontImage;
			%backgroundFloatingText3.FontSize = $RenderedFontSize;
			%backgroundFloatingText3.BlendColor = %backgroundTextColor;
			%backgroundFloatingText3.Text = %text;
			%backgroundFloatingText3.Position = %xPosition - $RenderedFontOutlinePadding SPC %yPosition - 2.0;
			addObjectToScene(%backgroundFloatingText3);
			%target.tInfoBackgroundPopup3 = %backgroundFloatingText3;
	}
	//%backgroundFloatingText3.moveTo(%xPosition - 0.1, %yPosition - 2.0 + %verticalBuffer, %moveSpeed, true, false);
	%backgroundFloatingText3.setLifetime(%lifetime);
	// Right.
	switch$ (%textType)
	{
		case "dialogue":
			%backgroundFloatingText4 = new ImageFont();
			%backgroundFloatingText4.SceneLayer = $RenderedFontSceneLayer;
			%backgroundFloatingText4.Image = $RenderedFontImage;
			%backgroundFloatingText4.FontSize = $RenderedFontSize;
			%backgroundFloatingText4.BlendColor = %backgroundTextColor;
			%backgroundFloatingText4.Text = %text;
			%backgroundFloatingText4.Position = %xPosition + $RenderedFontOutlinePadding SPC %yPosition - 2.0;
			addObjectToScene(%backgroundFloatingText4);
			%target.tInfoBackgroundPopup4 = %backgroundFloatingText4;
	}
	//%backgroundFloatingText4.moveTo(%xPosition + 0.1, %yPosition - 2.0 + %verticalBuffer, %moveSpeed, true, false);
	%backgroundFloatingText4.setLifetime(%lifetime);
	
	switch$ (%textType)
	{
		case "dialogue":
			%floatingText = new ImageFont();
			%floatingText.SceneLayer = $RenderedFontSceneLayer;
			%floatingText.Image = $RenderedFontImage;
			%floatingText.FontSize = $RenderedFontSize;
			%floatingText.BlendColor = %foregroundTextColor;
			%floatingText.Text = %text;
			%floatingText.Position = %xPosition SPC %yPosition - 2.0;
			addObjectToScene(%floatingText);
			%target.tInfoPopup = %floatingText;
	}
	//%floatingText.moveTo(%xPosition, %yPosition - 2 + %verticalBuffer, %moveSpeed, true, false);
	%floatingText.setLifetime(%lifetime);
}
// Scrolling (additional) info description text on a unit!
function scrollInfoDescriptionText (%target, %info)
{//echo("scrollInfoDescriptionText()");
	scrollInfoDescriptionTextWithBuffer(%target, %info, 6.0);
}
function scrollInfoDescriptionTextWithBuffer (%target, %info, %verticalBuffer)
{//echo("scrollInfoDescriptionTextWithBuffer()");
	%text = %info;
	%textType = "dialogue";
	%xPosition = getWord(%target.getPosition(), 0);
	%yPosition = getWord(%target.getPosition(), 1);
	if (isObject(%target.tInfoDescriptionPopup))
	{
		(%target.tInfoDescriptionPopup).safedelete();
	}
	%moveSpeed = 12.0;
	%lifetime = 6.0;
	%foregroundSceneLayer = 0;
	%foregroundTextColor = "255 255 255";
	%backgroundSceneLayer = 0;
	%backgroundTextColor = "1 1 0 0.2";
	// Delete background text.
	if (isObject(%target.tInfoDescriptionBackgroundPopup))
	{
		(%target.tInfoDescriptionBackgroundPopup).safeDelete();
	}
	if (isObject(%target.tInfoDescriptionBackgroundPopup2))
	{
		(%target.tInfoDescriptionBackgroundPopup2).safeDelete();
	}
	if (isObject(%target.tInfoDescriptionBackgroundPopup3))
	{
		(%target.tInfoDescriptionBackgroundPopup3).safeDelete();
	}
	if (isObject(%target.tInfoDescriptionBackgroundPopup4))
	{
		(%target.tInfoDescriptionBackgroundPopup4).safeDelete();
	}
	// Up.
	switch$ (%textType)
	{
		case "dialogue":
			%backgroundFloatingText = new ImageFont();
			%backgroundFloatingText.SceneLayer = $RenderedFontSceneLayer;
			%backgroundFloatingText.Image = $RenderedFontImage;
			%backgroundFloatingText.FontSize = $RenderedFontSize;
			%backgroundFloatingText.BlendColor = %backgroundTextColor;
			%backgroundFloatingText.Text = %text;
			%backgroundFloatingText.Position = getWord(%target.position, 0) SPC getWord(%target.position, 1) + 2.0 - $RenderedFontOutlinePadding;
			addObjectToScene(%backgroundFloatingText);
			%target.tInfoDescriptionBackgroundPopup = %backgroundFloatingText;
	}
	//%backgroundFloatingText.moveTo(%xPosition, %yPosition - 2.1 + %verticalBuffer, %moveSpeed, true, false);
	%backgroundFloatingText.setLifetime(%lifetime);
	// Down.
	switch$ (%textType)
	{
		case "dialogue":
			%backgroundFloatingText2 = new ImageFont();
			%backgroundFloatingText2.SceneLayer = $RenderedFontSceneLayer;
			%backgroundFloatingText2.Image = $RenderedFontImage;
			%backgroundFloatingText2.FontSize = $RenderedFontSize;
			%backgroundFloatingText2.BlendColor = %backgroundTextColor;
			%backgroundFloatingText2.Text = %text;
			%backgroundFloatingText2.Position = getWord(%target.position, 0) SPC getWord(%target.position, 1) + 2.0 + $RenderedFontOutlinePadding;
			addObjectToScene(%backgroundFloatingText2);
			%target.tInfoDescriptionBackgroundPopup2 = %backgroundFloatingText2;
	}
	//%backgroundFloatingText2.moveTo(%xPosition, %yPosition - 1.9 + %verticalBuffer, %moveSpeed, true, false);
	%backgroundFloatingText2.setLifetime(%lifetime);
	// Left.
	switch$ (%textType)
	{
		case "dialogue":
			%backgroundFloatingText3 = new ImageFont();
			%backgroundFloatingText3.SceneLayer = $RenderedFontSceneLayer;
			%backgroundFloatingText3.Image = $RenderedFontImage;
			%backgroundFloatingText3.FontSize = $RenderedFontSize;
			%backgroundFloatingText3.BlendColor = %backgroundTextColor;
			%backgroundFloatingText3.Text = %text;
			%backgroundFloatingText3.Position = getWord(%target.position, 0) - $RenderedFontOutlinePadding SPC getWord(%target.position, 1) + 2.0;
			addObjectToScene(%backgroundFloatingText3);
			%target.tInfoDescriptionBackgroundPopup3 = %backgroundFloatingText3;
	}
	//%backgroundFloatingText3.moveTo(%xPosition - 0.1, %yPosition - 2.0 + %verticalBuffer, %moveSpeed, true, false);
	%backgroundFloatingText3.setLifetime(%lifetime);
	// Right.
	switch$ (%textType)
	{
		case "dialogue":
			%backgroundFloatingText4 = new ImageFont();
			%backgroundFloatingText4.SceneLayer = $RenderedFontSceneLayer;
			%backgroundFloatingText4.Image = $RenderedFontImage;
			%backgroundFloatingText4.FontSize = $RenderedFontSize;
			%backgroundFloatingText4.BlendColor = %backgroundTextColor;
			%backgroundFloatingText4.Text = %text;
			%backgroundFloatingText4.Position = getWord(%target.position, 0) + $RenderedFontOutlinePadding SPC getWord(%target.position, 1) + 2.0;
			addObjectToScene(%backgroundFloatingText4);
			%target.tInfoDescriptionBackgroundPopup4 = %backgroundFloatingText4;
	}
	//%backgroundFloatingText4.moveTo(%xPosition + 0.1, %yPosition - 2.0 + %verticalBuffer, %moveSpeed, true, false);
	%backgroundFloatingText4.setLifetime(%lifetime);
	
	switch$ (%textType)
	{
		case "dialogue":
			%floatingText = new ImageFont();
			%floatingText.SceneLayer = $RenderedFontSceneLayer;
			%floatingText.Image = $RenderedFontImage;
			%floatingText.FontSize = $RenderedFontSize;
			%floatingText.BlendColor = %foregroundTextColor;
			%floatingText.Text = %text;
			%floatingText.Position = getWord(%target.position, 0) SPC getWord(%target.position, 1) + 2.0;
			addObjectToScene(%floatingText);
			%target.tInfoDescriptionPopup = %floatingText;
	}
	//%floatingText.moveTo(%xPosition, %yPosition - 2 + %verticalBuffer, %moveSpeed, true, false);
	%floatingText.setLifetime(%lifetime);
}

// Scrolls money gain text.
function scrollMoneyGain (%target, %credits)
{//echo("scrollMoneyGain()");
	%text = "Found " @ %credits @ " credits!";
	%textType = "dialogue";
	%xPosition = getWord(%target.getPosition(), 0);
	%yPosition = getWord(%target.getPosition(), 1);
	if (isObject(%target.tdialoguePopup))
	{
		(%target.tdialoguePopup).safedelete();
	}
	
	%moveSpeed = 12.0;
	%lifetime = 2.0;
	%foregroundSceneLayer = 0;
	%foregroundTextColor = "255 255 255";
	%backgroundSceneLayer = 0;
	%backgroundTextColor = "1 0 1 0.5";
	%verticalBuffer = -0.75;
	// Delete background text.
	if (isObject(%target.tdialogueBackgroundPopup))
	{
		(%target.tdialogueBackgroundPopup).safeDelete();
	}
	if (isObject(%target.tdialogueBackgroundPopup2))
	{
		(%target.tdialogueBackgroundPopup2).safeDelete();
	}
	if (isObject(%target.tdialogueBackgroundPopup3))
	{
		(%target.tdialogueBackgroundPopup3).safeDelete();
	}
	if (isObject(%target.tdialogueBackgroundPopup4))
	{
		(%target.tdialogueBackgroundPopup4).safeDelete();
	}
	// Up.
	switch$ (%textType)
	{
		case "dialogue":
			%backgroundFloatingText = new ImageFont();
			%backgroundFloatingText.SceneLayer = $RenderedFontSceneLayer;
			%backgroundFloatingText.Image = $RenderedFontImage;
			%backgroundFloatingText.FontSize = $RenderedFontSize;
			%backgroundFloatingText.BlendColor = %backgroundTextColor;
			%backgroundFloatingText.Text = %text;
			%backgroundFloatingText.Position = %xPosition SPC %yPosition + %verticalBuffer + $RenderedFontOutlinePadding;
			addObjectToScene(%backgroundFloatingText);
			%target.tdialogueBackgroundPopup = %backgroundFloatingText;
	}
	//%backgroundFloatingText.moveTo(%xPosition, %yPosition - 2.1, %moveSpeed, true, false);
	%backgroundFloatingText.setLifetime(%lifetime);
	// Down.
	switch$ (%textType)
	{
		case "dialogue":
			%backgroundFloatingText2 = new ImageFont();
			%backgroundFloatingText2.SceneLayer = $RenderedFontSceneLayer;
			%backgroundFloatingText2.Image = $RenderedFontImage;
			%backgroundFloatingText2.FontSize = $RenderedFontSize;
			%backgroundFloatingText2.BlendColor = %backgroundTextColor;
			%backgroundFloatingText2.Text = %text;
			%backgroundFloatingText2.Position = %xPosition SPC %yPosition + %verticalBuffer - $RenderedFontOutlinePadding;
			addObjectToScene(%backgroundFloatingText2);
			%target.tdialogueBackgroundPopup2 = %backgroundFloatingText2;
	}
	//%backgroundFloatingText2.moveTo(%xPosition, %yPosition - 1.9, %moveSpeed, true, false);
	%backgroundFloatingText2.setLifetime(%lifetime);
	// Left.
	switch$ (%textType)
	{
		case "dialogue":
			%backgroundFloatingText3 = new ImageFont();
			%backgroundFloatingText3.SceneLayer = $RenderedFontSceneLayer;
			%backgroundFloatingText3.Image = $RenderedFontImage;
			%backgroundFloatingText3.FontSize = $RenderedFontSize;
			%backgroundFloatingText3.BlendColor = %backgroundTextColor;
			%backgroundFloatingText3.Text = %text;
			%backgroundFloatingText3.Position = %xPosition - $RenderedFontOutlinePadding SPC %yPosition + %verticalBuffer;
			addObjectToScene(%backgroundFloatingText3);
			%target.tdialogueBackgroundPopup3 = %backgroundFloatingText3;
	}
	//%backgroundFloatingText3.moveTo(%xPosition - 0.1, %yPosition - 2.0, %moveSpeed, true, false);
	%backgroundFloatingText3.setLifetime(%lifetime);
	// Right.
	switch$ (%textType)
	{
		case "dialogue":
			%backgroundFloatingText4 = new ImageFont();
			%backgroundFloatingText4.SceneLayer = $RenderedFontSceneLayer;
			%backgroundFloatingText4.Image = $RenderedFontImage;
			%backgroundFloatingText4.FontSize = $RenderedFontSize;
			%backgroundFloatingText4.BlendColor = %backgroundTextColor;
			%backgroundFloatingText4.Text = %text;
			%backgroundFloatingText4.Position = %xPosition + $RenderedFontOutlinePadding SPC %yPosition + %verticalBuffer;
			addObjectToScene(%backgroundFloatingText4);
			%target.tdialogueBackgroundPopup4 = %backgroundFloatingText4;
	}
	//%backgroundFloatingText4.moveTo(%xPosition + 0.1, %yPosition - 2.0, %moveSpeed, true, false);
	%backgroundFloatingText4.setLifetime(%lifetime);
	
	switch$ (%textType)
	{
		case "dialogue":
			%floatingText = new ImageFont();
			%floatingText.SceneLayer = $RenderedFontSceneLayer;
			%floatingText.Image = $RenderedFontImage;
			%floatingText.FontSize = $RenderedFontSize;
			%floatingText.BlendColor = %foregroundTextColor;
			%floatingText.Text = %text;
			%floatingText.Position = %xPosition SPC %yPosition + %verticalBuffer;
			addObjectToScene(%floatingText);
			%target.tdialoguePopup = %floatingText;
	}
	//%floatingText.moveTo(%xPosition, %yPosition - 2, %moveSpeed, true, false);
	%floatingText.setLifetime(%lifetime);
}

// Updates health and action point floating text for all squad members.
function updateSquadMemberFloatingText ()
{//echo("updateSquadMemberFloatingText()");
	updateSquadMemberFloatingHealthPoints();
	updateSquadMemberFloatingActionPoints();
}

// Updates health and action point floating text for all monsters.
function updateMonsterFloatingText ()
{//echo("updateMonsterFloatingText()");
	updateAllMonstersFloatingHealthPointText();
	updateAllMonstersFloatingActionPointText();
}

// Updates all squad members' floating health points.
function updateSquadMemberFloatingHealthPoints ()
{//echo("updateSquadMemberFloatingHealthPoints()");
	if ($leaderPersist)
	{
		updateFloatingHealthPointText(0);
	}
	if ($scoutPersist)
	{
		updateFloatingHealthPointText(1);
	}
	if ($grenadierPersist)
	{
		updateFloatingHealthPointText(2);
	}
	if ($supportPersist)
	{
		updateFloatingHealthPointText(3);
	}
}
// Places health points text on specified character.
function updateFloatingHealthPointText (%characterIndex)
{//echo("updateFloatingHealthPointText()");
//return;		// Uncomment for trailer footage!
	// Compose target and text.
	%target = $playerSquad[%characterIndex];
	%text = %target.currentHealth;
	
	// Delete any old floatingHPText.
	if (isObject(%target.floatingHPText))
	{
		(%target.floatingHPText).safeDelete();
	}
	
	// Color HP text to indicate level of health!
	if (%target.currentHealth <= %target.maxHealth * 0.33)
	{
		%textColor = $HpMortalTextColor;
	}
	else if (%target.currentHealth < %target.maxHealth)
	{//echo("wounded!");
		%textColor = $HpWoundedTextColor;
	}
	else
	{//echo("not wounded!");
		%textColor = $HpTextColor;
	}
	//%textColor = $HpTextColor;		// Short circuit hp text change for now - hard to see with active character indicator!
	
	// Create floating text control.
	%target.floatingHPText = new ImageFont();
	%target.floatingHPText.SceneLayer = $RenderedFontSceneLayer;
	%target.floatingHPText.Image = $RenderedFontImage;
	%target.floatingHPText.FontSize = $RenderedFontSize;
	%target.floatingHPText.BlendColor = %textColor;
	%target.floatingHPText.Text = %text;
	%target.floatingHPText.Position = getWord(%target.position, 0) - 1.5 SPC getWord(%target.position, 1) + $GlobalVerticalShift / 2;
	addObjectToScene(%target.floatingHPText);
	if (%text $= "0")
	{
		(%target.floatingHPText).safeDelete();
	}
}

// Updates all squad members' floating action points.
function updateSquadMemberFloatingActionPoints ()
{//echo("updateSquadMemberFloatingActionPoints()");
	if ($leaderPersist)
	{
		updateFloatingActionPointText(0);
	}
	if ($scoutPersist)
	{
		updateFloatingActionPointText(1);
	}
	if ($grenadierPersist)
	{
		updateFloatingActionPointText(2);
	}
	if ($supportPersist)
	{
		updateFloatingActionPointText(3);
	}
}
// Places action points text on specified character.
function updateFloatingActionPointText (%characterIndex)
{//echo("updateFloatingActionPointText()");echo("%characterIndex =" SPC %characterIndex);
//return;		// Uncomment for trailer footage!
	// Compose target and text.
	%target = $playerSquad[%characterIndex];
	if (!isObject(%target))
	{
		return;
	}
	%text = $playerSquad[%characterIndex].currentActionPoints;
	if (!isObject(%target.floatingAPText))
	{
		%target.floatingAPText = new ImageFont();
		%target.floatingAPText.SceneLayer = $RenderedFontSceneLayer;
		%target.floatingAPText.Image = $RenderedFontImage;
		%target.floatingAPText.FontSize = $RenderedFontSize;
		%target.floatingAPText.BlendColor = $ApTextColor;
		addObjectToScene(%target.floatingAPText);
	}
	%target.floatingAPText.Text = %text;
	%target.floatingAPText.Position = getWord(%target.position, 0) - 1.5 SPC getWord(%target.position, 1) - 1.0 + $GlobalVerticalShift / 2;
}

// Updates all monsters' health point text.
function updateAllMonstersFloatingHealthPointText ()
{//echo("updateAllMonstersFloatingHealthPointText()");
	// Loop through all monsters.
	for (%i = 0; %i < $monsterList.getCount(); %i++)
	{
		// Update the monster's health point floating text.
		updateMonsterFloatingHealthPointText(%i);
	}
}
// Places health points text on specified monster.
function updateMonsterFloatingHealthPointText (%monsterIndex)
{//echo("updateMonsterFloatingHealthPointText()");
//return;		// Uncomment for trailer footage!
	// Compose target and text.
	%target = $monsterList.getObject(%monsterIndex);
	%text = %target.currentHealth;
	
	if (!isObject(%target))
	{
		return;
	}
	
	// Color HP text to indicate level of health!
	%textColor = "0 1 0 1";
	if (%target.currentHealth <= %target.maxHealth * 0.33)
	{
		%textColor = $HpMortalTextColor;
	}
	else if (%target.currentHealth < %target.maxHealth)
	{//echo("wounded!");
		%textColor = $HpWoundedTextColor;
	}
	else
	{//echo("not wounded!");
		%textColor = $HpTextColor;
	}
	
	// Check if floating text exists.
	if (!isObject(%target.floatingHPText))
	{
		%target.floatingHPText = new ImageFont();
		%target.floatingHPText.SceneLayer = $RenderedFontSceneLayer + 1;
		%target.floatingHPText.Image = $RenderedFontImage;
		%target.floatingHPText.FontSize = $RenderedFontSize;
		%target.floatingHPText.BlendColor = $HpTextColor;
		addObjectToScene(%target.floatingHPText);
	}
	%target.floatingHPText.Text = %text;
	if (%text $= "0")
	{
		(%target.floatingHPText).safeDelete();
	}
	%target.floatingHPText.Position = getWord(%target.position, 0) - 1.5 SPC getWord(%target.position, 1) + $GlobalVerticalShift / 2;
}

// Updates all monsters' action point text.
function updateAllMonstersFloatingActionPointText ()
{//echo("updateAllMonstersFloatingActionPointText()");
//return;		// Uncomment for trailer footage!
	// Loop through all monsters.
	for (%i = 0; %i < $monsterList.getCount(); %i++)
	{
		// Update the monster's action point floating text.
		updateMonsterFloatingActionPointText(%i);
	}
}
// Places action points text on specified monster.
function updateMonsterFloatingActionPointText (%monsterIndex)
{//echo("updateMonsterFloatingActionPointText()");
	%target = $monsterList.getObject(%monsterIndex);
	%text = %target.currentActionPoints;
	if (!isObject(%target.floatingAPText))
	{
		%target.floatingAPText = new ImageFont();
		%target.floatingAPText.SceneLayer = $RenderedFontSceneLayer + 1;
		%target.floatingAPText.Image = $RenderedFontImage;
		%target.floatingAPText.FontSize = $RenderedFontSize;
		%target.floatingAPText.BlendColor = $ApTextColor;
		addObjectToScene(%target.floatingAPText);
	}
	%target.floatingAPText.Text = %text;
	%target.floatingAPText.Position = getWord(%target.position, 0) - 1.5 SPC getWord(%target.position, 1) - 1.0 + $GlobalVerticalShift / 2;
}
function updateUnitHPAPPositions (%unit)
{//echo("updateUnitHPAPPositions()");
	%unit.floatingHPText.position = getWord(%unit.position, 0) - 1.5 SPC getWord(%unit.position, 1) + $GlobalVerticalShift / 2;
	%unit.floatingAPText.position = getWord(%unit.position, 0) - 1.5 SPC getWord(%unit.position, 1) - 1.0 + $GlobalVerticalShift / 2;
}
function updateUnitIndicatorPosition ()
{//echo("updateUnitIndicatorPosition()");
	%unit = $playerSquad[$activeCharacter];
	%verticalBuffer = 1.0;
	if (isLargeUnit(%unit))
	{
		%verticalBuffer = 0.75;
	}
	$indicatorAnimation.position = getWord(%unit.position, 0) SPC getWord(%unit.position, 1) + %verticalBuffer;
}
function updateUnitPromotionIndicatorPosition ()
{//echo("updateUnitPromotionIndicatorPosition()");
	if (isObject($playerSquad[$activeCharacter].promotionAnimation))
	{
		%unit = $playerSquad[$activeCharacter];
		%verticalBuffer = 1.0;
		if (isLargeUnit(%unit))
		{
			%verticalBuffer = 0.75;
		}
		$playerSquad[$activeCharacter].promotionAnimation.position = getWord(%unit.position, 0) SPC getWord(%unit.position, 1) + %verticalBuffer;
	}
}