// COMMON AI SYSTEMS INCLUDES
#using scripts\shared\ai_shared;
#using scripts\shared\ai_shared;
#using scripts\shared\ai\systems\ai_blackboard;
#using scripts\shared\ai\systems\ai_interface;
#using scripts\shared\ai\systems\animation_state_machine_utility;
#using scripts\shared\ai\systems\behavior_tree_utility;
#using scripts\shared\ai\systems\blackboard;

   	     	                                                                                                                                                                                                                                                                                                                                                                                                                                                             	                                                                                                                	         	    	                                                                                                    
           	                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              	  	                                 	                  	    	                                                      	   	        	                                                                         	                      	             	                                                                                                                                       	  	                                                                                                          	     	                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            	                                                                                                      	                                                                                                     	                                                                                                     	                                                                                                	     	                                                                                                                                                                                                                                                                                                                                                                                                                                	     	    	                                                                                                                                    	                      	              	  	             	  
        	                                                                                                                                                	                                                                                                                      	                                                                                     	                                                                                     	                                                            	                                                                                   	                                                                                     	                                                                                               	                                                                                                 	                                                                   	                                                                   	                                                                                                                 	                                                                                                                              	                                                                                                                       	                                                   	                                                                           	                                                                                 	                                       	                             	                                             	                                  	                                                                                 	                                                                                                                                                	      
                                                                                                                                               	

// ADDITIONAL INCLUDES
#using scripts\shared\ai\archetype_utility; 
#using scripts\shared\ai\archetype_cover_utility; 
#using scripts\shared\array_shared;
#using scripts\shared\laststand_shared;

                                                                  	                             	  	                                      
    	   	                                                                                                                                         	                                	                                                                                                                                                                                                                                                                                                                                                                    	        	     	              	    	   	               	                                              	                                                           	                               	                     	                                                                                                           	                                                                 	                                                              	                                                                                                                                             	                            	                                     	                                       	                                                                                                              	   	                  	       	                                                    	                   	                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            	                                                                                                 	                                    	                                                                                        	           	                        	                                            	                                             	                                                   	                                                             	                                                         	                                                                    	                                                                                                                                                                                                                                	                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  	    	         	                                                              	                                                          	                                   	                                   	                                                    	                                       	                                           	     	                                                                                                                                                                                                                                                      	                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         	                                                               	        	                                                                                                                              	                                                                                                                     	                               	                                                      	                          

function autoexec RegisterBehaviorScriptfunctions()
{	
	BehaviorTreeNetworkUtility::RegisterBehaviorTreeScriptAPI("shouldReturnToCoverCondition",&shouldReturnToCoverCondition);;
	BehaviorTreeNetworkUtility::RegisterBehaviorTreeScriptAPI("shouldReturnToSuppressedCover",&shouldReturnToSuppressedCover);;
			
	BehaviorTreeNetworkUtility::RegisterBehaviorTreeScriptAPI("shouldAdjustToCover",&shouldAdjustToCover);;
	BehaviorTreeNetworkUtility::RegisterBehaviorTreeScriptAPI("prepareForAdjustToCover",&prepareForAdjustToCover);;
			
	BehaviorTreeNetworkUtility::RegisterBehaviorTreeScriptAPI("coverBlindfireShootStart",&coverBlindfireShootActionStart);;
	
	BehaviorTreeNetworkUtility::RegisterBehaviorTreeScriptAPI("canChangeStanceAtCoverCondition",&canChangeStanceAtCoverCondition);;
	BehaviorTreeNetworkUtility::RegisterBehaviorTreeScriptAPI("coverChangeStanceActionStart",&coverChangeStanceActionStart);;
		
	BehaviorTreeNetworkUtility::RegisterBehaviorTreeScriptAPI("prepareToChangeStanceToStand",&prepareToChangeStanceToStand);;
	BehaviorTreeNetworkUtility::RegisterBehaviorTreeScriptAPI("cleanUpChangeStanceToStand",&cleanUpChangeStanceToStand);;

	BehaviorTreeNetworkUtility::RegisterBehaviorTreeScriptAPI("prepareToChangeStanceToCrouch",&prepareToChangeStanceToCrouch);;
	BehaviorTreeNetworkUtility::RegisterBehaviorTreeScriptAPI("cleanUpChangeStanceToCrouch",&cleanUpChangeStanceToCrouch);;

	BehaviorTreeNetworkUtility::RegisterBehaviorTreeScriptAPI("shouldVantageAtCoverCondition",&shouldVantageAtCoverCondition);;
	BehaviorTreeNetworkUtility::RegisterBehaviorTreeScriptAPI("supportsVantageCoverCondition",&supportsVantageCoverCondition);;
	BehaviorTreeNetworkUtility::RegisterBehaviorTreeScriptAPI("coverVantageInitialize",&coverVantageInitialize);;
	
	BehaviorTreeNetworkUtility::RegisterBehaviorTreeScriptAPI("shouldThrowGrenadeAtCoverCondition",&shouldThrowGrenadeAtCoverCondition);;
	BehaviorTreeNetworkUtility::RegisterBehaviorTreeScriptAPI("coverPrepareToThrowGrenade",&coverPrepareToThrowGrenade);;
	BehaviorTreeNetworkUtility::RegisterBehaviorTreeScriptAPI("coverCleanUpToThrowGrenade",&coverCleanUpToThrowGrenade);;
	
	BehaviorTreeNetworkUtility::RegisterBehaviorTreeScriptAPI("senseNearbyPlayers",&senseNearbyPlayers);;
}

