// Handles interactions with the handheld duplicator item.
// -------------------------------------------------------------------

//Set which image a client should use
function GameConnection::ndSetImage(%this, %image)
{
	%image = %image.getId();

	if(%image != %this.ndImage)
	{
		%this.ndImage = %image;

		if(%this.ndEquipped)
		{
			%this.ndIgnoreNextMount = true;
			%this.player.schedule(0, updateArm, %image);
			%this.player.schedule(0, mountImage, %image, 0);
		}
	}
}

//Mount the correct image when the item is equipped
function ND_Item::onUse(%this, %player, %slot)
{
	%image = %player.client.ndImage;

	if(!isObject(%image))
		%image = ND_Image;

	%player.updateArm(%image);
	%player.mountImage(%image, 0);
	%player.client.ndEquippedFromItem = true;
}

package NewDuplicator_Server
{
	//Start select mode when duplicator is equipped
	function ND_Image::onMount(%this, %player, %slot)
	{
		parent::onMount(%this, %player, %slot);
		%player.ndEquipped();
	}

	function ND_Image_Blue::onMount(%this, %player, %slot)
	{
		parent::onMount(%this, %player, %slot);
		%player.ndEquipped();
	}

	function ND_Image_Box::onMount(%this, %player, %slot)
	{
		parent::onMount(%this, %player, %slot);
		%player.ndEquipped();
	}

	//Cancel mode when duplicator is unequipped
	function ND_Image::onUnMount(%this, %player, %slot)
	{
		parent::onUnMount(%this, %player, %slot);
		%player.ndUnEquipped();
	}

	function ND_Image_Blue::onUnMount(%this, %player, %slot)
	{
		parent::onUnMount(%this, %player, %slot);
		%player.ndUnEquipped();
	}

	function ND_Image_Box::onUnMount(%this, %player, %slot)
	{
		parent::onUnMount(%this, %player, %slot);
		%player.ndUnEquipped();
	}
};

//Start the swinging animation
function ND_Image::onPreFire(%this, %player, %slot)
{
	%player.playThread(2, shiftTo);
}

function ND_Image_Blue::onPreFire(%this, %player, %slot)
{
	%player.playThread(2, shiftTo);
}

function ND_Image_Box::onPreFire(%this, %player, %slot)
{
	%player.playThread(2, shiftTo);
}

//Handle selecting things
function ND_Image::onFire(%this, %player, %slot)
{
	%player.ndFired();
}

function ND_Image_Blue::onFire(%this, %player, %slot)
{
	%player.ndFired();
}

function ND_Image_Box::onFire(%this, %player, %slot)
{
	%player.ndFired();
}

//Duplicator was equipped
function Player::ndEquipped(%this)
{
	%client = %this.client;

	if(%this.isHoleBot || %this.isSlayerBot || !isObject(%client))
		return;

	if(%client.ndIgnoreNextMount)
	{
		%client.ndIgnoreNextMount = false;
		return;
	}

	if($Pref::Server::ND::AdminOnly && !%client.isAdmin)
	{
		commandToClient(%client, 'centerPrint', "<font:Verdana:20>\c6Oops! The duplicator is admin only.", 5);
		return;
	}

	%client.ndEquipped = true;

	//Remove temp brick so it doesn't overlap the selection box
	if(isObject(%this.tempBrick))
		%this.tempBrick.delete();

	//Should resume last used select mode
	if(!%client.ndModeIndex)
		%client.ndSetMode(%client.ndLastSelectMode);
}

//Duplicator was unequipped
function Player::ndUnEquipped(%this)
{
	%client = %this.client;

	if(%this.isHoleBot || %this.isSlayerBot || !isObject(%client))
		return;

	if(%client.ndIgnoreNextMount)
		return;

	if(%client.ndModeIndex && !%client.ndMode.allowUnMount)
		%client.ndKillMode();

	%client.ndEquipped = false;
}

