Issue #1084 - Allow choosing target tile for meleeing adjacent targets (#1106)

* Issue #1084 - moving melee attacks can now choose the attack tile for adjacent targets.

* Implement requested changes.

* Update X2WOTCCommunityHighlander/Src/XComGame/Classes/X2MeleePathingPawn.uc

Co-authored-by: Xymanek <8d900e611b3c39c901bf75d424e86630eaa3a229@outlook.com>

* Update X2WOTCCommunityHighlander/Src/XComGame/Classes/X2MeleePathingPawn.uc

Co-authored-by: Xymanek <8d900e611b3c39c901bf75d424e86630eaa3a229@outlook.com>

* Fix adjacent attacks against targets on or near slopes and stairs.

* Switched to using `UnitState.GetVisibilityExtents()`

* Added UnitSize check for the attacker.

Co-authored-by: Xymanek <8d900e611b3c39c901bf75d424e86630eaa3a229@outlook.com>

//---------------------------------------------------------------------------------------
//  FILE:    X2MeleePathingPawn.uc
//  AUTHOR:  David Burchanowski  --  2/10/2014
//  PURPOSE: Specialized pathing pawn for activated melee pathing. Draws tiles around every unit the
//           currently selected ability can melee from, and allows the user to select one to move there.
//
//---------------------------------------------------------------------------------------
//  Copyright (c) 2016 Firaxis Games, Inc. All rights reserved.
//---------------------------------------------------------------------------------------

class X2MeleePathingPawn extends XComPathingPawn
	native(Unit);

var /* private */ XComGameState_Unit UnitState; // The unit we are currently using
var /* private */ XComGameState_Ability AbilityState; // The ability we are currently using
var /* private */ Actor TargetVisualizer; // Visualizer of the current target
var /* private */ X2TargetingMethod_MeleePath TargetingMethod; // targeting method that spawned this pathing pawn, if any

var /* private */ array<TTile> PossibleTiles; // list of possible tiles to melee from

// Instanced mesh component for the grapple target tile markup
var /* private */ InstancedStaticMeshComponent InstancedMeshComponent;

// adds tiles to the instance mesh component for every tile in the PossibileTiles array
/* private */ native function UpdatePossibleTilesVisuals();

function Init(XComGameState_Unit InUnitState, XComGameState_Ability InAbilityState, X2TargetingMethod_MeleePath InTargetingMethod)
{
	super.SetActive(XGUnitNativeBase(InUnitState.GetVisualizer()));

	UnitState = InUnitState;
	AbilityState = InAbilityState;
	TargetingMethod = InTargetingMethod;

	InstancedMeshComponent.SetStaticMesh(StaticMesh(DynamicLoadObject("UI_3D.Tile.AOETile", class'StaticMesh')));
	InstancedMeshComponent.SetAbsolute(true, true);
}

simulated function SetActive(XGUnitNativeBase kActiveXGUnit, optional bool bCanDash, optional bool bObeyMaxCost)
{
	`assert(false); // call Init() instead
}

// disable the built in pathing melee targeting.
simulated /* protected */ function bool CanUnitMeleeFromMove(XComGameState_BaseObject TargetObject, out XComGameState_Ability MeleeAbility)
{
	return false;
}

function GetTargetMeleePath(out array<TTile> OutPathTiles)
{
	OutPathTiles = PathTiles;
}

// overridden to always just show the slash UI, regardless of cursor location or other considerations
simulated /* protected */ function UpdatePuckVisuals(XComGameState_Unit ActiveUnitState,
												const out TTile PathDestination,
												Actor TargetActor,
												X2AbilityTemplate MeleeAbilityTemplate)
{
	local XComWorldData WorldData;
	local XGUnit Unit;
	local vector MeshTranslation;
	local Rotator MeshRotation;
	local vector MeshScale;
	local vector FromTargetTile;
	local float UnitSize;

	WorldData = `XWORLD;

	// determine target puck size and location
	MeshTranslation = TargetActor.Location;

	Unit = XGUnit(TargetActor);
	if(Unit != none)
	{
		UnitSize = Unit.GetVisualizedGameState().UnitSize;
		MeshTranslation = Unit.GetPawn().CollisionComponent.Bounds.Origin;
	}
	else
	{
		UnitSize = 1.0f;
	}

	MeshTranslation.Z = WorldData.GetFloorZForPosition(MeshTranslation) + PathHeightOffset;

	// when slashing, we will technically be out of range.
	// hide the out of range mesh, show melee mesh
	OutOfRangeMeshComponent.SetHidden(true);
	SlashingMeshComponent.SetHidden(false);
	SlashingMeshComponent.SetTranslation(MeshTranslation);

	// rotate the mesh to face the thing we are slashing
	FromTargetTile = WorldData.GetPositionFromTileCoordinates(PathDestination) - MeshTranslation;
	MeshRotation.Yaw = atan2(FromTargetTile.Y, FromTargetTile.X) * RadToUnrRot;

	SlashingMeshComponent.SetRotation(MeshRotation);
	SlashingMeshComponent.SetScale(UnitSize);

	// the normal puck is always visible, and located wherever the unit
	// will actually move to when he executes the move
	PuckMeshComponent.SetHidden(false);
	PuckMeshComponent.SetStaticMeshes(GetMeleePuckMeshForAbility(MeleeAbilityTemplate), PuckMeshConfirmed);
	//<workshop> SMOOTH_TACTICAL_CURSOR AMS 2016/01/22
	//INS:
	PuckMeshCircleComponent.SetHidden(false);
	PuckMeshCircleComponent.SetStaticMesh(GetMeleePuckMeshForAbility(MeleeAbilityTemplate));
	//</workshop>
	if (IsDashing() || ActiveUnitState.NumActionPointsForMoving() == 1)
	{
		RenderablePath.SetMaterial(PathMaterialDashing);
	}

	MeshTranslation = VisualPath.GetEndPoint(); // make sure we line up perfectly with the end of the path ribbon
	MeshTranslation.Z = WorldData.GetFloorZForPosition(MeshTranslation) + PathHeightOffset;
	PuckMeshComponent.SetTranslation(MeshTranslation);
	//<workshop> SMOOTH_TACTICAL_CURSOR AMS 2016/01/22
	//INS:
	PuckMeshCircleComponent.SetTranslation(MeshTranslation);
	//</workshop>

	MeshScale.X = ActiveUnitState.UnitSize;
	MeshScale.Y = ActiveUnitState.UnitSize;
	MeshScale.Z = 1.0f;
	PuckMeshComponent.SetScale3D(MeshScale);
	//<workshop> SMOOTH_TACTICAL_CURSOR AMS 2016/01/22
	//INS:
	PuckMeshCircleComponent.SetScale3D(MeshScale);
	//</workshop>
}

simulated function UpdateMeleeTarget(XComGameState_BaseObject Target)
{
	local X2AbilityTemplate AbilityTemplate;
	local vector TileLocation;

	//<workshop> Francois' Smooth Cursor AMS 2016/04/07
	//INS:
	local TTile InvalidTile;
	InvalidTile.X = -1;
	InvalidTile.Y = -1;
	InvalidTile.Z = -1;
	//</workshop>

	if(Target == none)
	{
		`Redscreen("X2MeleePathingPawn::UpdateMeleeTarget: Target is none!");
		return;
	}

	TargetVisualizer = Target.GetVisualizer();
	AbilityTemplate = AbilityState.GetMyTemplate();

	PossibleTiles.Length = 0;

	if(class'X2AbilityTarget_MovingMelee'.static.SelectAttackTile(UnitState, Target, AbilityTemplate, PossibleTiles))
	{
		// Start Issue #1084
		// The native `class'X2AbilityTarget_MovingMelee'.static.SelectAttackTile` function
		// gives only one possible attack tile for adjacent targets, so we use our own
		// script logic to add more possible attack tiles for adjacent targets.
		// If there's only one possible melee attack tile and the unit is standing on it,
		// then the target is directly adjacent.
		if (UnitState.UnitSize == 1 && PossibleTiles.Length == 1 && UnitState.TileLocation == PossibleTiles[0])
		{
			UpdatePossibleTilesForAdjacentTarget(Target);
		}
		// End Issue #1084

		// build a path to the default (best) tile
		//<workshop> Francois' Smooth Cursor AMS 2016/04/07
		//WAS:
		//RebuildPathingInformation(PossibleTiles[0], TargetVisualizer, AbilityTemplate);
		RebuildPathingInformation(PossibleTiles[0], TargetVisualizer, AbilityTemplate, InvalidTile);
		//</workshop>

		// and update the tiles to reflect the new target options
		UpdatePossibleTilesVisuals();

		if(`ISCONTROLLERACTIVE)
		{
			// move the 3D cursor to the new target
			if(`XWORLD.GetFloorPositionForTile(PossibleTiles[0], TileLocation))
			{
				// Single Line for #520
				/// HL-Docs: ref:Bugfixes; issue:520
				/// Controller input now allows choosing melee attack destination tile despite floor differences
				`CURSOR.m_iRequestedFloor = `CURSOR.WorldZToFloor(TargetVisualizer.Location);
				`CURSOR.CursorSetLocation(TileLocation, true, true);
			}
		}
	}
	//<workshop> TACTICAL_CURSOR_PROTOTYPING AMS 2015/12/07
	//INS:
	DoUpdatePuckVisuals(PossibleTiles[0], Target.GetVisualizer(), AbilityTemplate);
	//</workshop>
}