function shouldThrowGrenadeAtCoverCondition( behaviorTreeEntity, throwIfPossible = false )
{	
	// sjakatdar - Please do not use level.AIDisableGrenadeThrows, not a preferred method to disable grenades by script. Only used by campaign zombies.
	if( ( isdefined( level.AIDisableGrenadeThrows ) && level.AIDisableGrenadeThrows ) )
	{
		return false;
	}
	
	if( !IsDefined(  behaviorTreeEntity.enemy ) )
	{
		return false;
	}
	
	if ( !IsSentient( behaviorTreeEntity.enemy ) )
	{
		return false;
	}
	
	if ( IsVehicle( behaviorTreeEntity.enemy ) && behaviorTreeEntity.enemy.vehicleclass === "helicopter" )
	{
		return false;
	}
	
	if ( ai::HasAiAttribute( behaviorTreeEntity, "useGrenades" ) && !ai::GetAiAttribute( behaviorTreeEntity, "useGrenades" ) )
	{
		return false;
	}
	
	// Only throw a grenade if the enemy is within 60 degrees to the left or right of where the actor or the actor's node is facing.
	entityAngles = behaviorTreeEntity.angles;

	if ( IsDefined( behaviorTreeEntity.node ) &&
		( (behaviorTreeEntity.node.type == "Cover Left") || (behaviorTreeEntity.node.type == "Cover Right") || (behaviorTreeEntity.node.type == "Cover Pillar") || (behaviorTreeEntity.node.type == "Cover Stand" || behaviorTreeEntity.node.type == "Conceal Stand") || (behaviorTreeEntity.node.type == "Cover Crouch" || behaviorTreeEntity.node.type == "Cover Crouch Window" || behaviorTreeEntity.node.type == "Conceal Crouch" ) ) &&
		behaviorTreeEntity IsAtCoverNodeStrict() )
	{
		entityAngles = behaviorTreeEntity.node.angles;
	}
	
	toEnemy = behaviorTreeEntity.enemy.origin - behaviorTreeEntity.origin;
	toEnemy = VectorNormalize( ( toEnemy[0], toEnemy[1], 0 ) );
	
	entityForward = AnglesToForward( entityAngles );
	entityForward = VectorNormalize( ( entityForward[0], entityForward[1], 0 ) );
	
	// cos( 60 degrees ) = 0.5
	if ( VectorDot( toEnemy, entityForward ) < 0.5 )
	{
		return false;
	}
	
	if ( !throwIfPossible ) 
	{
		// Don't throw grenades at enemys that are next to players.
		if ( behaviorTreeEntity.team === "allies" )
		{
			foreach( player in level.players )
			{
				if( DistanceSquared( behaviorTreeEntity.enemy.origin, player.origin ) <= (500 * 500 ) )
				{
					return false;
				}
			}
		}
		
		// Don't throw grenades at enemies that are close to laststand players.
		foreach( player in level.players )
		{
			if ( player laststand::player_is_in_laststand() &&
				DistanceSquared( behaviortreeentity.enemy.origin, player.origin ) <= (500 * 500 ) )
			{
				return false;
			}
		}
	
		// if there was a grenade thrown by the same team recently, don't throw another one
		grenadeThrowInfos = Blackboard::GetBlackboardEvents( "team_grenade_throw" );
		foreach ( grenadeThrowInfo in grenadeThrowInfos )
		{
			if( grenadeThrowInfo.data.grenadeThrowerTeam === behaviorTreeEntity.team )
			{
				return false;
			}
		}
	
		// if there was a grenade that was thrown at the enemy recently, then dont throw it again
		grenadeThrowInfos = Blackboard::GetBlackboardEvents( "human_grenade_throw" );
		
		foreach ( grenadeThrowInfo in grenadeThrowInfos )
		{
			if( IsDefined( grenadeThrowInfo.data.grenadeThrownAt ) && IsAlive( grenadeThrowInfo.data.grenadeThrownAt ) )
			{
				if( grenadeThrowInfo.data.grenadeThrower == behaviorTreeEntity )
				{
					return false;
				}
			
				if( IsDefined( grenadeThrowInfo.data.grenadeThrownAt ) &&
					grenadeThrowInfo.data.grenadeThrownAt == behaviorTreeEntity.enemy )
				{
					return false;
				}
				
				if ( IsDefined( grenadeThrowInfo.data.grenadeThrownPosition ) &&
					IsDefined( behaviorTreeEntity.grenadeThrowPosition ) &&
					DistanceSquared( grenadeThrowInfo.data.grenadeThrownPosition, behaviorTreeEntity.grenadeThrowPosition ) <= (600 * 600) )
				{
					// Prevent too many grenades in the same area.
					return false;
				}
			}
		}
	}
	
	throw_dist = Distance2DSquared( behaviorTreeEntity.origin, behaviorTreeEntity LastKnownPos( behaviorTreeEntity.enemy ) );
	if ( throw_dist < ( (500) * (500) ) || throw_dist > ( (1250) * (1250) ) )
	{
		return false;
	}
	
	arm_offset = TEMP_get_arm_offset( behaviorTreeEntity, behaviorTreeEntity LastKnownPos( behaviorTreeEntity.enemy ) );
	throw_vel = behaviorTreeEntity CanThrowGrenadePos( arm_offset, behaviorTreeEntity LastKnownPos( behaviorTreeEntity.enemy ) );

	if ( !IsDefined( throw_vel ) )
	{
		return false;
	}
	
	return true;
}



