Beispiel #1
0
//-------------------------------------------------------------------------
int CScriptBind_Action::ClearEntityTags(IFunctionHandler* pH, ScriptHandle entityId)
{
	IPersistantDebug* pPD = CCryAction::GetCryAction()->GetIPersistantDebug();
	pPD->ClearEntityTags((EntityId)entityId.n);

	return pH->EndFunction();
}
	virtual void ProcessEvent(EFlowEvent event, SActivationInfo* pActInfo)
	{
#if !defined(_RELEASE)
		switch (event)
		{
			case eFE_Activate:
			{
				if (IsPortActive(pActInfo, eIP_Draw))
				{
					IPersistantDebug* pPersistentDebug = CCryAction::GetCryAction()->GetIPersistantDebug();
					if (pPersistentDebug)
					{
						const Vec3 pos1 = GetPortVec3(pActInfo, eIP_Pos1);
						const Vec3 pos2 = GetPortVec3(pActInfo, eIP_Pos2);
						const	float time = GetPortFloat(pActInfo, eIP_Time);
						const ColorF color = GetPortVec3(pActInfo, eIP_Color);

						Vec3 offset(pos2);

						if (pos2.IsZero())
						{
							offset = pos1 + (GetPortVec3(pActInfo, eIP_Dir) * GetPortFloat(pActInfo, eIP_Length));
						}
							
						pPersistentDebug->Begin("FG_Line", false);
						pPersistentDebug->AddLine(pos1, offset, color, time);
					}
				}
				break;
			}
		}
#endif
	}