// Start Issue #1084
private function UpdatePossibleTilesForAdjacentTarget(XComGameState_BaseObject Target)
{
	local array<TTile>               TargetTiles; // Array of tiles occupied by the target; these tiles can be attacked by melee.
	local TTile                      TargetTile;
	local array<TTile>               AdjacentTiles;	// Array of tiles adjacent to Target Tiles; the attacking unit can move to these tiles to attack.
	local TTile                      AdjacentTile;
	local XComGameState_Unit         TargetUnit;
	local XComGameState_Destructible TargetObject;
	local XComDestructibleActor      DestructibleActor;

	TargetUnit = XComGameState_Unit(Target);
	if (TargetUnit != none)
	{
		GatherTilesOccupiedByUnit(TargetUnit, TargetTiles);
	}
	else
	{
		TargetObject = XComGameState_Destructible(Target);
		if (TargetObject == none)
		{
			`LOG(self.Class.Name @ GetFuncName() @ ":: WARNING, target is not a unit and not a destructible object! Its class is:" @ Target.Class.Name @ ", unable to detect additional tiles to melee attack from. Attacking unit:" @ UnitState.GetFullName());
			return;
		}

		DestructibleActor = XComDestructibleActor(TargetObject.GetVisualizer());
		if (DestructibleActor == none)
		{
			`LOG(self.Class.Name @ GetFuncName() @ ":: WARNING, no visualizer found for destructible object with ID:" @ TargetObject.ObjectID @ ", unable to detect additional tiles to melee attack from. Attacking unit:" @ UnitState.GetFullName());
			return;
		}

		// AssociatedTiles is the array of tiles occupied by the destructible object.
	    // In theory, every tile from that array can be targeted by a melee attack.
		TargetTiles = DestructibleActor.AssociatedTiles;
	}

	// Collect non-duplicate tiles around every Target Tile to see which tiles we can attack from.
	GatherTilesAdjacentToTiles(TargetTiles, AdjacentTiles);

	foreach TargetTiles(TargetTile)
	{
		foreach AdjacentTiles(AdjacentTile)
		{
			if (class'Helpers'.static.FindTileInList(AdjacentTile, PossibleTiles) != INDEX_NONE)
				continue;

			if (class'X2AbilityTarget_MovingMelee'.static.IsValidAttackTile(UnitState, AdjacentTile, TargetTile, ActiveCache))
			{
				PossibleTiles.AddItem(AdjacentTile);
			}
		}
	}
}

private function GatherTilesOccupiedByUnit(const XComGameState_Unit TargetUnit, out array<TTile> OccupiedTiles)
{
	local XComWorldData      WorldData;
	local array<TilePosPair> TilePosPairs;
	local TilePosPair        TilePair;
	local Box                VisibilityExtents;

	TargetUnit.GetVisibilityExtents(VisibilityExtents);

	WorldData = `XWORLD;
	WorldData.CollectTilesInBox(TilePosPairs, VisibilityExtents.Min, VisibilityExtents.Max);

	foreach TilePosPairs(TilePair)
	{
		OccupiedTiles.AddItem(TilePair.Tile);
	}
}

private function GatherTilesAdjacentToTiles(out array<TTile> TargetTiles, out array<TTile> AdjacentTiles)
{
	local XComWorldData      WorldData;
	local array<TilePosPair> TilePosPairs;
	local TilePosPair        TilePair;
	local TTile              TargetTile;
	local vector             Minimum;
	local vector             Maximum;

	WorldData = `XWORLD;

	// Collect a 3x3 box of tiles around every target tile, excluding duplicates.
	// Melee attacks can happen diagonally upwards or downwards too,
	// so collecting tiles on the same Z level would not be enough.
	foreach TargetTiles(TargetTile)
	{
		Minimum = WorldData.GetPositionFromTileCoordinates(TargetTile);
		Maximum = Minimum;

		Minimum.X -= WorldData.WORLD_StepSize;
		Minimum.Y -= WorldData.WORLD_StepSize;
		Minimum.Z -= WorldData.WORLD_FloorHeight;

		Maximum.X += WorldData.WORLD_StepSize;
		Maximum.Y += WorldData.WORLD_StepSize;
		Maximum.Z += WorldData.WORLD_FloorHeight;

		WorldData.CollectTilesInBox(TilePosPairs, Minimum, Maximum);

		foreach TilePosPairs(TilePair)
		{
			if (class'Helpers'.static.FindTileInList(TilePair.Tile, AdjacentTiles) != INDEX_NONE)
				continue;

			AdjacentTiles.AddItem(TilePair.Tile);
		}
	}
}
// End Issue #1084