function private senseNearbyPlayers( entity )
{
	players = GetPlayers();
	
	foreach ( player in players )
	{
		distanceSq = DistanceSquared( player.origin, entity.origin );
		
		if ( distanceSq <= ( (360) * (360) ) )
		{
			distanceToPlayer = Sqrt( distanceSq );
			
			chanceToDetect = RandomFloat( 1.0 );
			
			if ( chanceToDetect < ( distanceToPlayer / 360 ) )
			{
				entity GetPerfectInfo( player );
			}
		}
	}
}

function private coverPrepareToThrowGrenade( behaviorTreeEntity )
{	
	AiUtility::keepClaimedNodeAndChooseCoverDirection( behaviorTreeEntity );
	
	if ( IsDefined( behaviorTreeEntity.enemy ) )
	{
		behaviorTreeEntity.grenadeThrowPosition = behaviorTreeEntity LastKnownPos( behaviorTreeEntity.enemy );
	}
	
	grenadeThrowInfo = SpawnStruct();
	grenadeThrowInfo.grenadeThrower = behaviorTreeEntity;
	grenadeThrowInfo.grenadeThrownAt = behaviorTreeEntity.enemy;
	grenadeThrowInfo.grenadeThrownPosition = behaviorTreeEntity.grenadeThrowPosition;
	Blackboard::AddBlackboardEvent( "human_grenade_throw", grenadeThrowInfo, RandomIntRange( 15000, 20000 ) );
	
	grenadeThrowInfo = SpawnStruct();
	grenadeThrowInfo.grenadeThrowerTeam = behaviorTreeEntity.team;
	Blackboard::AddBlackboardEvent( "team_grenade_throw", grenadeThrowInfo, RandomIntRange( 1000, 2000 ) );
	
	behaviorTreeEntity.prepareGrenadeAmmo = behaviorTreeEntity.grenadeammo;
}