Beispiel #3
0
//-------------------------------------------------------------------------
int CScriptBind_Action::ClearStaticTag(IFunctionHandler* pH, ScriptHandle entityId, const char *staticId)
{
	IPersistantDebug* pPD = CCryAction::GetCryAction()->GetIPersistantDebug();
	pPD->ClearStaticTag((EntityId)entityId.n, staticId);

	return pH->EndFunction();
}
int CScriptBind_Game::DebugDrawPersistanceDirection(
		IFunctionHandler *pH,
		float startX, float startY, float startZ, 
		float dirX, float dirY, float dirZ,
		int r, int g, int b,
		float duration)
{
	IPersistantDebug* debugRenderer = gEnv->pGame->GetIGameFramework()->GetIPersistantDebug();
	assert(debugRenderer != NULL);

	debugRenderer->Begin("CScriptBind_Game::DebugDrawPersistanceDirection", false);
	
	const Vec3 direction(dirX, dirY, dirZ);
	const float length = direction.GetLength();
	const float radius = max(0.1f, length * 0.05f);

	debugRenderer->AddDirection(Vec3(startX, startY, startZ), radius, direction,
		ColorF(
			((float)r) / 256.0f, 
			((float)g) / 256.0f, 
			((float)b) / 256.0f, 
			1.0f),
		duration);

	return pH->EndFunction();
}
Beispiel #5
0
//-------------------------------------------------------------------------
int CScriptBind_Action::PersistantArrow(IFunctionHandler* pH, Vec3 pos, float radius, Vec3 dir, Vec3 color, const char* name, float timeout)
{
  IPersistantDebug* pPD = CCryAction::GetCryAction()->GetIPersistantDebug();

  pPD->Begin(name, false);
  pPD->AddDirection(pos, radius, dir, ColorF(color, 1.f), timeout);

  return pH->EndFunction();
}
Beispiel #6
0
//-------------------------------------------------------------------------
int CScriptBind_Action::Persistant2DText(IFunctionHandler* pH, const char* text, float size, Vec3 color, const char* name, float timeout)
{
  IPersistantDebug* pPD = CCryAction::GetCryAction()->GetIPersistantDebug();

  pPD->Begin(name, false);
  pPD->Add2DText(text, size, ColorF(color, 1.f), timeout);

  return pH->EndFunction();
}
Beispiel #7
0
//-------------------------------------------------------------------------
int CScriptBind_Action::PersistantLine(IFunctionHandler* pH, Vec3 start, Vec3 end, Vec3 color, const char* name, float timeout)
{
  IPersistantDebug* pPD = CCryAction::GetCryAction()->GetIPersistantDebug();
  
  pPD->Begin(name, false);
  pPD->AddLine(start, end, ColorF(color, 1.f), timeout);

  return pH->EndFunction();
}
Beispiel #8
0
//-----------------------------------------------------------------------
IPersistantDebug*	CSpectacularKill::BeginPersistantDebug() const
{
#ifndef _RELEASE
	IPersistantDebug* pPersistantDebug = g_pGame->GetIGameFramework()->GetIPersistantDebug();
	pPersistantDebug->Begin((PERSISTANT_DEBUG_NOT_VALID_ANIM_TAG + m_pOwner->GetEntity()->GetName()).c_str(), true);

	return pPersistantDebug;
#else
	return NULL;
#endif
}
Beispiel #9
0
void CNetPlayerInput::DoSetState(const SSerializedPlayerInput& input )
{
	m_newInterpolation |= (input.position != m_curInput.position) || (input.deltaMovement != m_curInput.deltaMovement);

	const bool wasSprinting = m_curInput.sprint;

	m_curInput = input;
	CHANGED_NETWORK_STATE(m_pPlayer,  CPlayer::ASPECT_INPUT_CLIENT );

	if(wasSprinting != input.sprint)
	{
		SInputEventData inputEventData( SInputEventData::EInputEvent_Sprint, m_pPlayer->GetEntityId(), CCryName("sprint"), input.sprint ? eAAM_OnPress : eAAM_OnRelease, 0.f );
		m_pPlayer->StateMachineHandleEventMovement( SStateEventPlayerInput( &inputEventData ) );
	}

	// not having these set seems to stop a remote avatars rotation being reflected
	m_curInput.aiming = true;
	m_curInput.allowStrafing = true;
	m_curInput.usinglookik = true;

	IAIActor* pAIActor = CastToIAIActorSafe(m_pPlayer->GetEntity()->GetAI());
	if (pAIActor)
		pAIActor->GetState().bodystate=input.bodystate;

	CMovementRequest moveRequest;
	moveRequest.SetStance( (EStance)m_curInput.stance );

	if(IsDemoPlayback())
	{
		Vec3 localVDir(m_pPlayer->GetViewQuatFinal().GetInverted() * m_curInput.lookDirection);
		Ang3 deltaAngles(asinf(localVDir.z),0,atan2_tpl(-localVDir.x,localVDir.y));
		moveRequest.AddDeltaRotation(deltaAngles*gEnv->pTimer->GetFrameTime());
	}

	moveRequest.SetPseudoSpeed(CalculatePseudoSpeed());
	moveRequest.SetAllowStrafing(input.allowStrafing);

	m_pPlayer->GetMovementController()->RequestMovement(moveRequest);

#if !defined(_RELEASE)
	// debug..
	if (g_pGameCVars->g_debugNetPlayerInput & 1)
	{
		IPersistantDebug * pPD = gEnv->pGame->GetIGameFramework()->GetIPersistantDebug();
		pPD->Begin( string("net_player_input_") + m_pPlayer->GetEntity()->GetName(), true );
		pPD->AddSphere( moveRequest.GetLookTarget(), 0.5f, ColorF(1,0,1,1), 1.0f );
		//			pPD->AddSphere( moveRequest.GetMoveTarget(), 0.5f, ColorF(1,1,0,1), 1.0f );

		Vec3 wp(m_pPlayer->GetEntity()->GetWorldPos() + Vec3(0,0,2));
		pPD->AddDirection( wp, 1.5f, m_curInput.deltaMovement, ColorF(1,0,0,1), 1.0f );
		pPD->AddDirection( wp, 1.5f, m_curInput.lookDirection, ColorF(0,1,0,1), 1.0f );
	}
#endif
}
Beispiel #10
0
//-----------------------------------------------------------------------
bool CSpectacularKill::ObstacleCheck(const Vec3& vKillerPos, const Vec3& vTargetPos, const SSpectacularKillAnimation& anim) const
{
	// [*DavidR | 13/Sep/2010] ToDo: Find a way to make this asynchronously
	const float OBSTACLE_CHECK_RADIUS = 0.6f;
	const float OBSTACLE_CHECK_GROUND_OFFSET = 0.2f;

	const Vec3& vCapsuleKillerEnd = vKillerPos + anim.vKillerObstacleCheckOffset;

	primitives::capsule capsPrim;
	const Vec3& vKillerToTargetDist = vTargetPos - vCapsuleKillerEnd;
	capsPrim.axis = vKillerToTargetDist.GetNormalized();
	capsPrim.r = OBSTACLE_CHECK_RADIUS;

	// hh is actually half the total height (it's measured from the center)
	capsPrim.hh = static_cast<float>(__fsel(anim.fObstacleCheckLength, 
				(anim.fObstacleCheckLength * 0.5f) - capsPrim.r,
				(min(g_pGameCVars->g_spectacularKill.maxDistanceError, vKillerToTargetDist.GetLength()) * 0.5f) - capsPrim.r));

	capsPrim.center = vCapsuleKillerEnd + (capsPrim.axis * (capsPrim.hh + capsPrim.r));
	capsPrim.center.z += capsPrim.r + OBSTACLE_CHECK_GROUND_OFFSET;

	geom_contact* pContact = NULL;
	int collisionEntityTypes = ent_static | ent_terrain | ent_sleeping_rigid | ent_ignore_noncolliding;
	float d = gEnv->pPhysicalWorld->PrimitiveWorldIntersection(capsPrim.type, &capsPrim, Vec3Constants<float>::fVec3_Zero, collisionEntityTypes, &pContact, 0, geom_colltype0);

	bool bObstacleFound = (d != 0.0f) && pContact;

#ifndef _RELEASE
	if (bObstacleFound && (g_pGameCVars->g_spectacularKill.debug > 1))
	{
		const float fTime = 6.0f;

		// visually show why it failed
		IPersistantDebug* pPersistantDebug = BeginPersistantDebug();

		// Draw a capsule using a cylinder and two spheres
		const ColorF debugColor = Col_Coral * ColorF(1.0f, 1.0f, 1.0f, 0.6f);
		pPersistantDebug->AddCylinder(capsPrim.center, capsPrim.axis, capsPrim.r, capsPrim.hh * 2.0f, debugColor, fTime);
		pPersistantDebug->AddSphere(capsPrim.center - (capsPrim.axis * capsPrim.hh), capsPrim.r, debugColor, fTime);
		pPersistantDebug->AddSphere(capsPrim.center + (capsPrim.axis * capsPrim.hh), capsPrim.r, debugColor, fTime);

		for (int i = 0; i < (int)d; ++i)
		{
		// Draw the collision point
			geom_contact collisionData(pContact[i]);
		pPersistantDebug->AddCone(collisionData.pt, -collisionData.n, 0.1f, 0.8f, Col_Red, fTime + 2.0f);
	}
	}
#endif

	return bObstacleFound;
}
Beispiel #11
0
// ============================================================================
//	Render debug information.
//
void HazardModule::RenderDebug() const
{
	IPersistantDebug *debugRenderer = gEnv->pGame->GetIGameFramework()->GetIPersistantDebug();
	if (debugRenderer == NULL)
	{
		return;
	}

	debugRenderer->Begin("HazardDebugGraphics", false);

	RenderDebugProcessContainer(m_ProjectileHazards, *debugRenderer);
	RenderDebugProcessContainer(m_SphereHazards, *debugRenderer);
}
Beispiel #12
0
void CNetPlayerInput::DoSetState(const SSerializedPlayerInput& input )
{
	m_curInput = input;
	m_pPlayer->GetGameObject()->ChangedNetworkState( INPUT_ASPECT );

	CMovementRequest moveRequest;
	moveRequest.SetStance( (EStance)m_curInput.stance );

	if(IsDemoPlayback())
	{
		Vec3 localVDir(m_pPlayer->GetViewQuatFinal().GetInverted() * m_curInput.lookDirection);
		Ang3 deltaAngles(asin(localVDir.z),0,cry_atan2f(-localVDir.x,localVDir.y));
		moveRequest.AddDeltaRotation(deltaAngles*gEnv->pTimer->GetFrameTime());
	}
	//else
	{
		moveRequest.SetLookTarget( m_pPlayer->GetEntity()->GetWorldPos() + 10.0f * m_curInput.lookDirection );
		moveRequest.SetAimTarget(moveRequest.GetLookTarget());
	}

	float pseudoSpeed = 0.0f;
	if (m_curInput.deltaMovement.len2() > 0.0f)
	{
		pseudoSpeed = m_pPlayer->CalculatePseudoSpeed(m_curInput.sprint);
	}
	moveRequest.SetPseudoSpeed(pseudoSpeed);
	moveRequest.SetAllowStrafing(true);

	float lean=0.0f;
	if (m_curInput.leanl)
		lean-=1.0f;
	if (m_curInput.leanr)
		lean+=1.0f;
	moveRequest.SetLean(lean);

	m_pPlayer->GetMovementController()->RequestMovement(moveRequest);

	// debug..
	if (g_pGameCVars->g_debugNetPlayerInput & 1)
	{
		IPersistantDebug * pPD = gEnv->pGame->GetIGameFramework()->GetIPersistantDebug();
		pPD->Begin( string("net_player_input_") + m_pPlayer->GetEntity()->GetName(), true );
		pPD->AddSphere( moveRequest.GetLookTarget(), 0.5f, ColorF(1,0,1,1), 1.0f );
		//			pPD->AddSphere( moveRequest.GetMoveTarget(), 0.5f, ColorF(1,1,0,1), 1.0f );

		Vec3 wp(m_pPlayer->GetEntity()->GetWorldPos() + Vec3(0,0,2));
		pPD->AddDirection( wp, 1.5f, m_curInput.deltaMovement, ColorF(1,0,0,1), 1.0f );
		pPD->AddDirection( wp, 1.5f, m_curInput.lookDirection, ColorF(0,1,0,1), 1.0f );
	}
}
	void ProcessEvent(EFlowEvent event, SActivationInfo* pActInfo)
	{
#if !defined(_RELEASE)
		if (event == eFE_Initialize && IsPortActive(pActInfo, eIP_Draw))
		{
			m_waitTime = 0.0f;
			pActInfo->pGraph->SetRegularlyUpdated(pActInfo->myID, false);
		}
		else if (event == eFE_Activate && IsPortActive(pActInfo, eIP_Draw))
		{
			IEntity* pEntity = pActInfo->pEntity;
			if (pEntity)
			{
				IPersistantDebug* pPersistentDebug = CCryAction::GetCryAction()->GetIPersistantDebug();
				if (pPersistentDebug)
				{
					SEntityTagParams params;
					params.entity = pEntity->GetId();
					params.text = GetPortString(pActInfo, eIP_Message);
					params.size = GetPortFloat(pActInfo, eIP_FontSize);
					params.color = ColorF(GetPortVec3(pActInfo, eIP_Color), 1.0f);
					params.visibleTime = GetPortFloat(pActInfo, eIP_Time);
					params.fadeTime = GetPortFloat(pActInfo, eIP_FadeTime);
					params.viewDistance = GetPortFloat(pActInfo, eIP_ViewDistance);
					params.staticId = GetPortString(pActInfo, eIP_StaticID);
					params.column = GetPortInt(pActInfo, eIP_Column);
					params.tagContext = "FG_DrawEntityTagAdvanced";

					pPersistentDebug->AddEntityTag(params);

					m_waitTime = gEnv->pTimer->GetFrameStartTime() + (params.fadeTime + params.visibleTime);
					pActInfo->pGraph->SetRegularlyUpdated(pActInfo->myID, true);
				}
			}
		}
		else if (event == eFE_Update)
		{
			if (m_waitTime < gEnv->pTimer->GetFrameStartTime())
			{
				m_waitTime.SetSeconds(0.0f);
				pActInfo->pGraph->SetRegularlyUpdated(pActInfo->myID, false);
				ActivateOutput(pActInfo, eOP_Done, GetPortAny(pActInfo, eIP_Draw));
			}
		}
#endif
	}