// override the tick. Rather than do the normal path update stuff, we just want to see if the user has pointed the mouse
// at any of our other possible tiles
simulated event Tick(float DeltaTime)
{
	local XCom3DCursor Cursor;
	local XComWorldData WorldData;
	local vector CursorLocation;
	local TTile PossibleTile;
	local TTile CursorTile;
	local TTile ClosestTile;
	local X2AbilityTemplate AbilityTemplate;
	local float ClosestTileDistance;
	local float TileDistance;

	local TTile InvalidTile;
	InvalidTile.X = -1;
	InvalidTile.Y = -1;
	InvalidTile.Z = -1;

	if(TargetVisualizer == none)
	{
		return;
	}

	Cursor = `CURSOR;
	WorldData = `XWORLD;

	CursorLocation = Cursor.GetCursorFeetLocation();
	CursorTile = WorldData.GetTileCoordinatesFromPosition(CursorLocation);

	// mouse needs to actually highlight a specific tile, controller tabs through them
	if(`ISCONTROLLERACTIVE)
	{
		ClosestTileDistance = -1;

		if(VSizeSq2D(CursorLocation - TargetVisualizer.Location) > 0.1f)
		{
			CursorLocation = TargetVisualizer.Location + (Normal(Cursor.Location - TargetVisualizer.Location) * class'XComWorldData'.const.WORLD_StepSize);
			foreach PossibleTiles(PossibleTile)
			{
				// Single line for #520
				TileDistance = VSizeSq2D(WorldData.GetPositionFromTileCoordinates(PossibleTile) - CursorLocation);
				if(ClosestTileDistance < 0 || TileDistance < ClosestTileDistance)
				{
					ClosestTile = PossibleTile;
					ClosestTileDistance = TileDistance;
				}
			}

			if(ClosestTile != LastDestinationTile)
			{
				AbilityTemplate = AbilityState.GetMyTemplate();
				RebuildPathingInformation(ClosestTile, TargetVisualizer, AbilityTemplate, InvalidTile);
				DoUpdatePuckVisuals(ClosestTile, TargetVisualizer, AbilityTemplate);
				LastDestinationTile = ClosestTile;
				TargetingMethod.TickUpdatedDestinationTile(LastDestinationTile);
			}

			// put the cursor back on the unit
			Cursor.CursorSetLocation(TargetVisualizer.Location, true);
		}
	}
	else
	{
		if(CursorTile != LastDestinationTile)
		{
			foreach PossibleTiles(PossibleTile)
			{
				if(PossibleTile == CursorTile ||
				   // Start Issue #1084
				   // If the cursor is hovering above the tile occupied by the unit, the CursorTile.Z is increased by 1,
				   // so the direct comparison "PossibleTile == CursorTile" will always fail.
				   // So for the possible attack tile occupied by the attacker unit, we compare to cursor's Z location - 1.
				   (PossibleTile == UnitState.TileLocation && CursorTile.X == PossibleTile.X && PossibleTile.Y == CursorTile.Y && PossibleTile.Z == CursorTile.Z - 1)
				   // End issue #1084
				   )
				{
					AbilityTemplate = AbilityState.GetMyTemplate();

					// Start Issue #1084
					// Use PossibleTile instead of CursorTile to properly handle the case
					// when the cursor hovers over the tile occupied by the attacker unit.
					//RebuildPathingInformation(CursorTile, TargetVisualizer, AbilityTemplate, InvalidTile);
					//LastDestinationTile = CursorTile;
					RebuildPathingInformation(PossibleTile, TargetVisualizer, AbilityTemplate, InvalidTile);
					LastDestinationTile = PossibleTile;
					// End Issue #1084
					TargetingMethod.TickUpdatedDestinationTile(LastDestinationTile);
					break;
				}
			}
		}
	}
}

// don't update objective tiles
function UpdateObjectiveTiles(XComGameState_Unit InActiveUnitState);

defaultproperties
{
	Begin Object Class=InstancedStaticMeshComponent Name=InstancedMeshComponent0
		CastShadow=false
		BlockNonZeroExtent=false
		BlockZeroExtent=false
		BlockActors=false
		CollideActors=false
	End object
	InstancedMeshComponent=InstancedMeshComponent0
	Components.Add(InstancedMeshComponent0)
}

//---------------------------------------------------------------------------------------
//  FILE:    X2MeleePathingPawn.uc
//  AUTHOR:  David Burchanowski  --  2/10/2014
//  PURPOSE: Specialized pathing pawn for activated melee pathing. Draws tiles around every unit the
//           currently selected ability can melee from, and allows the user to select one to move there.
//
//---------------------------------------------------------------------------------------
//  Copyright (c) 2016 Firaxis Games, Inc. All rights reserved.
//---------------------------------------------------------------------------------------

class X2MeleePathingPawn extends XComPathingPawn
	native(Unit);

var /* private */ XComGameState_Unit UnitState; // The unit we are currently using
var /* private */ XComGameState_Ability AbilityState; // The ability we are currently using
var /* private */ Actor TargetVisualizer; // Visualizer of the current target
var /* private */ X2TargetingMethod_MeleePath TargetingMethod; // targeting method that spawned this pathing pawn, if any

var /* private */ array<TTile> PossibleTiles; // list of possible tiles to melee from

// Instanced mesh component for the grapple target tile markup
var /* private */ InstancedStaticMeshComponent InstancedMeshComponent;

// adds tiles to the instance mesh component for every tile in the PossibileTiles array
/* private */ native function UpdatePossibleTilesVisuals();

function Init(XComGameState_Unit InUnitState, XComGameState_Ability InAbilityState, X2TargetingMethod_MeleePath InTargetingMethod)
{
	super.SetActive(XGUnitNativeBase(InUnitState.GetVisualizer()));

	UnitState = InUnitState;
	AbilityState = InAbilityState;
	TargetingMethod = InTargetingMethod;

	InstancedMeshComponent.SetStaticMesh(StaticMesh(DynamicLoadObject("UI_3D.Tile.AOETile", class'StaticMesh')));
	InstancedMeshComponent.SetAbsolute(true, true);
}

simulated function SetActive(XGUnitNativeBase kActiveXGUnit, optional bool bCanDash, optional bool bObeyMaxCost)
{
	`assert(false); // call Init() instead
}

// disable the built in pathing melee targeting.
simulated /* protected */ function bool CanUnitMeleeFromMove(XComGameState_BaseObject TargetObject, out XComGameState_Ability MeleeAbility)
{
	return false;
}

function GetTargetMeleePath(out array<TTile> OutPathTiles)
{
	OutPathTiles = PathTiles;
}

// overridden to always just show the slash UI, regardless of cursor location or other considerations
simulated /* protected */ function UpdatePuckVisuals(XComGameState_Unit ActiveUnitState,
												const out TTile PathDestination,
												Actor TargetActor,
												X2AbilityTemplate MeleeAbilityTemplate)
{
	local XComWorldData WorldData;
	local XGUnit Unit;
	local vector MeshTranslation;
	local Rotator MeshRotation;
	local vector MeshScale;
	local vector FromTargetTile;
	local float UnitSize;

	WorldData = `XWORLD;

	// determine target puck size and location
	MeshTranslation = TargetActor.Location;

	Unit = XGUnit(TargetActor);
	if(Unit != none)
	{
		UnitSize = Unit.GetVisualizedGameState().UnitSize;
		MeshTranslation = Unit.GetPawn().CollisionComponent.Bounds.Origin;
	}
	else
	{
		UnitSize = 1.0f;
	}

	MeshTranslation.Z = WorldData.GetFloorZForPosition(MeshTranslation) + PathHeightOffset;

	// when slashing, we will technically be out of range.
	// hide the out of range mesh, show melee mesh
	OutOfRangeMeshComponent.SetHidden(true);
	SlashingMeshComponent.SetHidden(false);
	SlashingMeshComponent.SetTranslation(MeshTranslation);

	// rotate the mesh to face the thing we are slashing
	FromTargetTile = WorldData.GetPositionFromTileCoordinates(PathDestination) - MeshTranslation;
	MeshRotation.Yaw = atan2(FromTargetTile.Y, FromTargetTile.X) * RadToUnrRot;

	SlashingMeshComponent.SetRotation(MeshRotation);
	SlashingMeshComponent.SetScale(UnitSize);

	// the normal puck is always visible, and located wherever the unit
	// will actually move to when he executes the move
	PuckMeshComponent.SetHidden(false);
	PuckMeshComponent.SetStaticMeshes(GetMeleePuckMeshForAbility(MeleeAbilityTemplate), PuckMeshConfirmed);
	//<workshop> SMOOTH_TACTICAL_CURSOR AMS 2016/01/22
	//INS:
	PuckMeshCircleComponent.SetHidden(false);
	PuckMeshCircleComponent.SetStaticMesh(GetMeleePuckMeshForAbility(MeleeAbilityTemplate));
	//</workshop>
	if (IsDashing() || ActiveUnitState.NumActionPointsForMoving() == 1)
	{
		RenderablePath.SetMaterial(PathMaterialDashing);
	}

	MeshTranslation = VisualPath.GetEndPoint(); // make sure we line up perfectly with the end of the path ribbon
	MeshTranslation.Z = WorldData.GetFloorZForPosition(MeshTranslation) + PathHeightOffset;
	PuckMeshComponent.SetTranslation(MeshTranslation);
	//<workshop> SMOOTH_TACTICAL_CURSOR AMS 2016/01/22
	//INS:
	PuckMeshCircleComponent.SetTranslation(MeshTranslation);
	//</workshop>

	MeshScale.X = ActiveUnitState.UnitSize;
	MeshScale.Y = ActiveUnitState.UnitSize;
	MeshScale.Z = 1.0f;
	PuckMeshComponent.SetScale3D(MeshScale);
	//<workshop> SMOOTH_TACTICAL_CURSOR AMS 2016/01/22
	//INS:
	PuckMeshCircleComponent.SetScale3D(MeshScale);
	//</workshop>
}

simulated function UpdateMeleeTarget(XComGameState_BaseObject Target)
{
	local X2AbilityTemplate AbilityTemplate;
	local vector TileLocation;

	//<workshop> Francois' Smooth Cursor AMS 2016/04/07
	//INS:
	local TTile InvalidTile;
	InvalidTile.X = -1;
	InvalidTile.Y = -1;
	InvalidTile.Z = -1;
	//</workshop>

	if(Target == none)
	{
		`Redscreen("X2MeleePathingPawn::UpdateMeleeTarget: Target is none!");
		return;
	}

	TargetVisualizer = Target.GetVisualizer();
	AbilityTemplate = AbilityState.GetMyTemplate();

	PossibleTiles.Length = 0;

	if(class'X2AbilityTarget_MovingMelee'.static.SelectAttackTile(UnitState, Target, AbilityTemplate, PossibleTiles))
	{
		// build a path to the default (best) tile
		//<workshop> Francois' Smooth Cursor AMS 2016/04/07
		//WAS:
		//RebuildPathingInformation(PossibleTiles[0], TargetVisualizer, AbilityTemplate);
		RebuildPathingInformation(PossibleTiles[0], TargetVisualizer, AbilityTemplate, InvalidTile);
		//</workshop>

		// and update the tiles to reflect the new target options
		UpdatePossibleTilesVisuals();

		if(`ISCONTROLLERACTIVE)
		{
			// move the 3D cursor to the new target
			if(`XWORLD.GetFloorPositionForTile(PossibleTiles[0], TileLocation))
			{
				// Single Line for #520
				/// HL-Docs: ref:Bugfixes; issue:520
				/// Controller input now allows choosing melee attack destination tile despite floor differences
				`CURSOR.m_iRequestedFloor = `CURSOR.WorldZToFloor(TargetVisualizer.Location);
				`CURSOR.CursorSetLocation(TileLocation, true, true);
			}
		}
	}
	//<workshop> TACTICAL_CURSOR_PROTOTYPING AMS 2015/12/07
	//INS:
	DoUpdatePuckVisuals(PossibleTiles[0], Target.GetVisualizer(), AbilityTemplate);
	//</workshop>
}

// override the tick. Rather than do the normal path update stuff, we just want to see if the user has pointed the mouse
// at any of our other possible tiles
simulated event Tick(float DeltaTime)
{
	local XCom3DCursor Cursor;
	local XComWorldData WorldData;
	local vector CursorLocation;
	local TTile PossibleTile;
	local TTile CursorTile;
	local TTile ClosestTile;
	local X2AbilityTemplate AbilityTemplate;
	local float ClosestTileDistance;
	local float TileDistance;

	local TTile InvalidTile;
	InvalidTile.X = -1;
	InvalidTile.Y = -1;
	InvalidTile.Z = -1;

	if(TargetVisualizer == none)
	{
		return;
	}

	Cursor = `CURSOR;
	WorldData = `XWORLD;

	CursorLocation = Cursor.GetCursorFeetLocation();
	CursorTile = WorldData.GetTileCoordinatesFromPosition(CursorLocation);

	// mouse needs to actually highlight a specific tile, controller tabs through them
	if(`ISCONTROLLERACTIVE)
	{
		ClosestTileDistance = -1;

		if(VSizeSq2D(CursorLocation - TargetVisualizer.Location) > 0.1f)
		{
			CursorLocation = TargetVisualizer.Location + (Normal(Cursor.Location - TargetVisualizer.Location) * class'XComWorldData'.const.WORLD_StepSize);
			foreach PossibleTiles(PossibleTile)
			{
				// Single line for #520
				TileDistance = VSizeSq2D(WorldData.GetPositionFromTileCoordinates(PossibleTile) - CursorLocation);
				if(ClosestTileDistance < 0 || TileDistance < ClosestTileDistance)
				{
					ClosestTile = PossibleTile;
					ClosestTileDistance = TileDistance;
				}
			}

			if(ClosestTile != LastDestinationTile)
			{
				AbilityTemplate = AbilityState.GetMyTemplate();
				RebuildPathingInformation(ClosestTile, TargetVisualizer, AbilityTemplate, InvalidTile);
				DoUpdatePuckVisuals(ClosestTile, TargetVisualizer, AbilityTemplate);
				LastDestinationTile = ClosestTile;
				TargetingMethod.TickUpdatedDestinationTile(LastDestinationTile);
			}

			// put the cursor back on the unit
			Cursor.CursorSetLocation(TargetVisualizer.Location, true);
		}
	}
	else
	{
		if(CursorTile != LastDestinationTile)
		{
			foreach PossibleTiles(PossibleTile)
			{
				if(PossibleTile == CursorTile)
				{
					AbilityTemplate = AbilityState.GetMyTemplate();
					RebuildPathingInformation(CursorTile, TargetVisualizer, AbilityTemplate, InvalidTile);
					LastDestinationTile = CursorTile;
					TargetingMethod.TickUpdatedDestinationTile(LastDestinationTile);
					break;
				}
			}
		}
	}
}

// don't update objective tiles
function UpdateObjectiveTiles(XComGameState_Unit InActiveUnitState);

defaultproperties
{
	Begin Object Class=InstancedStaticMeshComponent Name=InstancedMeshComponent0
		CastShadow=false
		BlockNonZeroExtent=false
		BlockZeroExtent=false
		BlockActors=false
		CollideActors=false
	End object
	InstancedMeshComponent=InstancedMeshComponent0
	Components.Add(InstancedMeshComponent0)
}


lib/raid6: Fix filename emitted in generated code

The files were renamed in commit cc4589ebf; fix the name in the file
itself.

Signed-off-by: Dan McGee <a6e5737275ff1276377ee261739f3ee963671241@gmail.com>
Signed-off-by: NeilBrown <1c00aa603bb92d594c03cff60ecf8e63b2a5bcb1@suse.de>

/* -*- linux-c -*- ------------------------------------------------------- *
 *
 *   Copyright 2002-2004 H. Peter Anvin - All Rights Reserved
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
 *   Boston MA 02111-1307, USA; either version 2 of the License, or
 *   (at your option) any later version; incorporated herein by reference.
 *
 * ----------------------------------------------------------------------- */

/*
 * int$#.c
 *
 * $#-way unrolled portable integer math RAID-6 instruction set
 *
 * This file is postprocessed using unroll.awk
 */

#include <linux/raid/pq.h>

/*
 * This is the C data type to use
 */

/* Change this from BITS_PER_LONG if there is something better... */
#if BITS_PER_LONG == 64
# define NBYTES(x) ((x) * 0x0101010101010101UL)
# define NSIZE  8
# define NSHIFT 3
# define NSTRING "64"
typedef u64 unative_t;
#else
# define NBYTES(x) ((x) * 0x01010101U)
# define NSIZE  4
# define NSHIFT 2
# define NSTRING "32"
typedef u32 unative_t;
#endif

/*
 * IA-64 wants insane amounts of unrolling.  On other architectures that
 * is just a waste of space.
 */
#if ($# <= 8) || defined(__ia64__)

/*
 * These sub-operations are separate inlines since they can sometimes be
 * specially optimized using architecture-specific hacks.
 */

/*
 * The SHLBYTE() operation shifts each byte left by 1, *not*
 * rolling over into the next byte
 */
static inline __attribute_const__ unative_t SHLBYTE(unative_t v)
{
	unative_t vv;

	vv = (v << 1) & NBYTES(0xfe);
	return vv;
}

/*
 * The MASK() operation returns 0xFF in any byte for which the high
 * bit is 1, 0x00 for any byte for which the high bit is 0.
 */
static inline __attribute_const__ unative_t MASK(unative_t v)
{
	unative_t vv;

	vv = v & NBYTES(0x80);
	vv = (vv << 1) - (vv >> 7); /* Overflow on the top bit is OK */
	return vv;
}

static void raid6_int$#_gen_syndrome(int disks, size_t bytes, void **ptrs)
{
	u8 **dptr = (u8 **)ptrs;
	u8 *p, *q;
	int d, z, z0;

	unative_t wd$$, wq$$, wp$$, w1$$, w2$$;

	z0 = disks - 3;		/* Highest data disk */
	p = dptr[z0+1];		/* XOR parity */
	q = dptr[z0+2];		/* RS syndrome */

	for ( d = 0 ; d < bytes ; d += NSIZE*$# ) {
		wq$$ = wp$$ = *(unative_t *)&dptr[z0][d+$$*NSIZE];
		for ( z = z0-1 ; z >= 0 ; z-- ) {
			wd$$ = *(unative_t *)&dptr[z][d+$$*NSIZE];
			wp$$ ^= wd$$;
			w2$$ = MASK(wq$$);
			w1$$ = SHLBYTE(wq$$);
			w2$$ &= NBYTES(0x1d);
			w1$$ ^= w2$$;
			wq$$ = w1$$ ^ wd$$;
		}
		*(unative_t *)&p[d+NSIZE*$$] = wp$$;
		*(unative_t *)&q[d+NSIZE*$$] = wq$$;
	}
}

const struct raid6_calls raid6_intx$# = {
	raid6_int$#_gen_syndrome,
	NULL,		/* always valid */
	"int" NSTRING "x$#",
	0
};

