コード例 #1
0
//------------------------------------------------------------------------
int CScriptBind_Game::RegisterWithAutoAimManager(IFunctionHandler *pH, ScriptHandle entityId, float innerRadiusFactor, float outerRadiusFactor, float snapRadiusFactor)
{
	IEntity* pEntity = gEnv->pEntitySystem->GetEntity((EntityId)entityId.n);
	if (pEntity)
	{
		AABB entityBbox;
		pEntity->GetWorldBounds(entityBbox);

		const float entityRadius = (entityBbox.IsEmpty() == false) ? entityBbox.GetRadius() : 1.0f;
		SAutoaimTargetRegisterParams registerParams;
		registerParams.fallbackOffset = 0.0f;
		registerParams.innerRadius = entityRadius * innerRadiusFactor;
		registerParams.outerRadius = entityRadius * outerRadiusFactor;
		registerParams.snapRadius = entityRadius * snapRadiusFactor;
		registerParams.snapRadiusTagged = entityRadius;
		registerParams.primaryBoneId = -1;
		registerParams.physicsBoneId = -1;
		registerParams.secondaryBoneId = -1;
		
		g_pGame->GetAutoAimManager().RegisterAutoaimTargetObject((EntityId)entityId.n, registerParams);
	}

	return pH->EndFunction();
}
コード例 #2
0
//------------------------------------------------------------------------
void CVehicleDamageBehaviorBlowTire::Activate(bool activate)
{
  if (activate == m_isActive)
    return;

  if (activate && m_pVehicle->IsDestroyed())
    return;

	if (activate)
	{
		// NOTE: stance and physics position when getting into vehicles is set wrong
		if (!gEnv->pSystem->IsSerializingFile())
			DamagePlayers();
	}

  IVehicleComponent* pComponent = m_pVehicle->GetComponent(m_component.c_str());
  if (!pComponent)
    return;

  IVehiclePart* pPart = pComponent->GetPart(0);
  if (!pPart)
    return;

  // if IVehicleWheel available, execute full damage behavior. if null, only apply effects
  IVehicleWheel* pWheel = pPart->GetIWheel();
  
  if (activate)
  {
    IEntity* pEntity = m_pVehicle->GetEntity();
    IPhysicalEntity* pPhysics = pEntity->GetPhysics();
    const Matrix34& wheelTM = pPart->GetLocalTM(false);
    const SVehicleStatus& status = m_pVehicle->GetStatus();

    if (pWheel)
    { 
      const pe_cargeomparams* pParams = pWheel->GetCarGeomParams();  
            
      // handle destroyed wheel
      pe_params_wheel wheelParams;
      wheelParams.iWheel = pWheel->GetWheelIndex();            
      wheelParams.minFriction = wheelParams.maxFriction = 0.5f * pParams->maxFriction;      
      pPhysics->SetParams(&wheelParams); 
      
      if (IVehicleMovement* pMovement = m_pVehicle->GetMovement())
      { 
        SVehicleMovementEventParams params;
        params.pComponent = pComponent;
        params.iValue = pWheel->GetWheelIndex();
        pMovement->OnEvent(IVehicleMovement::eVME_TireBlown, params);
      }

      if (status.speed > 0.1f)
      {
        // add angular impulse
        pe_action_impulse angImp;
        float amount = m_pVehicle->GetMass() * status.speed * Random(0.25f, 0.45f) * -sgn(wheelTM.GetTranslation().x);
        angImp.angImpulse = pEntity->GetWorldTM().TransformVector(Vec3(0,0,amount));    
        pPhysics->Action(&angImp);
      }
      
      m_aiImmobilizedTimer = m_pVehicle->SetTimer(-1, AI_IMMOBILIZED_TIME*1000, this);  
    }

    if (!gEnv->pSystem->IsSerializingFile())
    {
      // add linear impulse       
      pe_action_impulse imp;
      imp.point = pPart->GetWorldTM().GetTranslation();

      float amount = m_pVehicle->GetMass() * Random(0.1f, 0.15f);

      if (pWheel)
      {
        amount *= max(0.5f, min(10.f, status.speed));

        if (status.speed < 0.1f)
          amount = -0.5f*amount;
      }
      else    
        amount *= 0.5f;

      imp.impulse = pEntity->GetWorldTM().TransformVector(Vec3(0,0,amount));
      pPhysics->Action(&imp);     

      // effect
      IParticleEffect* pEffect = gEnv->pParticleManager->FindEffect(TIRE_BLOW_EFFECT);
      if (pEffect)
      {
        int slot = pEntity->LoadParticleEmitter(-1, pEffect);
        if (slot > -1)
        { 
          float rotation = pWheel ? 0.5f * gf_PI * -sgn(wheelTM.GetTranslation().x) : gf_PI;
          Matrix34 tm = Matrix34::CreateRotationZ(rotation);        
          tm.SetTranslation(wheelTM.GetTranslation());        
          pEntity->SetSlotLocalTM(slot, tm);
        }
      }

			// remove affected decals
			{
				Vec3 pos = pPart->GetWorldTM().GetTranslation();
				AABB aabb = pPart->GetLocalBounds();
				float radius = aabb.GetRadius();
				Vec3 vRadius(radius,radius,radius);
        AABB areaBox(pos-vRadius, pos+vRadius);
        
        IRenderNode * pRenderNode = NULL;				
        if (IEntityRenderProxy *pRenderProxy = (IEntityRenderProxy*)pEntity->GetProxy(ENTITY_PROXY_RENDER))
					pRenderNode = pRenderProxy->GetRenderNode();

        gEnv->p3DEngine->DeleteDecalsInRange(&areaBox, pRenderNode);
			}
    }    
  }
  else
  { 
    if (pWheel)
    {
      // restore wheel properties        
      IPhysicalEntity* pPhysics = m_pVehicle->GetEntity()->GetPhysics();    
      pe_params_wheel wheelParams;

      for (int i=0; i<m_pVehicle->GetWheelCount(); ++i)
      { 
        const pe_cargeomparams* pParams = m_pVehicle->GetWheelPart(i)->GetIWheel()->GetCarGeomParams();

        wheelParams.iWheel = i;
        wheelParams.bBlocked = 0;
        wheelParams.suspLenMax = pParams->lenMax;
        wheelParams.bDriving = pParams->bDriving;      
        wheelParams.minFriction = pParams->minFriction;
        wheelParams.maxFriction = pParams->maxFriction;
        pPhysics->SetParams(&wheelParams);
      }

			if (IVehicleMovement* pMovement = m_pVehicle->GetMovement())
			{ 
				SVehicleMovementEventParams params;
				params.pComponent = pComponent;
				params.iValue = pWheel->GetWheelIndex();
				// reset the particle status
				pMovement->OnEvent(IVehicleMovement::eVME_TireRestored, params);
			}
    }  
    
    m_aiImmobilizedTimer = -1;
  }

  m_isActive = activate;      
}
コード例 #3
0
ファイル: Claymore.cpp プロジェクト: RenEvo/dead6
void CClaymore::Update(SEntityUpdateContext &ctx, int updateSlot)
{
	CProjectile::Update(ctx, updateSlot);

	bool debug = (g_pGameCVars->g_debugMines != 0);

	if(gEnv->bServer)
	{
		if(m_armed)
		{
			CGameRules* pGR = g_pGame->GetGameRules();
			if(pGR)
			{
				for(std::list<EntityId>::iterator it = m_targetList.begin(); it != m_targetList.end(); ++it)
				{
					IEntity* pEntity = gEnv->pEntitySystem->GetEntity(*it);
					if(!pEntity) continue;
						
					// if this is a team game, claymores aren't set off by their own team...
					if(pGR->GetTeamCount() > 0 && (m_teamId != 0 && pGR->GetTeam(pEntity->GetId()) == m_teamId))
						continue;

					// otherwise, not set off by the player who dropped them.
					if(pGR->GetTeamCount() == 0 && m_ownerId == pEntity->GetId())
						continue;
					
					IPhysicalEntity *pPhysics = pEntity->GetPhysics();
					if(pPhysics)
					{
						pe_status_dynamics physStatus;
						if(0 != pPhysics->GetStatus(&physStatus) && physStatus.v.GetLengthSquared() > 0.01f)
						{
							// now check angle between this claymore and approaching object
							//	to see if it is within the angular range m_triggerAngle.
							//	If it is, then check distance is less than m_triggerRange,
							//	and also check line-of-sight between the two entities.
							IRenderAuxGeom * pRAG = gEnv->pRenderer->GetIRenderAuxGeom();
							pRAG->SetRenderFlags( e_Mode3D | e_AlphaBlended | e_DrawInFrontOff | e_FillModeSolid | e_CullModeNone );

							AABB entityBBox;	
							pEntity->GetWorldBounds(entityBBox);

							if(debug)
							{
								pRAG->DrawAABB( entityBBox, true, ColorF(1,0,0,0.4f), eBBD_Faceted );
							}

							Vec3 enemyDir = entityBBox.GetCenter() - GetEntity()->GetPos();
							Vec3 checkDir = enemyDir; 
							checkDir.z = 0;
							float distanceSq = enemyDir.GetLengthSquared();

							// for players a simple distance check is fine, but for vehicles use a better intersection check
							//	so any corner of the vehicle going inside the zone sets off the claymore.
							static float playerRadius = 2.5f;
							bool inside = false;
							if(entityBBox.GetRadius() < playerRadius)
							{
								inside = (distanceSq < (m_triggerRadius * m_triggerRadius));
							}
							else
							{							
								static ray_hit hit;
								if(gEnv->pPhysicalWorld->CollideEntityWithBeam(pEntity->GetPhysics(), GetEntity()->GetWorldPos(), enemyDir, m_triggerRadius, &hit))
								{
									inside = true;
									enemyDir = hit.pt - GetEntity()->GetWorldPos();
								}
							}

							if(inside)
							{
								enemyDir.NormalizeSafe();
								checkDir.NormalizeSafe();
								float dotProd = checkDir.Dot(m_triggerDirection);

								if(debug)
								{
									pRAG->DrawLine(GetEntity()->GetPos(), ColorF(1,0,0,1), GetEntity()->GetPos() + Matrix33::CreateRotationZ(m_triggerAngle/2.0f)*m_triggerDirection*m_triggerRadius, ColorF(1,0,0,1), 5.0f);
									pRAG->DrawLine(GetEntity()->GetPos(), ColorF(1,0,0,1), GetEntity()->GetPos() + Matrix33::CreateRotationZ(-m_triggerAngle/2.0f)*m_triggerDirection*m_triggerRadius, ColorF(1,0,0,1), 5.0f);

									ColorF clr;
									clr.a = 0.3f;
									clr.b = 0.4f;
									clr.g = 0.1f;
									clr.r = 1.0f;
									pRAG->DrawLine(GetEntity()->GetPos(), clr, GetEntity()->GetPos() + (enemyDir * m_triggerRadius), clr, 5.0f);
								}

								if(dotProd > cry_cosf(m_triggerAngle/2.0f))
								{
									static const int objTypes = ent_all&(~ent_terrain);   
									static const unsigned int flags = rwi_stop_at_pierceable|rwi_colltype_any;
									ray_hit hit;
									int col = gEnv->pPhysicalWorld->RayWorldIntersection(GetEntity()->GetPos(), (enemyDir * m_triggerRadius * 1.5f), objTypes, flags, &hit, 1, GetEntity()->GetPhysics());

									bool bang = false;
									if (!col)
										bang = true;
									else if (entityBBox.IsContainPoint(hit.pt))
										bang = true;
									else if (hit.pt.GetSquaredDistance(GetEntity()->GetWorldPos()) >= distanceSq)
										bang = true;
									if (bang)
									{
										// pass in the explosion normal, which is -m_triggerDirection
										Explode(true, false, Vec3(0,0,0), -m_triggerDirection);

										if(debug)
										{
											ColorF clr;
											clr.a = 0.3f;
											clr.g = 0.1f;
											clr.r = 1.0f;
											clr.b = 1.0f;
											pRAG->DrawLine(GetEntity()->GetPos(), clr, GetEntity()->GetPos() + (enemyDir * m_triggerRadius), clr, 5.0f);
										}
									}
								}
							}
						}
					}
				}
			}
		}
		else
		{
			m_timeToArm -= gEnv->pTimer->GetFrameTime();
			if(m_timeToArm <= 0.0f)
			{
				m_armed = true;

				IEntityTriggerProxy *pTriggerProxy = (IEntityTriggerProxy*)(GetEntity()->GetProxy(ENTITY_PROXY_TRIGGER));

				if (!pTriggerProxy)
				{
					GetEntity()->CreateProxy(ENTITY_PROXY_TRIGGER);
					pTriggerProxy = (IEntityTriggerProxy*)GetEntity()->GetProxy(ENTITY_PROXY_TRIGGER);
				}

				if(pTriggerProxy)
				{
					// create a trigger volume a couple of metres bigger than we need, to ensure we catch vehicles.
					//	Checks above will still make sure the entity is within the radius before detonating though.
					float radius = m_triggerRadius + 2.0f;
					AABB boundingBox = AABB(Vec3(-radius,-radius,-radius), Vec3(radius,radius,radius));
					pTriggerProxy->SetTriggerBounds(boundingBox);
				}
			}
		}
	}

	if(debug && m_armed)
	{
		IRenderAuxGeom * pRAG = gEnv->pRenderer->GetIRenderAuxGeom();
		ColorF clr;
		clr.a = 0.3f;
		clr.b = 0.4f;
		clr.g = 0.1f;
		clr.r = 1.0f;
		pRAG->SetRenderFlags( e_Mode3D | e_AlphaBlended | e_DrawInFrontOff | e_FillModeSolid | e_CullModeNone );
		pRAG->DrawCylinder(GetEntity()->GetPos(), Vec3(0, 0, 1), m_triggerRadius, m_triggerRadius * 2.0f, clr);
		Vec3 size(m_triggerRadius + 2.0f, m_triggerRadius + 2.0f, m_triggerRadius + 2.0f);
		AABB box(GetEntity()->GetPos() - size, GetEntity()->GetPos() + size);
		pRAG->DrawAABB(box, false, ColorF(0.1f, 0.1f, 0.1f, 0.1f), eBBD_Faceted);
		pRAG->DrawLine(GetEntity()->GetPos(), clr, GetEntity()->GetPos() + m_triggerDirection, clr, 5.0f);
	}
}
コード例 #4
0
//-----------------------------------------------------
void CThrow::ThrowObject(IEntity *pEntity, IPhysicalEntity *pPE)
{
	bool strengthMode = false;
	CPlayer *pPlayer = static_cast<CPlayer *>(m_pWeapon->GetOwnerActor());

	if (pPlayer)
	{
		// Report throw to AI system.
		if (pPlayer->GetEntity() && pPlayer->GetEntity()->GetAI())
		{
			SAIEVENT AIevent;
			AIevent.targetId = pEntity->GetId();
			pPlayer->GetEntity()->GetAI()->Event(AIEVENT_PLAYER_THROW, &AIevent);
		}
	}

	Vec3 hit = GetProbableHit(WEAPON_HIT_RANGE);
	Vec3 pos = GetFiringPos(hit);
	Vec3 dir = ApplySpread(GetFiringDir(hit, pos), GetSpread());
	Vec3 vel = GetFiringVelocity(dir);
	float speed = 12.0f;

	if(strengthMode)
	{
		speed *= m_pShared->throwparams.strenght_scale;
	}

	speed = max(2.0f, speed);
	pe_params_pos ppos;
	ppos.pos = pEntity->GetWorldPos();
	pPE->SetParams(&ppos);

	if(CheckForIntersections(pPE, dir))
	{
		Matrix34 newTM = pEntity->GetWorldTM();
		newTM.SetTranslation(newTM.GetTranslation() - (dir * 0.4f));
		pEntity->SetWorldTM(newTM, ENTITY_XFORM_POS);
	}
	else
	{
		pe_action_set_velocity asv;
		asv.v = (dir * speed) + vel;
		AABB box;
		pEntity->GetWorldBounds(box);
		Vec3 finalW = -gEnv->pSystem->GetViewCamera().GetMatrix().GetColumn0() * (8.0f / max(0.1f, box.GetRadius()));
		finalW.x *= Random(0.5f, 1.3f);
		finalW.y *= Random(0.5f, 1.3f);
		finalW.z *= Random(0.5f, 1.3f);
		asv.w = finalW;
		//asv.w = Vec3(Random(-4.5f,3.5f),Random(-1.75f,2.5f),Random(-1.5f,2.2f));
		pPE->Action(&asv);
	}

	SEntityEvent entityEvent;
	entityEvent.event = ENTITY_EVENT_PICKUP;
	entityEvent.nParam[0] = 0;

	if (pPlayer)
	{
		entityEvent.nParam[1] = pPlayer->GetEntityId();
	}

	entityEvent.fParam[0] = speed;
	pEntity->SendEvent( entityEvent );
}
コード例 #5
0
void CGame::Draw()
{
	Vector vecForward = m_hPlayer->GetGlobalView();
	Vector vecUp(0, 1, 0);

	// Cross-product http://www.youtube.com/watch?v=FT7MShdqK6w
	Vector vecRight = vecUp.Cross(vecForward).Normalized();

	CRenderer* pRenderer = GetRenderer();

	// Tell the renderer how to set up the camera.
	pRenderer->SetCameraPosition(m_hPlayer->GetGlobalOrigin() - vecForward * 6 + vecUp * 3 - vecRight * 0.5f);
	pRenderer->SetCameraDirection(vecForward);
	pRenderer->SetCameraUp(Vector(0, 1, 0));
	pRenderer->SetCameraFOV(90);
	pRenderer->SetCameraNear(0.1f);
	pRenderer->SetCameraFar(1000);

	// This rendering context is a tool for rendering things to the screen.
	// All of our drawing commands are part of it.
	CRenderingContext r(pRenderer);

	// Clear the depth buffer and set a background color.
	r.ClearDepth();
	r.ClearColor(Color(210, 230, 255));

	// CRenderer::StartRendering() - This function sets up OpenGL with the
	// camera information that we passed it before.
	pRenderer->StartRendering(&r);

	m_oFrameFrustum = CFrustum(r.GetProjection() * r.GetView());

	// First tell OpenGL what "shader" or "program" to use.
	r.UseProgram("model");

	// Set the sunlight direction. The y component is -1 so the light is pointing down.
	Vector vecSunlight = Vector(1, -1, 1).Normalized();

	// Uncomment this code to make the sunlight rotate:
	//Vector vecSunlight = Vector(cos(Game()->GetTime()), -1, sin(Game()->GetTime())).Normalized();

	r.SetUniform("vecSunlight", vecSunlight);

	r.SetUniform("bLighted", false);
	r.SetUniform("bDiffuse", false);

	// Render the ground.
	r.SetUniform("vecColor", Vector4D(0.6f, 0.7f, 0.9f, 1));
	r.SetUniform("vecCameraPosition", GetRenderer()->GetCameraPosition());
	r.BeginRenderTriFan();
		r.Normal(Vector(0, 1, 0));
		r.Tangent(Vector(1, 0, 0));
		r.Bitangent(Vector(0, 0, 1));
		r.TexCoord(Vector2D(0, 1));
		r.Vertex(Vector(-30, 0, -30));
		r.TexCoord(Vector2D(0, 0));
		r.Vertex(Vector(-30, 0, 30));
		r.TexCoord(Vector2D(1, 0));
		r.Vertex(Vector(30, 0, 30));
		r.TexCoord(Vector2D(1, 1));
		r.Vertex(Vector(30, 0, -30));
	r.EndRender();

	r.SetUniform("bLighted", true);

	// Prepare a list of entities to render.
	m_apRenderOpaqueList.clear();
	m_apRenderTransparentList.clear();

	for (size_t i = 0; i < MAX_CHARACTERS; i++)
	{
		CCharacter* pCharacter = GetCharacterIndex(i);
		if (!pCharacter)
			continue;

		// We need to scale the AABB using the character's scale values before we can use it to calculate our center/radius.
		AABB aabbSizeWithScaling = pCharacter->m_aabbSize * pCharacter->m_vecScaling;
		Vector vecCharacterCenter = pCharacter->GetGlobalOrigin() + aabbSizeWithScaling.GetCenter();
		float flCharacterRadius = aabbSizeWithScaling.GetRadius();

		// If the entity is outside the viewing frustum then the player can't see it - don't draw it.
		// http://youtu.be/4p-E_31XOPM
		if (!m_oFrameFrustum.SphereIntersection(vecCharacterCenter, flCharacterRadius))
			continue;

		if (pCharacter->m_bDrawTransparent)
			m_apRenderTransparentList.push_back(pCharacter);
		else
			m_apRenderOpaqueList.push_back(pCharacter);
	}

	// Draw all opaque characters first.
	DrawCharacters(m_apRenderOpaqueList, false);

	for (size_t i = 0; i < MAX_CHARACTERS; i++)
	{
		CCharacter* pCharacter = GetCharacterIndex(i);
		if (!pCharacter)
			continue;

		if (!pCharacter->m_bEnemyAI)
			continue;

		float flRadius = 3.5f;

		Vector vecIndicatorOrigin = NearestPointOnSphere(m_hPlayer->GetGlobalOrigin(), flRadius, pCharacter->GetGlobalOrigin());

		float flBoxSize = 0.1f;

		r.SetUniform("vecColor", Color(255, 0, 0, 255));
		r.RenderBox(vecIndicatorOrigin - Vector(1, 1, 1)*flBoxSize, vecIndicatorOrigin + Vector(1, 1, 1)*flBoxSize);
	}

	// Sort the transparent render list so that we paint the items farther from the camera first. http://youtu.be/fEjZrwDKdi8
	MergeSortTransparentRenderList();

	// Now draw all transparent characters, sorted by distance from the camera.
	DrawCharacters(m_apRenderTransparentList, true);

	r.SetUniform("bDiffuse", false);

	// Render any bullet tracers that may have been created.
	float flBulletTracerTime = 0.1f;
	for (size_t i = 0; i < Game()->GetTracers().size(); i++)
	{
		if (Game()->GetTime() < Game()->GetTracers()[i].flTimeCreated + flBulletTracerTime)
		{
			Vector vecStart = Game()->GetTracers()[i].vecStart;
			Vector vecEnd = Game()->GetTracers()[i].vecEnd;

			r.SetUniform("vecColor", Vector4D(1, 0.9f, 0, 1));
			r.BeginRenderLines();
				r.Normal(Vector(0, 1, 0));
				r.Vertex(vecStart);
				r.Vertex(vecEnd);
			r.EndRender();
		}
	}

	// Render any puffs that may have been created.
	float flPuffTime = 0.3f;
	for (size_t i = 0; i < Game()->GetPuffs().size(); i++)
	{
		if (Game()->GetTime() < Game()->GetPuffs()[i].flTimeCreated + flPuffTime)
		{
			float flTimeCreated = Game()->GetPuffs()[i].flTimeCreated;
			float flTimeOver = Game()->GetPuffs()[i].flTimeCreated + flPuffTime;
			float flStartSize = 0.2f;
			float flEndSize = 2.0f;

			float flSize = Remap(Game()->GetTime(), flTimeCreated, flTimeOver, flStartSize, flEndSize);

			Vector vecOrigin = Game()->GetPuffs()[i].vecOrigin;

			int iOrange = (int)Remap(Game()->GetTime(), flTimeCreated, flTimeOver, 0, 255);
			r.SetUniform("vecColor", Color(255, iOrange, 0, 255));
			r.RenderBox(vecOrigin - Vector(1, 1, 1)*flSize, vecOrigin + Vector(1, 1, 1)*flSize);
		}
	}

	GraphDraw();

	pRenderer->FinishRendering(&r);

	// Call this last. Your rendered stuff won't appear on the screen until you call this.
	Application()->SwapBuffers();
}
コード例 #6
0
ファイル: AutoAimManager.cpp プロジェクト: Xydrel/Infected
void CAutoAimManager::UpdateTargetInfo(SAutoaimTarget& aaTarget, float fFrameTime)
{
	IEntity * pTargetEntity = gEnv->pEntitySystem->GetEntity(aaTarget.entityId);
	if(pTargetEntity)
	{
		CActorPtr pTargetActor = aaTarget.pActorWeak.lock();
		if (pTargetActor)
		{
			Vec3 characterPos;
			Quat characterRot;

			//Need this because of decouple catch-up movement 
			if (IAnimatedCharacter* pAnimatedCharacter = pTargetActor->GetAnimatedCharacter())
			{
				const QuatT& animationLocation = pAnimatedCharacter->GetAnimLocation();
				characterPos = animationLocation.t;
				characterRot = animationLocation.q;
			}
			else
			{
				const Matrix34& targetWorldTM = pTargetEntity->GetWorldTM();

				//Fallback to entity position
				characterPos = targetWorldTM.GetTranslation();
				characterRot = Quat(targetWorldTM);
			}

			Vec3 primaryOffset(0.0f, 0.0f, aaTarget.fallbackOffset);
			Vec3 secondaryOffset(0.0f, 0.0f, aaTarget.fallbackOffset);

			if (aaTarget.primaryBoneId >= 0)
			{
				if (pTargetActor->HasBoneID(aaTarget.primaryBoneId))
				{
					primaryOffset = pTargetActor->GetBoneTransform(aaTarget.primaryBoneId).t;
				}
				else
				{		
					GameWarning("CAutoAimManager: Character %s missing primary boneID: %s", pTargetEntity->GetName(), s_BONE_ID_NAME[aaTarget.primaryBoneId]);
					aaTarget.primaryBoneId = -1;
				}
			}
			if (aaTarget.secondaryBoneId >= 0)
			{
				if (pTargetActor->HasBoneID(aaTarget.secondaryBoneId))
				{
					secondaryOffset = pTargetActor->GetBoneTransform(aaTarget.secondaryBoneId).t;
				}
				else
				{		
					GameWarning("CAutoAimManager: Character %s missing secondary boneID: %s", pTargetEntity->GetName(), s_BONE_ID_NAME[aaTarget.secondaryBoneId]);
					aaTarget.secondaryBoneId = -1;
				}
			}

			aaTarget.primaryAimPosition = characterPos + (characterRot * primaryOffset);
			aaTarget.secondaryAimPosition = characterPos + (characterRot * secondaryOffset);

			//Update hostility (changes during gameplay)
			if (!gEnv->bMultiplayer)
			{
				uint8 targetFaction = (aaTarget.aiFaction != IFactionMap::InvalidFactionID) ? aaTarget.aiFaction : GetTargetFaction(*pTargetEntity);

				if (gEnv->pAISystem->GetFactionMap().GetReaction(GetLocalPlayerFaction(), aaTarget.aiFaction) == IFactionMap::Hostile)
				{
					aaTarget.SetFlag(eAATF_AIHostile);
				}
				else
				{
					aaTarget.RemoveFlag(eAATF_AIHostile);
				}

				aaTarget.aiFaction = targetFaction;
			}
		}
		else if(aaTarget.hasSkeleton)
		{
			//Not an actor but has a skeleton (and so can use bone offsets)
			ISkeletonPose* pSkeletonPose = pTargetEntity->GetCharacter(0)->GetISkeletonPose();

			const Matrix34& characterMat = pTargetEntity->GetWorldTM();
			const Vec3 characterPos = characterMat.GetTranslation();
			const Quat characterRot(characterMat);

			Vec3 primaryOffset(0.0f, 0.0f, aaTarget.fallbackOffset);
			Vec3 secondaryOffset(0.0f, 0.0f, aaTarget.fallbackOffset);

			if (aaTarget.primaryBoneId >= 0)
			{
				primaryOffset = pSkeletonPose->GetAbsJointByID(aaTarget.primaryBoneId).t;
			}
			if (aaTarget.secondaryBoneId >= 0)
			{
				secondaryOffset = pSkeletonPose->GetAbsJointByID(aaTarget.secondaryBoneId).t;
			}

			aaTarget.primaryAimPosition = characterPos + (characterRot * primaryOffset);
			aaTarget.secondaryAimPosition = characterPos + (characterRot * secondaryOffset);
		}
		else
		{
			//Must be an object
			const Matrix34& entityWorldTM = pTargetEntity->GetWorldTM(); 
			Vec3 primaryPosition = entityWorldTM.GetTranslation();
			Vec3 secondaryPosition = entityWorldTM.TransformPoint(Vec3(0.0f, 0.0f, 0.5f));

			AABB entityLocalBBox;
			pTargetEntity->GetLocalBounds(entityLocalBBox);
			if (!entityLocalBBox.IsEmpty())
			{
				const Vec3 offset (0.0f, 0.0f, entityLocalBBox.GetRadius() * 0.2f);
				const Vec3 objectCenter = entityLocalBBox.GetCenter();
				primaryPosition = entityWorldTM.TransformPoint((objectCenter - offset));
				secondaryPosition = entityWorldTM.TransformPoint((objectCenter + offset));
			}

			aaTarget.primaryAimPosition = primaryPosition;
			aaTarget.secondaryAimPosition = secondaryPosition;
		}

		//The physics drags the render proxy and entity behind it. If we auto aim at the render position,
		//	we will handicap the console players by failing to let them aim ahead of the target.
		if(IPhysicalEntity * pPhysicalEntity = pTargetEntity->GetPhysics())
		{
			pe_status_dynamics dyn;
			if(pPhysicalEntity->GetStatus(&dyn))
			{
				Vec3 lookAhead = (dyn.v * fFrameTime);
				aaTarget.primaryAimPosition = aaTarget.primaryAimPosition + lookAhead;
				aaTarget.secondaryAimPosition = aaTarget.secondaryAimPosition + lookAhead;
			}
		}
	}
}
コード例 #7
0
//------------------------------------------------------------------------
bool CTracer::Update(float frameTime, const Vec3 &camera, const float fovScale)
{
	frameTime							= (float)__fsel(-m_age, 0.002f, frameTime);
	const float tracerAge	= (float)__fsel(-m_age, 0.002f, m_age+frameTime);

	m_age = tracerAge;

	if (tracerAge >= m_lifeTime)
		return false;

	Vec3 currentLimitDestination;
	if (gEnv->bMultiplayer)
	{
		if(m_tracerFlags & kTracerFlag_updateDestFromBullet)
		{
			IEntity* pBulletEntity = gEnv->pEntitySystem->GetEntity(m_boundToBulletId);
			if(pBulletEntity)
			{
				m_dest = pBulletEntity->GetPos();
			}
		}
		currentLimitDestination = m_dest;
	}
	else
	{
		IEntity* pBulletEntity = gEnv->pEntitySystem->GetEntity(m_boundToBulletId);
		currentLimitDestination = pBulletEntity ? pBulletEntity->GetPos() : m_dest;
	}

	const Vec3 maxTravelledDistance = m_dest - m_startingPos;
	const float maxTravelledDistanceSqr = maxTravelledDistance.len2();
	
	float dist = sqrt_tpl(maxTravelledDistanceSqr);
	if (dist <= 0.001f)
		return false;
		
	const Vec3 dir = maxTravelledDistance * (float)__fres(dist);
	Vec3 pos = m_pos;
	float lengthScale = 1.f;
	Vec3 newPos = m_pos;
	
	if (!(m_tracerFlags & kTracerFlag_dontTranslate))
  {
    const float sqrRadius = GetGameConstCVar(g_tracers_slowDownAtCameraDistance) * GetGameConstCVar(g_tracers_slowDownAtCameraDistance);
		const float cameraDistance = (m_pos-camera).len2();
    const float speed = m_speed * (float)__fsel(sqrRadius - cameraDistance, 0.35f + (cameraDistance/(sqrRadius*2)), 1.0f); //Slow down tracer when near the player
    newPos += dir * min(speed*frameTime, dist);
	  pos = newPos;

		if(m_slideFrac > 0.f)
		{
			pos += (((2.f * cry_frand()) - 0.5f) * m_slideFrac * speed * frameTime * dir);
		}
  }

	// Now update visuals...
	if (IEntity *pEntity = gEnv->pEntitySystem->GetEntity(m_entityId))
	{
		AABB tracerBbox;
		pEntity->GetWorldBounds(tracerBbox);

		float tracerHalfLength = !tracerBbox.IsEmpty() ? tracerBbox.GetRadius() : 0.0f;
		const Vec3 frontOfTracerPos = pos + (dir * tracerHalfLength);

		if((frontOfTracerPos-m_startingPos).len2() > maxTravelledDistanceSqr)
		{
			return false;
		}
	
		if (!(m_tracerFlags & kTracerFlag_dontTranslate) && tracerHalfLength > 0.f)
		{
			//Ensure that never goes in front of the bullet
			const Vec3 dirFromFrontOfTracerToDestination = currentLimitDestination - frontOfTracerPos;
			if (dir.dot(dirFromFrontOfTracerToDestination) < 0)
			{
				pos += dirFromFrontOfTracerToDestination;
			}

			// ... and check if back of tracer is behind starting point, so adjust length.
			const Vec3 backOfTracerPos = pos - (dir * tracerHalfLength);
			const Vec3 dirFromBackOfTracerToStart = m_startingPos - backOfTracerPos;

			if (dir.dot(dirFromBackOfTracerToStart) > 0)
			{
				if(dir.dot((m_startingPos - pos)) > 0)
				{
					pos = m_startingPos + (dir * cry_frand() * tracerHalfLength);
				}

				lengthScale = ((pos - m_startingPos).GetLength() / tracerHalfLength);
			}
		}
		
		m_pos = newPos;
		
		Matrix34 tm(Matrix33::CreateRotationVDir(dir));
		tm.AddTranslation(pos);

		pEntity->SetWorldTM(tm);

		//Do not scale effects
		if((m_tracerFlags & kTracerFlag_useGeometry))
		{
			float finalFovScale = fovScale;
			if((m_tracerFlags & kTracerFlag_scaleToDistance) != 0)
			{
				lengthScale = dist * 0.5f;
			}
			else
			{
				const float cameraDistanceSqr = (m_pos-camera).len2();
				const float minScale = GetGameConstCVar(g_tracers_minScale);
				const float maxScale = GetGameConstCVar(g_tracers_maxScale);
				const float minDistanceRange = GetGameConstCVar(g_tracers_minScaleAtDistance) * GetGameConstCVar(g_tracers_minScaleAtDistance);
				const float maxDistanceRange = max(GetGameConstCVar(g_tracers_maxScaleAtDistance) * GetGameConstCVar(g_tracers_maxScaleAtDistance), minDistanceRange + 1.0f);
				const float currentRefDistance = clamp(cameraDistanceSqr, minDistanceRange, maxDistanceRange);

				const float distanceToCameraFactor = ((currentRefDistance - minDistanceRange) / (maxDistanceRange - minDistanceRange));
				const float distanceToCameraScale = LERP(minScale, maxScale, distanceToCameraFactor);
				
				lengthScale = m_scale * distanceToCameraScale;
				finalFovScale *= distanceToCameraScale;
			}
			
			const float widthScale = fovScale;

			tm.SetIdentity();
			tm.SetScale(Vec3(m_scale * finalFovScale, lengthScale, m_scale * finalFovScale));
			pEntity->SetSlotLocalTM(m_geometrySlot,tm);
		}
	}

	return true;
}
コード例 #8
0
void CPlayerView::ViewSpectatorTarget(SViewParams &viewParams)
{
	CActor *pTarget = (CActor *)g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(m_in.stats_spectatorTarget);

	if(!pTarget)
	{
		return;
	}

	Matrix34 worldTM = pTarget->GetEntity()->GetWorldTM();
	Vec3 worldPos = worldTM.GetTranslation();
	worldPos.z += 1.5f;
	Ang3 worldAngles = Ang3::GetAnglesXYZ(Matrix33(worldTM));
	float rot = worldAngles.z;// + m_rot;
	float distance = 3;//(m_defaultDistance != 0) ? m_defaultDistance : m_distance;

	if(IVehicle *pVehicle = pTarget->GetLinkedVehicle())
	{
		AABB vehicleBox;
		pVehicle->GetEntity()->GetLocalBounds(vehicleBox);
		distance = 2.0f * vehicleBox.GetRadius();
	}

	Vec3 goal;
	float zoom = 1.0f;
	goal.x = distance * zoom * cosf(rot + gf_PI * 1.5f) + worldPos.x;
	goal.y = distance * zoom * sinf(rot - gf_PI / 2.0f) + worldPos.y;
	AABB targetBounds;
	pTarget->GetEntity()->GetLocalBounds(targetBounds);
	goal.z = targetBounds.max.z;
	static float defaultOffset = 0.75f;
	float offset = defaultOffset;

	if(pTarget->GetLinkedVehicle())
	{
		offset = 2.0f;
	}

	goal.z += pTarget->GetEntity()->GetWorldPos().z + offset;
	// store / interpolate the offset, not the world pos (reduces percieved jitter in vehicles)
	static Vec3 viewOffset(goal - worldPos);
	static Vec3 position(goal);
	static Vec3 entPos(worldPos);
	static EntityId lastSpectatorTarget(m_in.stats_spectatorTarget);
	// do a ray cast to check for camera intersection
	static ray_hit hit;
	IPhysicalEntity *pSkipEntities[10];
	int nSkip = 0;
	IItem *pItem = pTarget->GetCurrentItem();

	if (pItem)
	{
		CWeapon *pWeapon = (CWeapon *)pItem->GetIWeapon();

		if (pWeapon)
		{
			nSkip = CSingle::GetSkipEntities(pWeapon, pSkipEntities, 10);
		}
	}
	else if(IVehicle *pVehicle = pTarget->GetLinkedVehicle())
	{
		// vehicle drivers don't seem to have current items, so need to add the vehicle itself here
		nSkip = pVehicle->GetSkipEntities(pSkipEntities, 10);
	}

	const float wallSafeDistance = 0.2f; // how far to keep camera from walls
	Vec3 dir = goal - worldPos;
	primitives::sphere sphere;
	sphere.center = worldPos;
	sphere.r = wallSafeDistance;
	geom_contact *pContact = 0;
	float hitDist = gEnv->pPhysicalWorld->PrimitiveWorldIntersection(sphere.type, &sphere, dir, ent_static | ent_terrain | ent_rigid | ent_sleeping_rigid,
					&pContact, 0, geom_colltype_player, 0, 0, 0, pSkipEntities, nSkip);
	// even when we have contact, keep the camera the same height above the target
	float minHeightDiff = dir.z;

	if(hitDist > 0 && pContact)
	{
		goal = worldPos + (hitDist * dir.GetNormalizedSafe());

		if(goal.z - worldPos.z < minHeightDiff)
		{
			// can't move the camera far enough away from the player in this direction. Try moving it directly up a bit
			sphere.center = goal;
			// (move back just slightly to avoid colliding with the wall we've already found...)
			sphere.center -= dir.GetNormalizedSafe() * 0.05f;
			float newHitDist = gEnv->pPhysicalWorld->PrimitiveWorldIntersection(sphere.type, &sphere, Vec3(0, 0, minHeightDiff), ent_static | ent_terrain | ent_rigid | ent_sleeping_rigid,
							   &pContact, 0, geom_colltype_player, 0, 0, 0, pSkipEntities, nSkip);
			float raiseDist = minHeightDiff - (goal.z - worldPos.z) - wallSafeDistance;

			if(newHitDist != 0)
			{
				raiseDist = MIN(minHeightDiff, newHitDist);
			}

			raiseDist = MAX(0.0f, raiseDist);
			goal.z += raiseDist;
			worldPos.z += raiseDist * 0.8f;
		}
	}

	int thisFrameId = gEnv->pRenderer->GetFrameID();
	static int frameNo(thisFrameId);

	if(thisFrameId - frameNo > 5)
	{
		// reset positions
		viewOffset = goal - worldPos;
		entPos = worldPos;
		position = goal;
	}

	if(lastSpectatorTarget != m_in.stats_spectatorTarget)
	{
		viewOffset = goal - worldPos;
		entPos = worldPos;
		position = goal;
		lastSpectatorTarget = m_in.stats_spectatorTarget;
	}

	frameNo = thisFrameId;

	if(pTarget->GetLinkedVehicle())
	{
		Interpolate(viewOffset, goal - worldPos, 5.0f, viewParams.frameTime);
		entPos = worldPos;
		viewParams.position = worldPos + viewOffset;
		position = viewParams.position;
	}
	else
	{
		Vec3 camPosChange = goal - position;
		Vec3 entPosChange = worldPos - entPos;

		if(camPosChange.GetLengthSquared() > 100.0f)
		{
			position = goal;
		}

		if(entPosChange.GetLengthSquared() > 100.0f)
		{
			entPos = worldPos;
		}

		Interpolate(position, goal, 5.0f, viewParams.frameTime);
		Interpolate(entPos, worldPos, 5.0f, viewParams.frameTime);
		viewParams.position = position;
	}

	Matrix33 rotation = Matrix33::CreateRotationVDir((entPos - viewParams.position).GetNormalizedSafe());
	viewParams.rotation = Quat(rotation);
	m_io.bUsePivot = true;
	m_io.stats_bobCycle = 0.0;
}