//-----------------------------------------------------------------------
void CMelee::PerformMelee(const Vec3 &pos, const Vec3 &dir, bool remote)
{
	CCCPOINT_IF(! remote, Melee_PerformLocal);
	CCCPOINT_IF(remote, Melee_PerformRemote);

	MeleeDebugLog ("CMelee<%p> PerformMelee(remote=%s)", this, remote ? "true" : "false");

#if !defined(_RELEASE)
	if(g_pGameCVars->pl_melee.debug_gfx)
	{
		IPersistantDebug  *pDebug = g_pGame->GetIGameFramework()->GetIPersistantDebug();
		pDebug->Begin("CMelee::PerformMelee", false);
		pDebug->AddLine(pos, (pos + dir), ColorF(1.f,0.f,0.f,1.f), 15.f);
	}
#endif

	m_collisionHelper.DoCollisionTest(SCollisionTestParams(pos, dir, GetRange(), m_pWeapon->GetOwnerId(), 0, remote));
}
Beispiel #15
0
//-------------------------------------------------------------------------
// Required Params: entityId, const char *text
// Optional Params: float size, Vec3 color, float visibleTime, float fadeTime, float viewDistance, const char* staticId, int columnNum, const char* contextTag
int CScriptBind_Action::PersistantEntityTag(IFunctionHandler* pH, ScriptHandle entityId, const char *text)
{
	IPersistantDebug* pPD = CCryAction::GetCryAction()->GetIPersistantDebug();

	SEntityTagParams params;
	params.entity = (EntityId)entityId.n;
	params.text = text;
	params.tagContext = "scriptbind";

	// Optional params
	if (pH->GetParamType(3) != svtNull) // Size
		pH->GetParam(3, params.size);
	if (pH->GetParamType(4) != svtNull) // Color
	{
		Vec3 color;
		pH->GetParam(4, color);
		params.color = ColorF(color, 1.f);
	}
	if (pH->GetParamType(5) != svtNull) // Visible Time
		pH->GetParam(5, params.visibleTime);
	if (pH->GetParamType(6) != svtNull) // Fade Time
		pH->GetParam(6, params.fadeTime);
	if (pH->GetParamType(7) != svtNull) // View Distance
		pH->GetParam(7, params.viewDistance);
	if (pH->GetParamType(8) != svtNull) // Static ID
	{
		const char *staticId;
		pH->GetParam(8, staticId);
		params.staticId = staticId;
	}
	if (pH->GetParamType(9) != svtNull) // Column Num
		pH->GetParam(9, params.column);
	if (pH->GetParamType(10) != svtNull) // Context Tag
	{
		const char *tagContext;
		pH->GetParam(10, tagContext);
		params.tagContext = tagContext; // overrides default one set above
	}

	pPD->AddEntityTag(params);
	
	return pH->EndFunction();
}
	virtual void ProcessEvent(EFlowEvent event, SActivationInfo* pActInfo)
	{
#if !defined(_RELEASE)
		if (event == eFE_Activate)
		{
			if (IsPortActive(pActInfo, eIP_Draw))
			{
				IPersistantDebug* pPersistentDebug = CCryAction::GetCryAction()->GetIPersistantDebug();
				if (pPersistentDebug)
				{
					const Vec3 pos = GetPortVec3(pActInfo, eIP_Pos);
					const float radius = GetPortFloat(pActInfo, eIP_Radius);
					const float time = GetPortFloat(pActInfo, eIP_Time);
					const ColorF color = GetPortVec3(pActInfo, eIP_Color);

					pPersistentDebug->Begin("FG_Sphere", false);
					pPersistentDebug->AddSphere(pos, radius, color, time);
				}
			}
		}
#endif
	}