#endif

/* -*- linux-c -*- ------------------------------------------------------- *
 *
 *   Copyright 2002-2004 H. Peter Anvin - All Rights Reserved
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
 *   Boston MA 02111-1307, USA; either version 2 of the License, or
 *   (at your option) any later version; incorporated herein by reference.
 *
 * ----------------------------------------------------------------------- */

/*
 * raid6int$#.c
 *
 * $#-way unrolled portable integer math RAID-6 instruction set
 *
 * This file is postprocessed using unroll.awk
 */

#include <linux/raid/pq.h>

/*
 * This is the C data type to use
 */

/* Change this from BITS_PER_LONG if there is something better... */
#if BITS_PER_LONG == 64
# define NBYTES(x) ((x) * 0x0101010101010101UL)
# define NSIZE  8
# define NSHIFT 3
# define NSTRING "64"
typedef u64 unative_t;
#else
# define NBYTES(x) ((x) * 0x01010101U)
# define NSIZE  4
# define NSHIFT 2
# define NSTRING "32"
typedef u32 unative_t;
#endif

/*
 * IA-64 wants insane amounts of unrolling.  On other architectures that
 * is just a waste of space.
 */
#if ($# <= 8) || defined(__ia64__)

/*
 * These sub-operations are separate inlines since they can sometimes be
 * specially optimized using architecture-specific hacks.
 */