function private coverCleanUpToThrowGrenade( behaviorTreeEntity )
{
	AiUtility::resetCoverParameters( behaviorTreeEntity );
	
	if ( behaviorTreeEntity.prepareGrenadeAmmo == behaviorTreeEntity.grenadeammo )
	{
		// Actor was killed before being able to drop a grenade, drop one instead.
		if ( behaviorTreeEntity.health <= 0 )
		{
			grenade = undefined;
		
			// Need someone living to spawn the dropped grenade, otherwise it cannot be picked up.
			if ( IsActor( behaviorTreeEntity.enemy ) && IsDefined( behaviorTreeEntity.grenadeweapon ) )
			{
				grenade = behaviorTreeEntity.enemy MagicGrenadeType(
					behaviorTreeEntity.grenadeweapon,
					behaviorTreeEntity GetTagOrigin( "j_wrist_ri" ),
					(0, 0, 0),
					behaviorTreeEntity.grenadeweapon.aifusetime / 1000 );
			}
			else if ( IsPlayer( behaviorTreeEntity.enemy ) && IsDefined( behaviorTreeEntity.grenadeweapon ) )
			{
				grenade = behaviorTreeEntity.enemy MagicGrenadePlayer(
					behaviorTreeEntity.grenadeweapon,
					behaviorTreeEntity GetTagOrigin( "j_wrist_ri" ),
					(0, 0, 0) );
			}
			
			if ( IsDefined( grenade ) )
			{
				grenade.owner = behaviorTreeEntity;
				grenade.team = behaviorTreeEntity.team;
				// Since the grenade is spawned so closely to the actor, disable collision against the actor.
				grenade SetContents( grenade SetContents( 0 ) & ~( (1 << 15) | (1 << 26) | (1 << 23) | (1 << 25) ) );
			}
		}
	}
}

function private canChangeStanceAtCoverCondition( behaviorTreeEntity )
{
	switch ( Blackboard::GetBlackBoardAttribute( behaviorTreeEntity, "_stance" ) )
	{
		case "stand":
			return AiUtility::isStanceAllowedAtNode( "crouch", behaviorTreeEntity.node );
		case "crouch":
			return AiUtility::isStanceAllowedAtNode( "stand", behaviorTreeEntity.node );
	}
	
	return false;
}

function private shouldReturnToSuppressedCover( entity )
{
	if ( !entity IsAtGoal() )
	{
		return true;
	}

	return false;
}

function private shouldReturnToCoverCondition( behaviorTreeEntity )
{
	if ( behaviorTreeEntity ASMIsTransitionRunning() )
	{
		return false;
	}
		
	if ( IsDefined( behaviorTreeEntity.coverShootStartTime ) )
	{
		// take a few shots before returning
		if ( GetTime() < behaviorTreeEntity.coverShootStartTime + 800 )
		{
			return false;
		}

		// try to finish off enemy
		if ( IsDefined( behaviorTreeEntity.enemy ) &&
			IsPlayer( behaviorTreeEntity.enemy ) &&
			behaviorTreeEntity.enemy.health < behaviorTreeEntity.enemy.maxHealth * 0.5 )
		{
			if ( GetTime() < behaviorTreeEntity.coverShootStartTime + 3000 )
			{
				return false;
			}
		}
	}
	
	if ( AiUtility::isSuppressedAtCoverCondition( behaviorTreeEntity ) )
	{
		return true;
	}
	
	if ( !behaviorTreeEntity IsAtGoal() )
	{
		// AI's that lean out of cover can fall outside of a very small goalradius, use the node's position instead.
		if ( IsDefined( behaviorTreeEntity.node ) )
		{
			offsetOrigin = behaviorTreeEntity GetNodeOffsetPosition( behaviorTreeEntity.node );
		
			return !behaviorTreeEntity IsPosAtGoal( offsetOrigin );
		}
		
		return true;
	}
	
	if ( !behaviorTreeEntity IsSafeFromGrenade() )
	{
		return true;
	}

	return false;
}

function private shouldAdjustToCover( behaviorTreeEntity ) 
{
	if( !IsDefined( behaviorTreeEntity.node ) )
	{
		return false;
	}
	
	// if the current stance is crouch, and highest supported stance for the node is crouch too then, 
	// there are no animations for that. Just do a pure animation blend.
	highestSupportedStance = AiUtility::getHighestNodeStance( behaviorTreeEntity.node );
	currentStance = Blackboard::GetBlackBoardAttribute( behaviorTreeEntity, "_stance" );
	
	if( currentStance == "crouch" && highestSupportedStance == "crouch" )
	{
		return false;
	}
	
	// if AI has just arrived at this cover node ( meaning previousCoverMode != COVER_ALERT_MODE )
	// That means he needs to adjust to the cover for the first time
	coverMode = Blackboard::GetBlackBoardAttribute( behaviorTreeEntity, "_cover_mode" );
	previousCoverMode = Blackboard::GetBlackBoardAttribute( behaviorTreeEntity, "_previous_cover_mode" );

	if ( coverMode != "cover_alert" && previousCoverMode != "cover_alert" && !behaviorTreeEntity.keepClaimedNode )
	{		
		return true;
	}

	// if somehow the AI is at the covernode with appropriate COVER_MODE, but unsupported stance, then 
	// let him adjust to the cover node.
	if( !AiUtility::isStanceAllowedAtNode( currentStance, behaviorTreeEntity.node ) )
	{
		return true;
	}
	
	return false;
}