Beispiel #17
0
void    CGunTurret::DrawDebug()
{
	IPersistantDebug *pDebug = gEnv->pGame->GetIGameFramework()->GetIPersistantDebug();
	pDebug->Begin("CGunTurret::DrawDebug", true);

	Vec3 gun(ZERO),rocket(ZERO),radar(ZERO),barrel(ZERO);

	gun = GetSlotHelperPos(eIGS_ThirdPerson,m_fireHelper,true);
	rocket = GetSlotHelperPos(eIGS_ThirdPerson,m_rocketHelper,true);
	barrel = GetSlotHelperPos(eIGS_ThirdPerson,m_barrelHelper,true);
	radar = GetSlotHelperPos(eIGS_Aux0,m_radarHelper,true);

	pDebug->AddSphere(gun, 0.2f, ColorF(1,0,0,1), 1.f);
	pDebug->AddSphere(rocket, 0.2f, ColorF(0,1,0,1), 1.f);
	pDebug->AddSphere(radar, 0.2f, ColorF(0,0,1,1), 1.f);
	pDebug->AddSphere(barrel, 0.2f, ColorF(1,0,1,1), 1.f);
}
Beispiel #18
0
//------------------------------------------------------------------------
Vec3 CGunTurret::PredictTargetPos(IEntity *pTarget, bool sec)//sec - weapon to use
{
	pTarget = ResolveTarget(pTarget);
	Vec3 tpos = GetTargetPos(pTarget);

	if(m_turretparams.search_only || m_turretparams.prediction == 0.f)
		return tpos;

	IPhysicalEntity *pe = pTarget->GetPhysics();
	pe_status_dynamics dyn;

	if(!pe || !pe->GetStatus(&dyn))
		return tpos;

	Vec3 vel = dyn.v;
	Vec3 acc = dyn.a;
	float a = acc.len();

	if(a < 0.01f)
		a = 0.f;
	else
		acc /= a;

	Vec3 vpos = GetWeaponPos();
	Vec3 dist = tpos-vpos;
	float d = dist.len();

	if(d < 0.01f)
		return tpos;

	dist /= d;
	float d_speed = vel*dist;

	float speed = 800.0f;
	const SAmmoParams *ammo = g_pGame->GetWeaponSystem()->GetAmmoParams(GetFireMode(0)->GetAmmoType());

	if(!ammo)
		return tpos;

	if(ammo->physicalizationType == ePT_None)
		return tpos;

	speed = ammo->speed;

	float time_to = d/max(1.f, speed-d_speed);

	// MR: clamped acc prediction to reduce jerkyness when targetting objects that are able
	// to do near-instant velocity changes (like players)
	a = min(a, 25.f);

	Vec3 delta = vel*(time_to) + 0.5f*a*acc*time_to*time_to;
	delta *= m_turretparams.prediction;

	if(g_pGameCVars->i_debug_turrets == eGTD_Prediction)
	{
		IPersistantDebug *pDebug = gEnv->pGame->GetIGameFramework()->GetIPersistantDebug();
		pDebug->Begin("CGunTurret::PredictTargetPos", false);
		pDebug->AddSphere(tpos+delta, 0.2f, ColorF(1,0,0,1), 1.f);
		gEnv->pRenderer->DrawLabel(vpos, 1.4f, "Predict %s: speed %.1f (dspeed %.1f), acc %.1f, time %.1f", pTarget->GetName(), vel.len(), d_speed, a, time_to);
	}

	return tpos+delta;
}
Beispiel #19
0
void CNetPlayerInput::DoSetState(const SSerializedPlayerInput& input )
{
	// PLAYERPREDICTION
	m_newInterpolation |= (input.position != m_curInput.position) || (input.deltaMovement != m_curInput.deltaMovement);

	m_curInput = input;
	CHANGED_NETWORK_STATE(m_pPlayer,  IPlayerInput::INPUT_ASPECT );

	// not having these set seems to stop a remote avatars rotation being reflected
	m_curInput.aiming = true;
	m_curInput.allowStrafing = true;
	m_curInput.usinglookik = true;
	// ~PLAYERPREDICTION

	IAIActor* pAIActor = CastToIAIActorSafe(m_pPlayer->GetEntity()->GetAI());
	if (pAIActor)
		pAIActor->GetState().bodystate=input.bodystate;

	CMovementRequest moveRequest;
	moveRequest.SetStance( (EStance)m_curInput.stance );

	if(IsDemoPlayback())
	{
		Vec3 localVDir(m_pPlayer->GetViewQuatFinal().GetInverted() * m_curInput.lookDirection);
		Ang3 deltaAngles(asinf(localVDir.z),0,cry_atan2f(-localVDir.x,localVDir.y));
		moveRequest.AddDeltaRotation(deltaAngles*gEnv->pTimer->GetFrameTime());
	}
	{
		if (m_curInput.usinglookik)
			moveRequest.SetLookTarget( m_pPlayer->GetEntity()->GetWorldPos() + 10.0f * m_curInput.lookDirection );
		else
			moveRequest.ClearLookTarget();
		if (m_curInput.aiming)
			moveRequest.SetAimTarget(moveRequest.GetLookTarget());
		else
			moveRequest.ClearAimTarget();
	}
/*
	float pseudoSpeed = 0.0f; 
	if (m_curInput.deltaMovement.len2() > 0.0f)
	{
		pseudoSpeed = m_pPlayer->CalculatePseudoSpeed(m_curInput.sprint);
	}
	*/
	// PLAYERPREDICTION
	moveRequest.SetPseudoSpeed(CalculatePseudoSpeed());
	// ~PLAYERPREDICTION
	moveRequest.SetAllowStrafing(input.allowStrafing);

	float lean=0.0f;
	if (m_curInput.leanl)
		lean-=1.0f;
	if (m_curInput.leanr)
		lean+=1.0f;
	moveRequest.SetLean(lean);

	m_pPlayer->GetMovementController()->RequestMovement(moveRequest);

	IAnimationGraphState *pState=0;
	if (m_pPlayer->GetAnimatedCharacter())
		pState=m_pPlayer->GetAnimatedCharacter()->GetAnimationGraphState();
		
// PLAYERPREDICTION
	if (pState)
	{
		pState->SetInput(m_pPlayer->m_inputAiming, m_curInput.aiming);
		pState->SetInput(m_pPlayer->m_inputUsingLookIK, m_curInput.usinglookik);
	}

#if !defined(_RELEASE)
	// debug..
	if (g_pGameCVars->g_debugNetPlayerInput & 1)
	{
		IPersistantDebug * pPD = gEnv->pGame->GetIGameFramework()->GetIPersistantDebug();
		pPD->Begin( string("net_player_input_") + m_pPlayer->GetEntity()->GetName(), true );
		pPD->AddSphere( moveRequest.GetLookTarget(), 0.5f, ColorF(1,0,1,1), 1.0f );
		//			pPD->AddSphere( moveRequest.GetMoveTarget(), 0.5f, ColorF(1,1,0,1), 1.0f );

		Vec3 wp(m_pPlayer->GetEntity()->GetWorldPos() + Vec3(0,0,2));
		pPD->AddDirection( wp, 1.5f, m_curInput.deltaMovement, ColorF(1,0,0,1), 1.0f );
		pPD->AddDirection( wp, 1.5f, m_curInput.lookDirection, ColorF(0,1,0,1), 1.0f );
	}
#endif
// ~PLAYERPREDICTION
}
Beispiel #20
0
void CNetPlayerInput::UpdateMoveRequest()
{
	CMovementRequest moveRequest;
	SMovementState moveState;
	m_pPlayer->GetMovementController()->GetMovementState(moveState);
	Quat worldRot = m_pPlayer->GetBaseQuat(); // m_pPlayer->GetEntity()->GetWorldRotation();
	Vec3 deltaMovement = worldRot.GetInverted().GetNormalized() * m_curInput.deltaMovement;
	// absolutely ensure length is correct
	deltaMovement = deltaMovement.GetNormalizedSafe(ZERO) * m_curInput.deltaMovement.GetLength();
	moveRequest.AddDeltaMovement( deltaMovement );
	if( IsDemoPlayback() )
	{
		Vec3 localVDir(m_pPlayer->GetViewQuatFinal().GetInverted() * m_curInput.lookDirection);
		Ang3 deltaAngles(asinf(localVDir.z),0,cry_atan2f(-localVDir.x,localVDir.y));
		moveRequest.AddDeltaRotation(deltaAngles*gEnv->pTimer->GetFrameTime());
	}
	//else
	{
		//--- Vector slerp actually produces QNans if the vectors are exactly opposite, in that case snap to the target
		if (m_lookDir.Dot(m_curInput.lookDirection) < (float)-0.99f)
		{
			m_lookDir = m_curInput.lookDirection;
		}
		else
		{
			m_lookDir.SetSlerp(m_lookDir, m_curInput.lookDirection, g_pGameCVars->pl_netAimLerpFactor);
		}

		Vec3 distantTarget = moveState.eyePosition + 1000.0f * m_lookDir;
		Vec3 lookTarget = distantTarget;

		if (m_curInput.usinglookik)
			moveRequest.SetLookTarget( lookTarget );
		else
			moveRequest.ClearLookTarget();

		if (m_curInput.aiming)
			moveRequest.SetAimTarget( lookTarget );
		else
			moveRequest.ClearAimTarget();

		if (m_curInput.deltaMovement.GetLengthSquared() > sqr(0.02f)) // 0.2f is almost stopped
			moveRequest.SetBodyTarget( distantTarget );
		else
			moveRequest.ClearBodyTarget();
	}

	moveRequest.SetAllowStrafing(m_curInput.allowStrafing);

	if(m_pPlayer->IsPlayer())
		moveRequest.SetPseudoSpeed(CalculatePseudoSpeed());
	else
		moveRequest.SetPseudoSpeed(m_curInput.pseudoSpeed);

	float lean=0.0f;
	if (m_curInput.leanl)
		lean-=1.0f;
	if (m_curInput.leanr)
		lean+=1.0f;

	if (fabsf(lean)>0.01f)
		moveRequest.SetLean(lean);
	else
		moveRequest.ClearLean();

	moveRequest.SetStance( (EStance)m_curInput.stance );

	m_pPlayer->GetMovementController()->RequestMovement(moveRequest);

	if (m_curInput.sprint)
		m_pPlayer->m_actions |= ACTION_SPRINT;
	else
		m_pPlayer->m_actions &= ~ACTION_SPRINT;

	if (m_curInput.leanl)
		m_pPlayer->m_actions |= ACTION_LEANLEFT;
	else
		m_pPlayer->m_actions &= ~ACTION_LEANLEFT;

	if (m_curInput.leanr)
		m_pPlayer->m_actions |= ACTION_LEANRIGHT;
	else
		m_pPlayer->m_actions &= ~ACTION_LEANRIGHT;

#if !defined(_RELEASE)
	// debug..
	if (g_pGameCVars->g_debugNetPlayerInput & 2)
	{
		IPersistantDebug * pPD = gEnv->pGame->GetIGameFramework()->GetIPersistantDebug();
		pPD->Begin( string("update_player_input_") + m_pPlayer->GetEntity()->GetName(), true );
		Vec3 wp = m_pPlayer->GetEntity()->GetWorldPos();
		wp.z += 2.0f;
		pPD->AddSphere( moveRequest.GetLookTarget(), 0.5f, ColorF(1,0,1,0.3f), 1.0f );
		//		pPD->AddSphere( moveRequest.GetMoveTarget(), 0.5f, ColorF(1,1,0,0.3f), 1.0f );
		pPD->AddDirection( m_pPlayer->GetEntity()->GetWorldPos() + Vec3(0,0,2), 1, m_curInput.deltaMovement, ColorF(1,0,0,0.3f), 1.0f );
	}
#endif

	//m_curInput.deltaMovement.zero();
}
Beispiel #21
0
void CNetPlayerInput::PreUpdate()
{
	IPhysicalEntity * pPhysEnt = m_pPlayer->GetEntity()->GetPhysics();
	if (!pPhysEnt)
		return;

	CMovementRequest moveRequest;
	SMovementState moveState;
	m_pPlayer->GetMovementController()->GetMovementState(moveState);
	Quat worldRot = m_pPlayer->GetBaseQuat(); // m_pPlayer->GetEntity()->GetWorldRotation();
	Vec3 deltaMovement = worldRot.GetInverted().GetNormalized() * m_curInput.deltaMovement;
	// absolutely ensure length is correct
	deltaMovement = deltaMovement.GetNormalizedSafe(ZERO) * m_curInput.deltaMovement.GetLength();
	moveRequest.AddDeltaMovement( deltaMovement );
	if( IsDemoPlayback() )
	{
		Vec3 localVDir(m_pPlayer->GetViewQuatFinal().GetInverted() * m_curInput.lookDirection);
		Ang3 deltaAngles(asin(localVDir.z),0,cry_atan2f(-localVDir.x,localVDir.y));
		moveRequest.AddDeltaRotation(deltaAngles*gEnv->pTimer->GetFrameTime());
	}
	//else
	{
		Vec3 distantTarget = moveState.eyePosition + 1000.0f * m_curInput.lookDirection;
		Vec3 lookTarget = distantTarget;
		if (gEnv->bClient && m_pPlayer->GetGameObject()->IsProbablyVisible())
		{
			// post-process aim direction	
			ray_hit hit;
			static const int obj_types = ent_all; // ent_terrain|ent_static|ent_rigid|ent_sleeping_rigid|ent_living;
			static const unsigned int flags = rwi_stop_at_pierceable|rwi_colltype_any;
			bool rayHitAny = 0 != gEnv->pPhysicalWorld->RayWorldIntersection( moveState.eyePosition, 150.0f * m_curInput.lookDirection, obj_types, flags, &hit, 1, pPhysEnt );
			if (rayHitAny)
			{
				lookTarget = hit.pt;
			}

			static float proneDist = 1.0f;
			static float crouchDist = 0.6f;
			static float standDist = 0.3f;

			float dist = standDist;
			if(m_pPlayer->GetStance() == STANCE_CROUCH)
				dist = crouchDist;
			else if(m_pPlayer->GetStance() == STANCE_PRONE)
				dist = proneDist;

			if((lookTarget - moveState.eyePosition).GetLength2D() < dist)
			{
				Vec3 eyeToTarget2d = lookTarget - moveState.eyePosition;
				eyeToTarget2d.z = 0.0f;
				eyeToTarget2d.NormalizeSafe();
				eyeToTarget2d *= dist;
				ray_hit newhit;
				bool rayHitAny = 0 != gEnv->pPhysicalWorld->RayWorldIntersection( moveState.eyePosition + eyeToTarget2d, 3 * Vec3(0,0,-1), obj_types, flags, &newhit, 1, pPhysEnt );
				if (rayHitAny)
				{
					lookTarget = newhit.pt;
				}
			}

			// SNH: new approach. Make sure the aimTarget is at least 1.5m away,
			//	if not, pick a point 1m down the vector instead.
			Vec3 dir = lookTarget - moveState.eyePosition;
			static float minDist = 1.5f;
			if(dir.GetLengthSquared() < minDist)
			{
				lookTarget = moveState.eyePosition + dir.GetNormalizedSafe();
			}

			// draw eye pos for comparison
			//gEnv->pRenderer->GetIRenderAuxGeom()->DrawSphere(moveState.eyePosition, 0.04f, ColorF(0.3f,0.2f,0.7f,1.0f));
		}

		moveRequest.SetLookTarget( lookTarget );
		moveRequest.SetAimTarget( lookTarget );
		if (m_curInput.deltaMovement.GetLengthSquared() > sqr(0.2f)) // 0.2f is almost stopped
			moveRequest.SetBodyTarget( distantTarget );
		else
			moveRequest.ClearBodyTarget();
	}
	moveRequest.SetAllowStrafing(true);

	float pseudoSpeed = 0.0f;
	if (m_curInput.deltaMovement.len2() > 0.0f)
	{
		pseudoSpeed = m_pPlayer->CalculatePseudoSpeed(m_curInput.sprint);
	}
	moveRequest.SetPseudoSpeed(pseudoSpeed);

	float lean=0.0f;
	if (m_curInput.leanl)
		lean-=1.0f;
	if (m_curInput.leanr)
		lean+=1.0f;

	if (fabsf(lean)>0.01f)
		moveRequest.SetLean(lean);
	else
		moveRequest.ClearLean();

	m_pPlayer->GetMovementController()->RequestMovement(moveRequest);

	if (m_curInput.sprint)
		m_pPlayer->m_actions |= ACTION_SPRINT;
	else
		m_pPlayer->m_actions &= ~ACTION_SPRINT;

	if (m_curInput.leanl)
		m_pPlayer->m_actions |= ACTION_LEANLEFT;
	else
		m_pPlayer->m_actions &= ~ACTION_LEANLEFT;

	if (m_curInput.leanr)
		m_pPlayer->m_actions |= ACTION_LEANRIGHT;
	else
		m_pPlayer->m_actions &= ~ACTION_LEANRIGHT;

	// debug..
	if (g_pGameCVars->g_debugNetPlayerInput & 2)
	{
		IPersistantDebug * pPD = gEnv->pGame->GetIGameFramework()->GetIPersistantDebug();
		pPD->Begin( string("update_player_input_") + m_pPlayer->GetEntity()->GetName(), true );
		Vec3 wp = m_pPlayer->GetEntity()->GetWorldPos();
		wp.z += 2.0f;
		pPD->AddSphere( moveRequest.GetLookTarget(), 0.5f, ColorF(1,0,1,0.3f), 1.0f );
		//		pPD->AddSphere( moveRequest.GetMoveTarget(), 0.5f, ColorF(1,1,0,0.3f), 1.0f );
		pPD->AddDirection( m_pPlayer->GetEntity()->GetWorldPos() + Vec3(0,0,2), 1, m_curInput.deltaMovement, ColorF(1,0,0,0.3f), 1.0f );
	}

	//m_curInput.deltaMovement.zero();
}
// ============================================================================
//	Render debug information.
//
//	In,out:		The debug renderer.
//
void HazardDataSphere::DebugRender (IPersistantDebug& debugRenderer) const
{
	debugRenderer.AddSphere(m_Context.m_CenterPos, m_Context.m_Radius, 
		HazardModule::debugColor, HazardModule::debugPrimitiveFadeDelay);
}
Beispiel #23
0
void CNetPlayerInput::UpdateMoveRequest()
{
	CMovementRequest moveRequest;
	SMovementState moveState;
	m_pPlayer->GetMovementController()->GetMovementState(moveState);
	Quat worldRot = m_pPlayer->GetBaseQuat(); // m_pPlayer->GetEntity()->GetWorldRotation();
	Vec3 deltaMovement = worldRot.GetInverted().GetNormalized() * m_curInput.deltaMovement;
	// absolutely ensure length is correct
	deltaMovement = deltaMovement.GetNormalizedSafe(ZERO) * m_curInput.deltaMovement.GetLength();
	moveRequest.AddDeltaMovement( deltaMovement );
	if( IsDemoPlayback() )
	{
		Vec3 localVDir(m_pPlayer->GetViewQuatFinal().GetInverted() * m_curInput.lookDirection);
		Ang3 deltaAngles(asinf(localVDir.z),0,atan2_tpl(-localVDir.x,localVDir.y));
		moveRequest.AddDeltaRotation(deltaAngles*gEnv->pTimer->GetFrameTime());
	}
	
	const float fNetAimLerpFactor = g_pGameCVars->pl_netAimLerpFactor;

	//Vector slerp produces artifacts here, using a per-component lerp instead
	Vec3 vCurrentRight			= m_lookDir.cross(Vec3Constants<float>::fVec3_OneZ);
	Vec3 vCurrentProjected = -(vCurrentRight.cross(Vec3Constants<float>::fVec3_OneZ));
	vCurrentRight.Normalize();
	vCurrentProjected.Normalize();

	Vec3 vNewRight					= m_curInput.lookDirection.cross(Vec3Constants<float>::fVec3_OneZ);
	Vec3 vNewProjected			= -(vNewRight.cross(Vec3Constants<float>::fVec3_OneZ));
	vNewProjected.Normalize();

	float fRotZDirDot	= vNewProjected.dot(vCurrentRight);
	float fRotZDot		= vNewProjected.dot(vCurrentProjected);
	float fRotZ				= acos_tpl(fRotZDot);

	fRotZ = AngleWrap_PI(fRotZ);

	float fRotZFinal	= -fsgnf(fRotZDirDot) * fRotZ * fNetAimLerpFactor;

	float fCurrentAngle = acos_tpl(Vec3Constants<float>::fVec3_OneZ.dot(m_lookDir));
	float fNewAngle			= acos_tpl(Vec3Constants<float>::fVec3_OneZ.dot(m_curInput.lookDirection));

	float fRotXFinal = (fNewAngle - fCurrentAngle) * -fNetAimLerpFactor;

	//Rotate around X first, as we have already generated the right vector
	Vec3 vNewLookDir = m_lookDir.GetRotated(vCurrentRight, fRotXFinal);

	m_lookDir = vNewLookDir.GetRotated(Vec3Constants<float>::fVec3_OneZ, fRotZFinal);

	Vec3 distantTarget = moveState.eyePosition + 1000.0f * m_lookDir;
	Vec3 lookTarget = distantTarget;

	if (m_curInput.usinglookik)
		moveRequest.SetLookTarget( lookTarget );
	else
		moveRequest.ClearLookTarget();

	if (m_curInput.aiming)
		moveRequest.SetAimTarget( lookTarget );
	else
		moveRequest.ClearAimTarget();

	if (m_curInput.deltaMovement.GetLengthSquared() > sqr(0.02f)) // 0.2f is almost stopped
		moveRequest.SetBodyTarget( distantTarget );
	else
		moveRequest.ClearBodyTarget();

	moveRequest.SetAllowStrafing(m_curInput.allowStrafing);

	moveRequest.SetPseudoSpeed(CalculatePseudoSpeed());

	moveRequest.SetStance( (EStance)m_curInput.stance );

	m_pPlayer->GetMovementController()->RequestMovement(moveRequest);

	if (m_curInput.sprint)
		m_pPlayer->m_actions |= ACTION_SPRINT;
	else
		m_pPlayer->m_actions &= ~ACTION_SPRINT;

#if 0
	if (m_pPlayer->m_netSetPosition)
	{
		SPredictedCharacterStates charStates;
		charStates.states[0].position		 = m_pPlayer->GetEntity()->GetPos();
		charStates.states[0].orientation = m_pPlayer->GetEntity()->GetRotation();
		charStates.states[0].deltatime	 = 0.0f;

		charStates.states[1].position		 = m_pPlayer->m_netCurrentLocation;
		charStates.states[1].orientation = m_pPlayer->GetEntity()->GetRotation();
		charStates.states[1].deltatime	 = gEnv->pTimer->GetFrameTime();

		charStates.states[2].position		 = m_pPlayer->m_netDesiredLocation;
		charStates.states[2].orientation = m_pPlayer->GetEntity()->GetRotation();
		charStates.states[2].deltatime	 = m_pPlayer->m_netLerpTime;
		charStates.nStates = 3;

		moveRequest.SetPrediction(charStates);
	}
#endif //0

#if !defined(_RELEASE)
	// debug..
	if (g_pGameCVars->g_debugNetPlayerInput & 2)
	{
		IPersistantDebug * pPD = gEnv->pGame->GetIGameFramework()->GetIPersistantDebug();
		pPD->Begin( string("update_player_input_") + m_pPlayer->GetEntity()->GetName(), true );
		Vec3 wp = m_pPlayer->GetEntity()->GetWorldPos();
		wp.z += 2.0f;
		pPD->AddSphere( moveRequest.GetLookTarget(), 0.5f, ColorF(1,0,1,0.3f), 1.0f );
		//		pPD->AddSphere( moveRequest.GetMoveTarget(), 0.5f, ColorF(1,1,0,0.3f), 1.0f );
		pPD->AddDirection( m_pPlayer->GetEntity()->GetWorldPos() + Vec3(0,0,2), 1, m_curInput.deltaMovement, ColorF(1,0,0,0.3f), 1.0f );
	}
#endif

	//m_curInput.deltaMovement.zero();
} 
Beispiel #24
0
	bool operator() (const SSpectacularKillAnimation& killAnim) const
	{
		const SSpectacularKillCVars& skCVars = g_pGameCVars->g_spectacularKill;
		const CActor* pOwner = m_spectacularKill.m_pOwner;

		// 0. the anim shouldn't be redundant
		if (((gEnv->pTimer->GetFrameStartTime().GetSeconds() - s_lastKillInfo.timeStamp) <= skCVars.minTimeBetweenSameKills) &&
			(killAnim.killerAnimation.compare(s_lastKillInfo.killerAnim)))
		{
			SK_DEBUG_LOG("GetValidAnim - %s is not valid: This animation was last played %.1f ago, a minimum time of %.1f is required", 
				killAnim.killerAnimation.c_str(), (gEnv->pTimer->GetFrameStartTime().GetSeconds() - s_lastKillInfo.timeStamp), skCVars.minTimeBetweenSameKills);

			return true;
		}


		// 1. the killer needs to be within a certain distance from the target
		IEntity* pTargetEntity = m_pTarget->GetEntity();
		IEntity* pKillerEntity = pOwner->GetEntity();

		const QuatT& killerTransform = pOwner->GetAnimatedCharacter()->GetAnimLocation();
		const QuatT& targetTransform = m_pTarget->GetAnimatedCharacter()->GetAnimLocation();
		const Vec3& vKillerPos = killerTransform.t;
		const Vec3& vTargetPos = targetTransform.t;

		Vec2 vKillerToTarget = Vec2(vTargetPos) - Vec2(vKillerPos);
		float distance = vKillerToTarget.GetLength();

		const float optimalDistance = killAnim.optimalDist;
		if ((optimalDistance > 0.0f) && (fabs_tpl(distance - optimalDistance) > skCVars.maxDistanceError))
		{
#ifndef _RELEASE
			if (g_pGameCVars->g_spectacularKill.debug > 1)
			{
				// visually shows why it failed
				IPersistantDebug* pPersistantDebug = m_spectacularKill.BeginPersistantDebug();
				const float fConeHeight = killAnim.optimalDist + skCVars.maxDistanceError;
				pPersistantDebug->AddPlanarDisc(vTargetPos, killAnim.optimalDist - skCVars.maxDistanceError, killAnim.optimalDist + skCVars.maxDistanceError, Col_Coral, 6.0f);
				pPersistantDebug->AddLine(vKillerPos, vKillerPos + Vec3(0.f, 0.f, 5.0f), Col_Red, 6.f);
			}

			SK_DEBUG_LOG("GetValidAnim - %s is not valid: Distance between actors should be %.2f, is %.2f (max error is %f)", 
				killAnim.killerAnimation.c_str(), optimalDistance, distance, skCVars.maxDistanceError);
#endif

			return true;
		}


		// 2. The killer needs to be facing the target within cosLookToConeHalfAngleRadians angle
		Vec2 vKillerDir(killerTransform.GetColumn1()); // In decoupled catchup mode we need the animated character's orientation
		vKillerDir.Normalize();
		if (vKillerToTarget.GetNormalizedSafe().Dot(vKillerDir) <= skCVars.minKillerToTargetDotProduct)
		{
			SK_DEBUG_LOG("GetValidAnim - %s is not valid: Killer is not looking within %.2f degrees towards the target", 
				killAnim.killerAnimation.c_str(), RAD2DEG(acos_tpl(skCVars.minKillerToTargetDotProduct) * 2.0f));

			return true;
		}


		// 3. If specified, the killer needs to be within a certain angle range from a given reference orientation from the target
		// e.g. Specifying referenceAngle 180 means using the back of the target as the center of the angle range 
		// (imagine it as a cone) where the killer has to be for the kill to be valid
		if (killAnim.targetToKillerAngle >= 0.f)
		{
			const float referenceAngle = killAnim.targetToKillerAngle;

			// Find the reference vector which will be the center of the allowed angle range
			Vec2 vTargetDir(targetTransform.GetColumn1());
			vTargetDir.Normalize();

			// 2D rotation
			Vec2 vReferenceDir((vTargetDir.x * cosf(referenceAngle)) - (vTargetDir.y * sinf(referenceAngle)), 
				(vTargetDir.y * cosf(referenceAngle)) + (vTargetDir.x * sinf(referenceAngle)));

			if (vKillerToTarget.GetNormalizedSafe().Dot(-vReferenceDir) <= killAnim.targetToKillerMinDot)
			{
#ifndef _RELEASE
				if (g_pGameCVars->g_spectacularKill.debug > 1)
				{
					// visually shows why it failed
					IPersistantDebug* pPersistantDebug = m_spectacularKill.BeginPersistantDebug();
					const float fConeHeight = killAnim.optimalDist + skCVars.maxDistanceError;
					pPersistantDebug->AddCone(vTargetPos + (vReferenceDir * fConeHeight), -vReferenceDir, killAnim.targetToKillerMinDot * fConeHeight * 2.0f, fConeHeight, Col_Coral, 6.f);
					pPersistantDebug->AddLine(vKillerPos, vKillerPos + Vec3(0.f, 0.f, 5.0f), Col_Red, 6.f);
				}

				float targetToKillerDot = vTargetDir.GetNormalizedSafe().Dot(-vKillerToTarget);
				SK_DEBUG_LOG("GetValidAnim - %s is not valid: Killer is not within a %.2f degrees cone centered on the target's %.2f degrees. Killer is at %.2f angles respect the target", 
					killAnim.killerAnimation.c_str(), RAD2DEG(acos_tpl(killAnim.targetToKillerMinDot) * 2.0f), RAD2DEG(killAnim.targetToKillerAngle), RAD2DEG(acos_tpl(targetToKillerDot)));
#endif

				return true;
			}
		}

		SK_DEBUG_LOG("GetValidAnim - %s is valid", killAnim.killerAnimation.c_str());
		return false;
	}