/*
 * The SHLBYTE() operation shifts each byte left by 1, *not*
 * rolling over into the next byte
 */
static inline __attribute_const__ unative_t SHLBYTE(unative_t v)
{
	unative_t vv;

	vv = (v << 1) & NBYTES(0xfe);
	return vv;
}

/*
 * The MASK() operation returns 0xFF in any byte for which the high
 * bit is 1, 0x00 for any byte for which the high bit is 0.
 */
static inline __attribute_const__ unative_t MASK(unative_t v)
{
	unative_t vv;

	vv = v & NBYTES(0x80);
	vv = (vv << 1) - (vv >> 7); /* Overflow on the top bit is OK */
	return vv;
}

static void raid6_int$#_gen_syndrome(int disks, size_t bytes, void **ptrs)
{
	u8 **dptr = (u8 **)ptrs;
	u8 *p, *q;
	int d, z, z0;

	unative_t wd$$, wq$$, wp$$, w1$$, w2$$;

	z0 = disks - 3;		/* Highest data disk */
	p = dptr[z0+1];		/* XOR parity */
	q = dptr[z0+2];		/* RS syndrome */

	for ( d = 0 ; d < bytes ; d += NSIZE*$# ) {
		wq$$ = wp$$ = *(unative_t *)&dptr[z0][d+$$*NSIZE];
		for ( z = z0-1 ; z >= 0 ; z-- ) {
			wd$$ = *(unative_t *)&dptr[z][d+$$*NSIZE];
			wp$$ ^= wd$$;
			w2$$ = MASK(wq$$);
			w1$$ = SHLBYTE(wq$$);
			w2$$ &= NBYTES(0x1d);
			w1$$ ^= w2$$;
			wq$$ = w1$$ ^ wd$$;
		}
		*(unative_t *)&p[d+NSIZE*$$] = wp$$;
		*(unative_t *)&q[d+NSIZE*$$] = wq$$;
	}
}

const struct raid6_calls raid6_intx$# = {
	raid6_int$#_gen_syndrome,
	NULL,		/* always valid */
	"int" NSTRING "x$#",
	0
};

#endif


Update typespecifiers.uc

Update typespecifiers.uc

Added type specifier $$ for wstring (Unicode Wide String)

# typespecifiers.uc - uCalc Transformation file
# This file was saved with uCalc Transform 2.0 on 1/7/2014 8:22:32 AM
# Comment: Replaces data type specifiers with explicit type names

ExternalKeywords: Exclude, Comment, Selected, ParentChild, FindMode, OutputFile, BatchAction, SEND
ExternalKeywords: Highlight, ForeColor, BackColor, FontName, FontSize, FontStyle
ExternalKeywords: FilterEndText, FilterSeparator, FilterSort, FilterSortFunc, FilterStartText, FilterUnique

FindMode: Replace

# Definitions

# Search Criteria

