// Update the Deku Scrub
entity.setPosition(p.x, p.y, p.z);	// Prevent entity from moving
if (hiding)
{
	if (entity.height != 0.1)
	{
		entity.height = 0.1;
	}
	// Make model move under the floor and create "dirt" particles
	if (m.y > -0.3)
	{
		m.moveBy(0, -0.1, 0);
		m.rotateBy(yawSpeed, 0, 0);
		if (m.yaw >= yawMax)
		{
			yawSpeed *= -1;
		}
		else if(m.yaw <= -yawMax)
		{
			yawSpeed *= -1;
		}

		// Create random particles
		for (var i=0; i<20; i++)
		{
			var px = entity.position.x + ((Math.random() * 1.5) - 0.75);
			var py = entity.position.y + ((Math.random() * 0.25) - 0.125);
			var pz = entity.position.z + ((Math.random() * 1.5) - 0.75);
			var arg1 = Math.random() * 0.75;
			var arg2 = arg1 / 2.0;
			var arg3 = arg1 / 4.0;

			effect.spawnParticle("reddust", px, py, pz, arg1, arg2, arg3);
		}
	}
	else if (m.yaw != 0)
	{
		m.yaw = 0;
	}

	// See if player is in a certain range
	var ents = entity.getEntitiesWithinRange(maxRange);
	for (var i=0; i<ents.length; i++)
	{
		if (ents[i].getClassType() == "Player")
		{
			hiding = false;
		}
	}
	if (!hiding)
	{
		// Check if player is too close
		ents = entity.getEntitiesWithinRange(minRange);
		for (var i=0; i<ents.length; i++)
		{
			if (ents[i].getClassType() == "Player")
			{
				hiding = true;
			}
		}
	}
	// If still not hiding play a sound
	if (!hiding)
	{
		sound.playSound3D("sound.scrub_up", p.x, p.y, p.z);
	}
}
else
{
	if (entity.height != scrubHeight)
	{
		entity.height = scrubHeight;
	}
	// Make model appear from the ground
	if (m.y < 0.7)
	{
		m.moveBy(0, 0.1, 0);
		m.rotateBy(yawSpeed, 0, 0);
		if (m.yaw >= yawMax)
		{
			yawSpeed *= -1;
		}
		else if(m.yaw <= -yawMax)
		{
			yawSpeed *= -1;
		}

		// Create random particles
		for (var i=0; i<20; i++)
		{
			var px = entity.position.x + ((Math.random() * 1.5) - 0.75);
			var py = entity.position.y + ((Math.random() * 0.25) - 0.125);
			var pz = entity.position.z + ((Math.random() * 1.5) - 0.75);
			var arg1 = Math.random() * 0.75;
			var arg2 = arg1 / 2.0;
			var arg3 = arg1 / 4.0;

			effect.spawnParticle("reddust", px, py, pz, arg1, arg2, arg3);
		}
	}
	else if (m.yaw != 0)
	{
		m.yaw = 0;
	}

	// Face the player
	var pPos = player.getPosition();
	var angle = Math.atan2(p.z - pPos.z, p.x - pPos.x);
	angle = (angle / Math.PI) * 180;
	angle += 90;
	entity.setRotation(angle, entity.rotation.pitch);


	// Count down shot timer
	shotTime--;
	if (shotTime <= 0)
	{
		// Create deku nut model
		shotModel = Model();
		shotModel.addBoxExpanded("DekuNut", -4, -4, -4, 8, 8, 8, 0, 0, -2.0);
		shotModel.addBoxExpanded("Inside", -3.5, -3.5, -3.5, 7, 7, 7, 0, 16, -2.0);
		shotModel.texture = "/models/projectiles/dekunut.png";
		// Fire at the player
		var vec = Array();
		vec.x = pPos.x - (p.x + m.x);
		vec.y = pPos.y - (p.y + m.y);
		vec.z = pPos.z - (p.z + m.z);
		// Normalize vector
		vMag = Math.sqrt((vec.x * vec.x) + (vec.y * vec.y) + (vec.z * vec.z));
		vec.x /= vMag;
		vec.y /= vMag;
		vec.z /= vMag;
		// Create projectile
		shotModel.setPosition(p.x + m.x, p.y + m.y, p.z + m.z);
		shot = Array();
		shot.model = shotModel;
		shot.position = Array();
		shot.position.x = p.x + m.x;
		shot.position.y = p.y + m.y;
		shot.position.z = p.z + m.z;
		shot.velocity = Array();
		shot.velocity.x = vec.x;
		shot.velocity.y = vec.y;
		shot.velocity.z = vec.z;
		shot.reversed = false;
		shot.remove = false;
		dekuNuts.push(shot);
		// Play sound
		sound.playSound3D("sound.scrub_shoot", p.x, p.y, p.z);
		// Reset shot timer
		shotTime = shotDelay;
	}

	// Check if player is still in range
	hiding = true;
	var ents = entity.getEntitiesWithinRange(maxRange);
	for (var i=0; i<ents.length; i++)
	{
		if (ents[i].getClassType() == "Player")
		{
			hiding = false;
		}
	}
	if (!hiding)
	{
		// Check if player is too close
		ents = entity.getEntitiesWithinRange(minRange);
		for (var i=0; i<ents.length; i++)
		{
			if (ents[i].getClassType() == "Player")
			{
				hiding = true;
			}
		}
	}
	// If hiding play a sound
	if (hiding)
	{
		shotTime = shotDelay;
		sound.playSound3D("sound.scrub_down", p.x, p.y, p.z);
	}
}

