bool CProceduralContextTurretAimPose::InitialiseCharacter( const int characterSlot )
{
	if ( m_entity == NULL )
	{
		return false;
	}

	ICharacterInstance* pCharacterInstance = m_entity->GetCharacter( characterSlot );
	if ( pCharacterInstance == NULL )
	{
		return false;
	}

	ISkeletonAnim* pSkeletonAnim = pCharacterInstance->GetISkeletonAnim();
	if ( pSkeletonAnim == NULL )
	{
		return false;
	}

	ISkeletonPose* pSkeletonPose = pCharacterInstance->GetISkeletonPose();
	if ( pSkeletonPose == NULL )
	{
		return false;
	}
	ICharacterModelSkeleton* pICharacterModelSkeleton = pCharacterInstance->GetICharacterModel()->GetICharacterModelSkeleton();

	m_pCharacterInstance = pCharacterInstance;
	m_pSkeletonAnim = pSkeletonAnim;
	m_pSkeletonPose = pSkeletonPose;
	m_pICharacterModelSkeleton = pICharacterModelSkeleton;

	return true;
}
Пример #2
0
//------------------------------------------------------------------------
const Matrix33 &CItem::GetSlotHelperRotation(int slot, const char *helper, bool worldSpace, bool relative)
{
	static Matrix33 rotation;
	rotation.SetIdentity();

	IEntity* pEntity = GetEntity();
	if(!pEntity)
		return rotation;

	SEntitySlotInfo info;
	if (pEntity->GetSlotInfo(slot, info))
	{
    if (info.pStatObj)
    {
      IStatObj *pStatObj = info.pStatObj;
      rotation = Matrix33(pStatObj->GetHelperTM(helper));
      rotation.OrthonormalizeFast();
      rotation = Matrix33(GetEntity()->GetSlotLocalTM(slot, false))*rotation;        
    }
		else if (info.pCharacter)
		{
			ICharacterInstance *pCharacter = info.pCharacter;
			if(!pCharacter)
				return rotation;

			IAttachment* pAttachment = pCharacter->GetIAttachmentManager()->GetInterfaceByName(helper);
			if(pAttachment)
			{
				rotation = Matrix33(worldSpace ? pAttachment->GetAttWorldAbsolute().q : pAttachment->GetAttModelRelative().q);
				return rotation;
			}
			else
			{
				ICharacterModelSkeleton* pICharacterModelSkeleton = pCharacter->GetICharacterModel()->GetICharacterModelSkeleton();
				ISkeletonPose* pSkeletonPose = pCharacter->GetISkeletonPose();
				int16 id = pICharacterModelSkeleton->GetJointIDByName(helper);
				if (id > -1)
				{
					rotation = relative ? Matrix33(pSkeletonPose->GetRelJointByID(id).q) : Matrix33(pSkeletonPose->GetAbsJointByID(id).q);
				}
			}

			if (!relative)
			{
				rotation = Matrix33(pEntity->GetSlotLocalTM(slot, false)) * rotation;
			}
		}    
	}

	if (worldSpace)
	{
		rotation = Matrix33(pEntity->GetWorldTM()) * rotation;
	}

	return rotation;
}
void CFlowConvoyNode::DiscoverConvoyCoaches(IEntity *pEntity)
{
	m_coaches.resize(0);

	while (pEntity)
	{
		SConvoyCoach tc;

		ICharacterInstance *pCharacterInstance = pEntity->GetCharacter(0);
		ISkeletonPose *pSkeletonPose = pCharacterInstance ? pCharacterInstance->GetISkeletonPose() : NULL;
		ICharacterModelSkeleton* pICharacterModelSkeleton = pCharacterInstance ? pCharacterInstance->GetICharacterModel()->GetICharacterModelSkeleton() : NULL;
		IPhysicalEntity* pPhysics = pEntity->GetPhysics();
		if(!pPhysics) 
		{
			// don't need physics here, but need it later, so don't use entity if it's not physicalized
			GameWarning("Convoy entity [%s] is not physicalized", pEntity->GetName());
			break;
		}

		AABB bbox;
		pEntity->GetLocalBounds(bbox);

		//tc.m_coachOffset = (bbox.max.y - bbox.min.y) * .5f;
		tc.m_coachOffset = 10.0f;

		tc.m_frontWheelBase = pICharacterModelSkeleton ? pICharacterModelSkeleton->GetJointIDByName("wheel_base1") : -1;
		tc.m_backWheelBase = pICharacterModelSkeleton ? pICharacterModelSkeleton->GetJointIDByName("wheel_base2") : -1;
		
		if (tc.m_frontWheelBase >=0 && tc.m_backWheelBase >= 0)
		{
			QuatT qt1 = pSkeletonPose->GetRelJointByID(tc.m_frontWheelBase);
			QuatT qt2 = pSkeletonPose->GetRelJointByID(tc.m_backWheelBase);
			tc.m_wheelDistance = qt1.t.GetDistance(qt2.t) * .5f;
		}
		else
		{
			// Fallback for entities that don't have wheel_base joints
			if ( m_bXAxisFwd )
				tc.m_wheelDistance = (bbox.max.x - bbox.min.x) * .5f;
			else
				tc.m_wheelDistance = (bbox.max.y - bbox.min.y) * .5f;
		}

		tc.m_pEntity = pEntity;
  //  pEntity->SetConvoyEntity();
		//for (int i = 0; i < pEntity->GetChildCount(); i++)
		//	pEntity->GetChild(i)->SetConvoyEntity();

		//tc.m_pEntitySoundsProxy = (IEntitySoundProxy*) tc.m_pEntity->CreateProxy(ENTITY_PROXY_SOUND);
		//assert(tc.m_pEntitySoundsProxy);

		m_coaches.push_back(tc);
		IEntityLink *pEntityLink = pEntity->GetEntityLinks();
		pEntity = pEntityLink ? gEnv->pEntitySystem->GetEntity(pEntityLink->entityId) : NULL;
	}
}
Пример #4
0
//------------------------------------------------------------------------
const char *CItem::GetCharacterAttachmentBone(int slot, const char *name)
{
	ICharacterInstance *pCharacter = GetEntity()->GetCharacter(slot);
	if(IAttachment * pAttachment = GetCharacterAttachment(pCharacter, name))
	{
		return pCharacter->GetICharacterModel()->GetICharacterModelSkeleton()->GetJointNameByID(pAttachment->GetJointID());
	}
	
	return NULL;
}
void CProceduralWeaponAnimationContext::Initialize(IScope* pScope)
{
	++m_instanceCount;

	if (m_pScope != 0)
		return;

	m_pScope = pScope;
	ICharacterInstance* pCharacter = m_pScope->GetCharInst();
	if (pCharacter)
	{
		CryCreateClassInstance("AnimationPoseModifier_OperatorQueue", m_pPoseModifier);
		m_params = SParams(pCharacter->GetICharacterModel()->GetICharacterModelSkeleton());
	}
}
Пример #6
0
//------------------------------------------------------------------------
Vec3 CItem::GetSlotHelperPos(int slot, const char *helper, bool worldSpace, bool relative) const
{
	Vec3 position(0,0,0);

	SEntitySlotInfo info;
	if (GetEntity()->GetSlotInfo(slot, info))
	{
		if (info.pStatObj)
		{
			IStatObj *pStatsObj = info.pStatObj;
			position = pStatsObj->GetHelperPos(helper);
			position = GetEntity()->GetSlotLocalTM(slot, false).TransformPoint(position);
		}
		else if (info.pCharacter)
		{
			ICharacterInstance *pCharacter = info.pCharacter;
			IAttachment* pAttachment = pCharacter->GetIAttachmentManager()->GetInterfaceByName(helper);
			if (pAttachment)
			{
				position = worldSpace ? pAttachment->GetAttWorldAbsolute().t : pAttachment->GetAttModelRelative().t;
				return position;
			}
			else
			{
				ICharacterModelSkeleton* pICharacterModelSkeleton = pCharacter->GetICharacterModel()->GetICharacterModelSkeleton();
				ISkeletonPose* pSkeletonPose = pCharacter->GetISkeletonPose();
				int16 id = pICharacterModelSkeleton->GetJointIDByName(helper);
				if (id > -1)
				{
					position = relative ? pSkeletonPose->GetRelJointByID(id).t : pSkeletonPose->GetAbsJointByID(id).t;
				}
			}

			if (!relative)
			{
				position = GetEntity()->GetSlotLocalTM(slot, false).TransformPoint(position);
			}
		}
	}

	if (worldSpace)
	{
		position = GetWorldTM().TransformPoint(position);
	}

	return position;
}
void CLaserBeam::FixAttachment(IEntity* pLaserEntity)
{
	m_usingEntityAttachment = false;

	IItemSystem* pItemSystem = g_pGame->GetIGameFramework()->GetIItemSystem();
	CItem* pOwnerItem = static_cast<CItem*>(pItemSystem->GetItem(m_ownerEntityId));

	if (pOwnerItem)
	{
		IEntity* pOwnerEntity = pOwnerItem->GetEntity();
		IEntity* pAttachedEntity = pOwnerEntity;
		const char* attach_helper = "laser_term";

		Vec3 offset = pOwnerItem->GetSlotHelperPos(m_geometrySlot, attach_helper, false);

		if(m_geometrySlot == eIGS_FirstPerson)
		{
			if(pOwnerItem->IsAccessory())
			{
				EntityId parentId = pOwnerItem->GetParentId();

				if(parentId)
				{
					if(CItem* pParentItem = static_cast<CItem*>(pItemSystem->GetItem(parentId)))
					{
						const SAccessoryParams* pParams = pParentItem->GetAccessoryParams(pAttachedEntity->GetClass());

						attach_helper = pParams->attach_helper.c_str();
						pAttachedEntity = pParentItem->GetEntity();
					}
				}
			}

			if(pAttachedEntity)
			{
				ICharacterInstance *pCharacter = pAttachedEntity->GetCharacter(eIGS_FirstPerson);
				if (pCharacter)
				{
					IAttachmentManager *pAttachmentManager = pCharacter->GetIAttachmentManager();

					IAttachment *pLaserAttachment = pAttachmentManager->GetInterfaceByName(LASER_ATTACH_NAME);

					if(!pLaserAttachment)
					{
						IAttachment *pAttachment = pAttachmentManager->GetInterfaceByName(attach_helper);

						if(pAttachment)
						{
							const char* pBone = pCharacter->GetICharacterModel()->GetICharacterModelSkeleton()->GetJointNameByID(pAttachment->GetJointID());

							pLaserAttachment = pAttachmentManager->CreateAttachment(LASER_ATTACH_NAME, CA_BONE, pBone);

							if(pLaserAttachment)
							{
								QuatT relative = pAttachment->GetAttRelativeDefault();

								if(pOwnerItem->GetEntity() != pAttachedEntity)
								 {
									Matrix34 mtx(relative);
									relative.t = relative * offset;
								}

								pLaserAttachment->SetAttRelativeDefault(relative);
							}
						}
					}

					if(pLaserAttachment)
					{
						CEntityAttachment* pEntAttach = new CEntityAttachment;

						pEntAttach->SetEntityId(m_laserEntityId);
						pLaserAttachment->AddBinding(pEntAttach);
						pLaserAttachment->HideAttachment(0);

						m_usingEntityAttachment = true;
					}		
				}
			}
		}	

		if(!m_usingEntityAttachment && pOwnerEntity)
		{
			pOwnerEntity->AttachChild(pLaserEntity);
			pLaserEntity->SetLocalTM(Matrix34::CreateTranslationMat(offset));
		}
	}
}
//------------------------------------------------------------------------
void CReplayActor::ProcessEvent(SEntityEvent &event)
{
	switch (event.event)
	{
	case ENTITY_EVENT_PREPHYSICSUPDATE:
		{
			const int currentFrameId = gEnv->pRenderer->GetFrameID();
			if(currentFrameId==m_lastFrameUpdated)
				return;
			m_lastFrameUpdated = currentFrameId;

			if (m_pActionController)
			{
				float frameTime = gEnv->pTimer->GetFrameTime();
				m_pActionController->Update(frameTime);
			}

			ICharacterInstance* pShadowCharacter = GetShadowCharacter();
			if (pShadowCharacter)
			{
				QuatTS pose = (QuatTS)GetEntity()->GetWorldTM();
				SAnimationProcessParams params;
				params.locationAnimation = pose;
				params.bOnRender = 1;
				params.zoomAdjustedDistanceFromCamera = (GetISystem()->GetViewCamera().GetPosition()-pose.t).GetLength();
				pShadowCharacter->StartAnimationProcessing(params);
				//--- Ensure that we disable the automatic update if we're doing it explicitly
				pShadowCharacter->SetFlags( pShadowCharacter->GetFlags()&(~CS_FLAG_UPDATE) );
			}

			ICharacterInstance *pCharacter = GetEntity()->GetCharacter(0);
			ISkeletonPose *pSkelPose = pCharacter ? pCharacter->GetISkeletonPose() : NULL;

			if(pSkelPose)
			{
				ICharacterModelSkeleton* pICharacterModelSkeleton = pCharacter->GetICharacterModel()->GetICharacterModelSkeleton();

				// GetJointIDByName() returns -1 if it fails; m_headBoneID is initialised to -2
				// since -1 is failure and 0+ are valid bone indices.
				if (m_headBoneID == -2)
				{
					// TODO: Should move this to an initialisation function
					m_headBoneID = pICharacterModelSkeleton->GetJointIDByName("Bip01 Head");
					m_cameraBoneID = pICharacterModelSkeleton->GetJointIDByName("Bip01 Camera");
				}

				if (m_headBoneID > -1)
				{
					m_headPos = pSkelPose->GetAbsJointByID(m_headBoneID);
				}
				if (m_cameraBoneID > -1)
				{
					m_cameraPos = pSkelPose->GetAbsJointByID(m_cameraBoneID);
				}
			}
		}
		break;
	case ENTITY_EVENT_DONE:
	case ENTITY_EVENT_RETURNING_TO_POOL:
		{
			SAFE_RELEASE(m_pActionController);
			SAFE_DELETE(m_pAnimContext);
			m_itemList.OnActionControllerDeleted();
		}
		break;
	}
}
//------------------------------------------------------------------------
void CDebugGun::Update( SEntityUpdateContext& ctx, int update)
{ 
  if (!IsSelected())
    return;
  
  static float drawColor[4] = {1,1,1,1};
  static const int dx = 5; 
  static const int dy = 15;
  static const float font = 1.2f;
  static const float fontLarge = 1.4f;

  IRenderer* pRenderer = gEnv->pRenderer;
  IRenderAuxGeom* pAuxGeom = pRenderer->GetIRenderAuxGeom();
  pAuxGeom->SetRenderFlags(e_Def3DPublicRenderflags);

  pRenderer->Draw2dLabel(pRenderer->GetWidth()/5.f, pRenderer->GetHeight()-35, fontLarge, drawColor, false, "Firemode: %s (%.1f)", m_fireModes[m_fireMode].first.c_str(), m_fireModes[m_fireMode].second);      

  ray_hit rayhit;
  
  unsigned int flags = rwi_stop_at_pierceable|rwi_colltype_any;
  if (m_fireModes[m_fireMode].first == "pierceability")
  { 
    flags = (unsigned int)m_fireModes[m_fireMode].second & rwi_pierceability_mask;
  }
  
  // use cam, no need for firing pos/dir
  CCamera& cam = GetISystem()->GetViewCamera();

  if (gEnv->pPhysicalWorld->RayWorldIntersection(cam.GetPosition()+cam.GetViewdir(), cam.GetViewdir()*HIT_RANGE, ent_all, flags, &rayhit, 1))
  {
    IMaterialManager* pMatMan = gEnv->p3DEngine->GetMaterialManager();
    IActorSystem* pActorSystem = g_pGame->GetIGameFramework()->GetIActorSystem();
    IVehicleSystem* pVehicleSystem = g_pGame->GetIGameFramework()->GetIVehicleSystem();
    
    int x = (int)(pRenderer->GetWidth() *0.5f) + dx;
    int y = (int)(pRenderer->GetHeight()*0.5f) + dx - dy;

    // draw normal
    ColorB colNormal(200,0,0,128);
    Vec3 end = rayhit.pt + 0.75f*rayhit.n;
    pAuxGeom->DrawLine(rayhit.pt, colNormal, end, colNormal);
    pAuxGeom->DrawCone(end, rayhit.n, 0.1f, 0.2f, colNormal);

    IEntity * pEntity = (IEntity*)rayhit.pCollider->GetForeignData(PHYS_FOREIGN_ID_ENTITY);
    if(pEntity)
    {  
      pRenderer->Draw2dLabel((float)x, (float)(y+=dy), (float)fontLarge, drawColor, false, pEntity->GetName());      
    }
    
    // material
    const char* matName = pMatMan->GetSurfaceType(rayhit.surface_idx)->GetName();

    if (matName[0])      
      pRenderer->Draw2dLabel((float)x, (y+=dy), (float)font, drawColor, false, "%s (%i)", matName, rayhit.surface_idx);

    pRenderer->Draw2dLabel((float)x, (float)(y+=dy), (float)font, drawColor, false, "%.1f m", rayhit.dist);

    if (pEntity)
    {
      IScriptTable* pScriptTable = pEntity->GetScriptTable();

      // physics 
      if (IPhysicalEntity* pPhysEnt = pEntity->GetPhysics())
      {
        pe_status_dynamics status;
        if (pPhysEnt->GetStatus(&status))
        {        
          if (status.mass > 0.f)
            pRenderer->Draw2dLabel((float)x, (float)(y+=dy), (float)font, drawColor, false, "%.1f kg", status.mass);

          pRenderer->Draw2dLabel((float)x, (float)(y+=dy), (float)font, drawColor, false, "pe_type: %i", pPhysEnt->GetType());                

					// PartId - Part name
				ICharacterInstance* pCharacter = pEntity->GetCharacter(0);
					if (pCharacter)
					{
						CryFixedStringT<64> hit_part("unknown part");

						const int FIRST_ATTACHMENT_PARTID = 1000;
						if (rayhit.partid >= FIRST_ATTACHMENT_PARTID)
						{
							IAttachmentManager* pAttachmentManager = pCharacter->GetIAttachmentManager();
							IAttachment* pAttachment = pAttachmentManager->GetInterfaceByIndex(rayhit.partid - FIRST_ATTACHMENT_PARTID);
							if (pAttachment)
							{
								hit_part = pAttachment->GetName();
							}
						}
						else
						{
							ICharacterModelSkeleton* pICharacterModelSkeleton = pCharacter->GetICharacterModel()->GetICharacterModelSkeleton();
							ISkeletonPose* pSkeletonPose = pCharacter->GetISkeletonPose();
							const char* szJointName = pICharacterModelSkeleton->GetJointNameByID(pSkeletonPose->getBonePhysParentOrSelfIndex(rayhit.partid));
							if (szJointName && *szJointName)
								hit_part = szJointName;
						}

						pRenderer->Draw2dLabel((float)x, (float)(y+=dy), (float)font, drawColor, false, "partId: %i (%s)", rayhit.partid, hit_part.c_str());
					}

          if (status.submergedFraction > 0.f)
            pRenderer->Draw2dLabel((float)x, (float)(y+=dy), (float)font, drawColor, false, "%.2f submerged", status.submergedFraction);

          if (status.v.len2() > 0.0001f)
            pRenderer->Draw2dLabel((float)x, (float)(y+=dy), (float)font, drawColor, false, "%.2f m/s", status.v.len());
        }   
      }  

    
      // class-specific stuff
      if (IActor* pActor = pActorSystem->GetActor(pEntity->GetId()))
      {
	        pRenderer->Draw2dLabel((float)x, y+=dy, (float)font, drawColor, false, "%8.2f health", pActor->GetHealth());
      }
      else if (IVehicle* pVehicle = pVehicleSystem->GetVehicle(pEntity->GetId()))
      {
        const SVehicleStatus& status = pVehicle->GetStatus();
        
        pRenderer->Draw2dLabel((float)x, y+=dy, (float)font, drawColor, false, "%.0f%% health", 100.f*status.health);
        pRenderer->Draw2dLabel((float)x, y+=dy, (float)font, drawColor, false, "%i passengers", status.passengerCount);
        
        if (pVehicle->GetMovement() && pVehicle->GetMovement()->IsPowered())
        {
          pRenderer->Draw2dLabel((float)x, (float)(y+=dy),(float) font, drawColor, false, "Running");
        }
      }
      else
      {
        if (pScriptTable)
        {
          HSCRIPTFUNCTION func = 0;
          if (pScriptTable->GetValue("GetHealth", func) && func)
          {
            float health = 0.f;
            if (Script::CallReturn(gEnv->pScriptSystem, func, pScriptTable, health))
            {
              pRenderer->Draw2dLabel((float)x, (float)(y+=dy),(float) font, drawColor, false, "%.0f health", health);
            }
          }
					gEnv->pScriptSystem->ReleaseFunc(func);
        }
      }
    }    
  }  
}
bool CStickyProjectile::StickToEntity( const SStickParams& stickParams, IEntity* pTargetEntity )
{
	IEntity* pProjectileEntity = stickParams.m_pProjectile->GetEntity();
	ICharacterInstance* pCharInstance = pTargetEntity->GetCharacter(0);
	if( pCharInstance)	
	{
		IActor* pActor = g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(pTargetEntity->GetId());
		if (!pActor || (stickParams.m_bStickToFriendlies || !pActor->IsFriendlyEntity(stickParams.m_ownerId)) && (gEnv->bMultiplayer || !pActor->IsDead()))
		{
			m_stuckJoint = GetJointIdFromPartId(*pTargetEntity, stickParams.m_targetPartId);
			m_stuckNormal = stickParams.m_stickNormal;
			m_stuckPartId = stickParams.m_targetPartId;

			ICharacterModelSkeleton* pICharacterModelSkeleton = pCharInstance->GetICharacterModel()->GetICharacterModelSkeleton();
			ISkeletonPose* pSkeleton = pCharInstance->GetISkeletonPose();
			const char* boneName = pICharacterModelSkeleton->GetJointNameByID(m_stuckJoint);
			const QuatT jointWorld = QuatT(pTargetEntity->GetWorldTM()) * pSkeleton->GetAbsJointByID(m_stuckJoint);
			QuatT loc;
			CalculateLocationForStick( *pProjectileEntity, stickParams.m_stickPosition, stickParams.m_stickNormal, loc );
			pProjectileEntity->SetWorldTM(Matrix34(loc));

			// Get the local pos and rot.
			loc = jointWorld.GetInverted() * loc;
			m_stuckPos = loc.t;
			m_stuckRot = loc.q;

			// Attach.
			if(AttachToCharacter( stickParams.m_pProjectile, *pTargetEntity, *pCharInstance, boneName))
			{
				m_flags |= eSF_IsStuck;
				m_flags |= pActor ? pActor->IsPlayer() ? eSF_StuckToPlayer : eSF_StuckToAI : 0;
				SetParentId(pTargetEntity->GetId());
				m_childId = pProjectileEntity->GetId();
				return true;
			}
		}
	}
	else
	{
		m_stuckNormal = stickParams.m_stickNormal;
		m_stuckPartId = stickParams.m_targetPartId;

		QuatT loc;
		CalculateLocationForStick( *pProjectileEntity, stickParams.m_stickPosition, stickParams.m_stickNormal, loc );

		AttachTo(stickParams.m_pProjectile, pTargetEntity);

		pProjectileEntity->SetWorldTM(Matrix34(loc));

		// Set as Stuck.
		SetParentId(pTargetEntity->GetId());
		m_childId = pProjectileEntity->GetId();
		m_flags |= eSF_IsStuck;

		//Store position and rotation relative to parent entity
		m_stuckPos = pProjectileEntity->GetPos();
		m_stuckRot = pProjectileEntity->GetRotation();
		return true;
	}

	return false;
}
Пример #11
0
//--------------------------------------------------------------------------------------------------
// Name: SpawnParticlesOnSkeleton
// Desc: Spawn particles on Skeleton
//--------------------------------------------------------------------------------------------------
void CGameEffect::SpawnParticlesOnSkeleton(IEntity* pEntity, IParticleEmitter* pParticleEmitter, uint32 numParticles,float maxHeightScale) const
{
	if((pEntity) && (numParticles>0) && (pParticleEmitter) && (maxHeightScale>0.0f))
	{
		ICharacterInstance* pCharacter = pEntity->GetCharacter(0);
		if(pCharacter)
		{
			ICharacterModelSkeleton* pICharacterModelSkeleton = pCharacter->GetICharacterModel()->GetICharacterModelSkeleton();
			ISkeletonPose* pPose = pCharacter->GetISkeletonPose();
			if(pPose && pICharacterModelSkeleton)
			{
				Vec3 animPos;
				Quat animRot;

				IActor* pActor = gEnv->pGame->GetIGameFramework()->GetIActorSystem()->GetActor(pEntity->GetId());
				if(pActor) // First try to get animation data
				{
					QuatT animLoc = pActor->GetAnimatedCharacter()->GetAnimLocation();
					animPos = animLoc.t;
					animRot = animLoc.q;
				}
				else // If no actor, then use entity data
				{
					animPos = pEntity->GetWorldPos();
					animRot = pEntity->GetWorldRotation();
				}

				animRot.Invert();

				AABB bbox;
				pEntity->GetLocalBounds(bbox);
				float bbHeight = bbox.max.z - bbox.min.z;
				// Avoid division by 0
				if(bbHeight == 0)
				{
					bbHeight = 0.0001f;
				}

				const uint32 numJoints = pICharacterModelSkeleton->GetJointCount();

				while(numParticles > 0)
				{
					int id = Random(numJoints);
					int parentId = pICharacterModelSkeleton->GetJointParentIDByID(id);

					if(parentId>0)
					{
						QuatT boneQuat = pPose->GetAbsJointByID(id);
						QuatT parentBoneQuat= pPose->GetAbsJointByID(parentId);
						float lerpScale = cry_frand();

						QuatTS loc(IDENTITY);
						loc.t = LERP(boneQuat.t,parentBoneQuat.t,lerpScale);

						float heightScale = ((loc.t.z - bbox.min.z) / bbHeight);
						if(heightScale < maxHeightScale)
						{
							loc.t = loc.t * animRot;
							loc.t = loc.t + animPos;

							pParticleEmitter->EmitParticle(NULL, NULL, &loc);
						}
					}
				}
			}
		}
	}
}//-------------------------------------------------------------------------------------------------
const Vec3& CTacticalManager::GetTacticalIconWorldPos(const EntityId tacticalEntityId, IEntity* pTacticalEntity, bool& inOutIsHeadBone)
{
	CRY_ASSERT(tacticalEntityId != 0);
	CRY_ASSERT(pTacticalEntity != NULL);
	if (pTacticalEntity == NULL)
	{
		return m_tempVec3.Set(0.0f,0.0f,0.0f);
	}

	// Try to get pos from headbone if don't have an override pos
	TTacticalEntityToOverrideEntities::const_iterator iter = m_tacEntityToOverrideEntities.find(tacticalEntityId);
	if (iter == m_tacEntityToOverrideEntities.end()) 
	{
		static IEntityClass* s_pTurretEntityClass = gEnv->pEntitySystem->GetClassRegistry()->FindClass("Turret");

		IEntityClass* pEntityClass = pTacticalEntity->GetClass();
		if (pEntityClass != NULL && pEntityClass == s_pTurretEntityClass)
		{
			ICharacterInstance* pCharacterInstance = pTacticalEntity->GetCharacter(0);
			if (pCharacterInstance != NULL)
			{
				ICharacterModelSkeleton* pICharacterModelSkeleton = pCharacterInstance->GetICharacterModel()->GetICharacterModelSkeleton();
				ISkeletonPose* pSkeletonPose = pCharacterInstance->GetISkeletonPose();
				CRY_ASSERT(pSkeletonPose != NULL);

				const int16 jointId = pICharacterModelSkeleton->GetJointIDByName("arcjoint");
				if (0 <= jointId)
				{
					QuatT boneLocation = pSkeletonPose->GetAbsJointByID(jointId);
					m_tempVec3 = pTacticalEntity->GetWorldTM().TransformPoint(boneLocation.t);
					return m_tempVec3;
				}
			}
		}


		CUICVars* pCVars = g_pGame->GetUI()->GetCVars();
		if (pCVars->hud_InterestPointsAtActorsHeads == 1)
		{
			CActor* pActor = static_cast<CActor*>(g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(tacticalEntityId)); // Only want units to go from headbone, since vehicles have headbone as well
			if(pActor)
			{
				if(pActor->HasBoneID(BONE_HEAD))
				{
					QuatT boneLocation = pActor->GetBoneTransform(BONE_HEAD);
					m_tempVec3 = pTacticalEntity->GetWorldTM().TransformPoint(boneLocation.t) + Vec3(0.0f, 0.0f, 0.25f);
					inOutIsHeadBone = true;
					return m_tempVec3;
				}
				else if(pActor->HasBoneID(BONE_SPINE))
				{
					QuatT boneLocation = pActor->GetBoneTransform(BONE_SPINE);
					m_tempVec3 = pTacticalEntity->GetWorldTM().TransformPoint(boneLocation.t);
					return m_tempVec3;
				}
			}
		}

		return GetTacticalIconCenterBBoxWorldPos(pTacticalEntity);
	}
	else // Override entity exists so it determines position
	{
		IEntity* pOverrideEntity = gEnv->pEntitySystem->GetEntity(iter->second);
		if (pOverrideEntity)
		{
			m_tempVec3 = pOverrideEntity->GetWorldPos();
			return m_tempVec3;
		}
		else
		{
			GameWarning("CTacticalManager::GetTacticalIconWorldPos: ID exists in mapping but failed to find entity, defaulting to center bounding box position");
			return GetTacticalIconCenterBBoxWorldPos(pTacticalEntity);
		}
	}
}