//------------------------------------------------------------------------
float CGameRulesCommonDamageHandling::GetCollisionEnergy( const IEntity *pVictim, const CGameRules::SCollisionHitInfo& colHitInfo ) const
{
	float m1 = colHitInfo.target_mass;
	float m0 = 0.f;

	IPhysicalEntity *phys = pVictim->GetPhysics();
	if(phys)
	{
		pe_status_dynamics	dyn;
		phys->GetStatus(&dyn);
		m0 = dyn.mass;
	}

	IEntity *pOffender = gEnv->pEntitySystem->GetEntity(colHitInfo.targetId);
	bool bCollider = (pOffender || m1 > 0.001f);

	const bool debugColl = DebugCollisions();
	if (debugColl)
	{
		CryLog("GetCollisionEnergy %s (%.1f) <-> %s (%.1f)", pVictim?pVictim->GetName():"[no entity]", m0, pOffender?pOffender->GetName():"[no entity]", m1);
	}

	float v0Sq = 0.f, v1Sq = 0.f;

	if (bCollider)	// non-static
	{
		m0 = min(m0, m1);

		Vec3 v0normal, v1normal, vrel;
		Vec3 tempNormal = colHitInfo.normal;

		float v0dotN = colHitInfo.velocity.dot(colHitInfo.normal);
		v0normal = tempNormal.scale(v0dotN);

		float v1dotN = colHitInfo.target_velocity.dot(colHitInfo.normal);;  // "target" is the offender
		v1normal = tempNormal.scale(v1dotN);

		vrel = v0normal.sub(v1normal);
		float vrelSq = vrel.len2();

		v0Sq = min( sqr(v0dotN), vrelSq );
		v1Sq = min( sqr(v1dotN), vrelSq );

		if (debugColl)
		{
			IPersistantDebug* pPD = g_pGame->GetIGameFramework()->GetIPersistantDebug();

			pPD->Begin("CollDamage", false);
			pPD->AddSphere(colHitInfo.pos, 0.15f, Col_Red, 5.f);
			pPD->AddDirection(colHitInfo.pos, 1.5f, tempNormal.scale(sgn(v0dotN)), Col_Green, 5.f);
			pPD->AddDirection(colHitInfo.pos, 1.5f, tempNormal.scale(sgn(v1dotN)), Col_Red, 5.f);

			if ((v0Sq > 2*2) || (v1Sq > 2*2))
			{
				CryLog("normal velocities: rel %.1f, <%s> %.1f / <%s> %.1f", sqrt(vrelSq), pVictim?pVictim->GetName():"none", v0dotN, pOffender?pOffender->GetName():"none", v1dotN); 
				CryLog("target_type: %i, target_velocity: %.2f %.2f %.2f", colHitInfo.target_type, colHitInfo.target_velocity.x, colHitInfo.target_velocity.y, colHitInfo.target_velocity.z);
			}
		}
	}
	else
	{
		v0Sq = sqr(colHitInfo.velocity.dot(colHitInfo.normal));

		if (debugColl && v0Sq>5*5)
		{
			IPersistantDebug* pPD = g_pGame->GetIGameFramework()->GetIPersistantDebug();

			pPD->Begin("CollDamage", false);
			pPD->AddDirection(colHitInfo.pos, 1.5f, colHitInfo.normal, Col_Green, 5.f);
			string debugText;
			debugText.Format("z: %f", colHitInfo.velocity.z);
			pPD->Add2DText(debugText.c_str(), 1.5f, Col_White, 5.f);
		}
	}

	float colliderEnergyScale = 1.f;
	if (pVictim != NULL && pOffender != NULL)
	{
		if(IActor* pVictimActor = g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(pVictim->GetId()))
		{
			colliderEnergyScale = !pVictimActor->IsPlayer() ?	GetAIPlayerAgainstColliderEnergyScale(*pOffender) :
																GetPlayerAgainstColliderEnergyScale(*pOffender);
			
			if (debugColl)
			{
				CryLog("colliderEnergyScale: %.1f", colliderEnergyScale);
			}
		}
	}

	const float energy0 = 0.5f * m0 * v0Sq;
	const float energy1 = 0.5f * m1 * v1Sq * colliderEnergyScale;

	return energy0 + energy1;
}