// ------- COVER - VANTAGE SHOOT BEHAVIOR -----------//
// TODO - Fix and enable vantage behavior.
function private shouldVantageAtCoverCondition( behaviorTreeEntity )
{
	if( !IsDefined( behaviorTreeEntity.node ) ||
		!IsDefined( behaviorTreeEntity.node.type ) ||
		!IsDefined( behaviorTreeEntity.enemy) ||
		!IsDefined( behaviorTreeEntity.enemy.origin ) )
	{
		return false;
	}
		
	yawToEnemyPosition = AiUtility::GetAimYawToEnemyFromNode( behaviorTreeEntity, behaviorTreeEntity.node, behaviorTreeEntity.enemy );
	pitchToEnemyPosition = AiUtility::GetAimPitchToEnemyFromNode( behaviorTreeEntity, behaviorTreeEntity.node, behaviorTreeEntity.enemy );
	aimLimitsForCover = behaviortreeentity GetAimLimitsFromEntry("cover_vantage");
	
	legalAim = false;

	// allow vantage aiming if our target is within the 25 to 85 degree arc in front of us and 3 or more feet below us
	if ( yawToEnemyPosition < aimLimitsForCover["aim_left"] &&
		 yawToEnemyPosition > aimLimitsForCover["aim_right"] &&
		 pitchToEnemyPosition < 85.0 &&
		 pitchToEnemyPosition > 25.0 &&
		 ( behaviorTreeEntity.node.origin[2] - behaviorTreeEntity.enemy.origin[2] ) >= ( 3 * 12 ) )
	{
		legalAim = true;
	}

	return legalAim;
}

function private supportsVantageCoverCondition( behaviorTreeEntity )
{
	return false;
	
	/*
	coverMode = Blackboard::GetBlackBoardAttribute( behaviorTreeEntity, COVER_MODE );
	
	if ( IsDefined( behaviorTreeEntity.node ) && IsDefined( coverMode ) && coverMode == COVER_ALERT_MODE )
	{
		if( NODE_COVER_CROUCH( behaviorTreeEntity.node ) || NODE_COVER_STAND( behaviorTreeEntity.node ) )
		{
			return true;
		}			
	}
	
	return false;
	*/
}

function private coverVantageInitialize( behaviorTreeEntity, asmStateName )
{
	AiUtility::keepClaimNode( behaviorTreeEntity );
	Blackboard::SetBlackBoardAttribute( behaviorTreeEntity, "_cover_mode", "cover_vantage" );
}
	
// ------- COVER - BLINDFIRE SHOOT BEHAVIOR -----------//
function private coverBlindfireShootActionStart( behaviorTreeEntity, asmStateName )
{
	AiUtility::keepClaimNode( behaviorTreeEntity );
	Blackboard::SetBlackBoardAttribute( behaviorTreeEntity, "_cover_mode", "cover_blind" );
	AiUtility::chooseCoverDirection( behaviorTreeEntity );
}

// ------- COVER - CHANGE STANCE BEHAVIOR -----------//
function private prepareToChangeStanceToStand( behaviorTreeEntity, asmStateName )
{
	AiUtility::cleanupCoverMode( behaviorTreeEntity );
	Blackboard::SetBlackBoardAttribute( behaviorTreeEntity, "_desired_stance", "stand" );
}

function private cleanUpChangeStanceToStand( behaviorTreeEntity, asmStateName )
{
	AiUtility::releaseClaimNode( behaviorTreeEntity );
	behaviorTreeEntity.newEnemyReaction = false;
}

function private prepareToChangeStanceToCrouch( behaviorTreeEntity, asmStateName )
{
	AiUtility::cleanupCoverMode( behaviorTreeEntity );
	Blackboard::SetBlackBoardAttribute( behaviorTreeEntity, "_desired_stance", "crouch" );
}

function private cleanUpChangeStanceToCrouch( behaviorTreeEntity, asmStateName )
{
	AiUtility::releaseClaimNode( behaviorTreeEntity );
	behaviorTreeEntity.newEnemyReaction = false;
}

