AUVec3f GetSpawnPosition( EGameObject type )
	{
		float width, height;
		PerModuleInterface::g_pSystemTable->pGame->GetWindowSize( width, height );
		float edgeMargin = 0.05f;

		// Spawn WBC in bottom quarter of screen, RBC in middle quarter, and Virus and Infected Cell
		// in the top quarter
		float min = height * edgeMargin;       // from bottom of screen
		float max = height * (1 - edgeMargin);  // from bottom of screen
		if (type == EGO_WBC)
		{
			max = height * 0.25f;
		}
		else if (type == EGO_RBC)
		{
			min = height * 0.375f;
			max = height * 0.625f;
		}
		else
		{
			min = height * 0.75f;
		}
		
		AUVec3f position;
		position.SetX( rand() * 1.0f / RAND_MAX * width * (1.0f - edgeMargin * 2) - width * (0.5f - edgeMargin) );
		position.SetY( 0.0f );
		position.SetZ( rand() * 1.0f / RAND_MAX * (max - min) + min - height * 0.5f);

		return position;
	}
	virtual void UpdateBehavior( float timeDelta )
	{
		if ( !m_pBBCommon->target_position.IsInfinite() )
		{
			AUVec3f targetVec = m_pBBCommon->target_position - m_pBBCommon->current_position;
			float distSqr = targetVec.MagnitudeSqr();
			if ( distSqr < 1.0f )
			{
				m_pBBCommon->target_position.SetInfinite();
			}
		}
	}
	virtual AUVec3f CalculateDesiredPosition( float timeDelta )
	{
		AUVec3f pos = m_pOwner->GetEntity()->GetPosition();

		if ( !m_pBBCommon->target_position.IsInfinite() ) 
		{
			AUVec3f targetVec = m_pBBCommon->target_position - m_pBBCommon->current_position;
			AUVec3f targetDir = targetVec.GetNormalised();
			float dist = std::min( targetVec.Magnitude(), m_pOwner->GetMaxSpeed() * timeDelta );
			pos += targetDir * dist;
		}

		return pos;
	}
	virtual AUVec3f CalculateDesiredPosition( float timeDelta )
	{
		AUVec3f pos = m_pOwner->GetEntity()->GetPosition();

		IGameObject* pGameObject = 0;
		IObjectUtils::GetObject( &pGameObject, m_pBBCommon->enemy_collision_objectid );
		if (pGameObject)
		{
			AUVec3f targetVec = pGameObject->GetEntity()->GetPosition() - m_pBBCommon->current_position;
			AUVec3f targetDir = targetVec.GetNormalised();
			float dist = std::min( targetVec.Magnitude(), m_pOwner->GetMaxSpeed() * timeDelta );
			pos += targetDir * dist;
		}

		return pos;
	}
	virtual AUVec3f CalculateDesiredPosition( float timeDelta )
	{
		AUVec3f pos = m_pOwner->GetEntity()->GetPosition();
		AUVec3f targetPos;
		if (m_pApproachTarget)
		{
			targetPos = m_pApproachTarget->GetEntity()->GetPosition();
		}
		else
		{
			targetPos = pos + m_PatrolDir * m_pOwner->GetMaxSpeed();
		}

		AUVec3f targetVec = targetPos - pos;
		AUVec3f targetDir = targetVec.GetNormalised();
		float dist = std::min( targetVec.Magnitude(), m_pOwner->GetMaxSpeed() * timeDelta );
		pos += targetDir * dist;

		return pos;
	}
	virtual void OnEvent( int event_id, const IGUIEvent& event_info )
	{
		AUVec3f selectPos;
		char buff[16];
		event_info.GetParameter( "mouse_x", buff, sizeof(buff) );
		selectPos.SetX( (float)atof( buff ) );
		event_info.GetParameter( "mouse_y", buff, sizeof(buff) );
		selectPos.SetY( (float)atof( buff ) );
		event_info.GetParameter( "button", buff, sizeof(buff) );
		int button = atoi( buff );

		AUVec3f worldPos = m_pCameraControl->Unproject( selectPos );

		IGameObject* pGameObject = GetSelectedObject( worldPos );
		if ( button == 0 ) // left button
		{
			if ( m_pSelectedObject && pGameObject != m_pSelectedObject )
			{
				// Deselect currently selected object
				m_pSelectedObject->OnDeselect();
				m_pSelectedObject = 0;
			}

			if ( pGameObject )
			{
				// Select object
				pGameObject->OnSelect();
				m_pSelectedObject = pGameObject;
			}
		}
		else // right button
		{
			if ( m_pSelectedObject && pGameObject != m_pSelectedObject )
			{
				// Set target
				m_pSelectedObject->OnPositionRequest( worldPos );
			}
		}
	}
	virtual bool IsHeadingToGameBounds( const AUVec3f& position, const AUVec3f& velocity ) const
	{
		float edgeProportion = (position.x * position.x) / m_fWorldCenteringDist.x +
			(position.z * position.z) / m_fWorldCenteringDist.z;
		return ( edgeProportion > 0.8f && position.Dot(velocity) > cos( M_PI_4 ) );
	}
		GameObjectSpawnParams( EGameObject type ) : type(type)
		{
			spawnPosition.SetInfinite();
		}