//Duplicator was fired
function Player::ndFired(%this)
{
	%client = %this.client;

	if(!isObject(%client) || !%client.ndModeIndex || !%client.ndMode.allowSelecting)
		return;

	if(isObject(%client.minigame) && !%client.minigame.enablebuilding)
	{
		commandToClient(%client, 'centerPrint', "<font:Verdana:20>\c6Oops! Building is disabled.", 5);
		return;
	}

	//Support for Script_RaycastOffTools by Conan
	if(%this.isRaycastTool)
		%mask = $TypeMasks::FxBrickObjectType | $TypeMasks::TerrainObjectType | $TypeMasks::InteriorObjectType;
	else
		%mask = $TypeMasks::FxBrickAlwaysObjectType | $TypeMasks::TerrainObjectType | $TypeMasks::InteriorObjectType;

	%start = %this.getEyePoint();
	%dir = %this.getEyeVector();

	//Octree::Raycast fails to detect close bricks (~1TU) with a long raycast, so we'll do 3.
	//First a very short one of 1 TU to detect very close bricks, then a slightly longer one
	//of 10 TU, and finally the long range one of 1000.
	%len[0] = 1;
	%len[1] = 10;
	%len[2] = 1000;

	for(%i = 0; %i < 3; %i++)
	{
		%end = vectorAdd(%start, vectorScale(%dir, %len[%i]));
		%ray = containerRaycast(%start, %end, %mask, %this);

		if(isObject(%obj = firstWord(%ray)))
			break;
	}

	if(!isObject(%obj))
		return;

	%position = posFromRaycast(%ray);
	%normal = normalFromRaycast(%ray);

	//Can't directly spawn an explosion, must use a projectile
	%data = %client.ndImage.projectile;

	if(!isObject(%data))
		%data = ND_HitProjectile;

	%proj = new Projectile()
	{
		datablock = %data;
		initialPosition = %position;
		initialVelocity = %normal;
	};

	//Pass on the selected object to the dupli mode
	%client.ndMode.onSelectObject(%client, %obj, %position, %normal);
}

package NewDuplicator_Server
{
	//Automatically start the "ambient" animation on duplicator items
	function ND_Item::onAdd(%this, %obj)
	{
		parent::onAdd(%this, %obj);
		%obj.playThread(0, ambient);

		//Fix colorshift bullshit
		%obj.schedule(100, setNodeColor, "ALL", %this.colorShiftColor);
	}

	//Prevent accidently unequipping the duplicator
	function serverCmdUnUseTool(%client)
	{
		if(%client.ndLastEquipTime + 1.5 > $Sim::Time)
			return;

		if(%client.ndModeIndex == $NDM::StackSelect || %client.ndModeIndex == $NDM::BoxSelect)
		{
			%client.ndToolSchedule = %client.schedule(100, ndUnUseTool);
			return;
		}

		parent::serverCmdUnUseTool(%client);
	}

	//Prevent creating ghost bricks in modes that allow un-mount
	function BrickDeployProjectile::onCollision(%this, %obj, %col, %fade, %pos, %normal)
	{
		%client = %obj.client;

		if(isObject(%client) && %client.ndModeIndex)
			%client.ndMode.onSelectObject(%client, %col, %pos, %normal);
		else
			parent::onCollision(%this, %obj, %col, %fade, %pos, %normal);
	}

	//Handle ghost brick movements from New Brick Tool
	function placeNewGhostBrick(%client, %pos, %normal, %noOrient)
	{
		if(!isObject(%client) || !%client.ndModeIndex)
			return parent::placeNewGhostBrick(%client, %pos, %normal, %noOrient);

		if(%client.ndModeIndex == $NDM::PlantCopy)
		{
			if(!%noOrient)
			{
				%angleID = getAngleIDFromPlayer(%client.getControlObject()) - %client.ndSelection.angleIDReference;
				%rotation = ((4 - %angleID) - %client.ndSelection.ghostAngleID) % 4;

				if(%rotation != 0)
					%client.ndSelection.rotateGhostBricks(%rotation, %client.ndPivot);
			}

			return NDM_PlantCopy.moveBricksTo(%client, %pos, %normal);
		}

		%client.ndMode.onSelectObject(%client, 0, %pos, %normal);
	}
};

//Fix for equipping paint can calling unUseTool
function GameConnection::ndUnUseTool(%this)
{
	%player = %this.player;

	if(%this.isTalking)
		serverCmdStopTalking(%this);

	if(!isObject(%player))
		return;

	%player.currTool = -1;
	%this.currInv = -1;
	%this.currInvSlot = -1;

	%player.unmountImage(0);
	%player.playThread(1, "root");
}