void WBCompEldAnchor::SetAnchor()
{
	EldritchWorld* const		pWorld			= GetWorld();
	ASSERT( pWorld );

	WBEntity* const				pEntity			= GetEntity();
	DEVASSERT( pEntity );

	WBCompEldTransform* const	pTransform		= pEntity->GetTransformComponent<WBCompEldTransform>();
	DEVASSERT( pTransform );

	const Angles				Orientation		= pTransform->GetOrientation();
	const Matrix				RotationMatrix	= Orientation.ToMatrix();
	const Vector				AnchorVector	= m_AnchorDirection * RotationMatrix;
	const Vector				StartLocation	= pTransform->GetLocation();
	const Ray					TraceRay		= Ray( StartLocation, AnchorVector );

	CollisionInfo Info;
	Info.m_CollideWorld		= true;
	Info.m_CollideEntities	= true;
	Info.m_CollidingEntity	= pEntity;
	Info.m_UserFlags		= EECF_CollideAsEntity | EECF_CollideStaticEntities;

	if( pWorld->Trace( TraceRay, Info ) )
	{
		m_AnchorPoint	= Info.m_Intersection + AnchorVector * 0.1f;
		ASSERT( pWorld->PointCheck( m_AnchorPoint, Info ) );	// Since hard-coded 0.1 might break for thin surfaces.
		m_IsAnchored	= true;
	}
}
Beispiel #2
0
/*virtual*/ void WBCompEldMesh::Tick(float DeltaTime) {
  XTRACE_FUNCTION;

  UpdateMesh(DeltaTime);

  // Add pseudo root motion. Hack from Couriers.
  if (m_Mesh && m_Mesh->IsAnimated()) {
    Vector AnimationVelocity;
    Angles AnimationRotationalVelocity;
    GetAnimationVelocity(AnimationVelocity, AnimationRotationalVelocity);

    if (AnimationVelocity.LengthSquared() > 0.0f ||
        !AnimationRotationalVelocity.IsZero()) {
      WBCompEldTransform* pTransform =
          GetEntity()->GetTransformComponent<WBCompEldTransform>();
      DEVASSERT(pTransform);

      // Kill velocity in direction of movement.
      if (AnimationVelocity.LengthSquared() > 0.0f) {
        Plane MovementPlane(AnimationVelocity.GetNormalized(), 0.0f);
        pTransform->SetVelocity(
            MovementPlane.ProjectVector(pTransform->GetVelocity()));
      }

      pTransform->ApplyImpulse(AnimationVelocity);
      pTransform->ApplyRotationalImpulse(AnimationRotationalVelocity);
    }
  }
}
Beispiel #3
0
float PolarDiagram::getGybeAngle(const float & speed){
    if(!contains(speed)){
        if(debug)
            qDebug() << Q_FUNC_INFO << QString("(%1): speed not found").arg(QString::number(speed));

        int i = 0;
        // List of all the speeds available in the diagram
        // given in ASC order
        QList<float> speeds = diagram.keys();

        while(speeds[i] < speed && i < speeds.size() - 1)
            ++i;

        float maxang;

        // input speed is bigger than any available
        if(i == speeds.size() - 1)
            maxang = getGybeAngle(speeds.last());
        // input speed is smaller than any available
        else if (i == 0)
            maxang = getGybeAngle(speeds.first());
        // input speed is between other available speeds
        else
            maxang = (getGybeAngle(speeds[i-1]) + getGybeAngle(speeds[i])) / 2;

        return maxang;
    }

    // input speed is contained in our diagram
    Angles aux = getAngles(speed);

    // List of available angles for this speed
    // List is in ASC order
    QList<float> angles = aux.keys();

    float maxta = 0, maxang = 0, ta, ang;
    bool on_gybe = true;

    for(int i = angles.size() - 1; on_gybe && i >= 0; --i){
        ang = angles[i];
        ta = aux.value(ang);

        if(ang < MIN_ANGLE_CONSIDERED_GYBE)
            on_gybe = false;
        else
            if(ta > maxta){
                maxta = ta;
                maxang = ang;
            }
    }

    if(debug)
        qDebug() << Q_FUNC_INFO << QString("(%1): %2").arg(QString::number(speed), QString::number(maxang));

    return maxang;
}
Beispiel #4
0
void PolarDiagram::addLine( const float &speed, const float &angle, const float &TA){
    if(debug)
        qDebug() << Q_FUNC_INFO;

    Angles aux;
    aux.insert(angle, TA);

    // setAngles() will take care if the speed already exists
    setAngles(speed, aux);
}
Beispiel #5
0
void PolarDiagram::setAngles(const float &speed, const Angles &angles){
    if(debug)
        qDebug() << Q_FUNC_INFO;
    if(contains(speed)){
        Angles merge = angles;
        Angles aux = getAngles(speed);

        Angles::const_iterator i = aux.constBegin();
        while(i != aux.constEnd()){
            merge.insert(i.key(), i.value());
            ++i;
        }

        diagram.insert(speed, merge);

    } else
        diagram.insert( speed, angles);
}
void WBActionEldRemoveBlock::TraceFromSourceEntity( WBEntity* const pSourceEntity ) const
{
	if( !pSourceEntity )
	{
		return;
	}

	WBCompEldTransform* const pTransform = pSourceEntity->GetTransformComponent<WBCompEldTransform>();
	if( !pTransform )
	{
		return;
	}

	// TODO: If I reuse this stuff a lot in weapons and powers, wrap it up.

	WBCompEldCamera* const pCamera = GET_WBCOMP( pSourceEntity, EldCamera );

	EldritchWorld* const pWorld = EldritchFramework::GetInstance()->GetWorld();
	ASSERT( pWorld );

	Vector EyeLoc = pTransform->GetLocation();
	Angles EyeRot = pTransform->GetOrientation();

	if( pCamera )
	{
		EyeLoc += pCamera->GetViewTranslationOffset( WBCompEldCamera::EVM_All );
		EyeRot += pCamera->GetViewOrientationOffset( WBCompEldCamera::EVM_All );
	}

	const Vector EyeDir = EyeRot.ToVector();
	const Ray TraceRay( EyeLoc, EyeDir );

	CollisionInfo Info;
	Info.m_CollideWorld		= true;
	Info.m_CollideEntities	= true;
	Info.m_CollidingEntity	= pSourceEntity;
	Info.m_UserFlags		= EECF_Trace;

	if( pWorld->Trace( TraceRay, Info ) )
	{
		const Vector HitLoc = Info.m_Intersection - Info.m_Plane.m_Normal * 0.1f;
		pWorld->RemoveVoxelAt( HitLoc );
	}
}
Beispiel #7
0
void EldritchFramework::CreateMinimapView() {
  PRINTF("EldritchFramework::CreateMinimapView\n");

  SafeDelete(m_MinimapView);

  STATICHASH(EldMinimap);

  STATICHASH(MinimapRTWidth);
  const float fMinimapRTWidth =
      ConfigManager::GetFloat(sMinimapRTWidth, 0.0f, sEldMinimap);

  STATICHASH(MinimapRTHeight);
  const float fMinimapRTHeight =
      ConfigManager::GetFloat(sMinimapRTHeight, 0.0f, sEldMinimap);

  STATICHASH(MinimapViewDistance);
  const float ViewDistance =
      ConfigManager::GetFloat(sMinimapViewDistance, 0.0f, sEldMinimap);

  STATICHASH(MinimapViewPitch);
  const float ViewPitch = DEGREES_TO_RADIANS(
      ConfigManager::GetFloat(sMinimapViewPitch, 0.0f, sEldMinimap));

  STATICHASH(MinimapViewFOV);
  const float FOV = ConfigManager::GetFloat(sMinimapViewFOV, 0.0f, sEldMinimap);

  STATICHASH(MinimapViewNearClip);
  const float NearClip =
      ConfigManager::GetFloat(sMinimapViewNearClip, 0.0f, sEldMinimap);

  STATICHASH(MinimapViewFarClip);
  const float FarClip =
      ConfigManager::GetFloat(sMinimapViewFarClip, 0.0f, sEldMinimap);

  const Angles EyeOrientation = Angles(ViewPitch, 0.0f, 0.0f);
  const Vector EyeDirection = EyeOrientation.ToVector();
  const Vector EyePosition = -EyeDirection * ViewDistance;
  const float AspectRatio = fMinimapRTWidth / fMinimapRTHeight;

  m_MinimapView = new View(EyePosition, EyeOrientation, FOV, AspectRatio,
                           NearClip, FarClip);
}
Beispiel #8
0
UP_ERROR PolarDiagram::check(){
    if(debug)
        qDebug() << Q_FUNC_INFO;

    if(name.isEmpty())
        return ERROR_PD_NAME;
    if(diagram.size() == 0)
        return ERROR_PD_SIZE;

    QList<float> speeds = diagram.keys();

    for(int i = 0; i < speeds.size(); i++){
        // for each speed we check the list of angles-ta
        // very simple not in deep check of the diagram
        Angles aux = getAngles(speeds[i]);
        QList<float> angles = aux.keys();

        bool a_gybe_angle = false;
        bool a_beat_angle = false;
        float ang, ta;

        for(int j = 0; j < angles.size(); j++){
            ang = angles[j];
            ta = aux.value(ang);

            if(ang < MAX_ANGLE_CONSIDERED_BEAT)
                a_beat_angle = true;
            else if(ang > MIN_ANGLE_CONSIDERED_GYBE)
                a_gybe_angle = true;
            // just check if TA is a reasonable value
            if(ta < MIN_TA_ALLOWED || ta > MAX_TA_ALLOWED)
                return ERROR_PD_TA;
        }
        // at least one beat angle and one gybe angle
        // is required in each list of angles-ta
        if(!a_beat_angle || !a_gybe_angle)
            return ERROR_PD_ANG;
    }
    return ERROR_NONE;
}
Beispiel #9
0
bool WBCompEldMesh::UpdateMeshTransform() {
  ASSERT(m_Mesh);

  WBCompEldTransform* pTransform =
      GetEntity()->GetTransformComponent<WBCompEldTransform>();
  DEVASSERT(pTransform);  // Makes no sense to have a mesh and no transform

  const Vector EntityLocation = pTransform->GetLocation();
  const Vector CurrentLocation = EntityLocation + m_Offset;
  m_Mesh->m_Location = CurrentLocation;

  const Angles EntityOrientation = pTransform->GetOrientation();
  m_Mesh->m_Rotation = EntityOrientation;

  // Optimization, avoid the matrix and AABB calcs if nothing has changed
  if (m_OldTransform_Location != m_Mesh->m_Location ||
      m_OldTransform_Rotation != m_Mesh->m_Rotation ||
      m_OldTransform_Scale != m_Mesh->m_Scale || m_ForceUpdateTransform) {
    m_OldTransform_Location = m_Mesh->m_Location;
    m_OldTransform_Rotation = m_Mesh->m_Rotation;
    m_OldTransform_Scale = m_Mesh->m_Scale;
    m_ForceUpdateTransform = false;

    // Seems like maybe this AABB stuff should be done routinely in the Mesh. :/
    const Matrix ScaleMatrix = Matrix::CreateScale(m_Mesh->m_Scale);
    const Matrix RotationMatrix = EntityOrientation.ToMatrix();
    const Matrix TranslationMatrix = Matrix::CreateTranslation(CurrentLocation);
    const Matrix AABBTransform =
        ScaleMatrix * RotationMatrix * TranslationMatrix;
    m_Mesh->m_AABB = m_MeshOriginalAABB.GetTransformedBound(AABBTransform);

    return true;
  } else {
    return false;
  }
}
Beispiel #10
0
float PolarDiagram::getTA(const float & speed, const float & angle){
    if(!contains(speed)){
        int i = 0;
        // List of ALL the speeds avilable in de diagram
        // given in ASC order
        QList<float> speeds = diagram.keys();

        while(speeds.at(i) < speed && i < speeds.size() - 1)
            ++i;

        float ta;

        // input speed is bigger than any available
        if(i == speeds.size() - 1)
            ta = getTA(speeds.last(), angle);
        // input speed is smaller than any available
        else if(i == 0)
            ta = getTA(speeds.first(), angle);
        // input speed is between other available speeds
        else
            ta = (getTA(speeds.at(i - 1), angle) + getTA(speeds.at(i), angle)) / 2;

        return ta;
    }

    // input speed is contained in our diagram
    Angles aux = getAngles(speed);

    // List of available angles for this speed
    // List is in ASC order
    QList<float> angles = aux.keys();

    int i = 0;

    while(angles.at(i) < angle && i < angles.size() - 1)
        ++i;

    // input angle is bigger than any available
    if(i == angles.size() - 1)
        return aux.value(angles.last());
    // input angle is smaller than any available
    else if(i == 0)
        return aux.value(angles.first());
    // input angle is between other available angles
    else
        return (aux.value(angles.at(i - 1)) + aux.value(angles.at(i))) / 2;
}
/*virtual*/ void WBActionEldCheckLine::Execute()
{
	WBAction::Execute();

	STATIC_HASHED_STRING( EventOwner );
	WBEntity* const				pEntity			= GetEntity();
	WBEntity* const				pOwnerEntity	= GetOwner();
	EldritchWorld* const		pWorld			= EldritchFramework::GetInstance()->GetWorld();
	WBEventManager* const		pEventManager	= WBWorld::GetInstance()->GetEventManager();

	Vector						LineStart;
	Angles						LineOrientation;
	GetLineTransform( LineStart, LineOrientation );
	const Vector				LineDirection	= LineOrientation.ToVector();

	CollisionInfo Info;
	Info.m_CollideWorld		= true;
	Info.m_CollideEntities	= true;
	Info.m_CollidingEntity	= pOwnerEntity;
	Info.m_UserFlags		= EECF_Trace;

	if( m_LineLength > 0.0f )
	{
		const Vector			LineEnd			= LineStart + LineDirection * m_LineLength;
		const Segment			TraceSegment	= Segment( LineStart, LineEnd );
		if( !pWorld->Trace( TraceSegment, Info ) )
		{
			return;
		}
	}
	else
	{
		const Ray				TraceRay		= Ray( LineStart, LineDirection );
		if( !pWorld->Trace( TraceRay, Info ) )
		{
			return;
		}
	}

	const Vector	HitLocation		= Info.m_Intersection;
	const Vector	HitNormal		= Info.m_Plane.m_Normal;

	// Notify this entity that the line check hit that entity.
	if( Info.m_HitEntity )
	{
		WB_MAKE_EVENT( OnLineCheck, pEntity );
		WB_SET_AUTO( OnLineCheck, Hash, CheckTag, m_CheckTag );
		WB_SET_AUTO( OnLineCheck, Entity, Checked, static_cast<WBEntity*>( Info.m_HitEntity ) );
		WB_SET_AUTO( OnLineCheck, Vector, LineDirection, LineDirection );
		WB_SET_AUTO( OnLineCheck, Vector, HitLocation, HitLocation );
		WB_SET_AUTO( OnLineCheck, Vector, HitNormal, HitNormal );
		WB_DISPATCH_EVENT( pEventManager, OnLineCheck, pEntity );
	}
	else
	{
		const Vector	HalfHitNormal	= 0.5f * Info.m_Plane.m_Normal;
		const Vector	HitVoxel		= pWorld->GetVoxelCenter( HitLocation - HalfHitNormal );

		WB_MAKE_EVENT( OnLineCheckMissed, pEntity );
		WB_SET_AUTO( OnLineCheckMissed, Hash, CheckTag, m_CheckTag );
		WB_SET_AUTO( OnLineCheckMissed, Vector, LineDirection, LineDirection );
		WB_SET_AUTO( OnLineCheckMissed, Vector, HitLocation, HitLocation );
		WB_SET_AUTO( OnLineCheckMissed, Vector, HitNormal, HitNormal );
		WB_SET_AUTO( OnLineCheckMissed, Vector, HitVoxel, HitVoxel );
		WB_DISPATCH_EVENT( pEventManager, OnLineCheckMissed, pEntity );
	}
}
void Sound3DListener::SetRotation( const Angles& Rotation )
{
	Vector DummyUp;
	Rotation.GetAxes( m_Right, m_Forward, DummyUp );
}
void WBCompEldWatson::TickPrimed()
{
	if( !EldritchGame::IsPlayerAlive() )
	{
		// Player can't cause Watson to teleport and attack when dead
		return;
	}

	if( !EldritchGame::IsPlayerVisible() )
	{
		// Player can't cause Watson to teleport and attack when invisible
		return;
	}

	if( !IsPlayerVulnerable( true ) )
	{
		// Do nothing, can't attack until player is vulnerable
		return;
	}

	WBEntity* const pEntity = GetEntity();
	DEVASSERT( pEntity );

	WBEntity* const pPlayer = EldritchGame::GetPlayer();
	ASSERT( pPlayer );

	WBCompEldTransform* const pTransform = pEntity->GetTransformComponent<WBCompEldTransform>();
	DEVASSERT( pTransform );

	WBCompEldTransform* const pPlayerTransform = pPlayer->GetTransformComponent<WBCompEldTransform>();
	ASSERT( pPlayerTransform );

	const Vector			PlayerLocation		= pPlayerTransform->GetLocation();
	const Angles			PlayerOrientation	= pPlayerTransform->GetOrientation();
	EldritchWorld* const	pWorld				= GetWorld();
	ASSERT( pWorld );

	const Angles				PlayerOrientation2D	= Angles( 0.0f, 0.0f, PlayerOrientation.Yaw );
	const Vector				PlayerFacing2D		= PlayerOrientation2D.ToVector();
	WBCompEldCollision* const	pCollision			= GET_WBCOMP( pEntity, EldCollision );
	const Vector				Extents				= pCollision->GetExtents();
	Vector						TeleportLocation	= PlayerLocation - ( PlayerFacing2D * m_TeleportDist );
	CollisionInfo FindSpotInfo;
	FindSpotInfo.m_CollideWorld		= true;
	FindSpotInfo.m_CollideEntities	= true;
	FindSpotInfo.m_UserFlags		= EECF_EntityCollision;
	FindSpotInfo.m_CollidingEntity	= pEntity;

	if( pCollision->MatchesAllCollisionFlags( EECF_BlocksEntities ) )
	{
		// HACK: Test against all entities, since Watson is a blocking entity.
		FindSpotInfo.m_UserFlags |= EECF_CollideAllEntities;
	}

	if( !pWorld->FindSpot( TeleportLocation, Extents, FindSpotInfo ) )
	{
		// Do nothing, we don't fit behind player
		return;
	}

	const Vector				NewToPlayer2D		= ( PlayerLocation - TeleportLocation ).Get2D();
	const Angles				NewOrientation		= NewToPlayer2D.ToAngles();

	pTransform->SetLocation( TeleportLocation );
	pTransform->SetOrientation( NewOrientation );

	WB_MAKE_EVENT( OnWatsonTeleported, GetEntity() );
	WB_DISPATCH_EVENT( GetEventManager(), OnWatsonTeleported, GetEntity() );

	// Need to prime again before we can do another teleport
	m_Primed = false;
}
bool WBCompEldWatson::IsPlayerVulnerable( const bool CheckMinDistance ) const
{
	WBEntity* const pEntity = GetEntity();
	DEVASSERT( pEntity );

	WBEntity* const pPlayer = EldritchGame::GetPlayer();
	ASSERT( pPlayer );

	WBCompEldTransform* const pTransform = pEntity->GetTransformComponent<WBCompEldTransform>();
	DEVASSERT( pTransform );

	WBCompEldTransform* const pPlayerTransform = pPlayer->GetTransformComponent<WBCompEldTransform>();
	ASSERT( pPlayerTransform );

	const Vector	EyeLocation			= pTransform->GetLocation() + Vector( 0.0f, 0.0f, m_EyeOffsetZ );
	const Vector	PlayerLocation		= pPlayerTransform->GetLocation();
	const Vector	PlayerViewLocation	= EldritchGame::GetPlayerViewLocation();
	const Vector	ToPlayer			= PlayerViewLocation - EyeLocation;
	const float		DistanceSq			= ToPlayer.LengthSquared();

	if( CheckMinDistance && DistanceSq < m_MinAttackDistSq )
	{
		// Do nothing, we're already close to player.
		return false;
	}

	if( DistanceSq > m_MaxAttackDistSq )
	{
		// Do nothing, we're too far from the player
		return false;
	}

	// Do both a 3D and 2D check. 3D check is necessary so Watson doesn't teleport
	// when player is looking up or down at it, and 2D is necessary so Watson doesn't
	// teleport when player is looking up or down *away* from it.
	const Angles	PlayerOrientation	= pPlayerTransform->GetOrientation();
	const Angles	PlayerOrientation2D	= Angles( 0.0f, 0.0f, PlayerOrientation.Yaw );
	const Vector	PlayerFacing		= PlayerOrientation.ToVector();
	const Vector	PlayerFacing2D		= PlayerOrientation2D.ToVector();
	const Vector	ToPlayer2D			= ToPlayer.Get2D();
	const float		CosPlayerAngle		= PlayerFacing.Dot( ToPlayer );
	const float		CosPlayerAngle2D	= PlayerFacing2D.Dot( ToPlayer2D );
	if( CosPlayerAngle < 0.0f || CosPlayerAngle2D < 0.0f )
	{
		// Do nothing, player is facing us.
		return false;
	}

	EldritchWorld* const	pWorld	= GetWorld();
	ASSERT( pWorld );

	CollisionInfo OcclusionInfo;
	OcclusionInfo.m_CollideWorld		= true;
	OcclusionInfo.m_CollideEntities		= true;
	OcclusionInfo.m_UserFlags			= EECF_Occlusion;
	OcclusionInfo.m_StopAtAnyCollision	= true;
	if( pWorld->LineCheck( EyeLocation, PlayerViewLocation, OcclusionInfo ) )
	{
		// Do nothing, player is occluded.
		return false;
	}

	return true;
}
void Pose::to_angles(Angles &into) const
{
  assert(skeleton);
  into.clear(skeleton->frame_size, skeleton);
  skeleton->get_angles(*this, &into.angles[0]);
}
Beispiel #16
0
	void Matrix3::fromAngles(const Angles& angles) {
		angles.toVectors(&m[0], &m[1], &m[2]);
	}