Criteria: 0
Enabled: True
Exclude: False
Comment: Replaces data type specifiers with explicit type names
Selected: False
Highlight: True
ForeColor: ControlText
BackColor: Aqua
FontName:
FontSize:
FontStyle:
CaseSensitive: False
QuoteSensitive: True
CodeBlockSensitive: True
FilterEndText:
FilterSeparator: {#10}
FilterSort: False
FilterSortFunc:
FilterStartText:
FilterUnique: False
Min: 0
Max: -1
MinSoft: 0
MaxSoft: -1
BatchAction: Transform
OutputFile:
SEND:
StartAfter: 0
StopAfter: -1
SkipOver: False
ParentChild: 0
Pass: 0
PassOnce: True
Precedence: 0
RightToLeft: False

Criteria: 1
Selected: True
Highlight: False
Find: {@Note:
         This transform does the following:

         * Adds explicit ByRef to args w/o ByVal or ByRef
         * Changes type specifiers to type names in param
           definitions and removes them elsewhere
         * Adds data type name to params that have neither
           an explicit type name or specifier, based on
           DefType definitions

         The section to the immediate right defines the
         required tables and an array to accomplish this.

         Bug: LCase() and UCase() are re-defined on the right
              due to a problem affecting pre-existing LCase/UCase.
              That is a temp solution.
      }
Replace: {@Define:
            LineContinue: " _"
            Var: DefTypeInitial(255) As String
            Var: Specifier As Table = _
                 {"%", "Integer", "&", "Long", "&&", "Quad", _
                  "?", "Byte", "??", "Word", "???", "DWORD", _
                  "!", "Single", "#", "double", "##", "Extended", _
                  "@", "Currency", "@@", "CurrencyX", _
                  "$", "string", "$$", "wstring"}
            Var: DefType As Table = _
                 {"INT", "Integer", "LNG", "Long", "QUD", "Quad", _
                 "BYT", "Byte", "WRD", "Word", "DWD", "Dword", _
                 "SNG", "Single", "DBL", "Double", "EXT", "Extended", _
                 "CUR", "Currency", "CUX", "CurrencyX", "STR", "String"}
            Var: dType="(INT|LNG|QUD|BYT|WRD|DWD|SNG|DBL|EXT|CUR|CUX|STR)\b"
            Func: LCase(c As String) As String = IIF(Asc(c) > 64 and Asc(c) < 91, Chr(Asc(c)+32), c)
            Func: UCase(c As String) As String = IIF(Asc(c) > 96 and Asc(c) < 123, Chr(Asc(c)-32), c)
         }{@Define:: Token: \x27.* ~~ Properties: ucWhitespace}

Criteria: 2
Comment: Handles DefType declarations; also inserts <Arg> marker for easier parsing
Pass: 1

Criteria: 3
Comment: Stores the DefType statement associated with character initials
Highlight: False
BackColor: Purple
Find: {"Def"}{type:"{@Eval: dType}"} {char} {nl}
Replace: {@Eval:
            SetVar(DefTypeInitial(Asc(LCase("{char}"))), ReadStr(DefType, "{type}"))
            SetVar(DefTypeInitial(Asc(UCase("{char}"))), ReadStr(DefType, "{type}"))
         }

Criteria: 4
Comment: Changes a DefType range into multiple DefType statements
Highlight: False
BackColor: SlateBlue
PassOnce: False
Find: {"Def"}{type:"{@Eval: dType}"} {from}-{to} {nl}
Replace: {@Eval: Range(Asc("{from}"), Asc("{to}"), "'Def{type} '+Chr(x)+Chr(10)")}

Criteria: 5
Comment: Break DefType statements containing commas into multiple DefStype statements (one per line)
Highlight: False
BackColor: Pink
PassOnce: False
Find: {"Def"}{type:"{@Eval: dType}"} {etc}, {more} {nl}
Replace: Def{type} {etc}
         Def{type} {more}

Criteria: 6
Comment: Inserts <arg> marker for easier parsing
Highlight: False
BackColor: Red
Find: {nl}{decl: Sub | Function } {etc} ({args})
Replace: {nl}{decl} {etc}(<Arg>{@Eval: Replace("{args}", ",", ", <Arg>")})

Criteria: 7
Highlight: False
SkipOver: True
Find: {nl}Function =
Replace: [Skip over]

Criteria: 8
Comment: Inserts ByRef to params that have neither ByRef nor ByVal
Pass: 2

Criteria: 9
Comment: Inserts ByRef in front of params that do not explicitlly have ByVal or ByRef
Highlight: False
BackColor: SandyBrown
Find: <Arg> [{optional: Optional}] {name:1}
Replace: <Arg>{optional} ByRef {name}

Criteria: 10
Comment: Skips params that already have ByVal or ByRef
Highlight: False
BackColor: Green
SkipOver: True
Find: <Arg> [Optional] { ByVal | ByRef }
Replace: [Skip over]

Criteria: 11
Comment: Adds explicit data types to arg or variable declarations (functions also)
Pass: 3

Criteria: 12
Highlight: False
BackColor: RoyalBlue
Find: <Arg> [Optional] {by: ByVal | ByRef } {name:1}
Replace: <Arg>{by} {name} As {@Eval: DefTypeInitial(Asc("{name}"))}

Criteria: 13
Highlight: False
Find: <Arg> [Optional] {by: ByVal | ByRef } {name:1}{spec:"[!?@#$%&]+"}
Replace: <Arg>{by} {name} As {@Eval: ReadStr(Specifier, "{spec}")}

Criteria: 14
Highlight: False
SkipOver: True
Find: <Arg> [Optional] {by: ByVal | ByRef } {name:1} As
Replace: [Skip over]

Criteria: 15
Highlight: False
BackColor: Tomato
PassOnce: False
Find: {decl: Dim | Global | Local | Static } {etc} {spec:"[!?@#$%&]+"}
Replace: {decl} {etc} As {@Eval: ReadStr(Specifier, "{spec}")}

Criteria: 16
Comment: Adds the appropriate type for functions with no explicit type or specifier
Highlight: False
BackColor: CornflowerBlue
Find: {nl}Function {name:1}([{args%}])
Replace: {nl}Function {name}({args}) As {@Eval: DefTypeInitial(Asc("{name}"))}

Criteria: 17
Comment: Changes function type specifier to data type name
Highlight: False
Find: {nl}Function {name:1}{spec:"[!?@#$%&]+"}([{args%}])
Replace: {nl}Function {name}({args}) As {@Eval: ReadStr(Specifier, "{spec}")}

Criteria: 18
Comment: Skips functions that already have an explicit type
Highlight: False
BackColor: Gold
Find: {nl}Function {name}([{args%}]) As {type}
Replace: {nl}Function {name}({args}) As {type}

Criteria: 19
Comment: Cleans up; removes <Arg> marker; as well as type specifiers
Pass: 4

Criteria: 20
Comment: Removes <Arg> that was inserted in earlier pass
Highlight: False
BackColor: SandyBrown
Find: <Arg>
Replace: {Nothing}

Criteria: 21
Comment: Removes statement specifiers
Highlight: False
BackColor: Violet
Find: {variable:"[a-z0-9_]+"}{spec:"[!?@#$%&]+"}
Replace: {variable}

# End Search

# typespecifiers.uc - uCalc Transformation file
# This file was saved with uCalc Transform 2.0 on 1/6/2014 10:33:05 AM
# Comment: Replaces data type specifiers with explicit type names

ExternalKeywords: Exclude, Comment, Selected, ParentChild, FindMode, OutputFile, BatchAction, SEND
ExternalKeywords: Highlight, ForeColor, BackColor, FontName, FontSize, FontStyle
ExternalKeywords: FilterEndText, FilterSeparator, FilterSort, FilterSortFunc, FilterStartText, FilterUnique

FindMode: Replace

# Definitions

# Search Criteria

Criteria: 0
Enabled: True
Exclude: False
Comment: Replaces data type specifiers with explicit type names
Selected: False
Highlight: True
ForeColor: ControlText
BackColor: Aqua
FontName:
FontSize:
FontStyle:
CaseSensitive: False
QuoteSensitive: True
CodeBlockSensitive: True
FilterEndText:
FilterSeparator: {#10}
FilterSort: False
FilterSortFunc:
FilterStartText:
FilterUnique: False
Min: 0
Max: -1
MinSoft: 0
MaxSoft: -1
BatchAction: Transform
OutputFile:
SEND:
StartAfter: 0
StopAfter: -1
SkipOver: False
ParentChild: 0
Pass: 0
PassOnce: True
Precedence: 0
RightToLeft: False

Criteria: 1
Selected: True
Highlight: False
Find: {@Note:
         This transform does the following:

         * Adds explicit ByRef to args w/o ByVal or ByRef
         * Changes type specifiers to type names in param
           definitions and removes them elsewhere
         * Adds data type name to params that have neither
           an explicit type name or specifier, based on
           DefType definitions

         The section to the immediate right defines the
         required tables and an array to accomplish this.

         Bug: LCase() and UCase() are re-defined on the right
              due to a problem affecting pre-existing LCase/UCase.
              That is a temp solution.
      }
Replace: {@Define:
            LineContinue: " _"
            Var: DefTypeInitial(255) As String
            Var: Specifier As Table = _
                 {"%", "Integer", "&", "Long", "&&", "Quad", _
                  "?", "Byte", "??", "Word", "???", "DWORD", _
                  "!", "Single", "#", "double", "##", "Extended", _
                  "@", "Currency", "@@", "CurrencyX", "$", "string"}
            Var: DefType As Table = _
                 {"INT", "Integer", "LNG", "Long", "QUD", "Quad", _
                 "BYT", "Byte", "WRD", "Word", "DWD", "Dword", _
                 "SNG", "Single", "DBL", "Double", "EXT", "Extended", _
                 "CUR", "Currency", "CUX", "CurrencyX", "STR", "String"}
            Var: dType="(INT|LNG|QUD|BYT|WRD|DWD|SNG|DBL|EXT|CUR|CUX|STR)\b"
            Func: LCase(c As String) As String = IIF(Asc(c) > 64 and Asc(c) < 91, Chr(Asc(c)+32), c)
            Func: UCase(c As String) As String = IIF(Asc(c) > 96 and Asc(c) < 123, Chr(Asc(c)-32), c)
         }{@Define:: Token: \x27.* ~~ Properties: ucWhitespace}

Criteria: 2
Comment: Handles DefType declarations; also inserts <Arg> marker for easier parsing
Pass: 1

Criteria: 3
Comment: Stores the DefType statement associated with character initials
Highlight: False
BackColor: Purple
Find: {"Def"}{type:"{@Eval: dType}"} {char} {nl}
Replace: {@Eval:
            SetVar(DefTypeInitial(Asc(LCase("{char}"))), ReadStr(DefType, "{type}"))
            SetVar(DefTypeInitial(Asc(UCase("{char}"))), ReadStr(DefType, "{type}"))
         }

Criteria: 4
Comment: Changes a DefType range into multiple DefType statements
Highlight: False
BackColor: SlateBlue
PassOnce: False
Find: {"Def"}{type:"{@Eval: dType}"} {from}-{to} {nl}
Replace: {@Eval: Range(Asc("{from}"), Asc("{to}"), "'Def{type} '+Chr(x)+Chr(10)")}

Criteria: 5
Comment: Break DefType statements containing commas into multiple DefStype statements (one per line)
Highlight: False
BackColor: Pink
PassOnce: False
Find: {"Def"}{type:"{@Eval: dType}"} {etc}, {more} {nl}
Replace: Def{type} {etc}
         Def{type} {more}

Criteria: 6
Comment: Inserts <arg> marker for easier parsing
Highlight: False
BackColor: Red
Find: {nl}{decl: Sub | Function } {etc} ({args})
Replace: {nl}{decl} {etc}(<Arg>{@Eval: Replace("{args}", ",", ", <Arg>")})

Criteria: 7
Highlight: False
SkipOver: True
Find: {nl}Function =
Replace: [Skip over]

Criteria: 8
Comment: Inserts ByRef to params that have neither ByRef nor ByVal
Pass: 2

Criteria: 9
Comment: Inserts ByRef in front of params that do not explicitlly have ByVal or ByRef
Highlight: False
BackColor: SandyBrown
Find: <Arg> [{optional: Optional}] {name:1}
Replace: <Arg>{optional} ByRef {name}

Criteria: 10
Comment: Skips params that already have ByVal or ByRef
Highlight: False
BackColor: Green
SkipOver: True
Find: <Arg> [Optional] { ByVal | ByRef }
Replace: [Skip over]

Criteria: 11
Comment: Adds explicit data types to arg or variable declarations (functions also)
Pass: 3

Criteria: 12
Highlight: False
BackColor: RoyalBlue
Find: <Arg> [Optional] {by: ByVal | ByRef } {name:1}
Replace: <Arg>{by} {name} As {@Eval: DefTypeInitial(Asc("{name}"))}

Criteria: 13
Highlight: False
Find: <Arg> [Optional] {by: ByVal | ByRef } {name:1}{spec:"[!?@#$%&]+"}
Replace: <Arg>{by} {name} As {@Eval: ReadStr(Specifier, "{spec}")}

Criteria: 14
Highlight: False
SkipOver: True
Find: <Arg> [Optional] {by: ByVal | ByRef } {name:1} As
Replace: [Skip over]

Criteria: 15
Highlight: False
BackColor: Tomato
PassOnce: False
Find: {decl: Dim | Global | Local | Static } {etc} {spec:"[!?@#$%&]+"}
Replace: {decl} {etc} As {@Eval: ReadStr(Specifier, "{spec}")}

Criteria: 16
Comment: Adds the appropriate type for functions with no explicit type or specifier
Highlight: False
BackColor: CornflowerBlue
Find: {nl}Function {name:1}([{args%}])
Replace: {nl}Function {name}({args}) As {@Eval: DefTypeInitial(Asc("{name}"))}

Criteria: 17
Comment: Changes function type specifier to data type name
Highlight: False
Find: {nl}Function {name:1}{spec:"[!?@#$%&]+"}([{args%}])
Replace: {nl}Function {name}({args}) As {@Eval: ReadStr(Specifier, "{spec}")}

Criteria: 18
Comment: Skips functions that already have an explicit type
Highlight: False
BackColor: Gold
Find: {nl}Function {name}([{args%}]) As {type}
Replace: {nl}Function {name}({args}) As {type}

Criteria: 19
Comment: Cleans up; removes <Arg> marker; as well as type specifiers
Pass: 4

Criteria: 20
Comment: Removes <Arg> that was inserted in earlier pass
Highlight: False
BackColor: SandyBrown
Find: <Arg>
Replace: {Nothing}

Criteria: 21
Comment: Removes statement specifiers
Highlight: False
BackColor: Violet
Find: {variable:"[a-z0-9_]+"}{spec:"[!?@#$%&]+"}
Replace: {variable}

# End Search


Update implicit-convert.uc

Update implicit-convert.uc

Improved type detection for array elements

# implicit-convert.uc - uCalc Transformation file
# This file was saved with uCalc Transform 2.96 on 5/28/2014 8:18:23 AM
# Comment: Handles implicit data type conversions

ExternalKeywords: Exclude, Comment, Selected, ParentChild, FindMode, InputFile, OutputFile, BatchAction, SEND
ExternalKeywords: Highlight, ForeColor, BackColor, FontName, FontSize, FontStyle
ExternalKeywords: FilterEndText, FilterSeparator, FilterSort, FilterSortFunc, FilterStartText, FilterUnique, FilterTally

FindMode: Replace

# Definitions

# Search Criteria

Criteria: 0
Enabled: False
Exclude: False
Comment: Handles implicit data type conversions
Selected: False
Highlight: True
ForeColor: ControlText
BackColor: Aqua
FontName:
FontSize:
FontStyle:
CaseSensitive: False
QuoteSensitive: False
CodeBlockSensitive: True
FilterEndText:
FilterSeparator: {#10}
FilterSort: False
FilterSortFunc:
FilterStartText:
FilterUnique: False
FilterTally: False
Min: 0
Max: -1
MinSoft: 0
MaxSoft: -1
BatchAction: Transform
InputFile:
OutputFile:
SEND:
StartAfter: 0
StopAfter: -1
SkipOver: False
ParentChild: 0
Pass: 0
PassOnce: True
Precedence: 0
RightToLeft: False

Criteria: 1
Enabled: True
Highlight: False
Find:
Replace: {@Eval:
            Dim Size As Table = {
               "Byte", 1, "Word", 2, "Integer", 2, "Long", 4, "Dword", 4,
               "Single", 4, "Double", 8, "Extended", 10
            }
         }
         {@Define:
            Var: Def As String
            Var: Args As String
            Var: Before As String
            Var: After As String
            Var: UDT As Table
            Var: Size
            Var: Final
            SyntaxArgL: {number} = {number:"([0-9]*\.)?[0-9]+(e[-+]?[0-9]+)?"}
         }
         {@Define:: Token: _.*\n ~~ Properties: ucWhitespace }

Criteria: 2
Comment: Inserts data type names in front of variabls and functions
Pass: 1

Criteria: 3
Enabled: True
Highlight: False
Find: {nl}[Declare] { Function | Sub } {name~:1} [Alias {alias}] ([{args%}]) [As {ftype:1=void}]
Replace: {@Exec:
            Args = Remove("{args}", "{ Optional | ByVal | ByRef | Ptr | () | {' *_.*\n *'} }")
            Before = Replace(Args, "{arg:1} As {type:1}", "{{arg}%}")
            After = Replace(Args, "{arg:1} As {type:1}", "##{type}({{arg}})")

            Def  = "Pass: 1 ~~ Syntax: {name}("+Before+")"
            Def += " ::= `{ftype}({name}(" + After + "))"
         }{@Define:: {@Eval: Def}}{Self}

Criteria: 4
Enabled: True
Selected: True
Highlight: False
Find: { Global | Local | Static | Dim | , | { ByVal | ByRef } } {var:1}[([{size}])] As {type:1}
Replace: {Self}{@Define:: Pass: 1 ~~ Syntax: {var}[({i%})] ::= `{type}({var}{i:({i})})}

Criteria: 5
Enabled: True
Highlight: False
Find: {number}
Replace: `Double({number})

Criteria: 6
Enabled: True
Highlight: False
BackColor: RoyalBlue
Find: {q}{text}{q}
Replace: `StringLit({Self})

Criteria: 7
Enabled: True
Highlight: False
BackColor: Pink
Find: {func: Asc|InStr|Len|UBound|VarPtr|StrPtr|Dir|CurDir } ({args%})
Replace: `Long({func}({args}))

Criteria: 8
Enabled: True
Highlight: False
BackColor: SlateBlue
Find: {func:
         Mid|Left|Right|Remove|Extract|Space|Hex|Oct|Bin|Dir|Min|Max|
         Remain|UCase|LCase|Trim|LTrim|RTrim|Choose|Repeat
      }$({args%})
Replace: `String({func}$({args}))

Criteria: 9
Enabled: True
Find: {nl}${equate:1}
Replace: {Self}{@Define:: Pass: 1 ~~ Syntax: ${equate} ::= `String(${equate})}

Criteria: 10
Enabled: True
Find: {nl}$${equate:1}
Replace: {Self}{@Define:: Pass: 1 ~~ Syntax: $${equate} ::= `WString($${equate})}

Criteria: 11
Enabled: True
Find: {nl}%{equate:1}
Replace: {Self}{@Define:: Pass: 1 ~~ Syntax: %{equate} ::= `Long(%{equate})}

Criteria: 12
Enabled: True
Highlight: False
BackColor: Purple
SkipOver: True
Find: {nl} { Type | Union }
         {members+}
      End {TypeOrUnion}
Replace: [Skip over]

Criteria: 13
Enabled: True
BackColor: Khaki
SkipOver: True
Find: {nl}{ # | ! | ASM } {etc} {@Note: Skips metastatements, ASM}
Replace: [Skip over]

Criteria: 14
Enabled: True
SkipOver: True
Find: ' {Comment:".*"}
Replace: [Skip over]

Criteria: 15
Comment: Convert
Pass: 2

Criteria: 16
Enabled: True
BackColor: Violet
PassOnce: False
Find: ##Asciiz(string({arg}))
Replace: `Asciiz({arg}.c_str())

Criteria: 17
Enabled: True
Find: `StringLit({arg})
Replace: `String({arg})

Criteria: 18
Enabled: True
PassOnce: False
Find: `StringLit({arg})+`StringLit({arg})
Replace: `String(string({arg})+{arg})

Criteria: 19
Enabled: True
BackColor: CornflowerBlue
PassOnce: False
Find: `WString({arg}) + `String({arg})
Replace: `WString({arg}) + `WString(string({arg}))

Criteria: 20
Enabled: True
Find: Len({other})
Replace: sizeof({other})

Criteria: 21
Enabled: True
BackColor: SandyBrown
PassOnce: False
Find: Len(`String({arg}))
Replace: string({arg}).length()

Criteria: 22
Enabled: True
BackColor: Gold
PassOnce: False
Find: Len(`LPCSTR({arg}))
Replace: `Long(strlen({arg}))

Criteria: 23
Enabled: True
PassOnce: False
Find: `{ Extended | Ext }
Replace: `Double

Criteria: 24
Enabled: True
SkipOver: True
Find: ' {Comment:".*"}
Replace: [Skip over]

Criteria: 25
Comment: Highlights the inserted data type names
Pass: 3

Criteria: 26
Enabled: True
Find: {@Start}
      {@Note:
         The use of Final is due to a limitation where immediate expansion in
         {arg%} expands with all passes causing the undesirable change in pass 3
         before it is needed.
      }
Replace: {@Exec: Final = True}

Criteria: 27
Enabled: False
BackColor: Red
Find: ##{type:1}
Replace: {Self}

Criteria: 28
Enabled: False
Comment: This line is there to provide highlighting for clarity
Find: `{type:1}
Replace: {Self}

Criteria: 29
Enabled: True
PassOnce: False
Find: { ` | ## }{type:1}({arg}) {@If: Final}
Replace: {arg}

# End Search

# implicit-convert.uc - uCalc Transformation file
# This file was saved with uCalc Transform 2.96 on 5/27/2014 6:24:47 PM
# Comment: Handles implicit data type conversions

ExternalKeywords: Exclude, Comment, Selected, ParentChild, FindMode, InputFile, OutputFile, BatchAction, SEND
ExternalKeywords: Highlight, ForeColor, BackColor, FontName, FontSize, FontStyle
ExternalKeywords: FilterEndText, FilterSeparator, FilterSort, FilterSortFunc, FilterStartText, FilterUnique, FilterTally

FindMode: Replace

# Definitions

# Search Criteria

Criteria: 0
Enabled: False
Exclude: False
Comment: Handles implicit data type conversions
Selected: False
Highlight: True
ForeColor: ControlText
BackColor: Aqua
FontName:
FontSize:
FontStyle:
CaseSensitive: False
QuoteSensitive: False
CodeBlockSensitive: True
FilterEndText:
FilterSeparator: {#10}
FilterSort: False
FilterSortFunc:
FilterStartText:
FilterUnique: False
FilterTally: False
Min: 0
Max: -1
MinSoft: 0
MaxSoft: -1
BatchAction: Transform
InputFile:
OutputFile:
SEND:
StartAfter: 0
StopAfter: -1
SkipOver: False
ParentChild: 0
Pass: 0
PassOnce: True
Precedence: 0
RightToLeft: False

Criteria: 1
Enabled: True
Highlight: False
Find:
Replace: {@Eval:
            Dim Size As Table = {
               "Byte", 1, "Word", 2, "Integer", 2, "Long", 4, "Dword", 4,
               "Single", 4, "Double", 8, "Extended", 10
            }
         }
         {@Define:
            Var: Def As String
            Var: Args As String
            Var: Before As String
            Var: After As String
            Var: UDT As Table
            Var: Size
            Var: Final
            SyntaxArgL: {number} = {number:"([0-9]*\.)?[0-9]+(e[-+]?[0-9]+)?"}
         }
         {@Define:: Token: _.*\n ~~ Properties: ucWhitespace }

Criteria: 2
Comment: Inserts data type names in front of variabls and functions
Pass: 1

Criteria: 3
Enabled: True
Highlight: False
Find: {nl}[Declare] { Function | Sub } {name~:1} [Alias {alias}] ([{args%}]) [As {ftype:1=void}]
Replace: {@Exec:
            Args = Remove("{args}", "{ Optional | ByVal | ByRef | Ptr | () | {' *_.*\n *'} }")
            Before = Replace(Args, "{arg:1} As {type:1}", "{{arg}%}")
            After = Replace(Args, "{arg:1} As {type:1}", "##{type}({{arg}})")

            Def  = "Pass: 1 ~~ Syntax: {name}("+Before+")"
            Def += " ::= `{ftype}({name}(" + After + "))"
         }{@Define:: {@Eval: Def}}{Self}

Criteria: 4
Enabled: True
Highlight: False
Find: { Global | Local | Static | Dim | , | { ByVal | ByRef } } {var:1}[()] As {type:1}
Replace: {Self}{@Define:: Pass: 1 ~~ Syntax: {var} ::= `{type}({var})}

Criteria: 5
Enabled: True
Highlight: False
Find: {number}
Replace: `Double({number})

Criteria: 6
Enabled: True
Highlight: False
BackColor: RoyalBlue
Find: {q}{text}{q}
Replace: `StringLit({Self})

Criteria: 7
Enabled: True
Highlight: False
BackColor: Pink
Find: {func: Asc|InStr|Len|UBound|VarPtr|StrPtr|Dir|CurDir } ({args%})
Replace: `Long({func}({args}))

Criteria: 8
Enabled: True
Highlight: False
BackColor: SlateBlue
Find: {func:
         Mid|Left|Right|Remove|Extract|Space|Hex|Oct|Bin|Dir|Min|Max|
         Remain|UCase|LCase|Trim|LTrim|RTrim|Choose|Repeat
      }$({args%})
Replace: `String({func}$({args}))

Criteria: 9
Enabled: True
Find: {nl}${equate:1}
Replace: {Self}{@Define:: Pass: 1 ~~ Syntax: ${equate} ::= `String(${equate})}

Criteria: 10
Enabled: True
Find: {nl}$${equate:1}
Replace: {Self}{@Define:: Pass: 1 ~~ Syntax: $${equate} ::= `WString($${equate})}

Criteria: 11
Enabled: True
Find: {nl}%{equate:1}
Replace: {Self}{@Define:: Pass: 1 ~~ Syntax: %{equate} ::= `Long(%{equate})}

Criteria: 12
Enabled: True
Highlight: False
BackColor: Purple
SkipOver: True
Find: {nl} { Type | Union }
         {members+}
      End {TypeOrUnion}
Replace: [Skip over]

Criteria: 13
Enabled: True
BackColor: Khaki
SkipOver: True
Find: {nl}{ # | ! | ASM } {etc} {@Note: Skips metastatements, ASM}
Replace: [Skip over]

Criteria: 14
Enabled: True
SkipOver: True
Find: ' {Comment:".*"}
Replace: [Skip over]

Criteria: 15
Comment: Convert
Pass: 2

Criteria: 16
Enabled: True
BackColor: Violet
PassOnce: False
Find: ##Asciiz(string({arg}))
Replace: `Asciiz({arg}.c_str())

Criteria: 17
Enabled: True
Find: `StringLit({arg})
Replace: `String({arg})

Criteria: 18
Enabled: True
PassOnce: False
Find: `StringLit({arg})+`StringLit({arg})
Replace: `String(string({arg})+{arg})

Criteria: 19
Enabled: True
BackColor: CornflowerBlue
PassOnce: False
Find: `WString({arg}) + `String({arg})
Replace: `WString({arg}) + `WString(string({arg}))

Criteria: 20
Enabled: True
Find: Len({other})
Replace: sizeof({other})

Criteria: 21
Enabled: True
BackColor: SandyBrown
PassOnce: False
Find: Len(`String({arg}))
Replace: string({arg}).length()

Criteria: 22
Enabled: True
BackColor: Gold
PassOnce: False
Find: Len(`LPCSTR({arg}))
Replace: `Long(strlen({arg}))

Criteria: 23
Enabled: True
PassOnce: False
Find: `{ Extended | Ext }
Replace: `Double

Criteria: 24
Enabled: True
Selected: True
SkipOver: True
Find: ' {Comment:".*"}
Replace: [Skip over]

Criteria: 25
Comment: Highlights the inserted data type names
Pass: 3

Criteria: 26
Enabled: True
Find: {@Start}
      {@Note:
         The use of Final is due to a limitation where immediate expansion in
         {arg%} expands with all passes causing the undesirable change in pass 3
         before it is needed.
      }
Replace: {@Exec: Final = True}

Criteria: 27
Enabled: False
BackColor: Red
Find: ##{type:1}
Replace: {Self}

Criteria: 28
Enabled: False
Comment: This line is there to provide highlighting for clarity
Find: `{type:1}
Replace: {Self}

Criteria: 29
Enabled: True
PassOnce: False
Find: { ` | ## }{type:1}({arg}) {@If: Final}
Replace: {arg}

# End Search