/**
 * ExileClient_construction_thread
 *
 * Exile Mod
 * www.exilemod.com
 * © 2015 Exile Mod Team
 *
 * This work is licensed under the Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License. 
 * To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-nd/4.0/.
 * 
	eXpochClient_FREE_vectorBuilding
	
	Made for Anarchy, adapted to eXpoch and ported into Altis Life and Operation BlockHead by DirtySanchez
	
	and NOW EXILE WILL FEEL THE FREE VECTOR, go get a job sellers of scripts, this is a modding community.
	Sharing is caring and douchebaggery is a bannable offense
	
	http://DonkeyPunch.INFO
 */
 
private["_boundingBox","_boundingBoxMinimum","_boundingBoxMaximum","_boundingBoxPointsTop","_boundingBoxPointsBottom","_objectColor","_materialColor","_simulatePhysics","_position","_rotation","_vectorDirection","_isFlag","_vectorUp","_potentionalSnapObject","_snapToClassName","_snapToConfig","_snapPosition","_possibleSnapPosition","_contactThreshold","_isBelowTerrain","_worldPosition","_isInAir","_numberOfContactsBottom","_startPosition","_endPosition","_newDirAndUp"];
scriptName 'Exile Construction Thread';
("ExileClientConstructionModeLayer" call BIS_fnc_rscLayer) cutRsc ["RscExileConstructionMode", "PLAIN", 1, false]; 
ExileClientIsInConstructionMode = true;
ExileClientConstructionResult = 0;
ExileClientConstructionStartPosition = getPosASL player;
_boundingBox = boundingBoxReal ExileClientConstructionObject;
_boundingBoxMinimum = _boundingBox select 0;
_boundingBoxMaximum = _boundingBox select 1;
_boundingBoxPointsTop = 
[
	[_boundingBoxMinimum select 0, _boundingBoxMinimum select 1, _boundingBoxMaximum select 2],
	[_boundingBoxMinimum select 0, _boundingBoxMaximum select 1, _boundingBoxMaximum select 2],
	[_boundingBoxMaximum select 0, _boundingBoxMinimum select 1, _boundingBoxMaximum select 2],
	[_boundingBoxMaximum select 0, _boundingBoxMaximum select 1, _boundingBoxMaximum select 2]
];
_boundingBoxPointsBottom = 
[
	[_boundingBoxMinimum select 0, _boundingBoxMinimum select 1, _boundingBoxMinimum select 2],
	[_boundingBoxMinimum select 0, _boundingBoxMaximum select 1, _boundingBoxMinimum select 2],
	[_boundingBoxMaximum select 0, _boundingBoxMinimum select 1, _boundingBoxMinimum select 2],
	[_boundingBoxMaximum select 0, _boundingBoxMaximum select 1, _boundingBoxMinimum select 2],
	[0, 0, _boundingBoxMinimum select 2] 
];
ExileClientConstructionBoundingRadius = 1 + 0.5 * ([_boundingBoxMaximum select 0, _boundingBoxMaximum select 1, 0] distance [_boundingBoxMinimum select 0, _boundingBoxMinimum select 1, 0]);
ExileClientConstructionOffset set [1, 5 max ExileClientConstructionBoundingRadius];
_objectColor = "#(argb,2,2,1)color(0.7,0.93,0,0.6,ca)";
_materialColor = _objectColor;
_simulatePhysics = false;
_position = [0, 0, 0];
_rotation = 0;
_vectorDirection = [0, 0, 0];
_isFlag = ExileClientConstructionKitClassName isEqualTo "Exile_Item_Flag";
if (_isFlag) then 
{
	ExileClientConstructionModePhysx = false;
};
[] call ExileClient_gui_constructionMode_update;
while {ExileClientConstructionResult isEqualTo 0} do
{
	if (ExileClientConstructionProcess isEqualTo 1) then 
	{
		if !(ExileClientConstructionKitClassName in (magazines player)) then 
		{
			ExileClientConstructionResult = 2;
		};
	};
	if !(ExileClientConstructionLock) then
	{
		_vectorUp = [0, 0, 1];
		ExileClientConstructionCanPlaceObject = false;
		switch (ExileClientConstructionMode) do
		{
			case 1:
			{
				if!(_isFlag)then{
					_newDirAndUp = [[sin BuildVecYaw * cos BuildVecPitch, cos BuildVecYaw * cos BuildVecPitch, sin BuildVecPitch],[[ sin BuildVecRoll,-sin BuildVecPitch,cos BuildVecRoll * cos BuildVecPitch],-BuildVecYaw] call BIS_fnc_rotateVector2D];	
					_vectorDirection = _newDirAndUp select 0;
					_vectorUp = _newDirAndUp select 1;
					ExileClientConstructionObject setVectorDirAndUp [_vectorDirection,_vectorUp];
					_position = ASLtoATL (AGLtoASL (player modelToWorld ExileClientConstructionOffset));
					ExileClientConstructionObject setPosATL _position;
					ExileClientConstructionObject attachTo [player,ExileClientConstructionOffset];
				}else{
					_position = ASLtoATL (AGLtoASL (player modelToWorld ExileClientConstructionOffset));
					_rotation = (ExileClientConstructionRotation + (getDir player) + 360) % 360;
					_vectorDirection = [sin(_rotation), cos(_rotation), 0];
				};
			};
			case 2:
			{
				_newDirAndUp = [[sin BuildVecYaw * cos BuildVecPitch, cos BuildVecYaw * cos BuildVecPitch, sin BuildVecPitch],[[ sin BuildVecRoll,-sin BuildVecPitch,cos BuildVecRoll * cos BuildVecPitch],-BuildVecYaw] call BIS_fnc_rotateVector2D];
				_vectorDirection = _newDirAndUp select 0;
				_vectorUp = _newDirAndUp select 1;
				ExileClientConstructionObject setVectorDirAndUp [_vectorDirection,_vectorUp];
				
				_position = ASLtoATL (AGLtoASL (player modelToWorld ExileClientConstructionOffset));
				_position = 
				[
					(_position select 0) - ((_position select 0) % (ExileClientConstructionGrid select 0)),
					(_position select 1) - ((_position select 1) % (ExileClientConstructionGrid select 1)),
					(_position select 2) - ((_position select 2) % (ExileClientConstructionGrid select 2))
				];
				
				
				//_rotation = (ExileClientConstructionRotation + 360) % 360;
				//_vectorDirection = [sin(_rotation), cos(_rotation), 0]; 	
			};
			case 3:
			{
				ExileClientConstructionIsSnapped = false;
				if (ExileClientConstructionIsInSelectSnapObjectMode) then 
				{
					ExileClientConstructionPossibleSnapPositions = [];
					ExileClientConstructionCurrentSnapToObject = objNull;
					_position = getPosATL player;
					_position set [2, -500];
					_newDirAndUp = [[sin BuildVecYaw * cos BuildVecPitch, cos BuildVecYaw * cos BuildVecPitch, sin BuildVecPitch],[[ sin BuildVecRoll,-sin BuildVecPitch,cos BuildVecRoll * cos BuildVecPitch],-BuildVecYaw] call BIS_fnc_rotateVector2D];	
					_vectorDirection = _newDirAndUp select 0;
					_potentionalSnapObject = cursorTarget;
					if !(isNull _potentionalSnapObject) then
					{
						if (_potentionalSnapObject distance player < 12) then 
						{
							_snapToClassName = typeOf _potentionalSnapObject;
							if (_snapToClassName in ExileClientConstructionSnapToObjectClassNames) then
							{
								ExileClientConstructionCurrentSnapToObject = _potentionalSnapObject;
								_snapToConfig = ("getText(_x >> 'staticObject') == _snapToClassName" configClasses(configFile >> "CfgConstruction")) select 0;
								{
									_snapPosition = getArray (_snapToConfig >> "SnapPositions" >> _x);
									_possibleSnapPosition = ASLtoATL (AGLtoASL (_potentionalSnapObject modelToWorld _snapPosition));
									ExileClientConstructionPossibleSnapPositions pushBack _possibleSnapPosition;
								}
								forEach getArray (ExileClientConstructionConfig >> "SnapObjects" >> _snapToClassName >> "positions");
							};
						};
					};	
				}
				else 
				{
					_newDirAndUp = [[sin BuildVecYaw * cos BuildVecPitch, cos BuildVecYaw * cos BuildVecPitch, sin BuildVecPitch],[[ sin BuildVecRoll,-sin BuildVecPitch,cos BuildVecRoll * cos BuildVecPitch],-BuildVecYaw] call BIS_fnc_rotateVector2D];	
					_vectorDirection = _newDirAndUp select 0;
					_vectorUp = _newDirAndUp select 1;
					ExileClientConstructionObject setVectorDirAndUp [_vectorDirection,_vectorUp];
					_position = ASLtoATL (AGLtoASL (player modelToWorld ExileClientConstructionOffset));
					ExileClientConstructionObject setPosATL _position;
					ExileClientConstructionObject attachTo [ExileClientConstructionCurrentSnapToObject,ExileClientConstructionOffset];
					{
						if (_x distance _position < 1) exitWith
						{
							_position = _x;
							_newDirAndUp = [[sin BuildVecYaw * cos BuildVecPitch, cos BuildVecYaw * cos BuildVecPitch, sin BuildVecPitch],[[ sin BuildVecRoll,-sin BuildVecPitch,cos BuildVecRoll * cos BuildVecPitch],-BuildVecYaw] call BIS_fnc_rotateVector2D];	
							_vectorDirection = _newDirAndUp select 0;
							_vectorUp = vectorUp ExileClientConstructionCurrentSnapToObject;
							ExileClientConstructionIsSnapped = true;
						};
					}
					forEach ExileClientConstructionPossibleSnapPositions;		
				};
			};
		};
		ExileClientConstructionObject setVectorDirAndUp [_vectorDirection,_vectorUp];
		ExileClientConstructionObject setPosATL _position;
	};
	_contactThreshold = 0.1; 
	_isBelowTerrain = true;
	{
		_worldPosition = ASLtoATL (AGLtoASL (ExileClientConstructionObject modelToWorld _x));
		if ((_worldPosition select 2) > _contactThreshold) exitWith {_isBelowTerrain = false};
	}
	forEach _boundingBoxPointsTop;
	_isInAir = true;
	_numberOfContactsBottom = 0;
	{
		_worldPosition = ASLtoATL (AGLtoASL (ExileClientConstructionObject modelToWorld _x));
		if ((_worldPosition select 2) < _contactThreshold) then 
		{
			_isInAir = false;
		};
		_startPosition = ATLtoASL[_worldPosition select 0, _worldPosition select 1, (_worldPosition select 2) + _contactThreshold];
		_endPosition = ATLtoASL [_worldPosition select 0, _worldPosition select 1, (_worldPosition select 2) - _contactThreshold];
		if (count lineIntersectsObjs[_startPosition, _endPosition, ExileClientConstructionObject, objNull, false, 2] > 0) then
		{
			_numberOfContactsBottom = _numberOfContactsBottom + 1;
		};
	}
	forEach _boundingBoxPointsBottom;
	if (_isBelowTerrain) then
	{
		ExileClientConstructionCanPlaceObject = false;
		_simulatePhysics = false;
		_objectColor = "#(argb,2,2,1)color(0.91,0,0,0.6,ca)";
	}
	else 
	{
		ExileClientConstructionCanPlaceObject = true;
		if !(ExileClientConstructionModePhysx) then
		{
			_objectColor = "#(argb,2,2,1)color(0.7,0.93,0,0.6,ca)";
			_simulatePhysics = false;
		}
		else 
		{
			if (_isInAir) then
			{	
				if (_numberOfContactsBottom >= 3) then
				{
					_objectColor = "#(argb,2,2,1)color(0.7,0.93,0,0.6,ca)";
					_simulatePhysics = false;
				}
				else 
				{
					_objectColor = "#(argb,2,2,1)color(1,0.79,0.07,0.6,ca)";
					_simulatePhysics = true;
				};
			}
			else 
			{
				_objectColor = "#(argb,2,2,1)color(0.7,0.93,0,0.6,ca)";
				_simulatePhysics = false;
			};
		};
	};
	if (ExileClientConstructionMode isEqualTo 3) then
	{
		if (!ExileClientConstructionIsSnapped) then
		{
			ExileClientConstructionCanPlaceObject = false;
			_simulatePhysics = false;
			_objectColor = "#(argb,2,2,1)color(0.91,0,0,0.6,ca)";
		};
	};
	if !(([configName ExileClientConstructionConfig, ASLtoAGL (getPosASL ExileClientConstructionObject), getPlayerUID player] call ExileClient_util_world_canBuildHere) isEqualTo 0) then
	{
		ExileClientConstructionCanPlaceObject = false;
		_simulatePhysics = false;
		_objectColor = "#(argb,2,2,1)color(0.91,0,0,0.6,ca)";
	};
	if (_isFlag) then 
	{
		if (((getPos ExileClientConstructionObject) select 2) > 0.2) then 
		{
			ExileClientConstructionCanPlaceObject = false;
			_simulatePhysics = false;
			_objectColor = "#(argb,2,2,1)color(0.91,0,0,0.6,ca)";
		};
	};
	if (_objectColor != _materialColor) then
	{
		ExileClientConstructionObject setObjectTextureGlobal[0, _objectColor];
		ExileClientConstructionObject setObjectTextureGlobal[1, _objectColor];
		ExileClientConstructionObject setObjectTextureGlobal[2, _objectColor];
		ExileClientConstructionObject setObjectTextureGlobal[3, _objectColor];
		_materialColor = _objectColor;
	};
	if (ExileClientConstructionStartPosition distance (getPosASL player) > 20) then
	{
		ExileClientConstructionResult = 3;
	};
	if (ExileClientPlayerIsInCombat) then
	{
		ExileClientConstructionModePhysx = true;
		ExileClientConstructionResult = 2;
	};
	uiSleep 0.001; 
};
if !(ExileClientConstructionModePhysx) then
{
	_simulatePhysics = false;
};
_simulatePhysics call ExileClient_construction_handleAbort;
ExileClientConstructionObject = objNull;
ExileClientIsInConstructionMode = false;
ExileClientConstructionResult = 0;
ExileClientConstructionProcess = 0;
ExileClientConstructionLock = false;
("ExileClientConstructionModeLayer" call BIS_fnc_rscLayer) cutText ["", "PLAIN"]; 
true