// ------- COVER - ADJUST STANCE BEHAVIOR -----------//
function private prepareForAdjustToCover( behaviorTreeEntity, asmStateName )
{
	AiUtility::keepClaimNode( behaviorTreeEntity );
	
	highestSupportedStance = AiUtility::getHighestNodeStance( behaviorTreeEntity.node );
	Blackboard::SetBlackBoardAttribute( behaviorTreeEntity, "_desired_stance", highestSupportedStance );
}

// ------- COVER - CHANGE STANCE BEHAVIOR -----------
function private coverChangeStanceActionStart( behaviorTreeEntity, asmStateName )
{
	Blackboard::SetBlackBoardAttribute( behaviorTreeEntity, "_cover_mode", "cover_alert" );
	AiUtility::keepClaimNode( behaviorTreeEntity );

	switch ( Blackboard::GetBlackBoardAttribute( behaviorTreeEntity, "_stance" ) )
	{
		case "stand":
			Blackboard::SetBlackBoardAttribute( behaviorTreeEntity, "_desired_stance", "crouch" );
			break;
		case "crouch":
			Blackboard::SetBlackBoardAttribute( behaviorTreeEntity, "_desired_stance", "stand" );
			break;
	}
}



function TEMP_get_arm_offset( behaviorTreeEntity, throwPosition )
{
	stance = Blackboard::GetBlackBoardAttribute( behaviorTreeEntity, "_stance" );
	arm_offset = undefined;

	// ( forward/back, left/right, up/down )
	if ( stance == "crouch" )
	{
		arm_offset = ( 13, -1, 56 );
	}
	else
	{
		arm_offset = ( 14, -3, 80 );
	}
	
	if( IsDefined( behaviorTreeEntity.node ) && behaviorTreeEntity IsAtCoverNodeStrict() )
	{
		if( (behaviorTreeEntity.node.type == "Cover Left") )
		{
			if ( stance == "crouch" )
			{
				arm_offset = ( -38, 15, 23 );
			}
			else
			{
				arm_offset = ( -45, 0, 40 );
			}
		}
		else if( (behaviorTreeEntity.node.type == "Cover Right") )
		{
			if ( stance == "crouch" )
			{
				arm_offset = ( 46, 12, 26 );
			}
			else
			{
				arm_offset = ( 34, -21, 50 );
			}
		}
		else if( (behaviorTreeEntity.node.type == "Cover Stand" || behaviorTreeEntity.node.type == "Conceal Stand") )
		{
			arm_offset = ( 10, 7, 77 );
		}
		else if( (behaviorTreeEntity.node.type == "Cover Crouch" || behaviorTreeEntity.node.type == "Cover Crouch Window" || behaviorTreeEntity.node.type == "Conceal Crouch" ) )
		{
			arm_offset = ( 19, 5, 60 );
		}
		else if( (behaviorTreeEntity.node.type == "Cover Pillar") )
		{
			leftOffset = undefined;
			rightOffset = undefined;
		
			if ( stance == "crouch" )
			{
				leftOffset = ( -20, 0, 35 );
				rightOffset = ( 34, 6, 50 );
			}
			else
			{
				leftOffset = ( -24, 0, 76 );
				rightOffset = ( 24, 0, 76 );
			}
		
			if( ( (isdefined(behaviorTreeEntity.node.spawnflags)&&((behaviorTreeEntity.node.spawnflags & 1024) == 1024))) )
			{
				arm_offset = rightOffset;
			}
			else if( ( (isdefined(behaviorTreeEntity.node.spawnflags)&&((behaviorTreeEntity.node.spawnflags & 2048) == 2048))) )
			{
				arm_offset = leftOffset;
			}
			else
			{
				yawToEnemyPosition = AngleClamp180( VectorToAngles( throwPosition - behaviorTreeEntity.node.origin )[1] - behaviorTreeEntity.node.angles[1] );
				aimLimitsForDirectionRight = behaviortreeentity GetAimLimitsFromEntry( "pillar_right_lean" );
				
				legalRightDirectionYaw = yawToEnemyPosition >= ( aimLimitsForDirectionRight["aim_right"] - 10 ) && yawToEnemyPosition <= 0;
				
				if( legalRightDirectionYaw )
				{
					arm_offset = rightOffset;
				}
				else
				{
					arm_offset = leftOffset;
				}
			}
		}
	}

	return arm_offset;
}