// Update Deku Scrub projectiles
for (var i=0; i<dekuNuts.length; i++)
{
	// Move projectile
	dekuNuts[i].position.x += dekuNuts[i].velocity.x;
	dekuNuts[i].position.y += dekuNuts[i].velocity.y;
	dekuNuts[i].position.z += dekuNuts[i].velocity.z;
	dekuNuts[i].model.moveTo(dekuNuts[i].position.x, dekuNuts[i].position.y, dekuNuts[i].position.z);
	// Rotate model
	dekuNuts[i].model.rotateBy(30, 30, 0);
	// Check collisions
	var start = dekuNuts[i].position;
	var end = Array();
	end.x = start.x + dekuNuts[i].velocity.x;
	end.y = start.y + dekuNuts[i].velocity.y;
	end.z = start.z + dekuNuts[i].velocity.z;
	var collideList = RayTrace(start, end);
	for (var j=0; j<collideList.length; j++)
	{
		if (collideList[j].type == "Entity")
		{
			if (entity.entityID != collideList[j].ent.entityID || dekuNuts[i].reversed)
			{
				// Collide with Deku Scrub
				if (collideList[j].ent.getClassType() == "Script" && collideList[j].ent.onCreated == "dekuScrubOnCreated.js")
				{
					collideList[j].ent.attackEntityFrom(collideList[j].ent, 4);
					dekuNuts[i].remove = true;
					break;
				}
				// Collide with Player
				else if (collideList[j].ent.getClassType() == "Player")
				{
					// Check if player has a shield out
					curItem = player.inventory.getCurrentItem();
					offItem = player.inventory.getOffhandItem();
					if ((curItem != null && curItem.itemID == 461) || (offItem != null && offItem.itemID == 461))
					{
						// Check if player is facing the deku nut
						var pVec = Array();
						pVec.x = dekuNuts[i].position.x - player.position.x;
						pVec.y = dekuNuts[i].position.y - player.position.y;
						pVec.z = dekuNuts[i].position.z - player.position.z;
						var lVec = player.getLookVec();
						lVecFlatMag = Math.sqrt((lVec.x * lVec.x) + (lVec.z * lVec.z));
						pVecFlatMag = Math.sqrt((pVec.x * pVec.x) + (pVec.z * pVec.z));
						pVecRy = Math.atan2(pVec.z, pVec.x);
						pVecRx = Math.atan2(pVec.y, pVecFlatMag);
						lVecRy = Math.atan2(lVec.z, lVec.x);
						lVecRx = Math.atan2(lVec.y, lVecFlatMag);
						var difference = Math.abs(lVecRy - pVecRy) + Math.abs(lVecRx - pVecRx);

						if (difference <= Math.PI / 2)
						{
							// Deflect Deku Nut
							dekuNuts[i].reversed = true;
							dekuNuts[i].velocity = player.getLookVec();
							sound.playSound3D("sound.shield_hit", dekuNuts[i].position.x, dekuNuts[i].position.y, dekuNuts[i].position.z);
							break;
						}
						else
						{
							var point = effect.spawnParticle("bubble", dekuNuts[i].position.x, dekuNuts[i].position.y, dekuNuts[i].position.z, 0, 0, 0);
							collideList[j].ent.attackEntityFrom(collideList[j].ent, 2);
							dekuNuts[i].remove = true;
							break;
						}
					}
					else
					{
						var point = effect.spawnParticle("bubble", dekuNuts[i].position.x, dekuNuts[i].position.y, dekuNuts[i].position.z, 0, 0, 0);
						collideList[j].ent.attackEntityFrom(collideList[j].ent, 2);
						dekuNuts[i].remove = true;
						break;
					}
				}
				// Collide with other mobs
				else if (!collideList[j].ent.getClassType() in nonMobs)
				{
					var point = effect.spawnParticle("bubble", dekuNuts[i].position.x, dekuNuts[i].position.y, dekuNuts[i].position.z, 0, 0, 0);
					collideList[j].ent.attackEntityFrom(collideList[j].ent, 5);
					dekuNuts[i].remove = true;
					break;
				}
			}
		}
		// Collide with block
		else
		{
			dekuNuts[i].remove = true;
			break;
		}
	}
}
// Remove deku nuts marked for removal
var liveShots = Array();
for (var i=0; i<dekuNuts.length; i++)
{
	if (dekuNuts[i].remove)
	{
		dekuNuts[i].model.removeFromRendering();
		var pos = dekuNuts[i].position;
		for (var i=0; i<20; i++)
		{
			var px = pos.x + ((Math.random() * 0.5) - 0.25);
			var py = pos.y + ((Math.random() * 0.5) - 0.25);
			var pz = pos.z + ((Math.random() * 0.5) - 0.25);
			var arg1 = Math.random() * 0.75;
			var arg2 = arg1 / 2.0;
			var arg3 = arg1 / 4.0;

			effect.spawnParticle("reddust", px, py, pz, arg1, arg2, arg3);
		}
		sound.playSound3D("sound.nut_hit", pos.x, pos.y, pos.z);
	}
	else
	{
		liveShots.push(dekuNuts[i]);
	}
}
dekuNuts = liveShots.slice(0);

// Make entity dead if it doesn't have health. Prevents onDeath script from being delayed for over a second.
if (entity.health <= 0)
{
	entity.setDead();
}